Additional ISO tools: Clause Names -> Clause names; Bold Table Headings. Allow fixing of the found issues.#96
Merged
Merged
Conversation
Implement heading-case tooling per ISO/IEC Directives, Part 2, 11.4 (clause titles in sentence case) as both a linter and a build-time Pandoc filter. Proper nouns are preserved via heuristics (camelCase, ALL_CAPS, alphanumeric mix) and an extensible YAML allowlist. Wire the existing bold-table-header filter into the build pipeline with an opt-in --bold-table-headers flag, and add documentation comments throughout. All three ISO features are off by default on the build subcommand: --heading-case-lint (pre-build check, prints violations) --heading-case-filter (rewrites headings in output) --bold-table-headers (bolds table header cells in output) The heading_case_lint standalone subcommand is also available. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove filter_heading_case from the build pipeline and add in-place editing (--fix) to iso_heading_case_lint.py, matching the pattern already used by bold_table_lint.py. Add heading_case_fix and bold_table_lint/bold_table_fix DocBuilder subcommands. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
These ISO formatting concerns are now handled by source-level lint/fix tools (iso_heading_case_lint.py, bold_table_lint.py) instead of Pandoc AST filters applied during PDF/HTML/DOCX production. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consistent naming with iso_heading_case_lint.py and iso_clause_lint.py. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract _collect_md_files, _get_sourcepos, _unwrap_sourcepos_spans, and DEFAULT_WORKERS into iso_lint_utils.py (was duplicated across all three linters). - All linters now accept a single .md file path in addition to directories. - Add iso_lint_all subcommand (runs all three linters). - Add iso_fix_all subcommand (fixes heading case and bold tables, then lints clause structure). - Rename iso_lint subcommand to iso_clause_lint for consistency with the module name and sibling subcommands. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract stringify import and run_parallel_check() into iso_lint_utils
- Add display_path param to Violation.format() instead of cloning objects
- Remove dead _SEPARATOR_RE/_is_separator_line from bold table linter
- Remove duplicate `import re` from heading case linter
- Use set.isdisjoint() for O(1) protected-range checks in heading fixer
- Simplify fix_file() newline handling with rstrip('\n')
- Have main() --fix call fix_spec() instead of reimplementing it
- Refactor iso_lint_all/iso_fix_all into data-driven loops
- Remove clause lint from iso_fix_all (belongs in iso_lint_all only)
- Fix stale iso_clause_lint_all references in docs (actual name: iso_lint_all)
- Add partial-bold edge case comment to _bold_header_row
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…orts - Move format_report() logic into iso_lint_utils parameterised by label - Each linter keeps a thin wrapper preserving its public API - Remove unused imports from iso_bold_table_lint (re, Set, field) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- fix_spec() accepts optional pre-computed violations list, skipping the redundant check_spec() call when the caller already has results - All call sites (main --fix, doc_builder fix methods, iso_fix_all) now pass violations through - Make Violation.format() keyword-only across all three linters - Remove commented-out code from iso_clause_lint Violation.format() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
dgovil
approved these changes
Jun 11, 2026
dgovil
left a comment
Collaborator
There was a problem hiding this comment.
Looks good to me though I think we should replace the getattr calls with direct properties to prevent the risk of typos or issues like that sneaking in.
The argparse namespaces always have these attributes defined by their respective parsers, so getattr with a fallback is unnecessary. Add --context to the iso_lint_all parser so it's explicitly declared rather than silently defaulted via getattr. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The build parser defines all five attributes (heading_case_lint, heading_proper_nouns, iso_xrefs, keep_pdf_latex), so the argparse namespace always has them — getattr with a fallback was unnecessary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
build_docs() is called from test scripts that build args via types.SimpleNamespace without all build-parser attributes. The getattr fallbacks are necessary here, unlike the ISO subcommand methods which are only ever invoked through their own parsers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add the missing build-parser attributes (heading_case_lint, heading_proper_nouns, iso_xrefs) to the SimpleNamespace in build_diff.py so build_docs() can use direct attribute access consistently. Future build flags that are missing from test callers will fail with a clear AttributeError instead of silently falling back to a default. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
For users
Three linters check Markdown specification sources against ISO/IEC Directives and report violations with file paths and line numbers. Two of them also auto-fix in place when asked.
iso_heading_case_lintiso_bold_table_lintiso_clause_lintRun all at once via
iso_lint_all(check) oriso_fix_all(auto-fix what's possible, then runiso_lint_allfor the rest). Each tool accepts a directory or a single.mdfile.Proper-noun detection combines heuristics (camelCase, ALL_CAPS, mixed alphanumeric tokens) with a YAML allowlist (
iso_heading_proper_nouns.yaml). The source-level fixer builds a set of protected character positions (code spans, link URLs) and only lowercases words outside those ranges.See
doc_build/ISO_LINTERS.mdfor CLI usage, DocBuilder subcommands, and a ready-to-use GitHub Actions snippet.For reviewers
Each linter follows the same pattern: Pandoc parses the file with
+sourceposto produce a JSON AST, then checker walks the AST to detect violations with accurate line numbers, and the fixer (where applicable) edits the source line directly via regex on the specific source lines.Using the Pandoc AST for editing is considered destructive as additional changes might be introduced besides the requested ISO formatting.