paperlint 10.4.1 → 11.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.
Files changed (131) hide show
  1. package/.github/workflows/deadlines.yml +27 -7
  2. package/README.md +16 -15
  3. package/dist/adapters/hotcrp/index.d.ts +6 -4
  4. package/dist/adapters/hotcrp/index.d.ts.map +1 -1
  5. package/dist/adapters/hotcrp/index.js +6 -4
  6. package/dist/adapters/hotcrp/index.js.map +1 -1
  7. package/dist/adapters/hotcrp/portal.io.d.ts +3 -1
  8. package/dist/adapters/hotcrp/portal.io.d.ts.map +1 -1
  9. package/dist/adapters/hotcrp/portal.io.js +36 -11
  10. package/dist/adapters/hotcrp/portal.io.js.map +1 -1
  11. package/dist/adapters/hotcrp/response.d.ts +6 -1
  12. package/dist/adapters/hotcrp/response.d.ts.map +1 -1
  13. package/dist/adapters/hotcrp/response.js +17 -0
  14. package/dist/adapters/hotcrp/response.js.map +1 -1
  15. package/dist/adapters/hotcrp/site.d.ts +9 -0
  16. package/dist/adapters/hotcrp/site.d.ts.map +1 -0
  17. package/dist/adapters/hotcrp/site.js +22 -0
  18. package/dist/adapters/hotcrp/site.js.map +1 -0
  19. package/dist/adapters/hotcrp/token.d.ts +13 -0
  20. package/dist/adapters/hotcrp/token.d.ts.map +1 -0
  21. package/dist/adapters/hotcrp/token.js +48 -0
  22. package/dist/adapters/hotcrp/token.js.map +1 -0
  23. package/dist/adapters/latex/abstract.d.ts +22 -0
  24. package/dist/adapters/latex/abstract.d.ts.map +1 -0
  25. package/dist/adapters/latex/abstract.js +187 -0
  26. package/dist/adapters/latex/abstract.js.map +1 -0
  27. package/dist/adapters/latex/headings.d.ts +6 -0
  28. package/dist/adapters/latex/headings.d.ts.map +1 -1
  29. package/dist/adapters/latex/headings.js +5 -4
  30. package/dist/adapters/latex/headings.js.map +1 -1
  31. package/dist/adapters/latex/index.d.ts.map +1 -1
  32. package/dist/adapters/latex/index.js +2 -0
  33. package/dist/adapters/latex/index.js.map +1 -1
  34. package/dist/adapters/latex/parse.d.ts +15 -0
  35. package/dist/adapters/latex/parse.d.ts.map +1 -1
  36. package/dist/adapters/latex/parse.js +58 -1
  37. package/dist/adapters/latex/parse.js.map +1 -1
  38. package/dist/cli.d.ts.map +1 -1
  39. package/dist/cli.js +20 -8
  40. package/dist/cli.js.map +1 -1
  41. package/dist/cycle-rules.d.ts.map +1 -1
  42. package/dist/cycle-rules.js +3 -4
  43. package/dist/cycle-rules.js.map +1 -1
  44. package/dist/domain/deadline.d.ts +8 -1
  45. package/dist/domain/deadline.d.ts.map +1 -1
  46. package/dist/domain/deadline.js +26 -12
  47. package/dist/domain/deadline.js.map +1 -1
  48. package/dist/domain/portal-token.d.ts +44 -0
  49. package/dist/domain/portal-token.d.ts.map +1 -0
  50. package/dist/domain/portal-token.js +32 -0
  51. package/dist/domain/portal-token.js.map +1 -0
  52. package/dist/domain/submission.d.ts +30 -0
  53. package/dist/domain/submission.d.ts.map +1 -1
  54. package/dist/domain/submission.js +68 -0
  55. package/dist/domain/submission.js.map +1 -1
  56. package/dist/lib/paper-config.d.ts +1 -1
  57. package/dist/lib/paper-config.d.ts.map +1 -1
  58. package/dist/lib/paper-config.js +6 -4
  59. package/dist/lib/paper-config.js.map +1 -1
  60. package/dist/paper-settings.d.ts +3 -1
  61. package/dist/paper-settings.d.ts.map +1 -1
  62. package/dist/paper-settings.js +11 -5
  63. package/dist/paper-settings.js.map +1 -1
  64. package/dist/ports/latex.d.ts +23 -0
  65. package/dist/ports/latex.d.ts.map +1 -1
  66. package/dist/ports/submission-portal.d.ts +39 -2
  67. package/dist/ports/submission-portal.d.ts.map +1 -1
  68. package/dist/ports/venue-deadlines.d.ts +1 -1
  69. package/dist/submission.d.ts +49 -11
  70. package/dist/submission.d.ts.map +1 -1
  71. package/dist/submission.js +332 -44
  72. package/dist/submission.js.map +1 -1
  73. package/docs/configuration.md +2 -1
  74. package/docs/rules/cycle/record.md +9 -6
  75. package/docs/submission.md +47 -48
  76. package/eslint.config.mjs +3 -0
  77. package/lib/paper-config.ts +7 -4
  78. package/package.json +6 -1
  79. package/presets/msr.jsonc +9 -7
  80. package/presets/msr.md +14 -10
  81. package/scripts/check.ts +1 -1
  82. package/scripts/refresh-deadlines/compare.test.ts +75 -0
  83. package/scripts/refresh-deadlines/compare.ts +101 -0
  84. package/scripts/refresh-deadlines/main.test.ts +140 -0
  85. package/scripts/refresh-deadlines/main.ts +56 -0
  86. package/scripts/refresh-deadlines/refresh.test.ts +287 -0
  87. package/scripts/refresh-deadlines/refresh.ts +183 -0
  88. package/skills/submission-portal/SKILL.md +60 -44
  89. package/skills/submission-portal/SKILL.md.spec.ts +62 -43
  90. package/skills/submission-portal/submission-portal.test.ts +4 -73
  91. package/src/adapters/hotcrp/cassette/README.md +4 -4
  92. package/src/adapters/hotcrp/cassette/deadlines-msr2027.html +9 -9
  93. package/src/adapters/hotcrp/deadlines.io.test.ts +2 -2
  94. package/src/adapters/hotcrp/deadlines.test.ts +3 -3
  95. package/src/adapters/hotcrp/index.ts +15 -3
  96. package/src/adapters/hotcrp/portal.io.ts +61 -17
  97. package/src/adapters/hotcrp/portal.test.ts +105 -1
  98. package/src/adapters/hotcrp/response.ts +21 -0
  99. package/src/adapters/hotcrp/site.ts +34 -0
  100. package/src/adapters/hotcrp/token.test.ts +69 -0
  101. package/src/adapters/hotcrp/token.ts +51 -0
  102. package/src/adapters/latex/abstract.test.ts +280 -0
  103. package/src/adapters/latex/abstract.ts +272 -0
  104. package/src/adapters/latex/headings.ts +5 -4
  105. package/src/adapters/latex/index.test.ts +31 -1
  106. package/src/adapters/latex/index.ts +2 -0
  107. package/src/adapters/latex/parse.ts +64 -3
  108. package/src/cli.test.ts +20 -8
  109. package/src/cli.ts +22 -13
  110. package/src/cycle-rules.test.ts +6 -6
  111. package/src/cycle-rules.ts +7 -4
  112. package/src/domain/deadline.test.ts +31 -2
  113. package/src/domain/deadline.ts +42 -16
  114. package/src/domain/portal-token.test.ts +55 -0
  115. package/src/domain/portal-token.ts +63 -0
  116. package/src/domain/submission.test.ts +88 -0
  117. package/src/domain/submission.ts +99 -0
  118. package/src/new-paper.test.ts +1 -0
  119. package/src/paper-settings.test.ts +20 -0
  120. package/src/paper-settings.ts +17 -5
  121. package/src/ports/latex.ts +25 -0
  122. package/src/ports/submission-portal.ts +43 -1
  123. package/src/ports/venue-deadlines.ts +1 -1
  124. package/src/presets.test.ts +8 -5
  125. package/src/submission-new.test.ts +569 -0
  126. package/src/submission-show.test.ts +210 -0
  127. package/src/submission-update.test.ts +160 -0
  128. package/src/submission.test.ts +140 -518
  129. package/src/submission.ts +494 -61
  130. package/scripts/refresh-deadlines.test.ts +0 -431
  131. package/scripts/refresh-deadlines.ts +0 -387
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # A shipped venue preset (presets/msr.jsonc, presets/aidc.jsonc) carries its portal's deadlines,
4
4
  # each with the day it was read. Chairs move deadlines; a paper only learns it if the preset does.
