punctilio 4.3.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +36 -22
  2. package/dist/constants.d.ts +0 -34
  3. package/dist/constants.d.ts.map +1 -1
  4. package/dist/constants.js +0 -49
  5. package/dist/constants.js.map +1 -1
  6. package/dist/dashes.d.ts +11 -7
  7. package/dist/dashes.d.ts.map +1 -1
  8. package/dist/dashes.js +1170 -176
  9. package/dist/dashes.js.map +1 -1
  10. package/dist/index.d.ts +14 -118
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +65 -116
  13. package/dist/index.js.map +1 -1
  14. package/dist/markdown.js +1 -1
  15. package/dist/markdown.js.map +1 -1
  16. package/dist/nbsp.d.ts +19 -13
  17. package/dist/nbsp.d.ts.map +1 -1
  18. package/dist/nbsp.js +214 -69
  19. package/dist/nbsp.js.map +1 -1
  20. package/dist/prose-view.d.ts +52 -1
  21. package/dist/prose-view.d.ts.map +1 -1
  22. package/dist/prose-view.js +179 -17
  23. package/dist/prose-view.js.map +1 -1
  24. package/dist/quote-classifier.d.ts +5 -4
  25. package/dist/quote-classifier.d.ts.map +1 -1
  26. package/dist/quote-classifier.js +601 -96
  27. package/dist/quote-classifier.js.map +1 -1
  28. package/dist/quotes.d.ts +12 -4
  29. package/dist/quotes.d.ts.map +1 -1
  30. package/dist/quotes.js +24 -27
  31. package/dist/quotes.js.map +1 -1
  32. package/dist/rehype.d.ts +53 -8
  33. package/dist/rehype.d.ts.map +1 -1
  34. package/dist/rehype.js +105 -62
  35. package/dist/rehype.js.map +1 -1
  36. package/dist/remark.d.ts +1 -1
  37. package/dist/remark.d.ts.map +1 -1
  38. package/dist/remark.js +6 -9
  39. package/dist/remark.js.map +1 -1
  40. package/dist/symbols.d.ts +25 -14
  41. package/dist/symbols.d.ts.map +1 -1
  42. package/dist/symbols.js +812 -220
  43. package/dist/symbols.js.map +1 -1
  44. package/dist/transform-options.d.ts +97 -0
  45. package/dist/transform-options.d.ts.map +1 -0
  46. package/dist/transform-options.js +34 -0
  47. package/dist/transform-options.js.map +1 -0
  48. package/dist/utils.d.ts +0 -16
  49. package/dist/utils.d.ts.map +1 -1
  50. package/dist/utils.js +0 -56
  51. package/dist/utils.js.map +1 -1
  52. package/package.json +6 -2
  53. package/src/constants.ts +0 -56
  54. package/src/dashes.ts +1217 -208
  55. package/src/index.ts +71 -291
  56. package/src/markdown.ts +1 -1
  57. package/src/nbsp.ts +255 -78
  58. package/src/prose-view.ts +250 -25
  59. package/src/quote-classifier.ts +618 -97
  60. package/src/quotes.ts +36 -19
  61. package/src/rehype.ts +169 -88
  62. package/src/remark.ts +6 -11
  63. package/src/symbols.ts +814 -251
  64. package/src/transform-options.ts +143 -0
  65. package/src/utils.ts +0 -82
package/README.md CHANGED
@@ -80,28 +80,20 @@ _Note on benchmark construction: I assembled the initial cases myself. I then so
80
80
 
