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.
- package/.github/workflows/deadlines.yml +27 -7
- package/README.md +16 -15
- package/dist/CLAUDE.md.spec.d.ts.map +1 -1
- package/dist/CLAUDE.md.spec.js +6 -3
- package/dist/CLAUDE.md.spec.js.map +1 -1
- package/dist/adapters/hotcrp/index.d.ts +6 -4
- package/dist/adapters/hotcrp/index.d.ts.map +1 -1
- package/dist/adapters/hotcrp/index.js +6 -4
- package/dist/adapters/hotcrp/index.js.map +1 -1
- package/dist/adapters/hotcrp/portal.io.d.ts +3 -1
- package/dist/adapters/hotcrp/portal.io.d.ts.map +1 -1
- package/dist/adapters/hotcrp/portal.io.js +36 -11
- package/dist/adapters/hotcrp/portal.io.js.map +1 -1
- package/dist/adapters/hotcrp/response.d.ts +6 -1
- package/dist/adapters/hotcrp/response.d.ts.map +1 -1
- package/dist/adapters/hotcrp/response.js +17 -0
- package/dist/adapters/hotcrp/response.js.map +1 -1
- package/dist/adapters/hotcrp/site.d.ts +9 -0
- package/dist/adapters/hotcrp/site.d.ts.map +1 -0
- package/dist/adapters/hotcrp/site.js +22 -0
- package/dist/adapters/hotcrp/site.js.map +1 -0
- package/dist/adapters/hotcrp/token.d.ts +13 -0
- package/dist/adapters/hotcrp/token.d.ts.map +1 -0
- package/dist/adapters/hotcrp/token.js +48 -0
- package/dist/adapters/hotcrp/token.js.map +1 -0
- package/dist/adapters/latex/abstract.d.ts +22 -0
- package/dist/adapters/latex/abstract.d.ts.map +1 -0
- package/dist/adapters/latex/abstract.js +187 -0
- package/dist/adapters/latex/abstract.js.map +1 -0
- package/dist/adapters/latex/captions.d.ts +9 -0
- package/dist/adapters/latex/captions.d.ts.map +1 -0
- package/dist/adapters/latex/captions.js +40 -0
- package/dist/adapters/latex/captions.js.map +1 -0
- package/dist/adapters/latex/headings.d.ts +6 -0
- package/dist/adapters/latex/headings.d.ts.map +1 -1
- package/dist/adapters/latex/headings.js +5 -4
- package/dist/adapters/latex/headings.js.map +1 -1
- package/dist/adapters/latex/index.d.ts +1 -0
- package/dist/adapters/latex/index.d.ts.map +1 -1
- package/dist/adapters/latex/index.js +3 -0
- package/dist/adapters/latex/index.js.map +1 -1
- package/dist/adapters/latex/parse.d.ts +15 -0
- package/dist/adapters/latex/parse.d.ts.map +1 -1
- package/dist/adapters/latex/parse.js +64 -1
- package/dist/adapters/latex/parse.js.map +1 -1
- package/dist/adapters/node/list-entries.io.d.ts.map +1 -1
- package/dist/adapters/node/list-entries.io.js +3 -1
- package/dist/adapters/node/list-entries.io.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +20 -8
- package/dist/cli.js.map +1 -1
- package/dist/cycle-rules.d.ts.map +1 -1
- package/dist/cycle-rules.js +3 -4
- package/dist/cycle-rules.js.map +1 -1
- package/dist/domain/deadline.d.ts +8 -1
- package/dist/domain/deadline.d.ts.map +1 -1
- package/dist/domain/deadline.js +26 -12
- package/dist/domain/deadline.js.map +1 -1
- package/dist/domain/decide-first.d.ts +11 -1
- package/dist/domain/decide-first.d.ts.map +1 -1
- package/dist/domain/decide-first.js +6 -0
- package/dist/domain/decide-first.js.map +1 -1
- package/dist/domain/index-columns.d.ts.map +1 -1
- package/dist/domain/index-columns.js +2 -0
- package/dist/domain/index-columns.js.map +1 -1
- package/dist/domain/portal-token.d.ts +44 -0
- package/dist/domain/portal-token.d.ts.map +1 -0
- package/dist/domain/portal-token.js +32 -0
- package/dist/domain/portal-token.js.map +1 -0
- package/dist/domain/study-registry.d.ts +65 -8
- package/dist/domain/study-registry.d.ts.map +1 -1
- package/dist/domain/study-registry.js +63 -19
- package/dist/domain/study-registry.js.map +1 -1
- package/dist/domain/submission.d.ts +30 -0
- package/dist/domain/submission.d.ts.map +1 -1
- package/dist/domain/submission.js +68 -0
- package/dist/domain/submission.js.map +1 -1
- package/dist/lib/paper-config.d.ts +1 -1
- package/dist/lib/paper-config.d.ts.map +1 -1
- package/dist/lib/paper-config.js +6 -4
- package/dist/lib/paper-config.js.map +1 -1
- package/dist/outputs-before-decision-rule.d.ts +1 -1
- package/dist/outputs-before-decision-rule.d.ts.map +1 -1
- package/dist/outputs-before-decision-rule.js +21 -17
- package/dist/outputs-before-decision-rule.js.map +1 -1
- package/dist/paper-settings.d.ts +3 -1
- package/dist/paper-settings.d.ts.map +1 -1
- package/dist/paper-settings.js +11 -5
- package/dist/paper-settings.js.map +1 -1
- package/dist/ports/latex.d.ts +23 -0
- package/dist/ports/latex.d.ts.map +1 -1
- package/dist/ports/list-entries.d.ts +7 -4
- package/dist/ports/list-entries.d.ts.map +1 -1
- package/dist/ports/study-deps.d.ts +14 -0
- package/dist/ports/study-deps.d.ts.map +1 -0
- package/dist/ports/study-deps.js +2 -0
- package/dist/ports/study-deps.js.map +1 -0
- package/dist/ports/study-folder.d.ts +43 -0
- package/dist/ports/study-folder.d.ts.map +1 -0
- package/dist/ports/study-folder.js +2 -0
- package/dist/ports/study-folder.js.map +1 -0
- package/dist/ports/submission-portal.d.ts +39 -2
- package/dist/ports/submission-portal.d.ts.map +1 -1
- package/dist/ports/venue-deadlines.d.ts +1 -1
- package/dist/presets.d.ts +1 -2
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +1 -2
- package/dist/presets.js.map +1 -1
- package/dist/studies.d.ts.map +1 -1
- package/dist/studies.js +10 -7
- package/dist/studies.js.map +1 -1
- package/dist/study-folder.d.ts +14 -0
- package/dist/study-folder.d.ts.map +1 -0
- package/dist/study-folder.js +123 -0
- package/dist/study-folder.js.map +1 -0
- package/dist/study-gate.d.ts +1 -1
- package/dist/study-gate.d.ts.map +1 -1
- package/dist/study-gate.js +65 -28
- package/dist/study-gate.js.map +1 -1
- package/dist/study-index-input.d.ts +1 -1
- package/dist/study-index-input.d.ts.map +1 -1
- package/dist/study-index-input.js +8 -3
- package/dist/study-index-input.js.map +1 -1
- package/dist/study-modes.d.ts +38 -27
- package/dist/study-modes.d.ts.map +1 -1
- package/dist/study-modes.js +42 -53
- package/dist/study-modes.js.map +1 -1
- package/dist/study-registry-rule.d.ts +2 -6
- package/dist/study-registry-rule.d.ts.map +1 -1
- package/dist/study-registry-rule.js +32 -41
- package/dist/study-registry-rule.js.map +1 -1
- package/dist/submission.d.ts +49 -11
- package/dist/submission.d.ts.map +1 -1
- package/dist/submission.js +332 -44
- package/dist/submission.js.map +1 -1
- package/docs/configuration.md +2 -1
- package/docs/design/study-modes.md +46 -28
- package/docs/rules/cycle/record.md +9 -6
- package/docs/rules/repro/outputs-before-decision.md +3 -0
- package/docs/rules/repro/study-registered.md +3 -2
- package/docs/rules/tex/heading-case.md +1 -1
- package/docs/submission.md +47 -48
- package/eslint.config.mjs +39 -24
- package/lib/paper-config.ts +7 -4
- package/package.json +6 -1
- package/presets/msr.jsonc +9 -7
- package/presets/msr.md +14 -10
- package/scripts/check.ts +1 -1
- package/scripts/refresh-deadlines/compare.test.ts +75 -0
- package/scripts/refresh-deadlines/compare.ts +101 -0
- package/scripts/refresh-deadlines/main.test.ts +140 -0
- package/scripts/refresh-deadlines/main.ts +56 -0
- package/scripts/refresh-deadlines/refresh.test.ts +287 -0
- package/scripts/refresh-deadlines/refresh.ts +183 -0
- package/skills/grade-paper-writing/SKILL.md +4 -2
- package/skills/grade-paper-writing/SKILL.md.spec.ts +3 -1
- package/skills/grade-paper-writing/__snapshots__/prose-lint.test.ts.snap +16 -3
- package/skills/grade-paper-writing/prose-lint.mjs +127 -95
- package/skills/grade-paper-writing/prose-lint.test.ts +119 -10
- package/skills/submission-portal/SKILL.md +60 -44
- package/skills/submission-portal/SKILL.md.spec.ts +62 -43
- package/skills/submission-portal/submission-portal.test.ts +4 -73
- package/src/CLAUDE.md +7 -4
- package/src/CLAUDE.md.spec.ts +6 -3
- package/src/adapters/hotcrp/cassette/README.md +4 -4
- package/src/adapters/hotcrp/cassette/deadlines-msr2027.html +9 -9
- package/src/adapters/hotcrp/deadlines.io.test.ts +2 -2
- package/src/adapters/hotcrp/deadlines.test.ts +3 -3
- package/src/adapters/hotcrp/index.ts +15 -3
- package/src/adapters/hotcrp/portal.io.ts +61 -17
- package/src/adapters/hotcrp/portal.test.ts +105 -1
- package/src/adapters/hotcrp/response.ts +21 -0
- package/src/adapters/hotcrp/site.ts +34 -0
- package/src/adapters/hotcrp/token.test.ts +69 -0
- package/src/adapters/hotcrp/token.ts +51 -0
- package/src/adapters/latex/abstract.test.ts +280 -0
- package/src/adapters/latex/abstract.ts +272 -0
- package/src/adapters/latex/captions.test.ts +57 -0
- package/src/adapters/latex/captions.ts +56 -0
- package/src/adapters/latex/headings.ts +5 -4
- package/src/adapters/latex/index.test.ts +31 -1
- package/src/adapters/latex/index.ts +3 -0
- package/src/adapters/latex/parse.ts +71 -3
- package/src/adapters/node/list-entries.io.ts +2 -1
- package/src/adapters/node/list-entries.test.ts +18 -0
- package/src/cli.test.ts +20 -8
- package/src/cli.ts +22 -13
- package/src/cycle-rules.test.ts +6 -6
- package/src/cycle-rules.ts +7 -4
- package/src/domain/deadline.test.ts +31 -2
- package/src/domain/deadline.ts +42 -16
- package/src/domain/decide-first.test.ts +33 -0
- package/src/domain/decide-first.ts +16 -1
- package/src/domain/index-columns.test.ts +49 -4
- package/src/domain/index-columns.ts +2 -0
- package/src/domain/portal-token.test.ts +55 -0
- package/src/domain/portal-token.ts +63 -0
- package/src/domain/study-measurements.test.ts +7 -3
- package/src/domain/study-registry.test.ts +34 -6
- package/src/domain/study-registry.ts +123 -31
- package/src/domain/submission.test.ts +88 -0
- package/src/domain/submission.ts +99 -0
- package/src/new-paper.test.ts +1 -0
- package/src/outputs-before-decision-rule.test.ts +47 -2
- package/src/outputs-before-decision-rule.ts +31 -22
- package/src/paper-settings.test.ts +20 -0
- package/src/paper-settings.ts +17 -5
- package/src/ports/latex.ts +25 -0
- package/src/ports/list-entries.ts +7 -4
- package/src/ports/study-deps.ts +14 -0
- package/src/ports/study-folder.ts +38 -0
- package/src/ports/submission-portal.ts +43 -1
- package/src/ports/venue-deadlines.ts +1 -1
- package/src/presets.test.ts +8 -5
- package/src/presets.ts +1 -2
- package/src/studies-index-modes.test.ts +2 -2
- package/src/studies.ts +19 -10
- package/src/study-folder.test.ts +237 -0
- package/src/study-folder.ts +176 -0
- package/src/study-gate.test.ts +158 -7
- package/src/study-gate.ts +127 -54
- package/src/study-index-input.ts +12 -4
- package/src/study-modes.ts +67 -80
- package/src/study-registry-rule.test.ts +87 -0
- package/src/study-registry-rule.ts +58 -66
- package/src/submission-new.test.ts +569 -0
- package/src/submission-show.test.ts +210 -0
- package/src/submission-update.test.ts +160 -0
- package/src/submission.test.ts +140 -518
- package/src/submission.ts +494 -61
- package/scripts/refresh-deadlines.test.ts +0 -431
- 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":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,MAAM,EACN,gBAAgB,EAChB,SAAS,EACT,UAAU,GACX,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,
|
|
1
|
+
{"version":3,"file":"study-registry-rule.js","sourceRoot":"","sources":["../src/study-registry-rule.ts"],"names":[],"mappings":"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"}
|
package/dist/submission.d.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
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
|
-
|
|
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
|
package/dist/submission.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submission.d.ts","sourceRoot":"","sources":["../src/submission.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"submission.d.ts","sourceRoot":"","sources":["../src/submission.ts"],"names":[],"mappings":"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"}
|
package/dist/submission.js
CHANGED
|
@@ -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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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({
|
|
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
|
|
118
|
-
?
|
|
119
|
-
:
|
|
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} ${
|
|
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 (
|
|
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 (
|
|
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
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
-
/**
|
|
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
|
|
246
|
-
if (!
|
|
247
|
-
return (deps.err(
|
|
248
|
-
const
|
|
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(
|
|
252
|
-
: runUpdate(
|
|
539
|
+
? runShow(target, portal, pdfPath, withToken)
|
|
540
|
+
: runUpdate(target, portal, { ...a, pdfPath }, withToken);
|
|
253
541
|
}
|
|
254
542
|
//# sourceMappingURL=submission.js.map
|