@citestyle/registry 0.0.2 → 1.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/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # @citestyle/registry
2
2
 
3
- Citation registry that manages cross-citation state for a compiled CSL style. Handles citation numbering, bibliography sorting, year-suffix disambiguation, name disambiguation, cite collapsing, and subsequent-author-substitute.
3
+ Citation registry for managing cross-reference state across a document. When you have multiple citations and need them to interact — numbered references, year-suffix disambiguation (Smith 2024a, 2024b), cite collapsing ([1-3, 5]), sorted bibliographies — the registry handles it.
4
+
5
+ For one-off formatting where citations don't interact, this package also exports a simpler `format()` API that needs no setup.
4
6
 
5
7
  ## Installation
6
8
 
@@ -8,16 +10,14 @@ Citation registry that manages cross-citation state for a compiled CSL style. Ha
8
10
  npm install @citestyle/registry
9
11
  ```
10
12
 
11
- ## Usage
13
+ ## Quick start
12
14
 
13
- ```js
15
+ ```javascript
14
16
  import { createRegistry } from '@citestyle/registry'
15
17
  import * as apa from '@citestyle/styles/apa'
16
18
 
17
- // Create a registry bound to a compiled style
18
19
  const registry = createRegistry(apa)
19
20
 
20
- // Add items (assigns citation numbers, triggers disambiguation)
21
21
  registry.addItems([
22
22
  {
23
23
  id: 'smith2024',
@@ -40,84 +40,129 @@ registry.addItems([
40
40
  },
41
41
  ])
42
42
 
43
- // Format an inline citation
44
- const citation = registry.cite([{ id: 'smith2024' }])
45
- console.log(citation.text) // (Smith, 2024)
46
- console.log(citation.html) // <span class="csl-citation">(Smith, 2024)</span>
43
+ // Inline citation
44
+ registry.cite([{ id: 'smith2024' }])
45
+ // → { text: '(Smith, 2024)', html: '<span class="csl-citation">...</span>' }
47
46
 
48
- // Citation with locator
49
- const withPage = registry.cite([
50
- { id: 'smith2024', locator: '105', label: 'page' },
51
- ])
52
- console.log(withPage.text) // (Smith, 2024, p. 105)
47
+ // Citation with page locator
48
+ registry.cite([{ id: 'smith2024', locator: '105', label: 'page' }])
49
+ // → { text: '(Smith, 2024, p. 105)', html: '...' }
53
50
 
54
- // Multi-cite
55
- const multi = registry.cite([
56
- { id: 'smith2024' },
57
- { id: 'doe2023' },
58
- ])
59
- console.log(multi.text) // (Doe, 2023; Smith, 2024)
51
+ // Multi-cite (sorted per style rules)
52
+ registry.cite([{ id: 'smith2024' }, { id: 'doe2023' }])
53
+ // → { text: '(Doe, 2023; Smith, 2024)', html: '...' }
60
54
 
61
- // Get the full bibliography (sorted per style rules)
55
+ // Full bibliography — sorted, numbered, disambiguated
62
56
  const entries = registry.getBibliography()
63
- for (const entry of entries) {
64
- console.log(entry.text) // Plain text
65
- console.log(entry.html) // Semantic HTML with CSS classes
66
- }
57
+ entries[0].text // Plain text
58
+ entries[0].html // Semantic HTML with CSS classes and linked DOIs
59
+ entries[0].parts // Decomposed fields for custom layouts
60
+ entries[0].links // Extracted DOI, URL links
61
+ ```
62
+
63
+ ## Simple API (no registry)
64
+
65
+ When you just need to format one or a few items and don't need cross-reference features:
67
66
 
68
- // Check registry size
69
- console.log(registry.size) // 2
67
+ ```javascript
68
+ import { format, formatAll, formatCitation } from '@citestyle/registry'
69
+ import * as apa from '@citestyle/styles/apa'
70
+
71
+ // Single bibliography entry
72
+ const entry = format(apa, item)
73
+ // → { html, text, parts, links }
74
+
75
+ // Multiple entries (sorted per style rules, auto-numbered)
76
+ const entries = formatAll(apa, [item1, item2, item3])
77
+
78
+ // Single inline citation
79
+ const cite = formatCitation(apa, [{ item, locator: '42', label: 'page' }])
80
+ // → { html, text }
70
81
  ```