81
81
  Setting aside the benchmark, `punctilio`’s test suite runs at 100% branch coverage with well over a thousand tests, including edge cases derived from competitor libraries ([`smartquotes`](https://github.com/kellym/smartquotes.js), [`retext-smartypants`](https://github.com/retextjs/retext-smartypants), [`typograf`](https://github.com/typograf/typograf)) and the [Standard Ebooks typography manual](https://standardebooks.org/manual/). The 100% figure isn’t hand-maintained: Jest’s `coverageThreshold` requires 100% branches, functions, lines, and statements, CI fails below that, and the coverage badge above is regenerated from the actual coverage report on every push to `main`. I also verify that all transformations are stable when applied multiple times. Uses [`recheck`](https://makenowjust-labs.github.io/recheck/) to statically verify the absence of inefficient RegEx patterns.
82
82
 
83
- ## Works with HTML DOMs via separation boundaries
83
+ ## Works with HTML DOMs via boundary-aware views
84
84
 
85
- Perhaps the most innovative feature of the library is that it properly handles DOMs! Other typography libraries take one of two approaches, both with drawbacks. 
85
+ Perhaps the most innovative feature of the library is that it properly handles DOMs! Other typography libraries take one of two approaches, both with drawbacks.
86
86
 
87
- 1. String-based libraries (like [`smartypants`](https://www.npmjs.com/package/smartypants)) transform plain text but are unaware of HTML structure. If you flatten text from `"<em>"Wait</em>"` into `"Wait"`, transform the text so that it has smart quotes (`“Wait”`), and then try to convert back—you've lost track of where the `</em>` belongs. 
88
- 2. AST-based libraries (like [`rehype-retext`](https://github.com/rehypejs/rehype-retext)) process each text node individually, preserving structure but losing cross-node information. A quote that opens inside `<em>"Wait</em>` and closes outside it `"` spans two text nodes. Processed independently, the library can't tell whether the final `"` is opening or closing, because it never sees both at once. 
87
+ 1. String-based libraries (like [`smartypants`](https://www.npmjs.com/package/smartypants)) transform plain text but are unaware of HTML structure. If you flatten text from `"<em>"Wait</em>"` into `"Wait"`, transform the text so that it has smart quotes (`“Wait”`), and then try to convert back—you've lost track of where the `</em>` belongs.
88
+ 2. AST-based libraries (like [`rehype-retext`](https://github.com/rehypejs/rehype-retext)) process each text node individually, preserving structure but losing cross-node information. A quote that opens inside `<em>"Wait</em>` and closes outside it `"` spans two text nodes. Processed independently, the library can't tell whether the final `"` is opening or closing, because it never sees both at once.
89
89
 
90
- `punctilio` introduces _separation boundaries_ to get the best of both worlds:
90
+ `punctilio` gets the best of both worlds with a _ProseView_: a view over a sequence of text nodes that exposes their concatenated text plus the offsets where one node ends and the next begins.
91
91
 
92
- 1. Flatten the parent container's contents to a string, delimiting element boundaries with a two-character private-use Unicode sentinel (`U+E000 U+E001`) to avoid unintended matches.
93
- 2. Every regex allows (and preserves) these characters, treating them as boundaries of a “permeable membrane” through which contextual information flows. For example, `.U+E000..` still becomes `…U+E000`.
94
- 3. Rehydrate the HTML AST. For all _k_, set element _k_’s text content to the segment starting at separator occurrence _k_.
92
+ 1. Every pass scans the full concatenated text, so cross-node context (the closing `"` above) is always visible.
93
+ 2. Passes consult the node boundaries explicitly — a rule can treat a boundary as transparent, as a word boundary, or as a blocker, matching what the markup means.
94
+ 3. Edits are queued by offset and committed back onto the source text nodes, so the HTML structure is never lost and never has to be re-derived.
95
95
 
96
- ```typescript
97
- import { transform, DEFAULT_SEPARATOR } from "punctilio";
98
-
99
- transform(`"Wait${DEFAULT_SEPARATOR}"`);
100
- // → `“Wait”${DEFAULT_SEPARATOR}`
101
- // The separator doesn’t block the information that this should be an end-quote!
102
- ```
103
-
104
- For `rehype` / `unified` pipelines, use the built-in plugin which handles the separator logic automatically:
96
+ For `rehype` / `unified` pipelines, use the built-in plugin which handles all of this automatically:
105
97
 
106
98
  ```typescript
107
99
  import rehypePunctilio from "punctilio/rehype";
@@ -116,8 +108,31 @@ unified()
116
108
  // are both resolved correctly across the element boundary.
117
109
  ```
118
110
 
119
- * For Markdown ASTs via `remark`, use `remarkPunctilio` which applies the same separator technique to preserve inline element boundaries, or use `transformMarkdown` for a simpler Markdown-to-Markdown pipeline.
120
- * For manual DOM walking or custom transforms, use `transformElement` from `punctilio/rehype`.
111
+ * For Markdown ASTs via `remark`, use `remarkPunctilio` which builds the same boundary-aware views over inline text nodes, or use `transformMarkdown` for a simpler Markdown-to-Markdown pipeline.
112
+ * For manual DOM walking, use `collectProseBlocks` from `punctilio/rehype` to find the elements to transform, then `applyPasses` (below) to transform each one. (`proseViewOf` builds a raw `ProseView` over an element’s text nodes if you need to drive `transformView` or a pass yourself.)
113
+
114
+ ### Boundary-aware custom transforms
115
+
116
+ Your own site-specific regexes can join punctilio’s passes as first-class citizens. `definePass` (root export) wraps a regex and replacement into a pass with the same shape as the built-ins: string in, string out; `ProseView` in, edits committed in place. Each pattern makes an explicit decision about matches that span a node boundary (a word split by `<em>`, say): `skip` them (the safe default), `allow` them, or decide per match with a predicate.
117
+
118
+ `applyPasses` (from `punctilio/rehype`) then runs built-in and custom passes over an element in order, committing between passes so each sees the previous one’s output—you never touch a `ProseView` directly. An entry may carry its own `shouldSkip`/`shouldSkipText` predicates, applied in addition to the base options for that pass only:
119
+
120
+ ```typescript
121
+ import { definePass, hyphenReplace, niceQuotes } from "punctilio";
122
+ import { applyPasses } from "punctilio/rehype";
123
+
124
+ const fahrenheit = definePass(/(?<deg>\d+) ?F\b/g, "$<deg> °F"); // $&, $1, $<name>, $$ supported
125
+ const fractions = definePass(/\b1\/2\b/g, "½"); // boundary-spanning matches skipped by default
126
+
127
+ applyPasses(element, [
128
+ niceQuotes,
129
+ hyphenReplace,
130
+ fahrenheit,
131
+ { pass: fractions, shouldSkip: (node) => node.tagName === "a" }, // extra skip set for this pass only
132
+ ]);
133
+ ```
134
+
135
+ Migrating from the v4 marker-character API (`transformElement`, the `separator` option, standalone `primeMarks`)? See the [v5 migration guide](docs/migrating-to-v5.md).
121
136
 
122
137
  ## Options
123
138
 
@@ -136,7 +151,6 @@ transform(text, {
136
151
  superscript: false, // 1st → 1ˢᵗ
137
152
  ligatures: false, // ??? → ⁇, ?! → ⁈, !? → ⁉, !!! → !
138
153
  nbsp: true, // non-breaking spaces (after honorifics, between numbers and units, etc.)
139
- checkIdempotency: false, // verify transform(transform(x)) === transform(x); doubles the work
140
154
  });
141
155
  ```
142
156
 
@@ -195,7 +209,7 @@ prettier --write 'docs/**/*.md'
195
209
  # "Hello" -- world. → “Hello” – world.
196
210
  ```
197
211
 
198
- Code spans, fenced code blocks, and inline HTML are left untouched. The plugin currently transforms Markdown (`*.md`, `*.mdx` via the markdown parser); for HTML files, use the [CLI](#cli) or the [`rehype` plugin](#works-with-html-doms-via-separation-boundaries) below.
212
+ Code spans, fenced code blocks, and inline HTML are left untouched. The plugin currently transforms Markdown (`*.md`, `*.mdx` via the markdown parser); for HTML files, use the [CLI](#cli) or the [`rehype` plugin](#works-with-html-doms-via-boundary-aware-views) below.
199
213
 
200
214
  ### CLI
201
215
 
@@ -240,7 +254,7 @@ repos:
240
254
  - Single quotes remain as curly quotes
241
255
  - Punctuation outside quotes
242
256
  - Setting either style to `none` skips the entire transform category: `punctuationStyle: 'none'` preserves straight quotes, apostrophes, and prime marks; `dashStyle: 'none'` preserves all hyphens, number ranges, date ranges, and minus signs.
243
- - `punctilio` is idempotent by design: `transform(transform(text))` always equals `transform(text)`. Set `checkIdempotency: true` to verify this on every call (off by default, since the check doubles the work); `punctilio`’s own test suite runs with it enabled.
257
+ - `punctilio` is idempotent by design: `transform(transform(text))` always equals `transform(text)`. The test suite verifies the fixed point on every case plus fuzzed mixed content.
244
258
  - Use `classifyApostrophes(text)` to distinguish apostrophes from closing single quotes. It returns text with apostrophes as U+02BC (MODIFIER LETTER APOSTROPHE) and closing quotes as U+2019 (RIGHT SINGLE QUOTATION MARK). Per the [Unicode Standard](https://www.unicode.org/versions/Unicode16.0.0/core-spec/chapter-6/#G30602), `transform()` and `niceQuotes()` use U+2019 for both in their output.
245
259
 
246
260
  ## Changelog
@@ -1,5 +1,3 @@
1
- import escapeStringRegexp from "escape-string-regexp";
2
- export { escapeStringRegexp };
3
1
  export declare const UNICODE_SYMBOLS: {
4
2
  readonly ELLIPSIS: "…";
5
3
  readonly MULTIPLICATION: "×";
@@ -84,38 +82,6 @@ export declare const TERMINAL_PUNCTUATION: readonly ["!", "?", ".", ",", ";", ":
84
82
  * Examples of covered characters: é, ñ, ü, ø, ą, ł, ș, ả, ầ, ẁ, ẃ
85
83
  */
86
84
  export declare const LATIN_LETTERS = "A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u00FF\\u0100-\\u017F\\u0180-\\u024F\\u1E00-\\u1EFF";
87
- /**
88
- * Default separator for text spanning HTML elements.
89
- * Uses a two-character sentinel from the Unicode Private Use Area
90
- * (U+E000 U+E001) to avoid collisions with CJK fonts, Apple emoji
91
- * internals, PDF-to-text output, and icon fonts that repurpose U+E000.
92
- */
93
- export declare const DEFAULT_SEPARATOR = "\uE000\uE001";
94
- /**
95
- * Regex-escaped separator wrapped in `(?:...)` so quantifiers apply to
96
- * the entire multi-character sequence.
97
- */
98
- export declare function getEscapedSeparator(options: {
99
- separator?: string;
100
- }): string;
101
- /** Regex-special characters, used for testing separator escaping. */
102
- export declare const REGEX_SPECIAL_CHARS: readonly [".", "*", "+", "?", "^", "$", "[", "]", "\\", "|", "(", ")"];
103
- /**
104
- * Marker-aware word boundary pattern for the START of a match.
105
- *
106
- * Standard `\b` can create false boundaries when separator markers appear
107
- * between word characters (e.g., `x\uE000ReLU` has a false `\b` before `R`).
108
- * This pattern uses a negative lookbehind to reject matches preceded by a
109
- * word character followed by up to `MAX_BOUNDARY_SEPARATORS` markers.
110
- */
111
- export declare function wordBoundaryStart(escapedSeparator: string): string;
112
- /**
113
- * Marker-aware word boundary pattern for the END of a match.
114
- *
115
- * Mirror of `wordBoundaryStart` \u2014 rejects matches followed by up to
116
- * `MAX_BOUNDARY_SEPARATORS` markers and then a word character.
117
- */
118
- export declare function wordBoundaryEnd(escapedSeparator: string): string;
119
85
  /** Space chars for regex `[...]`: regular space, tab, NBSP, NNBSP. */
120
86
  export declare const SPACE_CHARS: string;
121
87
  /** Non-breaking space chars only (NBSP, NNBSP) for regex `[...]`. */
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,sBAAsB,CAAA;AAGrD,OAAO,EAAE,kBAAkB,EAAE,CAAA;AAE7B,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyElB,CAAA;AAEV,mGAAmG;AACnG,eAAO,MAAM,oBAAoB,8HAYvB,CAAA;AAEV;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,qGAAqG,CAAA;AAE/H;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,iBAAiB,CAAA;AAG/C;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAK3E;AAED,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,wEAAyE,CAAA;AAUzG;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAElE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CAEhE;AAED,sEAAsE;AACtE,eAAO,MAAM,WAAW,QAAuD,CAAA;AAE/E,qEAAqE;AACrE,eAAO,MAAM,UAAU,QAAoD,CAAA;AAE3E,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,OAAO,CAAA;AAEvC,sEAAsE;AACtE,eAAO,MAAM,UAAU,yDAAyD,CAAA;AAEhF,eAAO,MAAM,oBAAoB,OAAO,CAAA;AAGxC,yFAAyF;AACzF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CASnE;AAED,gBAAgB;AAChB,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C;AAED,gBAAgB;AAChB,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyElB,CAAA;AAEV,mGAAmG;AACnG,eAAO,MAAM,oBAAoB,8HAYvB,CAAA;AAEV;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,aAAa,qGAAqG,CAAA;AAE/H,sEAAsE;AACtE,eAAO,MAAM,WAAW,QAAuD,CAAA;AAE/E,qEAAqE;AACrE,eAAO,MAAM,UAAU,QAAoD,CAAA;AAE3E,gFAAgF;AAChF,eAAO,MAAM,mBAAmB,OAAO,CAAA;AAEvC,sEAAsE;AACtE,eAAO,MAAM,UAAU,yDAAyD,CAAA;AAEhF,eAAO,MAAM,oBAAoB,OAAO,CAAA;AAGxC,yFAAyF;AACzF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CASnE;AAED,gBAAgB;AAChB,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAE3C;AAED,gBAAgB;AAChB,wBAAgB,eAAe,IAAI,IAAI,CAEtC"}
package/dist/constants.js CHANGED
@@ -1,6 +1,4 @@
1
- import escapeStringRegexp from "escape-string-regexp";
2
1
  import QuickLRU from "quick-lru";
3
- export { escapeStringRegexp };
4
2
  export const UNICODE_SYMBOLS = {
5
3
  ELLIPSIS: "\u2026",
6
4
  MULTIPLICATION: "\u00D7",
@@ -103,53 +101,6 @@ export const TERMINAL_PUNCTUATION = [
103
101
  * Examples of covered characters: é, ñ, ü, ø, ą, ł, ș, ả, ầ, ẁ, ẃ
104
102
  */
105
103
  export const LATIN_LETTERS = "A-Za-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u00FF\\u0100-\\u017F\\u0180-\\u024F\\u1E00-\\u1EFF";
106
- /**
107
- * Default separator for text spanning HTML elements.
108
- * Uses a two-character sentinel from the Unicode Private Use Area
109
- * (U+E000 U+E001) to avoid collisions with CJK fonts, Apple emoji
110
- * internals, PDF-to-text output, and icon fonts that repurpose U+E000.
111
- */
112
- export const DEFAULT_SEPARATOR = "\uE000\uE001";
113
- const ESCAPED_DEFAULT_SEPARATOR = escapeStringRegexp(DEFAULT_SEPARATOR);
114
- /**
115
- * Regex-escaped separator wrapped in `(?:...)` so quantifiers apply to
116
- * the entire multi-character sequence.
117
- */
118
- export function getEscapedSeparator(options) {
119
- const escaped = options.separator
120
- ? escapeStringRegexp(options.separator)
121
- : ESCAPED_DEFAULT_SEPARATOR;
122
- return `(?:${escaped})`;
123
- }
124
- /** Regex-special characters, used for testing separator escaping. */
125
- export const REGEX_SPECIAL_CHARS = [".", "*", "+", "?", "^", "$", "[", "]", "\\", "|", "(", ")"];
126
- /**
127
- * Maximum stack of adjacent separator markers tolerated in the boundary
128
- * lookarounds. Three covers any realistic depth of nested HTML element
129
- * boundaries; the bound also keeps the variable-width lookbehind in a
130
- * range that static ReDoS analyzers can prove safe.
131
- */
132
- const MAX_BOUNDARY_SEPARATORS = 3;
133
- /**
134
- * Marker-aware word boundary pattern for the START of a match.
135
- *
136
- * Standard `\b` can create false boundaries when separator markers appear
137
- * between word characters (e.g., `x\uE000ReLU` has a false `\b` before `R`).
138
- * This pattern uses a negative lookbehind to reject matches preceded by a
139
- * word character followed by up to `MAX_BOUNDARY_SEPARATORS` markers.
140
- */
141
- export function wordBoundaryStart(escapedSeparator) {
142
- return `(?<!\\w${escapedSeparator}{0,${MAX_BOUNDARY_SEPARATORS}})\\b`;
143
- }
144
- /**
145
- * Marker-aware word boundary pattern for the END of a match.
146
- *
147
- * Mirror of `wordBoundaryStart` \u2014 rejects matches followed by up to
148
- * `MAX_BOUNDARY_SEPARATORS` markers and then a word character.
149
- */
150
- export function wordBoundaryEnd(escapedSeparator) {
151
- return `\\b(?!${escapedSeparator}{0,${MAX_BOUNDARY_SEPARATORS}}\\w)`;
152
- }
153
104
  /** Space chars for regex `[...]`: regular space, tab, NBSP, NNBSP. */
154
105
  export const SPACE_CHARS = ` \t${UNICODE_SYMBOLS.NBSP}${UNICODE_SYMBOLS.NNBSP}`;
155
106
  /** Non-breaking space chars only (NBSP, NNBSP) for regex `[...]`. */
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,WAAW,CAAA;AAEhC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,QAAQ,EAAE,QAAQ;IAClB,cAAc,EAAE,QAAQ;IACxB,SAAS,EAAE,QAAQ;IACnB,UAAU,EAAE,QAAQ;IACpB,SAAS,EAAE,QAAQ;IACnB,UAAU,EAAE,QAAQ;IACpB,SAAS,EAAE,QAAQ;IACnB,MAAM,EAAE,QAAQ;IAChB,WAAW,EAAE,QAAQ;IACrB,UAAU,EAAE,QAAQ;IACpB,gBAAgB,EAAE,QAAQ;IAC1B,WAAW,EAAE,QAAQ;IACrB,UAAU,EAAE,QAAQ;IACpB,aAAa,EAAE,QAAQ;IACvB,KAAK,EAAE,QAAQ;IACf,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,YAAY,EAAE,QAAQ;IACtB,OAAO,EAAE,QAAQ;IACjB,OAAO,EAAE,QAAQ;IACjB,KAAK,EAAE,QAAQ;IACf,iBAAiB,EAAE,QAAQ;IAC3B,kBAAkB,EAAE,QAAQ;IAC5B,iBAAiB,EAAE,QAAQ;IAC3B,kBAAkB,EAAE,QAAQ;IAC5B,0BAA0B,EAAE,QAAQ;IACpC,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,QAAQ,EAAoB,0DAA0D;IAC7F,WAAW,EAAE,QAAQ,EAAc,0DAA0D;IAC7F,kBAAkB,EAAE,QAAQ,EAAO,IAAI;IACvC,kBAAkB,EAAE,QAAQ,EAAM,IAAI;IACtC,cAAc,EAAE,QAAQ,EAAU,IAAI;IACtC,eAAe,EAAE,QAAQ,EAAS,IAAI;IACtC,+BAA+B;IAC/B,cAAc,EAAE,cAAc,EAAE,KAAK;IACrC,cAAc,EAAE,cAAc,EAAE,KAAK;IACrC,cAAc,EAAE,cAAc,EAAE,KAAK;IACrC,cAAc,EAAE,cAAc,EAAE,KAAK;IACrC,wBAAwB;IACxB,eAAe,EAAE,QAAQ,EAAE,IAAI;IAC/B,oBAAoB,EAAE,QAAQ,EAAE,IAAI;IACpC,oBAAoB,EAAE,QAAQ,EAAE,IAAI;IACpC,kBAAkB,EAAE,QAAQ,EAAE,IAAI;IAClC,WAAW,EAAE,QAAQ,EAAE,IAAI;IAC3B,4BAA4B;IAC5B,qBAAqB,EAAE,QAAQ,EAAE,IAAI;IACrC,kBAAkB,EAAE,QAAQ,EAAE,IAAI;IAClC,gBAAgB,EAAE,QAAQ,EAAE,IAAI;IAChC,eAAe,EAAE,QAAQ,EAAE,IAAI;IAC/B,mBAAmB,EAAE,QAAQ,EAAE,IAAI;IACnC,eAAe,EAAE,QAAQ,EAAE,IAAI;IAC/B,8BAA8B;IAC9B,qBAAqB,EAAE,QAAQ,EAAE,IAAI;IACrC,iBAAiB,EAAE,QAAQ,EAAE,IAAI;IACjC,qBAAqB;IACrB,oBAAoB,EAAE,QAAQ,EAAE,IAAI;IACpC,gBAAgB,EAAE,QAAQ,EAAE,IAAI;IAChC,oBAAoB;IACpB,mBAAmB,EAAE,QAAQ,EAAE,4CAA4C;CACnE,CAAA;AAEV,mGAAmG;AACnG,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG;IAC5B,eAAe,CAAC,QAAQ;IACxB,eAAe,CAAC,eAAe,EAAE,eAAe,CAAC,oBAAoB;IACrE,eAAe,CAAC,oBAAoB,EAAE,eAAe,CAAC,kBAAkB;IACxE,eAAe,CAAC,WAAW;IAC3B,eAAe,CAAC,qBAAqB,EAAE,eAAe,CAAC,kBAAkB;IACzE,eAAe,CAAC,gBAAgB,EAAE,eAAe,CAAC,eAAe;IACjE,eAAe,CAAC,mBAAmB,EAAE,eAAe,CAAC,eAAe;IACpE,eAAe,CAAC,qBAAqB,EAAE,eAAe,CAAC,iBAAiB;IACxE,eAAe,CAAC,oBAAoB,EAAE,eAAe,CAAC,gBAAgB;IACtE,eAAe,CAAC,mBAAmB;CAC3B,CAAA;AAEV;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,kGAAkG,CAAA;AAE/H,sEAAsE;AACtE,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,eAAe,CAAC,IAAI,GAAG,eAAe,CAAC,KAAK,EAAE,CAAA;AAE/E,qEAAqE;AACrE,MAAM,CAAC,MAAM,UAAU,GAAG,GAAG,eAAe,CAAC,IAAI,GAAG,eAAe,CAAC,KAAK,EAAE,CAAA;AAE3E,gFAAgF;AAChF,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,CAAA;AAEvC,sEAAsE;AACtE,MAAM,CAAC,MAAM,UAAU,GAAG,sDAAsD,CAAA;AAEhF,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAA;AACxC,MAAM,UAAU,GAAG,IAAI,QAAQ,CAAiB,EAAE,OAAO,EAAE,oBAAoB,EAAE,CAAC,CAAA;AAElF,yFAAyF;AACzF,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,KAAa;IACzD,MAAM,GAAG,GAAG,GAAG,OAAO,KAAK,KAAK,EAAE,CAAA;IAClC,IAAI,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,CAAC,EAAE,EAAE,CAAC;QACR,EAAE,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QAC/B,UAAU,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;IACzB,CAAC;IACD,EAAE,CAAC,SAAS,GAAG,CAAC,CAAA;IAChB,OAAO,EAAE,CAAA;AACX,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,gBAAgB;IAC9B,OAAO,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAA;AACxC,CAAC;AAED,gBAAgB;AAChB,MAAM,UAAU,eAAe;IAC7B,UAAU,CAAC,KAAK,EAAE,CAAA;AACpB,CAAC"}
package/dist/dashes.d.ts CHANGED
@@ -1,19 +1,22 @@
1
+ import { type ProseView } from "./prose-view.js";
1
2
  export declare const DASH_STYLES: readonly ["american", "british", "none"];
2
3
  export type DashStyle = (typeof DASH_STYLES)[number];
3
4
  export interface DashOptions {
4
- /** Boundary marker for HTML element boundaries. Default: "\uE000\uE001" */
5
- separator?: string;
6
5
  /** "american" (unspaced em), "british" (spaced en), "none". Default: "american" */
7
6
  dashStyle?: DashStyle;
8
7
  }
9
8
  export declare const numberRangeDisallowedPrefixes: readonly ["-", "–", "—", "−"];
10
9
  /** Convert number ranges to en-dash (e.g., "1-5" → "1–5"). */
11
- export declare function enDashNumberRange(text: string, options?: DashOptions): string;
10
+ export declare function enDashNumberRange(input: string): string;
11
+ export declare function enDashNumberRange(input: ProseView): void;
12
12
  /** Convert month ranges to en-dash (e.g., "January-March" → "January–March"). */
13
- export declare function enDashDateRange(text: string, options?: DashOptions): string;
13
+ export declare function enDashDateRange(input: string, options?: DashOptions): string;
14
+ export declare function enDashDateRange(input: ProseView, options?: DashOptions): void;
14
15
  /** Convert hyphens to minus signs in numeric contexts (e.g., "-5" → "−5"). */
15
- export declare function minusReplace(text: string, options?: DashOptions): string;
16
- export declare function hyphenReplace(text: string, options?: DashOptions): string;
16
+ export declare function minusReplace(input: string): string;
17
+ export declare function minusReplace(input: ProseView): void;
18
+ export declare function hyphenReplace(input: string, options?: DashOptions): string;
19
+ export declare function hyphenReplace(input: ProseView, options?: DashOptions): void;
17
20
  /**
18
21
  * Insert a word joiner (U+2060) immediately before each unspaced em or en
19
22
  * dash that has preceding content, preventing the dash from appearing as the
@@ -29,5 +32,6 @@ export declare function hyphenReplace(text: string, options?: DashOptions): stri
29
32
  * `nbspTransform` (U+00A0 breaks `Fig. 1` searches). Apply only in rendered
30
33
  * HTML; do not write into Markdown source.
31
34
  */
32
- export declare function dashWordJoiner(text: string): string;
35
+ export declare function dashWordJoiner(input: string): string;
36
+ export declare function dashWordJoiner(input: ProseView): void;
33
37
  //# sourceMappingURL=dashes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dashes.d.ts","sourceRoot":"","sources":["../src/dashes.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,0CAA2C,CAAA;AACnE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAYD,eAAO,MAAM,6BAA6B,+BAA0C,CAAA;AAiBpF,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,MAAM,CAoFjF;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,MAAM,CA2B/E;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,MAAM,CAkC5E;AAyED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,MAAM,CAU7E;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGnD"}
1
+ {"version":3,"file":"dashes.d.ts","sourceRoot":"","sources":["../src/dashes.ts"],"names":[],"mappings":"AACA,OAAO,EAA8B,KAAK,SAAS,EAA4C,MAAM,iBAAiB,CAAA;AAGtH,eAAO,MAAM,WAAW,0CAA2C,CAAA;AACnE,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAA;AAEpD,MAAM,WAAW,WAAW;IAC1B,mFAAmF;IACnF,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AASD,eAAO,MAAM,6BAA6B,+BAA0C,CAAA;AAiLpF,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;AACxD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;AAmbzD,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAAA;AAC7E,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;AAwE9E,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;AACnD,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;AA0iBpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,CAAA;AAC3E,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;AAe5E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;AACrD,wBAAgB,cAAc,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA"}