punctilio 3.11.2 → 3.11.4

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 (66) hide show
  1. package/dist/cli.d.ts +1 -12
  2. package/dist/cli.d.ts.map +1 -1
  3. package/dist/cli.js +4 -26
  4. package/dist/cli.js.map +1 -1
  5. package/dist/constants.d.ts +13 -61
  6. package/dist/constants.d.ts.map +1 -1
  7. package/dist/constants.js +12 -61
  8. package/dist/constants.js.map +1 -1
  9. package/dist/dashes.d.ts +0 -9
  10. package/dist/dashes.d.ts.map +1 -1
  11. package/dist/dashes.js +5 -27
  12. package/dist/dashes.js.map +1 -1
  13. package/dist/html.d.ts +1 -32
  14. package/dist/html.d.ts.map +1 -1
  15. package/dist/html.js +1 -29
  16. package/dist/html.js.map +1 -1
  17. package/dist/index.d.ts +5 -44
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +6 -45
  20. package/dist/index.js.map +1 -1
  21. package/dist/markdown.d.ts +1 -34
  22. package/dist/markdown.d.ts.map +1 -1
  23. package/dist/markdown.js +1 -34
  24. package/dist/markdown.js.map +1 -1
  25. package/dist/nbsp.d.ts +1 -68
  26. package/dist/nbsp.d.ts.map +1 -1
  27. package/dist/nbsp.js +7 -87
  28. package/dist/nbsp.js.map +1 -1
  29. package/dist/prettier-plugin.d.ts +0 -14
  30. package/dist/prettier-plugin.d.ts.map +1 -1
  31. package/dist/prettier-plugin.js +0 -19
  32. package/dist/prettier-plugin.js.map +1 -1
  33. package/dist/quotes.d.ts +0 -3
  34. package/dist/quotes.d.ts.map +1 -1
  35. package/dist/quotes.js +11 -58
  36. package/dist/quotes.js.map +1 -1
  37. package/dist/rehype.d.ts +5 -142
  38. package/dist/rehype.d.ts.map +1 -1
  39. package/dist/rehype.js +9 -146
  40. package/dist/rehype.js.map +1 -1
  41. package/dist/remark.d.ts +0 -30
  42. package/dist/remark.d.ts.map +1 -1
  43. package/dist/remark.js +0 -41
  44. package/dist/remark.js.map +1 -1
  45. package/dist/symbols.d.ts +1 -7
  46. package/dist/symbols.d.ts.map +1 -1
  47. package/dist/symbols.js +10 -54
  48. package/dist/symbols.js.map +1 -1
  49. package/dist/utils.d.ts +10 -58
  50. package/dist/utils.d.ts.map +1 -1
  51. package/dist/utils.js +10 -58
  52. package/dist/utils.js.map +1 -1
  53. package/package.json +6 -5
  54. package/src/cli.ts +7 -33
  55. package/src/constants.ts +13 -62
  56. package/src/dashes.ts +5 -28
  57. package/src/html.ts +1 -33
  58. package/src/index.ts +30 -70
  59. package/src/markdown.ts +1 -38
  60. package/src/nbsp.ts +7 -88
  61. package/src/prettier-plugin.ts +0 -20
  62. package/src/quotes.ts +11 -59
  63. package/src/rehype.ts +11 -165
  64. package/src/remark.ts +1 -43
  65. package/src/symbols.ts +10 -67
  66. package/src/utils.ts +10 -60
package/dist/utils.d.ts CHANGED
@@ -1,76 +1,28 @@
1
1
  /**
2
- * Utility functions for text transformation validation.
3
- *
4
- * @module utils
5
- */
6
- /**
7
- * Formats a string for error messages. If the string exceeds the threshold,
8
- * truncates it and shows the total length.
9
- *
10
- * In Node.js environments, also writes the full content to stderr
11
- * so it's available in build logs for debugging.
2
+ * Formats a string for error messages, truncating above the threshold.
3
+ * Writes full content to stderr in Node.js so build logs capture it.
12
4
  */
13
5
  export declare function formatErrorString(content: string, label: string): string;