71
82
 
72
- ## API
83
+ Use `createRegistry()` instead when you need any of the cross-reference features below.
73
84
 
74
- ### `createRegistry(style, options?)`
85
+ ## When to use the registry vs. `format()`
75
86
 
76
- Create a new registry for a compiled CSL style.
87
+ | Feature | `format()` | `createRegistry()` |
88
+ |---|---|---|
89
+ | Format a bibliography entry | Yes | Yes |
90
+ | Format a citation | Yes | Yes |
91
+ | Sort bibliography | Yes | Yes |
92
+ | Citation numbering (IEEE, Vancouver) | No | Yes |
93
+ | Year-suffix disambiguation (2024a, 2024b) | No | Yes |
94
+ | Name disambiguation (expand initials/names) | No | Yes |
95
+ | Cite collapsing ([1-3] or "Smith 2020, 2021") | No | Yes |
96
+ | Subsequent-author-substitute (em-dash) | No | Yes |
77
97
 
78
- - `style` -- A compiled style module (must export `bibliography` or `citation`)
79
- - `options.subsequentAuthorSubstitute` (string) -- Override the style's substitute string (e.g., `"---"`)
98
+ **Rule of thumb**: use `format()` for publication lists, portfolio pages, and anywhere each entry stands alone. Use `createRegistry()` for documents — papers, articles, blog posts — where citations reference and interact with each other.
80
99
 
81
- Returns a `Registry` object.
100
+ ## API
101
+
102
+ ### `createRegistry(style, options?)`
103
+
104
+ Create a new registry bound to a compiled style.
82
105
 
83
- ### Registry Methods
106
+ - `style` — A compiled style module (from `@citestyle/styles/*` or your own compiled `.js`)
107
+ - `options.subsequentAuthorSubstitute` (string) — Override the style's substitute string (e.g., `"---"`)
84
108
 
85
- #### `addItems(items)`
109
+ ### `registry.addItems(items)`
86
110
 
87
- Add CSL-JSON items to the registry. Items are stored by `id` and assigned citation numbers in insertion order. Duplicate IDs update the existing item.
111
+ Add CSL-JSON items. Items are stored by `id` and assigned citation numbers in insertion order. Adding an item with a duplicate ID updates the existing entry.
88
112
 
89
- #### `getItem(id)`
113
+ ### `registry.getItem(id)`
90
114
 
91
115
  Look up a single item by ID. Returns `undefined` if not found.
92
116
 
93
- #### `cite(cites, ctx?)`
117
+ ### `registry.cite(cites, ctx?)`
94
118
 
95
- Format a citation cluster. Each cite object can include:
119
+ Format a citation cluster. Each cite can include:
96
120
 
97
121
  | Property | Type | Description |
98
122
  |---|---|---|
99
- | `id` | string | Item ID (resolved from registry) |
123
+ | `id` | string | Item ID (looked up from registry) |
100
124
  | `item` | CslItem | Pre-resolved item (bypasses lookup) |
101
- | `locator` | string | Locator value (e.g., page number) |
102
- | `label` | string | Locator label (`'page'`, `'chapter'`, etc.) |
103
- | `prefix` | string | Text before the citation |
104
- | `suffix` | string | Text after the citation |
125
+ | `locator` | string | Locator value (page number, chapter, etc.) |
126
+ | `label` | string | Locator label: `'page'`, `'chapter'`, `'section'`, etc. |
127
+ | `prefix` | string | Text inserted before the citation |
128
+ | `suffix` | string | Text appended after the citation |
105
129
 
106
130
  Returns `{ text: string, html: string }`.
107
131
 
108
- #### `getBibliography(ctx?)`
132
+ ### `registry.getBibliography(ctx?)`
133
+
134
+ Get the full formatted bibliography. Items are sorted per the style's sort rules. Returns an array of `FormattedEntry` objects:
135
+
136
+ ```javascript
137
+ {
138
+ text: string, // Plain text
139
+ html: string, // Semantic HTML with CSS classes and auto-linked DOIs
140
+ parts: object, // Decomposed fields (authors, year, title, ...)
141
+ links: object, // Extracted links (doi, url)
142
+ }
143
+ ```
144
+
145
+ ### `registry.size`
146
+
147
+ Read-only property: number of items in the registry.
148
+
149
+ ### `format(style, item, ctx?)`
150
+
151
+ Format a single bibliography entry without a registry. Returns `{ text, html, parts, links }`.
152
+
153
+ ### `formatAll(style, items, ctx?)`
109
154
 
