paperlint 4.0.0 → 4.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.
Files changed (236) hide show
  1. package/.github/workflows/ci.yml +16 -23
  2. package/CLAUDE.md +55 -11
  3. package/CONTRIBUTING.md +30 -7
  4. package/README.md +11 -8
  5. package/dist/adapters/banal/invocation.d.ts +1 -1
  6. package/dist/adapters/latex/document-class.d.ts +23 -0
  7. package/dist/adapters/latex/document-class.d.ts.map +1 -0
  8. package/dist/adapters/latex/document-class.js +110 -0
  9. package/dist/adapters/latex/document-class.js.map +1 -0
  10. package/dist/adapters/latex/hidden.d.ts +16 -0
  11. package/dist/adapters/latex/hidden.d.ts.map +1 -0
  12. package/dist/adapters/latex/hidden.js +49 -0
  13. package/dist/adapters/latex/hidden.js.map +1 -0
  14. package/dist/adapters/latex/includes.d.ts +12 -0
  15. package/dist/adapters/latex/includes.d.ts.map +1 -0
  16. package/dist/adapters/latex/includes.js +42 -0
  17. package/dist/adapters/latex/includes.js.map +1 -0
  18. package/dist/adapters/latex/index.d.ts +33 -0
  19. package/dist/adapters/latex/index.d.ts.map +1 -0
  20. package/dist/adapters/latex/index.js +25 -0
  21. package/dist/adapters/latex/index.js.map +1 -0
  22. package/dist/adapters/latex/nodes.d.ts +58 -0
  23. package/dist/adapters/latex/nodes.d.ts.map +1 -0
  24. package/dist/adapters/latex/nodes.js +97 -0
  25. package/dist/adapters/latex/nodes.js.map +1 -0
  26. package/dist/adapters/latex/outline.d.ts +10 -0
  27. package/dist/adapters/latex/outline.d.ts.map +1 -0
  28. package/dist/adapters/latex/outline.js +39 -0
  29. package/dist/adapters/latex/outline.js.map +1 -0
  30. package/dist/adapters/latex/parse.d.ts +42 -0
  31. package/dist/adapters/latex/parse.d.ts.map +1 -0
  32. package/dist/adapters/latex/parse.js +95 -0
  33. package/dist/adapters/latex/parse.js.map +1 -0
  34. package/dist/adapters/latex/prose.d.ts +8 -0
  35. package/dist/adapters/latex/prose.d.ts.map +1 -0
  36. package/dist/adapters/latex/prose.js +353 -0
  37. package/dist/adapters/latex/prose.js.map +1 -0
  38. package/dist/adapters/latex/rendered.d.ts +10 -0
  39. package/dist/adapters/latex/rendered.d.ts.map +1 -0
  40. package/dist/adapters/latex/rendered.js +39 -0
  41. package/dist/adapters/latex/rendered.js.map +1 -0
  42. package/dist/adapters/pdfjs/fill.d.ts.map +1 -1
  43. package/dist/adapters/pdfjs/fill.js +12 -12
  44. package/dist/adapters/pdfjs/fill.js.map +1 -1
  45. package/dist/build.js +4 -4
  46. package/dist/build.js.map +1 -1
  47. package/dist/claim-provenance.d.ts +34 -0
  48. package/dist/claim-provenance.d.ts.map +1 -0
  49. package/dist/claim-provenance.js +146 -0
  50. package/dist/claim-provenance.js.map +1 -0
  51. package/dist/cli.d.ts.map +1 -1
  52. package/dist/cli.js +49 -5
  53. package/dist/cli.js.map +1 -1
  54. package/dist/domain/paper-source.d.ts +58 -0
  55. package/dist/domain/paper-source.d.ts.map +1 -0
  56. package/dist/domain/paper-source.js +109 -0
  57. package/dist/domain/paper-source.js.map +1 -0
  58. package/dist/domain/sentences.d.ts +26 -0
  59. package/dist/domain/sentences.d.ts.map +1 -0
  60. package/dist/domain/sentences.js +48 -0
  61. package/dist/domain/sentences.js.map +1 -0
  62. package/dist/domain/tex-document.d.ts +119 -0
  63. package/dist/domain/tex-document.d.ts.map +1 -0
  64. package/dist/domain/tex-document.js +43 -0
  65. package/dist/domain/tex-document.js.map +1 -0
  66. package/dist/eslint-rules/paper-typography.d.ts +7 -0
  67. package/dist/eslint-rules/paper-typography.d.ts.map +1 -1
  68. package/dist/eslint-rules/paper-typography.js +53 -1
  69. package/dist/eslint-rules/paper-typography.js.map +1 -1
  70. package/dist/facts-file.d.ts.map +1 -1
  71. package/dist/facts-file.js +2 -2
  72. package/dist/facts-file.js.map +1 -1
  73. package/dist/new-paper.d.ts +5 -0
  74. package/dist/new-paper.d.ts.map +1 -1
  75. package/dist/new-paper.js +3 -0
  76. package/dist/new-paper.js.map +1 -1
  77. package/dist/package-dirs.d.ts +5 -0
  78. package/dist/package-dirs.d.ts.map +1 -0
  79. package/dist/package-dirs.js +14 -0
  80. package/dist/package-dirs.js.map +1 -0
  81. package/dist/ports/latex.d.ts +35 -0
  82. package/dist/ports/latex.d.ts.map +1 -0
  83. package/dist/ports/latex.js +2 -0
  84. package/dist/ports/latex.js.map +1 -0
  85. package/dist/presets.d.ts +15 -2
  86. package/dist/presets.d.ts.map +1 -1
  87. package/dist/presets.js +19 -6
  88. package/dist/presets.js.map +1 -1
  89. package/dist/register.d.ts +40 -0
  90. package/dist/register.d.ts.map +1 -0
  91. package/dist/register.js +134 -0
  92. package/dist/register.js.map +1 -0
  93. package/dist/tex-paper.d.ts +19 -0
  94. package/dist/tex-paper.d.ts.map +1 -0
  95. package/dist/tex-paper.js +105 -0
  96. package/dist/tex-paper.js.map +1 -0
  97. package/dist/tex-requirements.d.ts +11 -0
  98. package/dist/tex-requirements.d.ts.map +1 -1
  99. package/dist/tex-requirements.js +14 -8
  100. package/dist/tex-requirements.js.map +1 -1
  101. package/dist/tex-venue-rules.d.ts +88 -0
  102. package/dist/tex-venue-rules.d.ts.map +1 -0
  103. package/dist/tex-venue-rules.js +268 -0
  104. package/dist/tex-venue-rules.js.map +1 -0
  105. package/dist/venue-rules.d.ts +1 -1
  106. package/dist/venue-rules.d.ts.map +1 -1
  107. package/docs/configuration.md +3 -2
  108. package/docs/e2e.md +69 -40
  109. package/docs/install.md +1 -1
  110. package/docs/prior-art/README.md +1 -1
  111. package/docs/prior-art/package-location.md +5 -5
  112. package/docs/prior-art/repro/README.md +1 -1
  113. package/docs/prior-art/test-tooling.md +21 -10
  114. package/docs/rules/tex/claim-provenance.md +83 -0
  115. package/docs/rules/tex/missing-input.md +58 -0
  116. package/docs/rules/tex/register.md +77 -0
  117. package/docs/rules/tex/required-section.md +75 -0
  118. package/docs/rules/tex/template.md +74 -0
  119. package/docs/rules/tex/venue-leftover.md +73 -0
  120. package/docs/rules.md +73 -48
  121. package/docs/testing.md +17 -4
  122. package/docs/texlive-install-decision.md +1 -1
  123. package/docs/toolchain.md +2 -2
  124. package/eslint-rules/paper-typography.test.mjs +48 -1
  125. package/eslint-rules/paper-typography.ts +72 -1
  126. package/eslint.config.mjs +156 -15
  127. package/fixtures/build-e2e/acmart/expect.json +26 -0
  128. package/fixtures/build-e2e/aidc/PIPELINE-STATUS.md +3 -0
  129. package/fixtures/build-e2e/aidc/expect.json +14 -0
  130. package/fixtures/build-e2e/aidc/paper.tex +46 -0
  131. package/fixtures/build-e2e/aidc/paperlint.json +1 -0
  132. package/fixtures/build-e2e/broken/expect.json +11 -0
  133. package/fixtures/build-e2e/cite/expect.json +27 -0
  134. package/fixtures/build-e2e/empty/expect.json +12 -0
  135. package/fixtures/build-e2e/fallback/expect.json +53 -0
  136. package/fixtures/build-e2e/guards/expect.json +6 -0
  137. package/fixtures/build-e2e/no-source/expect.json +10 -0
  138. package/fixtures/build-e2e/unbalanced/expect.json +60 -0
  139. package/fixtures/pdf-facts/README.md +1 -1
  140. package/fixtures/real-markdown-paper/baseline.ts +8 -7
  141. package/fixtures/render-paper/build-clean.sh +3 -5
  142. package/package.json +14 -2
  143. package/{skills/submit-paper/references/venues → presets}/acm-sigconf.jsonc +4 -1
  144. package/{skills/submit-paper/references/venues → presets}/agenticdev.jsonc +4 -0
  145. package/presets/aidc.jsonc +73 -0
  146. package/{skills/submit-paper/references/venues → presets}/aisec.jsonc +4 -0
  147. package/presets/ieee-conference.jsonc +66 -0
  148. package/{skills/submit-paper/references/venues → presets}/realm.jsonc +8 -1
  149. package/{skills/submit-paper/references/venues → presets/tex}/paper-guards.tex +1 -1
  150. package/{skills/submit-paper/references/venues → presets}/venue-profile.schema.json +30 -2
  151. package/scripts/check.harness.ts +64 -10
  152. package/scripts/check.test.ts +60 -13
  153. package/scripts/check.ts +83 -30
  154. package/scripts/test.test.ts +1 -1
  155. package/scripts/test.ts +1 -1
  156. package/skills/cold-read-diff/SKILL.md +31 -10
  157. package/skills/cold-read-diff/SKILL.md.spec.ts +30 -9
  158. package/skills/draft-paper/SKILL.md +2 -2
  159. package/skills/draft-paper/SKILL.md.spec.ts +1 -1
  160. package/skills/grade-paper-writing/SKILL.md +109 -44
  161. package/skills/grade-paper-writing/SKILL.md.spec.ts +108 -43
  162. package/skills/harden-paper/SKILL.md +35 -36
  163. package/skills/harden-paper/SKILL.md.spec.ts +34 -35
  164. package/skills/paper-adversarial-review/SKILL.md +2 -2
  165. package/skills/paper-adversarial-review/SKILL.md.spec.ts +1 -1
  166. package/skills/paper-pipeline/PIPELINE-MAP.md +2 -2
  167. package/skills/paper-pipeline/SKILL.md +4 -4
  168. package/skills/paper-pipeline/SKILL.md.spec.ts +3 -3
  169. package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +6 -6
  170. package/skills/paper-pipeline/references/writing-craft.md +53 -18
  171. package/skills/paper-pipeline/scripts/consumer.d.mts +0 -2
  172. package/skills/paper-pipeline/scripts/consumer.mjs +1 -15
  173. package/skills/pc-panel-review/SKILL.md +36 -11
  174. package/skills/pc-panel-review/SKILL.md.spec.ts +35 -10
  175. package/skills/render-paper/SKILL.md +2 -2
  176. package/skills/render-paper/SKILL.md.spec.ts +1 -1
  177. package/skills/render-paper/check-render.sh +16 -63
  178. package/skills/render-paper/render-paper.harness.mjs +17 -59
  179. package/src/adapters/banal/index.test.ts +1 -1
  180. package/src/adapters/banal/invocation.ts +1 -1
  181. package/src/adapters/banal/output.test.ts +1 -1
  182. package/src/adapters/banal/run.test.ts +1 -1
  183. package/src/adapters/banal/xml.test.ts +1 -1
  184. package/src/adapters/latex/document-class.ts +155 -0
  185. package/src/adapters/latex/hidden.ts +70 -0
  186. package/src/adapters/latex/includes.ts +66 -0
  187. package/src/adapters/latex/index.test.ts +535 -0
  188. package/src/adapters/latex/index.ts +65 -0
  189. package/src/adapters/latex/nodes.ts +150 -0
  190. package/src/adapters/latex/outline.ts +64 -0
  191. package/src/adapters/latex/parse.ts +137 -0
  192. package/src/adapters/latex/prose.ts +484 -0
  193. package/src/adapters/latex/rendered.ts +59 -0
  194. package/src/adapters/pdfjs/fill.test.ts +1 -1
  195. package/src/adapters/pdfjs/fill.ts +18 -10
  196. package/src/build.harness.mjs +5 -7
  197. package/src/build.ts +4 -4
  198. package/src/claim-provenance.test.ts +352 -0
  199. package/src/claim-provenance.ts +217 -0
  200. package/src/cli.harness.mjs +1 -1
  201. package/src/cli.test.ts +2 -8
  202. package/src/cli.ts +53 -8
  203. package/src/domain/paper-source.test.ts +156 -0
  204. package/src/domain/paper-source.ts +233 -0
  205. package/src/domain/sentences.ts +67 -0
  206. package/src/domain/tex-document.test.ts +80 -0
  207. package/src/domain/tex-document.ts +143 -0
  208. package/src/engine.harness.mjs +1 -1
  209. package/src/facts-file.test.ts +4 -7
  210. package/src/facts-file.ts +2 -2
  211. package/src/latex-loop.harness.ts +1 -1
  212. package/src/new-paper.test.ts +28 -3
  213. package/src/new-paper.ts +8 -0
  214. package/src/package-dirs.ts +17 -0
  215. package/src/paper-settings-commands.test.ts +6 -1
  216. package/src/ports/latex.ts +42 -0
  217. package/src/presets.test.ts +65 -4
  218. package/src/presets.ts +38 -15
  219. package/src/register.test.ts +165 -0
  220. package/src/register.ts +177 -0
  221. package/src/rule-cases.test.ts +524 -0
  222. package/src/rule-docs.test.ts +159 -0
  223. package/src/tex-paper.test.ts +131 -0
  224. package/src/tex-paper.ts +152 -0
  225. package/src/tex-requirements.harness.ts +13 -23
  226. package/src/tex-requirements.ts +35 -8
  227. package/src/tex-venue-rules.test.ts +741 -0
  228. package/src/tex-venue-rules.ts +461 -0
  229. package/src/toolchain.harness.mjs +1 -1
  230. package/src/venue-rules.test.ts +96 -4
  231. package/src/venue-rules.ts +1 -1
  232. package/templates/paper/paper.tex +2 -1
  233. package/skills/harden-paper/fixtures/uncited-assertions-sample.md +0 -43
  234. package/skills/harden-paper/fixtures/uncited-assertions-sample.tex +0 -77
  235. /package/{skills/submit-paper/references/venues → presets/tex}/agenticdev.tex +0 -0
  236. /package/{skills/submit-paper/references/venues → presets}/tex-base.jsonc +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/latex/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAYxD,OAAO,EACL,eAAe,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,QAAQ,EACR,OAAO,EACP,UAAU,EACV,SAAS,EACT,QAAQ,EACR,OAAO,EACP,MAAM,GACP,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,mFAAmF;AACnF,eAAO,MAAM,WAAW,EAAE,WASzB,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { documentClassOf, parseTemplate, replaceDocumentClass, } from "./document-class.js";