14
- /**
15
- * Throws if any text node contains the separator character, which would
16
- * corrupt the split/join mechanism used by the rehype and remark plugins.
17
- *
18
- * @throws Error if the separator is found in any text value
19
- */
6
+ /** Throws if any text node contains the separator (would corrupt split/join). */
20
7
  export declare function assertSeparatorAbsent(textValues: string[], separator: string): void;
21
- /**
22
- * Counts non-overlapping occurrences of the separator string in the text.
23
- */
24
8
  export declare function countSeparators(text: string, separator?: string): number;
25
- /** Minimal text-node interface shared by mdast.Text and hast.Text. */
26
9
  interface TextNode {
27
10
  value: string;
28
11
  }
29
12
  /**
30
13
  * Applies a text transformation across an array of text nodes using the
31
- * separator-marking technique.
32
- *
33
- * 1. Validates no text node already contains the separator.
34
- * 2. Appends the separator to each node's value, concatenates into one string.
35
- * 3. Runs the transform function on the concatenated string.
36
- * 4. Splits the result back on the separator and writes each fragment
37
- * back into the corresponding text node.
38
- *
39
- * `textNodes` is mutated in place.
40
- *
41
- * @throws Error if the transformation alters the number of text nodes
14
+ * separator-marking technique: appends the separator to each node's value,
15
+ * concatenates, transforms, then splits back on the separator and writes
16
+ * each fragment into the corresponding text node. Mutates `textNodes`.
42
17
  */
43
18
  export declare function transformTextNodes(textNodes: TextNode[], transformFn: (input: string) => string, separator: string): void;
44
- /**
45
- * Validates that a transformation preserved the separator count.
46
- * Throws an error if separators were added or removed.
47
- *
48
- * @throws Error if separator count changed
49
- */
19
+ /** Throws if a transformation changed the separator count. */
50
20
  export declare function assertSeparatorCountPreserved(original: string, transformed: string, separator?: string, transformName?: string): void;
51
- /**
52
- * Returns a copy of `obj` with `undefined`-valued keys removed.
53
- * Used so caller-supplied `{ foo: undefined }` doesn't override a default.
54
- *
55
- * @internal
56
- */
21
+ /** Returns a copy of `obj` with `undefined`-valued keys removed. @internal */
57
22
  export declare function filterUndefined<T extends object>(obj: T): Partial<T>;
58
- /**
59
- * Returns a deterministic JSON-style string for an options object: drops
60
- * `undefined` values and sorts keys, so equivalent option sets always
61
- * produce the same string (suitable as a cache or LRU key).
62
- *
63
- * @internal
64
- */
23
+ /** Deterministic JSON string for an options object, suitable as cache key. @internal */
65
24
  export declare function stableStringify(obj: object): string;
66
- /**
67
- * Extracts the named-groups object from a `String.prototype.replace`
68
- * callback's argument tuple. The last element is always the groups
69
- * object when the regex has named captures. Callers supply the group
70
- * shape via the type parameter to localise the unavoidable type cast.
71
- *
72
- * @internal
73
- */
25
+ /** Extracts named groups from a `.replace()` callback's arguments. @internal */
74
26
  export declare function namedGroups<G>(args: unknown[]): G;
75
27
  export {};
76
28
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAkBxE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAanF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAA0B,GAAG,MAAM,CAS3F;AAED,sEAAsE;AACtE,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,QAAQ,EAAE,EACrB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EACtC,SAAS,EAAE,MAAM,GAChB,IAAI,CAmBN;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAA0B,EACrC,aAAa,GAAE,MAAoB,GAClC,IAAI,CAUN;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAMpE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAEjD"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAkBxE;AAED,iFAAiF;AACjF,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAanF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAA0B,GAAG,MAAM,CAS3F;AAED,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAA;CACd;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,QAAQ,EAAE,EACrB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,EACtC,SAAS,EAAE,MAAM,GAChB,IAAI,CAmBN;AAED,8DAA8D;AAC9D,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAA0B,EACrC,aAAa,GAAE,MAAoB,GAClC,IAAI,CAUN;AAED,8EAA8E;AAC9E,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAMpE;AAED,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKnD;AAED,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,CAEjD"}
package/dist/utils.js CHANGED
@@ -1,17 +1,8 @@
1
- /**
2
- * Utility functions for text transformation validation.
3
- *
4
- * @module utils
5
- */
6
1
  import { DEFAULT_SEPARATOR, ISSUES_URL } from "./constants.js";
