paperlint 3.1.3 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +12 -7
- package/CLAUDE.md +3 -3
- package/CONTRIBUTING.md +34 -5
- package/dist/adapters/banal/index.d.ts.map +1 -1
- package/dist/adapters/banal/index.js +9 -5
- package/dist/adapters/banal/index.js.map +1 -1
- package/dist/adapters/banal/invocation.d.ts +1 -1
- package/dist/adapters/node/files.io.d.ts.map +1 -1
- package/dist/adapters/node/files.io.js +2 -1
- package/dist/adapters/node/files.io.js.map +1 -1
- package/dist/adapters/node/process.io.d.ts +0 -5
- package/dist/adapters/node/process.io.d.ts.map +1 -1
- package/dist/adapters/node/process.io.js +4 -3
- package/dist/adapters/node/process.io.js.map +1 -1
- package/dist/adapters/pdfjs/fill.d.ts.map +1 -1
- package/dist/adapters/pdfjs/fill.js +13 -7
- package/dist/adapters/pdfjs/fill.js.map +1 -1
- package/dist/adapters/references/index.d.ts.map +1 -1
- package/dist/adapters/references/index.js +4 -5
- package/dist/adapters/references/index.js.map +1 -1
- package/dist/adapters/references/pool.d.ts.map +1 -1
- package/dist/adapters/references/pool.js +4 -5
- package/dist/adapters/references/pool.js.map +1 -1
- package/dist/adapters/references/reach.io.d.ts.map +1 -1
- package/dist/adapters/references/reach.io.js +2 -1
- package/dist/adapters/references/reach.io.js.map +1 -1
- package/dist/build-engine.js +2 -2
- package/dist/build-engine.js.map +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +14 -11
- package/dist/build.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +31 -34
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +3 -2
- package/dist/doctor.js.map +1 -1
- package/dist/domain/lookup-cache.d.ts.map +1 -1
- package/dist/domain/lookup-cache.js +10 -8
- package/dist/domain/lookup-cache.js.map +1 -1
- package/dist/domain/text.d.ts +12 -0
- package/dist/domain/text.d.ts.map +1 -1
- package/dist/domain/text.js +17 -0
- package/dist/domain/text.js.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +4 -3
- package/dist/engine.js.map +1 -1
- package/dist/eslint-rules/bib-reachable-entry.d.ts +22 -0
- package/dist/eslint-rules/bib-reachable-entry.d.ts.map +1 -0
- package/dist/eslint-rules/bib-reachable-entry.js +75 -0
- package/dist/eslint-rules/bib-reachable-entry.js.map +1 -0
- package/dist/eslint-rules/install-path-literals.d.ts +80 -0
- package/dist/eslint-rules/install-path-literals.d.ts.map +1 -0
- package/dist/eslint-rules/install-path-literals.js +105 -0
- package/dist/eslint-rules/install-path-literals.js.map +1 -0
- package/dist/eslint-rules/latex-language.d.ts +136 -0
- package/dist/eslint-rules/latex-language.d.ts.map +1 -0
- package/dist/eslint-rules/latex-language.js +639 -0
- package/dist/eslint-rules/latex-language.js.map +1 -0
- package/dist/eslint-rules/paper-research-question.d.ts +31 -0
- package/dist/eslint-rules/paper-research-question.d.ts.map +1 -0
- package/dist/eslint-rules/paper-research-question.js +188 -0
- package/dist/eslint-rules/paper-research-question.js.map +1 -0
- package/dist/eslint-rules/paper-stages.d.ts +83 -0
- package/dist/eslint-rules/paper-stages.d.ts.map +1 -0
- package/dist/eslint-rules/paper-stages.js +358 -0
- package/dist/eslint-rules/paper-stages.js.map +1 -0
- package/dist/eslint-rules/paper-typography.d.ts +74 -0
- package/dist/eslint-rules/paper-typography.d.ts.map +1 -0
- package/dist/eslint-rules/paper-typography.js +404 -0
- package/dist/eslint-rules/paper-typography.js.map +1 -0
- package/dist/eslint-rules/papers.d.ts +42 -0
- package/dist/eslint-rules/papers.d.ts.map +1 -0
- package/dist/eslint-rules/papers.js +145 -0
- package/dist/eslint-rules/papers.js.map +1 -0
- package/dist/eslint-rules/pdf-last-page-balance.d.ts +72 -0
- package/dist/eslint-rules/pdf-last-page-balance.d.ts.map +1 -0
- package/dist/eslint-rules/pdf-last-page-balance.js +237 -0
- package/dist/eslint-rules/pdf-last-page-balance.js.map +1 -0
- package/dist/eslint-rules/review-frontmatter.d.ts +57 -0
- package/dist/eslint-rules/review-frontmatter.d.ts.map +1 -0
- package/dist/eslint-rules/review-frontmatter.js +126 -0
- package/dist/eslint-rules/review-frontmatter.js.map +1 -0
- package/dist/eslint-rules/review-frontmatter.schema.json +36 -0
- package/dist/eslint-rules/rule-context.d.ts +55 -0
- package/dist/eslint-rules/rule-context.d.ts.map +1 -0
- package/dist/eslint-rules/rule-context.js +9 -0
- package/dist/eslint-rules/rule-context.js.map +1 -0
- package/dist/eslint-rules/sibling-frontmatter.d.ts +25 -0
- package/dist/eslint-rules/sibling-frontmatter.d.ts.map +1 -0
- package/dist/eslint-rules/sibling-frontmatter.js +16 -0
- package/dist/eslint-rules/sibling-frontmatter.js.map +1 -0
- package/dist/eslint-rules/sibling-frontmatter.schema.json +14 -0
- package/dist/eslint-rules/temp-root-realpath.d.ts +71 -0
- package/dist/eslint-rules/temp-root-realpath.d.ts.map +1 -0
- package/dist/eslint-rules/temp-root-realpath.js +139 -0
- package/dist/eslint-rules/temp-root-realpath.js.map +1 -0
- package/dist/eslint-rules/tex-build.d.ts +35 -0
- package/dist/eslint-rules/tex-build.d.ts.map +1 -0
- package/dist/eslint-rules/tex-build.js +313 -0
- package/dist/eslint-rules/tex-build.js.map +1 -0
- package/dist/facts-file.d.ts.map +1 -1
- package/dist/facts-file.js +2 -1
- package/dist/facts-file.js.map +1 -1
- package/dist/hooks-settings.d.ts +1 -1
- package/dist/hooks-settings.d.ts.map +1 -1
- package/dist/hooks-settings.js +14 -9
- package/dist/hooks-settings.js.map +1 -1
- package/dist/init.d.ts +5 -5
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +15 -7
- package/dist/init.js.map +1 -1
- package/dist/latex-loop.d.ts +2 -2
- package/dist/latex-loop.d.ts.map +1 -1
- package/dist/latex-loop.js +2 -2
- package/dist/latex-loop.js.map +1 -1
- package/dist/lib/agent-cli-version.d.ts +65 -0
- package/dist/lib/agent-cli-version.d.ts.map +1 -0
- package/dist/lib/agent-cli-version.js +77 -0
- package/dist/lib/agent-cli-version.js.map +1 -0
- package/dist/lib/check.d.ts +19 -0
- package/dist/lib/check.d.ts.map +1 -0
- package/dist/lib/check.js +52 -0
- package/dist/lib/check.js.map +1 -0
- package/dist/lib/markdown.d.ts +180 -0
- package/dist/lib/markdown.d.ts.map +1 -0
- package/dist/lib/markdown.js +302 -0
- package/dist/lib/markdown.js.map +1 -0
- package/dist/lib/paper-config.d.ts +84 -0
- package/dist/lib/paper-config.d.ts.map +1 -0
- package/dist/lib/paper-config.js +142 -0
- package/dist/lib/paper-config.js.map +1 -0
- package/dist/lib/skill-eval-fixture.d.ts +29 -0
- package/dist/lib/skill-eval-fixture.d.ts.map +1 -0
- package/dist/lib/skill-eval-fixture.js +62 -0
- package/dist/lib/skill-eval-fixture.js.map +1 -0
- package/dist/link-skills.d.ts.map +1 -1
- package/dist/link-skills.js +5 -4
- package/dist/link-skills.js.map +1 -1
- package/dist/new-paper.d.ts.map +1 -1
- package/dist/new-paper.js +2 -2
- package/dist/new-paper.js.map +1 -1
- package/dist/paper-settings.d.ts.map +1 -1
- package/dist/paper-settings.js +5 -4
- package/dist/paper-settings.js.map +1 -1
- package/dist/pdf-facts.d.ts.map +1 -1
- package/dist/pdf-facts.js +2 -1
- package/dist/pdf-facts.js.map +1 -1
- package/dist/pdf-geometry.d.ts.map +1 -1
- package/dist/pdf-geometry.js +1 -1
- package/dist/pdf-geometry.js.map +1 -1
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +3 -2
- package/dist/presets.js.map +1 -1
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +11 -6
- package/dist/references.js.map +1 -1
- package/dist/rules-config.d.ts.map +1 -1
- package/dist/rules-config.js +6 -3
- package/dist/rules-config.js.map +1 -1
- package/dist/structure.js +1 -1
- package/dist/structure.js.map +1 -1
- package/dist/tex-requirements.d.ts.map +1 -1
- package/dist/tex-requirements.js +8 -3
- package/dist/tex-requirements.js.map +1 -1
- package/dist/toolchain.d.ts.map +1 -1
- package/dist/toolchain.js +21 -16
- package/dist/toolchain.js.map +1 -1
- package/dist/venue-rules.js +1 -1
- package/dist/venue-rules.js.map +1 -1
- package/docs/e2e.md +7 -7
- package/docs/install.md +1 -1
- package/docs/prior-art/README.md +1 -1
- package/docs/prior-art/package-location.md +5 -5
- package/docs/prior-art/repro/README.md +1 -1
- package/docs/prior-art/test-tooling.md +2 -2
- package/docs/testing.md +11 -8
- package/docs/toolchain.md +1 -1
- package/eslint-rules/{bib-reachable-entry.mjs → bib-reachable-entry.ts} +4 -3
- package/eslint-rules/install-path-literals.harness.mjs +1 -1
- package/eslint-rules/{install-path-literals.mjs → install-path-literals.ts} +16 -8
- package/eslint-rules/latex-language.harness.mjs +2 -2
- package/eslint-rules/latex-language.test.mjs +7 -1
- package/eslint-rules/{latex-language.mjs → latex-language.ts} +297 -109
- package/eslint-rules/paper-research-question.harness.mjs +3 -3
- package/eslint-rules/{paper-research-question.mjs → paper-research-question.ts} +34 -15
- package/eslint-rules/paper-stages.harness.mjs +2 -2
- package/eslint-rules/paper-stages.test.mjs +8 -2
- package/eslint-rules/{paper-stages.mjs → paper-stages.ts} +74 -29
- package/eslint-rules/paper-typography.test.mjs +3 -3
- package/eslint-rules/{paper-typography.mjs → paper-typography.ts} +132 -54
- package/eslint-rules/papers.harness.mjs +2 -2
- package/eslint-rules/{papers.mjs → papers.ts} +7 -4
- package/eslint-rules/pdf-last-page-balance.harness.mjs +3 -3
- package/eslint-rules/{pdf-last-page-balance.mjs → pdf-last-page-balance.ts} +88 -31
- package/eslint-rules/review-frontmatter.test.mjs +2 -2
- package/eslint-rules/{review-frontmatter.mjs → review-frontmatter.ts} +37 -15
- package/eslint-rules/rule-context.ts +62 -0
- package/eslint-rules/{sibling-frontmatter.mjs → sibling-frontmatter.ts} +1 -1
- package/eslint-rules/temp-root-realpath.harness.mjs +1 -1
- package/eslint-rules/{temp-root-realpath.mjs → temp-root-realpath.ts} +19 -6
- package/eslint-rules/tex-build.harness.mjs +2 -2
- package/eslint-rules/{tex-build.mjs → tex-build.ts} +4 -3
- package/eslint.config.mjs +139 -30
- package/fixtures/pdf-facts/README.md +2 -2
- package/fixtures/real-markdown-paper/{baseline.mjs → baseline.ts} +31 -10
- package/hooks/{hooks.harness.mjs → hooks.harness.ts} +51 -34
- package/hooks/paper-edit-guard.hook.mjs +1 -1
- package/hooks/{paper-edit-guard.test.mjs → paper-edit-guard.test.ts} +3 -7
- package/hooks/paper-skills-nudge.hook.mjs +1 -1
- package/hooks/{paper-skills-nudge.test.mjs → paper-skills-nudge.test.ts} +2 -6
- package/hooks/{paper-status-gates.test.mjs → paper-status-gates.test.ts} +2 -6
- package/lib/agent-cli-version.harness.mjs +1 -1
- package/lib/{agent-cli-version.mjs → agent-cli-version.ts} +32 -18
- package/lib/check.test.ts +14 -9
- package/lib/{check.mjs → check.ts} +22 -9
- package/lib/markdown.test.mjs +7 -7
- package/lib/{markdown.mjs → markdown.ts} +68 -29
- package/lib/paper-config.harness.mjs +8 -8
- package/lib/{paper-config.mjs → paper-config.ts} +19 -14
- package/lib/skill-checks.mjs +1 -1
- package/lib/skill-checks.test.mjs +1 -1
- package/lib/skill-corpus.mjs +1 -1
- package/lib/skill-eval-kit.mjs +1 -1
- package/package.json +42 -10
- package/scripts/{check.harness.mjs → check.harness.ts} +111 -10
- package/scripts/{check.test.mjs → check.test.ts} +13 -10
- package/scripts/{check.mjs → check.ts} +116 -42
- package/scripts/coverage-config.test.ts +80 -37
- package/scripts/eslint-report-guard.test.mjs +1 -1
- package/scripts/harness-api.frozen.json +14 -15
- package/scripts/harness-api.test.ts +8 -5
- package/scripts/layer-legacy-frozen.test.ts +17 -13
- package/scripts/{layer-legacy-frozen.mjs → layer-legacy-frozen.ts} +128 -39
- package/scripts/release-config.test.ts +12 -4
- package/scripts/rules-see-files.test.mjs +1 -1
- package/scripts/test.test.ts +78 -0
- package/scripts/test.ts +87 -0
- package/skills/grade-paper-writing/prose-lint.mjs +1 -1
- package/skills/grade-paper-writing/{prose-lint.test.mjs → prose-lint.test.ts} +2 -2
- package/skills/paper-pipeline/description-language.eval.mjs +1 -1
- package/skills/paper-pipeline/framing-vs-vocabulary.eval.mjs +1 -1
- package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +1 -1
- package/skills/paper-pipeline/pipeline-firing.eval.mjs +1 -1
- package/skills/paper-pipeline/pipeline-language.eval.mjs +1 -1
- package/skills/paper-pipeline/scripts/README.md +1 -1
- package/skills/paper-pipeline/scripts/announce.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/artifact-coverage.mjs +1 -1
- package/skills/paper-pipeline/scripts/{artifact-coverage.test.mjs → artifact-coverage.test.ts} +2 -2
- package/skills/paper-pipeline/scripts/consumer.mjs +1 -5
- package/skills/paper-pipeline/scripts/consumer.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +1 -1
- package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +1 -4
- package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/fixtures/{scorecard.mjs → scorecard.ts} +36 -7
- package/skills/paper-pipeline/scripts/{generated-code.test.mjs → generated-code.test.ts} +3 -3
- package/skills/paper-pipeline/scripts/ledger.cli.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/pipeline-check.cli.test.mjs +2 -2
- package/skills/paper-pipeline/scripts/pipeline-check.harness.mjs +2 -2
- package/skills/paper-pipeline/scripts/pipeline-check.mjs +1 -4
- package/skills/paper-pipeline/scripts/population-map.mjs +1 -4
- package/skills/paper-pipeline/scripts/population-map.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/{round-diff.harness.mjs → round-diff.harness.ts} +45 -18
- package/skills/paper-pipeline/scripts/round-diff.mjs +1 -1
- package/skills/paper-pipeline/scripts/round-diff.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/run-mechanical.test.mjs +1 -1
- package/skills/paper-pipeline/scripts/status.test.mjs +1 -1
- package/skills/plan-paper-timeline/fixtures/{fake-google-calendar.mjs → fake-google-calendar.ts} +101 -70
- package/skills/plan-paper-timeline/plan-paper-timeline.effects.harness.mjs +3 -3
- package/skills/render-paper/{extract-pdf-facts.harness.mjs → extract-pdf-facts.harness.ts} +34 -9
- package/skills/render-paper/render-paper.harness.mjs +2 -2
- package/skills/tighten-paper/structure.mjs +1 -1
- package/skills/tighten-paper/{structure.test.mjs → structure.test.ts} +4 -3
- package/skills/verify-citations/scripts/{bib-authors.cli.test.mjs → bib-authors.cli.test.ts} +14 -4
- package/skills/verify-citations/scripts/bib-authors.d.mts +63 -0
- package/skills/verify-citations/scripts/bib-authors.mjs +1 -4
- package/skills/verify-citations/scripts/{verify-cites.cli.test.mjs → verify-cites.cli.test.ts} +32 -9
- package/skills/verify-citations/scripts/verify-cites.d.mts +58 -0
- package/src/CLAUDE.md +1 -1
- package/src/adapters/banal/index.test.ts +3 -6
- package/src/adapters/banal/index.ts +7 -4
- package/src/adapters/banal/invocation.test.ts +3 -1
- package/src/adapters/banal/invocation.ts +1 -1
- package/src/adapters/banal/output.test.ts +1 -1
- package/src/adapters/banal/run.test.ts +3 -3
- package/src/adapters/banal/xml.test.ts +1 -1
- package/src/adapters/curl/download.test.ts +4 -2
- package/src/adapters/node/files.io.ts +2 -2
- package/src/adapters/node/files.test.ts +3 -1
- package/src/adapters/node/process.io.ts +4 -3
- package/src/adapters/node/process.test.ts +1 -1
- package/src/adapters/node/workspace.test.ts +3 -1
- package/src/adapters/pdfjs/fill.test.ts +2 -2
- package/src/adapters/pdfjs/fill.ts +14 -7
- package/src/adapters/references/index.test.ts +31 -38
- package/src/adapters/references/index.ts +26 -58
- package/src/adapters/references/pool.ts +3 -5
- package/src/adapters/references/reach.io.ts +2 -1
- package/src/build-engine.harness.mjs +1 -1
- package/src/build-engine.test.ts +2 -2
- package/src/build-engine.ts +2 -2
- package/src/build.harness.mjs +2 -2
- package/src/build.test.ts +15 -14
- package/src/build.ts +28 -19
- package/src/cli.harness.mjs +6 -6
- package/src/cli.test.ts +13 -6
- package/src/cli.ts +39 -37
- package/src/doctor.harness.mjs +3 -3
- package/src/doctor.ts +3 -2
- package/src/domain/lookup-cache.ts +21 -11
- package/src/domain/result.test.ts +2 -2
- package/src/domain/text.test.ts +32 -0
- package/src/domain/text.ts +23 -0
- package/src/engine.harness.mjs +2 -2
- package/src/engine.ts +4 -3
- package/src/facts-file.test.ts +9 -7
- package/src/facts-file.ts +2 -1
- package/src/{hooks-settings.harness.mjs → hooks-settings.harness.ts} +39 -20
- package/src/hooks-settings.ts +20 -9
- package/src/init.test.ts +12 -9
- package/src/init.ts +22 -12
- package/src/{latex-log.harness.mjs → latex-log.harness.ts} +14 -14
- package/src/{latex-loop.harness.mjs → latex-loop.harness.ts} +64 -36
- package/src/latex-loop.ts +3 -3
- package/src/{link-skills.harness.mjs → link-skills.harness.ts} +19 -19
- package/src/link-skills.test.ts +3 -3
- package/src/link-skills.ts +5 -4
- package/src/lint-fix.test.ts +4 -6
- package/src/linted-set.test.ts +2 -2
- package/src/new-paper.harness.mjs +2 -2
- package/src/new-paper.test.ts +8 -10
- package/src/new-paper.ts +2 -2
- package/src/paper-files.test.ts +3 -5
- package/src/paper-settings-commands.test.ts +5 -4
- package/src/paper-settings.test.ts +5 -5
- package/src/paper-settings.ts +8 -9
- package/src/{pdf-facts.harness.mjs → pdf-facts.harness.ts} +9 -8
- package/src/pdf-facts.test.ts +10 -11
- package/src/pdf-facts.ts +2 -1
- package/src/{pdf-geometry.harness.mjs → pdf-geometry.harness.ts} +19 -12
- package/src/pdf-geometry.ts +3 -1
- package/src/presets.ts +3 -2
- package/src/references.test.ts +51 -43
- package/src/references.ts +14 -7
- package/src/{rules-config.harness.mjs → rules-config.harness.ts} +7 -13
- package/src/rules-config.ts +7 -4
- package/src/rules-off.test.ts +6 -4
- package/src/{structure.harness.mjs → structure.harness.ts} +26 -15
- package/src/structure.ts +1 -1
- package/src/{tex-requirements.harness.mjs → tex-requirements.harness.ts} +50 -22
- package/src/tex-requirements.ts +8 -5
- package/src/toolchain.harness.mjs +2 -2
- package/src/toolchain.test.ts +1 -1
- package/src/toolchain.ts +31 -17
- package/src/venue-rules.test.ts +62 -64
- package/src/venue-rules.ts +1 -1
- package/tsconfig.json +6 -3
- package/tsconfig.pkg.json +10 -0
- package/lib/check.d.mts +0 -17
- package/lib/paper-config.d.mts +0 -31
- package/scripts/layer-legacy-frozen.d.mts +0 -36
- package/scripts/rules-are-content-only.harness.mjs +0 -105
- package/scripts/rules-are-content-only.mjs +0 -148
- package/scripts/rules-are-content-only.test.mjs +0 -61
- package/scripts/test.mjs +0 -44
- package/scripts/test.test.mjs +0 -52
- /package/bin/{paperlint.test.mjs → paperlint.test.ts} +0 -0
- /package/lib/{skill-eval-fixture.mjs → skill-eval-fixture.ts} +0 -0
- /package/skills/grade-paper-writing/__snapshots__/{prose-lint.test.mjs.snap → prose-lint.test.ts.snap} +0 -0
- /package/skills/osf-artifact-upload/{osf-artifact-upload.harness.mjs → osf-artifact-upload.harness.ts} +0 -0
- /package/skills/tighten-paper/__snapshots__/{structure.test.mjs.snap → structure.test.ts.snap} +0 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Three mechanical conventions a reviewer already raised, ONE RULE EACH, reported where each
|
|
3
|
+
* occurrence is and fixed by `paperlint lint --fix`:
|
|
4
|
+
*
|
|
5
|
+
* paper/section-word `§5`, `\S\ref{…}` → `Section 5`, `Section~\ref{…}`
|
|
6
|
+
* paper/leading-zero `.05` → `0.05`
|
|
7
|
+
* paper/figure-ref-style `Fig.~\ref` beside `Figure~\ref` in one document → the majority form
|
|
8
|
+
*
|
|
9
|
+
* The fourth check of the old `paper/typography`, an unreachable bibliography entry, is
|
|
10
|
+
* `bib/reachable-entry` (bib-reachable-entry.mjs): it is about the bibliography, not the prose,
|
|
11
|
+
* and it has no fix.
|
|
12
|
+
*
|
|
13
|
+
* ── PROVENANCE: every one is a real review finding, not an invented style ───────────────
|
|
14
|
+
* From HotCRP #20 (2026-08-23). Reviewer B listed two as literal to-dos:
|
|
15
|
+
* B#11 "§ -> Section" one paper in the source corpus carried 246
|
|
16
|
+
* B#12 ".05 -> 0.05" four in the submitted text, fixed by hand
|
|
17
|
+
* (own) `Fig.` and `Figure` side by side
|
|
18
|
+
*
|
|
19
|
+
* ── WHY THERE IS NO DEBT OPTION ANY MORE (3.0.0) ──────────────────────────────────────────
|
|
20
|
+
* Until 3.0.0 this was ONE rule, `paper/typography`, that counted all four per paper against a
|
|
21
|
+
* declared `debt` and spoke only when a count grew. A ratchet was needed because the rule could
|
|
22
|
+
* only COUNT: 246 section signs meant 246 edits by hand, so the only way to turn it on was to
|
|
23
|
+
* freeze the backlog. Every check here now has a FIX, so the backlog costs one command
|
|
24
|
+
* (`paperlint lint --fix`), and the ratchet — per-paper numbers in the project config, keyed by
|
|
25
|
+
* a path — has nothing left to protect. A deliberate exception is an ESLint disable directive on
|
|
26
|
+
* the line (`% eslint-disable-next-line paper/section-word -- reason`), the standard escape
|
|
27
|
+
* hatch every ESLint user already knows, not a counter.
|
|
28
|
+
*
|
|
29
|
+
* ── WHY section-word AND figure-ref-style READ `sourceCode.raw` ───────────────────────────
|
|
30
|
+
* They are about MARKUP. The prose projection of the LaTeX language blanks macros — that is its
|
|
31
|
+
* purpose — so `\S\ref{}` and `Fig.~\ref{}` reach a normal rule as spaces. Offsets coincide
|
|
32
|
+
* between the two (blanking preserves length), so scanning `raw` and reporting the offset found
|
|
33
|
+
* there points at the right byte. Comments and the inline bibliography are skipped.
|
|
34
|
+
*
|
|
35
|
+
* 🔴 BOTH forms of the section sign, and the second one is why this check was ever wrong. The
|
|
36
|
+
* first version counted only the literal `§` and returned ZERO on the very paper whose reviewer
|
|
37
|
+
* raised it: the source writes `\S\ref{sec:threats}`, which RENDERS as `§5`.
|
|
38
|
+
*
|
|
39
|
+
* ── WHY leading-zero READS THE PARSED TREE (paperlint#44) ──────────────────────────────────
|
|
40
|
+
* ISO 80000-1 ("the decimal sign shall be preceded by a zero" for magnitudes below 1) and the
|
|
41
|
+
* IEEE Editorial Style Manual ("0.25, not .25") require the zero. A regex over the raw source
|
|
42
|
+
* found 22 decimals on a real corpus and none was a defect: every one sat in markup (an option,
|
|
43
|
+
* a column spec, a comment, a listing, a tikz coordinate). So this walks the TREE and keeps only
|
|
44
|
+
* what the reader sees as a number:
|
|
45
|
+
* LaTeX prose, inline and display math, table cells, and the text arguments of a known
|
|
46
|
+
* set of text macros. Not: any other macro's arguments, environment arguments,
|
|
47
|
+
* comments, verbatim/listings/`\lstinline`, tikz, the preamble, the bibliography.
|
|
48
|
+
* Markdown text nodes, table cells included. Not: code, inline code, html, front matter.
|
|
49
|
+
* Each character of a run keeps its source offset, so the finding points at the dot and the fix
|
|
50
|
+
* inserts the zero there. The arXiv lookbehind stays: in `2310.05736` the dot follows a digit.
|
|
51
|
+
* A text macro outside the known set (`\hl{.05}`) is read as a parameter and NOT reported — a
|
|
52
|
+
* miss costs less than a finding on markup.
|
|
53
|
+
*
|
|
54
|
+
* 🔴 A NUMBER AFTER `¶` OR `§` IS A DESIGNATOR, NOT A DECIMAL (#102). An auditing standard is cited
|
|
55
|
+
* by paragraph as `¶¶.42`, and `--fix` rewrote it to `¶¶0.42` — a fix that changed a reference.
|
|
56
|
+
* So a lexeme right after the sign (`¶`, `§`, `\P`, `\S`, spaces or `~` between) is silent. The
|
|
57
|
+
* same sentence then goes on `and .44`: a paragraph number continuing the list, or a decimal —
|
|
58
|
+
* the text does not say which. In a paragraph that already cites `¶.nn` this way, a bare decimal
|
|
59
|
+
* is REPORTED WITHOUT A FIX and the zero is offered as a suggestion: an autofix must never be the
|
|
60
|
+
* one to decide what a number means. A real `.05` in any other paragraph is fixed as before.
|
|
61
|
+
*/
|
|
62
|
+
import assert from "node:assert/strict";
|
|
63
|
+
import { getParser } from "@unified-latex/unified-latex-util-parse";
|
|
64
|
+
/** The inline bibliography — a `filecontents` block writing a `.bib` — with its offsets. */
|
|
65
|
+
export function bibRange(text) {
|
|
66
|
+
const m = /\\begin\{filecontents\*?\}(?:\[[^\]]*\])?\{[^}]*\.bib\}\r?\n([\s\S]*?)\\end\{filecontents\*?\}/d.exec(text);
|
|
67
|
+
if (!m)
|
|
68
|
+
return null;
|
|
69
|
+
const [whole, body] = m;
|
|
70
|
+
const bodyStart = m.indices?.[1]?.[0];
|
|
71
|
+
// The `d` flag records every group's indices, and group 1 is not optional.
|
|
72
|
+
assert.ok(body !== undefined && bodyStart !== undefined, "no .bib body");
|
|
73
|
+
return { start: m.index, end: m.index + whole.length, bodyStart, body };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The ranges a markup rule must not read: LaTeX comments (the language gives them as `html`
|
|
77
|
+
* nodes, with positions) and the inline bibliography.
|
|
78
|
+
*/
|
|
79
|
+
function skippedRanges(sourceCode, raw) {
|
|
80
|
+
const out = [];
|
|
81
|
+
for (const n of sourceCode.ast?.children ?? [])
|
|
82
|
+
if (n.type === "html" && n.position) {
|
|
83
|
+
// An offset-less point compares as NaN: inside no range, as `undefined` always did.
|
|
84
|
+
const { start: { offset: s = Number.NaN }, end: { offset: e = Number.NaN }, } = n.position;
|
|
85
|
+
out.push([s, e]);
|
|
86
|
+
}
|
|
87
|
+
const bib = bibRange(raw);
|
|
88
|
+
if (bib)
|
|
89
|
+
out.push([bib.start, bib.end]);
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
const inside = (ranges, i) => ranges.some(([s, e]) => i >= s && i < e);
|
|
93
|
+
/** Every match of `re` in `raw` outside the skipped ranges. */
|
|
94
|
+
function markupMatches(sourceCode, re) {
|
|
95
|
+
const raw = sourceCode.raw;
|
|
96
|
+
const skip = skippedRanges(sourceCode, raw);
|
|
97
|
+
return [...raw.matchAll(re)].filter((m) => !inside(skip, m.index));
|
|
98
|
+
}
|
|
99
|
+
const isTex = (sourceCode) => typeof sourceCode.raw === "string";
|
|
100
|
+
// ── the text a READER sees, with the source offset of every character ─────────────────────
|
|
101
|
+
/** A run of visible text; `offs[i]` is the source offset of `text[i]`, or null when unknown. */
|
|
102
|
+
const run = () => ({ text: "", offs: [] });
|
|
103
|
+
// Environments whose body is not typeset as text: code, drawings, the inline bibliography.
|
|
104
|
+
const TEX_HIDDEN_ENV = /^(verbatim|Verbatim|lstlisting|minted|tikzpicture|filecontents\*?|comment)$/;
|
|
105
|
+
// Text macros whose mandatory argument IS prose. Every other macro's arguments are parameters.
|
|
106
|
+
const TEX_PROSE_ARG = /^(emph|textbf|textit|textsl|textsc|textup|textmd|textrm|textsf|textnormal|underline|text|mbox|caption|footnote|footnotetext|thanks|title|textsuperscript|textsubscript|part|chapter|section|subsection|subsubsection|paragraph|subparagraph)$/;
|
|
107
|
+
// Macros whose LAST mandatory argument is what the reader sees.
|
|
108
|
+
const TEX_LAST_ARG = /^(multicolumn|multirow|textcolor|href)$/;
|
|
109
|
+
// In math every macro argument is typeset except these.
|
|
110
|
+
const TEX_MATH_HIDDEN = /^(label|ref|eqref|autoref|cite|hspace|vspace|hskip|vskip|kern|mkern|mskip|rule|phantom|hphantom|vphantom|color|raisebox|includegraphics)$/;
|
|
111
|
+
const mandatory = (macro) => (macro.args || []).filter((a) => a.openMark === "{");
|
|
112
|
+
/**
|
|
113
|
+
* unified-latex attaches arguments only to what it has a signature for. For the rest the
|
|
114
|
+
* arguments come back as the NEXT SIBLINGS: an optional `[…]` as bare strings, then groups.
|
|
115
|
+
* They are parameters, not prose. Returns the index of the last sibling to skip after `i`.
|
|
116
|
+
*/
|
|
117
|
+
/** Whether `n` is a string node whose text passes `test`. */
|
|
118
|
+
const isString = (n, test) => n?.type === "string" && test(n.content);
|
|
119
|
+
function unparsedArgsEnd(nodes, i) {
|
|
120
|
+
let j = i + 1;
|
|
121
|
+
if (isString(nodes[j], (c) => c.startsWith("["))) {
|
|
122
|
+
let k = j;
|
|
123
|
+
while (k < nodes.length && !isString(nodes[k], (c) => c.endsWith("]")))
|
|
124
|
+
k++;
|
|
125
|
+
if (k < nodes.length)
|
|
126
|
+
j = k + 1;
|
|
127
|
+
}
|
|
128
|
+
while (nodes[j]?.type === "group")
|
|
129
|
+
j++;
|
|
130
|
+
return j - 1;
|
|
131
|
+
}
|
|
132
|
+
/** Append a string node to the current run, keeping each character's offset. */
|
|
133
|
+
function appendString(cur, n, src) {
|
|
134
|
+
const start = n.position?.start?.offset;
|
|
135
|
+
const exact = typeof start === "number" &&
|
|
136
|
+
src.slice(start, start + n.content.length) === n.content
|
|
137
|
+
? start
|
|
138
|
+
: null;
|
|
139
|
+
for (let i = 0; i < n.content.length; i++)
|
|
140
|
+
cur.offs.push(exact === null ? null : exact + i);
|
|
141
|
+
cur.text += n.content;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Collect runs of visible text from a unified-latex node list. A run is a stretch of sibling
|
|
145
|
+
* `string` nodes with nothing between them: math splits `.05` into `.`, `0`, `5`, and prose
|
|
146
|
+
* keeps `2310.05736` whole — both come back as one word. Anything else ends the run.
|
|
147
|
+
*/
|
|
148
|
+
/** What stands in for an index past the end: a node every branch below passes over. */
|
|
149
|
+
const NOTHING = { type: "whitespace" };
|
|
150
|
+
function texRuns(nodes, math, src, out) {
|
|
151
|
+
let cur = run();
|
|
152
|
+
const flush = () => {
|
|
153
|
+
if (cur.text)
|
|
154
|
+
out.push(cur);
|
|
155
|
+
cur = run();
|
|
156
|
+
};
|
|
157
|
+
const list = nodes || [];
|
|
158
|
+
for (let i = 0; i < list.length; i++) {
|
|
159
|
+
const { [i]: n = NOTHING } = list;
|
|
160
|
+
if (n.type === "string") {
|
|
161
|
+
appendString(cur, n, src);
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
flush();
|
|
165
|
+
if (n.type === "inlinemath" ||
|
|
166
|
+
n.type === "displaymath" ||
|
|
167
|
+
n.type === "mathenv")
|
|
168
|
+
texRuns(n.content, true, src, out);
|
|
169
|
+
else if (n.type === "environment") {
|
|
170
|
+
const env = typeof n.env === "string" ? n.env : "";
|
|
171
|
+
if (!TEX_HIDDEN_ENV.test(env)) {
|
|
172
|
+
const body = n.content || [];
|
|
173
|
+
const from = (n.args || []).length ? 0 : unparsedArgsEnd(body, -1) + 1;
|
|
174
|
+
texRuns(body.slice(from), math, src, out);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
else if (n.type === "group") {
|
|
178
|
+
texRuns(n.content, math, src, out);
|
|
179
|
+
}
|
|
180
|
+
else if (n.type === "macro") {
|
|
181
|
+
const args = mandatory(n);
|
|
182
|
+
if (math) {
|
|
183
|
+
if (!TEX_MATH_HIDDEN.test(n.content))
|
|
184
|
+
for (const a of args)
|
|
185
|
+
texRuns(a.content, true, src, out);
|
|
186
|
+
}
|
|
187
|
+
else if (TEX_PROSE_ARG.test(n.content)) {
|
|
188
|
+
for (const a of args)
|
|
189
|
+
texRuns(a.content, false, src, out);
|
|
190
|
+
}
|
|
191
|
+
else if (TEX_LAST_ARG.test(n.content) && args.length) {
|
|
192
|
+
texRuns(args.at(-1)?.content, false, src, out);
|
|
193
|
+
}
|
|
194
|
+
if (!math && !(n.args || []).length)
|
|
195
|
+
i = unparsedArgsEnd(list, i);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
flush();
|
|
199
|
+
return out;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* The visible runs of a LaTeX source. `parse` is unified-latex's parser; a test hands in a tree
|
|
203
|
+
* with the fields the walk tolerates being absent.
|
|
204
|
+
*/
|
|
205
|
+
export function texVisibleRuns(raw, { parse = (s) => getParser().parse(s), } = {}) {
|
|
206
|
+
const root = parse(raw).content;
|
|
207
|
+
// Only the document body is typeset. A fragment with no `document` environment is all body.
|
|
208
|
+
const document = root.find((n) => n.type === "environment" && n.env === "document");
|
|
209
|
+
return texRuns(document ? document.content : root, false, raw, []);
|
|
210
|
+
}
|
|
211
|
+
// Markdown node types that are not prose.
|
|
212
|
+
const MD_HIDDEN = new Set([
|
|
213
|
+
"code",
|
|
214
|
+
"inlineCode",
|
|
215
|
+
"html",
|
|
216
|
+
"yaml",
|
|
217
|
+
"toml",
|
|
218
|
+
"math",
|
|
219
|
+
"inlineMath",
|
|
220
|
+
]);
|
|
221
|
+
/**
|
|
222
|
+
* The source offset of each character of a text node's value. The value is the source with
|
|
223
|
+
* markdown's escapes (`\*`) and character references (`<`) resolved, so the two are walked
|
|
224
|
+
* side by side; a character whose source cannot be followed gets null (reported, not fixed).
|
|
225
|
+
*/
|
|
226
|
+
function mdOffsets(value, src, start) {
|
|
227
|
+
const offs = [];
|
|
228
|
+
let j = start;
|
|
229
|
+
for (const ch of value) {
|
|
230
|
+
if (src[j] === ch)
|
|
231
|
+
offs.push(j++);
|
|
232
|
+
else if (src[j] === "\\" && src[j + 1] === ch) {
|
|
233
|
+
offs.push(j + 1);
|
|
234
|
+
j += 2;
|
|
235
|
+
}
|
|
236
|
+
else if (src[j] === "&" && /^&#?\w{1,8};/.test(src.slice(j, j + 10))) {
|
|
237
|
+
offs.push(null);
|
|
238
|
+
j = src.indexOf(";", j) + 1;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
offs.push(null);
|
|
242
|
+
j++;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return offs;
|
|
246
|
+
}
|
|
247
|
+
function mdVisibleRuns(node, src, out = []) {
|
|
248
|
+
if (!node || MD_HIDDEN.has(node.type))
|
|
249
|
+
return out;
|
|
250
|
+
if (node.type === "text") {
|
|
251
|
+
const start = node.position?.start.offset;
|
|
252
|
+
out.push({
|
|
253
|
+
text: node.value,
|
|
254
|
+
offs: typeof start === "number"
|
|
255
|
+
? mdOffsets(node.value, src, start)
|
|
256
|
+
: Array.from(node.value, () => null),
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
for (const c of "children" in node ? node.children : [])
|
|
260
|
+
mdVisibleRuns(c, src, out);
|
|
261
|
+
return out;
|
|
262
|
+
}
|
|
263
|
+
const visibleRuns = (sourceCode) => isTex(sourceCode)
|
|
264
|
+
? texVisibleRuns(sourceCode.raw)
|
|
265
|
+
: mdVisibleRuns(sourceCode.ast, sourceCode.text);
|
|
266
|
+
/** A report at `[from, to)` of the file. */
|
|
267
|
+
const at = (context, from, to, rest) => {
|
|
268
|
+
const sc = context.sourceCode;
|
|
269
|
+
context.report({
|
|
270
|
+
loc: { start: sc.getLocFromIndex(from), end: sc.getLocFromIndex(to) },
|
|
271
|
+
...rest,
|
|
272
|
+
});
|
|
273
|
+
};
|
|
274
|
+
// ── paper/section-word ─────────────────────────────────────────────────────────────────
|
|
275
|
+
// The sign (the glyph, or the `\S` macro not followed by a letter), the separator after it, and
|
|
276
|
+
// what follows: a reference (group 3) or a number (group 4).
|
|
277
|
+
const SECTION_TEX = /(§|\\S(?![A-Za-z]))(~|[ \t]*)(?=(\\(?:auto)?ref\b)|(\d))/g;
|
|
278
|
+
const SECTION_GLYPH = /§/g;
|
|
279
|
+
function sectionWord(context) {
|
|
280
|
+
const sc = context.sourceCode;
|
|
281
|
+
if (isTex(sc)) {
|
|
282
|
+
const seen = new Set();
|
|
283
|
+
for (const m of markupMatches(sc, SECTION_TEX)) {
|
|
284
|
+
seen.add(m.index);
|
|
285
|
+
const word = m[3] ? "Section~" : "Section ";
|
|
286
|
+
const range = [m.index, m.index + m[0].length];
|
|
287
|
+
at(context, range[0], range[1], {
|
|
288
|
+
messageId: "sign",
|
|
289
|
+
fix: (f) => f.replaceTextRange(range, word),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
// A glyph before neither a reference nor a number: reported, not rewritten — there is no
|
|
293
|
+
// single right word for a doubled sign or a sign before prose.
|
|
294
|
+
for (const m of markupMatches(sc, SECTION_GLYPH))
|
|
295
|
+
if (!seen.has(m.index))
|
|
296
|
+
at(context, m.index, m.index + 1, { messageId: "sign" });
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
for (const r of visibleRuns(sc))
|
|
300
|
+
for (const m of r.text.matchAll(/§([ \t]*)(\d)?/g)) {
|
|
301
|
+
const from = r.offs[m.index];
|
|
302
|
+
if (from === null || from === undefined)
|
|
303
|
+
continue;
|
|
304
|
+
// The sign and the space after it; the number stays.
|
|
305
|
+
const [, gap = ""] = m;
|
|
306
|
+
const range = [from, from + 1 + gap.length];
|
|
307
|
+
at(context, range[0], range[1], {
|
|
308
|
+
messageId: "sign",
|
|
309
|
+
...(m[2] ? { fix: (f) => f.replaceTextRange(range, "Section ") } : {}),
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
// ── paper/leading-zero ─────────────────────────────────────────────────────────────────
|
|
314
|
+
// The lexeme, matched inside ONE run of visible text. The lookbehind keeps arXiv ids
|
|
315
|
+
// (2310.05736) out: there the dot follows a digit.
|
|
316
|
+
const BARE_DECIMAL = /(?<![\d.\w])\.\d{2,}\b/g;
|
|
317
|
+
// A paragraph or section sign — the glyph, or `\P`/`\S` not followed by a letter — and what may
|
|
318
|
+
// sit between it and the number. Both read the SOURCE, because in LaTeX `\P\P.42` reaches the
|
|
319
|
+
// visible runs as `.42` alone: the macros end the run.
|
|
320
|
+
const DESIGNATOR_BEFORE = /(?:[¶§]|\\[PS](?![A-Za-z]))[ \t~]*$/;
|
|
321
|
+
const DESIGNATED = /(?:[¶§]|\\[PS](?![A-Za-z]))[ \t~]*\.\d/;
|
|
322
|
+
/** The source of the paragraph holding `i`, up to `i`: from the last blank line before it. */
|
|
323
|
+
const paragraphBefore = (src, i) => {
|
|
324
|
+
const head = src.slice(0, i);
|
|
325
|
+
const blank = [...head.matchAll(/\n[ \t]*\n/g)].at(-1);
|
|
326
|
+
return head.slice(blank ? blank.index + blank[0].length : 0);
|
|
327
|
+
};
|
|
328
|
+
function leadingZero(context) {
|
|
329
|
+
const sc = context.sourceCode;
|
|
330
|
+
const src = isTex(sc) ? sc.raw : sc.text;
|
|
331
|
+
for (const r of visibleRuns(sc))
|
|
332
|
+
for (const m of r.text.matchAll(BARE_DECIMAL)) {
|
|
333
|
+
const dot = r.offs[m.index];
|
|
334
|
+
if (dot === null || dot === undefined)
|
|
335
|
+
continue;
|
|
336
|
+
const before = paragraphBefore(src, dot);
|
|
337
|
+
if (DESIGNATOR_BEFORE.test(before))
|
|
338
|
+
continue;
|
|
339
|
+
const zero = (f) => f.insertTextBeforeRange([dot, dot], "0");
|
|
340
|
+
at(context, dot, dot + 1, DESIGNATED.test(before)
|
|
341
|
+
? {
|
|
342
|
+
messageId: "ambiguous",
|
|
343
|
+
data: { n: m[0] },
|
|
344
|
+
suggest: [
|
|
345
|
+
{ messageId: "insertZero", data: { n: m[0] }, fix: zero },
|
|
346
|
+
],
|
|
347
|
+
}
|
|
348
|
+
: { messageId: "bare", data: { n: m[0] }, fix: zero });
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
// ── paper/figure-ref-style ─────────────────────────────────────────────────────────────
|
|
352
|
+
const FIG_REF = /\b(Fig\.|Figure)(?=~?\\(?:ref|autoref)\b)/g;
|
|
353
|
+
function figureRefStyle(context) {
|
|
354
|
+
const sc = context.sourceCode;
|
|
355
|
+
if (!isTex(sc))
|
|
356
|
+
return;
|
|
357
|
+
const all = markupMatches(sc, FIG_REF);
|
|
358
|
+
const short = all.filter((m) => m[1] === "Fig.");
|
|
359
|
+
const long = all.filter((m) => m[1] === "Figure");
|
|
360
|
+
if (!short.length || !long.length)
|
|
361
|
+
return;
|
|
362
|
+
// The minority form is rewritten to the majority one; on a tie, to the full word.
|
|
363
|
+
const [minority, word] = short.length > long.length ? [long, "Fig."] : [short, "Figure"];
|
|
364
|
+
for (const m of minority) {
|
|
365
|
+
const [, form = ""] = m;
|
|
366
|
+
const range = [m.index, m.index + form.length];
|
|
367
|
+
at(context, range[0], range[1], {
|
|
368
|
+
messageId: "mixed",
|
|
369
|
+
data: { form, word, n: String(all.length - minority.length) },
|
|
370
|
+
fix: (f) => f.replaceTextRange(range, word),
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const rule = (description, messages, check, meta = {}) => ({
|
|
375
|
+
meta: {
|
|
376
|
+
type: "suggestion",
|
|
377
|
+
fixable: "code",
|
|
378
|
+
docs: { description },
|
|
379
|
+
schema: [],
|
|
380
|
+
messages,
|
|
381
|
+
...meta,
|
|
382
|
+
},
|
|
383
|
+
create: (context) => ({
|
|
384
|
+
"root:exit": () => {
|
|
385
|
+
check(context);
|
|
386
|
+
},
|
|
387
|
+
}),
|
|
388
|
+
});
|
|
389
|
+
export default {
|
|
390
|
+
rules: {
|
|
391
|
+
"section-word": rule("`§` / `\\S` instead of the word Section (a reviewer's to-do); fixable", {
|
|
392
|
+
sign: "`§` instead of the word «Section» — `paperlint lint --fix` writes it",
|
|
393
|
+
}, sectionWord),
|
|
394
|
+
"leading-zero": rule("a decimal below 1 written without its leading zero (IEEE / ISO 80000-1); fixable", {
|
|
395
|
+
bare: "`{{n}}` has no leading zero — write `0{{n}}` (IEEE / ISO 80000-1); `paperlint lint --fix` inserts it",
|
|
396
|
+
ambiguous: "`{{n}}` in a paragraph that cites `¶`/`§` numbers: a decimal without its leading zero, or another paragraph number? Not fixed automatically — write `0{{n}}` for a decimal, or put the sign before a paragraph number",
|
|
397
|
+
insertZero: "It is a decimal: write `0{{n}}`",
|
|
398
|
+
}, leadingZero, { hasSuggestions: true }),
|
|
399
|
+
"figure-ref-style": rule("`Fig.~\\ref` and `Figure~\\ref` mixed in one document; fixable to the majority form", {
|
|
400
|
+
mixed: "`{{form}}` beside {{n}} × `{{word}}` in one document — use one form; `paperlint lint --fix` writes `{{word}}`",
|
|
401
|
+
}, figureRefStyle),
|
|
402
|
+
},
|
|
403
|
+
};
|
|
404
|
+
//# sourceMappingURL=paper-typography.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paper-typography.js","sourceRoot":"","sources":["../../eslint-rules/paper-typography.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { DEFAULT_PAPERS_ROOT } from "../lib/paper-config.ts";
|
|
2
|
+
export { DEFAULT_PAPERS_ROOT };
|
|
3
|
+
/**
|
|
4
|
+
* The declared papers root, verified to be on disk.
|
|
5
|
+
*
|
|
6
|
+
* @param settings the project's root `paperlint.json`, parsed (`settingsOf(root)`), or undefined
|
|
7
|
+
* @param baseDir the directory the root is relative to. PASS `import.meta.dirname` FROM THE
|
|
8
|
+
* CONFIG rather than relying on the default: `process.cwd()` is wherever the
|
|
9
|
+
* editor, the hook runtime or the CI step happened to start, and in a git
|
|
10
|
+
* worktree it can be a different checkout entirely. The config file sits at
|
|
11
|
+
* the repository root, so its own directory is the stable answer.
|
|
12
|
+
* @returns the root as DECLARED (relative), not resolved — it goes straight into `files:`
|
|
13
|
+
* globs, which ESLint interprets relative to the config, and an absolute path there
|
|
14
|
+
* would change their meaning.
|
|
15
|
+
*/
|
|
16
|
+
export declare function papersRoot(settings: Readonly<Record<string, unknown>> | null | undefined, baseDir?: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* The glob sets a consumer declares its blocks on, derived from one root.
|
|
19
|
+
*
|
|
20
|
+
* 🔴 THE SHAPES LIVE HERE, NOT IN THE CONSUMER, and that is the half that keeps a rule from
|
|
21
|
+
* going blind later. `paper.md` + `draft.md`, `_build/*.facts.json`, `PIPELINE-STATUS.md` are
|
|
22
|
+
* this pipeline's CONVENTION; if a rule starts reading a new file, the glob for it must arrive
|
|
23
|
+
* with the rule, in the same package, rather than as a line every consumer has to add by hand
|
|
24
|
+
* to keep up. A hand-maintained list of paths is the thing that rots, and rots silently.
|
|
25
|
+
*/
|
|
26
|
+
export declare function paperFiles(root: string): {
|
|
27
|
+
/** Markdown drafts — the two names a paper's prose is allowed to have. */
|
|
28
|
+
md: string[];
|
|
29
|
+
/** The LaTeX source of a paper (not its figures, not its vendored drafts). */
|
|
30
|
+
tex: string[];
|
|
31
|
+
/** The per-paper stage ledger. */
|
|
32
|
+
status: string[];
|
|
33
|
+
/** The per-paper settings file, `paperlint.json`. */
|
|
34
|
+
venue: string[];
|
|
35
|
+
/** Facts extracted from the built PDF. */
|
|
36
|
+
pdfFacts: string[];
|
|
37
|
+
/** Facts extracted from the bibliography. */
|
|
38
|
+
refFacts: string[];
|
|
39
|
+
/** Everything under the root — for blocks that turn other tooling OFF rather than on. */
|
|
40
|
+
all: string[];
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=papers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"papers.d.ts","sourceRoot":"","sources":["../../eslint-rules/papers.ts"],"names":[],"mappings":"AA+EA,OAAO,EAEL,mBAAmB,EAGpB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAE/B;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,EAC9D,OAAO,GAAE,MAAsB,GAC9B,MAAM,CA2BR;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM;IAEnC,0EAA0E;;IAE1E,8EAA8E;;IAE9E,kCAAkC;;IAElC,qDAAqD;;IAErD,0CAA0C;;IAE1C,6CAA6C;;IAE7C,yFAAyF;;EAG5F"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* papers.mjs — WHERE THE CONSUMER'S PAPERS LIVE. One declaration, three readers.
|
|
3
|
+
*
|
|
4
|
+
* ── THE PROBLEM THIS SOLVES ─────────────────────────────────────────────────
|
|
5
|
+
* This package lints papers. It must not know where any particular consumer keeps them: the
|
|
6
|
+
* first consumer keeps them two levels deep under a directory named in its own language, and
|
|
7
|
+
* a package that hard-codes that word is a package with exactly one possible user. But the
|
|
8
|
+
* path cannot simply be "passed in" either, because it is needed by FOUR carriers with four
|
|
9
|
+
* different mechanics — an ESLint config (JavaScript), a compiled hook (a closed vocabulary
|
|
10
|
+
* that forbids imports), the PROSE of a skill (read by a model, not resolved by code), and
|
|
11
|
+
* LaTeX (`TEXINPUTS`, kpathsea).
|
|
12
|
+
*
|
|
13
|
+
* ── THE DECISION ────────────────────────────────────────────────────────────
|
|
14
|
+
* ONE declaration, in the project's root `paperlint.json`, with a default:
|
|
15
|
+
*
|
|
16
|
+
* { "papersDir": "docs/papers" }
|
|
17
|
+
*
|
|
18
|
+
* No file, or no key → `papers`. Every carrier then reads that one value with its OWN standard
|
|
19
|
+
* mechanism:
|
|
20
|
+
*
|
|
21
|
+
* ESLint → `settingsOf(root)` (lib/paper-config.mjs) + this module
|
|
22
|
+
* hook → `needs: [provide("config", …)]` cats the file, JSON.parse inside `decide`
|
|
23
|
+
* prose → the skill names a COMMAND, not a path:
|
|
24
|
+
* `node -p "(() => { try { return require('./paperlint.json').papersDir } catch {} })() ?? 'papers'"`
|
|
25
|
+
* LaTeX → `TEXINPUTS` built FROM THE SCRIPT (`$(dirname "$0")/../tex//:`), so the
|
|
26
|
+
* consumer declares nothing at all for this carrier
|
|
27
|
+
*
|
|
28
|
+
* ── WHAT WAS MEASURED AND KILLED, so it is not proposed again ───────────────
|
|
29
|
+
* (full measurements: consumer repo, `idei/paper-pipeline-extraction/`, 2026-09-11)
|
|
30
|
+
*
|
|
31
|
+
* A SYMLINK (`papers -> <the real directory>`) plus a hard-coded default, no config at all.
|
|
32
|
+
* ESLint does NOT descend into a symlinked directory when walking `.`: the run reported
|
|
33
|
+
* ZERO files and exit 0 — the green zero this package has a dedicated guard against.
|
|
34
|
+
*
|
|
35
|
+
* AN ENVIRONMENT VARIABLE (`$PAPER_ROOT`).
|
|
36
|
+
* A compiled hook cannot read `process.env` — the vocabulary check rejects every import
|
|
37
|
+
* except `vigiles/hook`. The only way in is `provide("root", "echo $PAPER_ROOT")`, and
|
|
38
|
+
* then THREE different places must set the same value (the agent harness that spawns the
|
|
39
|
+
* hook, CI, the editor running ESLint). Unset, it expands to the empty string and every
|
|
40
|
+
* prefix test silently passes.
|
|
41
|
+
*
|
|
42
|
+
* A FILENAME MARKER, no root at all (`**\/paper.tex`).
|
|
43
|
+
* Measured on the first consumer: `paper.tex` ×4 with one outside the corpus,
|
|
44
|
+
* `PIPELINE-STATUS.md` ×6 with two of them test fixtures, `paper.md` ×3 with two outside.
|
|
45
|
+
* The guard that would consume this is a `deny` at `error` severity; a denial on writing
|
|
46
|
+
* a fixture gets the hook switched off the same day.
|
|
47
|
+
*
|
|
48
|
+
* `context.settings`.
|
|
49
|
+
* It delivers data INTO a rule; it does not choose which files a rule sees. `files:` is
|
|
50
|
+
* the only mechanism that does. Useful for a plugin's `structureRoot`, useless here.
|
|
51
|
+
*
|
|
52
|
+
* ── WHY THIS THROWS INSTEAD OF FALLING BACK ─────────────────────────────────
|
|
53
|
+
* 🔴 A wrong root does not produce wrong findings — it produces NO findings, and a run with no
|
|
54
|
+
* findings is byte-identical to a run that examined everything and passed. That is the one
|
|
55
|
+
* failure mode of this whole design, and it belongs to the ESLint carrier alone: the other
|
|
56
|
+
* three fail loudly on their own (a hook throws on `join(undefined)`, `ls` exits non-zero,
|
|
57
|
+
* LaTeX stops with `! Emergency stop.`). So this module refuses to return a root it cannot
|
|
58
|
+
* see on disk, and the refusal happens while the CONFIG is loading — before any rule runs,
|
|
59
|
+
* where it cannot be mistaken for a clean lint.
|
|
60
|
+
*
|
|
61
|
+
* ⚠️ THAT IS NOT ENOUGH ON ITS OWN, and saying so is the point. `existsSync` proves the
|
|
62
|
+
* directory exists, not that any rule was handed a file from it: a root that exists but holds
|
|
63
|
+
* no papers, or a glob shape that stopped matching, still yields the green zero. The second
|
|
64
|
+
* net is `scripts/rules-see-files.mjs`, which asks ESLint what the effective config of every
|
|
65
|
+
* linted file is and names any rule that saw none. A consumer using this module without
|
|
66
|
+
* running that script has one net, not two.
|
|
67
|
+
*
|
|
68
|
+
* ⚠️ THE EXAMPLES IN THIS FILE ARE DELIBERATELY GENERIC (`docs/papers`), and that is ENFORCED
|
|
69
|
+
* rather than a style preference: `papers.harness.mjs` part IV fails if the first consumer's own
|
|
70
|
+
* directory name appears anywhere in this package outside the test itself. It caught this very
|
|
71
|
+
* docblock on 2026-09-11, where the example used the real value. An exemption list is what turns
|
|
72
|
+
* such a check into decoration, so there is exactly one exemption: the file asserting it.
|
|
73
|
+
*/
|
|
74
|
+
import { existsSync } from "node:fs";
|
|
75
|
+
import { resolve } from "node:path";
|
|
76
|
+
// Re-exported, not re-declared. This file is not a hook, so nothing stops it importing the one
|
|
77
|
+
// source; it had its own copy for no reason, and that copy was outside the agreement check that
|
|
78
|
+
// compares the three hooks — it could have drifted in silence.
|
|
79
|
+
import { CONFIG_KEY, DEFAULT_PAPERS_ROOT, PAPERS_DIR_FIELD, CONFIG_FILE, } from "../lib/paper-config.js";
|
|
80
|
+
export { DEFAULT_PAPERS_ROOT };
|
|
81
|
+
/**
|
|
82
|
+
* The declared papers root, verified to be on disk.
|
|
83
|
+
*
|
|
84
|
+
* @param settings the project's root `paperlint.json`, parsed (`settingsOf(root)`), or undefined
|
|
85
|
+
* @param baseDir the directory the root is relative to. PASS `import.meta.dirname` FROM THE
|
|
86
|
+
* CONFIG rather than relying on the default: `process.cwd()` is wherever the
|
|
87
|
+
* editor, the hook runtime or the CI step happened to start, and in a git
|
|
88
|
+
* worktree it can be a different checkout entirely. The config file sits at
|
|
89
|
+
* the repository root, so its own directory is the stable answer.
|
|
90
|
+
* @returns the root as DECLARED (relative), not resolved — it goes straight into `files:`
|
|
91
|
+
* globs, which ESLint interprets relative to the config, and an absolute path there
|
|
92
|
+
* would change their meaning.
|
|
93
|
+
*/
|
|
94
|
+
export function papersRoot(settings, baseDir = process.cwd()) {
|
|
95
|
+
const declared = settings?.[PAPERS_DIR_FIELD];
|
|
96
|
+
// 🔴 `declared === undefined`, NOT `declared ?? DEFAULT`. The two differ on exactly one
|
|
97
|
+
// input — `"papersDir": null` — and the difference is the whole point: `??` reads an explicit
|
|
98
|
+
// `null` as "nothing was declared" and silently uses the default, which is a typed keystroke
|
|
99
|
+
// being treated as an absence. Caught by the harness on 2026-09-11, where the first draft of
|
|
100
|
+
// this line used `??` and let `null` through. Absence means default; anything written down
|
|
101
|
+
// means it must be usable.
|
|
102
|
+
const root = declared === undefined ? DEFAULT_PAPERS_ROOT : declared;
|
|
103
|
+
if (typeof root !== "string" || root.length === 0)
|
|
104
|
+
throw new TypeError(`${CONFIG_KEY}: "${PAPERS_DIR_FIELD}" must be a non-empty string, got ${JSON.stringify(root)}`);
|
|
105
|
+
if (!existsSync(resolve(baseDir, root)))
|
|
106
|
+
throw new Error(`${CONFIG_KEY}: the papers root "${root}" does not exist under ${baseDir}.\n` +
|
|
107
|
+
(declared === undefined
|
|
108
|
+
? `Nothing was declared, so the default "${DEFAULT_PAPERS_ROOT}" was used. Declare the ` +
|
|
109
|
+
`real location in ${CONFIG_FILE}:\n` +
|
|
110
|
+
` { "${PAPERS_DIR_FIELD}": "path/to/papers" }`
|
|
111
|
+
: `It is declared in ${CONFIG_FILE} as "${root}". Fix it there, or create the ` +
|
|
112
|
+
`directory.`) +
|
|
113
|
+
`\nThis is thrown rather than ignored on purpose: a papers root that matches nothing ` +
|
|
114
|
+
`makes every rule lint zero files, and a run with zero findings is indistinguishable ` +
|
|
115
|
+
`from a run that checked everything and passed.`);
|
|
116
|
+
return root;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The glob sets a consumer declares its blocks on, derived from one root.
|
|
120
|
+
*
|
|
121
|
+
* 🔴 THE SHAPES LIVE HERE, NOT IN THE CONSUMER, and that is the half that keeps a rule from
|
|
122
|
+
* going blind later. `paper.md` + `draft.md`, `_build/*.facts.json`, `PIPELINE-STATUS.md` are
|
|
123
|
+
* this pipeline's CONVENTION; if a rule starts reading a new file, the glob for it must arrive
|
|
124
|
+
* with the rule, in the same package, rather than as a line every consumer has to add by hand
|
|
125
|
+
* to keep up. A hand-maintained list of paths is the thing that rots, and rots silently.
|
|
126
|
+
*/
|
|
127
|
+
export function paperFiles(root) {
|
|
128
|
+
return {
|
|
129
|
+
/** Markdown drafts — the two names a paper's prose is allowed to have. */
|
|
130
|
+
md: [`${root}/*/paper.md`, `${root}/*/draft.md`],
|
|
131
|
+
/** The LaTeX source of a paper (not its figures, not its vendored drafts). */
|
|
132
|
+
tex: [`${root}/*/paper.tex`],
|
|
133
|
+
/** The per-paper stage ledger. */
|
|
134
|
+
status: [`${root}/*/PIPELINE-STATUS.md`],
|
|
135
|
+
/** The per-paper settings file, `paperlint.json`. */
|
|
136
|
+
venue: [`${root}/*/${CONFIG_FILE}`],
|
|
137
|
+
/** Facts extracted from the built PDF. */
|
|
138
|
+
pdfFacts: [`${root}/*/_build/paper.facts.json`],
|
|
139
|
+
/** Facts extracted from the bibliography. */
|
|
140
|
+
refFacts: [`${root}/*/_build/refs.facts.json`],
|
|
141
|
+
/** Everything under the root — for blocks that turn other tooling OFF rather than on. */
|
|
142
|
+
all: [`${root}/**/*.*`],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=papers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"papers.js","sourceRoot":"","sources":["../../eslint-rules/papers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwEG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,+FAA+F;AAC/F,gGAAgG;AAChG,+DAA+D;AAC/D,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,gBAAgB,EAChB,WAAW,GACZ,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,CAAC;AAE/B;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,UAAU,CACxB,QAA8D,EAC9D,UAAkB,OAAO,CAAC,GAAG,EAAE;IAE/B,MAAM,QAAQ,GAAG,QAAQ,EAAE,CAAC,gBAAgB,CAAC,CAAC;IAC9C,wFAAwF;IACxF,8FAA8F;IAC9F,6FAA6F;IAC7F,6FAA6F;IAC7F,2FAA2F;IAC3F,2BAA2B;IAC3B,MAAM,IAAI,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAC/C,MAAM,IAAI,SAAS,CACjB,GAAG,UAAU,MAAM,gBAAgB,qCAAqC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAC/F,CAAC;IACJ,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACrC,MAAM,IAAI,KAAK,CACb,GAAG,UAAU,sBAAsB,IAAI,0BAA0B,OAAO,KAAK;YAC3E,CAAC,QAAQ,KAAK,SAAS;gBACrB,CAAC,CAAC,yCAAyC,mBAAmB,0BAA0B;oBACtF,oBAAoB,WAAW,KAAK;oBACpC,QAAQ,gBAAgB,uBAAuB;gBACjD,CAAC,CAAC,qBAAqB,WAAW,QAAQ,IAAI,iCAAiC;oBAC7E,YAAY,CAAC;YACjB,sFAAsF;YACtF,sFAAsF;YACtF,gDAAgD,CACnD,CAAC;IACJ,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,OAAO;QACL,0EAA0E;QAC1E,EAAE,EAAE,CAAC,GAAG,IAAI,aAAa,EAAE,GAAG,IAAI,aAAa,CAAC;QAChD,8EAA8E;QAC9E,GAAG,EAAE,CAAC,GAAG,IAAI,cAAc,CAAC;QAC5B,kCAAkC;QAClC,MAAM,EAAE,CAAC,GAAG,IAAI,uBAAuB,CAAC;QACxC,qDAAqD;QACrD,KAAK,EAAE,CAAC,GAAG,IAAI,MAAM,WAAW,EAAE,CAAC;QACnC,0CAA0C;QAC1C,QAAQ,EAAE,CAAC,GAAG,IAAI,4BAA4B,CAAC;QAC/C,6CAA6C;QAC7C,QAAQ,EAAE,CAAC,GAAG,IAAI,2BAA2B,CAAC;QAC9C,yFAAyF;QACzF,GAAG,EAAE,CAAC,GAAG,IAAI,SAAS,CAAC;KACxB,CAAC;AACJ,CAAC"}
|