110
- Get the formatted bibliography. Items are sorted per the style's sort rules. Returns an array of `FormattedEntry` objects, each with `{ text, html, parts, links }`.
155
+ Format multiple bibliography entries. Applies the style's sort order and assigns citation numbers. Returns an array of `{ text, html, parts, links }`.
111
156
 
112
- #### `size`
157
+ ### `formatCitation(style, cites, ctx?)`
113
158
 
114
- Read-only property returning the number of items in the registry.
159
+ Format a single citation cluster without a registry. Each cite must include an `item` property (not an `id`, since there's no registry to look it up from). Returns `{ text, html }`.
115
160
 
116
- ## Features
161
+ ## What the registry handles automatically
117
162
 
118
- - **Citation numbering**: Numeric styles (IEEE, Vancouver) get auto-assigned numbers
119
- - **Bibliography sorting**: Uses the style's compiled sort comparator
120
- - **Year-suffix**: Detects author+year collisions and assigns a/b/c suffixes
121
- - **Name disambiguation**: `disambiguate-add-givenname` (5 rules) and `disambiguate-add-names`
122
- - **Cite collapsing**: Numeric ranges (`[1-3, 5]`) and author-date grouping (`Smith, 2020, 2021`)
123
- - **Subsequent-author-substitute**: Replaces repeated authors in bibliography (e.g., with em-dash)
163
+ - **Citation numbering** — Numeric styles (IEEE, Vancouver) get auto-assigned `[1]`, `[2]`, etc. in insertion order
164
+ - **Bibliography sorting** — Uses the style's compiled sort comparator (alphabetical for APA, insertion-order for IEEE, etc.)
165
+ - **Year-suffix disambiguation** — When two items share the same author(s) and year, the registry assigns suffixes: Smith (2024a), Smith (2024b)
166
+ - **Name disambiguation** — Expands initials or adds names to distinguish ambiguous citations, following the style's `disambiguate-add-givenname` rules (5 rule variants supported)
167
+ - **Cite collapsing** — Numeric ranges: `[1, 2, 3, 5]` → `[1-3, 5]`. Author-date grouping: `(Smith 2020; Smith 2021)` → `(Smith 2020, 2021)`
168
+ - **Subsequent-author-substitute** — Replaces repeated authors in the bibliography with a dash or other substitute string, per the style's rules
package/package.json CHANGED
@@ -1,7 +1,22 @@
1
1
  {
2
2
  "name": "@citestyle/registry",
3
- "version": "0.0.2",
4
- "description": "Citation registry: year-suffixes, numbering, sorting (~5-8KB)",
3
+ "version": "1.0.0",
4
+ "description": "Citation registry: year-suffixes, numbering, sorting, disambiguation (~5-8KB)",
5
+ "author": "Uniweb",
6
+ "homepage": "https://github.com/uniweb/csl/tree/main/packages/registry",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/uniweb/csl.git",
10
+ "directory": "packages/registry"
11
+ },
12
+ "keywords": [
13
+ "csl",
14
+ "citation",
15
+ "registry",
16
+ "bibliography",
17
+ "disambiguation",
18
+ "year-suffix"
19
+ ],
5
20
  "type": "module",
6
21
  "exports": {
7
22
  ".": {
@@ -15,8 +30,8 @@
15
30
  "README.md"
16
31
  ],
17
32
  "dependencies": {
18
- "@citestyle/core": "0.0.2",
19
- "@citestyle/types": "0.0.2"
33
+ "@citestyle/core": "1.0.0",
34
+ "@citestyle/types": "1.0.0"
20
35
  },
21
36
  "devDependencies": {
22
37
  "vitest": "^3.1.1"
@@ -26,7 +41,6 @@
26
41
  },
27
42
  "license": "MIT",
28
43
  "scripts": {
29
- "test": "vitest run --passWithNoTests",
30
- "lint": "echo 'TODO: configure linter'"
44
+ "test": "vitest run --passWithNoTests"
31
45
  }
32
46
  }
package/src/format.js ADDED
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Simple formatting API — format items without a full registry.
3
+ *
4
+ * Use these for one-off formatting where you don't need cross-reference
5
+ * features (year-suffix, citation numbering, disambiguation, collapsing).
6
+ * For documents with multiple citations, use createRegistry() instead.
7
+ */
8
+
9
+ /**
10
+ * Format a single bibliography entry.
11
+ *
12
+ * @param {import('@citestyle/types').CompiledStyle} style - A compiled CSL style module
13
+ * @param {import('@citestyle/types').CslItem} item - CSL-JSON item
14
+ * @param {import('@citestyle/types').FormatContext} [ctx] - Optional format context
15
+ * @returns {import('@citestyle/types').FormattedEntry}
16
+ */
17
+ export function format(style, item, ctx = {}) {
18
+ if (!style?.bibliography) {
19
+ throw new Error('format() requires a compiled style with a bibliography() function')
20
+ }
21
+ return style.bibliography(item, ctx)
22
+ }
23
+
24
+ /**
25
+ * Format multiple bibliography entries with basic sorting.
26
+ *
27
+ * Items are sorted using the style's sort comparator (if any) and assigned
28
+ * citation numbers in order. Does NOT perform year-suffix disambiguation,
29
+ * name disambiguation, or subsequent-author-substitute — use createRegistry()
30
+ * for those features.
31
+ *
32
+ * @param {import('@citestyle/types').CompiledStyle} style - A compiled CSL style module
33
+ * @param {import('@citestyle/types').CslItem[]} items - CSL-JSON items
34
+ * @param {import('@citestyle/types').FormatContext} [ctx] - Optional format context
35
+ * @returns {import('@citestyle/types').FormattedEntry[]}
36
+ */
37
+ export function formatAll(style, items, ctx = {}) {
38
+ if (!style?.bibliography) {
39
+ throw new Error('formatAll() requires a compiled style with a bibliography() function')
40
+ }
41
+ let sorted = [...items]
42
+ if (style.bibliographySort) {
43
+ sorted.sort(style.bibliographySort)
44
+ }
45
+ // Assign citation numbers (shallow-clone to avoid mutating user's items)
46
+ sorted = sorted.map((item, i) => ({ ...item, 'citation-number': i + 1 }))
47
+ return sorted.map(item => style.bibliography(item, ctx))
48
+ }
49
+
50
+ /**
51
+ * Format a single inline citation.
52
+ *
53
+ * @param {import('@citestyle/types').CompiledStyle} style - A compiled CSL style module
54
+ * @param {import('@citestyle/types').CiteRef[]} cites - Citation references with items
55
+ * @param {import('@citestyle/types').FormatContext} [ctx] - Optional format context
56
+ * @returns {import('@citestyle/types').FormattedCitation}
57
+ */
58
+ export function formatCitation(style, cites, ctx = {}) {
59
+ if (!style?.citation) {
60
+ throw new Error('formatCitation() requires a compiled style with a citation() function')
61
+ }
62
+ // Assign citation numbers if not already set (shallow-clone to avoid mutating user's items)
63
+ const safeCites = cites.map((cite, i) => {
64
+ if (cite.item && cite.item['citation-number'] == null) {
65
+ return { ...cite, item: { ...cite.item, 'citation-number': i + 1 } }
66
+ }
67
+ return cite
68
+ })
69
+ return style.citation(safeCites, ctx)
70
+ }
package/src/index.js CHANGED
@@ -8,6 +8,10 @@
8
8
  * - Citation number tracking (numeric styles)
9
9
  * - Bibliography sorting (using compiled comparator)
10
10
  * - Subsequent-author-substitute
11
+ *
12
+ * Also provides simple format/formatAll/formatCitation helpers for
13
+ * one-off formatting without a full registry.
11
14
  */
12
15
 
13
16
  export { createRegistry } from './registry.js'
17
+ export { format, formatAll, formatCitation } from './format.js'
package/types.d.ts CHANGED
@@ -1 +1 @@
1
- export { createRegistry, Registry, RegistryOptions } from '@citestyle/types'
1
+ export { createRegistry, format, formatAll, formatCitation, Registry, RegistryOptions } from '@citestyle/types'