paperlint 10.4.0 → 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 (232) hide show
  1. package/.github/workflows/deadlines.yml +27 -7
  2. package/README.md +16 -15
  3. package/dist/CLAUDE.md.spec.d.ts.map +1 -1
  4. package/dist/CLAUDE.md.spec.js +6 -3
  5. package/dist/CLAUDE.md.spec.js.map +1 -1
  6. package/dist/adapters/hotcrp/index.d.ts +6 -4
  7. package/dist/adapters/hotcrp/index.d.ts.map +1 -1
  8. package/dist/adapters/hotcrp/index.js +6 -4
  9. package/dist/adapters/hotcrp/index.js.map +1 -1
  10. package/dist/adapters/hotcrp/portal.io.d.ts +3 -1
  11. package/dist/adapters/hotcrp/portal.io.d.ts.map +1 -1
  12. package/dist/adapters/hotcrp/portal.io.js +36 -11
  13. package/dist/adapters/hotcrp/portal.io.js.map +1 -1
  14. package/dist/adapters/hotcrp/response.d.ts +6 -1
  15. package/dist/adapters/hotcrp/response.d.ts.map +1 -1
  16. package/dist/adapters/hotcrp/response.js +17 -0
  17. package/dist/adapters/hotcrp/response.js.map +1 -1
  18. package/dist/adapters/hotcrp/site.d.ts +9 -0
  19. package/dist/adapters/hotcrp/site.d.ts.map +1 -0
  20. package/dist/adapters/hotcrp/site.js +22 -0
  21. package/dist/adapters/hotcrp/site.js.map +1 -0
  22. package/dist/adapters/hotcrp/token.d.ts +13 -0
  23. package/dist/adapters/hotcrp/token.d.ts.map +1 -0
  24. package/dist/adapters/hotcrp/token.js +48 -0
  25. package/dist/adapters/hotcrp/token.js.map +1 -0
  26. package/dist/adapters/latex/abstract.d.ts +22 -0
  27. package/dist/adapters/latex/abstract.d.ts.map +1 -0
  28. package/dist/adapters/latex/abstract.js +187 -0
  29. package/dist/adapters/latex/abstract.js.map +1 -0
  30. package/dist/adapters/latex/captions.d.ts +9 -0
  31. package/dist/adapters/latex/captions.d.ts.map +1 -0
  32. package/dist/adapters/latex/captions.js +40 -0
  33. package/dist/adapters/latex/captions.js.map +1 -0
  34. package/dist/adapters/latex/headings.d.ts +6 -0
  35. package/dist/adapters/latex/headings.d.ts.map +1 -1
  36. package/dist/adapters/latex/headings.js +5 -4
  37. package/dist/adapters/latex/headings.js.map +1 -1
  38. package/dist/adapters/latex/index.d.ts +1 -0
  39. package/dist/adapters/latex/index.d.ts.map +1 -1
  40. package/dist/adapters/latex/index.js +3 -0
  41. package/dist/adapters/latex/index.js.map +1 -1
  42. package/dist/adapters/latex/parse.d.ts +15 -0
  43. package/dist/adapters/latex/parse.d.ts.map +1 -1
  44. package/dist/adapters/latex/parse.js +64 -1
  45. package/dist/adapters/latex/parse.js.map +1 -1
  46. package/dist/adapters/node/list-entries.io.d.ts.map +1 -1
  47. package/dist/adapters/node/list-entries.io.js +3 -1
  48. package/dist/adapters/node/list-entries.io.js.map +1 -1
  49. package/dist/cli.d.ts.map +1 -1
  50. package/dist/cli.js +20 -8
  51. package/dist/cli.js.map +1 -1
  52. package/dist/cycle-rules.d.ts.map +1 -1
  53. package/dist/cycle-rules.js +3 -4
  54. package/dist/cycle-rules.js.map +1 -1
  55. package/dist/domain/deadline.d.ts +8 -1
  56. package/dist/domain/deadline.d.ts.map +1 -1
  57. package/dist/domain/deadline.js +26 -12
  58. package/dist/domain/deadline.js.map +1 -1
  59. package/dist/domain/decide-first.d.ts +11 -1
  60. package/dist/domain/decide-first.d.ts.map +1 -1
  61. package/dist/domain/decide-first.js +6 -0
  62. package/dist/domain/decide-first.js.map +1 -1
  63. package/dist/domain/index-columns.d.ts.map +1 -1
  64. package/dist/domain/index-columns.js +2 -0
  65. package/dist/domain/index-columns.js.map +1 -1
  66. package/dist/domain/portal-token.d.ts +44 -0
  67. package/dist/domain/portal-token.d.ts.map +1 -0
  68. package/dist/domain/portal-token.js +32 -0
  69. package/dist/domain/portal-token.js.map +1 -0
  70. package/dist/domain/study-registry.d.ts +65 -8
  71. package/dist/domain/study-registry.d.ts.map +1 -1
  72. package/dist/domain/study-registry.js +63 -19
  73. package/dist/domain/study-registry.js.map +1 -1
  74. package/dist/domain/submission.d.ts +30 -0
  75. package/dist/domain/submission.d.ts.map +1 -1
  76. package/dist/domain/submission.js +68 -0
  77. package/dist/domain/submission.js.map +1 -1
  78. package/dist/lib/paper-config.d.ts +1 -1
  79. package/dist/lib/paper-config.d.ts.map +1 -1
  80. package/dist/lib/paper-config.js +6 -4
  81. package/dist/lib/paper-config.js.map +1 -1
  82. package/dist/outputs-before-decision-rule.d.ts +1 -1
  83. package/dist/outputs-before-decision-rule.d.ts.map +1 -1
  84. package/dist/outputs-before-decision-rule.js +21 -17
  85. package/dist/outputs-before-decision-rule.js.map +1 -1
  86. package/dist/paper-settings.d.ts +3 -1
  87. package/dist/paper-settings.d.ts.map +1 -1
  88. package/dist/paper-settings.js +11 -5
  89. package/dist/paper-settings.js.map +1 -1
  90. package/dist/ports/latex.d.ts +23 -0
  91. package/dist/ports/latex.d.ts.map +1 -1
  92. package/dist/ports/list-entries.d.ts +7 -4
  93. package/dist/ports/list-entries.d.ts.map +1 -1
  94. package/dist/ports/study-deps.d.ts +14 -0
  95. package/dist/ports/study-deps.d.ts.map +1 -0
  96. package/dist/ports/study-deps.js +2 -0
  97. package/dist/ports/study-deps.js.map +1 -0
  98. package/dist/ports/study-folder.d.ts +43 -0
  99. package/dist/ports/study-folder.d.ts.map +1 -0
  100. package/dist/ports/study-folder.js +2 -0
  101. package/dist/ports/study-folder.js.map +1 -0
  102. package/dist/ports/submission-portal.d.ts +39 -2
  103. package/dist/ports/submission-portal.d.ts.map +1 -1
  104. package/dist/ports/venue-deadlines.d.ts +1 -1
  105. package/dist/presets.d.ts +1 -2
  106. package/dist/presets.d.ts.map +1 -1
  107. package/dist/presets.js +1 -2
  108. package/dist/presets.js.map +1 -1
  109. package/dist/studies.d.ts.map +1 -1
  110. package/dist/studies.js +10 -7
  111. package/dist/studies.js.map +1 -1
  112. package/dist/study-folder.d.ts +14 -0
  113. package/dist/study-folder.d.ts.map +1 -0
  114. package/dist/study-folder.js +123 -0
  115. package/dist/study-folder.js.map +1 -0
  116. package/dist/study-gate.d.ts +1 -1
  117. package/dist/study-gate.d.ts.map +1 -1
  118. package/dist/study-gate.js +65 -28
  119. package/dist/study-gate.js.map +1 -1
  120. package/dist/study-index-input.d.ts +1 -1
  121. package/dist/study-index-input.d.ts.map +1 -1
  122. package/dist/study-index-input.js +8 -3
  123. package/dist/study-index-input.js.map +1 -1
  124. package/dist/study-modes.d.ts +38 -27
  125. package/dist/study-modes.d.ts.map +1 -1
  126. package/dist/study-modes.js +42 -53
  127. package/dist/study-modes.js.map +1 -1
  128. package/dist/study-registry-rule.d.ts +2 -6
  129. package/dist/study-registry-rule.d.ts.map +1 -1
  130. package/dist/study-registry-rule.js +32 -41
  131. package/dist/study-registry-rule.js.map +1 -1
  132. package/dist/submission.d.ts +49 -11
  133. package/dist/submission.d.ts.map +1 -1
  134. package/dist/submission.js +332 -44
  135. package/dist/submission.js.map +1 -1
  136. package/docs/configuration.md +2 -1
  137. package/docs/design/study-modes.md +46 -28
  138. package/docs/rules/cycle/record.md +9 -6
  139. package/docs/rules/repro/outputs-before-decision.md +3 -0
  140. package/docs/rules/repro/study-registered.md +3 -2
  141. package/docs/rules/tex/heading-case.md +1 -1
  142. package/docs/submission.md +47 -48
  143. package/eslint.config.mjs +39 -24
  144. package/lib/paper-config.ts +7 -4
  145. package/package.json +6 -1
  146. package/presets/msr.jsonc +9 -7
  147. package/presets/msr.md +14 -10
  148. package/scripts/check.ts +1 -1
  149. package/scripts/refresh-deadlines/compare.test.ts +75 -0
  150. package/scripts/refresh-deadlines/compare.ts +101 -0
  151. package/scripts/refresh-deadlines/main.test.ts +140 -0
  152. package/scripts/refresh-deadlines/main.ts +56 -0
  153. package/scripts/refresh-deadlines/refresh.test.ts +287 -0
  154. package/scripts/refresh-deadlines/refresh.ts +183 -0
  155. package/skills/grade-paper-writing/SKILL.md +4 -2
  156. package/skills/grade-paper-writing/SKILL.md.spec.ts +3 -1
  157. package/skills/grade-paper-writing/__snapshots__/prose-lint.test.ts.snap +16 -3
  158. package/skills/grade-paper-writing/prose-lint.mjs +127 -95
  159. package/skills/grade-paper-writing/prose-lint.test.ts +119 -10
  160. package/skills/submission-portal/SKILL.md +60 -44
  161. package/skills/submission-portal/SKILL.md.spec.ts +62 -43
  162. package/skills/submission-portal/submission-portal.test.ts +4 -73
  163. package/src/CLAUDE.md +7 -4
  164. package/src/CLAUDE.md.spec.ts +6 -3
  165. package/src/adapters/hotcrp/cassette/README.md +4 -4
  166. package/src/adapters/hotcrp/cassette/deadlines-msr2027.html +9 -9
  167. package/src/adapters/hotcrp/deadlines.io.test.ts +2 -2
  168. package/src/adapters/hotcrp/deadlines.test.ts +3 -3
  169. package/src/adapters/hotcrp/index.ts +15 -3
  170. package/src/adapters/hotcrp/portal.io.ts +61 -17
  171. package/src/adapters/hotcrp/portal.test.ts +105 -1
  172. package/src/adapters/hotcrp/response.ts +21 -0
  173. package/src/adapters/hotcrp/site.ts +34 -0
  174. package/src/adapters/hotcrp/token.test.ts +69 -0
  175. package/src/adapters/hotcrp/token.ts +51 -0
  176. package/src/adapters/latex/abstract.test.ts +280 -0
  177. package/src/adapters/latex/abstract.ts +272 -0
  178. package/src/adapters/latex/captions.test.ts +57 -0
  179. package/src/adapters/latex/captions.ts +56 -0
  180. package/src/adapters/latex/headings.ts +5 -4
  181. package/src/adapters/latex/index.test.ts +31 -1
  182. package/src/adapters/latex/index.ts +3 -0
  183. package/src/adapters/latex/parse.ts +71 -3
  184. package/src/adapters/node/list-entries.io.ts +2 -1
  185. package/src/adapters/node/list-entries.test.ts +18 -0
  186. package/src/cli.test.ts +20 -8
  187. package/src/cli.ts +22 -13
  188. package/src/cycle-rules.test.ts +6 -6
  189. package/src/cycle-rules.ts +7 -4
  190. package/src/domain/deadline.test.ts +31 -2
  191. package/src/domain/deadline.ts +42 -16
  192. package/src/domain/decide-first.test.ts +33 -0
  193. package/src/domain/decide-first.ts +16 -1
  194. package/src/domain/index-columns.test.ts +49 -4
  195. package/src/domain/index-columns.ts +2 -0
  196. package/src/domain/portal-token.test.ts +55 -0
  197. package/src/domain/portal-token.ts +63 -0
  198. package/src/domain/study-measurements.test.ts +7 -3
  199. package/src/domain/study-registry.test.ts +34 -6
  200. package/src/domain/study-registry.ts +123 -31
  201. package/src/domain/submission.test.ts +88 -0
  202. package/src/domain/submission.ts +99 -0
  203. package/src/new-paper.test.ts +1 -0
  204. package/src/outputs-before-decision-rule.test.ts +47 -2
  205. package/src/outputs-before-decision-rule.ts +31 -22
  206. package/src/paper-settings.test.ts +20 -0
  207. package/src/paper-settings.ts +17 -5
  208. package/src/ports/latex.ts +25 -0
  209. package/src/ports/list-entries.ts +7 -4
  210. package/src/ports/study-deps.ts +14 -0
  211. package/src/ports/study-folder.ts +38 -0
  212. package/src/ports/submission-portal.ts +43 -1
  213. package/src/ports/venue-deadlines.ts +1 -1
  214. package/src/presets.test.ts +8 -5
  215. package/src/presets.ts +1 -2
  216. package/src/studies-index-modes.test.ts +2 -2
  217. package/src/studies.ts +19 -10
  218. package/src/study-folder.test.ts +237 -0
  219. package/src/study-folder.ts +176 -0
  220. package/src/study-gate.test.ts +158 -7
  221. package/src/study-gate.ts +127 -54
  222. package/src/study-index-input.ts +12 -4
  223. package/src/study-modes.ts +67 -80
  224. package/src/study-registry-rule.test.ts +87 -0
  225. package/src/study-registry-rule.ts +58 -66
  226. package/src/submission-new.test.ts +569 -0
  227. package/src/submission-show.test.ts +210 -0
  228. package/src/submission-update.test.ts +160 -0
  229. package/src/submission.test.ts +140 -518
  230. package/src/submission.ts +494 -61
  231. package/scripts/refresh-deadlines.test.ts +0 -431
  232. package/scripts/refresh-deadlines.ts +0 -387