5
- # So this job reads every preset's portal (`scripts/refresh-deadlines.ts`, through the HotCRP adapter
5
+ # So this job reads every preset's portal (`npm run refresh-deadlines`, through the HotCRP adapter
6
6
  # in src/adapters/hotcrp/ — the public deadlines page, no account, no secret) and, when a value
7
7
  # changed, opens ONE pull request with the new values, or updates the one already open. Its commit
8
8
  # and title are `fix(presets): …`, which semantic-release (.releaserc.json, conventionalcommits)
@@ -13,7 +13,8 @@
13
13
  # line in the pull request's body, and the script exits 0: the venue's outage is not a defect of this
14
14
  # repository, and tomorrow's run reads it again. Only a preset that does not parse fails the run
15
15
  # (exit 1) — that one IS ours, and `ci` fails on it too. `ci` itself never touches the network for
16
- # this: scripts/refresh-deadlines.test.ts replays the pages recorded in src/adapters/hotcrp/cassette/.
16
+ # this: scripts/refresh-deadlines/main.test.ts replays the MSR page recorded in
17
+ # src/adapters/hotcrp/cassette/, and refresh.test.ts fakes the portal.
17
18
  #
18
19
  # ⚠️ A pull request opened with GITHUB_TOKEN does not start other workflows (GitHub's rule against
19
20
  # loops), so `ci` would never run on it and the PR could not show green. The last step therefore
@@ -37,11 +38,13 @@ concurrency:
37
38
  group: deadlines
38
39
  cancel-in-progress: false
39
40
 
40
- # Push the bot's branch · open or edit its pull request · dispatch `ci` on it. Nothing else.
41
+ # Push the bot's branch · open or edit its pull request · dispatch `ci` on it · report a failed run
42
+ # in one issue. Nothing else.
41
43
  permissions:
42
44
  contents: write
43
45
  pull-requests: write
44
46
  actions: write
