paperlint 7.2.0 → 9.0.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/CLAUDE.md +9 -25
- package/CONTRIBUTING.md +5 -4
- package/README.md +4 -3
- package/dist/adapters/bibtex/index.d.ts +3 -0
- package/dist/adapters/bibtex/index.d.ts.map +1 -0
- package/dist/adapters/bibtex/index.js +103 -0
- package/dist/adapters/bibtex/index.js.map +1 -0
- package/dist/adapters/latex/filecontents.d.ts +33 -0
- package/dist/adapters/latex/filecontents.d.ts.map +1 -0
- package/dist/adapters/latex/filecontents.js +65 -0
- package/dist/adapters/latex/filecontents.js.map +1 -0
- package/dist/adapters/latex/includes.d.ts +3 -3
- package/dist/adapters/latex/includes.d.ts.map +1 -1
- package/dist/adapters/latex/includes.js +18 -10
- package/dist/adapters/latex/includes.js.map +1 -1
- package/dist/adapters/latex/index.d.ts.map +1 -1
- package/dist/adapters/latex/index.js +2 -0
- package/dist/adapters/latex/index.js.map +1 -1
- package/dist/adapters/latex/nodes.d.ts +12 -0
- package/dist/adapters/latex/nodes.d.ts.map +1 -1
- package/dist/adapters/latex/nodes.js +39 -0
- package/dist/adapters/latex/nodes.js.map +1 -1
- package/dist/adapters/latex/parse.d.ts +7 -1
- package/dist/adapters/latex/parse.d.ts.map +1 -1
- package/dist/adapters/latex/parse.js +55 -6
- package/dist/adapters/latex/parse.js.map +1 -1
- package/dist/adapters/memory/index.d.ts +3 -0
- package/dist/adapters/memory/index.d.ts.map +1 -1
- package/dist/adapters/memory/index.js +9 -0
- package/dist/adapters/memory/index.js.map +1 -1
- package/dist/adapters/references/index.d.ts.map +1 -1
- package/dist/adapters/references/index.js +27 -24
- package/dist/adapters/references/index.js.map +1 -1
- package/dist/adapters/sources-record/index.d.ts +9 -0
- package/dist/adapters/sources-record/index.d.ts.map +1 -0
- package/dist/adapters/sources-record/index.js +68 -0
- package/dist/adapters/sources-record/index.js.map +1 -0
- package/dist/adapters/tex-output/blg.d.ts +9 -0
- package/dist/adapters/tex-output/blg.d.ts.map +1 -0
- package/dist/adapters/tex-output/blg.js +20 -0
- package/dist/adapters/tex-output/blg.js.map +1 -0
- package/dist/adapters/tex-output/fls.d.ts +8 -0
- package/dist/adapters/tex-output/fls.d.ts.map +1 -0
- package/dist/adapters/tex-output/fls.js +16 -0
- package/dist/adapters/tex-output/fls.js.map +1 -0
- package/dist/adapters/tex-output/index.d.ts +7 -0
- package/dist/adapters/tex-output/index.d.ts.map +1 -0
- package/dist/adapters/tex-output/index.js +7 -0
- package/dist/adapters/tex-output/index.js.map +1 -0
- package/dist/bib-rules.d.ts +47 -0
- package/dist/bib-rules.d.ts.map +1 -0
- package/dist/bib-rules.js +127 -0
- package/dist/bib-rules.js.map +1 -0
- package/dist/build.d.ts +29 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +41 -30
- package/dist/build.js.map +1 -1
- package/dist/claim-provenance.d.ts +2 -2
- package/dist/cli.d.ts +9 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +43 -68
- package/dist/cli.js.map +1 -1
- package/dist/domain/paper-source.d.ts +1 -10
- package/dist/domain/paper-source.d.ts.map +1 -1
- package/dist/domain/paper-source.js +34 -24
- package/dist/domain/paper-source.js.map +1 -1
- package/dist/domain/paper-sources.d.ts +72 -0
- package/dist/domain/paper-sources.d.ts.map +1 -0
- package/dist/domain/paper-sources.js +18 -0
- package/dist/domain/paper-sources.js.map +1 -0
- package/dist/domain/sources-record.d.ts +102 -0
- package/dist/domain/sources-record.d.ts.map +1 -0
- package/dist/domain/sources-record.js +38 -0
- package/dist/domain/sources-record.js.map +1 -0
- package/dist/domain/tex-run.d.ts +25 -0
- package/dist/domain/tex-run.d.ts.map +1 -0
- package/dist/domain/tex-run.js +79 -0
- package/dist/domain/tex-run.js.map +1 -0
- package/dist/eslint-rules/latex-language.d.ts.map +1 -1
- package/dist/eslint-rules/latex-language.js +10 -13
- package/dist/eslint-rules/latex-language.js.map +1 -1
- package/dist/eslint-rules/paper-context.d.ts.map +1 -1
- package/dist/eslint-rules/paper-context.js +6 -5
- package/dist/eslint-rules/paper-context.js.map +1 -1
- package/dist/eslint-rules/paper-typography.d.ts +0 -9
- package/dist/eslint-rules/paper-typography.d.ts.map +1 -1
- package/dist/eslint-rules/paper-typography.js +34 -96
- package/dist/eslint-rules/paper-typography.js.map +1 -1
- package/dist/eslint-rules/papers.d.ts +1 -3
- package/dist/eslint-rules/papers.d.ts.map +1 -1
- package/dist/eslint-rules/papers.js +2 -4
- package/dist/eslint-rules/papers.js.map +1 -1
- package/dist/eslint-rules/tex-build.d.ts.map +1 -1
- package/dist/eslint-rules/tex-build.js +8 -25
- package/dist/eslint-rules/tex-build.js.map +1 -1
- package/dist/init.d.ts +1 -4
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +3 -9
- package/dist/init.js.map +1 -1
- package/dist/latex-log.d.ts +10 -0
- package/dist/latex-log.d.ts.map +1 -1
- package/dist/latex-log.js +10 -0
- package/dist/latex-log.js.map +1 -1
- package/dist/latex-loop.d.ts +2 -0
- package/dist/latex-loop.d.ts.map +1 -1
- package/dist/latex-loop.js.map +1 -1
- package/dist/lib/markdown.d.ts +5 -81
- package/dist/lib/markdown.d.ts.map +1 -1
- package/dist/lib/markdown.js +5 -116
- package/dist/lib/markdown.js.map +1 -1
- package/dist/lib/paper-config.d.ts.map +1 -1
- package/dist/lib/paper-config.js +0 -2
- package/dist/lib/paper-config.js.map +1 -1
- package/dist/lib/skill-eval-fixture.d.ts +6 -4
- package/dist/lib/skill-eval-fixture.d.ts.map +1 -1
- package/dist/lib/skill-eval-fixture.js +25 -18
- package/dist/lib/skill-eval-fixture.js.map +1 -1
- package/dist/new-paper.d.ts +5 -11
- package/dist/new-paper.d.ts.map +1 -1
- package/dist/new-paper.js +12 -23
- package/dist/new-paper.js.map +1 -1
- package/dist/package-dirs.d.ts.map +1 -1
- package/dist/package-dirs.js +3 -2
- package/dist/package-dirs.js.map +1 -1
- package/dist/paper-files.d.ts +4 -4
- package/dist/paper-includes.d.ts +4 -7
- package/dist/paper-includes.d.ts.map +1 -1
- package/dist/paper-includes.js +29 -21
- package/dist/paper-includes.js.map +1 -1
- package/dist/paper-prose.d.ts +17 -0
- package/dist/paper-prose.d.ts.map +1 -0
- package/dist/paper-prose.js +46 -0
- package/dist/paper-prose.js.map +1 -0
- package/dist/paper-record.d.ts +25 -0
- package/dist/paper-record.d.ts.map +1 -0
- package/dist/paper-record.js +39 -0
- package/dist/paper-record.js.map +1 -0
- package/dist/paper-sources.d.ts +66 -0
- package/dist/paper-sources.d.ts.map +1 -0
- package/dist/paper-sources.js +92 -0
- package/dist/paper-sources.js.map +1 -0
- package/dist/ports/bib-reader.d.ts +18 -0
- package/dist/ports/bib-reader.d.ts.map +1 -0
- package/dist/ports/bib-reader.js +2 -0
- package/dist/ports/bib-reader.js.map +1 -0
- package/dist/ports/check-references.d.ts +9 -4
- package/dist/ports/check-references.d.ts.map +1 -1
- package/dist/ports/latex.d.ts +15 -0
- package/dist/ports/latex.d.ts.map +1 -1
- package/dist/ports/sources-codec.d.ts +11 -0
- package/dist/ports/sources-codec.d.ts.map +1 -0
- package/dist/ports/sources-codec.js +2 -0
- package/dist/ports/sources-codec.js.map +1 -0
- package/dist/ports/tex-output.d.ts +17 -0
- package/dist/ports/tex-output.d.ts.map +1 -0
- package/dist/ports/tex-output.js +2 -0
- package/dist/ports/tex-output.js.map +1 -0
- package/dist/recorded-bibliography.d.ts +89 -0
- package/dist/recorded-bibliography.d.ts.map +1 -0
- package/dist/recorded-bibliography.js +136 -0
- package/dist/recorded-bibliography.js.map +1 -0
- package/dist/reference-rules.d.ts +5 -5
- package/dist/reference-rules.d.ts.map +1 -1
- package/dist/reference-rules.js +150 -77
- package/dist/reference-rules.js.map +1 -1
- package/dist/references.d.ts +71 -16
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +110 -26
- package/dist/references.js.map +1 -1
- package/dist/register-bands.d.ts +3 -3
- package/dist/register-bands.d.ts.map +1 -1
- package/dist/register-bands.js.map +1 -1
- package/dist/register.d.ts +2 -2
- package/dist/sources-record.d.ts +38 -0
- package/dist/sources-record.d.ts.map +1 -0
- package/dist/sources-record.js +123 -0
- package/dist/sources-record.js.map +1 -0
- package/dist/sources-rules.d.ts +44 -0
- package/dist/sources-rules.d.ts.map +1 -0
- package/dist/sources-rules.js +76 -0
- package/dist/sources-rules.js.map +1 -0
- package/dist/structure.d.ts.map +1 -1
- package/dist/structure.js +4 -3
- package/dist/structure.js.map +1 -1
- package/dist/tex-paper.d.ts +10 -15
- package/dist/tex-paper.d.ts.map +1 -1
- package/dist/tex-paper.js +24 -40
- package/dist/tex-paper.js.map +1 -1
- package/dist/tex-venue-rules.d.ts +3 -3
- package/dist/tex-venue-rules.d.ts.map +1 -1
- package/dist/tex-venue-rules.js.map +1 -1
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +1 -1
- package/docs/configuration.md +18 -12
- package/docs/design/paper-sources.md +197 -0
- package/docs/e2e.md +4 -6
- package/docs/package-shape-options.md +1 -1
- package/docs/prior-art/paper-folder-scaffolding.md +24 -29
- package/docs/references.md +34 -8
- package/docs/rules/bib/reachable-entry.md +64 -0
- package/docs/rules/paper/sources-fresh.md +81 -0
- package/docs/rules/tex/claim-provenance.md +0 -1
- package/docs/rules.md +62 -61
- package/eslint-rules/latex-language.harness.mjs +3 -3
- package/eslint-rules/latex-language.ts +10 -13
- package/eslint-rules/paper-context.ts +6 -5
- package/eslint-rules/paper-typography.test.mjs +29 -157
- package/eslint-rules/paper-typography.ts +35 -104
- package/eslint-rules/papers.harness.mjs +1 -1
- package/eslint-rules/papers.ts +2 -4
- package/eslint-rules/tex-build.harness.mjs +2 -2
- package/eslint-rules/tex-build.ts +8 -25
- package/eslint.config.mjs +22 -1
- package/fixtures/build-e2e/aidc/paper.tex +1 -1
- package/fixtures/build-e2e/anon-ack/paper.tex +1 -1
- package/fixtures/build-e2e/anon-author/paper.tex +1 -1
- package/fixtures/build-e2e/anon-bib/paper.tex +1 -1
- package/fixtures/build-e2e/anon-href/paper.tex +1 -1
- package/fixtures/build-e2e/anon-macro/paper.tex +1 -1
- package/fixtures/build-e2e/anon-pdfauthor/paper.tex +1 -1
- package/fixtures/paper-sources/p1/paper.tex +30 -0
- package/fixtures/paper-sources/p1/refs.bib +6 -0
- package/fixtures/paper-sources/p1/sections/dead.tex +6 -0
- package/fixtures/paper-sources/p1/sections/intro.tex +7 -0
- package/fixtures/paper-sources/p1/sections/parked.tex +6 -0
- package/fixtures/paper-sources/p1/tex-truth.json +37 -0
- package/fixtures/paper-sources/p1/versions/2026-01-01-review.tex +4 -0
- package/fixtures/paper-sources/v1-stale/paper.tex +14 -0
- package/fixtures/paper-sources/v1-stale/refs.bib +6 -0
- package/fixtures/paper-sources/v1-stale/tex-truth.json +32 -0
- package/fixtures/paper-sources/v10-ifthenelse/anon.bib +1 -0
- package/fixtures/paper-sources/v10-ifthenelse/paper.tex +9 -0
- package/fixtures/paper-sources/v10-ifthenelse/real.bib +1 -0
- package/fixtures/paper-sources/v10-ifthenelse/tex-truth.json +28 -0
- package/fixtures/paper-sources/v11-two-blocks/paper.tex +12 -0
- package/fixtures/paper-sources/v11-two-blocks/tex-truth.json +30 -0
- package/fixtures/paper-sources/v13-percent-text/paper.tex +6 -0
- package/fixtures/paper-sources/v13-percent-text/refs.bib +3 -0
- package/fixtures/paper-sources/v13-percent-text/tex-truth.json +30 -0
- package/fixtures/paper-sources/v15-after-end/paper.tex +6 -0
- package/fixtures/paper-sources/v15-after-end/refs.bib +1 -0
- package/fixtures/paper-sources/v15-after-end/tex-truth.json +17 -0
- package/fixtures/paper-sources/v16-included-block/bibblock.tex +3 -0
- package/fixtures/paper-sources/v16-included-block/paper.tex +7 -0
- package/fixtures/paper-sources/v16-included-block/refs.bib +1 -0
- package/fixtures/paper-sources/v16-included-block/tex-truth.json +35 -0
- package/fixtures/paper-sources/v17-include-order/bibsetup.tex +1 -0
- package/fixtures/paper-sources/v17-include-order/first.bib +1 -0
- package/fixtures/paper-sources/v17-include-order/later.bib +1 -0
- package/fixtures/paper-sources/v17-include-order/paper.tex +7 -0
- package/fixtures/paper-sources/v17-include-order/tex-truth.json +40 -0
- package/fixtures/paper-sources/v2-overwrite/paper.tex +14 -0
- package/fixtures/paper-sources/v2-overwrite/refs.bib +6 -0
- package/fixtures/paper-sources/v2-overwrite/tex-truth.json +30 -0
- package/fixtures/paper-sources/v22-parked-thebibliography/paper.tex +7 -0
- package/fixtures/paper-sources/v22-parked-thebibliography/tex-truth.json +17 -0
- package/fixtures/paper-sources/v23-parked-include/old.bib +1 -0
- package/fixtures/paper-sources/v23-parked-include/paper.tex +7 -0
- package/fixtures/paper-sources/v23-parked-include/parked.tex +1 -0
- package/fixtures/paper-sources/v23-parked-include/refs.bib +1 -0
- package/fixtures/paper-sources/v23-parked-include/tex-truth.json +28 -0
- package/fixtures/paper-sources/v24-quoted-fields/paper.tex +6 -0
- package/fixtures/paper-sources/v24-quoted-fields/refs.bib +5 -0
- package/fixtures/paper-sources/v24-quoted-fields/tex-truth.json +32 -0
- package/fixtures/paper-sources/v25-string-differs/paper.tex +10 -0
- package/fixtures/paper-sources/v25-string-differs/refs.bib +2 -0
- package/fixtures/paper-sources/v25-string-differs/tex-truth.json +32 -0
- package/fixtures/paper-sources/v26-comment-in-names/one.bib +1 -0
- package/fixtures/paper-sources/v26-comment-in-names/paper.tex +7 -0
- package/fixtures/paper-sources/v26-comment-in-names/tex-truth.json +32 -0
- package/fixtures/paper-sources/v26-comment-in-names/two.bib +1 -0
- package/fixtures/paper-sources/v27-shared-string/abbreviations.bib +2 -0
- package/fixtures/paper-sources/v27-shared-string/paper.tex +6 -0
- package/fixtures/paper-sources/v27-shared-string/references.bib +6 -0
- package/fixtures/paper-sources/v27-shared-string/tex-truth.json +31 -0
- package/fixtures/paper-sources/v28-shared-string-block/abbreviations.bib +2 -0
- package/fixtures/paper-sources/v28-shared-string-block/paper.tex +14 -0
- package/fixtures/paper-sources/v28-shared-string-block/tex-truth.json +33 -0
- package/fixtures/paper-sources/v29-generated-input/paper.tex +9 -0
- package/fixtures/paper-sources/v29-generated-input/tex-truth.json +24 -0
- package/fixtures/paper-sources/v3-declared/paper.bib +6 -0
- package/fixtures/paper-sources/v3-declared/paper.tex +6 -0
- package/fixtures/paper-sources/v3-declared/tex-truth.json +28 -0
- package/fixtures/paper-sources/v30-name-next-line/paper.tex +14 -0
- package/fixtures/paper-sources/v30-name-next-line/tex-truth.json +30 -0
- package/fixtures/paper-sources/v4-commented/paper.tex +14 -0
- package/fixtures/paper-sources/v4-commented/refs.bib +6 -0
- package/fixtures/paper-sources/v4-commented/tex-truth.json +28 -0
- package/fixtures/paper-sources/v5-percent-entry/paper.tex +20 -0
- package/fixtures/paper-sources/v5-percent-entry/tex-truth.json +37 -0
- package/fixtures/paper-sources/v6-unclosed/paper.tex +6 -0
- package/fixtures/paper-sources/v6-unclosed/refs.bib +5 -0
- package/fixtures/paper-sources/v6-unclosed/tex-truth.json +37 -0
- package/fixtures/paper-sources/v8-jobname/paper.tex +9 -0
- package/fixtures/paper-sources/v8-jobname/tex-truth.json +30 -0
- package/fixtures/paper-sources/v9-two-bibliographies/one.bib +1 -0
- package/fixtures/paper-sources/v9-two-bibliographies/paper.tex +7 -0
- package/fixtures/paper-sources/v9-two-bibliographies/tex-truth.json +35 -0
- package/fixtures/paper-sources/v9-two-bibliographies/two.bib +1 -0
- package/fixtures/paper-typography/clean-paper/paper.tex +1 -1
- package/fixtures/paper-typography/messy-paper/paper.tex +1 -1
- package/hooks/hooks.harness.ts +15 -15
- package/hooks/paper-edit-guard.hook.mjs +5 -8
- package/hooks/paper-edit-guard.test.ts +12 -3
- package/hooks/paper-skills-nudge.hook.mjs +2 -3
- package/hooks/paper-skills-nudge.test.ts +13 -3
- package/hooks/paper-status-gates.hook.mjs +2 -2
- package/hooks/paper-status-gates.test.ts +14 -2
- package/lib/markdown.test.mjs +5 -60
- package/lib/markdown.ts +9 -136
- package/lib/paper-config.ts +0 -2
- package/lib/skill-checks.test.mjs +4 -1
- package/lib/skill-eval-fixture.ts +25 -18
- package/package.json +2 -12
- package/presets/realm.jsonc +1 -1
- package/scripts/check.test.ts +23 -1
- package/scripts/check.ts +7 -3
- package/scripts/coverage-config.test.ts +19 -10
- package/scripts/harness-api.frozen.json +0 -5
- package/scripts/layer-legacy-frozen.test.ts +41 -2
- package/scripts/layer-legacy-frozen.ts +31 -2
- package/skills/cold-read-diff/SKILL.md +3 -3
- package/skills/cold-read-diff/SKILL.md.spec.ts +2 -2
- package/skills/grade-paper-writing/SKILL.md +15 -22
- package/skills/grade-paper-writing/SKILL.md.spec.ts +14 -21
- package/skills/grade-paper-writing/__snapshots__/prose-lint.test.ts.snap +40 -26
- package/skills/grade-paper-writing/prose-lint.mjs +117 -278
- package/skills/grade-paper-writing/prose-lint.test.ts +230 -79
- package/skills/paper-adversarial-review/SKILL.md +2 -2
- package/skills/paper-adversarial-review/SKILL.md.spec.ts +1 -1
- package/skills/paper-pipeline/SKILL.md +9 -12
- package/skills/paper-pipeline/SKILL.md.spec.ts +8 -11
- package/skills/paper-pipeline/description-language.eval.mjs +25 -15
- package/skills/paper-pipeline/framing-vs-vocabulary.eval.mjs +25 -15
- package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +25 -15
- package/skills/paper-pipeline/pipeline-firing.eval.mjs +27 -16
- package/skills/paper-pipeline/pipeline-language.eval.mjs +25 -15
- package/skills/paper-pipeline/references/acceptance-gate.md +16 -20
- package/skills/paper-pipeline/references/artifact-checklist.md +4 -5
- package/skills/paper-pipeline/references/pipeline-status-template.md +1 -1
- package/skills/paper-pipeline/scripts/README.md +0 -4
- package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +91 -105
- package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +85 -241
- package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +166 -153
- package/skills/paper-pipeline/scripts/generated-code.harness.mjs +3 -3
- package/skills/paper-status/SKILL.md +2 -2
- package/skills/paper-status/SKILL.md.spec.ts +1 -1
- package/skills/render-paper/SKILL.md +2 -2
- package/skills/render-paper/SKILL.md.spec.ts +1 -1
- package/skills/render-paper/extract-pdf-facts.mjs +2 -2
- package/skills/tighten-paper/SKILL.md +29 -42
- package/skills/tighten-paper/SKILL.md.spec.ts +28 -41
- package/skills/verify-citations/SKILL.md +7 -4
- package/skills/verify-citations/SKILL.md.spec.ts +6 -3
- package/skills/verify-citations/scripts/bib-authors.check.test.mjs +17 -32
- package/skills/verify-citations/scripts/bib-authors.cli.test.ts +138 -43
- package/skills/verify-citations/scripts/bib-authors.d.mts +22 -2
- package/skills/verify-citations/scripts/bib-authors.mjs +54 -193
- package/skills/verify-citations/scripts/bib-authors.test.mjs +1 -44
- package/skills/verify-citations/scripts/verify-cites.cli.test.ts +16 -0
- package/skills/verify-citations/scripts/verify-cites.d.mts +19 -3
- package/skills/verify-citations/scripts/verify-cites.mjs +42 -108
- package/skills/verify-citations/scripts/verify-cites.test.mjs +23 -36
- package/src/adapters/bibtex/index.test.ts +163 -0
- package/src/adapters/bibtex/index.ts +155 -0
- package/src/adapters/latex/filecontents.ts +114 -0
- package/src/adapters/latex/includes.ts +18 -10
- package/src/adapters/latex/index.test.ts +73 -0
- package/src/adapters/latex/index.ts +2 -0
- package/src/adapters/latex/nodes.ts +64 -0
- package/src/adapters/latex/parse.test.ts +38 -0
- package/src/adapters/latex/parse.ts +67 -6
- package/src/adapters/memory/index.ts +17 -0
- package/src/adapters/references/index.test.ts +75 -21
- package/src/adapters/references/index.ts +37 -32
- package/src/adapters/sources-record/index.test.ts +87 -0
- package/src/adapters/sources-record/index.ts +82 -0
- package/src/adapters/tex-output/blg.ts +27 -0
- package/src/adapters/tex-output/fls.ts +24 -0
- package/src/adapters/tex-output/index.test.ts +171 -0
- package/src/adapters/tex-output/index.ts +12 -0
- package/src/bib-rules.test.ts +356 -0
- package/src/bib-rules.ts +228 -0
- package/src/bibliography-at.test.ts +286 -0
- package/src/build.harness.mjs +2 -2
- package/src/build.test.ts +211 -1
- package/src/build.ts +101 -41
- package/src/claim-provenance.test.ts +33 -7
- package/src/claim-provenance.ts +2 -2
- package/src/cli.harness.mjs +46 -56
- package/src/cli.test.ts +44 -48
- package/src/cli.ts +51 -82
- package/src/domain/paper-source.test.ts +58 -20
- package/src/domain/paper-source.ts +38 -42
- package/src/domain/paper-sources.ts +94 -0
- package/src/domain/sources-record.test.ts +71 -0
- package/src/domain/sources-record.ts +136 -0
- package/src/domain/tex-run.test.ts +228 -0
- package/src/domain/tex-run.ts +139 -0
- package/src/folder-venue-rule.test.ts +1 -1
- package/src/heading-case.test.ts +24 -10
- package/src/init.test.ts +6 -7
- package/src/init.ts +3 -22
- package/src/latex-log.ts +20 -0
- package/src/latex-loop.harness.ts +1 -0
- package/src/latex-loop.ts +2 -0
- package/src/lint-fix.test.ts +10 -4
- package/src/linted-set.test.ts +9 -1
- package/src/new-paper.harness.mjs +12 -30
- package/src/new-paper.test.ts +15 -11
- package/src/new-paper.ts +11 -30
- package/src/package-dirs.ts +3 -2
- package/src/paper-files.test.ts +5 -4
- package/src/paper-files.ts +4 -4
- package/src/paper-includes.test.ts +157 -38
- package/src/paper-includes.ts +39 -35
- package/src/paper-prose.test.ts +78 -0
- package/src/paper-prose.ts +67 -0
- package/src/paper-record.test.ts +173 -0
- package/src/paper-record.ts +66 -0
- package/src/paper-settings-commands.test.ts +5 -2
- package/src/paper-sources.ts +151 -0
- package/src/parse-args.test.ts +0 -1
- package/src/ports/bib-reader.ts +27 -0
- package/src/ports/check-references.ts +7 -3
- package/src/ports/latex.ts +19 -0
- package/src/ports/sources-codec.ts +11 -0
- package/src/ports/tex-output.ts +17 -0
- package/src/recorded-bibliography.ts +297 -0
- package/src/reference-rules.ts +217 -104
- package/src/references.test.ts +520 -177
- package/src/references.ts +185 -37
- package/src/register-bands.test.ts +5 -1
- package/src/register-bands.ts +3 -5
- package/src/register.test.ts +6 -1
- package/src/register.ts +2 -2
- package/src/rule-cases.test.ts +68 -12
- package/src/rule-docs.test.ts +0 -1
- package/src/sources-record.test.ts +308 -0
- package/src/sources-record.ts +231 -0
- package/src/sources-rules.test.ts +152 -0
- package/src/sources-rules.ts +117 -0
- package/src/structure.harness.ts +5 -11
- package/src/structure.ts +4 -3
- package/src/tex-paper.test.ts +148 -78
- package/src/tex-paper.ts +31 -61
- package/src/tex-venue-rules.test.ts +36 -8
- package/src/tex-venue-rules.ts +3 -5
- package/src/types.ts +0 -2
- package/dist/eslint-rules/bib-reachable-entry.d.ts +0 -22
- package/dist/eslint-rules/bib-reachable-entry.d.ts.map +0 -1
- package/dist/eslint-rules/bib-reachable-entry.js +0 -75
- package/dist/eslint-rules/bib-reachable-entry.js.map +0 -1
- package/eslint-rules/bib-reachable-entry.ts +0 -76
- package/fixtures/real-markdown-paper/baseline.json +0 -22
- package/fixtures/real-markdown-paper/baseline.ts +0 -70
- package/skills/paper-pipeline/PIPELINE-MAP.md +0 -381
- package/skills/paper-pipeline/pipeline-firing.baseline.json +0 -270
- package/skills/paper-pipeline/references/sweep-2026-08-09-ideal-pipeline.md +0 -585
- package/skills/paper-pipeline/scripts/artifact-coverage.harness.mjs +0 -492
- package/skills/paper-pipeline/scripts/artifact-coverage.mjs +0 -397
- package/skills/paper-pipeline/scripts/artifact-coverage.test.ts +0 -86
- package/skills/paper-pipeline/scripts/check-provenance.mjs +0 -184
- package/skills/paper-pipeline/scripts/population-map.harness.mjs +0 -135
- package/skills/paper-pipeline/scripts/population-map.mjs +0 -188
- package/skills/paper-pipeline/scripts/population-map.test.mjs +0 -154
- package/skills/paper-pipeline/scripts/provenance.harness.mjs +0 -266
- package/skills/paper-pipeline/scripts/round-diff.harness.ts +0 -907
- package/skills/paper-pipeline/scripts/round-diff.mjs +0 -583
- package/skills/paper-pipeline/scripts/round-diff.test.mjs +0 -159
- package/skills/tighten-paper/__snapshots__/structure.test.ts.snap +0 -133
- package/skills/tighten-paper/structure.mjs +0 -364
- package/skills/tighten-paper/structure.test.ts +0 -117
- package/templates/paper/paper.md +0 -4
|
@@ -9,16 +9,23 @@
|
|
|
9
9
|
* answers about one file (the class, the outline, the rendered text, the body's passages) is
|
|
10
10
|
* answered about the paper, unchanged. A subfile is a document of its own; only its body is spliced.
|
|
11
11
|
*
|
|
12
|
+
* ── THE END OF AN INCLUDED FILE'S LAST LINE ─────────────────────────────────────
|
|
13
|
+
* TeX ends every line it reads with its end-of-line character, the last line of a file included:
|
|
14
|
+
* `a\input{f}b` with `f` holding `foo` and no final newline typesets "afoo b" (measured, TeX Live
|
|
15
|
+
* 2026), not "afoob". The splice does the same: an included file whose text does not end in a newline
|
|
16
|
+
* gets one, mapped to the end of that file; an empty file read no line and gets nothing. The main file
|
|
17
|
+
* is the caller's text and is left as given.
|
|
18
|
+
*
|
|
12
19
|
* ── WHAT IS NOT DONE ─────────────────────────────────────────────────────────────
|
|
13
20
|
* No macro is expanded, so a path built from a macro (`\input{\dir/intro}`) is read as written. A
|
|
14
|
-
* file
|
|
15
|
-
*
|
|
21
|
+
* file the caller's `read` has none of contributes nothing; a file that includes itself, directly or
|
|
22
|
+
* through others, is spliced once.
|
|
16
23
|
*/
|
|
17
|
-
import {
|
|
24
|
+
import { posix } from "node:path";
|
|
18
25
|
/** The paths TeX tries for a target: `name.tex`, then `name` — or the name alone if it has one. */
|
|
19
26
|
const candidates = (target) => {
|
|
20
|
-
const t = normalize(target.trim());
|
|
21
|
-
return extname(t) === "" ? [`${t}.tex`, t] : [t];
|
|
27
|
+
const t = posix.normalize(target.trim());
|
|
28
|
+
return posix.extname(t) === "" ? [`${t}.tex`, t] : [t];
|
|
22
29
|
};
|
|
23
30
|
/** The first candidate path that exists, with its text. */
|
|
24
31
|
function found(target, read) {
|
|
@@ -36,15 +43,13 @@ const copied = ({ file, text, from, to, via }) => ({
|
|
|
36
43
|
segments: to > from
|
|
37
44
|
? [{ start: 0, end: to - from, file, source: text, from, via }]
|
|
38
45
|
: [],
|
|
39
|
-
missing: [],
|
|
40
46
|
});
|
|
41
47
|
/** Nothing: an include left out. */
|
|
42
|
-
const NOTHING = { text: "", segments: []
|
|
48
|
+
const NOTHING = { text: "", segments: [] };
|
|
43
49
|
/** Pieces joined in order. */
|
|
44
50
|
const joined = (pieces) => pieces.reduce((acc, p) => ({
|
|
45
51
|
text: acc.text + p.text,
|
|
46
52
|
segments: [...acc.segments, ...shifted(p.segments, acc.text.length)],
|
|
47
|
-
missing: [...acc.missing, ...p.missing],
|
|
48
53
|
}), NOTHING);
|
|
49
54
|
function spliced(file, text, range, ctx) {
|
|
50
55
|
const incs = ctx.deps
|
|
@@ -55,35 +60,40 @@ function spliced(file, text, range, ctx) {
|
|
|
55
60
|
pieces: [
|
|
56
61
|
...acc.pieces,
|
|
57
62
|
at(acc.cursor, inc.span.start),
|
|
58
|
-
included(
|
|
63
|
+
included(inc, ctx),
|
|
59
64
|
],
|
|
60
65
|
cursor: inc.span.end,
|
|
61
66
|
}), { pieces: [], cursor: range.start });
|
|
62
67
|
return joined([...pieces, at(cursor, range.end)]);
|
|
63
68
|
}
|
|
64
|
-
/**
|
|
65
|
-
|
|
69
|
+
/** TeX's end of line after the last line of `file`, standing where its text ends: one newline. */
|
|
70
|
+
const endOfLine = (file, text, via) => ({
|
|
71
|
+
text: "\n",
|
|
72
|
+
segments: [{ start: 0, end: 1, file, source: text, from: text.length, via }],
|
|
73
|
+
});
|
|
74
|
+
/** One include: the file it names, spliced, or — when the reader has none of it — nothing. */
|
|
75
|
+
function included(inc, ctx) {
|
|
66
76
|
const via = ctx.via ?? inc.span;
|
|
67
77
|
const hit = found(inc.target, ctx.deps.read);
|
|
68
|
-
if (hit === null)
|
|
69
|
-
return {
|
|
70
|
-
...NOTHING,
|
|
71
|
-
missing: [{ file, target: inc.target, span: inc.span, via }],
|
|
72
|
-
};
|
|
73
|
-
if (ctx.stack.includes(hit.path))
|
|
78
|
+
if (hit === null || ctx.stack.includes(hit.path))
|
|
74
79
|
return NOTHING;
|
|
75
80
|
const body = inc.macro === "subfile" ? ctx.deps.documentBody(hit.text) : null;
|
|
76
|
-
|
|
81
|
+
const range = body ?? { start: 0, end: hit.text.length };
|
|
82
|
+
const piece = spliced(hit.path, hit.text, range, {
|
|
83
|
+
deps: ctx.deps,
|
|
84
|
+
stack: [...ctx.stack, hit.path],
|
|
85
|
+
via,
|
|
86
|
+
});
|
|
87
|
+
// The last line of the file is read to its end; a subfile's body ends inside its last line.
|
|
88
|
+
const endsLine = range.end === hit.text.length &&
|
|
89
|
+
hit.text !== "" &&
|
|
90
|
+
!hit.text.endsWith("\n");
|
|
91
|
+
return endsLine ? joined([piece, endOfLine(hit.path, hit.text, via)]) : piece;
|
|
77
92
|
}
|
|
78
93
|
/** The paper whose main file is `main` (a path relative to the paper directory) with `text`. */
|
|
79
94
|
export function assemblePaper(main, text, deps) {
|
|
80
95
|
const p = spliced(main, text, { start: 0, end: text.length }, { deps, stack: [main], via: null });
|
|
81
|
-
return {
|
|
82
|
-
main,
|
|
83
|
-
text: p.text,
|
|
84
|
-
segments: p.segments,
|
|
85
|
-
missing: p.missing,
|
|
86
|
-
};
|
|
96
|
+
return { main, text: p.text, segments: p.segments };
|
|
87
97
|
}
|
|
88
98
|
/**
|
|
89
99
|
* The origin of `span` of the assembled text: the file of its first character. A span that runs
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paper-source.js","sourceRoot":"","sources":["../../src/domain/paper-source.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"paper-source.js","sourceRoot":"","sources":["../../src/domain/paper-source.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHAT A DATABASE IS — the values the bibtex reader (`BibReader`, src/ports/bib-reader.ts) returns for
|
|
3
|
+
* a `.bib`, or for the body of a `filecontents` block: its entries, and the bytes bibtex takes from
|
|
4
|
+
* them. Which databases a paper reads is TeX's answer, recorded by the build (`_build/sources.json`,
|
|
5
|
+
* src/domain/sources-record.ts, docs/design/paper-sources.md §1); nothing here decides it.
|
|
6
|
+
*/
|
|
7
|
+
import type { AbsolutePath } from "./paths.ts";
|
|
8
|
+
import type { Span } from "./tex-document.ts";
|
|
9
|
+
/** The main file's name — the file TeX is given. */
|
|
10
|
+
export declare const MAIN_FILE = "paper.tex";
|
|
11
|
+
/** A name in a name list (`author`, `editor`), split into its parts as BibTeX defines them. */
|
|
12
|
+
export interface BibName {
|
|
13
|
+
readonly lastName?: string;
|
|
14
|
+
readonly firstName?: string;
|
|
15
|
+
readonly prefix?: string;
|
|
16
|
+
readonly suffix?: string;
|
|
17
|
+
/** A name written as one unit (`{World Health Organization}`). */
|
|
18
|
+
readonly name?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The `@string`s in force: each name as bibtex folds it (upper case) → its value as bibtex takes it,
|
|
22
|
+
* the `@string`s it used expanded and its LaTeX as written. bibtex reads a paper's databases one after
|
|
23
|
+
* the other with one table of them, so a `@string` an earlier database defines is in force in a later
|
|
24
|
+
* one (measured: `\\bibliography{abbreviations,references}` typesets an entry of `references.bib` with
|
|
25
|
+
* the author and booktitle `abbreviations.bib` defines; in the other order both are undefined).
|
|
26
|
+
*/
|
|
27
|
+
export type BibStrings = Readonly<Record<string, string>>;
|
|
28
|
+
/** One entry of a database. */
|
|
29
|
+
export interface BibEntry {
|
|
30
|
+
/** Lower-cased (`@Article` → `article`). */
|
|
31
|
+
readonly type: string;
|
|
32
|
+
readonly key: string;
|
|
33
|
+
/** From its `@` to its closing brace or parenthesis, in the text of the file that holds it. */
|
|
34
|
+
readonly span: Span;
|
|
35
|
+
/** Its fields, LaTeX read into text (`{\"u}` → `ü`, `\url{x}` → a link); a list field joined by ` and `. */
|
|
36
|
+
readonly fields: Readonly<Record<string, string>>;
|
|
37
|
+
/** Its name lists (`author`, `editor`, …), each name split into its parts. */
|
|
38
|
+
readonly names: Readonly<Record<string, readonly BibName[]>>;
|
|
39
|
+
}
|
|
40
|
+
/** The bytes of one database, where they sit, and what the reader read from them. */
|
|
41
|
+
export interface BibText {
|
|
42
|
+
/** The file holding the bytes: the `.bib`, or the `.tex` that holds the block. */
|
|
43
|
+
readonly path: AbsolutePath;
|
|
44
|
+
/** That file's whole text; every span here is an offset into it. */
|
|
45
|
+
readonly text: string;
|
|
46
|
+
/** The database inside `text`: all of it for a `.bib`, the body for a block. */
|
|
47
|
+
readonly body: Span;
|
|
48
|
+
readonly entries: readonly BibEntry[];
|
|
49
|
+
/** The same entries as bibtex takes them, in order: what two databases are compared by. */
|
|
50
|
+
readonly written: readonly WrittenEntry[];
|
|
51
|
+
/** The `@preamble` commands, as written, in order: bibtex writes them into the `.bbl`. */
|
|
52
|
+
readonly preamble: readonly string[];
|
|
53
|
+
/** The `@string`s the databases bibtex read before this one left in force: none for one read alone. */
|
|
54
|
+
readonly inherited: BibStrings;
|
|
55
|
+
/** The `@string`s in force after it — `inherited` and its own, a later one winning: what the next database starts with. */
|
|
56
|
+
readonly strings: BibStrings;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* An entry as bibtex takes it from the database: the type, the key, and each field's value with the
|
|
60
|
+
* `@string`s it uses expanded where it uses them (a later redefinition changes nothing) and its LaTeX
|
|
61
|
+
* as written — `{\"o}` and `ö` are different values here, as they are in the `.bbl` bibtex writes.
|
|
62
|
+
*/
|
|
63
|
+
export interface WrittenEntry {
|
|
64
|
+
/** Lower-cased, as bibtex reads it. */
|
|
65
|
+
readonly type: string;
|
|
66
|
+
readonly key: string;
|
|
67
|
+
/** Whitespace runs folded to one space, as bibtex folds them. */
|
|
68
|
+
readonly fields: Readonly<Record<string, string>>;
|
|
69
|
+
}
|
|
70
|
+
/** Whether two databases hold the same, as TeX's own copy of a block holds the block's. */
|
|
71
|
+
export declare const sameDatabase: (a: BibText, b: BibText) => boolean;
|
|
72
|
+
//# sourceMappingURL=paper-sources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paper-sources.d.ts","sourceRoot":"","sources":["../../src/domain/paper-sources.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAE9C,oDAAoD;AACpD,eAAO,MAAM,SAAS,cAAc,CAAC;AAErC,+FAA+F;AAC/F,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE1D,+BAA+B;AAC/B,MAAM,WAAW,QAAQ;IACvB,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,+FAA+F;IAC/F,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,4GAA4G;IAC5G,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,OAAO,EAAE,CAAC,CAAC,CAAC;CAC9D;AAED,qFAAqF;AACrF,MAAM,WAAW,OAAO;IACtB,kFAAkF;IAClF,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gFAAgF;IAChF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAC;IACtC,2FAA2F;IAC3F,QAAQ,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,CAAC;IAC1C,0FAA0F;IAC1F,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,uGAAuG;IACvG,QAAQ,CAAC,SAAS,EAAE,UAAU,CAAC;IAC/B,2HAA2H;IAC3H,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;CAC9B;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAiBD,2FAA2F;AAC3F,eAAO,MAAM,YAAY,GAAI,GAAG,OAAO,EAAE,GAAG,OAAO,KAAG,OACvB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** The main file's name — the file TeX is given. */
|
|
2
|
+
export const MAIN_FILE = "paper.tex";
|
|
3
|
+
/**
|
|
4
|
+
* What bibtex takes from a database, for comparing two: each entry as bibtex reads it, in order, its
|
|
5
|
+
* fields in name order, and the `@preamble` commands. Nothing else in the bytes reaches the `.bbl`:
|
|
6
|
+
* not the text between entries (a `filecontents` header among it), not a `@string` no entry uses.
|
|
7
|
+
*/
|
|
8
|
+
const contentOf = (b) => JSON.stringify([
|
|
9
|
+
b.written.map((e) => [
|
|
10
|
+
e.type,
|
|
11
|
+
e.key,
|
|
12
|
+
Object.entries(e.fields).sort(([x], [y]) => x.localeCompare(y)),
|
|
13
|
+
]),
|
|
14
|
+
b.preamble,
|
|
15
|
+
]);
|
|
16
|
+
/** Whether two databases hold the same, as TeX's own copy of a block holds the block's. */
|
|
17
|
+
export const sameDatabase = (a, b) => contentOf(a) === contentOf(b);
|
|
18
|
+
//# sourceMappingURL=paper-sources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paper-sources.js","sourceRoot":"","sources":["../../src/domain/paper-sources.ts"],"names":[],"mappings":"AASA,oDAAoD;AACpD,MAAM,CAAC,MAAM,SAAS,GAAG,WAAW,CAAC;AAkErC;;;;GAIG;AACH,MAAM,SAAS,GAAG,CAAC,CAAU,EAAU,EAAE,CACvC,IAAI,CAAC,SAAS,CAAC;IACb,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACnB,CAAC,CAAC,IAAI;QACN,CAAC,CAAC,GAAG;QACL,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;KAChE,CAAC;IACF,CAAC,CAAC,QAAQ;CACX,CAAC,CAAC;AAEL,2FAA2F;AAC3F,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAU,EAAE,CAAU,EAAW,EAAE,CAC9D,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHAT THE LAST BUILD READ — `<paper>/_build/sources.json`, written by `paperlint build` from TeX's
|
|
3
|
+
* own files (docs/design/paper-sources.md §1) and read, offline, by the rules that need to know which
|
|
4
|
+
* files make up a paper and which bibliography it uses. Nothing else answers either question: no
|
|
5
|
+
* code of paperlint reads TeX source to decide them.
|
|
6
|
+
*
|
|
7
|
+
* { "schema": 1,
|
|
8
|
+
* "inputs": [ { "path": "paper.tex", "role": "body" }, … ], the files of the paper directory TeX
|
|
9
|
+
* read, in first-read order
|
|
10
|
+
* "written": [ "refs.bib" ], the `.bib` and `.tex` files TeX wrote (filecontents)
|
|
11
|
+
* "bibdata": [ "refs" ], what `\bibdata` told bibtex to read
|
|
12
|
+
* "bibtex": { "ran": true, "databases": [ "refs.bib" ], the files bibtex opened, the keys it
|
|
13
|
+
* "keys": [ … ], "exit": 0, "errors": [] }, typeset, how it ended
|
|
14
|
+
* "sha256": { "paper.tex": "…", … } } every input and every database bibtex
|
|
15
|
+
* opened, by path and bytes
|
|
16
|
+
*
|
|
17
|
+
* 🔴 A role is the file's, and the main file is the body. A file is `preamble` when TeX read it only
|
|
18
|
+
* before `\begin{document}` — before it opened `paper.aux` for writing (measured) — and `body` when
|
|
19
|
+
* any read of it came after. The main file, the first one read, is `body` whatever its place in that
|
|
20
|
+
* order: it holds `\begin{document}` itself.
|
|
21
|
+
*
|
|
22
|
+
* The text of the file is checked once, where it enters: `SourcesCodec` (`src/ports/sources-codec.ts`),
|
|
23
|
+
* whose adapter holds the zod schema of this shape. The domain holds the value.
|
|
24
|
+
*
|
|
25
|
+
* 🔴 STALENESS is the record's own question: `changesSince` compares the bytes now with `sha256`, one
|
|
26
|
+
* key per file, so a rule can tell that the paper changed after the build without running TeX. A `.bib`
|
|
27
|
+
* TeX wrote is hashed too: the rules read it from disk, so an edit to it after the build is a change.
|
|
28
|
+
*/
|
|
29
|
+
import type { Sha256 } from "./sha256.ts";
|
|
30
|
+
export declare const SOURCES_SCHEMA = 1;
|
|
31
|
+
export declare const SOURCES_DIR = "_build";
|
|
32
|
+
export declare const SOURCES_FILE = "sources.json";
|
|
33
|
+
/** The job name every file a build writes carries (`paper.aux`, `paper.fls`): the build names its job so. */
|
|
34
|
+
export declare const JOBNAME = "paper";
|
|
35
|
+
/** Before or after `\begin{document}`. */
|
|
36
|
+
export type InputRole = "preamble" | "body";
|
|
37
|
+
/** One file of the paper directory that TeX read. `path` is relative to it, with forward slashes. */
|
|
38
|
+
export interface RecordedInput {
|
|
39
|
+
readonly path: string;
|
|
40
|
+
readonly role: InputRole;
|
|
41
|
+
}
|
|
42
|
+
/** One error bibtex reported, as its `.blg` says it. */
|
|
43
|
+
export interface BibtexError {
|
|
44
|
+
readonly message: string;
|
|
45
|
+
/** The file it was reading (`refs.bib`, `paper.aux`). */
|
|
46
|
+
readonly file: string;
|
|
47
|
+
/** Null when bibtex named no line. */
|
|
48
|
+
readonly line: number | null;
|
|
49
|
+
}
|
|
50
|
+
/** What the build's bibtex did — or that the build ran none (the paper names no database). */
|
|
51
|
+
export type RecordedBibtex = {
|
|
52
|
+
readonly ran: false;
|
|
53
|
+
} | {
|
|
54
|
+
readonly ran: true;
|
|
55
|
+
/** The database files it opened, as it names them (`refs.bib`, `bibs/x.bib`). */
|
|
56
|
+
readonly databases: readonly string[];
|
|
57
|
+
/** The keys it typeset: every `\bibitem` of the `.bbl`. */
|
|
58
|
+
readonly keys: readonly string[];
|
|
59
|
+
readonly exit: number;
|
|
60
|
+
readonly errors: readonly BibtexError[];
|
|
61
|
+
};
|
|
62
|
+
export interface SourcesRecord {
|
|
63
|
+
readonly schema: typeof SOURCES_SCHEMA;
|
|
64
|
+
readonly inputs: readonly RecordedInput[];
|
|
65
|
+
readonly written: readonly string[];
|
|
66
|
+
readonly bibdata: readonly string[];
|
|
67
|
+
readonly bibtex: RecordedBibtex;
|
|
68
|
+
/** Path → digest of its bytes; null for a file that was not there when the record was made. */
|
|
69
|
+
readonly sha256: Readonly<Record<string, string | null>>;
|
|
70
|
+
}
|
|
71
|
+
export type ParsedRecord = {
|
|
72
|
+
readonly ok: true;
|
|
73
|
+
readonly record: SourcesRecord;
|
|
74
|
+
} | {
|
|
75
|
+
readonly ok: false;
|
|
76
|
+
readonly why: string;
|
|
77
|
+
};
|
|
78
|
+
/** The record as the file holds it: two-space JSON and a final newline, so a diff of two builds reads. */
|
|
79
|
+
export declare const serializeSourcesRecord: (r: SourcesRecord) => string;
|
|
80
|
+
export type ChangeKind = "edited" | "deleted" | "added";
|
|
81
|
+
/** One file whose bytes are not those the build hashed. */
|
|
82
|
+
export interface Change {
|
|
83
|
+
readonly path: string;
|
|
84
|
+
readonly change: ChangeKind;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* The files whose bytes now differ from the record's: edited, deleted, or present where the record saw
|
|
88
|
+
* none. `now` answers for one path with the digest of its bytes, or null when there is no such file.
|
|
89
|
+
* Empty when the record is current.
|
|
90
|
+
*/
|
|
91
|
+
export declare function changesSince(r: SourcesRecord, now: (path: string) => Sha256 | null): readonly Change[];
|
|
92
|
+
/** `paper.tex edited, sections/a.tex deleted` — what a finding names. */
|
|
93
|
+
export declare const describeChanges: (cs: readonly Change[]) => string;
|
|
94
|
+
/**
|
|
95
|
+
* The name among `names` that `name` stands for: `name` itself, else the one name equal to it ignoring
|
|
96
|
+
* case — null when there is none, or several. TeX opens a file by the name the source gives it; on a
|
|
97
|
+
* file system that ignores case that is the source's spelling, on one that does not TeX retries
|
|
98
|
+
* without case, and the record holds the disk's spelling either way. A name and the record's spelling
|
|
99
|
+
* of it are matched by this, once, wherever one is looked up in the other.
|
|
100
|
+
*/
|
|
101
|
+
export declare function spelledIn(names: readonly string[], name: string): string | null;
|
|
102
|
+
//# sourceMappingURL=sources-record.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources-record.d.ts","sourceRoot":"","sources":["../../src/domain/sources-record.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,eAAO,MAAM,cAAc,IAAI,CAAC;AAChC,eAAO,MAAM,WAAW,WAAW,CAAC;AACpC,eAAO,MAAM,YAAY,iBAAiB,CAAC;AAE3C,6GAA6G;AAC7G,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B,0CAA0C;AAC1C,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAE5C,qGAAqG;AACrG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;CAC1B;AAED,wDAAwD;AACxD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,8FAA8F;AAC9F,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAA;CAAE,GACvB;IACE,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;IACnB,iFAAiF;IACjF,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,CAAC;CACzC,CAAC;AAEN,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,cAAc,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,+FAA+F;IAC/F,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;CAC1D;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjD,0GAA0G;AAC1G,eAAO,MAAM,sBAAsB,GAAI,GAAG,aAAa,KAAG,MACvB,CAAC;AAIpC,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AAExD,2DAA2D;AAC3D,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,CAAC,EAAE,aAAa,EAChB,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GACnC,SAAS,MAAM,EAAE,CASnB;AAED,yEAAyE;AACzE,eAAO,MAAM,eAAe,GAAI,IAAI,SAAS,MAAM,EAAE,KAAG,MACL,CAAC;AAEpD;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,IAAI,CAMf"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export const SOURCES_SCHEMA = 1;
|
|
2
|
+
export const SOURCES_DIR = "_build";
|
|
3
|
+
export const SOURCES_FILE = "sources.json";
|
|
4
|
+
/** The job name every file a build writes carries (`paper.aux`, `paper.fls`): the build names its job so. */
|
|
5
|
+
export const JOBNAME = "paper";
|
|
6
|
+
/** The record as the file holds it: two-space JSON and a final newline, so a diff of two builds reads. */
|
|
7
|
+
export const serializeSourcesRecord = (r) => `${JSON.stringify(r, null, 2)}\n`;
|
|
8
|
+
/**
|
|
9
|
+
* The files whose bytes now differ from the record's: edited, deleted, or present where the record saw
|
|
10
|
+
* none. `now` answers for one path with the digest of its bytes, or null when there is no such file.
|
|
11
|
+
* Empty when the record is current.
|
|
12
|
+
*/
|
|
13
|
+
export function changesSince(r, now) {
|
|
14
|
+
return Object.entries(r.sha256).flatMap(([path, recorded]) => {
|
|
15
|
+
const current = now(path);
|
|
16
|
+
if (current === recorded)
|
|
17
|
+
return [];
|
|
18
|
+
if (current === null)
|
|
19
|
+
return [{ path, change: "deleted" }];
|
|
20
|
+
return [{ path, change: recorded === null ? "added" : "edited" }];
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** `paper.tex edited, sections/a.tex deleted` — what a finding names. */
|
|
24
|
+
export const describeChanges = (cs) => cs.map((c) => `${c.path} ${c.change}`).join(", ");
|
|
25
|
+
/**
|
|
26
|
+
* The name among `names` that `name` stands for: `name` itself, else the one name equal to it ignoring
|
|
27
|
+
* case — null when there is none, or several. TeX opens a file by the name the source gives it; on a
|
|
28
|
+
* file system that ignores case that is the source's spelling, on one that does not TeX retries
|
|
29
|
+
* without case, and the record holds the disk's spelling either way. A name and the record's spelling
|
|
30
|
+
* of it are matched by this, once, wherever one is looked up in the other.
|
|
31
|
+
*/
|
|
32
|
+
export function spelledIn(names, name) {
|
|
33
|
+
if (names.includes(name))
|
|
34
|
+
return name;
|
|
35
|
+
const [only, ...more] = names.filter((n) => n.toLowerCase() === name.toLowerCase());
|
|
36
|
+
return only !== undefined && more.length === 0 ? only : null;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=sources-record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sources-record.js","sourceRoot":"","sources":["../../src/domain/sources-record.ts"],"names":[],"mappings":"AA8BA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAChC,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC;AACpC,MAAM,CAAC,MAAM,YAAY,GAAG,cAAc,CAAC;AAE3C,6GAA6G;AAC7G,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AA+C/B,0GAA0G;AAC1G,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAgB,EAAU,EAAE,CACjE,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;AAYpC;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,CAAgB,EAChB,GAAoC;IAEpC,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CACrC,CAAC,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAqB,EAAE;QACtC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,OAAO,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACpC,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAC3D,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC,CACF,CAAC;AACJ,CAAC;AAED,yEAAyE;AACzE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAqB,EAAU,EAAE,CAC/D,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEpD;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CACvB,KAAwB,EACxB,IAAY;IAEZ,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAClC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAC9C,CAAC;IACF,OAAO,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { RecordedInput } from "./sources-record.ts";
|
|
2
|
+
/** One line of an `.fls`: TeX opened a file to read it, or to write it. */
|
|
3
|
+
export interface FlsLine {
|
|
4
|
+
readonly op: "INPUT" | "OUTPUT";
|
|
5
|
+
/** As TeX named the file: `./a.tex` and `a.tex` for one file, an absolute path for the TeX tree's. */
|
|
6
|
+
readonly path: string;
|
|
7
|
+
}
|
|
8
|
+
/** A pdflatex `-recorder` file: where it ran, and every file it opened, in order. */
|
|
9
|
+
export interface Fls {
|
|
10
|
+
/** The directory pdflatex ran in, or null when the file names none. */
|
|
11
|
+
readonly pwd: string | null;
|
|
12
|
+
readonly lines: readonly FlsLine[];
|
|
13
|
+
}
|
|
14
|
+
export interface RunFiles {
|
|
15
|
+
readonly inputs: readonly RecordedInput[];
|
|
16
|
+
readonly written: readonly string[];
|
|
17
|
+
}
|
|
18
|
+
export interface RunOptions {
|
|
19
|
+
/** The job name: `<jobname>.aux` is the file whose opening marks `\begin{document}`. */
|
|
20
|
+
readonly jobname: string;
|
|
21
|
+
/** Files other programs wrote from TeX's own output, relative to the paper directory (`paper.bbl`). */
|
|
22
|
+
readonly generated: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
export declare function filesOfRun(passes: readonly Fls[], options: RunOptions): RunFiles;
|
|
25
|
+
//# sourceMappingURL=tex-run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tex-run.d.ts","sourceRoot":"","sources":["../../src/domain/tex-run.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,2EAA2E;AAC3E,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,QAAQ,CAAC;IAChC,sGAAsG;IACtG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,qFAAqF;AACrF,MAAM,WAAW,GAAG;IAClB,uEAAuE;IACvE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC;AAgCD,MAAM,WAAW,UAAU;IACzB,wFAAwF;IACxF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,uGAAuG;IACvG,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AA8BD,wBAAgB,UAAU,CACxB,MAAM,EAAE,SAAS,GAAG,EAAE,EACtB,OAAO,EAAE,UAAU,GAClB,QAAQ,CAyBV"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHICH FILES A BUILD'S TeX PASSES READ — decided from the lines of each pass's `.fls` (pdflatex
|
|
3
|
+
* `-recorder`), not from any TeX source (docs/design/paper-sources.md §1).
|
|
4
|
+
*
|
|
5
|
+
* inputs the files of the paper directory the LAST pass read, in the order it first read them,
|
|
6
|
+
* each a `preamble` or `body` file: before or after TeX opened `<jobname>.aux` for writing,
|
|
7
|
+
* which `\begin{document}` does (measured). The main file, read first, is `body`.
|
|
8
|
+
* written the `.bib` and `.tex` files ANY pass wrote — a `filecontents` block's.
|
|
9
|
+
*
|
|
10
|
+
* 🔴 WHY THE LAST PASS FOR INPUTS AND EVERY PASS FOR WHAT WAS WRITTEN. A block without `[overwrite]`
|
|
11
|
+
* writes its file on the first pass only; the later passes find it there and read it (measured on TeX
|
|
12
|
+
* Live 2026: pass 1 `OUTPUT refs.bib`, passes 2 and 3 `INPUT refs.bib`, no OUTPUT). The last pass alone
|
|
13
|
+
* would list TeX's own copy of a `.bib` as a file of the paper. And the first pass reads no `.aux`,
|
|
14
|
+
* `.toc` or `.out` yet, so only a later pass lists what the paper reads and the passes after it write.
|
|
15
|
+
*
|
|
16
|
+
* 🔴 A FILE TeX WROTE IS AN INPUT ONLY WHEN IT IS TeX SOURCE OF THE PAPER: a `.tex`. A block that
|
|
17
|
+
* writes `body.tex` the body `\input`s puts that text in the PDF (measured: pass 1 `OUTPUT body.tex`
|
|
18
|
+
* then `INPUT ./body.tex` after `\begin{document}`; the later passes read it again), so it is an
|
|
19
|
+
* input like any other: hashed, spliced where its include stands. Every other file a pass wrote is
|
|
20
|
+
* TeX's bookkeeping or a database — its `.aux`, `.out` and `.toc`, a block's `.bib` — and is no input.
|
|
21
|
+
* A file another program wrote from TeX's output (`generated`: the `.bbl`, when bibtex ran) is none
|
|
22
|
+
* either.
|
|
23
|
+
*/
|
|
24
|
+
import { isAbsolute, posix } from "node:path";
|
|
25
|
+
/**
|
|
26
|
+
* `path` as TeX named it → relative to the paper directory with forward slashes, or null when the file
|
|
27
|
+
* is not in it: the TeX tree's, a file of a sibling directory, an absolute path outside `pwd`.
|
|
28
|
+
*/
|
|
29
|
+
function inPaperDir(path, pwd) {
|
|
30
|
+
const rel = isAbsolute(path)
|
|
31
|
+
? pwd === null
|
|
32
|
+
? null
|
|
33
|
+
: posix.relative(pwd, path)
|
|
34
|
+
: posix.normalize(path);
|
|
35
|
+
// `..` or `../x`: a file of a sibling directory. (`..x` is a file of this one.)
|
|
36
|
+
return rel === null || rel.split("/")[0] === ".." ? null : rel;
|
|
37
|
+
}
|
|
38
|
+
const distinct = (xs) => [...new Set(xs)];
|
|
39
|
+
/** A file TeX writes that the record names: TeX source of the paper (`.tex`) or a database (`.bib`). */
|
|
40
|
+
const isTexSource = (path) => posix.extname(path) === ".tex";
|
|
41
|
+
const isRecordedWrite = (path) => isTexSource(path) || posix.extname(path) === ".bib";
|
|
42
|
+
/** The files of the paper directory a pass opened, with the op, in order. */
|
|
43
|
+
const opened = (pass) => pass.lines.flatMap((l) => {
|
|
44
|
+
const rel = inPaperDir(l.path, pass.pwd);
|
|
45
|
+
return rel === null ? [] : [{ ...l, rel }];
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* The reads of the last pass: INPUT lines of files nothing wrote, or that a pass wrote as TeX source,
|
|
49
|
+
* each with its place against the line that opens `<jobname>.aux` — `\begin{document}`. No such line
|
|
50
|
+
* (the run stopped first): none is after it.
|
|
51
|
+
*/
|
|
52
|
+
function readsOf(last, outputs, { jobname, generated }) {
|
|
53
|
+
const boundary = last.findIndex((l) => l.op === "OUTPUT" && l.rel === `${jobname}.aux`);
|
|
54
|
+
return last.flatMap((l, i) => l.op === "INPUT" &&
|
|
55
|
+
(!outputs.has(l.rel) || isTexSource(l.rel)) &&
|
|
56
|
+
!generated.includes(l.rel)
|
|
57
|
+
? [{ path: l.rel, afterBegin: boundary >= 0 && i > boundary }]
|
|
58
|
+
: []);
|
|
59
|
+
}
|
|
60
|
+
export function filesOfRun(passes, options) {
|
|
61
|
+
const everyPass = passes.flatMap(opened);
|
|
62
|
+
const wrote = (l) => l.op === "OUTPUT";
|
|
63
|
+
const outputs = new Set(everyPass.filter(wrote).map((l) => l.rel));
|
|
64
|
+
const last = passes.at(-1);
|
|
65
|
+
const reads = readsOf(last === undefined ? [] : opened(last), outputs, options);
|
|
66
|
+
// The main file holds `\begin{document}` itself, so it is body wherever TeX opened it.
|
|
67
|
+
const body = (path) => path === reads[0]?.path ||
|
|
68
|
+
reads.some((r) => r.path === path && r.afterBegin);
|
|
69
|
+
return {
|
|
70
|
+
inputs: distinct(reads.map((r) => r.path)).map((path) => ({
|
|
71
|
+
path,
|
|
72
|
+
role: body(path) ? "body" : "preamble",
|
|
73
|
+
})),
|
|
74
|
+
written: distinct(everyPass
|
|
75
|
+
.filter((l) => wrote(l) && isRecordedWrite(l.rel))
|
|
76
|
+
.map((l) => l.rel)),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=tex-run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tex-run.js","sourceRoot":"","sources":["../../src/domain/tex-run.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"latex-language.d.ts","sourceRoot":"","sources":["../../eslint-rules/latex-language.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"latex-language.d.ts","sourceRoot":"","sources":["../../eslint-rules/latex-language.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AN ESLint LANGUAGE FOR `.tex` — so that
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* AN ESLint LANGUAGE FOR `.tex` — so that prose rules read a paper's LaTeX source. The spike it
|
|
3
|
+
* grew out of lives in the source corpus as a coverage measurement plus an executable prototype
|
|
4
|
+
* kept as history.
|
|
5
5
|
*
|
|
6
6
|
* ── CONSTRUCTION: two legs ──────────────────────────────────────────────────
|
|
7
7
|
* 1. AST — a flat mdast-like root (heading / code / html / strong) with REAL positions taken
|
|
@@ -9,9 +9,8 @@
|
|
|
9
9
|
* 2. TEXT — a projection of `.tex` into a markdown-like view THAT PRESERVES LENGTHS AND
|
|
10
10
|
* OFFSETS: comments, the preamble, math, service macros and code environments are blanked
|
|
11
11
|
* with spaces; `\section{X}` projects to `## X `, `\texttt{X}` to `` `X` ``.
|
|
12
|
-
* The point: a rule
|
|
13
|
-
*
|
|
14
|
-
* rewritten for LaTeX.
|
|
12
|
+
* The point: a rule reads a plain, heading-marked text and KNOWS NOTHING about LaTeX, while
|
|
13
|
+
* the position of a finding points into the real `.tex`.
|
|
15
14
|
*
|
|
16
15
|
* ── HEADING SYNTHESIS: not decoration, but the repair of seven silent rules ──
|
|
17
16
|
* Measured 2026-08-26 across three real papers: NONE of them has a `Limitations` /
|
|
@@ -47,10 +46,8 @@
|
|
|
47
46
|
* `95 of it, costing 5 and A B`. This matters: a word splitter counts `%` as part of
|
|
48
47
|
* a word, and a plain-language rule counts NUMBERS — so the percent sign detaches from
|
|
49
48
|
* its number. Not fixed: three exceptions would have to be written and pinned.
|
|
50
|
-
* 3.
|
|
51
|
-
*
|
|
52
|
-
* blanking and 1208 after — a 2.5% discrepancy. The discrepancy is ACCEPTED deliberately;
|
|
53
|
-
* the thresholds were not recalibrated.
|
|
49
|
+
* 3. MACRO BLANKING SHIFTS WORD COUNTS. The same place gave 1239 words before macro blanking
|
|
50
|
+
* and 1208 after — a 2.5% discrepancy, ACCEPTED deliberately.
|
|
54
51
|
* 4. ONE FILE AT A TIME. `\input` / `\include` are in OPAQUE: the projection of `paper.tex`
|
|
55
52
|
* does not hold what they pull in. `paperlint lint` hands ESLint each file the paper includes
|
|
56
53
|
* from its body as a file of its own (src/paper-includes.ts), and a file with no `document`
|
|
@@ -400,9 +397,9 @@ export function texToMdast(src, { parse = (s) => getParser().parse(s), } = {}) {
|
|
|
400
397
|
// 🔴 AND SYMMETRICALLY ON THE LEFT (found by a run on 2026-08-27, not by reading). A
|
|
401
398
|
// comment that follows a line of text directly, rather than a blank line, comes back from
|
|
402
399
|
// unified-latex with a position starting at the PREVIOUS newline instead of at `%`.
|
|
403
|
-
// Consumers recognise a comment by its first character (
|
|
404
|
-
//
|
|
405
|
-
//
|
|
400
|
+
// Consumers recognise a comment by its first character (`%`), so such a node was not a
|
|
401
|
+
// comment to them: notes above bold appendix lead-ins never bound, and the block-note /
|
|
402
|
+
// block-verdict rules could NEVER fire. Measured:
|
|
406
403
|
// 2 out of 2 blocks were reported as "no note AT ALL" while the notes were right there.
|
|
407
404
|
let cs = pos.start.offset;
|
|
408
405
|
while (cs < ce && src[cs] !== "%")
|