@@ -1 +1 @@
1
- {"version":3,"file":"study-registry-rule.js","sourceRoot":"","sources":["../src/study-registry-rule.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"study-registry-rule.js","sourceRoot":"","sources":["../src/study-registry-rule.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,23 @@
1
1
  import { type Result } from "./domain/result.ts";
2
2
  import { type Sha256 } from "./domain/sha256.ts";
3
- import { type PortalFailure, type SubmissionView, type SupportedPortal, type UpdateOutcome } from "./domain/submission.ts";
3
+ import { type Author, type CreateOutcome, type PortalFailure, type SubmissionView, type SupportedPortal, type UpdateOutcome } from "./domain/submission.ts";
4
4
  import type { Files } from "./ports/files.ts";
5
- import type { SubmissionPortal } from "./ports/submission-portal.ts";
5
+ import type { PortalSite } from "./ports/submission-portal.ts";
6
6
  import { type PresetDeps } from "./presets.ts";
7
7
  import { type InForce } from "./domain/deadline.ts";
8
- /** The environment variable each portal kind's token is read from. */
9
- export declare const TOKEN_ENV: Readonly<Record<SupportedPortal["kind"], string>>;
10
- export declare const SUBCOMMANDS: readonly ["show", "update"];
8
+ import { type TokenProblem } from "./domain/portal-token.ts";
9
+ import type { LatexReader } from "./ports/latex.ts";
10
+ import type { SourcesCodec } from "./ports/sources-codec.ts";
11
+ /** How to make and set the site's token: the page, the scopes, the variable. Pure. */
12
+ export declare function tokenSteps(portal: SupportedPortal, site: PortalSite, variable: string): readonly string[];
13
+ /** Why there is no token, as the complete instruction the author follows. Pure. */
14
+ export declare function tokenProblemLines(portal: SupportedPortal, site: PortalSite, p: TokenProblem): readonly string[];
15
+ /**
16
+ * What to do when the portal turned the token away: 401 is "this site does not know the token", 403
17
+ * a token without the scope — both answered with the site's token page. Empty for anything else. Pure.
18
+ */
19
+ export declare function tokenRefusedLines(portal: SupportedPortal, site: PortalSite, f: PortalFailure): readonly string[];
20
+ export declare const SUBCOMMANDS: readonly ["new", "show", "update"];
11
21
  export type Subcommand = (typeof SUBCOMMANDS)[number];
12
22
  /** What one `submission` run was asked, after the command line. */
13
23
  export interface SubmissionArgs {
@@ -17,7 +27,10 @@ export interface SubmissionArgs {
17
27
  readonly extra: readonly string[];
18
28
  /** `--pdf <file>`, relative to `cwd`; null: the paper's own PDF. */
19
29
  readonly pdf: string | null;
20
- /** `--abstract <file>`, relative to `cwd`; null: leave the abstract as it is. */
30
+ /**
31
+ * `--abstract <file>`, relative to `cwd`; null: `update` leaves the abstract as it is, `new` reads
32
+ * it from the build.
33
+ */
21
34
  readonly abstract: string | null;
22
35
  readonly submit: boolean;
23
36
  readonly save: boolean;
@@ -28,14 +41,26 @@ export interface SubmissionDeps {
28
41
  readonly cwd: string;
29
42
  /** The value of an environment variable; the root reads the environment. */
30
43
  readonly env: (name: string) => string | undefined;
31
- readonly portalFor: (p: SupportedPortal, token: string) => SubmissionPortal;
44
+ /** The portal site of a supported kind: its token variable and help, and its API once there is a token. */
45
+ readonly site: (p: SupportedPortal) => PortalSite;
46
+ /** Reads the paper's `\title` and its abstract, its includes spliced in (`new`). */
47
+ readonly latex: LatexReader;
48
+ /** Reads the build's record of the files TeX read, for the includes (`new`). */
49
+ readonly codec: SourcesCodec;
32
50
  readonly log: (line: string) => void;
33
51
  readonly err: (line: string) => void;
34
52
  }
35
53
  /** A paper's portal, its submission there, and the PDF the paper builds. */
36
54
  export interface SubmissionTarget {
37
55
  readonly portal: SupportedPortal;
38
- readonly id: number;
56
+ /** The paper's submission on the portal; null before `new` created one. */
57
+ readonly id: number | null;
58
+ /** The paper's `paperlint.json`, absolute. */
59
+ readonly config: string;
60
+ /** The authors the paper declares for the portal; null when it declares none. */
61
+ readonly authors: readonly Author[] | null;
62
+ /** The cycle attempt is accepted: a new submission belongs to a new cycle. */
63
+ readonly accepted: boolean;
39
64
  /** The paper's built PDF, absolute. */
40
65
  readonly pdf: string;
41
66
  /** The venue's call for papers (the preset's `url`); null when the preset names no venue. */
@@ -48,8 +73,6 @@ export interface SubmissionTarget {
48
73
  }
49
74
  /** The paper directory → its portal and submission, or the line naming the file and key to set. */
50
75
  export declare function submissionTarget(paperDir: string, deps: PresetDeps): Result<SubmissionTarget, string>;
51
- /** The token from the environment, or the line naming the variable and where to get one. */
52
- export declare function tokenFor(portal: SupportedPortal, env: (name: string) => string | undefined): Result<string, string>;
53
76
  /** A failure in words: HTTP status and the portal's own messages. Never the token. */
54
77
  export declare function failureText(f: PortalFailure): string;
55
78
  /** One deadline in force, what set it, and the other readings of it. Pure. */
@@ -70,8 +93,23 @@ export declare function updateLines(o: UpdateOutcome, local: {
70
93
  readonly shown: string;
71
94
  readonly sha256: Sha256;
72
95
  }, save: boolean): readonly string[];
96
+ /**
97
+ * The title as the paper sets it: its `\title`, as text — or, when the title holds a command
98
+ * paperlint cannot read (a macro of the author's own), the PDF's own Title (`pdftitle`). Pure.
99
+ */
100
+ export declare function titleOf(source: {
101
+ readonly text: string;
102
+ /** Where an offset of `text` stands, as a message names it (file:line:column). */
103
+ readonly where: (offset: number) => string;
104
+ } | null, latex: Pick<LatexReader, "headings">, metadata: Readonly<Record<string, string>> | null): Result<string, string>;
105
+ /** What `new` will send, as the author reads it before saying yes. Pure. */
106
+ export declare function newLines(title: string, abstract: string, authors: readonly Author[]): readonly string[];
107
+ /** What the author does on the site after `new`: what paperlint does not send. Pure. */
108
+ export declare function onTheSiteLines(site: PortalSite, id: number | null, paperArg: string): readonly string[];
109
+ /** `new`'s report of the portal's answer. Pure. */
110
+ export declare function createLines(o: CreateOutcome, save: boolean): readonly string[];
73
111
  /** Why the command line cannot be run as asked; null when it can. Pure. */
74
112
  export declare function usageProblem(a: SubmissionArgs): string | null;
75
- /** `paperlint submission <show|update> [paper-dir]` — exit 0, 1 (the portal said no), or 2 (usage). */
113
+ /** `paperlint submission <new|show|update> [paper-dir]` — exit 0, 1 (the portal said no), or 2 (usage). */
76
114
  export declare function runSubmission(a: SubmissionArgs, deps: SubmissionDeps): Promise<number>;
77
115
  //# sourceMappingURL=submission.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"submission.d.ts","sourceRoot":"","sources":["../src/submission.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"submission.d.ts","sourceRoot":"","sources":["../src/submission.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAW,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAa,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAIL,KAAK,MAAM,EACX,KAAK,aAAa,EAElB,KAAK,aAAa,EAElB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EACV,UAAU,EAEX,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAIL,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAGL,KAAK,OAAO,EACb,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAIpD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAG7D,sFAAsF;AACtF,wBAAgB,UAAU,CACxB,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,GACf,SAAS,MAAM,EAAE,CAOnB;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,UAAU,EAChB,CAAC,EAAE,YAAY,GACd,SAAS,MAAM,EAAE,CAMnB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,UAAU,EAChB,CAAC,EAAE,aAAa,GACf,SAAS,MAAM,EAAE,CASnB;AAED,eAAO,MAAM,WAAW,oCAAqC,CAAC;AAC9D,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAItD,mEAAmE;AACnE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,oEAAoE;IACpE,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACnD,2GAA2G;IAC3G,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,eAAe,KAAK,UAAU,CAAC;IAClD,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,gFAAgF;IAChF,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,4EAA4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,2EAA2E;IAC3E,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAC3C,8EAA8E;IAC9E,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,6FAA6F;IAC7F,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,OAAO,EAAE,CAAC;CACxC;AA6CD,mGAAmG;AACnG,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,UAAU,GACf,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAWlC;AAQD,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,CAAC,EAAE,aAAa,GAAG,MAAM,CAWpD;AAkBD,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAa/C;AAED,6BAA6B;AAC7B,wBAAgB,SAAS,CACvB,CAAC,EAAE,gBAAgB,EACnB,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAChE,SAAS,MAAM,EAAE,CAcnB;AAED;;;;GAIG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,EAAE,MAAM,MAAM,GAAG,IAAI,KAAG,MACoS,CAAC;AAEvW,+BAA+B;AAC/B,wBAAgB,WAAW,CACzB,CAAC,EAAE,aAAa,EAChB,KAAK,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC1D,IAAI,EAAE,OAAO,GACZ,SAAS,MAAM,EAAE,CAcnB;AAgKD;;;GAGG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE;IACN,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;CAC5C,GAAG,IAAI,EACR,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,EACpC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,GAChD,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqBxB;AAgBD,4EAA4E;AAC5E,wBAAgB,QAAQ,CACtB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,SAAS,MAAM,EAAE,CAUnB;AAED,wFAAwF;AACxF,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,EAAE,EAAE,MAAM,GAAG,IAAI,EACjB,QAAQ,EAAE,MAAM,GACf,SAAS,MAAM,EAAE,CAMnB;AAED,mDAAmD;AACnD,wBAAgB,WAAW,CACzB,CAAC,EAAE,aAAa,EAChB,IAAI,EAAE,OAAO,GACZ,SAAS,MAAM,EAAE,CAanB;AA+KD,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,CAAC,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CAW7D;AAqBD,2GAA2G;AAC3G,wBAAsB,aAAa,CACjC,CAAC,EAAE,cAAc,EACjB,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,MAAM,CAAC,CAwBjB"}
@@ -17,22 +17,50 @@
17
17
  */
18
18
  import { basename, join, resolve } from "node:path";
19
19
  import { absolutePath } from "./domain/paths.js";
20
+ import { messageOf } from "./domain/text.js";
20
21
  import { err, ok } from "./domain/result.js";
21
22
  import { sha256Hex } from "./domain/sha256.js";
22
- import { supportedPortal, wordCount, } from "./domain/submission.js";
23
+ import { supportedPortal, withSubmissionId, wordCount, } from "./domain/submission.js";
23
24
  import { paperPreset, unusablePresetLine, } from "./presets.js";
24
25
  import { currentDeadlines } from "./domain/cycle.js";
25
- import { deadlinesInForce, } from "./domain/deadline.js";
26
+ import { deadlinesInForce, readingText, } from "./domain/deadline.js";
26
27
  import { CONFIG_FILE } from "#lib/paper-config";
27
- /** The environment variable each portal kind's token is read from. */
28
- export const TOKEN_ENV = {
29
- hotcrp: "HOTCRP_TOKEN",
30
- };
31
- /** Where each portal kind lets an author create a token. */
32
- const TOKEN_HELP = {
33
- hotcrp: "create one on the HotCRP site under Account settings → Developer, with the scopes submeta:read and document:read (show) and submeta:write and document:write (update)",
34
- };
35
- export const SUBCOMMANDS = ["show", "update"];
28
+ import { hostOf, lookUpToken, } from "./domain/portal-token.js";
29
+ import { LINE_BREAK, OPAQUE, runText } from "./domain/tex-document.js";
30
+ import { factsPath, parseFactsText } from "./facts-file.js";
31
+ import { lineColumn, readPaper } from "./tex-paper.js";
32
+ import { originOf } from "./domain/paper-source.js";
33
+ import { MAIN } from "./build.js";
34
+ /** How to make and set the site's token: the page, the scopes, the variable. Pure. */
35
+ export function tokenSteps(portal, site, variable) {
36
+ const c = site.credentials;
37
+ return [
38
+ ` 1. create a token on this site: ${c.page} (${c.where}), with the scopes ${c.scopes}`,
39
+ ` 2. set it in your environment — never paste it into a chat: export ${variable}=<the token>`,
40
+ ` tokens are per ${portal.kind} site: ${variable} is read for ${hostOf(portal.url)} alone, so two venues take two variables`,
41
+ ];
42
+ }
43
+ /** Why there is no token, as the complete instruction the author follows. Pure. */
44
+ export function tokenProblemLines(portal, site, p) {
45
+ const head = p.kind === "missing"
46
+ ? `no ${portal.kind} token for ${portal.url}: ${p.variable} is not set`
47
+ : `${p.siteLess} is no longer read: tokens are per ${portal.kind} site. If it was made on ${hostOf(portal.url)}, rename it to ${p.variable}; if it was made on another site, rename it to that site's variable (${site.variablePattern}) and create a token here:`;
48
+ return [head, ...tokenSteps(portal, site, p.variable)];
49
+ }
50
+ /**
51
+ * What to do when the portal turned the token away: 401 is "this site does not know the token", 403
52
+ * a token without the scope — both answered with the site's token page. Empty for anything else. Pure.
53
+ */
54
+ export function tokenRefusedLines(portal, site, f) {
55
+ if (f.kind !== "refused" || (f.httpStatus !== 401 && f.httpStatus !== 403))
56
+ return [];
57
+ const variable = site.tokenVariable;
58
+ const why = f.httpStatus === 401
59
+ ? `${variable} was used; it may belong to another ${portal.kind} site (tokens are per site), or be revoked or expired`
60
+ : `${variable} was used; the site turned the request away — the token may lack a scope this subcommand needs`;
61
+ return [why, ...tokenSteps(portal, site, variable)];
62
+ }
63
+ export const SUBCOMMANDS = ["new", "show", "update"];
36
64
  const isSubcommand = (s) => SUBCOMMANDS.some((x) => x === s);
37
65
  const configOf = (dir) => join(dir, CONFIG_FILE);
38
66
  /** Why a paper without a venue preset has no portal: the key to set, or — with cycles — where. */
@@ -44,9 +72,6 @@ function targetOf(paperDir, p) {
44
72
  const declared = p.preset.portal;
45
73
  if (declared === null)
46
74
  return err(`the venue preset declares no "portal" (read: ${p.preset.chain.join(", ")}) — add "portal": { "kind": "hotcrp", "url": "<the site>" } to the venue's preset, or upload by hand`);
47
- const sub = p.settings.submission;
48
- if (sub === null)
49
- return err(`${configOf(paperDir)}: no "submission" — add "submission": { "id": <the submission number on ${declared.url}> }`);
50
75
  const portal = supportedPortal(declared);
51
76
  if (!portal.ok)
52
77
  return portal;
@@ -57,7 +82,16 @@ function targetOf(paperDir, p) {
57
82
  ? []
58
83
  : currentDeadlines(p.settings.cycles.current);
59
84
  const deadlines = deadlinesInForce(own, p.preset.deadlines);
60
- return ok({ portal: portal.value, id: sub.id, pdf, call, deadlines });
85
+ return ok({
86
+ portal: portal.value,
87
+ id: p.settings.submission?.id ?? null,
88
+ config: configOf(paperDir),
89
+ authors: p.settings.authors,
90
+ accepted: p.settings.cycles?.current.kind === "accepted",
91
+ pdf,
92
+ call,
93
+ deadlines,
94
+ });
61
95
  }
62
96
  /** The paper directory → its portal and submission, or the line naming the file and key to set. */
63
97
  export function submissionTarget(paperDir, deps) {
@@ -72,14 +106,6 @@ export function submissionTarget(paperDir, deps) {
72
106
  return targetOf(paperDir, p);
73
107
  }
74
108
  }
75
- /** The token from the environment, or the line naming the variable and where to get one. */
76
- export function tokenFor(portal, env) {
77
- const name = TOKEN_ENV[portal.kind];
78
- const v = env(name)?.trim();
79
- return v
80
- ? ok(v)
81
- : err(`${name} is not set — the ${portal.kind} API needs a token: ${TOKEN_HELP[portal.kind]}. Then: export ${name}=…`);
82
- }
83
109
  const iso = (seconds) => seconds === null ? "—" : new Date(seconds * 1000).toISOString();
84
110
  const messageLine = (m) => ` portal says: ${m.field === null ? "" : `${m.field}: `}${m.message}`;
85
111
  /** A failure in words: HTTP status and the portal's own messages. Never the token. */
@@ -110,18 +136,17 @@ function matchLine(view, local) {
110
136
  const pdfLine = (view) => view.pdf === null
111
137
  ? "portal PDF none"
112
138
  : `portal PDF ${view.pdf.hash}, ${view.pdf.size === null ? "?" : String(view.pdf.size)} bytes, uploaded ${iso(view.pdf.uploadedAt)}`;
113
- const readingText = (o) => `${o.source} ${o.at}, read ${o.read}`;
114
139
  /** One deadline in force, what set it, and the other readings of it. Pure. */
115
140
  export function deadlineLine(d) {
116
141
  const by = d.by;
117
- const why = by.kind === "override"
118
- ? `override: ${by.override.reason} (${by.override.evidence})`
119
- : `${by.reading.source}, read ${by.reading.read}`;
142
+ const set = by.kind === "override"
143
+ ? `${d.at} — override: ${by.override.reason} (${by.override.evidence})`
144
+ : readingText(by.reading);
120
145
  const others = d.readings.filter((r) => by.kind === "override" || r !== by.reading);
121
146
  const also = others.length
122
147
  ? `; also ${others.map(readingText).join("; ")}`
123
148
  : "";
124
- return `deadline ${d.what} ${d.at} — ${why}${also}`;
149
+ return `deadline ${d.what} ${set}${also}`;
125
150
  }
126
151
  /** `show`'s report. Pure. */
127
152
  export function showLines(t, view, local) {
@@ -164,11 +189,22 @@ export function updateLines(o, local, save) {
164
189
  const shownPath = (cwd, p) => p.startsWith(`${cwd}/`) ? p.slice(cwd.length + 1) : p;
165
190
  /** The file's bytes, or null when there is none. */
166
191
  const bytesAt = (files, p) => files.readBytes(absolutePath(p));
192
+ /** A failure printed — the portal's words, then what to do about the token if it was the token — exit 1. */
193
+ function failed(f, deps) {
194
+ [failureText(f), ...deps.refused(f)].forEach((l) => {
195
+ deps.err(l);
196
+ });
197
+ return 1;
198
+ }
199
+ /** The submission's id, or the line naming the key to set — `show` and `update` need one. */
200
+ const idOf = (t) => t.id === null
201
+ ? err(`${t.config}: no "submission" — add "submission": { "id": <the submission number on ${t.portal.url}> }, or create the submission with \`paperlint submission new\``)
202
+ : ok(t.id);
167
203
  /** `show`: read the submission and compare its PDF with the local one. */
168
204
  async function runShow(t, portal, pdfPath, deps) {
169
205
  const view = await portal.show(t.id);
170
206
  if (!view.ok)
171
- return (deps.err(failureText(view.error)), 1);
207
+ return failed(view.error, deps);
172
208
  const bytes = bytesAt(deps.files, pdfPath);
173
209
  const local = {
174
210
  shown: shownPath(deps.cwd, pdfPath),
@@ -210,7 +246,7 @@ async function runUpdate(t, portal, a, deps) {
210
246
  save: a.save,
211
247
  });
212
248
  if (!r.ok)
213
- return (deps.err(failureText(r.error)), 1);
249
+ return failed(r.error, deps);
214
250
  const local = { shown, sha256: sha256Hex(bytes) };
215
251
  updateLines(r.value, local, a.save).forEach((l) => {
216
252
  deps.log(l);
@@ -218,22 +254,262 @@ async function runUpdate(t, portal, a, deps) {
218
254
  const fine = r.value.valid && r.value.httpStatus >= 200 && r.value.httpStatus < 300;
219
255
  return fine ? 0 : 1;
220
256
  }
257
+ // ── new ──────────────────────────────────────────────────────────────────────────────
258
+ /**
259
+ * The metadata of the PDF that is sent, from the build's facts — the title's fallback; null when
260
+ * there are no facts, or they describe another PDF.
261
+ */
262
+ function pdfMetadata(paperDir, pdf, deps) {
263
+ const bytes = bytesAt(deps.files, factsPath(paperDir));
264
+ const facts = bytes === null ? null : parseFactsText(new TextDecoder().decode(bytes));
265
+ return facts?.ok === true && facts.value.sha === sha256Hex(pdf)
266
+ ? facts.value.text.metadata
267
+ : null;
268
+ }
269
+ /** Where an offset of the assembled paper stands in its own file: `file:line:column`. */
270
+ function placeIn(paper, offset) {
271
+ const o = originOf(paper, { start: offset, end: offset });
272
+ return o === null ? MAIN : `${o.file}:${lineColumn(o.source, o.span.start)}`;
273
+ }
274
+ /**
275
+ * The abstract from the paper's source: its `abstract` environment, with the files it includes
276
+ * spliced in as the build recorded them, as plain text — or why it cannot be read without guessing.
277
+ */
278
+ function sourceAbstract(paper, deps) {
279
+ const instead = "give the abstract with --abstract <file>, a plain-text file";
280
+ if (paper === null)
281
+ return err(`no ${MAIN} to read the abstract from — ${instead}`);
282
+ const r = deps.latex.abstractText(paper.text);
283
+ if (r.ok)
284
+ return r;
285
+ const guess = "paperlint sends no text it would have to guess";
286
+ switch (r.error.kind) {
287
+ case "none":
288
+ return err(`${MAIN} has no \\begin{abstract}…\\end{abstract} — ${instead}`);
289
+ case "unreadable":
290
+ return err(`the abstract, ${placeIn(paper, r.error.at)}: ${r.error.what} — ${guess}; ${instead}`);
291
+ case "redefined":
292
+ return err(`the abstract uses \\${r.error.name}, which the paper defines ${String(r.error.at.length)} times (${r.error.at.map((o) => placeIn(paper, o)).join(", ")}) — which one TeX uses there is not guessed; ${instead}`);
293
+ }
294
+ }
295
+ /**
296
+ * The title as the paper sets it: its `\title`, as text — or, when the title holds a command
297
+ * paperlint cannot read (a macro of the author's own), the PDF's own Title (`pdftitle`). Pure.
298
+ */
299
+ export function titleOf(source, latex, metadata) {
300
+ const titles = (source === null ? [] : latex.headings(source.text)).filter((h) => h.command.kind === "title" && h.argument === "title");
301
+ // One \title is read; several are not chosen between — the PDF's own Title stands in, or the fix.
302
+ const [heading] = titles.length === 1 ? titles : [];
303
+ const text = heading === undefined
304
+ ? ""
305
+ : runText(heading.title)
306
+ .replaceAll(LINE_BREAK, " ")
307
+ .replace(/\s+/g, " ")
308
+ .trim();
309
+ if (text !== "" && !text.includes(OPAQUE))
310
+ return ok(text);
311
+ const pdfTitle = pdfTitleOf(metadata);
312
+ if (pdfTitle !== "")
313
+ return ok(pdfTitle);
314
+ return err(titles.length > 1
315
+ ? `the paper sets \\title ${String(titles.length)} times (${titles.map((h) => source?.where(h.title.segments[0].at)).join(", ")}), and the PDF names no Title — which one to send is not guessed: keep one \\title, or set \\hypersetup{pdftitle={<the title as plain text>}} and rebuild`
316
+ : noReadableTitle(text));
317
+ }
318
+ /** The Info dictionary's Title, else the XMP packet's dc:title (pdf-content.ts keeps both); "" for none. */
319
+ const pdfTitleOf = (metadata) => [metadata?.["Title"], metadata?.["dc:title"]]
320
+ .map((t) => t?.trim() ?? "")
321
+ .find((t) => t !== "") ?? "";
322
+ /** The fix when the one \\title is missing (`text` "") or holds a command paperlint does not read. */
323
+ const noReadableTitle = (text) => text === ""
324
+ ? `no \\title in ${MAIN}, and the PDF names no Title — add \\title{…}, or \\hypersetup{pdftitle={…}}, and rebuild`
325
+ : `the \\title in ${MAIN} uses a command paperlint does not read («${text.replaceAll(OPAQUE, "…")}»), and the PDF names no Title — set \\hypersetup{pdftitle={<the title as plain text>}} and rebuild`;
326
+ /** What `new` will send, as the author reads it before saying yes. Pure. */
327
+ export function newLines(title, abstract, authors) {
328
+ return [
329
+ `title ${title}`,
330
+ ...authors.map((a, i) => `author ${String(i + 1).padEnd(6)} ${a.name} <${a.email}>${a.affiliation === null ? "" : `, ${a.affiliation}`}`),
331
+ `abstract ${String(wordCount(abstract))} words:`,
332
+ ` ${abstract}`,
333
+ ];
334
+ }
335
+ /** What the author does on the site after `new`: what paperlint does not send. Pure. */
336
+ export function onTheSiteLines(site, id, paperArg) {
337
+ return [
338
+ `do on the site, ${site.submissionPage(id)} — paperlint sends only the title, the abstract, the authors and the PDF:`,
339
+ ...site.siteOnly.map((f) => ` - ${f}`),
340
+ ` - then mark it submitted: npx paperlint submission update ${paperArg} --submit (a dry run; --save after your yes)`,
341
+ ];
342
+ }
343
+ /** `new`'s report of the portal's answer. Pure. */
344
+ export function createLines(o, save) {
345
+ const mode = save
346
+ ? o.id === null
347
+ ? "NOTHING CREATED — the portal did not save it"
348
+ : `created submission ${String(o.id)}`
349
+ : "dry run — the portal checked the new submission and kept nothing; --save creates it for real";
350
+ return [
351
+ mode,
352
+ `HTTP ${String(o.httpStatus)}`,
353
+ `valid ${o.valid ? "yes" : "NO"}`,
354
+ `changes ${o.changes.length ? o.changes.join(", ") : "—"}`,
355
+ ...o.messages.map(messageLine),
356
+ ];
357
+ }
358
+ /** A file's JSON, or why there is none: gone, or not JSON. */
359
+ function jsonAt(files, path) {
360
+ const bytes = bytesAt(files, path);
361
+ if (bytes === null)
362
+ return err("the file is gone");
363
+ try {
364
+ return ok(JSON.parse(new TextDecoder().decode(bytes)));
365
+ }
366
+ catch (e) {
367
+ return err(`not JSON: ${messageOf(e)}`);
368
+ }
369
+ }
370
+ /** `paperlint.json` with the new id recorded in it, written; or why it was not. */
371
+ function recordId(config, id, deps) {
372
+ const json = jsonAt(deps.files, config);
373
+ if (!json.ok)
374
+ return json;
375
+ const next = withSubmissionId(json.value, id);
376
+ if (!next.ok)
377
+ return next;
378
+ // A write that fails (read-only, disk full) must not lose the id the portal just gave.
379
+ try {
380
+ deps.files.writeAtomic(absolutePath(config), new TextEncoder().encode(`${JSON.stringify(next.value, null, 2)}\n`));
381
+ return ok(null);
382
+ }
383
+ catch (e) {
384
+ return err(messageOf(e));
385
+ }
386
+ }
387
+ //** Why `new` cannot run for this paper, or the authors it sends: checked before anything is read. */
388
+ function readyForNew(t) {
389
+ if (t.id !== null)
390
+ return err(`${t.config}: the paper already has submission ${String(t.id)} on ${t.portal.url} — \`paperlint submission show\` reads it, \`paperlint submission update\` changes it`);
391
+ if (t.accepted)
392
+ return err(`${t.config}: the current attempt is accepted — a new submission belongs to a new cycle`);
393
+ return t.authors === null
394
+ ? err(`${t.config}: no "authors" — add "authors": [{ "name": "…", "email": "…", "affiliation": "…" }], every author in the paper's order, as ${hostOf(t.portal.url)} should record them; paperlint never guesses them`)
395
+ : ok(t.authors);
396
+ }
397
+ /** The paper as the build read it: paper.tex with the files it includes spliced in; null without one. */
398
+ function assembledPaper(paperDir, deps) {
399
+ const bytes = bytesAt(deps.files, join(paperDir, MAIN));
400
+ return bytes === null
401
+ ? null
402
+ : readPaper(join(paperDir, MAIN), new TextDecoder().decode(bytes), deps);
403
+ }
404
+ /** The title and the abstract: the paper's `\title`, and `--abstract`'s file or the source's abstract. */
405
+ function titleAndAbstract(a, pdf, deps) {
406
+ const own = abstractOf(a, deps);
407
+ if (!own.ok)
408
+ return own;
409
+ const paper = assembledPaper(a.paperDir, deps);
410
+ const metadata = pdfMetadata(a.paperDir, pdf, deps);
411
+ const title = titleOf(paper === null
412
+ ? null
413
+ : { text: paper.text, where: (o) => placeIn(paper, o) }, deps.latex, metadata);
414
+ if (!title.ok)
415
+ return title;
416
+ const abstract = own.value === null
417
+ ? sourceAbstract(paper, deps)
418
+ : ok(own.value.replace(/\s+/g, " "));
419
+ return abstract.ok
420
+ ? ok({ title: title.value, abstract: abstract.value })
421
+ : abstract;
422
+ }
423
+ /** What `new` sends, or the first line saying what is missing. */
424
+ function newSubmissionOf(t, a, deps) {
425
+ const authors = readyForNew(t);
426
+ if (!authors.ok)
427
+ return authors;
428
+ const shown = shownPath(deps.cwd, a.pdfPath);
429
+ const pdf = bytesAt(deps.files, a.pdfPath);
430
+ if (pdf === null)
431
+ return err(`no PDF at ${shown} — build the paper, or name one with --pdf`);
432
+ const text = titleAndAbstract(a, pdf, deps);
433
+ if (!text.ok)
434
+ return text;
435
+ const paper = {
436
+ ...text.value,
437
+ authors: authors.value,
438
+ pdf: { name: basename(a.pdfPath), bytes: pdf },
439
+ };
440
+ return ok({ paper, shown });
441
+ }
442
+ //** After a save that created one: the id written into `paperlint.json`, and the next command. */
443
+ function recordCreated(t, id, paperArg, deps) {
444
+ const config = shownPath(deps.cwd, t.config);
445
+ const recorded = recordId(t.config, id, deps);
446
+ if (!recorded.ok) {
447
+ deps.err(`submission ${String(id)} was created (${deps.portalSite.submissionPage(id)}), but ${config} was not changed (${recorded.error}) — add "submission": { "id": ${String(id)} } to the current attempt by hand`);
448
+ return 1;
449
+ }
450
+ deps.log(`recorded "submission": { "id": ${String(id)} } in ${config}`);
451
+ deps.log(`next npx paperlint submission show ${paperArg} — it should say "match yes"`);
452
+ return 0;
453
+ }
454
+ const logAll = (lines, deps) => {
455
+ lines.forEach((l) => {
456
+ deps.log(l);
457
+ });
458
+ };
459
+ /**
460
+ * `new`: create the paper's submission — title and abstract from the build, the authors the paper
461
+ * declares, the PDF. A dry run unless `--save`; after a save, the id goes into `paperlint.json`.
462
+ */
463
+ async function runNew(t, portal, a, deps) {
464
+ const n = newSubmissionOf(t, a, deps);
465
+ if (!n.ok)
466
+ return (deps.err(n.error), 2);
467
+ const { paper, shown } = n.value;
468
+ deps.log(checkPdfLine(shown, t.call));
469
+ logAll(newLines(paper.title, paper.abstract, paper.authors), deps);
470
+ const r = await portal.create(paper, { save: a.save });
471
+ if (!r.ok)
472
+ return failed(r.error, deps);
473
+ logAll(createLines(r.value, a.save), deps);
474
+ const fine = r.value.valid && r.value.httpStatus >= 200 && r.value.httpStatus < 300;
475
+ if (!fine || (a.save && r.value.id === null))
476
+ return 1;
477
+ const paperArg = a.paperDir === deps.cwd ? "." : shownPath(deps.cwd, a.paperDir);
478
+ logAll(onTheSiteLines(deps.portalSite, r.value.id, paperArg), deps);
479
+ return r.value.id === null ? 0 : recordCreated(t, r.value.id, paperArg, deps);
480
+ }
481
+ //** The flags that change something, as given. */
482
+ const writingFlags = (a) => [
483
+ a.abstract === null ? null : "--abstract",
484
+ a.submit ? "--submit" : null,
485
+ a.save ? "--save" : null,
486
+ ].filter((f) => f !== null);
221
487
  /** Why the command line cannot be run as asked; null when it can. Pure. */
222
488
  export function usageProblem(a) {
223
489
  if (!isSubcommand(a.sub))
224
490
  return `\`submission\` needs a subcommand: ${SUBCOMMANDS.join(" or ")} — got \`${a.sub ?? ""}\``;
225
491
  if (a.extra.length > 0)
226
492
  return `\`submission ${a.sub}\` takes one paper folder — got also \`${a.extra.join(" ")}\``;
227
- const updateOnly = [
228
- a.abstract === null ? null : "--abstract",
229
- a.submit ? "--submit" : null,
230
- a.save ? "--save" : null,
231
- ].filter((f) => f !== null);
232
- return a.sub === "show" && updateOnly.length > 0
233
- ? `${updateOnly.join(", ")}: only \`submission update\` changes anything; \`show\` reads`
493
+ const writing = writingFlags(a);
494
+ if (a.sub === "show" && writing.length > 0)
495
+ return `${writing.join(", ")}: only \`submission new\` and \`submission update\` change anything; \`show\` reads`;
496
+ return a.sub === "new" && a.submit
497
+ ? "--submit: `submission new` creates the submission; mark it submitted with `submission update --submit` once `show` says the portal holds this build"
234
498
  : null;
235
499
  }
236
- /** `paperlint submission <show|update> [paper-dir]` — exit 0, 1 (the portal said no), or 2 (usage). */
500
+ /** The variables a site's token lookup reads. */
501
+ const tokenNames = (site) => ({
502
+ variable: site.tokenVariable,
503
+ siteLess: site.siteLessVariable,
504
+ });
505
+ /** No token to use: the complete instruction, exit 2 — nothing is sent. */
506
+ function tokenMissing(portal, site, p, deps) {
507
+ tokenProblemLines(portal, site, p).forEach((l) => {
508
+ deps.err(l);
509
+ });
510
+ return 2;
511
+ }
512
+ /** `paperlint submission <new|show|update> [paper-dir]` — exit 0, 1 (the portal said no), or 2 (usage). */
237
513
  export async function runSubmission(a, deps) {
238
514
  const usage = usageProblem(a);
239
515
  if (usage !== null)
@@ -242,13 +518,25 @@ export async function runSubmission(a, deps) {
242
518
  const t = submissionTarget(paperDir, deps.presets);
243
519
  if (!t.ok)
244
520
  return (deps.err(t.error), 2);
245
- const token = tokenFor(t.value.portal, deps.env);
246
- if (!token.ok)
247
- return (deps.err(token.error), 2);
248
- const portal = deps.portalFor(t.value.portal, token.value);
521
+ const id = a.sub === "new" ? ok(null) : idOf(t.value);
522
+ if (!id.ok)
523
+ return (deps.err(id.error), 2);
524
+ const site = deps.site(t.value.portal);
525
+ const found = lookUpToken(tokenNames(site), deps.env);
526
+ if (!found.ok)
527
+ return tokenMissing(t.value.portal, site, found.error, deps);
528
+ const portal = site.connect(found.value.token);
249
529
  const pdfPath = a.pdf === null ? t.value.pdf : resolve(deps.cwd, a.pdf);
530
+ const withToken = {
531
+ ...deps,
532
+ portalSite: site,
533
+ refused: (f) => tokenRefusedLines(t.value.portal, site, f),
534
+ };
535
+ if (id.value === null)
536
+ return runNew(t.value, portal, { ...a, pdfPath, paperDir }, withToken);
537
+ const target = { ...t.value, id: id.value };
250
538
  return a.sub === "show"
251
- ? runShow(t.value, portal, pdfPath, deps)
252
- : runUpdate(t.value, portal, { ...a, pdfPath }, deps);
539
+ ? runShow(target, portal, pdfPath, withToken)
540
+ : runUpdate(target, portal, { ...a, pdfPath }, withToken);
253
541
  }
254
542
  //# sourceMappingURL=submission.js.map