47
+ issues: write
45
48
 
46
49
  jobs:
47
50
  refresh:
@@ -57,14 +60,17 @@ jobs:
57
60
  node-version: "22"
58
61
  cache: npm
59
62
 
60
- # `--ignore-scripts`: the script runs from source (Node strips the types); `prepare`'s tsc
61
- # build is not needed to read a page and rewrite a JSONC file.
63
+ # `--ignore-scripts`: no `prepare` build, so there is no `dist/`. The npm script runs the code
64
+ # from source with `--conditions=paperlint-source` (package.json); without it `#lib/*` resolves
65
+ # to `dist/`, and every run from 2026-10-06 to 2026-10-19 died on ERR_MODULE_NOT_FOUND
66
+ # dist/lib/paper-config.js. scripts/refresh-deadlines/main.test.ts runs the same npm script on every
67
+ # pull request under test/no-dist.ts, which refuses any module in `dist/`.
62
68
  - name: npm ci
63
69
  run: npm ci --ignore-scripts
64
70
  timeout-minutes: 5
65
71
 
66
72
  - name: read every preset's portal
67
- run: node scripts/refresh-deadlines.ts --summary "$RUNNER_TEMP/deadlines.md"
73
+ run: npm run refresh-deadlines -- --summary "$RUNNER_TEMP/deadlines.md"
68
74
  timeout-minutes: 3
69
75
 
70
76
  - name: open or update the pull request
@@ -85,7 +91,7 @@ jobs:
85
91
  git commit -F - <<'MSG'
86
92
  fix(presets): venue deadlines as their portals publish them now
87
93
 
88
- Re-read by .github/workflows/deadlines.yml (scripts/refresh-deadlines.ts); the pull
94
+ Re-read by .github/workflows/deadlines.yml (npm run refresh-deadlines); the pull
89
95
  request's body lists each value that changed and where it was read.
90
96
  MSG
91
97
  # The branch is the bot's own and is rebuilt from main on every run: force is the point.
@@ -98,3 +104,17 @@ jobs:
98
104
  gh pr edit "$open" --repo "$REPO" --title "$title" --body-file "$RUNNER_TEMP/deadlines.md"
99
105
  fi
100
106
  gh workflow run ci.yml --repo "$REPO" --ref "$BRANCH"
107
+
108
+ # 🔴 A FAILED RUN IS AN ISSUE, NOT A RED DOT NOBODY OPENS. The job failed on every scheduled run
109
+ # from 2026-10-06 to 2026-10-19 and nobody looked: MSR moved both deadlines and the preset kept
110
+ # the old ones (#235). So any failure opens ONE issue labelled and titled "deadline refresh
111
+ # failing", or comments on the open one, with the run's link. A portal that is down is not a
112
+ # failure (the script warns and exits 0), so this fires only for a defect of ours.
113
+ - name: report a failed refresh in one issue
114
+ if: failure()
115
+ uses: jayqi/failed-build-issue-action@940568ce50eeef3f31a920614cefcc6102d2f930 # v1.3.0
116
+ with:
117
+ label-name: deadline refresh failing
118
+ title-template: deadline refresh failing
119
+ body-template: |
120
+ The scheduled refresh of the venue presets' deadlines failed: {{serverUrl}}/{{repo.owner}}/{{repo.repo}}/actions/runs/{{runId}} — until it is fixed, a deadline a portal moves is not picked up by the presets.
package/README.md CHANGED
@@ -150,20 +150,21 @@ Each stage's skills, what it writes and what checks it, drawn as one flow, with
150
150
 
151
151
  ## 🧰 Commands
152
152
 
153
- | command | what it does |
154
- | ----------------------------------------------------------- | ------------------------------------------------------------------------------ |
155
- | `npx paperlint init` | sets the project up |
156
- | `npx paperlint new my-paper --venue <preset> --kind <kind>` | creates a paper folder for that venue, or completes an existing one |
157
- | `npx paperlint build <paper>` | compiles `paper.tex` to `paper.pdf`, measures it, checks the references online |
158
- | `npx paperlint lint` | runs every check over your papers; `--fix` fixes what can be fixed |
159
- | `npx paperlint toolchain` | installs TeX Live with the packages your venues need (~270 MB, ~3 min, once) |
160
- | `npx paperlint doctor` | checks the setup and exits non-zero if something is miswired |
161
- | `npx paperlint submission show <paper>` | the paper's submission on the venue's portal, and whether it holds your build |
162
- | `npx paperlint submission update <paper>` | checks a new PDF/abstract against the portal; `--save` sends it for real |
163
- | `npx paperlint studies new <paper> "<title>"` | registers a study: the next id in `repro/studies.json`, its folder, the index |
164
- | `npx paperlint studies index <paper>` | regenerates the index of the studies in `repro/README.md` |
165
- | `npx paperlint studies gate <paper> <id>` | exits 0 only once the study's decision is committed: run it before the study |
166
- | `npx paperlint --help` | every command and flag |
153
+ | command | what it does |
154
+ | ----------------------------------------------------------- | --------------------------------------------------------------------------------------- |
155
+ | `npx paperlint init` | sets the project up |
156
+ | `npx paperlint new my-paper --venue <preset> --kind <kind>` | creates a paper folder for that venue, or completes an existing one |
157
+ | `npx paperlint build <paper>` | compiles `paper.tex` to `paper.pdf`, measures it, checks the references online |
158
+ | `npx paperlint lint` | runs every check over your papers; `--fix` fixes what can be fixed |
159
+ | `npx paperlint toolchain` | installs TeX Live with the packages your venues need (~270 MB, ~3 min, once) |
160
+ | `npx paperlint doctor` | checks the setup and exits non-zero if something is miswired |
161
+ | `npx paperlint submission new <paper>` | creates the submission on the portal (title, abstract, authors, PDF); `--save` for real |
162
+ | `npx paperlint submission show <paper>` | the paper's submission on the venue's portal, and whether it holds your build |
163
+ | `npx paperlint submission update <paper>` | checks a new PDF/abstract against the portal; `--save` sends it for real |
164
+ | `npx paperlint studies new <paper> "<title>"` | registers a study: the next id in `repro/studies.json`, its folder, the index |
165
+ | `npx paperlint studies index <paper>` | regenerates the index of the studies in `repro/README.md` |
166
+ | `npx paperlint studies gate <paper> <id>` | exits 0 only once the study's decision is committed: run it before the study |
167
+ | `npx paperlint --help` | every command and flag |
167
168
 
