Skip to content

Commit 07f63e3

Browse files
Add documentation linting tools and style guide
Co-authored-by: timosachsenberg <[email protected]>
1 parent 0d734ff commit 07f63e3

File tree

4 files changed

+225
-2
lines changed

4 files changed

+225
-2
lines changed

.editorconfig

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# EditorConfig helps maintain consistent coding styles
2+
# https://editorconfig.org
3+
4+
root = true
5+
6+
[*]
7+
charset = utf-8
8+
end_of_line = lf
9+
insert_final_newline = true
10+
trim_trailing_whitespace = true
11+
12+
[*.{md,rst}]
13+
indent_style = space
14+
indent_size = 3
15+
max_line_length = 120
16+
17+
[*.py]
18+
indent_style = space
19+
indent_size = 4
20+
21+
[*.{yml,yaml}]
22+
indent_style = space
23+
indent_size = 2
24+
25+
[Makefile]
26+
indent_style = tab

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ Now, open index.html file to view the changes or output of OpenMS ReadTheDocs do
5353

5454
## Contributing to OpenMS Docs
5555

56-
Please read our [contributing guidelines](.github/CONTRIBUTING.md), before starting with contributing to OpenMS
57-
Documentation.
56+
Please read our [contributing guidelines](.github/CONTRIBUTING.md) and [style guide](STYLE_GUIDE.md), before starting with contributing to OpenMS Documentation.
5857

