paperlint 6.3.0 → 7.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/CONTRIBUTING.md +4 -2
- package/README.md +2 -2
- package/dist/adapters/latex/conditionals.d.ts +21 -0
- package/dist/adapters/latex/conditionals.d.ts.map +1 -0
- package/dist/adapters/latex/conditionals.js +75 -0
- package/dist/adapters/latex/conditionals.js.map +1 -0
- package/dist/adapters/latex/headings.d.ts +10 -0
- package/dist/adapters/latex/headings.d.ts.map +1 -0
- package/dist/adapters/latex/headings.js +129 -0
- package/dist/adapters/latex/headings.js.map +1 -0
- 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 +1 -1
- package/dist/adapters/latex/parse.d.ts.map +1 -1
- package/dist/adapters/latex/parse.js +3 -2
- package/dist/adapters/latex/parse.js.map +1 -1
- package/dist/build.d.ts +1 -1
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +1 -1
- package/dist/build.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +17 -3
- package/dist/cli.js.map +1 -1
- package/dist/domain/heading-case.d.ts +100 -0
- package/dist/domain/heading-case.d.ts.map +1 -0
- package/dist/domain/heading-case.js +365 -0
- package/dist/domain/heading-case.js.map +1 -0
- package/dist/domain/tex-document.d.ts +32 -0
- package/dist/domain/tex-document.d.ts.map +1 -1
- package/dist/domain/tex-document.js +11 -0
- package/dist/domain/tex-document.js.map +1 -1
- package/dist/eslint-rules/latex-language.d.ts.map +1 -1
- package/dist/eslint-rules/latex-language.js +16 -3
- package/dist/eslint-rules/latex-language.js.map +1 -1
- package/dist/facts-file.d.ts +3 -3
- package/dist/facts-file.d.ts.map +1 -1
- package/dist/facts-file.js +3 -3
- package/dist/facts-file.js.map +1 -1
- package/dist/folder-venue-rule.js +6 -6
- package/dist/folder-venue-rule.js.map +1 -1
- package/dist/heading-case.d.ts +48 -0
- package/dist/heading-case.d.ts.map +1 -0
- package/dist/heading-case.js +191 -0
- package/dist/heading-case.js.map +1 -0
- package/dist/ports/latex.d.ts +7 -1
- package/dist/ports/latex.d.ts.map +1 -1
- package/dist/preset-card-rule.d.ts +100 -0
- package/dist/preset-card-rule.d.ts.map +1 -0
- package/dist/preset-card-rule.js +221 -0
- package/dist/preset-card-rule.js.map +1 -0
- package/dist/presets.d.ts +19 -2
- package/dist/presets.d.ts.map +1 -1
- package/dist/presets.js +97 -62
- package/dist/presets.js.map +1 -1
- package/dist/tex-requirements.d.ts +33 -3
- package/dist/tex-requirements.d.ts.map +1 -1
- package/dist/tex-requirements.js +27 -2
- package/dist/tex-requirements.js.map +1 -1
- package/dist/tex-venue-rules.d.ts +1 -1
- package/dist/tex-venue-rules.d.ts.map +1 -1
- package/dist/tex-venue-rules.js.map +1 -1
- package/docs/configuration.md +13 -1
- package/docs/optional-rules.md +4 -3
- package/docs/rules/format/page-limit.md +1 -1
- package/docs/rules/paper/folder-venue-leftover.md +1 -1
- package/docs/rules/talk/profile.md +1 -1
- package/docs/rules/tex/heading-case.md +424 -0
- package/docs/rules.md +62 -53
- package/eslint-rules/latex-language.test.mjs +12 -0
- package/eslint-rules/latex-language.ts +17 -4
- package/eslint-rules/paper-typography.test.mjs +12 -0
- package/eslint.config.mjs +59 -1
- package/fixtures/build-e2e/acmart/paper.tex +1 -1
- package/fixtures/build-e2e/fallback/expect.json +3 -3
- package/lib/skill-checks.mjs +31 -0
- package/package.json +7 -1
- package/presets/acm-sigconf.jsonc +5 -0
- package/presets/acm-sigconf.md +43 -0
- package/presets/agenticdev.jsonc +27 -6
- package/presets/agenticdev.md +151 -0
- package/presets/aidc.jsonc +6 -0
- package/presets/aidc.md +75 -0
- package/presets/aisec.jsonc +5 -1
- package/presets/aisec.md +117 -0
- package/presets/ieee-conference.jsonc +5 -0
- package/presets/ieee-conference.md +38 -0
- package/presets/realm.jsonc +7 -2
- package/presets/realm.md +166 -0
- package/presets/tex/agenticdev.tex +1 -1
- package/presets/tex-base.jsonc +6 -0
- package/presets/tex-base.md +30 -0
- package/presets/venue-profile.schema.json +40 -1
- package/skills/find-venue/SKILL.md +6 -5
- package/skills/find-venue/SKILL.md.spec.ts +5 -4
- package/skills/paper-pipeline/SKILL.md +5 -6
- package/skills/paper-pipeline/SKILL.md.spec.ts +4 -5
- package/skills/paper-pipeline/references/acl-venue-rules.md +1 -1
- package/skills/study-accepted-papers/SKILL.md +3 -3
- package/skills/study-accepted-papers/SKILL.md.spec.ts +2 -2
- package/skills/submit-paper/SKILL.md +26 -22
- package/skills/submit-paper/SKILL.md.spec.ts +25 -21
- package/skills/submit-paper/references/publishers/acm.md +1 -1
- package/src/adapters/latex/conditionals.ts +130 -0
- package/src/adapters/latex/headings.ts +163 -0
- package/src/adapters/latex/index.test.ts +65 -0
- package/src/adapters/latex/index.ts +3 -0
- package/src/adapters/latex/parse.ts +3 -2
- package/src/build.ts +2 -2
- package/src/cli.test.ts +50 -7
- package/src/cli.ts +21 -4
- package/src/domain/heading-case.test.ts +660 -0
- package/src/domain/heading-case.ts +538 -0
- package/src/domain/tex-document.ts +36 -0
- package/src/domain/venue-name.test.ts +13 -7
- package/src/facts-file.test.ts +4 -4
- package/src/facts-file.ts +6 -6
- package/src/folder-venue-rule.test.ts +10 -10
- package/src/folder-venue-rule.ts +6 -6
- package/src/heading-case.test.ts +500 -0
- package/src/heading-case.ts +275 -0
- package/src/init.test.ts +1 -1
- package/src/new-paper.test.ts +10 -6
- package/src/paper-settings-commands.test.ts +25 -10
- package/src/ports/latex.ts +7 -0
- package/src/preset-card-rule.test.ts +266 -0
- package/src/preset-card-rule.ts +384 -0
- package/src/presets.test.ts +193 -40
- package/src/presets.ts +139 -70
- package/src/rule-cases.test.ts +136 -50
- package/src/submission.test.ts +2 -1
- package/src/talk-rules.test.ts +6 -3
- package/src/tex-requirements.harness.ts +25 -11
- package/src/tex-requirements.test.ts +127 -1
- package/src/tex-requirements.ts +70 -8
- package/src/tex-venue-rules.test.ts +35 -21
- package/src/tex-venue-rules.ts +2 -1
- package/src/venue-rules.test.ts +7 -6
- package/templates/paper/paper.tex +1 -1
- package/skills/submit-paper/references/venues/agenticdev.md +0 -171
- package/skills/submit-paper/references/venues/aisec.md +0 -105
- package/skills/submit-paper/references/venues/realm.md +0 -155
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
# tex/heading-case
|
|
2
|
+
|
|
3
|
+
**Level:** off unless turned on. Only the AgenticDev preset turns it on (`error`, `chicago-headline`)
|
|
4
|
+
· **Reads:** `paper.tex` and the files its body includes, one at a time · **Fixable:** `--fix`, for
|
|
5
|
+
`chicago-headline`
|
|
6
|
+
|
|
7
|
+
## What it catches
|
|
8
|
+
|
|
9
|
+
A word in the **paper's title** or in a **heading** that is not in the capitalization the venue
|
|
10
|
+
asks:
|
|
11
|
+
|
|
12
|
+
- the title: `\title{…}`, and the short title of `\title[short]{long}`;
|
|
13
|
+
- the headings: `\section`, `\subsection`, `\subsubsection`, `\paragraph` and `\subparagraph`,
|
|
14
|
+
starred or not, each with its short title in brackets.
|
|
15
|
+
|
|
16
|
+
You say which style the title takes and which style the headings take. A level the venue sets
|
|
17
|
+
apart gets its own entry:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
type CaseStyle = "chicago-headline" | "sentence" | "any";
|
|
21
|
+
type HeadingLevel =
|
|
22
|
+
"section" | "subsection" | "subsubsection" | "paragraph" | "subparagraph";
|
|
23
|
+
|
|
24
|
+
interface HeadingCaseOptions {
|
|
25
|
+
title: CaseStyle; // \title{…}, short title included
|
|
26
|
+
headings: CaseStyle; // every heading command, starred or not, short title included
|
|
27
|
+
levels?: Partial<Record<HeadingLevel, CaseStyle>>; // a level whose style differs from `headings`
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
```jsonc
|
|
32
|
+
// a venue preset, or a paper's own paperlint.json
|
|
33
|
+
"rules": {
|
|
34
|
+
"tex/heading-case": ["error", { "title": "chicago-headline", "headings": "chicago-headline" }]
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
A heading takes `levels[its level]` when that is set, and `headings` otherwise. `levels` never
|
|
39
|
+
applies to the title.
|
|
40
|
+
|
|
41
|
+
Each finding is reported where the word stands, in the file it stands in: a title in the preamble
|
|
42
|
+
at its line there, a heading in `sections/results.tex` at that file and line. `--fix` edits that
|
|
43
|
+
file.
|
|
44
|
+
|
|
45
|
+
## The styles
|
|
46
|
+
|
|
47
|
+
Each style is named after the text that defines it. There is no style called just `headline`: see
|
|
48
|
+
[why](#why-not-one-headline-style).
|
|
49
|
+
|
|
50
|
+
| style | authority | what it checks | what it leaves silent on purpose | `--fix` |
|
|
51
|
+
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
|
|
52
|
+
| `chicago-headline` | Conference Publishing Consulting's quote of the _Chicago Manual of Style_, sections 8.157–8.159 ([Help.php](https://www.conference-publishing.com/Help.php), quoted below) | first and last word, the first word after a colon, and every major word are capitalized; articles, prepositions «regardless of length», `and` `but` `for` `or` `nor`, `to` and `as` are lowercase; hyphenated compounds by the publisher's rule | words that are a preposition in one title and a particle or conjunction in another (`up`, `over`, `in`, `if`, `that`, `using` …) in the middle of a title; the second element after a bound prefix (`Multi-turn`); names, acronyms, code, math (see below) | yes, where the source holds the word's letters side by side |
|
|
53
|
+
| `sentence` | the venue's own words, e.g. NeurIPS: «lower case (except for first word and proper nouns)» | the first word is capitalized | every other word: a proper noun (_Python_, _Bayesian_) cannot be told from an over-capitalized word without a dictionary of names | no — a product name written in lowercase looks the same |
|
|
54
|
+
| `any` | — | nothing | everything: the venue sets no case for this scope | — |
|
|
55
|
+
|
|
56
|
+
`chicago-headline` is the one headline variant built. Other variants are added one at a time, each
|
|
57
|
+
as a new style, when a preset needs one: [Adding a style](#adding-a-style).
|
|
58
|
+
|
|
59
|
+
## Why
|
|
60
|
+
|
|
61
|
+
Some proceedings vendors check the case of the title and of every heading before a paper goes
|
|
62
|
+
into the proceedings: the vendor's checklist names it, and papers that miss it are returned to
|
|
63
|
+
their authors. A heading in sentence case (`\section{Related work}`) passes every other gate
|
|
64
|
+
paperlint has, so without this rule nothing catches it before the vendor does.
|
|
65
|
+
|
|
66
|
+
The requirement, verbatim, from Conference Publishing Consulting's help page
|
|
67
|
+
(https://www.conference-publishing.com/Help.php, read 2026-10-03). The vendor produces SIGSOFT and
|
|
68
|
+
SIGPLAN proceedings (ASE, ICSE, …) for ACM:
|
|
69
|
+
|
|
70
|
+
> Headline-Style Capitalization (according to the Chicago Manual of Style, Sections 8.157, 8.158,
|
|
71
|
+
> and 8.159)
|
|
72
|
+
> Capitalize: first and last word, first word after a colon (subtitle); all major words (nouns,
|
|
73
|
+
> pronouns, verbs, adjectives, adverbs)
|
|
74
|
+
> Lowercase: articles (the, a, an); prepositions (regardless of length); conjunctions (and, but,
|
|
75
|
+
> for, or, nor); to, as
|
|
76
|
+
> Hyphenated Compounds: always capitalize first element; lowercase second element for articles,
|
|
77
|
+
> prepositions, conjunctions and if the first element is a prefix or combining form that could not
|
|
78
|
+
> stand by itself (unless the second element is a proper noun / proper adjective)
|
|
79
|
+
> Examples: Multi-stage, Non-termination
|
|
80
|
+
|
|
81
|
+
Its author instructions name both scopes. The checklist
|
|
82
|
+
(https://www.conference-publishing.com/Instructions.php?Conf=ICSE12) asks whether the paper "has
|
|
83
|
+
the title and all headings properly capitalized", and an event's instructions
|
|
84
|
+
(https://www.conference-publishing.com/Instructions.php?Event=ITICSE18) say:
|
|
85
|
+
|
|
86
|
+
> The title should use headline-style capitalization (e.g., 'The Best POPL Paper of All Time')
|
|
87
|
+
|
|
88
|
+
> All levels of headings use headline-style capitalization.
|
|
89
|
+
|
|
90
|
+
So the rule reads the title as well as the headings.
|
|
91
|
+
|
|
92
|
+
## Venues, and which preset turns the rule on
|
|
93
|
+
|
|
94
|
+
What each venue's author text says about case, read 2026-10-04 unless marked. **Only the
|
|
95
|
+
`agenticdev` preset turns the rule on.** The others are off for one of two reasons, named in the
|
|
96
|
+
last column: the requirement was **not read**, or the venue asks for a **variant that is not built**
|
|
97
|
+
(a `chicago-headline` check there would report words the venue wants capitalized). "Not read" means
|
|
98
|
+
the page could not be opened. It never means the venue has no requirement.
|
|
99
|
+
|
|
100
|
+
| venue or publisher | title | headings | the text, verbatim | source | paperlint preset |
|
|
101
|
+
| ----------------------------------------------------------------------- | --------------------------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------- |
|
|
102
|
+
| **Conference Publishing Consulting** (ACM SIGSOFT, SIGPLAN; AgenticDev) | headline, Chicago | headline, all levels | quoted [above](#why) | [Help.php](https://www.conference-publishing.com/Help.php) · [ITiCSE18](https://www.conference-publishing.com/Instructions.php?Event=ITICSE18) | `agenticdev`: **on**, `error`, `chicago-headline` for both |
|
|
103
|
+
| **Sheridan Communications** (ACM CCS) | «Initial Caps», for the submission form | not stated | «Be sure that the title is in Initial Caps -- Initial Caps Meaning First Letter of the Main Words Should be Made Capital Letters.» · «Capitalize the First Letter of Main Words in the Title (Most Nouns), except a, an, the, conjunctions (and, but, or, for,…), & prepositions (of, to, in, on,…)» — in the section on the submission page's fields, not about the PDF | [CCS instructions](https://www.scomminc.com/pp/acmsig/ccs.htm) | `aisec`, `acm-sigconf`: off — the text is about the form field, not the paper |
|
|
104
|
+
| **ACM** (authors.acm.org, TAPS, proceedings template) | not read | not read | HTTP 403 from the origin | [LaTeX](https://authors.acm.org/proceedings/production-information/preparing-your-article-with-latex) · [TAPS](https://www.acm.org/publications/taps/word-template-workflow) · [template](https://www.acm.org/publications/proceedings-template) | `acm-sigconf`: off — not read |
|
|
105
|
+
| **Springer LNCS** (guidelines, a conference's copy; `llncsdoc` 2025) | headline, own wording | headline, all levels; corrected by typesetter | «Headings should be capitalized (i.e., nouns, verbs, and all other words except articles, prepositions, and conjunctions should be set with an initial capital)» · «Words joined by a hyphen are subject to a special rule. If the first word can stand alone, the second word should be capitalized.» · «the capitalization of the headings is checked and corrected if need be» | [guidelines](https://adc2020.github.io/documents/typeinst.pdf) · [llncsdoc](https://ctan.math.illinois.edu/macros/latex/contrib/llncs/llncsdoc.pdf) (Springer's own page asks for a login: not read) | none — a `springer-headline` variant is not built |
|
|
106
|
+
| **IEEE Editorial Style Manual** (journals) | headline, IEEE's own list | differs by level | «Prepositions of more than three letters (Before, From, Through, With, Versus, Among, Under, Between, Without) are capitalized.» · «Quaternary headings (subsect3) … only the first letter of the heading is capitalized.» | [manual (PDF)](https://journals.ieeeauthorcenter.ieee.org/wp-content/uploads/sites/7/IEEE-Editorial-Style-Manual-for-Authors.pdf) | none — journals, and an `ieee-title` variant is not built |
|
|
107
|
+
| **IEEEtran HOWTO** (class documentation: guidance) | «generally capitalized» | not stated | «Titles are generally capitalized except for words such as a, an, and, as, at, but, by, for, in, nor, of, on, or, the, to and up, which are usually not capitalized unless they are the first or last word of the title.» | [IEEEtran_HOWTO](https://us.mirrors.cicku.me/ctan/macros/latex/contrib/IEEEtran/IEEEtran_HOWTO.pdf) | `ieee-conference`, `aidc`: off |
|
|
108
|
+
| **IEEE conference template** | not read | not read | the download came back empty | [template (.docx)](https://www.ieee.org/content/dam/ieee-org/ieee/web/org/conferences/conference-template-a4.docx) | `ieee-conference`, `aidc`: off — not read |
|
|
109
|
+
| **ACL / EMNLP / NAACL** (ACLPUB) | title case, **APA** | not stated | «Write the title in title case [a link to APA title case]; do not write the title in all capital letters, except for acronyms and names (e.g., "BLEU") that are normally written in all capitals.» | [ACLPUB formatting](https://acl-org.github.io/ACLPUB/formatting.html) (`acl_latex.tex`: not read) | `realm`: off — an `apa-title` variant is not built |
|
|
110
|
+
| **APA title case** (the authority ACL links) | — | — | capitalize «words of four letters or more (e.g., 'With,' 'Between,' 'From')» and «major words, including the second part of hyphenated major words (e.g., 'Self-Report')» | [APA](https://apastyle.apa.org/style-grammar-guidelines/capitalization/title-case) | — |
|
|
111
|
+
| **NeurIPS** (2023 template; 2025 not read) | «initial caps/lower case» | **sentence**, all levels | «The paper title should be 17 point, initial caps/lower case, bold, centered between two horizontal rules.» · «All headings should be lower case (except for first word and proper nouns), flush left, and bold.» | [neurips_2023.tex](https://media.neurips.cc/Conferences/NeurIPS2023/Styles/neurips_2023.tex) | none |
|
|
112
|
+
| **ICML 2025** | «content words capitalized» | «content words capitalized», ≤ 3 levels | «The title should have content words capitalized.» · «Section headings should be numbered, flush left, and set in 11 pt bold type with the content words capitalized.» | [example_paper.pdf](https://media.icml.cc/Conferences/ICML2025/Styles/example_paper.pdf) | none |
|
|
113
|
+
| **AAAI** (an undated copy of the instructions; the 2026 kit not read) | «mixed case» | «mixed case» | «Your title must follow US capitalization rules» · first-level headings in «mixed case (initial capitals followed by lower case on all words except articles, conjunctions, and prepositions, which should appear entirely in lower case)» | [copy (PDF)](https://pages.cs.wisc.edu/~ansari/nlp-report/formatting-instructions.pdf) | none |
|
|
114
|
+
| **LIPIcs / Dagstuhl** | headline, Chicago **or** a web service | headline, all headings, `\subparagraph*` too | «For a detailed description, please use the Chicago Style Guideline or use a web service, such as http://individed.com/code/to-title-case/.» · «All headings, including the title, have to be left aligned and should be capitalized.» | [instructions](https://submission.dagstuhl.de/styles/instructions/66) | none |
|
|
115
|
+
| **ICLR 2026** | small caps (the class sets it) | small caps L1–L3 (the class) | «Paper title is 17 point, in small caps and left-aligned.» | [iclr2026_conference.tex](https://raw.githubusercontent.com/ICLR/Master-Template/master/iclr2026/iclr2026_conference.tex) | none |
|
|
116
|
+
| **USENIX**, **Elsevier**, **PMLR** | not stated | not stated | no passage on capitalization in the pages read | [USENIX](https://www.usenix.org/conferences/author-resources/paper-templates) · [Elsevier](https://www.elsevier.com/researcher/author/policies-and-guidelines/latex-instructions) · [PMLR](https://proceedings.mlr.press/faq.html) | none |
|
|
117
|
+
| **IJCAI** | not read | not read | the page is silent; the rules are in the kit, which was not opened | [authors kit](https://www.ijcai.org/authors_kit) | none |
|
|
118
|
+
| **Chicago Manual of Style** 8.159 itself | — | — | behind a login: not read. What this rule knows of Chicago is Conference Publishing's quote of it | [CMOS](https://www.chicagomanualofstyle.org/book/ed17/part2/ch08/psec159.html) | — |
|
|
119
|
+
|
|
120
|
+
Two things follow from the table. Venues speak in **two scopes**: the title, and "all headings".
|
|
121
|
+
Only the IEEE journal manual sets a level apart, which is what `levels` is for. And venues name
|
|
122
|
+
**different authorities**, which is why the style names one.
|
|
123
|
+
|
|
124
|
+
A paper whose venue has no preset here may turn the rule on in its own `paperlint.json`, with the
|
|
125
|
+
style its author kit names. Do not write `chicago-headline` for an APA or IEEE venue.
|
|
126
|
+
|
|
127
|
+
## Why not one `headline` style
|
|
128
|
+
|
|
129
|
+
Every variant above is called "headline" or "title case", and they disagree on real words:
|
|
130
|
+
|
|
131
|
+
| word, in the middle of a title | Chicago (Conference Publishing) | APA (ACL's title) | IEEE manual (title) | Springer |
|
|
132
|
+
| ------------------------------------- | ------------------------------------------------------ | -------------------------------------- | -------------------------------------------- | ------------------------------------------------ |
|
|
133
|
+
| `With`, `Between`, `From`, `Without` | lowercase («regardless of length») | **capitalized** (four letters or more) | **capitalized** (more than three letters) | lowercase (listed: «from, with, without, under») |
|
|
134
|
+
| `If`, `That`, `Because` | not on the lowercase list | `if` lowercase (a short conjunction) | **capitalized** (subordinating conjunctions) | not named |
|
|
135
|
+
| `Self-determinations` / `Self-Report` | `self` is not a bound prefix, so `Self-Determinations` | `Self-Report` capitalized | — | **`Self-determinations`** (their example) |
|
|
136
|
+
|
|
137
|
+
On 277 `acmart` papers this rule found 60 capitals it would lowercase (`Across`, `With`, `Between`,
|
|
138
|
+
`To`, `From`, `Of`, `Without`, `Against`, `And`, `Versus` …). Under Chicago every one is a correct
|
|
139
|
+
finding. Under APA or IEEE the ones of four letters or more are capitals those venues require. A
|
|
140
|
+
single value called `headline` would let a preset author write it for an ACL venue and fail correct
|
|
141
|
+
titles there at `error`. So the value names its authority, and `headline` on its own is refused
|
|
142
|
+
with a message naming `chicago-headline`.
|
|
143
|
+
|
|
144
|
+
## Adding a style
|
|
145
|
+
|
|
146
|
+
A new style is added only when a preset needs it, and the change only adds: no existing name
|
|
147
|
+
changes what it means. The names reserved for this are `apa-title`, `springer-headline`,
|
|
148
|
+
`ieee-title`, and a loose `headline` that would report only what every variant agrees on. None of
|
|
149
|
+
them exists yet. Each one needs:
|
|
150
|
+
|
|
151
|
+
1. **The venue's quote**, verbatim, with its URL and the date it was read. It goes on this page
|
|
152
|
+
and in the preset that uses the style.
|
|
153
|
+
2. **A word-class table of its own**: which words are lowercase, which are major, and which are
|
|
154
|
+
ambiguous and left unread, for that authority. The silent set belongs to the variant, not to the
|
|
155
|
+
config.
|
|
156
|
+
3. **Tests on real titles of that venue**: accepted papers built from the venue's template, with
|
|
157
|
+
the expected verdicts established by reading the papers rather than by running the rule, and
|
|
158
|
+
variants of those titles that change one thing each.
|
|
159
|
+
4. **A new member of `CaseStyle`** in `src/domain/heading-case.ts` with its judge (an exhaustive
|
|
160
|
+
`switch` makes TypeScript list every place that must handle it), and a row in the tables above.
|
|
161
|
+
|
|
162
|
+
## Examples
|
|
163
|
+
|
|
164
|
+
Failing, under `{ "title": "chicago-headline", "headings": "chicago-headline" }`:
|
|
165
|
+
|
|
166
|
+
```latex
|
|
167
|
+
\title[short form]{Measuring the wrong thing} % «short», «form» (\title[…]); «wrong», «thing» (\title)
|
|
168
|
+
\section{Related work} % «work» → «Work»
|
|
169
|
+
\subsection{The advertised savings don't show up} % «advertised», «savings», «don't», «show», «up»
|
|
170
|
+
\section{Method: a cost-aware, correctness-gated harness} % «a» (after a colon), «cost-aware», «correctness-gated», «harness»
|
|
171
|
+
\section{Discussion And Threats To Validity} % «And» → «and», «To» → «to»
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Passing:
|
|
175
|
+
|
|
176
|
+
```latex
|
|
177
|
+
\title[Short Form]{Measuring the Wrong Thing}
|
|
178
|
+
\section{Related Work}
|
|
179
|
+
\subsection{The Advertised Savings Don't Show Up}
|
|
180
|
+
\section{Method: A Cost-Aware, Correctness-Gated Harness}
|
|
181
|
+
\section{Discussion and Threats to Validity}
|
|
182
|
+
\subsection{Multi-turn Agents in CI} % a bound prefix: «Multi-Turn» passes too
|
|
183
|
+
\section{Evaluating \texttt{grep} on $k=3$} % code and math are not read
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
A finding reads:
|
|
187
|
+
|
|
188
|
+
> \section: capitalize «work» → «Work» — the last word of a heading is capitalized (chicago-headline)
|
|
189
|
+
|
|
190
|
+
**A level set apart.** A venue that wants headline style everywhere but sentence case for run-in
|
|
191
|
+
`\paragraph` headings:
|
|
192
|
+
|
|
193
|
+
```jsonc
|
|
194
|
+
"tex/heading-case": ["error", {
|
|
195
|
+
"title": "chicago-headline",
|
|
196
|
+
"headings": "chicago-headline",
|
|
197
|
+
"levels": { "paragraph": "sentence" }
|
|
198
|
+
}]
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
```latex
|
|
202
|
+
\section{Related Work} % passes: headings
|
|
203
|
+
\paragraph{Threats to validity.} % passes: paragraph is sentence
|
|
204
|
+
\paragraph{threats to validity.} % «threats» → «Threats» (sentence; not fixed)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**Sentence headings, and a title rule that names no authority.** NeurIPS asks for sentence-case
|
|
208
|
+
headings; its title rule («initial caps/lower case») names no headline variant, so leave the title
|
|
209
|
+
open:
|
|
210
|
+
|
|
211
|
+
```jsonc
|
|
212
|
+
"tex/heading-case": ["warn", { "title": "any", "headings": "sentence" }]
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
```latex
|
|
216
|
+
\section{Related work} % passes
|
|
217
|
+
\section{related work} % «related» → «Related» (sentence; not fixed)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Options / preset fields
|
|
221
|
+
|
|
222
|
+
`title` and `headings` are required; `levels` is optional; no other key is accepted, at either
|
|
223
|
+
level. The rule is **optional**, like [`pdf/last-page-balance`](../../optional-rules.md): a preset
|
|
224
|
+
turns it on, and a paper turns it off for itself with `"rules": { "tex/heading-case": "off" }` in
|
|
225
|
+
its `paperlint.json`.
|
|
226
|
+
|
|
227
|
+
ESLint replaces a rule's options as a whole, so a paper that changes one scope of its preset's
|
|
228
|
+
setting writes all of it again: `title`, `headings` and any `levels`.
|
|
229
|
+
|
|
230
|
+
**What is refused, and when.** ESLint's schema checks the shape when it loads the config; the rule
|
|
231
|
+
checks the values when ESLint loads it. Either way the run stops before anything is reported:
|
|
232
|
+
|
|
233
|
+
| you wrote | you get |
|
|
234
|
+
| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
235
|
+
| `"headline"` | refused: write `"chicago-headline"`; the other headline variants (APA, IEEE, Springer) are not implemented yet |
|
|
236
|
+
| `"off"` as a style | refused: write `"any"` for a scope with no requirement, or turn the rule off |
|
|
237
|
+
| a misspelt style (`"chicago-headlin"`, `"Sentence"`) | refused, naming the styles there are and where the bad value stands (`"levels.paragraph"`) |
|
|
238
|
+
| `"any"` for `title` and `headings`, no stricter level | refused: that is the rule turned off. Remove it from `rules` or set it to `"off"` |
|
|
239
|
+
| a missing `title` or `headings` | ESLint: `should have required property 'title'` |
|
|
240
|
+
| an unknown key (the old `"style"`, `"captions"`) | ESLint: `Unexpected property "style". Expected properties: "title", "headings", "levels".` |
|
|
241
|
+
| an unknown level (`"chapter"`) | ESLint: `Unexpected property "chapter". Expected properties: "section", "subsection", "subsubsection", "paragraph", "subparagraph".` |
|
|
242
|
+
| `"error"` with no options | ESLint accepts it, so the rule reports once at the top of each file that it judged nothing, and shows the shape to write |
|
|
243
|
+
|
|
244
|
+
A single heading that is right as written (a product that is spelled in lowercase) is kept with
|
|
245
|
+
ESLint's directive and its reason:
|
|
246
|
+
|
|
247
|
+
```latex
|
|
248
|
+
% eslint-disable-next-line tex/heading-case -- the tool is spelled in lowercase
|
|
249
|
+
\section{Evaluating vigiles}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## How a word is decided, under `chicago-headline`
|
|
253
|
+
|
|
254
|
+
Every word gets one of four classes. Only the first two can ever be reported, and the rule was
|
|
255
|
+
built so that a word it is unsure of lands in the third.
|
|
256
|
+
|
|
257
|
+
| class | words | between the first and the last word | first, last, after a colon |
|
|
258
|
+
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------------------------- |
|
|
259
|
+
| **lower** | `the a an` · `and but for or nor` · `to as` · `of at by from into onto upon via per with within without during among amongst against between across throughout toward towards amid despite versus beneath beside` | lowercase | capitalized |
|
|
260
|
+
| **major** | every word on no list: nouns, verbs, adjectives, adverbs, pronouns, `is` `it` `this` `any` `not` … | capitalized | capitalized |
|
|
261
|
+
| **either** | `up down over out off on in through under around about above below along after before behind near past inside outside beyond like than since until till vs` · `if because while when where whether although though whereas unless once so yet that how` · `using following including regarding concerning given excluding considering besides` | **not read, in either case** | capitalized |
|
|
262
|
+
| **name** | `von van de der den da di du del della la le el` | not read | not read |
|
|
263
|
+
|
|
264
|
+
The **either** class is the ambiguity rule. `up`, `over`, `out`, `off`, `on`, `in` are prepositions
|
|
265
|
+
in one title and particles in another (_Scaling up_, _Turning Off the Cache_), `if`, `while`,
|
|
266
|
+
`that`, `than` are conjunctions the publisher's list does not name, and `using`, `following` are
|
|
267
|
+
prepositions in some grammars and verbs in others. For these the rule says nothing in the middle of
|
|
268
|
+
a title, in either case, and never offers a fix. At the ends and after a colon the case is not in
|
|
269
|
+
doubt: a title begins and ends with a capital.
|
|
270
|
+
|
|
271
|
+
A finding at error level that is wrong costs more than a finding missed, so the rule also does not
|
|
272
|
+
read:
|
|
273
|
+
|
|
274
|
+
- a word with a capital anywhere past its first letter (`LLM`, `LLMs`, `GitHub`, `iOS`);
|
|
275
|
+
- a single letter other than the lowercase article (`k`, `n`, and the capital in `Module A`);
|
|
276
|
+
- anything with a digit, a dot, a slash or a TeX accent in it (`GPT-4`, `e.g.`,
|
|
277
|
+
`input/output`, `Caf\'e`);
|
|
278
|
+
- a word followed by a full stop before the title ends (`al.`, `etc.`, `vs.`, `cf.`), and the
|
|
279
|
+
abbreviations `et`, `al`, `etc`, `cf`, `eg`, `ie`, `approx`, `viz` wherever they stand;
|
|
280
|
+
- a word whose capital is not one letter, such as one starting with the ligature `fi` (its capital
|
|
281
|
+
is `FI`);
|
|
282
|
+
- everything set in math or code, and every command whose text is not plain: `\texttt`, `\textsc`,
|
|
283
|
+
`\cite`, `\ref`, … A formatting command is read as the words it wraps (`\emph{very}`, `\textbf{…}`,
|
|
284
|
+
`\textit{…}`); `\label`, `\footnote`, `\thanks` and `\index` are not part of the title.
|
|
285
|
+
A group written right after a macro of your own (`\ours{…}`, `\finding{label}{a sentence}`) is
|
|
286
|
+
that macro's argument, and is not read either.
|
|
287
|
+
|
|
288
|
+
A word that stands right beside something the rule does not read is not known to be first or
|
|
289
|
+
last, so a minor word there is left as it is (`\texttt{grep} And Friends`, `Results For $k$`,
|
|
290
|
+
`Fast And \cite{x} Safe`).
|
|
291
|
+
|
|
292
|
+
A `%` comment inside a title ends its line: the words on either side of it are two words. Text
|
|
293
|
+
inside `\iffalse … \fi` is not read at all — TeX never reads it, and neither does any paperlint
|
|
294
|
+
rule that reads the LaTeX tree.
|
|
295
|
+
|
|
296
|
+
### A title in parts
|
|
297
|
+
|
|
298
|
+
A title or heading can have parts: a subtitle after a colon, a question or exclamation mark, a
|
|
299
|
+
dash (`--`, `---`, `—`), or a line break (`\\`, `\\[1ex]`, `\newline`, `\linebreak`). Chicago
|
|
300
|
+
capitalizes the first and the last word of a title and of its subtitle, so:
|
|
301
|
+
|
|
302
|
+
- the first word of a part is a start. A word of the **lower** class there is not asked either way
|
|
303
|
+
(`Agents and Tools:\\ The Empirical Study`, `Main Title\\ The Subtitle`); after a colon it is
|
|
304
|
+
capitalized, as above;
|
|
305
|
+
- the last word of a part is the end of a title. A word of the **lower** class there may be a
|
|
306
|
+
particle (_What Is It Good For: An Analysis_) or a preposition the author ends on, so it is not
|
|
307
|
+
asked either way either (`Agents to Talk To --- A Study` and `… Talk to --- …` both pass).
|
|
308
|
+
|
|
309
|
+
### Hyphenated compounds
|
|
310
|
+
|
|
311
|
+
The first element is capitalized. Each later element is lowercase when it is an article, a
|
|
312
|
+
preposition or a conjunction (_Peer-to-Peer_, _State-of-the-Art_, _Question-and-Answer_), and
|
|
313
|
+
capitalized otherwise (_Cost-Aware_, _Output-Trimming_, _Self-Supervised_, _Fine-Tuning_).
|
|
314
|
+
|
|
315
|
+
After a **bound prefix** the second element is not read — _Multi-turn_ and _Multi-Turn_ both pass.
|
|
316
|
+
The publisher's text asks for lowercase there («Multi-stage, Non-termination») and adds «unless the
|
|
317
|
+
second element is a proper noun / proper adjective» (_Non-Western_), and the rule cannot tell a
|
|
318
|
+
prefix from a first element that merely looks like one. The list is small and fixed:
|
|
319
|
+
|
|
320
|
+
`anti` `co` `de` `inter` `intra` `multi` `non` `post` `pre` `pseudo` `quasi` `re` `semi` `sub`
|
|
321
|
+
`trans` `ultra` `un`
|
|
322
|
+
|
|
323
|
+
Not on it: `self` (_Self-Supervised_ capitalizes), `cross`, `meta`, `over`, `under`, `micro`,
|
|
324
|
+
`mini`, `super`, `mid`, `counter`, `pro` — each stands by itself, or is not certain not to. A
|
|
325
|
+
compound with a single-letter element (`k-means`, `e-mail`, `x-axis`) is not read.
|
|
326
|
+
|
|
327
|
+
### Sentence
|
|
328
|
+
|
|
329
|
+
Sentence case cannot be judged word by word: a proper noun (_Python_, _Alice_, _Bayesian_) is
|
|
330
|
+
capitalized in the middle of a sentence-case title, and nothing in the text tells it from an
|
|
331
|
+
over-capitalized word. So the style asks for the first word only, and offers no fix. If you need
|
|
332
|
+
more, it is a case for a dictionary of names and is not built.
|
|
333
|
+
|
|
334
|
+
## Prior art — why this is not `title-case`
|
|
335
|
+
|
|
336
|
+
Checked before writing it, as this repository asks. The four npm libraries that title-case a string
|
|
337
|
+
were installed and run on the same headings (2026-10-03; `title-case` 4.3.2, `ap-style-title-case`
|
|
338
|
+
2.0.0, `titlecase` 1.1.3, `chicago-capitalize` 0.1.0). Each turns a string into a string; none says
|
|
339
|
+
where a word stands or which word it was unsure of, and they disagree with each other where the
|
|
340
|
+
publisher's text is specific or silent:
|
|
341
|
+
|
|
342
|
+
| input | `title-case` | `ap-style-title-case` | `titlecase` | `chicago-capitalize` | the publisher |
|
|
343
|
+
| ------------------------------------------ | ------------------------- | ------------------------- | ------------------------- | ------------------------- | ---------------------------------------- |
|
|
344
|
+
| `Multi-turn agents in the wild` | `Multi-Turn …` | `Multi-Turn …` | `Multi-Turn …` | `Multi-Turn …` | lowercase after a prefix (`Multi-stage`) |
|
|
345
|
+
| `Non-trivial pre-trained models` | `Non-Trivial Pre-Trained` | `Non-Trivial Pre-Trained` | `Non-Trivial Pre-Trained` | `Non-Trivial Pre-Trained` | lowercase after a prefix |
|
|
346
|
+
| `Results for $k=3$` | `… $K=3$` | `… $k=3$` | `… $K=3$` | `… $K=3$` | math is not text |
|
|
347
|
+
| `Looking at the data over time` | `… Data over Time` | `… Data Over Time` | `… Data Over Time` | `… Data Over Time` | `over` is not decided |
|
|
348
|
+
| `Scaling up the pipeline` | `Scaling up …` | `Scaling up …` | `Scaling Up …` | `Scaling up …` | `up` is not decided |
|
|
349
|
+
| `Why the tool is safe if used as intended` | `… if Used as …` | `… If Used As …` | `… if Used as …` | `… if Used as …` | `as` lowercase; `if` is not named |
|
|
350
|
+
|
|
351
|
+
A checker built on them would compare a string with its title-cased copy and report every place the
|
|
352
|
+
two disagree: the first three rows are findings that are wrong, the last three are three different
|
|
353
|
+
answers to a question the publisher leaves open. `title-case` takes a `smallWords` option, so the
|
|
354
|
+
next question was whether our own lists inside it would do. They do not (`title-case` 4.3.2 with
|
|
355
|
+
`smallWords` set to the lowercase class above):
|
|
356
|
+
|
|
357
|
+
| input | result | what is wrong |
|
|
358
|
+
| --------------------------- | --------------------------- | -------------------------------------------------------- |
|
|
359
|
+
| `iOS builds and k-means` | `IOS Builds and K-Means` | a name and a symbol are rewritten |
|
|
360
|
+
| `Pitfalls, e.g., timeouts` | `Pitfalls, E.g., Timeouts` | an abbreviation is rewritten |
|
|
361
|
+
| `\texttt{grep} and friends` | `\Texttt{grep} and Friends` | a command name is rewritten |
|
|
362
|
+
| `Fast And $k$` | `Fast And $K$` | math is rewritten |
|
|
363
|
+
| `multi-turn agents` | `Multi-Turn Agents` | no way to say «a prefix leaves its second element alone» |
|
|
364
|
+
| `scaling up the pipeline` | `Scaling Up the Pipeline` | no third value: a word is lower or it is not |
|
|
365
|
+
|
|
366
|
+
It also returns no offset, which a fix needs, and its own list puts `only`, `some` and `neither`
|
|
367
|
+
among the lowercase words, which the publisher's text makes major. What is reusable is a `toUpperCase`;
|
|
368
|
+
the rule is the word classes, the places, the compounds and what it leaves unread, so it is written
|
|
369
|
+
here.
|
|
370
|
+
|
|
371
|
+
## Measured on real ACM papers
|
|
372
|
+
|
|
373
|
+
A rule that judges a venue's requirement is validated on papers of that venue, not on fixtures its
|
|
374
|
+
author wrote. Two corpora, 2026-10-03, both measured on headings, before the rule read `\title`:
|
|
375
|
+
|
|
376
|
+
- **The accepted paper in this repository**, `fixtures/accepted-papers/agenticdev-acm26`: 9
|
|
377
|
+
headings, 6 of them in sentence case, which the vendor's checklist does not accept. The rule
|
|
378
|
+
reports 18 words, every one a true positive, and its fixes write the six corrected
|
|
379
|
+
headings ([`fixtures/accepted-papers/README.md`](../../../fixtures/accepted-papers/README.md)).
|
|
380
|
+
Its `\title` and short title, read since 2026-10-04, are already in headline style and add no
|
|
381
|
+
finding.
|
|
382
|
+
- **277 `acmart` sources from arXiv** (authors' versions of papers whose arXiv comment names an ACM
|
|
383
|
+
venue — ICSE, ASE, FSE, ISSTA, CCS, CHI, CSCW, MSR and others; acceptance was **not** verified
|
|
384
|
+
paper by paper, and they are not the copy-edited proceedings versions, so many are in sentence
|
|
385
|
+
case). Not committed: the licences differ. 9 515 headings; 93 papers drew no finding, 184 drew
|
|
386
|
+
2 697 findings, and **a finding is not a miss of the rule**: in a sentence-case paper nearly every
|
|
387
|
+
heading is one. The titles of this corpus have not been run.
|
|
388
|
+
|
|
389
|
+
On the second corpus the findings were read, not counted: all 60 where a capital would become
|
|
390
|
+
lowercase (`Across`, `With`, `Between`, `To`, `From`, `Of`, `Without`, `Against`, `And`, `Versus`
|
|
391
|
+
…), every compound, every flagged word of six letters or fewer, and every finding in the 59 papers
|
|
392
|
+
with one or two. Three false-finding classes came out of that reading, each now a test:
|
|
393
|
+
|
|
394
|
+
| what the rule did | what it was | now |
|
|
395
|
+
| ----------------------------------------------------------------------- | ------------------------------------------------------------------------ | ---------------------------------------------------- |
|
|
396
|
+
| lowercased `A` in `Module A: Element Relation` | a capital letter that labels something, not an article | a single letter other than lowercase `a` is not read |
|
|
397
|
+
| capitalized `using`, `following`, `including`, `given` | prepositions in some grammars, verbs in others | in the **either** class |
|
|
398
|
+
| read the words of `\finding{label}{a sentence of words}` as title words | a group right after a macro of the author's own is that macro's argument | not read |
|
|
399
|
+
|
|
400
|
+
One class remains and is documented, not fixed: a **lowercase name set in plain text** is read as a
|
|
401
|
+
lowercase word (`\paragraph{libssh}`, `keygen`: 2 findings in 2 697). The rule cannot tell a tool
|
|
402
|
+
from a noun without a dictionary; set the name in `\texttt{}` or keep it with a directive (above).
|
|
403
|
+
|
|
404
|
+
## What it does not check
|
|
405
|
+
|
|
406
|
+
- A title or heading in **sentence** style past its first word, for the reason above.
|
|
407
|
+
- A word of the **either** class in the middle of a title, in either case.
|
|
408
|
+
- Whether a word is a proper noun, except as a capital inside it: `Python` and `python` are both
|
|
409
|
+
words the rule reads as «major», so a lowercase product name (`npm`, `vigiles`) is reported
|
|
410
|
+
like any lowercase word. Set it in `\texttt{}` or keep it with a directive.
|
|
411
|
+
- A `\title` in a file the **preamble** includes: paperlint lints the files the body includes, not
|
|
412
|
+
the preamble's (those hold macros, not the paper). Keep `\title` in `paper.tex`, or in a file
|
|
413
|
+
included after `\begin{document}`.
|
|
414
|
+
- `\subtitle`, `\caption`, a table's header, or a run-in label set with `\textbf{…}`: the title and
|
|
415
|
+
the headings above only.
|
|
416
|
+
- Spelling, and whether a heading is a good one.
|
|
417
|
+
|
|
418
|
+
## How to fix
|
|
419
|
+
|
|
420
|
+
`paperlint lint --fix` writes every fix the rule is sure of. A finding it did not fix (a word split
|
|
421
|
+
by markup, or in the **sentence** style) names the word and the form it wants: edit it by hand. If
|
|
422
|
+
the heading is right as written, keep it with a directive and its reason. If the venue does not
|
|
423
|
+
ask for this style at all, set `"rules": { "tex/heading-case": "off" }` in the paper's
|
|
424
|
+
`paperlint.json`.
|