168
169
  ## 🧠 Skills
169
170
 
@@ -276,7 +277,7 @@ Only `paperlint lint --fix`, and only three rules: `paper/section-word` (`§`
276
277
  - [`docs/configuration.md`](docs/configuration.md) — every setting, how `build` compiles, using your own ESLint
277
278
  - [`docs/rules.md`](docs/rules.md) — every check, venue presets, recording a submitted PDF
278
279
  - [`docs/references.md`](docs/references.md) — the reference check, and the cache file to commit
279
- - [`docs/submission.md`](docs/submission.md) — reading and updating a submission on the venue's portal (HotCRP)
280
+ - [`docs/submission.md`](docs/submission.md) — creating, reading and updating a submission on the venue's portal (HotCRP); one token variable per site
280
281
  - [`docs/optional-rules.md`](docs/optional-rules.md) — checks only some venues need
281
282
  - [`docs/toolchain.md`](docs/toolchain.md) — TeX Live, and Banal (HotCRP's page-geometry checker, GPL)
282
283
  - [`CONTRIBUTING.md`](CONTRIBUTING.md) — how the package is tested and released, and adding a venue to it
@@ -1,9 +1,11 @@
1
1
  /**
2
- * HotCRP, as the `SubmissionPortal` port: its REST API read and written over `fetch`, its answers
3
- * parsed here. Everything that changes if HotCRP's API does lives in this folder.
2
+ * HotCRP, as the `PortalSite` and `SubmissionPortal` ports: its token variables and token page, its
3
+ * REST API read and written over `fetch`, its answers parsed here. Everything that changes if HotCRP's API does lives in this folder.
4
4
  */
5
- export { CONTENT_FIELD, changeObject, hotcrpPortal, type HotcrpOptions, } from "./portal.io.ts";
6
- export { parseShow, parseUpdate, sha256OfHash } from "./response.ts";
5
+ export { CONTENT_FIELD, changeObject, createObject, hotcrpPortal, type HotcrpOptions, } from "./portal.io.ts";
6
+ export { parseCreate, parseShow, parseUpdate, sha256OfHash, } from "./response.ts";
7
7
  export { hotcrpDeadlines } from "./deadlines.io.ts";
8
+ export { hotcrpSite } from "./site.ts";
9
+ export { SITE_LESS_VARIABLE, VARIABLE_PATTERN, tokenVariable, } from "./token.ts";
8
10
  export { parseDeadlinesPage, whatOf } from "./deadlines.ts";
9
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/hotcrp/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/hotcrp/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,KAAK,aAAa,GACnB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1,9 +1,11 @@
1
1
  /**
2
- * HotCRP, as the `SubmissionPortal` port: its REST API read and written over `fetch`, its answers
3
- * parsed here. Everything that changes if HotCRP's API does lives in this folder.
2
+ * HotCRP, as the `PortalSite` and `SubmissionPortal` ports: its token variables and token page, its
3
+ * REST API read and written over `fetch`, its answers parsed here. Everything that changes if HotCRP's API does lives in this folder.
4
4
  */
5
- export { CONTENT_FIELD, changeObject, hotcrpPortal, } from "./portal.io.js";
6
- export { parseShow, parseUpdate, sha256OfHash } from "./response.js";
5
+ export { CONTENT_FIELD, changeObject, createObject, hotcrpPortal, } from "./portal.io.js";
6
+ export { parseCreate, parseShow, parseUpdate, sha256OfHash, } from "./response.js";
7
7
  export { hotcrpDeadlines } from "./deadlines.io.js";
8
+ export { hotcrpSite } from "./site.js";
9
+ export { SITE_LESS_VARIABLE, VARIABLE_PATTERN, tokenVariable, } from "./token.js";
8
10
  export { parseDeadlinesPage, whatOf } from "./deadlines.js";
9
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/hotcrp/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,YAAY,GAEb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/hotcrp/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,YAAY,GAEb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1,4 +1,4 @@
1
- import type { SubmissionChange } from "../../domain/submission.ts";
1
+ import type { NewSubmission, SubmissionChange } from "../../domain/submission.ts";
2
2
  import type { SubmissionPortal } from "../../ports/submission-portal.ts";
3
3
  /**
4
4
  * The form field the PDF travels in, and the name the `json` object's `content_file` refers to it
@@ -15,6 +15,8 @@ export interface HotcrpOptions {
15
15
  }
16
16
  /** The submission object a change sends: only the fields it changes. */
17
17
  export declare function changeObject(id: number, c: SubmissionChange): Readonly<Record<string, unknown>>;
18
+ /** The submission object a creation sends: title, abstract, authors and the PDF's field. */
19
+ export declare function createObject(p: NewSubmission): Readonly<Record<string, unknown>>;
18
20
  /** HotCRP at `o.url`, read and changed with `o.token`. */
19
21
  export declare function hotcrpPortal(o: HotcrpOptions): SubmissionPortal;
20
22
  //# sourceMappingURL=portal.io.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"portal.io.d.ts","sourceRoot":"","sources":["../../../src/adapters/hotcrp/portal.io.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAGzE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAM7C,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAmCD,wEAAwE;AACxE,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,gBAAgB,GAClB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAQnC;AAmBD,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,CAAC,EAAE,aAAa,GAAG,gBAAgB,CAsB/D"}
1
+ {"version":3,"file":"portal.io.d.ts","sourceRoot":"","sources":["../../../src/adapters/hotcrp/portal.io.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAEV,aAAa,EAEb,gBAAgB,EACjB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kCAAkC,CAAC;AAGzE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAM7C,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAmCD,wEAAwE;AACxE,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,gBAAgB,GAClB,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAQnC;AASD,4FAA4F;AAC5F,wBAAgB,YAAY,CAC1B,CAAC,EAAE,aAAa,GACf,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CASnC;AAuCD,0DAA0D;AAC1D,wBAAgB,YAAY,CAAC,CAAC,EAAE,aAAa,GAAG,gBAAgB,CAkB/D"}
@@ -9,12 +9,17 @@
9
9
  * (the documented form: `curl -F "json=<data.json" -F paper.pdf=@paper.pdf SITEURL/api/paper`).
10
10
  * Without `save` the request carries `dry_run=1`: HotCRP checks the change and keeps nothing.
11
11
  *
12
+ * Create: the same `POST`, with `p=new` and `"pid": "new"` in the object — «Setting `p=new` will
13
+ * create a new submission; the response will contain the chosen submission ID»
14
+ * (`devel/apidoc/submissions.md`, `post /paper`, in kohler/hotcrp). The object carries the title, the
15
+ * abstract, the authors and the PDF; nothing else is sent.
16
+ *
12
17
  * 🔴 THE TOKEN goes in the `Authorization` header and nowhere else: not into a URL, a message, or an
13
18
  * error. A failure is described by HTTP status, HotCRP's own messages, or the network error's text.
14
19
  */
15
20
  import { messageOf } from "../../domain/text.js";
16
21
  import { err } from "../../domain/result.js";
17
- import { parseShow, parseUpdate } from "./response.js";
22
+ import { parseCreate, parseShow, parseUpdate } from "./response.js";
18
23
  /**
19
24
  * The form field the PDF travels in, and the name the `json` object's `content_file` refers to it
20
25
  * by. 🔴 NO DOT, SPACE OR BRACKET: HotCRP looks the name up in PHP's `$_FILES`, and PHP renames a
@@ -60,14 +65,33 @@ export function changeObject(id, c) {
60
65
  ...(c.submit ? { status: "submitted" } : {}),
61
66
  };
62
67
  }
63
- function formOf(id, c) {
68
+ /** An author as HotCRP's submission object spells one (`Author::make_keyed` reads `name`). */
69
+ const authorObject = (a) => ({
70
+ name: a.name,
71
+ email: a.email,
72
+ ...(a.affiliation === null ? {} : { affiliation: a.affiliation }),
73
+ });
74
+ /** The submission object a creation sends: title, abstract, authors and the PDF's field. */
75
+ export function createObject(p) {
76
+ return {
77
+ object: "paper",
78
+ pid: "new",
79
+ title: p.title,
80
+ abstract: p.abstract,
81
+ authors: p.authors.map(authorObject),
82
+ submission: { content_file: CONTENT_FIELD },
83
+ };
84
+ }
85
+ function formOf(object, pdf) {
64
86
  const form = new FormData();
65
- form.append("json", JSON.stringify(changeObject(id, c)));
66
- if (c.pdf !== null)
67
- form.append(CONTENT_FIELD, new Blob([new Uint8Array(c.pdf.bytes)], { type: "application/pdf" }), c.pdf.name);
87
+ form.append("json", JSON.stringify(object));
88
+ if (pdf !== null)
89
+ form.append(CONTENT_FIELD, new Blob([new Uint8Array(pdf.bytes)], { type: "application/pdf" }), pdf.name);
68
90
  return form;
69
91
  }
70
92
  const endpoint = (base, params) => `${base}/api/paper?${new URLSearchParams(params).toString()}`;
93
+ /** A `POST /api/paper` carrying the object and the PDF, a dry run unless saving. */
94
+ const post = (o, w) => call(endpoint(o.url, { p: w.p, ...(w.save ? {} : { dry_run: "1" }) }), { method: "POST", body: formOf(w.object, w.pdf) }, o.token, WRITE_TIMEOUT_MS);
71
95
  /** HotCRP at `o.url`, read and changed with `o.token`. */
72
96
  export function hotcrpPortal(o) {
73
97
  return {
@@ -77,14 +101,15 @@ export function hotcrpPortal(o) {
77
101
  return a.ok ? parseShow(a.value.status, a.value.body) : a;
78
102
  },
79
103
  async update(id, change, { save }) {
80
- const url = endpoint(o.url, {
81
- p: String(id),
82
- ...(save ? {} : { dry_run: "1" }),
83
- });
84
- const body = formOf(id, change);
85
- const a = await call(url, { method: "POST", body }, o.token, WRITE_TIMEOUT_MS);
104
+ const object = changeObject(id, change);
105
+ const a = await post(o, { p: String(id), object, pdf: change.pdf, save });
86
106
  return a.ok ? parseUpdate(a.value.status, a.value.body) : a;
87
107
  },
108
+ async create(paper, { save }) {
109
+ const object = createObject(paper);
110
+ const a = await post(o, { p: "new", object, pdf: paper.pdf, save });
111
+ return a.ok ? parseCreate(a.value.status, a.value.body) : a;
112
+ },
88
113
  };
89
114
  }
90
115
  //# sourceMappingURL=portal.io.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"portal.io.js","sourceRoot":"","sources":["../../../src/adapters/hotcrp/portal.io.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"portal.io.js","sourceRoot":"","sources":["../../../src/adapters/hotcrp/portal.io.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { type Result } from "../../domain/result.ts";
2
2
  import { type Sha256 } from "../../domain/sha256.ts";
3
- import type { PortalFailure, SubmissionView, UpdateOutcome } from "../../domain/submission.ts";
3
+ import type { CreateOutcome, PortalFailure, SubmissionView, UpdateOutcome } from "../../domain/submission.ts";
4
4
  /** HotCRP's `sha2-<hex>` → the sha256; null for any other hash it may name. */
5
5
  export declare function sha256OfHash(hash: string): Sha256 | null;
6
6
  /** `GET /api/paper` → the submission, or why there is none. */
@@ -10,4 +10,9 @@ export declare function parseShow(httpStatus: number, body: unknown): Result<Sub
10
10
  * the change whatever the HTTP status; the caller decides the exit from both.
11
11
  */
12
12
  export declare function parseUpdate(httpStatus: number, body: unknown): Result<UpdateOutcome, PortalFailure>;
13
+ /**
14
+ * `POST /api/paper?p=new` → the outcome, with the id HotCRP chose: its `pid`, a number only when the
15
+ * submission was saved (a dry run answers `"pid": "new"`).
16
+ */
17
+ export declare function parseCreate(httpStatus: number, body: unknown): Result<CreateOutcome, PortalFailure>;
13
18
  //# sourceMappingURL=response.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../../src/adapters/hotcrp/response.ts"],"names":[],"mappings":"AAUA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAe,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,KAAK,EAEV,aAAa,EAEb,cAAc,EACd,aAAa,EACd,MAAM,4BAA4B,CAAC;AA6CpC,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGxD;AAkFD,+DAA+D;AAC/D,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,CAMvC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,aAAa,EAAE,aAAa,CAAC,CAYtC"}
1
+ {"version":3,"file":"response.d.ts","sourceRoot":"","sources":["../../../src/adapters/hotcrp/response.ts"],"names":[],"mappings":"AAUA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAe,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,KAAK,EACV,aAAa,EAEb,aAAa,EAEb,cAAc,EACd,aAAa,EACd,MAAM,4BAA4B,CAAC;AA+CpC,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGxD;AAkFD,+DAA+D;AAC/D,wBAAgB,SAAS,CACvB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,cAAc,EAAE,aAAa,CAAC,CAMvC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,aAAa,EAAE,aAAa,CAAC,CAYtC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,OAAO,GACZ,MAAM,CAAC,aAAa,EAAE,aAAa,CAAC,CAStC"}
@@ -43,6 +43,8 @@ const UpdateBody = z.object({
43
43
  change_list: z.array(z.string()).optional(),
44
44
  message_list: Messages,
45
45
  dry_run: z.boolean().optional(),
46
+ // The submission's id: a number once saved, `"new"` for a creation that was not.
47
+ pid: z.union([z.number(), z.string()]).optional(),
46
48
  });
47
49
  const Envelope = z.object({ message_list: Messages });
48
50
  const SHA2 = /^sha2-([0-9a-f]{64})$/;
@@ -135,4 +137,19 @@ export function parseUpdate(httpStatus, body) {
135
137
  dryRun: b.data.dry_run ?? false,
136
138
  });
137
139
  }
140
+ /**
141
+ * `POST /api/paper?p=new` → the outcome, with the id HotCRP chose: its `pid`, a number only when the
142
+ * submission was saved (a dry run answers `"pid": "new"`).
143
+ */
144
+ export function parseCreate(httpStatus, body) {
145
+ const u = parseUpdate(httpStatus, body);
146
+ if (!u.ok)
147
+ return u;
148
+ const pid = UpdateBody.safeParse(body).data?.pid;
149
+ const saved = u.value.valid && !u.value.dryRun;
150
+ return ok({
151
+ ...u.value,
152
+ id: saved && typeof pid === "number" ? pid : null,
153
+ });
154
+ }
138
155
  //# sourceMappingURL=response.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"response.js","sourceRoot":"","sources":["../../../src/adapters/hotcrp/response.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"response.js","sourceRoot":"","sources":["../../../src/adapters/hotcrp/response.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * A HotCRP site before any token, as the `PortalSite` port: the variable its token is read from,
3
+ * where on the site an author makes one and with which scopes, what `submission new` leaves to the
4
+ * site, a submission's page — and the API, once there is a token. Every word here is HotCRP's.
5
+ */
6
+ import type { PortalSite } from "../../ports/submission-portal.ts";
7
+ /** The HotCRP site at `url` (no trailing slash). */
8
+ export declare const hotcrpSite: (url: string) => PortalSite;
9
+ //# sourceMappingURL=site.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site.d.ts","sourceRoot":"","sources":["../../../src/adapters/hotcrp/site.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAC;AAQnE,oDAAoD;AACpD,eAAO,MAAM,UAAU,GAAI,KAAK,MAAM,KAAG,UAmBvC,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { hotcrpPortal } from "./portal.io.js";
2
+ import { SITE_LESS_VARIABLE, VARIABLE_PATTERN, tokenVariable, } from "./token.js";
3
+ /** The HotCRP site at `url` (no trailing slash). */
4
+ export const hotcrpSite = (url) => ({
5
+ tokenVariable: tokenVariable(url),
6
+ siteLessVariable: SITE_LESS_VARIABLE,
7
+ variablePattern: VARIABLE_PATTERN,
8
+ credentials: {
9
+ // HotCRP's own link to it: `hotlink("Profile > Developer", "profile", ["t" => "developer"])`
10
+ // (src/help/h_developer.php in kohler/hotcrp).
11
+ page: `${url}/profile?t=developer`,
12
+ where: "Account settings → Developer → API tokens",
13
+ scopes: "submeta:read and document:read (show), submeta:write and document:write (update, new) — tick all four to use every subcommand",
14
+ },
15
+ siteOnly: [
16
+ "PC conflicts (HotCRP's API takes them as pc_conflicts; paperlint does not send them)",
17
+ "topics, and every field the venue adds (paper type, artifact, consent boxes …)",
18
+ ],
19
+ submissionPage: (id) => `${url}/paper/${id === null ? "<its number>" : String(id)}`,
20
+ connect: (token) => hotcrpPortal({ url, token }),
21
+ });
22
+ //# sourceMappingURL=site.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site.js","sourceRoot":"","sources":["../../../src/adapters/hotcrp/site.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,oDAAoD;AACpD,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAc,EAAE,CAAC,CAAC;IACtD,aAAa,EAAE,aAAa,CAAC,GAAG,CAAC;IACjC,gBAAgB,EAAE,kBAAkB;IACpC,eAAe,EAAE,gBAAgB;IACjC,WAAW,EAAE;QACX,6FAA6F;QAC7F,+CAA+C;QAC/C,IAAI,EAAE,GAAG,GAAG,sBAAsB;QAClC,KAAK,EAAE,2CAA2C;QAClD,MAAM,EACJ,+HAA+H;KAClI;IACD,QAAQ,EAAE;QACR,sFAAsF;QACtF,gFAAgF;KACjF;IACD,cAAc,EAAE,CAAC,EAAE,EAAE,EAAE,CACrB,GAAG,GAAG,UAAU,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;IAC7D,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;CACjD,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ /** The site-less variable, read until #236: named when it is still set, never used. */
2
+ export declare const SITE_LESS_VARIABLE = "HOTCRP_TOKEN";
3
+ /** The shape of a site's variable, as a message names it. */
4
+ export declare const VARIABLE_PATTERN = "HOTCRP_TOKEN_<LABEL>";
5
+ /**
6
+ * The variable a HotCRP site's token is read from: `HOTCRP_TOKEN_` and the site's label upper-cased,
7
+ * every run of characters but letters and digits made one `_`, none at either end.
8
+ * `https://msr2027.hotcrp.com` → `HOTCRP_TOKEN_MSR2027`; `https://aidc.submit.acsac.org` →
9
+ * `HOTCRP_TOKEN_AIDC_SUBMIT_ACSAC_ORG`; `https://hotcrp.example.edu/conf2027` →
10
+ * `HOTCRP_TOKEN_HOTCRP_EXAMPLE_EDU_CONF2027`.
11
+ */
12
+ export declare function tokenVariable(url: string): string;
13
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/adapters/hotcrp/token.ts"],"names":[],"mappings":"AAaA,uFAAuF;AACvF,eAAO,MAAM,kBAAkB,iBAAiB,CAAC;AAEjD,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,yBAAkC,CAAC;AAmBhE;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAOjD"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * WHICH ENVIRONMENT VARIABLE HOLDS A HOTCRP SITE'S API TOKEN — HotCRP's fact, so HotCRP's adapter.
3
+ * Pure.
4
+ *
5
+ * A HotCRP token works on the site it was made on and nowhere else (measured 2026-10-19: a token
6
+ * made on one HotCRP site gets `401 Unauthorized` from `msr2027.hotcrp.com`'s `/api/whoami`). So the
7
+ * variable is named after the site, and no two sites share one — `HOTCRP_TOKEN_<subdomain>` on the
8
+ * hosted service, `HOTCRP_TOKEN_<host and path>` anywhere else — and an author with live submissions
9
+ * at two venues sets two variables (#236). The site-less `HOTCRP_TOKEN` is no longer read; the policy that refuses it
10
+ * by name is the domain's (`src/domain/portal-token.ts`).
11
+ */
12
+ import { hostOf } from "../../domain/portal-token.js";
13
+ /** The site-less variable, read until #236: named when it is still set, never used. */
14
+ export const SITE_LESS_VARIABLE = "HOTCRP_TOKEN";
15
+ /** The shape of a site's variable, as a message names it. */
16
+ export const VARIABLE_PATTERN = `${SITE_LESS_VARIABLE}_<LABEL>`;
17
+ /** The hosted service, where each conference is a subdomain of its own. */
18
+ const HOSTED = ".hotcrp.com";
19
+ /**
20
+ * What names a site, and no other: on the hosted service the subdomain alone
21
+ * (`msr2027.hotcrp.com` → `msr2027`); anywhere else the whole host, with a port other than the
22
+ * scheme's default, and path (`hotcrp.example.edu/conf2027`, `review.example.org:8443/conf`),
23
+ * because one install may serve several conferences under paths or ports, and two hosts may share a
24
+ * first label.
25
+ */
26
+ function siteLabel(url) {
27
+ const host = hostOf(url);
28
+ if (host.endsWith(HOSTED))
29
+ return host.slice(0, -HOSTED.length);
30
+ const path = URL.canParse(url) ? new URL(url).pathname : "";
31
+ return `${host}${path}`;
32
+ }
33
+ /**
34
+ * The variable a HotCRP site's token is read from: `HOTCRP_TOKEN_` and the site's label upper-cased,
35
+ * every run of characters but letters and digits made one `_`, none at either end.
36
+ * `https://msr2027.hotcrp.com` → `HOTCRP_TOKEN_MSR2027`; `https://aidc.submit.acsac.org` →
37
+ * `HOTCRP_TOKEN_AIDC_SUBMIT_ACSAC_ORG`; `https://hotcrp.example.edu/conf2027` →
38
+ * `HOTCRP_TOKEN_HOTCRP_EXAMPLE_EDU_CONF2027`.
39
+ */
40
+ export function tokenVariable(url) {
41
+ const label = siteLabel(url);
42
+ const name = label
43
+ .toUpperCase()
44
+ .replace(/[^A-Z0-9]+/g, "_")
45
+ .replace(/^_+|_+$/g, "");
46
+ return `${SITE_LESS_VARIABLE}_${name}`;
47
+ }
48
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/adapters/hotcrp/token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AAEtD,uFAAuF;AACvF,MAAM,CAAC,MAAM,kBAAkB,GAAG,cAAc,CAAC;AAEjD,6DAA6D;AAC7D,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,kBAAkB,UAAU,CAAC;AAEhE,2EAA2E;AAC3E,MAAM,MAAM,GAAG,aAAa,CAAC;AAE7B;;;;;;GAMG;AACH,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,OAAO,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;AAC1B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK;SACf,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3B,OAAO,GAAG,kBAAkB,IAAI,IAAI,EAAE,CAAC;AACzC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * THE ABSTRACT AS PLAIN TEXT, FROM THE SOURCE — the body of `\begin{abstract}…\end{abstract}`, as
3
+ * `paperlint submission new` sends it. Pure.
4
+ *
5
+ * unified-latex does the TeX: util-macros reads `\newcommand`/`\renewcommand`/`\providecommand` and
6
+ * expands them, util-ligatures turns `--`, ``` `` ```, `~`, `\%`, `\ldots`, accents… into the
7
+ * characters TeX prints. The macro categories are the adapter's shared sets (parse.ts, headings.ts).
8
+ * What is ours is the policy. A macro the source defines once, before the abstract, is expanded (`\def`, which
9
+ * util-macros does not read, by hand). One it defines more than once is refused with every
10
+ * definition's place: which one TeX uses depends on order, groups and the definer
11
+ * (`\providecommand` keeps an earlier one), and paperlint does not reimplement that. Refused too, with
12
+ * where it stands: a macro nobody defined, one that takes arguments or expands into itself, math
13
+ * beyond digits and symbols, any other construct. Never guessed.
14
+ */
15
+ import type * as Ast from "@unified-latex/unified-latex-types";
16
+ import { type Result } from "../../domain/result.ts";
17
+ import type { AbstractProblem } from "../../ports/latex.ts";
18
+ /** The abstract of `src` as one paragraph of plain text, or what stops it; nothing after `\\end{document}` is read. */
19
+ export declare const abstractText: (src: string) => Result<string, AbstractProblem>;
20
+ /** The same, over a tree already parsed from `src`. */
21
+ export declare function abstractOfTree(root: Readonly<Ast.Root>, src: string): Result<string, AbstractProblem>;
22
+ //# sourceMappingURL=abstract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract.d.ts","sourceRoot":"","sources":["../../../src/adapters/latex/abstract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,KAAK,GAAG,MAAM,oCAAoC,CAAC;AAW/D,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAkO5D,uHAAuH;AACvH,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CACzB,CAAC;AAEjD,uDAAuD;AACvD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EACxB,GAAG,EAAE,MAAM,GACV,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAWjC"}