7
- /** Threshold above which strings are truncated in error messages. */
8
2
  const ERROR_STRING_THRESHOLD = 2000;
9
3
  /**
10
- * Formats a string for error messages. If the string exceeds the threshold,
11
- * truncates it and shows the total length.
12
- *
13
- * In Node.js environments, also writes the full content to stderr
14
- * so it's available in build logs for debugging.
4
+ * Formats a string for error messages, truncating above the threshold.
5
+ * Writes full content to stderr in Node.js so build logs capture it.
15
6
  */
16
7
  export function formatErrorString(content, label) {
17
8
  if (content.length <= ERROR_STRING_THRESHOLD) {
@@ -29,12 +20,7 @@ export function formatErrorString(content, label) {
29
20
  const truncated = content.slice(0, ERROR_STRING_THRESHOLD);
30
21
  return `[${label}: ${JSON.stringify(truncated)}... (${content.length} chars total)]`;
31
22
  }
32
- /**
33
- * Throws if any text node contains the separator character, which would
34
- * corrupt the split/join mechanism used by the rehype and remark plugins.
35
- *
36
- * @throws Error if the separator is found in any text value
37
- */
23
+ /** Throws if any text node contains the separator (would corrupt split/join). */
38
24
  export function assertSeparatorAbsent(textValues, separator) {
39
25
  for (const value of textValues) {
40
26
  if (!value.includes(separator))
@@ -47,9 +33,6 @@ export function assertSeparatorAbsent(textValues, separator) {
47
33
  `Text: ${formatErrorString(value, "input")}`);
48
34
  }
49
35
  }
50
- /**
51
- * Counts non-overlapping occurrences of the separator string in the text.
52
- */
53
36
  export function countSeparators(text, separator = DEFAULT_SEPARATOR) {
54
37
  if (separator.length === 0)
55
38
  return 0;
@@ -63,17 +46,9 @@ export function countSeparators(text, separator = DEFAULT_SEPARATOR) {
63
46
  }
64
47
  /**
65
48
  * Applies a text transformation across an array of text nodes using the
66
- * separator-marking technique.
67
- *
68
- * 1. Validates no text node already contains the separator.
69
- * 2. Appends the separator to each node's value, concatenates into one string.
70
- * 3. Runs the transform function on the concatenated string.
71
- * 4. Splits the result back on the separator and writes each fragment
72
- * back into the corresponding text node.
73
- *
74
- * `textNodes` is mutated in place.
75
- *
76
- * @throws Error if the transformation alters the number of text nodes
49
+ * separator-marking technique: appends the separator to each node's value,
50
+ * concatenates, transforms, then splits back on the separator and writes
51
+ * each fragment into the corresponding text node. Mutates `textNodes`.
77
52
  */
78
53
  export function transformTextNodes(textNodes, transformFn, separator) {
79
54
  assertSeparatorAbsent(textNodes.map((n) => n.value), separator);
@@ -90,12 +65,7 @@ export function transformTextNodes(textNodes, transformFn, separator) {
90
65
  n.value = transformedFragments[index];
91
66
  });
92
67
  }
93
- /**
94
- * Validates that a transformation preserved the separator count.
95
- * Throws an error if separators were added or removed.
96
- *
97
- * @throws Error if separator count changed
98
- */
68
+ /** Throws if a transformation changed the separator count. */
99
69
  export function assertSeparatorCountPreserved(original, transformed, separator = DEFAULT_SEPARATOR, transformName = "transform") {
100
70
  const originalCount = countSeparators(original, separator);
101
71
  const transformedCount = countSeparators(transformed, separator);
@@ -105,12 +75,7 @@ export function assertSeparatorCountPreserved(original, transformed, separator =
105
75
  `Include the input text that caused this error.`);
106
76
  }
107
77
  }
108
- /**
109
- * Returns a copy of `obj` with `undefined`-valued keys removed.
110
- * Used so caller-supplied `{ foo: undefined }` doesn't override a default.
111
- *
112
- * @internal
113
- */
78
+ /** Returns a copy of `obj` with `undefined`-valued keys removed. @internal */
114
79
  export function filterUndefined(obj) {
115
80
  const result = {};
116
81
  for (const [k, v] of Object.entries(obj)) {
@@ -119,27 +84,14 @@ export function filterUndefined(obj) {
119
84
  }
120
85
  return result;
121
86
  }
122
- /**
123
- * Returns a deterministic JSON-style string for an options object: drops
124
- * `undefined` values and sorts keys, so equivalent option sets always
125
- * produce the same string (suitable as a cache or LRU key).
126
- *
127
- * @internal
128
- */
87
+ /** Deterministic JSON string for an options object, suitable as cache key. @internal */
129
88
  export function stableStringify(obj) {
130
89
  const entries = Object.entries(obj)
131
90
  .filter(([, v]) => v !== undefined)
132
91
  .sort(([a], [b]) => a.localeCompare(b));
133
92
  return JSON.stringify(entries);
134
93
  }
135
- /**
136
- * Extracts the named-groups object from a `String.prototype.replace`
137
- * callback's argument tuple. The last element is always the groups
138
- * object when the regex has named captures. Callers supply the group
139
- * shape via the type parameter to localise the unavoidable type cast.
140
- *
141
- * @internal
142
- */
94
+ /** Extracts named groups from a `.replace()` callback's arguments. @internal */
143
95
  export function namedGroups(args) {
144
96
  return args[args.length - 1];
145
97
  }
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "punctilio",
3
- "version": "3.11.2",
3
+ "version": "3.11.4",
4
4
  "description": "Smart typography transformations: curly quotes, em-dashes, en-dashes, and more",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -86,12 +86,13 @@
86
86
  "@types/node": "20.19.30",
87
87
  "@types/seedrandom": "3.0.8",
88
88
  "eslint": "9.39.2",
89
+ "eslint-plugin-perfectionist": "5.9.0",
89
90
  "eslint-plugin-redos": "4.5.0",
90
91
  "eslint-plugin-regexp": "3.1.0",
91
92
  "hastscript": "9.0.1",
92
93
  "jest": "29.7.0",
93
94
  "lint-staged": "16.4.0",
94
- "prettier": "3.8.1",
95
+ "prettier": "3.8.3",
95
96
  "recheck": "4.5.0",
96
97
  "rehype-parse": "9.0.1",
97
98
  "rehype-stringify": "10.0.1",
@@ -104,10 +105,10 @@
104
105
  "smartquotes": "2.3.2",
105
106
  "smartypants": "0.2.2",
106
107
  "tipograph": "0.7.4",
107
- "ts-jest": "29.4.9",
108
- "tsx": "4.21.0",
108
+ "ts-jest": "29.4.11",
109
+ "tsx": "4.22.3",
109
110
  "typescript": "5.9.3",
110
- "typescript-eslint": "8.59.2",
111
+ "typescript-eslint": "8.59.4",
111
112
  "typograf": "7.7.0",
112
113
  "unified": "11.0.5"
113
114
  },
package/src/cli.ts CHANGED
@@ -1,10 +1,4 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Command-line entry point: format Markdown and HTML files in place,
4
- * or check whether they would be reformatted (for use as a pre-commit hook).
5
- *
6
- * @packageDocumentation
7
- */
8
2
 
9
3
  import { createHash } from "node:crypto"
10
4
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"
@@ -17,8 +11,8 @@ import { cosmiconfig } from "cosmiconfig"
17
11
  import ignore, { type Ignore } from "ignore"
18
12
  import { glob } from "tinyglobby"
19
13
 
20
- import { transformMarkdown, type MarkdownOptions } from "./markdown.js"
21
- import { transformHtml, type HtmlOptions } from "./html.js"
14
+ import { type MarkdownOptions, transformMarkdown } from "./markdown.js"
15
+ import { type HtmlOptions, transformHtml } from "./html.js"
22
16
  import { PUNCTUATION_STYLES, type PunctuationStyle } from "./quotes.js"
23
17
  import { DASH_STYLES, type DashStyle } from "./dashes.js"
24
18
  import { stableStringify } from "./utils.js"
@@ -42,11 +36,7 @@ const RULE_MARKERS = ["-", "*", "_"] as const
42
36
  const MARKDOWN_EXTENSIONS = new Set([".md", ".markdown"])
43
37
  const HTML_EXTENSIONS = new Set([".html", ".htm"])
44
38
 
45
- /**
46
- * Shape of `program.opts()` after parsing. Fields named after their CLI
47
- * flags (camelCased by commander). `commander.choices()` guarantees the
48
- * literal types at runtime; we assert them at the boundary.
49
- */
39
+ // Fields match commander's camelCased flag names; .choices() guarantees literals at runtime.
50
40
  interface ParsedFlags {
51
41
  check?: boolean
52
42
  cache?: boolean
@@ -147,8 +137,7 @@ function isGlobPattern(pattern: string): boolean {
147
137
  return /[*?[\]{}]/.test(pattern)
148
138
  }
149
139
 
150
- // Non-glob positionals pass through as literal paths so they error loudly
151
- // if missing, matching the prior behavior of `punctilio file.md`.
140
+ // Non-glob positionals pass through as literal paths so they error loudly if missing.
152
141
  async function discoverFiles(
153
142
  patterns: string[],
154
143
  cwd: string,
@@ -213,12 +202,7 @@ function saveCache(location: string, cache: Cache): void {
213
202
  writeFileSync(location, JSON.stringify(cache))
214
203
  }
215
204
 
216
- /**
217
- * Cache key for a file. Always cwd-relative so a project that moves
218
- * directories (or syncs the cache file across machines via the same
219
- * repo layout) keeps hitting the cache. Files outside cwd appear as
220
- * `../foo.md` and still hash consistently.
221
- */
205
+ // cwd-relative so the cache survives directory moves and cross-machine syncs.
222
206
  function cacheKey(filePath: string, cwd: string): string {
223
207
  return relative(cwd, filePath)
224
208
  }
@@ -249,12 +233,7 @@ async function transformContent(input: string, type: FileType, opts: CliOptions)
249
233
  return type === "md" ? transformMarkdown(input, opts) : transformHtml(input, opts)
250
234
  }
251
235
 
252
- /**
253
- * Preserves whether the original file ends with a trailing newline.
254
- * The unified pipelines for Markdown and HTML both unconditionally append
255
- * one, so without this adjustment every file lacking a trailing newline
256
- * would always appear as needing a rewrite.
257
- */
236
+ // Unified pipelines unconditionally append a trailing newline; undo if original lacked one.
258
237
  function matchTrailingNewline(original: string, formatted: string): string {
259
238
  const originalHas = original.endsWith("\n")
260
239
  const formattedHas = formatted.endsWith("\n")
@@ -282,12 +261,7 @@ async function readPackageVersion(): Promise<string> {
282
261
  }
283
262
  }
284
263
 
285
- /**
286
- * Runs the CLI with the given arguments and I/O streams.
287
- *
288
- * @returns Exit code: 0 if no changes (or all changes written),
289
- * 1 if `--check` saw a file that would change, 2 for usage errors.
290
- */
264
+ /** Returns exit code: 0 success, 1 `--check` saw changes, 2 usage error. */
291
265
  export async function runCli(args: string[], io: CliIO): Promise<number> {
292
266
  const version = await readPackageVersion()
293
267
  const program = buildProgram(version, io)
package/src/constants.ts CHANGED
@@ -1,13 +1,8 @@
1
- /**
2
- * Shared Unicode constants and regex utilities.
3
- */
4
-
5
1
  import escapeStringRegexp from "escape-string-regexp"
6
2
  import QuickLRU from "quick-lru"
7
3
 
8
- /**
9
- * Unicode symbols for typography transformations.
10
- */
4
+ export { escapeStringRegexp }
5
+
11
6
  export const UNICODE_SYMBOLS = {
12
7
  ELLIPSIS: "\u2026",
13
8
  MULTIPLICATION: "\u00D7",
@@ -82,13 +77,7 @@ export const UNICODE_SYMBOLS = {
82
77
  GREEK_QUESTION_MARK: "\u037E", // ; (visually identical to ASCII semicolon)
83
78
  } as const
84
79
 
85
- /**
86
- * All terminal punctuation characters that signal a quote is "already terminated".
87
- * Covers ASCII, ellipsis, punctuation ligatures, interrobang, CJK fullwidth,
88
- * CJK ideographic, Arabic, and Greek question mark.
89
- *
90
- * Used as a regex character class fragment in quotes.ts and as a test fixture.
91
- */
80
+ /** All terminal punctuation chars for regex character classes (ASCII through CJK/Arabic/Greek). */
92
81
  export const TERMINAL_PUNCTUATION = [
93
82
  "!", "?", ".", ",", ";", ":",
94
83
  UNICODE_SYMBOLS.ELLIPSIS,
@@ -128,13 +117,8 @@ export const DEFAULT_SEPARATOR = "\uE000\uE001"
128
117
  const ESCAPED_DEFAULT_SEPARATOR = escapeStringRegexp(DEFAULT_SEPARATOR)
129
118
 
130
119
  /**
131
- * Returns the regex-escaped separator string for the given options,
132
- * wrapped in a non-capturing group so that quantifiers like `?` and `*`
133
- * apply to the entire separator sequence (critical for multi-character
134
- * separators like the default U+E000 U+E001).
135
- *
136
- * @param options - Object with an optional `separator` field
137
- * @returns Regex-escaped separator string wrapped in `(?:...)`
120
+ * Regex-escaped separator wrapped in `(?:...)` so quantifiers apply to
121
+ * the entire multi-character sequence.
138
122
  */
139
123
  export function getEscapedSeparator(options: { separator?: string }): string {
140
124
  const escaped = options.separator
@@ -143,10 +127,7 @@ export function getEscapedSeparator(options: { separator?: string }): string {
143
127
  return `(?:${escaped})`
144
128
  }
145
129
 
146
- /**
147
- * Characters that have special meaning in regular expressions.
148
- * Used for testing that separator escaping works correctly.
149
- */
130
+ /** Regex-special characters, used for testing separator escaping. */
150
131
  export const REGEX_SPECIAL_CHARS = [".", "*", "+", "?", "^", "$", "[", "]", "\\", "|", "(", ")"] as const
151
132
 
152
133
  /**
@@ -179,45 +160,22 @@ export function wordBoundaryEnd(escapedSeparator: string): string {
179
160
  return `\\b(?!${escapedSeparator}{0,${MAX_BOUNDARY_SEPARATORS}}\\w)`
180
161
  }
181
162
 
182
- /**
183
- * Pattern string for space characters (regular space, tab, non-breaking space,
184
- * and narrow no-break space). Use inside regex character classes: `[${SPACE_CHARS}]`
185
- */
163
+ /** Space chars for regex `[...]`: regular space, tab, NBSP, NNBSP. */
186
164
  export const SPACE_CHARS = ` \t${UNICODE_SYMBOLS.NBSP}${UNICODE_SYMBOLS.NNBSP}`
187
165
 
188
- /**
189
- * Pattern string for the non-breaking space characters only (NBSP and NNBSP).
190
- * Use inside regex character classes: `[${NBSP_CHARS}]`. Used by patterns
191
- * that need to detect existing nbsp chains without also matching plain spaces.
192
- */
166
+ /** Non-breaking space chars only (NBSP, NNBSP) for regex `[...]`. */
193
167
  export const NBSP_CHARS = `${UNICODE_SYMBOLS.NBSP}${UNICODE_SYMBOLS.NNBSP}`
194
168
 
195
- /**
196
- * Maximum recursion depth used by the rehype and remark tree walkers.
197
- * Guards against stack overflow from maliciously or accidentally deep
198
- * AST nesting. Shared so both plugins behave identically.
199
- */
169
+ /** Max AST recursion depth; guards against stack overflow from deep nesting. */
200
170
  export const MAX_RECURSION_DEPTH = 1000
201
171
 
202
- /**
203
- * Canonical issue tracker URL, referenced in user-facing error messages
204
- * so there's exactly one source of truth if the repository ever moves.
205
- */
172
+ /** Single source of truth for issue tracker URL in error messages. */
206
173
  export const ISSUES_URL = "https://github.com/alexander-turner/punctilio/issues"
207
174
 
208
- /**
209
- * LRU cache for compiled RegExp objects keyed by `pattern + '\0' + flags`.
210
- * Avoids recompiling identical regexes on every function call (common
211
- * when using the default separator). Capped to prevent unbounded growth.
212
- */
213
175
  export const MAX_REGEX_CACHE_SIZE = 1000
214
176
  const regexCache = new QuickLRU<string, RegExp>({ maxSize: MAX_REGEX_CACHE_SIZE })
215
177
 
216
- /**
217
- * Returns a cached RegExp for the given pattern and flags.
218
- * Resets `lastIndex` before returning to prevent stale state when
219
- * callers use `.test()` or `.exec()` on global-flag regexes.
220
- */
178
+ /** Returns a cached RegExp, resetting `lastIndex` to prevent stale global-flag state. */
221
179
  export function cachedRegExp(pattern: string, flags: string): RegExp {
222
180
  const key = `${pattern}\0${flags}`
223
181
  let re = regexCache.get(key)
@@ -229,19 +187,12 @@ export function cachedRegExp(pattern: string, flags: string): RegExp {
229
187
  return re
230
188
  }
231
189
 
232
- /**
233
- * Returns all currently cached RegExp objects. Exported for test
234
- * introspection only (e.g. ReDoS scanning every compiled pattern).
235
- * @internal
236
- */
190
+ /** @internal */
237
191
  export function getCachedRegExps(): RegExp[] {
238
192
  return Array.from(regexCache.values())
239
193
  }
240
194
 
241
- /**
242
- * Clears the regex cache. Exported for test isolation only.
243
- * @internal
244
- */
195
+ /** @internal */
245
196
  export function clearRegexCache(): void {
246
197
  regexCache.clear()
247
198
  }
package/src/dashes.ts CHANGED
@@ -1,8 +1,4 @@
1
- /**
2
- * Dash transformation: hyphens → em-dashes, en-dashes, minus signs.
3
- */
4
-
5
- import { UNICODE_SYMBOLS, DEFAULT_SEPARATOR, LATIN_LETTERS, wordBoundaryStart, wordBoundaryEnd, getEscapedSeparator, cachedRegExp } from "./constants.js"
1
+ import { cachedRegExp, DEFAULT_SEPARATOR, getEscapedSeparator, LATIN_LETTERS, UNICODE_SYMBOLS, wordBoundaryEnd, wordBoundaryStart } from "./constants.js"
6
2
  import { namedGroups } from "./utils.js"
7
3
 
8
4
  export const DASH_STYLES = ["american", "british", "none"] as const
@@ -17,19 +13,10 @@ export interface DashOptions {
17
13
 
18
14
  const { EN_DASH, EM_DASH, MINUS, LEFT_DOUBLE_QUOTE, RIGHT_DOUBLE_QUOTE, LEFT_SINGLE_QUOTE, RIGHT_SINGLE_QUOTE } = UNICODE_SYMBOLS
19
15
 
20
- /**
21
- * Characters that, when preceding a number, prevent it from being
22
- * treated as the start of a number range. This prevents false positives
23
- * in model names like "Llama-2-7B" where "2-7" should not become "2–7".
24
- */
16
+ // Prevents false-positive ranges in model names like "Llama-2-7B".
25
17
  export const numberRangeDisallowedPrefixes = ["-", EN_DASH, EM_DASH, MINUS] as const
26
18
 
27
- /**
28
- * Regex character-class fragment built from {@link numberRangeDisallowedPrefixes}.
29
- * Non-ASCII dashes are escaped to `\uXXXX` form so the fragment is safe to
30
- * embed inside a `[...]` class regardless of the regex source encoding.
31
- * Computed once at module load — the inputs are `const`.
32
- */
19
+ // Non-ASCII dashes escaped to \uXXXX for safe embedding in [...] classes.
33
20
  const DISALLOWED_PREFIX_CLASS_FRAGMENT = numberRangeDisallowedPrefixes
34
21
  .map((c) => (c === "-" ? c : `\\u${c.charCodeAt(0).toString(16).padStart(4, "0")}`))
35
22
  .join("")
@@ -185,10 +172,6 @@ export function minusReplace(text: string, options: DashOptions = {}): string {
185
172
  return text
186
173
  }
187
174
 
188
- /**
189
- * Convert surrounded dashes to em/en dashes.
190
- * Handles patterns like "word - word" → "word—word" (Chicago) or "word – word" (Oxford).
191
- */
192
175
  function convertParentheticalDashes(text: string, sep: string, style: DashStyle): string {
193
176
  const localizedDash = style === "british" ? EN_DASH : EM_DASH
194
177
  const maybeSpace = style === "british" ? " " : ""
@@ -239,13 +222,8 @@ function convertParentheticalDashes(text: string, sep: string, style: DashStyle)
239
222
  return text
240
223
  }
241
224
 
242
- /**
243
- * Normalize em-dash spacing for Chicago style (American).
244
- * Removes all spaces around em-dashes per Chicago Manual of Style.
245
- *
246
- * TODO: Handle interrupted-then-resumed speech within quotes, where Chicago
247
- * allows a space after the dash: "Don't inter— Hey! Who threw that?"
248
- */
225
+ // TODO: Handle interrupted-then-resumed speech within quotes, where Chicago
226
+ // allows a space after the dash: "Don't inter— Hey! Who threw that?"
249
227
  function normalizeEmDashSpacing(text: string, sep: string): string {
250
228
  const escapedSep = getEscapedSeparator({ separator: sep })
251
229
 
@@ -265,7 +243,6 @@ function normalizeEmDashSpacing(text: string, sep: string): string {
265
243
  return text
266
244
  }
267
245
 
268
- /** Full dash transformation. */
269
246
  export function hyphenReplace(text: string, options: DashOptions = {}): string {
270
247
  const sep = options.separator ?? DEFAULT_SEPARATOR
271
248
  const style = options.dashStyle ?? "american"
package/src/html.ts CHANGED
@@ -1,14 +1,3 @@
1
- /**
2
- * Convenience module for HTML-to-HTML typography transformations.
3
- *
4
- * Provides a single function that takes HTML input and returns
5
- * typographically improved HTML output.
6
- *
7
- * Requires `unified`, `rehype-parse`, and `rehype-stringify` to be installed.
8
- *
9
- * @packageDocumentation
10
- */
11
-
12
1
  import { unified } from "unified"
13
2
  import rehypeParse from "rehype-parse"
14
3
  import rehypeStringify from "rehype-stringify"
@@ -17,9 +6,6 @@ import QuickLRU from "quick-lru"
17
6
  import { rehypePunctilio, type RehypePunctilioOptions } from "./rehype.js"
18
7
  import { stableStringify } from "./utils.js"
19
8
 
20
- /**
21
- * Options for the HTML transform pipeline.
22
- */
23
9
  export interface HtmlOptions extends RehypePunctilioOptions {
24
10
  /**
25
11
  * Whether to parse the input as an HTML fragment (no implicit `<html>`,
@@ -43,29 +29,11 @@ const processorCache = new QuickLRU<string, ReturnType<typeof createProcessor>>(
43
29
  maxSize: MAX_PROCESSOR_CACHE_SIZE,
44
30
  })
45
31
 
46
- /**
47
- * Clears the processor cache. Exported for test isolation only.
48
- * @internal
49
- */
32
+ /** @internal */
50
33
  export function clearProcessorCache(): void {
51
34
  processorCache.clear()
52
35
  }
53
36
 
54
- /**
55
- * Transforms HTML text with typographic improvements.
56
- *
57
- * Parses the input as HTML, applies punctilio typography transformations,
58
- * and serializes back to HTML. The unified processor pipeline is cached
59
- * and reused across calls with identical options.
60
- *
61
- * @example
62
- * ```ts
63
- * import { transformHtml } from 'punctilio/html'
64
- *
65
- * await transformHtml('<p>"Hello" -- world</p>')
66
- * // → '<p>“Hello”—world</p>'
67
- * ```
68
- */
69
37
  export async function transformHtml(
70
38
  input: string,
71
39
  options: HtmlOptions = {}