5958
Let us know what you would like to read in OpenMS documentation using [GitHub issues](https://github.com/OpenMS/OpenMS-docs/issues/new/choose)!

STYLE_GUIDE.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# OpenMS Documentation Style Guide
2+
3+
This document supplements the [Contributing Guidelines](.github/CONTRIBUTING.md) with specific style conventions for OpenMS documentation.
4+
5+
## Terminology and Capitalization
6+
7+
### Product and Technology Names
8+
9+
Use proper capitalization for all OpenMS-related products and technologies:
10+
11+
- **OpenMS** - Always capitalize both 'O' and 'MS'. Never use 'openMS', 'Openms', or 'openms' (except in URLs or file paths)
12+
- **pyOpenMS** - Python bindings, with lowercase 'py' prefix
13+
- **TOPP** (The OpenMS Proteomics Pipeline) - Always in all caps
14+
- **TOPPView** - Visualization tool, with camelCase
15+
- **KNIME** - Always in all caps
16+
17+
### File Formats and Technical Terms
18+
19+
- **mzML**, **mzTab** - Lowercase 'mz' followed by format name
20+
- **LC-MS** - Use hyphen, both parts capitalized
21+
- Use {term}\`technical term\` for glossary references
22+
23+
## Links and URLs
24+
25+
- **Always use HTTPS** instead of HTTP where available
26+
- For external links, verify they work before committing
27+
- Use reference-style links for frequently used URLs
28+
- Format: `[Link Text](https://example.com)`
29+
30+
## Code and File References
31+
32+
- Use backticks for code, commands, and file paths: \`filename.txt\`
33+
- Use {path}\`path,to,file\` for OpenMS-specific path references
34+
- Always specify language for code blocks:
35+
36+
\`\`\`python
37+
print("Hello OpenMS")
38+
\`\`\`
39+
40+
## Whitespace and Formatting
41+
42+
- **No trailing whitespace** - Lines should not end with spaces or tabs
43+
- **Line length**: Maximum 120 characters (soft limit)
44+
- **Blank lines**: Use one blank line between sections
45+
- Use UTF-8 encoding for all files
46+
47+
## Images and Figures
48+
49+
- Always provide descriptive alt text: `![Descriptive text](path/to/image.png)`
50+
- Reference figures with anchors: `(Figure_1)=` and `<a href="#figure-1">Figure 1</a>`
51+
- Store images in `docs/_images/` with descriptive subdirectories
52+
53+
## Admonitions
54+
55+
Use appropriate admonition types:
56+
57+
\`\`\`markdown
58+
\`\`\`{note}
59+
Important information for readers
60+
\`\`\`
61+
62+
\`\`\`{warning}
63+
Critical warnings about potential issues
64+
\`\`\`
65+
66+
\`\`\`{tip}
67+
Helpful tips and best practices
68+
\`\`\`
69+
\`\`\`
70+
71+
## Version References
72+
73+
- Reference "latest" for stable releases
74+
- Reference "develop" for development version
75+
- Be explicit about version requirements when necessary
76+
77+
## Common Mistakes to Avoid
78+
79+
1.`openMS` → ✅ `OpenMS`
80+
2.`Toppview` → ✅ `TOPPView`
81+
3.`http://example.com` → ✅ `https://example.com`
82+
4. ❌ Trailing spaces → ✅ Clean line endings
83+
5.`TODO: fix this` → ✅ Open an issue instead
84+
85+
## Tools
86+
87+
- Use `.editorconfig` file settings in your editor
88+
- Run `make html` to build and check documentation locally
89+
- Check for broken links before committing
90+
91+
## Questions?
92+
93+
Join us on [Discord](https://discord.gg/aJyWqf6uCn) or [GitHub Discussions](https://github.com/OpenMS/OpenMS-docs/discussions).

lint_docs.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Documentation linting script for OpenMS-docs.
4+
Checks for common style and consistency issues.
5+
"""
6+
7+
import os
8+
import re
9+
import sys
10+
from pathlib import Path
11+
12+
13+
class DocLinter:
14+
def __init__(self):
15+
self.errors = []
16+
self.warnings = []
17+
18+
def check_file(self, filepath):
19+
"""Check a single file for issues."""
20+
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
21+
content = f.read()
22+
lines = content.split('\n')
23+
24+
for i, line in enumerate(lines, 1):
25+
# Check for trailing whitespace
26+
if line.endswith(' ') or line.endswith('\t'):
27+
self.errors.append(f"{filepath}:{i}: Trailing whitespace")
28+
29+
# Check for insecure HTTP links (excluding specific domains)
30+
if 'http://' in line and not any(x in line for x in ['localhost', 'openms.org', 'openms.de', 'rforge.net']):
31+
self.warnings.append(f"{filepath}:{i}: Consider using HTTPS instead of HTTP")
32+
33+
# Check for inconsistent terminology
34+
if re.search(r'\b(openMS|Openms)\b', line):
35+
# Check if it's not in a URL, path, filename, or image directive
36+
if not re.search(r'(https?://|\.openms|/openms|openms-|openms\.|image::|\.\.\s+figure::|\{image\})', line):
37+
self.errors.append(f"{filepath}:{i}: Use 'OpenMS' instead of variant spelling")
38+
39+
if re.search(r'\b(Toppview)\b', line):
40+
# Check if it's not in a URL, path, or image
41+
if not re.search(r'(https?://|/toppview|toppview-|image::|\.\.\s+figure::)', line, re.IGNORECASE):
42+
self.errors.append(f"{filepath}:{i}: Use 'TOPPView' (correct capitalization)")
43+
44+
# Check for TODO/FIXME in markdown comments (but allow in code blocks)
45+
if re.search(r'<!--.*TODO.*-->', line) or re.search(r'<!--.*FIXME.*-->', line):
46+
self.warnings.append(f"{filepath}:{i}: TODO/FIXME comment found - consider creating an issue")
47+
48+
def check_directory(self, directory):
49+
"""Check all documentation files in a directory."""
50+
for root, dirs, files in os.walk(directory):
51+
for file in files:
52+
if file.endswith('.md') or file.endswith('.rst'):
53+
filepath = os.path.join(root, file)
54+
self.check_file(filepath)
55+
56+
def report(self):
57+
"""Print the linting report."""
58+
print(f"\n{'='*60}")
59+
print("OpenMS Documentation Linting Report")
60+
print(f"{'='*60}\n")
61+
62+
if self.errors:
63+
print(f"❌ ERRORS ({len(self.errors)}):")
64+
for error in self.errors[:20]: # Show first 20
65+
print(f" {error}")
66+
if len(self.errors) > 20:
67+
print(f" ... and {len(self.errors) - 20} more")
68+
print()
69+
70+
if self.warnings:
71+
print(f"⚠️ WARNINGS ({len(self.warnings)}):")
72+
for warning in self.warnings[:20]: # Show first 20
73+
print(f" {warning}")
74+
if len(self.warnings) > 20:
75+
print(f" ... and {len(self.warnings) - 20} more")
76+
print()
77+
78+
if not self.errors and not self.warnings:
79+
print("✅ No issues found! Documentation looks good.")
80+
print()
81+
82+
return len(self.errors)
83+
84+
85+
def main():
86+
"""Main entry point."""
87+
linter = DocLinter()
88+
89+
# Check docs directory
90+
docs_dir = Path(__file__).parent / 'docs'
91+
if docs_dir.exists():
92+
linter.check_directory(docs_dir)
93+
else:
94+
print(f"Error: docs directory not found at {docs_dir}")
95+
return 1
96+
97+
# Generate report
98+
error_count = linter.report()
99+
100+
# Return error code if errors found
101+
return 1 if error_count > 0 else 0
102+
103+
104+
if __name__ == '__main__':
105+
sys.exit(main())

0 commit comments

Comments
 (0)