2
+ import { documentBodyOf, includesOf } from "./includes.js";
3
+ import { outlineOf } from "./outline.js";
4
+ import { parseLatex } from "./parse.js";
5
+ import { bodyProse } from "./prose.js";
6
+ import { renderedRuns } from "./rendered.js";
7
+ export { documentClassOf, parseTemplate, replaceDocumentClass, } from "./document-class.js";
8
+ export { collapse, inPlace, macroPlace, mandatory, optional, placeOf, textOf, } from "./nodes.js";
9
+ export { documentBodyOf, includesOf } from "./includes.js";
10
+ export { outlineOf } from "./outline.js";
11
+ export { parseLatex } from "./parse.js";
12
+ export { bodyProse } from "./prose.js";
13
+ export { renderedRuns } from "./rendered.js";
14
+ /** The `LatexReader` port over unified-latex: each call parses its source once. */
15
+ export const latexReader = {
16
+ documentClass: (src) => documentClassOf(parseLatex(src)),
17
+ outline: (src) => outlineOf(parseLatex(src)),
18
+ renderedRuns: (src) => renderedRuns(parseLatex(src)),
19
+ bodyProse: (src) => bodyProse(parseLatex(src)),
20
+ includes: (src) => includesOf(parseLatex(src)),
21
+ documentBody: (src) => documentBodyOf(parseLatex(src)),
22
+ template: parseTemplate,
23
+ withDocumentClass: (src, want) => replaceDocumentClass(parseLatex(src), want),
24
+ };
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/latex/index.ts"],"names":[],"mappings":"AAuBA,OAAO,EACL,eAAe,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,OAAO,EACL,eAAe,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,QAAQ,EACR,OAAO,EACP,UAAU,EACV,SAAS,EACT,QAAQ,EACR,OAAO,EACP,MAAM,GACP,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAkB,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C,mFAAmF;AACnF,MAAM,CAAC,MAAM,WAAW,GAAgB;IACtC,aAAa,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACxD,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC5C,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACpD,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC9C,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IAC9C,YAAY,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACtD,QAAQ,EAAE,aAAa;IACvB,iBAAiB,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;CAC9E,CAAC"}
@@ -0,0 +1,58 @@
1
+ /** What the three readers share about unified-latex nodes: places, text, and the walk. */
2
+ import type * as Ast from "@unified-latex/unified-latex-types";
3
+ import type { Place, Span } from "../../domain/tex-document.ts";
4
+ export { collapse } from "../../domain/tex-document.ts";
5
+ /** unified-latex's node types, read-only: nothing here writes to a tree. */
6
+ export type Node = Readonly<Ast.Node>;
7
+ export type Macro = Readonly<Ast.Macro>;
8
+ export type Argument = Readonly<Ast.Argument>;
9
+ /** Anything the parser may have given a position: offsets of its first and past its last character. */
10
+ interface Positioned {
11
+ readonly position?: {
12
+ readonly start: {
13
+ readonly offset: number;
14
+ };
15
+ readonly end: {
16
+ readonly offset: number;
17
+ };
18
+ };
19
+ }
20
+ /** Where a node stands, or that it has no position. */
21
+ export declare const placeOf: (n: Positioned) => Place;
22
+ /** What `f` makes of a place's span, or nothing for a node the parser gave no position. */
23
+ export declare const inPlace: <T>(p: Place, f: (span: Span) => readonly T[]) => readonly T[];
24
+ /** A macro's arguments, in order: none when the parser attached none. */
25
+ export declare const argumentsOf: (m: Macro) => readonly Argument[];
26
+ /** The first mandatory (`{…}`) and optional (`[…]`) arguments' contents, and the last mandatory one's. */
27
+ export declare const mandatory: (m: Macro) => readonly Argument[];
28
+ export declare const optional: (m: Macro) => Argument | undefined;
29
+ /** What a string node reads as: itself, except a tie (`~`), which is a space the reader sees. */
30
+ export declare const stringText: (content: string) => string;
31
+ /**
32
+ * The text of a node list with markup dropped: strings, spaces, what groups hold, and the argument a
33
+ * formatting macro typesets — its last mandatory one (`\textbf{Usage}`, `\textcolor{red}{Usage}`,
34
+ * `\href{url}{Usage}` → `Usage`) unless `SHOWN_ARGUMENT` says otherwise. A key macro's arguments
35
+ * (`\label{…}`, `\cite{…}`) are not text.
36
+ */
37
+ export declare const textOf: (nodes: readonly Node[] | undefined) => string;
38
+ /**
39
+ * A macro's place with its arguments: from its name to past the closing mark of the last argument
40
+ * that holds text. unified-latex positions the name and the arguments' contents, never the
41
+ * arguments themselves, so an empty trailing argument is not covered.
42
+ */
43
+ export declare function macroPlace(m: Macro): Place;
44
+ /** What visit reaches: a node, an argument, or a node list (a content array, an argument list). */
45
+ export type Visited = Readonly<Ast.Ast> | readonly (Node | Argument)[];
46
+ /**
47
+ * Everything visit reaches under `tree`, in document order, node lists included; `skip` prunes what
48
+ * it is given (a node or an argument, with the node that holds it) and everything under it. visit
49
+ * reports through a callback and returns nothing, so the one collection point of this adapter is here.
50
+ */
51
+ export declare function visited(tree: Ast.Ast, skip: (v: Visited, parent: Visited | undefined) => boolean): readonly Visited[];
52
+ /** A node list visit reached. `Array.isArray` alone does not narrow a readonly array. */
53
+ export declare const isList: (v: Visited) => v is readonly (Node | Argument)[];
54
+ /** A macro's argument, as visit reports it. */
55
+ export declare const isArgument: (v: Visited) => v is Argument;
56
+ /** A node, as opposed to a node list or an argument (which visit also reports). */
57
+ export declare const isNode: (v: Visited) => v is Node;
58
+ //# sourceMappingURL=nodes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../../../src/adapters/latex/nodes.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,OAAO,KAAK,KAAK,GAAG,MAAM,oCAAoC,CAAC;AAE/D,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,8BAA8B,CAAC;AAGhE,OAAO,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAExD,4EAA4E;AAC5E,MAAM,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACtC,MAAM,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACxC,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAE9C,uGAAuG;AACvG,UAAU,UAAU;IAClB,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAClB,QAAQ,CAAC,KAAK,EAAE;YAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC5C,QAAQ,CAAC,GAAG,EAAE;YAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3C,CAAC;CACH;AAED,uDAAuD;AACvD,eAAO,MAAM,OAAO,GAAI,GAAG,UAAU,KAAG,KAMjC,CAAC;AAER,2FAA2F;AAC3F,eAAO,MAAM,OAAO,GAAI,CAAC,EACvB,GAAG,KAAK,EACR,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,SAAS,CAAC,EAAE,KAC9B,SAAS,CAAC,EAAwC,CAAC;AAEtD,yEAAyE;AACzE,eAAO,MAAM,WAAW,GAAI,GAAG,KAAK,KAAG,SAAS,QAAQ,EAAkB,CAAC;AAE3E,0GAA0G;AAC1G,eAAO,MAAM,SAAS,GAAI,GAAG,KAAK,KAAG,SAAS,QAAQ,EACJ,CAAC;AACnD,eAAO,MAAM,QAAQ,GAAI,GAAG,KAAK,KAAG,QAAQ,GAAG,SACC,CAAC;AAEjD,iGAAiG;AACjG,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,KAAG,MACZ,CAAC;AA+BlC;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,OAAO,SAAS,IAAI,EAAE,GAAG,SAAS,KAAG,MAU/C,CAAC;AAEd;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,CAS1C;AAED,mGAAmG;AACnG,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC;AAEvE;;;;GAIG;AACH,wBAAgB,OAAO,CAErB,IAAI,EAAE,GAAG,CAAC,GAAG,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,SAAS,KAAK,OAAO,GACzD,SAAS,OAAO,EAAE,CAapB;AAED,yFAAyF;AACzF,eAAO,MAAM,MAAM,GAAI,GAAG,OAAO,KAAG,CAAC,IAAI,SAAS,CAAC,IAAI,GAAG,QAAQ,CAAC,EACjD,CAAC;AAEnB,+CAA+C;AAC/C,eAAO,MAAM,UAAU,GAAI,GAAG,OAAO,KAAG,CAAC,IAAI,QACR,CAAC;AAEtC,mFAAmF;AACnF,eAAO,MAAM,MAAM,GAAI,GAAG,OAAO,KAAG,CAAC,IAAI,IACiB,CAAC"}
@@ -0,0 +1,97 @@
1
+ import { CONTINUE, SKIP, visit } from "@unified-latex/unified-latex-util-visit";
2
+ import { KEY_SIGNATURES } from "./parse.js";
3
+ export { collapse } from "../../domain/tex-document.js";
4
+ /** Where a node stands, or that it has no position. */
5
+ export const placeOf = (n) => n.position === undefined
6
+ ? { kind: "unplaced" }
7
+ : {
8
+ kind: "at",
9
+ span: { start: n.position.start.offset, end: n.position.end.offset },
10
+ };
11
+ /** What `f` makes of a place's span, or nothing for a node the parser gave no position. */
12
+ export const inPlace = (p, f) => (p.kind === "at" ? f(p.span) : []);
13
+ /** A macro's arguments, in order: none when the parser attached none. */
14
+ export const argumentsOf = (m) => m.args ?? [];
15
+ /** The first mandatory (`{…}`) and optional (`[…]`) arguments' contents, and the last mandatory one's. */
16
+ export const mandatory = (m) => argumentsOf(m).filter((a) => a.openMark === "{");
17
+ export const optional = (m) => argumentsOf(m).find((a) => a.openMark === "[");
18
+ /** What a string node reads as: itself, except a tie (`~`), which is a space the reader sees. */
19
+ export const stringText = (content) => content === "~" ? " " : content;
20
+ const LAST = { kind: "argument", at: -1 };
21
+ const NONE = { kind: "none" };
22
+ /**
23
+ * Macros that do not typeset their last mandatory argument, as data. `\texorpdfstring{shown}{bookmark}`
24
+ * typesets the first; a declaration (`\color{red}`, `\fontsize{10}{12}`, `\vspace{1em}`,
25
+ * `\setlength{\x}{0pt}`) typesets none. Every other macro typesets its last (`\textcolor{red}{x}`,
26
+ * `\colorbox{yellow}{x}`, `\href{url}{x}`).
27
+ */
28
+ const SHOWN_ARGUMENT = new Map([
29
+ ["texorpdfstring", { kind: "argument", at: 0 }],
30
+ ...["color", "fontsize", "vspace", "hspace", "setlength", "addtolength"].map((m) => [m, NONE]),
31
+ ]);
32
+ /** The text a (non-key) macro typesets: see `SHOWN_ARGUMENT`. */
33
+ function shownText(m) {
34
+ const shown = SHOWN_ARGUMENT.get(m.content) ?? LAST;
35
+ return shown.kind === "none"
36
+ ? ""
37
+ : textOf(mandatory(m).at(shown.at)?.content);
38
+ }
39
+ /**
40
+ * The text of a node list with markup dropped: strings, spaces, what groups hold, and the argument a
41
+ * formatting macro typesets — its last mandatory one (`\textbf{Usage}`, `\textcolor{red}{Usage}`,
42
+ * `\href{url}{Usage}` → `Usage`) unless `SHOWN_ARGUMENT` says otherwise. A key macro's arguments
43
+ * (`\label{…}`, `\cite{…}`) are not text.
44
+ */
45
+ export const textOf = (nodes) => (nodes ?? [])
46
+ .map((n) => {
47
+ if (n.type === "string")
48
+ return stringText(n.content);
49
+ if (n.type === "whitespace" || n.type === "parbreak")
50
+ return " ";
51
+ if (n.type === "group")
52
+ return textOf(n.content);
53
+ return n.type === "macro" && !(n.content in KEY_SIGNATURES)
54
+ ? shownText(n)
55
+ : "";
56
+ })
57
+ .join("");
58
+ /**
59
+ * A macro's place with its arguments: from its name to past the closing mark of the last argument
60
+ * that holds text. unified-latex positions the name and the arguments' contents, never the
61
+ * arguments themselves, so an empty trailing argument is not covered.
62
+ */
63
+ export function macroPlace(m) {
64
+ const name = placeOf(m);
65
+ if (name.kind === "unplaced")
66
+ return name;
67
+ const end = (m.args ?? []).reduce((e, a) => {
68
+ const last = a.content.at(-1)?.position?.end.offset;
69
+ return last === undefined ? e : last + a.closeMark.length;
70
+ }, name.span.end);
71
+ const span = { start: name.span.start, end };
72
+ return { kind: "at", span };
73
+ }
74
+ /**
75
+ * Everything visit reaches under `tree`, in document order, node lists included; `skip` prunes what
76
+ * it is given (a node or an argument, with the node that holds it) and everything under it. visit
77
+ * reports through a callback and returns nothing, so the one collection point of this adapter is here.
78
+ */
79
+ export function visited(
80
+ // eslint-disable-next-line functional/prefer-immutable-types -- visit's own parameter type is mutable
81
+ tree, skip) {
82
+ // eslint-disable-next-line functional/prefer-immutable-types -- the one accumulator, see above
83
+ const seen = [];
84
+ visit(tree, (node, info) => {
85
+ // eslint-disable-next-line functional/immutable-data -- visit is callback-only; see above
86
+ seen.push(node);
87
+ return skip(node, info.parents[0]) ? SKIP : CONTINUE;
88
+ }, { includeArrays: true });
89
+ return seen;
90
+ }
91
+ /** A node list visit reached. `Array.isArray` alone does not narrow a readonly array. */
92
+ export const isList = (v) => Array.isArray(v);
93
+ /** A macro's argument, as visit reports it. */
94
+ export const isArgument = (v) => !isList(v) && v.type === "argument";
95
+ /** A node, as opposed to a node list or an argument (which visit also reports). */
96
+ export const isNode = (v) => !isList(v) && v.type !== "argument" && v.type !== "root";
97
+ //# sourceMappingURL=nodes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodes.js","sourceRoot":"","sources":["../../../src/adapters/latex/nodes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Outline } from "../../domain/tex-document.ts";
2
+ import type { ParsedTex } from "./parse.ts";
3
+ /**
4
+ * The body's `\section`s (starred or not) in document order, the first back-matter node, and the
5
+ * end of the document. A source with no `document` environment is read whole, as a fragment. What
6
+ * the PDF never shows is pruned (`isUnrendered`), and so is a macro definition's body
7
+ * (`isDefinition`): a heading in a comment environment or in a definition is not a section.
8
+ */
9
+ export declare function outlineOf(t: ParsedTex): Outline;
10
+ //# sourceMappingURL=outline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outline.d.ts","sourceRoot":"","sources":["../../../src/adapters/latex/outline.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAW,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAYrE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAyB5C;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAiB/C"}
@@ -0,0 +1,39 @@
1
+ import { isDefined } from "remeda";
2
+ import { collapse, isNode, macroPlace, mandatory, textOf, visited, } from "./nodes.js";
3
+ import { isDefinition, isUnrendered } from "./hidden.js";
4
+ /** Macros and the environment that start the back matter: the appendix and the bibliography. */
5
+ const BACK_MATTER_MACROS = new Set([
6
+ "appendix",
7
+ "bibliography",
8
+ "printbibliography",
9
+ ]);
10
+ const isBackMatter = (n) => (n.type === "macro" && BACK_MATTER_MACROS.has(n.content)) ||
11
+ (n.type === "environment" && n.env === "thebibliography");
12
+ const isSection = (n) => n.type === "macro" && n.content === "section";
13
+ const isDocument = (n) => n.type === "environment" && n.env === "document";
14
+ /** One `\section`/`\section*`: the last mandatory argument is its title. */
15
+ const headingOf = (m) => ({
16
+ title: collapse(textOf(mandatory(m).at(-1)?.content)),
17
+ place: macroPlace(m),
18
+ });
19
+ /**
20
+ * The body's `\section`s (starred or not) in document order, the first back-matter node, and the
21
+ * end of the document. A source with no `document` environment is read whole, as a fragment. What
22
+ * the PDF never shows is pruned (`isUnrendered`), and so is a macro definition's body
23
+ * (`isDefinition`): a heading in a comment environment or in a definition is not a section.
24
+ */
25
+ export function outlineOf(t) {
26
+ const doc = t.root.content.find(isDocument);
27
+ const nodes = visited(doc?.content ?? t.root.content, (v, parent) => isUnrendered(v, parent) || isDefinition(v)).filter(isNode);
28
+ const backMatter = nodes
29
+ .filter(isBackMatter)
30
+ .map((n) => n.position?.start.offset)
31
+ .filter(isDefined)[0] ?? null;
32
+ const docEnd = doc?.position?.end.offset;
33
+ return {
34
+ sections: nodes.filter(isSection).map(headingOf),
35
+ backMatter,
36
+ end: docEnd === undefined ? null : docEnd - 1,
37
+ };
38
+ }
39
+ //# sourceMappingURL=outline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outline.js","sourceRoot":"","sources":["../../../src/adapters/latex/outline.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEnC,OAAO,EACL,QAAQ,EACR,MAAM,EACN,UAAU,EACV,SAAS,EACT,MAAM,EACN,OAAO,GAGR,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGzD,gGAAgG;AAChG,MAAM,kBAAkB,GAAwB,IAAI,GAAG,CAAC;IACtD,UAAU;IACV,cAAc;IACd,mBAAmB;CACpB,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,CAAO,EAAW,EAAE,CACxC,CAAC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,GAAG,KAAK,iBAAiB,CAAC,CAAC;AAE5D,MAAM,SAAS,GAAG,CAAC,CAAO,EAAc,EAAE,CACxC,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC;AAEhD,MAAM,UAAU,GAAG,CAAC,CAAO,EAAkC,EAAE,CAC7D,CAAC,CAAC,IAAI,KAAK,aAAa,IAAI,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC;AAEnD,4EAA4E;AAC5E,MAAM,SAAS,GAAG,CAAC,CAAQ,EAAW,EAAE,CAAC,CAAC;IACxC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACrD,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;CACrB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,CAAY;IACpC,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,EAC9B,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,YAAY,CAAC,CAAC,CAAC,CAC1D,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjB,MAAM,UAAU,GACd,KAAK;SACF,MAAM,CAAC,YAAY,CAAC;SACpB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC;SACpC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IAClC,MAAM,MAAM,GAAG,GAAG,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC;IACzC,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;QAChD,UAAU;QACV,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC;KAC9C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * A LaTeX source → its unified-latex tree, as one `ParsedTex` that keeps the two together.
3
+ *
4
+ * ── CITATION KEYS ARE ARGUMENTS, NOT TEXT ────────────────────────────────────────
5
+ * unified-latex attaches arguments only to macros it has a signature for. natbib's and biblatex's
6
+ * citation commands have none, so `\citep{aisec2025}` came back with its key as a separate group —
7
+ * readable as prose. `KEY_SIGNATURES` declares them, and the other macros whose arguments name a
8
+ * file, a label or a URL rather than say something, so their arguments are attached and the
9
+ * rendered text skips them structurally. `\href` says something in one argument and names a URL in
10
+ * the other, so it is signed too, and `KEY_ARGUMENT` says which of its arguments is not text.
11
+ */
12
+ import type * as Ast from "@unified-latex/unified-latex-types";
13
+ /** Citation commands: their `{…}` argument is a key, their `[…]` ones are notes the reader sees. */
14
+ export declare const CITATION_MACROS: ReadonlySet<string>;
15
+ /** Macros whose arguments are keys, labels, files or URLs — never text a reader sees. */
16
+ export declare const KEY_SIGNATURES: Readonly<Record<string, {
17
+ readonly signature: string;
18
+ }>>;
19
+ /**
20
+ * Macros that print some arguments and not others: the index of the one argument that is a key or
21
+ * a URL. A citation (`o o m`) prints its `[…]` notes, not its `{…}` key; `\href` (`m m`) prints its
22
+ * link text, not its URL.
23
+ */
24
+ export declare const KEY_ARGUMENT: ReadonlyMap<string, number>;
25
+ /**
26
+ * Macros that define other macros or environments. A heading in a body is no section where it is
27
+ * written, so the outline skips these; the rendered text reads a body as written, since nothing here
28
+ * expands macros. `\def` and its kin get a signature so the name and the body attach to them; a
29
+ * parameter text (`\def\x#1{…}`) is not modelled.
30
+ */
31
+ export declare const DEFINITION_MACROS: ReadonlySet<string>;
32
+ declare const PARSED: unique symbol;
33
+ /** A source and ITS tree: only `parseLatex` makes one, so a tree cannot be paired with another source. */
34
+ export interface ParsedTex {
35
+ readonly src: string;
36
+ readonly root: Ast.Root;
37
+ readonly [PARSED]: true;
38
+ }
39
+ /** A LaTeX source → its tree. */
40
+ export declare const parseLatex: (src: string) => ParsedTex;
41
+ export {};
42
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/adapters/latex/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,KAAK,GAAG,MAAM,oCAAoC,CAAC;AAU/D,oGAAoG;AACpG,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,CAgB9C,CAAC;AAEH,yFAAyF;AACzF,eAAO,MAAM,cAAc,EAAE,QAAQ,CACnC,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAwB9C,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAGnD,CAAC;AAUH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAWhD,CAAC;AAOH,QAAA,MAAM,MAAM,eAAsB,CAAC;AAEnC,0GAA0G;AAC1G,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC;IACxB,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC;CACzB;AAcD,iCAAiC;AACjC,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,KAAG,SAIvC,CAAC"}
@@ -0,0 +1,95 @@
1
+ import { getParser } from "@unified-latex/unified-latex-util-parse";
2
+ import { once } from "remeda";
3
+ const signed = (names, signature) => names.map((m) => [m, { signature }]);
4
+ /** Citation commands: their `{…}` argument is a key, their `[…]` ones are notes the reader sees. */
5
+ export const CITATION_MACROS = new Set([
6
+ "cite",
7
+ "citep",
8
+ "citet",
9
+ "citealp",
10
+ "citealt",
11
+ "citeauthor",
12
+ "citeyear",
13
+ "citeyearpar",
14
+ "Citep",
15
+ "Citet",
16
+ "nocite",
17
+ "parencite",
18
+ "textcite",
19
+ "autocite",
20
+ "footcite",
21
+ ]);
22
+ /** Macros whose arguments are keys, labels, files or URLs — never text a reader sees. */
23
+ export const KEY_SIGNATURES = Object.fromEntries([
24
+ ...signed([...CITATION_MACROS], "o o m"),
25
+ ...signed([
26
+ "label",
27
+ "ref",
28
+ "eqref",
29
+ "pageref",
30
+ "autoref",
31
+ "cref",
32
+ "Cref",
33
+ "url",
34
+ "input",
35
+ "include",
36
+ "subfile",
37
+ "bibliography",
38
+ "bibliographystyle",
39
+ "addbibresource",
40
+ ], "m"),
41
+ ...signed(["includegraphics"], "s o o m"),
42
+ ...signed(["usepackage", "RequirePackage", "documentclass"], "o m o"),
43
+ ]);
44
+ /**
45
+ * Macros that print some arguments and not others: the index of the one argument that is a key or
46
+ * a URL. A citation (`o o m`) prints its `[…]` notes, not its `{…}` key; `\href` (`m m`) prints its
47
+ * link text, not its URL.
48
+ */
49
+ export const KEY_ARGUMENT = new Map([
50
+ ...[...CITATION_MACROS].map((m) => [m, 2]),
51
+ ["href", 0],
52
+ ]);
53
+ const LINK_SIGNATURES = Object.fromEntries(signed(["href"], "m m"));
54
+ /**
55
+ * Declarations unified-latex has no signature for: signed so their arguments (sizes, not text)
56
+ * attach to them instead of standing beside them as groups a reader would seem to see.
57
+ */
58
+ const DECLARATION_SIGNATURES = Object.fromEntries(signed(["fontsize"], "m m"));
59
+ /**
60
+ * Macros that define other macros or environments. A heading in a body is no section where it is
61
+ * written, so the outline skips these; the rendered text reads a body as written, since nothing here
62
+ * expands macros. `\def` and its kin get a signature so the name and the body attach to them; a
63
+ * parameter text (`\def\x#1{…}`) is not modelled.
64
+ */
65
+ export const DEFINITION_MACROS = new Set([
66
+ "newcommand",
67
+ "renewcommand",
68
+ "providecommand",
69
+ "DeclareRobustCommand",
70
+ "newenvironment",
71
+ "renewenvironment",
72
+ "def",
73
+ "gdef",
74
+ "edef",
75
+ "xdef",
76
+ ]);
77
+ const DEF_SIGNATURES = Object.fromEntries(signed(["def", "gdef", "edef", "xdef"], "m m"));
78
+ // Not exported: a `ParsedTex` carries this property, and the one way to write it is `parseLatex`.
79
+ const PARSED = Symbol("ParsedTex");
80
+ /** One parser for the process, made on first use: building one compiles its grammar. */
81
+ const parser = once(() => getParser({
82
+ macros: {
83
+ ...KEY_SIGNATURES,
84
+ ...LINK_SIGNATURES,
85
+ ...DECLARATION_SIGNATURES,
86
+ ...DEF_SIGNATURES,
87
+ },
88
+ }));
89
+ /** A LaTeX source → its tree. */
90
+ export const parseLatex = (src) => ({
91
+ src,
92
+ root: parser().parse(src),
93
+ [PARSED]: true,
94
+ });
95
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../../../src/adapters/latex/parse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { Passage } from "../../domain/tex-document.ts";
2
+ import { type ParsedTex } from "./parse.ts";
3
+ /**
4
+ * The body's prose, in document order: the content of the `document` environment (the whole
5
+ * source when there is none), up to the first back-matter node.
6
+ */
7
+ export declare function bodyProse(t: ParsedTex): readonly Passage[];
8
+ //# sourceMappingURL=prose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prose.d.ts","sourceRoot":"","sources":["../../../src/adapters/latex/prose.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAS,OAAO,EAAc,MAAM,8BAA8B,CAAC;AAW/E,OAAO,EAAsC,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AA6bhF;;;GAGG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,OAAO,EAAE,CAM1D"}