paperlint 2.0.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +6 -1
- package/CONTRIBUTING.md +21 -0
- package/README.md +231 -180
- package/action.yml +4 -6
- package/dist/adapters/references/index.d.ts +13 -0
- package/dist/adapters/references/index.d.ts.map +1 -0
- package/dist/adapters/references/index.js +55 -0
- package/dist/adapters/references/index.js.map +1 -0
- package/dist/adapters/references/reach.io.d.ts +3 -0
- package/dist/adapters/references/reach.io.d.ts.map +1 -0
- package/dist/adapters/references/reach.io.js +14 -0
- package/dist/adapters/references/reach.io.js.map +1 -0
- package/dist/build-engine.d.ts.map +1 -1
- package/dist/build-engine.js +5 -2
- package/dist/build-engine.js.map +1 -1
- package/dist/build.d.ts +16 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +40 -5
- package/dist/build.js.map +1 -1
- package/dist/cli.d.ts +37 -20
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +377 -251
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +37 -52
- package/dist/doctor.js.map +1 -1
- package/dist/facts-file.d.ts +33 -9
- package/dist/facts-file.d.ts.map +1 -1
- package/dist/facts-file.js +117 -17
- package/dist/facts-file.js.map +1 -1
- package/dist/hooks-settings.d.ts +0 -21
- package/dist/hooks-settings.d.ts.map +1 -1
- package/dist/hooks-settings.js +17 -135
- package/dist/hooks-settings.js.map +1 -1
- package/dist/init.d.ts +40 -19
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +144 -109
- package/dist/init.js.map +1 -1
- package/dist/link-skills.d.ts +1 -1
- package/dist/link-skills.d.ts.map +1 -1
- package/dist/link-skills.js +11 -29
- package/dist/link-skills.js.map +1 -1
- package/dist/new-paper.d.ts +2 -2
- package/dist/new-paper.d.ts.map +1 -1
- package/dist/new-paper.js +6 -2
- package/dist/new-paper.js.map +1 -1
- package/dist/paper-files.d.ts +63 -0
- package/dist/paper-files.d.ts.map +1 -0
- package/dist/paper-files.js +69 -0
- package/dist/paper-files.js.map +1 -0
- package/dist/paper-settings.d.ts +40 -0
- package/dist/paper-settings.d.ts.map +1 -0
- package/dist/paper-settings.js +144 -0
- package/dist/paper-settings.js.map +1 -0
- package/dist/ports/check-references.d.ts +31 -0
- package/dist/ports/check-references.d.ts.map +1 -0
- package/dist/ports/check-references.js +7 -0
- package/dist/ports/check-references.js.map +1 -0
- package/dist/presets.d.ts +84 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +184 -0
- package/dist/presets.js.map +1 -0
- package/dist/reference-rules.d.ts +47 -0
- package/dist/reference-rules.d.ts.map +1 -0
- package/dist/reference-rules.js +156 -0
- package/dist/reference-rules.js.map +1 -0
- package/dist/references.d.ts +36 -0
- package/dist/references.d.ts.map +1 -0
- package/dist/references.js +91 -0
- package/dist/references.js.map +1 -0
- package/dist/rules-config.d.ts +11 -2
- package/dist/rules-config.d.ts.map +1 -1
- package/dist/rules-config.js +25 -11
- package/dist/rules-config.js.map +1 -1
- package/dist/structure.d.ts.map +1 -1
- package/dist/structure.js +3 -2
- package/dist/structure.js.map +1 -1
- package/dist/tex-requirements.d.ts +63 -7
- package/dist/tex-requirements.d.ts.map +1 -1
- package/dist/tex-requirements.js +91 -24
- package/dist/tex-requirements.js.map +1 -1
- package/dist/types.d.ts +20 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/venue-rules.d.ts +109 -0
- package/dist/venue-rules.d.ts.map +1 -0
- package/dist/venue-rules.js +389 -0
- package/dist/venue-rules.js.map +1 -0
- package/docs/configuration.md +152 -77
- package/docs/e2e.md +1 -1
- package/docs/install.md +25 -40
- package/docs/optional-rules.md +26 -24
- package/docs/rules.md +181 -15
- package/eslint-rules/bib-reachable-entry.mjs +75 -0
- package/eslint-rules/latex-language.mjs +29 -1
- package/eslint-rules/paper-stages.harness.mjs +1 -117
- package/eslint-rules/paper-stages.mjs +0 -120
- package/eslint-rules/paper-stages.mutations.mjs +0 -76
- package/eslint-rules/paper-typography.mjs +267 -192
- package/eslint-rules/paper-typography.test.mjs +297 -0
- package/eslint-rules/papers.harness.mjs +8 -12
- package/eslint-rules/papers.mjs +17 -27
- package/eslint-rules/pdf-last-page-balance.mjs +23 -5
- package/eslint-rules/review-frontmatter.mjs +118 -0
- package/eslint-rules/review-frontmatter.schema.json +36 -0
- package/eslint-rules/review-frontmatter.test.mjs +118 -0
- package/eslint-rules/sibling-frontmatter.mjs +19 -0
- package/eslint-rules/sibling-frontmatter.schema.json +14 -0
- package/eslint.config.mjs +0 -15
- package/fixtures/build-e2e/acmart/paperlint.json +1 -0
- package/fixtures/real-markdown-paper/baseline.json +6 -7
- package/hooks/hooks.harness.mjs +39 -98
- package/hooks/hooks.mutations.mjs +6 -6
- package/hooks/paper-edit-guard.hook.d.mts +2 -3
- package/hooks/paper-edit-guard.hook.mjs +31 -42
- package/hooks/paper-skills-nudge.hook.mjs +21 -19
- package/hooks/paper-status-gates.hook.mjs +21 -19
- package/hooks/paper-status-gates.sh +8 -13
- package/lib/paper-config.d.mts +15 -18
- package/lib/paper-config.harness.mjs +18 -35
- package/lib/paper-config.mjs +90 -81
- package/lib/paper-config.mutations.mjs +2 -2
- package/lib/skill-checks.mjs +1 -1
- package/lib/skill-trigger-cases.harness.mjs +9 -8
- package/lib/skill-trigger-cases.mjs +7 -15
- package/package.json +1 -1
- package/scripts/eslint-report-guard.mjs +1 -1
- package/scripts/harness-api.frozen.json +0 -3
- package/scripts/mutation-batteries.frozen.json +4 -13
- package/skills/analyze-sibling-paper/SKILL.md +16 -12
- package/skills/analyze-sibling-paper/SKILL.md.spec.ts +15 -11
- package/skills/cold-read-diff/SKILL.md +20 -1
- package/skills/cold-read-diff/SKILL.md.spec.ts +19 -0
- package/skills/find-venue/SKILL.md +5 -1
- package/skills/find-venue/SKILL.md.spec.ts +4 -0
- package/skills/grade-paper-writing/SKILL.md +20 -1
- package/skills/grade-paper-writing/SKILL.md.spec.ts +19 -0
- package/skills/paper-pipeline/PIPELINE-MAP.md +14 -4
- package/skills/paper-pipeline/SKILL.md +4 -3
- package/skills/paper-pipeline/SKILL.md.spec.ts +3 -2
- package/skills/paper-pipeline/scripts/consumer.d.mts +0 -1
- package/skills/paper-pipeline/scripts/consumer.harness.mjs +8 -12
- package/skills/paper-pipeline/scripts/consumer.mjs +19 -33
- package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +6 -4
- package/skills/paper-pipeline/scripts/run-mechanical.mjs +2 -11
- package/skills/plan-paper-timeline/SKILL.md +2 -2
- package/skills/plan-paper-timeline/SKILL.md.spec.ts +1 -1
- package/skills/plan-paper-timeline/plan-paper-timeline.effects.harness.mjs +1 -1
- package/skills/plan-paper-timeline/plan-paper-timeline.effects.mutations.mjs +2 -2
- package/skills/render-paper/check-render.sh +2 -3
- package/skills/render-paper/extract-pdf-facts.harness.mjs +5 -5
- package/skills/render-paper/extract-pdf-facts.mjs +4 -4
- package/skills/render-paper/render-paper.harness.mjs +2 -2
- package/skills/study-accepted-papers/SKILL.md +2 -1
- package/skills/study-accepted-papers/SKILL.md.spec.ts +1 -0
- package/skills/submit-paper/SKILL.md +9 -1
- package/skills/submit-paper/SKILL.md.spec.ts +8 -0
- package/skills/submit-paper/references/venues/acm-sigconf.jsonc +86 -0
- package/skills/submit-paper/references/venues/agenticdev.jsonc +34 -102
- package/skills/submit-paper/references/venues/aisec.jsonc +21 -82
- package/skills/submit-paper/references/venues/realm.jsonc +45 -43
- package/skills/submit-paper/references/venues/tex-base.jsonc +1 -1
- package/skills/submit-paper/references/venues/venue-profile.schema.json +119 -29
- package/skills/verify-citations/SKILL.md +10 -1
- package/skills/verify-citations/SKILL.md.spec.ts +9 -0
- package/skills/verify-citations/scripts/bib-authors.mjs +48 -26
- package/src/adapters/references/index.ts +102 -0
- package/src/adapters/references/reach.io.ts +12 -0
- package/src/build-engine.ts +10 -2
- package/src/build.harness.mjs +31 -22
- package/src/build.ts +65 -8
- package/src/cli.harness.mjs +151 -294
- package/src/cli.mutations.mjs +35 -44
- package/src/cli.ts +457 -288
- package/src/doctor.harness.mjs +41 -84
- package/src/doctor.mutations.mjs +9 -9
- package/src/doctor.ts +41 -61
- package/src/facts-file.test.ts +47 -7
- package/src/facts-file.ts +145 -24
- package/src/hooks-settings.harness.mjs +7 -92
- package/src/hooks-settings.mutations.mjs +2 -17
- package/src/hooks-settings.ts +18 -162
- package/src/init.test.ts +206 -0
- package/src/init.ts +193 -159
- package/src/link-skills.harness.mjs +1 -38
- package/src/link-skills.mutations.mjs +9 -5
- package/src/link-skills.ts +10 -34
- package/src/lint-fix.test.ts +120 -0
- package/src/new-paper.harness.mjs +9 -6
- package/src/new-paper.test.ts +133 -0
- package/src/new-paper.ts +7 -2
- package/src/paper-files.test.ts +290 -0
- package/src/paper-files.ts +144 -0
- package/src/paper-settings-commands.test.ts +274 -0
- package/src/paper-settings.test.ts +249 -0
- package/src/paper-settings.ts +208 -0
- package/src/ports/check-references.ts +28 -0
- package/src/presets.test.ts +236 -0
- package/src/presets.ts +297 -0
- package/src/reference-rules.ts +229 -0
- package/src/references.test.ts +209 -0
- package/src/references.ts +138 -0
- package/src/rules-config.harness.mjs +24 -8
- package/src/rules-config.ts +30 -13
- package/src/structure.harness.mjs +6 -4
- package/src/structure.ts +3 -2
- package/src/tex-requirements.harness.mjs +11 -17
- package/src/tex-requirements.ts +179 -29
- package/src/types.ts +30 -18
- package/src/venue-rules.test.ts +554 -0
- package/src/venue-rules.ts +571 -0
- package/templates/paper/paperlint.json +4 -0
- package/eslint-rules/doc-fields.harness.mjs +0 -336
- package/eslint-rules/doc-fields.mjs +0 -186
- package/eslint-rules/doc-fields.mutations.mjs +0 -96
- package/eslint-rules/paper-typography.harness.mjs +0 -291
- package/eslint-rules/paper-typography.mutations.mjs +0 -131
- package/eslint-rules/review-findings-cause.harness.mjs +0 -228
- package/eslint-rules/review-findings-cause.mjs +0 -135
- package/eslint-rules/review-findings-cause.mutations.mjs +0 -72
- package/fixtures/build-e2e/acmart/venue.json +0 -1
- package/fixtures/paper-stages/authors-ran/PIPELINE-STATUS.md +0 -16
- package/fixtures/paper-stages/marker-in-prose/PIPELINE-STATUS.md +0 -17
- package/fixtures/review-findings-cause/clean.md +0 -17
- package/fixtures/review-findings-cause/defect.md +0 -14
- package/fixtures/review-findings-cause/old-debt.md +0 -14
- package/fixtures/review-findings-cause/quiet-in-fence.md +0 -16
package/src/tex-requirements.ts
CHANGED
|
@@ -20,12 +20,13 @@
|
|
|
20
20
|
* allowed to know where this package is installed (rule 10).
|
|
21
21
|
*/
|
|
22
22
|
// eslint-disable-next-line boundaries/dependencies -- legacy I/O, moves behind a port in #76
|
|
23
|
-
import {
|
|
23
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
24
24
|
import { createRequire } from "node:module";
|
|
25
25
|
import { join } from "node:path";
|
|
26
26
|
// eslint-disable-next-line boundaries/dependencies -- legacy layer, moves behind a port in #76
|
|
27
27
|
import Ajv from "ajv";
|
|
28
28
|
import { packageVenuesDir } from "../skills/paper-pipeline/scripts/consumer.mjs";
|
|
29
|
+
import { CONFIG_FILE } from "../lib/paper-config.mjs";
|
|
29
30
|
|
|
30
31
|
/** CTAN package name → the names that prove it is installed. */
|
|
31
32
|
export type PackageProofs = Readonly<Record<string, readonly string[]>>;
|
|
@@ -78,18 +79,133 @@ function violations(file: string, v: Validate): string[] {
|
|
|
78
79
|
);
|
|
79
80
|
}
|
|
80
81
|
|
|
82
|
+
/** One kind of paper a venue takes (`short`, `research`, …) and its page limits; null = not limited. */
|
|
83
|
+
export interface KindLimits {
|
|
84
|
+
readonly bodyPagesMax: number | null;
|
|
85
|
+
readonly refPagesMax: number | null;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The format a venue's call for papers sets — what the `pdf/*` venue rules judge a built PDF
|
|
90
|
+
* against. Every field the profile leaves out is null, and a rule that finds null checks nothing:
|
|
91
|
+
* a profile that does not name a number never makes one up.
|
|
92
|
+
*/
|
|
93
|
+
export interface VenueFormat {
|
|
94
|
+
readonly pageWidthIn: number | null;
|
|
95
|
+
readonly pageHeightIn: number | null;
|
|
96
|
+
readonly columns: number | null;
|
|
97
|
+
readonly bodyPt: number | null;
|
|
98
|
+
readonly bodyPtTol: number | null;
|
|
99
|
+
readonly refPtMin: number | null;
|
|
100
|
+
readonly refPtMax: number | null;
|
|
101
|
+
/** The prefix a font name of the body text starts with (`LinLibertine`). */
|
|
102
|
+
readonly fontsText: string | null;
|
|
103
|
+
readonly fontsTitle: string | null;
|
|
104
|
+
readonly kinds: ReadonlyMap<string, KindLimits>;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Every format field a preset left out is null; a merge fills it from the parent. */
|
|
108
|
+
export const NO_FORMAT: VenueFormat = {
|
|
109
|
+
pageWidthIn: null,
|
|
110
|
+
pageHeightIn: null,
|
|
111
|
+
columns: null,
|
|
112
|
+
bodyPt: null,
|
|
113
|
+
bodyPtTol: null,
|
|
114
|
+
refPtMin: null,
|
|
115
|
+
refPtMax: null,
|
|
116
|
+
fontsText: null,
|
|
117
|
+
fontsTitle: null,
|
|
118
|
+
kinds: new Map(),
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* One preset FILE, parsed — before its `extends` chain is resolved (`src/presets.ts` does that).
|
|
123
|
+
* A preset is a venue or a template family: `{ extends?, name?, template?, format?, tex?, rules? }`.
|
|
124
|
+
*/
|
|
125
|
+
export interface PresetFile {
|
|
126
|
+
/** The preset this one builds on: `paperlint:<name>` or a relative path. */
|
|
127
|
+
readonly extends: string | null;
|
|
128
|
+
/** A display name for messages; the file name otherwise. */
|
|
129
|
+
readonly name: string | null;
|
|
130
|
+
readonly template: string | null;
|
|
131
|
+
/** Null when the file declares no `tex` block (allowed only with `extends`). */
|
|
132
|
+
readonly tex: TexRequirements | null;
|
|
133
|
+
readonly format: VenueFormat;
|
|
134
|
+
/** rule id → ESLint entry, checked against the shipped rules where a config is built. */
|
|
135
|
+
readonly rules: Readonly<Record<string, unknown>>;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
type KindsJson = Readonly<
|
|
139
|
+
Record<string, { body_pages_max?: number; ref_pages_max?: number }>
|
|
140
|
+
>;
|
|
141
|
+
|
|
142
|
+
/** A preset's `format` block after the schema accepted it. */
|
|
143
|
+
interface FormatJson {
|
|
144
|
+
readonly page_w_in?: number;
|
|
145
|
+
readonly page_h_in?: number;
|
|
146
|
+
readonly columns?: number;
|
|
147
|
+
readonly body_pt?: number;
|
|
148
|
+
readonly body_pt_tol?: number;
|
|
149
|
+
readonly ref_pt_min?: number;
|
|
150
|
+
readonly ref_pt_max?: number;
|
|
151
|
+
readonly fonts_text?: string;
|
|
152
|
+
readonly fonts_title?: string;
|
|
153
|
+
readonly kinds?: KindsJson;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/** The preset's JSON after the schema accepted it — the shape `venue-profile.schema.json` allows. */
|
|
157
|
+
interface PresetJson {
|
|
158
|
+
readonly extends?: string;
|
|
159
|
+
readonly name?: string;
|
|
160
|
+
readonly template?: string;
|
|
161
|
+
readonly tex?: Partial<TexRequirements>;
|
|
162
|
+
readonly format?: FormatJson;
|
|
163
|
+
readonly rules?: Readonly<Record<string, unknown>>;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** An optional field as the typed preset holds it: absent is null. */
|
|
167
|
+
const orNull = <T>(v: T | undefined): T | null => (v === undefined ? null : v);
|
|
168
|
+
|
|
169
|
+
function kindsOf(k: KindsJson | undefined): ReadonlyMap<string, KindLimits> {
|
|
170
|
+
return new Map(
|
|
171
|
+
Object.entries(k ?? {}).map(([name, v]) => [
|
|
172
|
+
name,
|
|
173
|
+
{
|
|
174
|
+
bodyPagesMax: orNull(v.body_pages_max),
|
|
175
|
+
refPagesMax: orNull(v.ref_pages_max),
|
|
176
|
+
},
|
|
177
|
+
]),
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function formatOf(j: FormatJson = {}): VenueFormat {
|
|
182
|
+
return {
|
|
183
|
+
pageWidthIn: orNull(j.page_w_in),
|
|
184
|
+
pageHeightIn: orNull(j.page_h_in),
|
|
185
|
+
columns: orNull(j.columns),
|
|
186
|
+
bodyPt: orNull(j.body_pt),
|
|
187
|
+
bodyPtTol: orNull(j.body_pt_tol),
|
|
188
|
+
refPtMin: orNull(j.ref_pt_min),
|
|
189
|
+
refPtMax: orNull(j.ref_pt_max),
|
|
190
|
+
fontsText: orNull(j.fonts_text),
|
|
191
|
+
fontsTitle: orNull(j.fonts_title),
|
|
192
|
+
kinds: kindsOf(j.kinds),
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
81
196
|
/**
|
|
82
|
-
* The text of one
|
|
197
|
+
* The text of one preset file → the typed file, or an Error naming every problem. The ONE parser
|
|
198
|
+
* of a preset: the toolchain reads its `tex`, the venue rules its `format`, the config its `rules`.
|
|
83
199
|
*
|
|
84
200
|
* @param text the file's contents
|
|
85
201
|
* @param file the name to put in messages
|
|
86
202
|
* @param dir the directory holding the schema (the shipped venues directory by default)
|
|
87
203
|
*/
|
|
88
|
-
export function
|
|
204
|
+
export function parsePreset(
|
|
89
205
|
text: string,
|
|
90
206
|
file: string,
|
|
91
207
|
dir: string = packageVenuesDir(),
|
|
92
|
-
):
|
|
208
|
+
): PresetFile {
|
|
93
209
|
const { config, error } = typescript().parseConfigFileTextToJson(file, text);
|
|
94
210
|
if (error)
|
|
95
211
|
throw new Error(
|
|
@@ -100,8 +216,38 @@ export function parseProfile(
|
|
|
100
216
|
throw new Error(
|
|
101
217
|
`${file} does not match ${SCHEMA_FILE}:\n ${violations(file, validate).join("\n ")}`,
|
|
102
218
|
);
|
|
103
|
-
const
|
|
104
|
-
return {
|
|
219
|
+
const j = config as PresetJson;
|
|
220
|
+
return {
|
|
221
|
+
extends: orNull(j.extends),
|
|
222
|
+
name: orNull(j.name),
|
|
223
|
+
template: orNull(j.template),
|
|
224
|
+
tex: j.tex
|
|
225
|
+
? { packages: j.tex.packages ?? {}, tools: j.tex.tools ?? {} }
|
|
226
|
+
: null,
|
|
227
|
+
format: formatOf(j.format),
|
|
228
|
+
rules: j.rules ?? {},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/** The text of one preset → the TeX requirements it declares itself (none without a `tex` block). */
|
|
233
|
+
export function parseProfile(
|
|
234
|
+
text: string,
|
|
235
|
+
file: string,
|
|
236
|
+
dir: string = packageVenuesDir(),
|
|
237
|
+
): TexRequirements {
|
|
238
|
+
return parsePreset(text, file, dir).tex ?? NO_REQUIREMENTS;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* The file a venue's profile lives in, or null when the name cannot be a venue (the base set is a
|
|
243
|
+
* profile file but not a venue). Whether the file exists is the caller's question.
|
|
244
|
+
*/
|
|
245
|
+
export function profileFileOf(venue: string): string | null {
|
|
246
|
+
return venue === BASE_PROFILE.slice(0, -PROFILE_EXT.length) ||
|
|
247
|
+
venue.includes("/") ||
|
|
248
|
+
venue.includes("\\")
|
|
249
|
+
? null
|
|
250
|
+
: `${venue}${PROFILE_EXT}`;
|
|
105
251
|
}
|
|
106
252
|
|
|
107
253
|
function readProfile(dir: string, file: string): TexRequirements {
|
|
@@ -141,41 +287,45 @@ export function packageNames(tex: TexRequirements): string[] {
|
|
|
141
287
|
}
|
|
142
288
|
|
|
143
289
|
/**
|
|
144
|
-
* What ONE paper needs: the base set plus its venue's
|
|
145
|
-
*
|
|
146
|
-
* without
|
|
290
|
+
* What ONE paper needs: the base set plus its venue preset's `tex` (the union over the preset's
|
|
291
|
+
* `extends` chain, resolved by `src/presets.ts`). A paper with no preset gets the base set, and the
|
|
292
|
+
* source says so, so an ACM paper built without a preset is visibly running on the base set.
|
|
147
293
|
*/
|
|
148
294
|
export function requirementsFor(
|
|
149
|
-
|
|
295
|
+
preset: { readonly label: string; readonly tex: TexRequirements } | null,
|
|
150
296
|
dir: string = packageVenuesDir(),
|
|
151
297
|
): PaperRequirements {
|
|
152
298
|
const base = readProfile(dir, BASE_PROFILE);
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
tex: base,
|
|
163
|
-
};
|
|
164
|
-
return {
|
|
165
|
-
source: `venue ${venue}`,
|
|
166
|
-
tex: mergeRequirements(base, readProfile(dir, file)),
|
|
167
|
-
};
|
|
299
|
+
return preset === null
|
|
300
|
+
? {
|
|
301
|
+
source: `the base set (no venue preset in ${CONFIG_FILE})`,
|
|
302
|
+
tex: base,
|
|
303
|
+
}
|
|
304
|
+
: {
|
|
305
|
+
source: `venue ${preset.label}`,
|
|
306
|
+
tex: mergeRequirements(base, preset.tex),
|
|
307
|
+
};
|
|
168
308
|
}
|
|
169
309
|
|
|
170
|
-
/**
|
|
171
|
-
|
|
310
|
+
/**
|
|
311
|
+
* Everything any shipped preset declares, plus `extra` — the resolved presets of the project's own
|
|
312
|
+
* papers, which may live outside the package. The set `paperlint toolchain` installs, so one tree
|
|
313
|
+
* builds any paper.
|
|
314
|
+
*/
|
|
315
|
+
export function declaredUnion(
|
|
316
|
+
dir: string = packageVenuesDir(),
|
|
317
|
+
extra: readonly TexRequirements[] = [],
|
|
318
|
+
): {
|
|
172
319
|
readonly tex: TexRequirements;
|
|
173
320
|
readonly profiles: number;
|
|
174
321
|
} {
|
|
175
322
|
const venues = venueNames(dir);
|
|
176
|
-
const
|
|
323
|
+
const shipped = venues.reduce(
|
|
177
324
|
(acc, v) => mergeRequirements(acc, readProfile(dir, `${v}${PROFILE_EXT}`)),
|
|
178
325
|
readProfile(dir, BASE_PROFILE),
|
|
179
326
|
);
|
|
180
|
-
return {
|
|
327
|
+
return {
|
|
328
|
+
tex: extra.reduce(mergeRequirements, shipped),
|
|
329
|
+
profiles: venues.length + 1,
|
|
330
|
+
};
|
|
181
331
|
}
|
package/src/types.ts
CHANGED
|
@@ -5,29 +5,27 @@ import type { RuleBlock } from "./rules-config.ts";
|
|
|
5
5
|
* in someone's head: a typo in a config key read as "field not set", not as an error.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* The project's settings — the root `paperlint.json`, optional. Every key is optional; the key list
|
|
10
|
+
* (and which keys a paper's own `paperlint.json` may also hold) is `SETTINGS_KEYS` in
|
|
11
|
+
* lib/paper-config.mjs.
|
|
12
|
+
*/
|
|
9
13
|
export interface PaperlintConfig {
|
|
10
|
-
/**
|
|
14
|
+
/** The paper director(ies), relative to the project root. Default `papers`. The field name is
|
|
11
15
|
* `PAPERS_DIR_FIELD` in lib/paper-config.mjs; code reads it through `papersDirOf()` in cli.ts. */
|
|
12
16
|
papersDir?: string | string[];
|
|
13
|
-
/** The command that prints the author list from .bib — each corpus has its own. */
|
|
14
|
-
authorListCommand?: string;
|
|
15
|
-
/** Per-paper typography debt: how many findings already exist; the number may only go down. */
|
|
16
|
-
typographyDebt?: Record<string, Record<string, number>>;
|
|
17
|
-
/** Frontmatter fields required for review notes, and the permitted values of each. */
|
|
18
|
-
docFields?: Record<string, { values: string[] }>;
|
|
19
|
-
/** Ignore review findings older than this date. */
|
|
20
|
-
reviewSince?: string;
|
|
21
|
-
/** How many findings a cold read must produce to count as a cold read. */
|
|
22
|
-
minFindings?: number;
|
|
23
|
-
/** The word with which review notes introduce the cause. */
|
|
24
|
-
causeMarker?: string;
|
|
25
17
|
/** Which files a paper directory must carry; `false` turns the check off entirely. */
|
|
26
18
|
structure?: StructureConfig | false;
|
|
27
|
-
/** REMOVED — `paperlint build` compiles the paper itself. Still typed so a leftover key can be named. */
|
|
28
|
-
buildScripts?: unknown;
|
|
29
19
|
/** ESLint config blocks appended after paperlint's own — PARSED by `parseSettings` in cli.ts. */
|
|
30
20
|
rules?: readonly RuleBlock[];
|
|
21
|
+
/** The default venue preset of every paper that names none (`src/paper-settings.ts`). */
|
|
22
|
+
extends?: string | null;
|
|
23
|
+
/** The default kind of paper. */
|
|
24
|
+
kind?: string;
|
|
25
|
+
/** The default path of the built PDF, relative to each paper. */
|
|
26
|
+
pdf?: string;
|
|
27
|
+
/** A note for humans; ignored. */
|
|
28
|
+
$comment?: unknown;
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
export interface StructureConfig {
|
|
@@ -47,6 +45,8 @@ export interface Args {
|
|
|
47
45
|
paths: string[];
|
|
48
46
|
config: string | null;
|
|
49
47
|
json: boolean;
|
|
48
|
+
/** `--fix`: `lint` writes every fix a rule offers, then reports what is left. */
|
|
49
|
+
fix: boolean;
|
|
50
50
|
all: boolean;
|
|
51
51
|
dryRun: boolean;
|
|
52
52
|
/** `--check`: `toolchain` reports what is missing and changes nothing. */
|
|
@@ -102,5 +102,17 @@ export interface BuildResult {
|
|
|
102
102
|
|
|
103
103
|
/** The result of reading the config: either data, or the exit code the caller exits with. */
|
|
104
104
|
export type ConfigRead =
|
|
105
|
-
| {
|
|
106
|
-
|
|
105
|
+
| {
|
|
106
|
+
opts: PaperlintConfig;
|
|
107
|
+
/** The root `paperlint.json`, or null when the project has none. */
|
|
108
|
+
configPath: string | null;
|
|
109
|
+
/** The project root: `papersDir` and the `rules` globs are relative to it. */
|
|
110
|
+
root: string;
|
|
111
|
+
code?: undefined;
|
|
112
|
+
}
|
|
113
|
+
| {
|
|
114
|
+
code: number;
|
|
115
|
+
opts?: undefined;
|
|
116
|
+
configPath?: undefined;
|
|
117
|
+
root?: undefined;
|
|
118
|
+
};
|