punctilio 3.11.3 → 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.
- package/dist/cli.d.ts +1 -12
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +4 -26
- package/dist/cli.js.map +1 -1
- package/dist/constants.d.ts +13 -61
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +12 -61
- package/dist/constants.js.map +1 -1
- package/dist/dashes.d.ts +0 -9
- package/dist/dashes.d.ts.map +1 -1
- package/dist/dashes.js +4 -26
- package/dist/dashes.js.map +1 -1
- package/dist/html.d.ts +1 -32
- package/dist/html.d.ts.map +1 -1
- package/dist/html.js +1 -29
- package/dist/html.js.map +1 -1
- package/dist/index.d.ts +0 -39
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -39
- package/dist/index.js.map +1 -1
- package/dist/markdown.d.ts +1 -34
- package/dist/markdown.d.ts.map +1 -1
- package/dist/markdown.js +1 -34
- package/dist/markdown.js.map +1 -1
- package/dist/nbsp.d.ts +1 -68
- package/dist/nbsp.d.ts.map +1 -1
- package/dist/nbsp.js +6 -86
- package/dist/nbsp.js.map +1 -1
- package/dist/prettier-plugin.d.ts +0 -14
- package/dist/prettier-plugin.d.ts.map +1 -1
- package/dist/prettier-plugin.js +0 -19
- package/dist/prettier-plugin.js.map +1 -1
- package/dist/quotes.d.ts +0 -3
- package/dist/quotes.d.ts.map +1 -1
- package/dist/quotes.js +11 -58
- package/dist/quotes.js.map +1 -1
- package/dist/rehype.d.ts +4 -141
- package/dist/rehype.d.ts.map +1 -1
- package/dist/rehype.js +7 -144
- package/dist/rehype.js.map +1 -1
- package/dist/remark.d.ts +0 -30
- package/dist/remark.d.ts.map +1 -1
- package/dist/remark.js +0 -41
- package/dist/remark.js.map +1 -1
- package/dist/symbols.d.ts +1 -7
- package/dist/symbols.d.ts.map +1 -1
- package/dist/symbols.js +9 -53
- package/dist/symbols.js.map +1 -1
- package/dist/utils.d.ts +10 -58
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +10 -58
- package/dist/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/cli.ts +5 -31
- package/src/constants.ts +13 -62
- package/src/dashes.ts +4 -27
- package/src/html.ts +1 -33
- package/src/index.ts +0 -40
- package/src/markdown.ts +1 -38
- package/src/nbsp.ts +6 -87
- package/src/prettier-plugin.ts +0 -20
- package/src/quotes.ts +11 -59
- package/src/rehype.ts +8 -162
- package/src/remark.ts +0 -42
- package/src/symbols.ts +9 -66
- package/src/utils.ts +10 -60
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prettier-plugin.js","sourceRoot":"","sources":["../src/prettier-plugin.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"prettier-plugin.js","sourceRoot":"","sources":["../src/prettier-plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,KAAK,gBAAgB,MAAM,2BAA2B,CAAA;AAG7D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC,OAAO,EAAE,eAAe,EAA+B,MAAM,aAAa,CAAA;AAE1E,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,OAAO,CAAC,QAAwB,CAAA;AAC1E,MAAM,QAAQ,GAAG,WAAW,CAAC,WAAW,CAAC,CAAA;AAEzC,KAAK,UAAU,mBAAmB,CAAC,UAAkB;IACnD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;IAChD,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAE,MAAM,CAAC,MAAiC,CAAA;AACnF,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,IAA4B,EAAE,GAAS;IACvE,uEAAuE;IACvE,uEAAuE;IACvE,4DAA4D;IAC5D,MAAM,WAAW,GAAG,eAAe,CAAC,IAAI,CAAyC,CAAA;IACjF,MAAM,WAAW,CAAC,GAAG,CAAC,CAAA;AACxB,CAAC;AAED,MAAM,MAAM,GAAW;IACrB,OAAO,EAAE;QACP,QAAQ,EAAE;YACR,GAAG,gBAAgB;YACnB,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO;gBACvB,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;gBACvD,MAAM,UAAU,GAAG,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,CAAA;gBACnG,MAAM,IAAI,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAA;gBAClD,MAAM,kBAAkB,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;gBACnC,OAAO,GAAG,CAAA;YACZ,CAAC;SACF;KACF;CACF,CAAA;AAED,eAAe,MAAM,CAAA"}
|
package/dist/quotes.d.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Smart quote transformation: straight quotes → curly quotes.
|
|
3
|
-
*/
|
|
4
1
|
export declare const PUNCTUATION_STYLES: readonly ["american", "british", "german", "french", "none"];
|
|
5
2
|
export type PunctuationStyle = (typeof PUNCTUATION_STYLES)[number];
|
|
6
3
|
export interface QuoteOptions {
|
package/dist/quotes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quotes.d.ts","sourceRoot":"","sources":["../src/quotes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"quotes.d.ts","sourceRoot":"","sources":["../src/quotes.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,kBAAkB,8DAA+D,CAAA;AAC9F,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAA;AAElE,MAAM,WAAW,YAAY;IAC3B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;CACpC;AAgRD,+CAA+C;AAC/C,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAK3E;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,MAAM,CAEpF"}
|
package/dist/quotes.js
CHANGED
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
* Smart quote transformation: straight quotes → curly quotes.
|
|
3
|
-
*/
|
|
4
|
-
import escapeStringRegexp from "escape-string-regexp";
|
|
5
|
-
import { cachedRegExp, DEFAULT_SEPARATOR, getEscapedSeparator, LATIN_LETTERS, TERMINAL_PUNCTUATION, UNICODE_SYMBOLS } from "./constants.js";
|
|
1
|
+
import { cachedRegExp, DEFAULT_SEPARATOR, escapeStringRegexp, getEscapedSeparator, LATIN_LETTERS, TERMINAL_PUNCTUATION, UNICODE_SYMBOLS } from "./constants.js";
|
|
6
2
|
const { EM_DASH, LEFT_DOUBLE_QUOTE, RIGHT_DOUBLE_QUOTE, LEFT_SINGLE_QUOTE, RIGHT_SINGLE_QUOTE, MODIFIER_LETTER_APOSTROPHE, } = UNICODE_SYMBOLS;
|
|
7
|
-
/** Joined string of all terminal punctuation characters for use in regex character classes. */
|
|
8
3
|
const TERMINAL_PUNCTUATION_CLASS = TERMINAL_PUNCTUATION.join("");
|
|
9
|
-
|
|
10
|
-
* Maximum consecutive closing quotes the punctuation-placement regexes will
|
|
11
|
-
* traverse in a single match (e.g., '". for two-deep nesting). Bounded to keep
|
|
12
|
-
* the regex linear on pathological inputs that contain many closing quotes
|
|
13
|
-
* without any following period or comma.
|
|
14
|
-
*/
|
|
4
|
+
// Bounded to keep punctuation-placement regexes linear on pathological inputs.
|
|
15
5
|
const MAX_NESTED_QUOTES = 4;
|
|
16
6
|
export const PUNCTUATION_STYLES = ["american", "british", "german", "french", "none"];
|
|
17
|
-
/** Convert straight single quotes to curly quotes and apostrophes */
|
|
18
7
|
function convertSingleQuotes(text, sep) {
|
|
19
8
|
const escapedSep = getEscapedSeparator({ separator: sep });
|
|
20
9
|
// Handle empty single quotes '' and whitespace-only quotes ' ' first
|
|
@@ -51,11 +40,8 @@ function convertSingleQuotes(text, sep) {
|
|
|
51
40
|
text = convertUnmatchedPluralPossessives(text, sep);
|
|
52
41
|
return text;
|
|
53
42
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* Tracks LSQ/RSQ balance left-to-right so that paired closing quotes
|
|
57
|
-
* (e.g., 'yes' where s precedes RSQ) remain RSQ.
|
|
58
|
-
*/
|
|
43
|
+
// Converts unmatched RSQ after s/S to MLA (plural possessives).
|
|
44
|
+
// Tracks LSQ/RSQ balance so paired closing quotes remain RSQ.
|
|
59
45
|
function convertUnmatchedPluralPossessives(text, sep) {
|
|
60
46
|
let singleQuoteBalance = 0;
|
|
61
47
|
return text.replace(cachedRegExp(`[${LEFT_SINGLE_QUOTE}${RIGHT_SINGLE_QUOTE}]`, "g"), (match, offset) => {
|
|
@@ -77,9 +63,6 @@ function convertUnmatchedPluralPossessives(text, sep) {
|
|
|
77
63
|
return match;
|
|
78
64
|
});
|
|
79
65
|
}
|
|
80
|
-
/**
|
|
81
|
-
* Build the beginning-double-quote regex pattern from named fragments.
|
|
82
|
-
*/
|
|
83
66
|
function buildBeginningDoublePattern(escapedSep, rawEscSep) {
|
|
84
67
|
// Consuming boundary (not a lookbehind): variable-width lookbehinds
|
|
85
68
|
// with alternation cause ReDoS. Re-emitted via $<boundary> in the replacement.
|
|
@@ -97,7 +80,6 @@ function buildBeginningDoublePattern(escapedSep, rawEscSep) {
|
|
|
97
80
|
];
|
|
98
81
|
return `${boundary}${beforeCapture}["](?:${afterConditions.join("|")})`;
|
|
99
82
|
}
|
|
100
|
-
/** Convert straight double quotes to curly quotes */
|
|
101
83
|
function convertDoubleQuotes(text, sep) {
|
|
102
84
|
const rawEscSep = escapeStringRegexp(sep);
|
|
103
85
|
const escapedSep = getEscapedSeparator({ separator: sep });
|
|
@@ -116,18 +98,8 @@ function convertDoubleQuotes(text, sep) {
|
|
|
116
98
|
return text;
|
|
117
99
|
}
|
|
118
100
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
*
|
|
122
|
-
* Shape: `<non-terminal>(sepBefore)(quotes)(sepAfter)<punctuation>`
|
|
123
|
-
*
|
|
124
|
-
* - The lookbehind ensures the char just before the match isn't already terminal
|
|
125
|
-
* punctuation (so we don't rewrite, e.g., "Stop!".).
|
|
126
|
-
* - `quotes` matches 1 to MAX_NESTED_QUOTES closing quotes (possibly separated
|
|
127
|
-
* by element-boundary markers). The bound keeps the regex linear on
|
|
128
|
-
* pathological inputs — unbounded `*` causes catastrophic backtracking when
|
|
129
|
-
* many closing quotes appear with no following punctuation.
|
|
130
|
-
* - `punctuationPattern` is the trailing pattern (e.g. `,` or `(?!\.\.\.)\.`).
|
|
101
|
+
* Matches punctuation OUTSIDE consecutive closing quotes (American style).
|
|
102
|
+
* `quotes` is bounded to MAX_NESTED_QUOTES to prevent catastrophic backtracking.
|
|
131
103
|
*/
|
|
132
104
|
function buildOutsidePunctuationRegex(escapedSep, punctuationPattern) {
|
|
133
105
|
const closingQuoteClass = `[${RIGHT_SINGLE_QUOTE}${RIGHT_DOUBLE_QUOTE}]`;
|
|
@@ -140,15 +112,10 @@ function buildOutsidePunctuationRegex(escapedSep, punctuationPattern) {
|
|
|
140
112
|
punctuationPattern;
|
|
141
113
|
return cachedRegExp(pattern, "g");
|
|
142
114
|
}
|
|
143
|
-
/**
|
|
144
|
-
* Move a punctuation mark sitting outside one or more consecutive closing
|
|
145
|
-
* quotes to the inside (American style): `Hello'".` → `Hello.'"`.
|
|
146
|
-
*/
|
|
147
115
|
function moveOutsideToInside(text, escapedSep, replacementChar, punctuationPattern) {
|
|
148
116
|
const regex = buildOutsidePunctuationRegex(escapedSep, punctuationPattern);
|
|
149
117
|
return text.replace(regex, `$<sepBefore>${replacementChar}$<quotes>$<sepAfter>`);
|
|
150
118
|
}
|
|
151
|
-
/** Apply American or British punctuation style */
|
|
152
119
|
function applyPunctuationStyle(text, sep, style) {
|
|
153
120
|
const escapedSep = getEscapedSeparator({ separator: sep });
|
|
154
121
|
if (style === "american") {
|
|
@@ -172,11 +139,8 @@ function applyPunctuationStyle(text, sep, style) {
|
|
|
172
139
|
}
|
|
173
140
|
return text;
|
|
174
141
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
* Tracks „..." (U+201E/U+201C) and ‚...' (U+201A/U+2018) pairs so that
|
|
178
|
-
* the ambiguous closer characters are mapped to the correct American equivalents.
|
|
179
|
-
*/
|
|
142
|
+
// Normalize German quotes back to American for idempotent re-processing.
|
|
143
|
+
// Tracks „..." and ‚...' pairs so ambiguous closers map correctly.
|
|
180
144
|
function normalizeGermanQuotes(text) {
|
|
181
145
|
const DLQ = UNICODE_SYMBOLS.DOUBLE_LOW_9_QUOTE;
|
|
182
146
|
const SLQ = UNICODE_SYMBOLS.SINGLE_LOW_9_QUOTE;
|
|
@@ -216,7 +180,6 @@ function normalizeGermanQuotes(text) {
|
|
|
216
180
|
}
|
|
217
181
|
return chars.join("");
|
|
218
182
|
}
|
|
219
|
-
/** Remap American curly quotes to German low-9 style. Safe because apostrophes are still MLA at this stage. */
|
|
220
183
|
function applyGermanQuotes(text) {
|
|
221
184
|
return text
|
|
222
185
|
.replaceAll(LEFT_DOUBLE_QUOTE, UNICODE_SYMBOLS.DOUBLE_LOW_9_QUOTE)
|
|
@@ -224,34 +187,24 @@ function applyGermanQuotes(text) {
|
|
|
224
187
|
.replaceAll(LEFT_SINGLE_QUOTE, UNICODE_SYMBOLS.SINGLE_LOW_9_QUOTE)
|
|
225
188
|
.replaceAll(RIGHT_SINGLE_QUOTE, LEFT_SINGLE_QUOTE);
|
|
226
189
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
* Strips either NBSP or NNBSP padding — older outputs used NBSP before the
|
|
230
|
-
* fix to the Unicode CLDR / Imprimerie nationale prescription of NNBSP.
|
|
231
|
-
*/
|
|
190
|
+
// Normalize French guillemets back to American for idempotent re-processing.
|
|
191
|
+
// Strips either NBSP or NNBSP padding (older outputs used NBSP).
|
|
232
192
|
function normalizeFrenchQuotes(text) {
|
|
233
193
|
const innerSpace = `[${UNICODE_SYMBOLS.NBSP}${UNICODE_SYMBOLS.NNBSP}]`;
|
|
234
194
|
return text
|
|
235
195
|
.replace(cachedRegExp(`${UNICODE_SYMBOLS.LEFT_GUILLEMET}${innerSpace}?`, "g"), LEFT_DOUBLE_QUOTE)
|
|
236
196
|
.replace(cachedRegExp(`${innerSpace}?${UNICODE_SYMBOLS.RIGHT_GUILLEMET}`, "g"), RIGHT_DOUBLE_QUOTE);
|
|
237
197
|
}
|
|
238
|
-
|
|
239
|
-
* Remap American curly double quotes to French guillemets with NNBSP padding.
|
|
240
|
-
* Uses U+202F (NARROW NO-BREAK SPACE) per Unicode CLDR fr locale and
|
|
241
|
-
* Imprimerie nationale's "Lexique des règles typographiques" (6th ed., 2002),
|
|
242
|
-
* which prescribe a narrow non-breaking space — not U+00A0 — inside `« … »`.
|
|
243
|
-
*/
|
|
198
|
+
// Uses U+202F (NARROW NO-BREAK SPACE) per Unicode CLDR and Imprimerie nationale.
|
|
244
199
|
function applyFrenchQuotes(text) {
|
|
245
200
|
return text
|
|
246
201
|
.replaceAll(LEFT_DOUBLE_QUOTE, `${UNICODE_SYMBOLS.LEFT_GUILLEMET}${UNICODE_SYMBOLS.NNBSP}`)
|
|
247
202
|
.replaceAll(RIGHT_DOUBLE_QUOTE, `${UNICODE_SYMBOLS.NNBSP}${UNICODE_SYMBOLS.RIGHT_GUILLEMET}`);
|
|
248
203
|
}
|
|
249
|
-
/** Locale-specific normalize (pre-pipeline) and apply (post-pipeline) functions. */
|
|
250
204
|
const localeQuoteTransforms = {
|
|
251
205
|
german: { normalize: normalizeGermanQuotes, apply: applyGermanQuotes },
|
|
252
206
|
french: { normalize: normalizeFrenchQuotes, apply: applyFrenchQuotes },
|
|
253
207
|
};
|
|
254
|
-
/** Shared quote-processing pipeline. Returns text with MLA for apostrophes. */
|
|
255
208
|
function processQuotes(text, options) {
|
|
256
209
|
const sep = options.separator ?? DEFAULT_SEPARATOR;
|
|
257
210
|
const punctuationStyle = options.punctuationStyle ?? "american";
|
package/dist/quotes.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"quotes.js","sourceRoot":"","sources":["../src/quotes.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"quotes.js","sourceRoot":"","sources":["../src/quotes.ts"],"names":[],"mappings":"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"}
|
package/dist/rehype.d.ts
CHANGED
|
@@ -1,31 +1,10 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Rehype plugin for applying punctilio typography transformations to HTML.
|
|
3
|
-
*
|
|
4
|
-
* This plugin integrates punctilio with the unified/rehype ecosystem,
|
|
5
|
-
* allowing you to apply smart typography transformations to HTML ASTs.
|
|
6
|
-
*
|
|
7
|
-
* @packageDocumentation
|
|
8
|
-
*/
|
|
9
1
|
import type { Element, ElementContent, Parent, Root, RootContent, Text } from "hast";
|
|
10
2
|
import type { Transformer } from "unified";
|
|
11
3
|
import { type TransformOptions } from "./index.js";
|
|
12
|
-
/** Predicate that decides whether an HTML element should be skipped during transformation. */
|
|
13
4
|
type ElementPredicate = (node: Element) => boolean;
|
|
14
|
-
/** Function that transforms a plain-text string (e.g. smart quotes, dashes). */
|
|
15
5
|
type TextTransformer = (input: string) => string;
|
|
16
|
-
/**
|
|
17
|
-
* Predicate that decides whether an individual text node should be excluded
|
|
18
|
-
* from transformation. Called after element-level `shouldSkip`, so it is
|
|
19
|
-
* never invoked for text inside elements that are already skipped.
|
|
20
|
-
*
|
|
21
|
-
* `ancestors` is the chain of Element parents for the text node, ordered
|
|
22
|
-
* root first, nearest last.
|
|
23
|
-
*/
|
|
6
|
+
/** Per-text-node skip predicate, called after element-level `shouldSkip`. */
|
|
24
7
|
export type TextNodeSkipPredicate = (textNode: Text, ancestors: readonly Element[]) => boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Options shared by functions that flatten and transform text nodes inside
|
|
27
|
-
* an element tree.
|
|
28
|
-
*/
|
|
29
8
|
export interface ElementTransformOptions {
|
|
30
9
|
/**
|
|
31
10
|
* Optional per-text-node skip predicate. When it returns `true` for a
|
|
@@ -35,9 +14,6 @@ export interface ElementTransformOptions {
|
|
|
35
14
|
*/
|
|
36
15
|
shouldSkipText?: TextNodeSkipPredicate;
|
|
37
16
|
}
|
|
38
|
-
/**
|
|
39
|
-
* Options for the rehype-punctilio plugin.
|
|
40
|
-
*/
|
|
41
17
|
export interface RehypePunctilioOptions extends TransformOptions, ElementTransformOptions {
|
|
42
18
|
/**
|
|
43
19
|
* HTML tag names to skip when applying transformations.
|
|
@@ -55,130 +31,17 @@ export interface RehypePunctilioOptions extends TransformOptions, ElementTransfo
|
|
|
55
31
|
*/
|
|
56
32
|
skipClasses?: string[];
|
|
57
33
|
}
|
|
58
|
-
/**
|
|
59
|
-
* Flattens text nodes from an element tree into a single array.
|
|
60
|
-
*
|
|
61
|
-
* Pass `options.shouldSkipText` to exclude individual text nodes from the
|
|
62
|
-
* result. Applied after element-level `shouldSkip`, so the hook is never
|
|
63
|
-
* invoked for text inside an already-skipped element.
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```ts
|
|
67
|
-
* const textNodes = flattenTextNodes(paragraphElement, (el) => el.tagName === 'code')
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
34
|
export declare function flattenTextNodes(node: Element | ElementContent, shouldSkip: ElementPredicate, options?: ElementTransformOptions): Text[];
|
|
71
|
-
/**
|
|
72
|
-
* Extracts concatenated text content from an element.
|
|
73
|
-
*
|
|
74
|
-
* @example
|
|
75
|
-
* ```ts
|
|
76
|
-
* const text = getTextContent(paragraphElement)
|
|
77
|
-
* // Returns "Hello, world!" for <p>Hello, <em>world!</em></p>
|
|
78
|
-
* ```
|
|
79
|
-
*/
|
|
80
35
|
export declare function getTextContent(node: Element, shouldSkip?: ElementPredicate): string;
|
|
81
|
-
/**
|
|
82
|
-
* Recursively finds the first text node in a tree of HTML elements.
|
|
83
|
-
* Returns null if no text nodes exist.
|
|
84
|
-
*
|
|
85
|
-
* @example
|
|
86
|
-
* ```ts
|
|
87
|
-
* const textNode = getFirstTextNode(divElement)
|
|
88
|
-
* if (textNode) console.log(textNode.value)
|
|
89
|
-
* ```
|
|
90
|
-
*/
|
|
91
36
|
export declare function getFirstTextNode(node: Parent | RootContent, depth?: number): Text | null;
|
|
92
|
-
/**
|
|
93
|
-
* Validates that smart double quotes in a text string are properly matched.
|
|
94
|
-
*
|
|
95
|
-
* Only checks double quotes (\u201C/\u201D). Single quotes are intentionally
|
|
96
|
-
* excluded because \u2019 (right single quote) doubles as an apostrophe,
|
|
97
|
-
* making balance-checking unreliable.
|
|
98
|
-
*
|
|
99
|
-
* @throws Error if double quotes are mismatched
|
|
100
|
-
*
|
|
101
|
-
* @example
|
|
102
|
-
* ```ts
|
|
103
|
-
* assertSmartQuotesMatch('\u201CHello\u201D') // OK
|
|
104
|
-
* assertSmartQuotesMatch('\u201CHello') // throws Error
|
|
105
|
-
* ```
|
|
106
|
-
*/
|
|
107
37
|
export declare function assertSmartQuotesMatch(input: string): void;
|
|
108
38
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* HTML elements. It:
|
|
113
|
-
* 1. Appends a private-use Unicode character to each child's text content
|
|
114
|
-
* 2. Concatenates and transforms the whole paragraph
|
|
115
|
-
* 3. Splits the result back into the original text nodes
|
|
116
|
-
*
|
|
117
|
-
* When `checkInvariance` is true, also verifies that the transform produces
|
|
118
|
-
* the same result with and without markers — i.e.,
|
|
119
|
-
* `stripMarkers(transform(textWithMarkers)) === transform(stripMarkers(text))`.
|
|
120
|
-
* Useful for debugging transforms that accidentally interact with markers.
|
|
121
|
-
*
|
|
122
|
-
* Pass `options.shouldSkipText` to opt individual text nodes out of
|
|
123
|
-
* transformation without skipping their enclosing element; skipped text
|
|
124
|
-
* nodes keep their original `.value`.
|
|
125
|
-
*
|
|
126
|
-
* @throws Error if transformation alters the number of text nodes
|
|
127
|
-
* @throws Error if `checkInvariance` is true and the invariance check fails
|
|
128
|
-
*
|
|
129
|
-
* @example
|
|
130
|
-
* ```ts
|
|
131
|
-
* import { transformElement, DEFAULT_SEPARATOR } from 'punctilio/rehype'
|
|
132
|
-
*
|
|
133
|
-
* // Apply a custom transform to an element
|
|
134
|
-
* transformElement(
|
|
135
|
-
* paragraphElement,
|
|
136
|
-
* (text) => text.replace(/eg\b/g, 'e.g.'),
|
|
137
|
-
* (el) => el.tagName === 'code',
|
|
138
|
-
* DEFAULT_SEPARATOR
|
|
139
|
-
* )
|
|
140
|
-
* ```
|
|
39
|
+
* Transforms element text using the separator-marking technique. When
|
|
40
|
+
* `checkInvariance` is true, verifies `stripMarkers(transform(marked)) ===
|
|
41
|
+
* transform(stripMarkers(text))` for debugging marker interactions.
|
|
141
42
|
*/
|
|
142
43
|
export declare function transformElement(node: Element, transformFn: TextTransformer, shouldSkip: ElementPredicate, separator: string, checkInvariance?: boolean, options?: ElementTransformOptions): void;
|
|
143
|
-
/**
|
|
144
|
-
* Collects elements that should have text transformations applied.
|
|
145
|
-
*
|
|
146
|
-
* An element is collected as a single transformation unit when it:
|
|
147
|
-
* 1. Has direct text children (original behavior), OR
|
|
148
|
-
* 2. Has text descendants and NO block-level children — meaning all its
|
|
149
|
-
* content is inline (phrasing) and should share transformation context
|
|
150
|
-
* (e.g., `<p><em>"Hello</em><span>, world"</span></p>`).
|
|
151
|
-
*
|
|
152
|
-
* When an element has block-level children, we recurse so each block
|
|
153
|
-
* is processed independently (e.g., `<div><p>A</p><p>B</p></div>`).
|
|
154
|
-
*
|
|
155
|
-
* @param alreadyTransformed - Elements already processed; skipped during traversal to avoid redundant work
|
|
156
|
-
*/
|
|
157
44
|
export declare function collectTransformableElements(node: Element, shouldSkip: ElementPredicate, depth?: number, alreadyTransformed?: ReadonlySet<Element>): Element[];
|
|
158
|
-
/**
|
|
159
|
-
* Rehype plugin that applies punctilio typography transformations to HTML.
|
|
160
|
-
*
|
|
161
|
-
* @example
|
|
162
|
-
* ```ts
|
|
163
|
-
* import { unified } from 'unified'
|
|
164
|
-
* import remarkParse from 'remark-parse'
|
|
165
|
-
* import remarkRehype from 'remark-rehype'
|
|
166
|
-
* import rehypeStringify from 'rehype-stringify'
|
|
167
|
-
* import { rehypePunctilio } from 'punctilio/rehype'
|
|
168
|
-
*
|
|
169
|
-
* const result = await unified()
|
|
170
|
-
* .use(remarkParse)
|
|
171
|
-
* .use(remarkRehype)
|
|
172
|
-
* .use(rehypePunctilio, {
|
|
173
|
-
* punctuationStyle: 'american',
|
|
174
|
-
* dashStyle: 'american',
|
|
175
|
-
* })
|
|
176
|
-
* .use(rehypeStringify)
|
|
177
|
-
* .process('"Hello," she said -- "it\'s nice."')
|
|
178
|
-
*
|
|
179
|
-
* // Output HTML will have smart quotes and em-dashes
|
|
180
|
-
* ```
|
|
181
|
-
*/
|
|
182
45
|
export declare function rehypePunctilio(options?: RehypePunctilioOptions): Transformer<Root, Root>;
|
|
183
46
|
export default rehypePunctilio;
|
|
184
47
|
//# sourceMappingURL=rehype.d.ts.map
|
package/dist/rehype.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rehype.d.ts","sourceRoot":"","sources":["../src/rehype.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rehype.d.ts","sourceRoot":"","sources":["../src/rehype.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AACpF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAI1C,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAI7D,KAAK,gBAAgB,GAAG,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAA;AAElD,KAAK,eAAe,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;AAEhD,6EAA6E;AAC7E,MAAM,MAAM,qBAAqB,GAAG,CAClC,QAAQ,EAAE,IAAI,EACd,SAAS,EAAE,SAAS,OAAO,EAAE,KAC1B,OAAO,CAAA;AAEZ,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,qBAAqB,CAAA;CACvC;AAED,MAAM,WAAW,sBACf,SAAQ,gBAAgB,EACtB,uBAAuB;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IAEnB;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CACvB;AAID,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,OAAO,GAAG,cAAc,EAC9B,UAAU,EAAE,gBAAgB,EAC5B,OAAO,CAAC,EAAE,uBAAuB,GAChC,IAAI,EAAE,CAMR;AAuCD,wBAAgB,cAAc,CAC5B,IAAI,EAAE,OAAO,EACb,UAAU,GAAE,gBAA8B,GACzC,MAAM,CAIR;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,GAAG,WAAW,EAC1B,KAAK,GAAE,MAAU,GAChB,IAAI,GAAG,IAAI,CAeb;AAOD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAoB1D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,OAAO,EACb,WAAW,EAAE,eAAe,EAC5B,UAAU,EAAE,gBAAgB,EAC5B,SAAS,EAAE,MAAM,EACjB,eAAe,GAAE,OAAe,EAChC,OAAO,CAAC,EAAE,uBAAuB,GAChC,IAAI,CAgCN;AA6FD,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,OAAO,EACb,UAAU,EAAE,gBAAgB,EAC5B,KAAK,GAAE,MAAU,EACjB,kBAAkB,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,GACxC,OAAO,EAAE,CAsCX;AAgBD,wBAAgB,eAAe,CAC7B,OAAO,GAAE,sBAA2B,GACnC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAsEzB;AAED,eAAe,eAAe,CAAA"}
|
package/dist/rehype.js
CHANGED
|
@@ -1,28 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Rehype plugin for applying punctilio typography transformations to HTML.
|
|
3
|
-
*
|
|
4
|
-
* This plugin integrates punctilio with the unified/rehype ecosystem,
|
|
5
|
-
* allowing you to apply smart typography transformations to HTML ASTs.
|
|
6
|
-
*
|
|
7
|
-
* @packageDocumentation
|
|
8
|
-
*/
|
|
9
1
|
import { SKIP, visitParents } from "unist-util-visit-parents";
|
|
10
2
|
import { transform } from "./index.js";
|
|
11
3
|
import { DEFAULT_SEPARATOR, MAX_RECURSION_DEPTH } from "./constants.js";
|
|
12
4
|
import { formatErrorString, transformTextNodes } from "./utils.js";
|
|
13
5
|
const DEFAULT_SKIP_TAGS = ["code", "pre", "script", "style", "kbd", "var", "samp", "template", "math", "svg"];
|
|
14
|
-
/**
|
|
15
|
-
* Flattens text nodes from an element tree into a single array.
|
|
16
|
-
*
|
|
17
|
-
* Pass `options.shouldSkipText` to exclude individual text nodes from the
|
|
18
|
-
* result. Applied after element-level `shouldSkip`, so the hook is never
|
|
19
|
-
* invoked for text inside an already-skipped element.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```ts
|
|
23
|
-
* const textNodes = flattenTextNodes(paragraphElement, (el) => el.tagName === 'code')
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
6
|
export function flattenTextNodes(node, shouldSkip, options) {
|
|
27
7
|
const shouldSkipText = options?.shouldSkipText;
|
|
28
8
|
// Only track ancestors when shouldSkipText needs them, to avoid the
|
|
@@ -56,30 +36,11 @@ function flattenTextNodesImpl(node, shouldSkip, shouldSkipText, ancestors, depth
|
|
|
56
36
|
}
|
|
57
37
|
return [];
|
|
58
38
|
}
|
|
59
|
-
/**
|
|
60
|
-
* Extracts concatenated text content from an element.
|
|
61
|
-
*
|
|
62
|
-
* @example
|
|
63
|
-
* ```ts
|
|
64
|
-
* const text = getTextContent(paragraphElement)
|
|
65
|
-
* // Returns "Hello, world!" for <p>Hello, <em>world!</em></p>
|
|
66
|
-
* ```
|
|
67
|
-
*/
|
|
68
39
|
export function getTextContent(node, shouldSkip = () => false) {
|
|
69
40
|
return flattenTextNodes(node, shouldSkip)
|
|
70
41
|
.map((n) => n.value)
|
|
71
42
|
.join("");
|
|
72
43
|
}
|
|
73
|
-
/**
|
|
74
|
-
* Recursively finds the first text node in a tree of HTML elements.
|
|
75
|
-
* Returns null if no text nodes exist.
|
|
76
|
-
*
|
|
77
|
-
* @example
|
|
78
|
-
* ```ts
|
|
79
|
-
* const textNode = getFirstTextNode(divElement)
|
|
80
|
-
* if (textNode) console.log(textNode.value)
|
|
81
|
-
* ```
|
|
82
|
-
*/
|
|
83
44
|
export function getFirstTextNode(node, depth = 0) {
|
|
84
45
|
if (!node || depth > MAX_RECURSION_DEPTH)
|
|
85
46
|
return null;
|
|
@@ -97,21 +58,8 @@ export function getFirstTextNode(node, depth = 0) {
|
|
|
97
58
|
}
|
|
98
59
|
const QUOTE_OPENERS = new Set(["\u201C"]);
|
|
99
60
|
const CLOSER_TO_OPENER = { "\u201D": "\u201C" };
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
*
|
|
103
|
-
* Only checks double quotes (\u201C/\u201D). Single quotes are intentionally
|
|
104
|
-
* excluded because \u2019 (right single quote) doubles as an apostrophe,
|
|
105
|
-
* making balance-checking unreliable.
|
|
106
|
-
*
|
|
107
|
-
* @throws Error if double quotes are mismatched
|
|
108
|
-
*
|
|
109
|
-
* @example
|
|
110
|
-
* ```ts
|
|
111
|
-
* assertSmartQuotesMatch('\u201CHello\u201D') // OK
|
|
112
|
-
* assertSmartQuotesMatch('\u201CHello') // throws Error
|
|
113
|
-
* ```
|
|
114
|
-
*/
|
|
61
|
+
// Only checks double quotes \u2014 single quotes are excluded because
|
|
62
|
+
// U+2019 doubles as an apostrophe, making balance-checking unreliable.
|
|
115
63
|
export function assertSmartQuotesMatch(input) {
|
|
116
64
|
if (!input)
|
|
117
65
|
return;
|
|
@@ -134,38 +82,9 @@ export function assertSmartQuotesMatch(input) {
|
|
|
134
82
|
}
|
|
135
83
|
}
|
|
136
84
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* HTML elements. It:
|
|
141
|
-
* 1. Appends a private-use Unicode character to each child's text content
|
|
142
|
-
* 2. Concatenates and transforms the whole paragraph
|
|
143
|
-
* 3. Splits the result back into the original text nodes
|
|
144
|
-
*
|
|
145
|
-
* When `checkInvariance` is true, also verifies that the transform produces
|
|
146
|
-
* the same result with and without markers — i.e.,
|
|
147
|
-
* `stripMarkers(transform(textWithMarkers)) === transform(stripMarkers(text))`.
|
|
148
|
-
* Useful for debugging transforms that accidentally interact with markers.
|
|
149
|
-
*
|
|
150
|
-
* Pass `options.shouldSkipText` to opt individual text nodes out of
|
|
151
|
-
* transformation without skipping their enclosing element; skipped text
|
|
152
|
-
* nodes keep their original `.value`.
|
|
153
|
-
*
|
|
154
|
-
* @throws Error if transformation alters the number of text nodes
|
|
155
|
-
* @throws Error if `checkInvariance` is true and the invariance check fails
|
|
156
|
-
*
|
|
157
|
-
* @example
|
|
158
|
-
* ```ts
|
|
159
|
-
* import { transformElement, DEFAULT_SEPARATOR } from 'punctilio/rehype'
|
|
160
|
-
*
|
|
161
|
-
* // Apply a custom transform to an element
|
|
162
|
-
* transformElement(
|
|
163
|
-
* paragraphElement,
|
|
164
|
-
* (text) => text.replace(/eg\b/g, 'e.g.'),
|
|
165
|
-
* (el) => el.tagName === 'code',
|
|
166
|
-
* DEFAULT_SEPARATOR
|
|
167
|
-
* )
|
|
168
|
-
* ```
|
|
85
|
+
* Transforms element text using the separator-marking technique. When
|
|
86
|
+
* `checkInvariance` is true, verifies `stripMarkers(transform(marked)) ===
|
|
87
|
+
* transform(stripMarkers(text))` for debugging marker interactions.
|
|
169
88
|
*/
|
|
170
89
|
export function transformElement(node, transformFn, shouldSkip, separator, checkInvariance = false, options) {
|
|
171
90
|
/* istanbul ignore if -- defensive: elements should always have children array */
|
|
@@ -193,12 +112,8 @@ export function transformElement(node, transformFn, shouldSkip, separator, check
|
|
|
193
112
|
}
|
|
194
113
|
}
|
|
195
114
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
* child, its children are processed independently rather than as a single
|
|
199
|
-
* unit. This prevents merging text across semantically independent blocks
|
|
200
|
-
* (e.g., separate paragraphs inside a div).
|
|
201
|
-
*/
|
|
115
|
+
// Block children cause per-block processing to avoid merging text across
|
|
116
|
+
// semantically independent blocks (e.g., separate <p>s inside a <div>).
|
|
202
117
|
const BLOCK_ELEMENTS = new Set([
|
|
203
118
|
"address", "article", "aside", "blockquote", "details", "dialog",
|
|
204
119
|
"dd", "div", "dl", "dt", "fieldset", "figcaption", "figure",
|
|
@@ -206,10 +121,6 @@ const BLOCK_ELEMENTS = new Set([
|
|
|
206
121
|
"header", "hgroup", "hr", "li", "main", "nav", "ol",
|
|
207
122
|
"p", "pre", "section", "table", "ul",
|
|
208
123
|
]);
|
|
209
|
-
/**
|
|
210
|
-
* HTML elements that can contain transformable text content.
|
|
211
|
-
* We traverse into these to find text nodes to transform.
|
|
212
|
-
*/
|
|
213
124
|
const TRANSFORMABLE_ELEMENTS = new Set([
|
|
214
125
|
"p",
|
|
215
126
|
"em",
|
|
@@ -266,11 +177,6 @@ const TRANSFORMABLE_ELEMENTS = new Set([
|
|
|
266
177
|
"rt",
|
|
267
178
|
"rp",
|
|
268
179
|
]);
|
|
269
|
-
/**
|
|
270
|
-
* Checks whether an element has any text node descendants (skipping elements
|
|
271
|
-
* matched by shouldSkip). Returns as soon as one is found — avoids allocating
|
|
272
|
-
* an array of all text nodes just to check existence.
|
|
273
|
-
*/
|
|
274
180
|
function hasTextDescendant(node, shouldSkip, depth = 0) {
|
|
275
181
|
if (depth > MAX_RECURSION_DEPTH) {
|
|
276
182
|
return false;
|
|
@@ -286,20 +192,6 @@ function hasTextDescendant(node, shouldSkip, depth = 0) {
|
|
|
286
192
|
}
|
|
287
193
|
return false;
|
|
288
194
|
}
|
|
289
|
-
/**
|
|
290
|
-
* Collects elements that should have text transformations applied.
|
|
291
|
-
*
|
|
292
|
-
* An element is collected as a single transformation unit when it:
|
|
293
|
-
* 1. Has direct text children (original behavior), OR
|
|
294
|
-
* 2. Has text descendants and NO block-level children — meaning all its
|
|
295
|
-
* content is inline (phrasing) and should share transformation context
|
|
296
|
-
* (e.g., `<p><em>"Hello</em><span>, world"</span></p>`).
|
|
297
|
-
*
|
|
298
|
-
* When an element has block-level children, we recurse so each block
|
|
299
|
-
* is processed independently (e.g., `<div><p>A</p><p>B</p></div>`).
|
|
300
|
-
*
|
|
301
|
-
* @param alreadyTransformed - Elements already processed; skipped during traversal to avoid redundant work
|
|
302
|
-
*/
|
|
303
195
|
export function collectTransformableElements(node, shouldSkip, depth = 0, alreadyTransformed) {
|
|
304
196
|
/* istanbul ignore if -- defensive: prevents stack overflow from malicious HTML */
|
|
305
197
|
if (depth > MAX_RECURSION_DEPTH) {
|
|
@@ -332,11 +224,6 @@ export function collectTransformableElements(node, shouldSkip, depth = 0, alread
|
|
|
332
224
|
}
|
|
333
225
|
return results;
|
|
334
226
|
}
|
|
335
|
-
/**
|
|
336
|
-
* Recursively marks all element descendants as transformed.
|
|
337
|
-
* Used to prevent redundant processing of nested elements whose text
|
|
338
|
-
* was already processed as part of a parent element.
|
|
339
|
-
*/
|
|
340
227
|
function markDescendants(node, set, depth = 0) {
|
|
341
228
|
/* istanbul ignore if -- defensive: prevents stack overflow from malicious HTML */
|
|
342
229
|
if (depth > MAX_RECURSION_DEPTH) {
|
|
@@ -349,30 +236,6 @@ function markDescendants(node, set, depth = 0) {
|
|
|
349
236
|
}
|
|
350
237
|
}
|
|
351
238
|
}
|
|
352
|
-
/**
|
|
353
|
-
* Rehype plugin that applies punctilio typography transformations to HTML.
|
|
354
|
-
*
|
|
355
|
-
* @example
|
|
356
|
-
* ```ts
|
|
357
|
-
* import { unified } from 'unified'
|
|
358
|
-
* import remarkParse from 'remark-parse'
|
|
359
|
-
* import remarkRehype from 'remark-rehype'
|
|
360
|
-
* import rehypeStringify from 'rehype-stringify'
|
|
361
|
-
* import { rehypePunctilio } from 'punctilio/rehype'
|
|
362
|
-
*
|
|
363
|
-
* const result = await unified()
|
|
364
|
-
* .use(remarkParse)
|
|
365
|
-
* .use(remarkRehype)
|
|
366
|
-
* .use(rehypePunctilio, {
|
|
367
|
-
* punctuationStyle: 'american',
|
|
368
|
-
* dashStyle: 'american',
|
|
369
|
-
* })
|
|
370
|
-
* .use(rehypeStringify)
|
|
371
|
-
* .process('"Hello," she said -- "it\'s nice."')
|
|
372
|
-
*
|
|
373
|
-
* // Output HTML will have smart quotes and em-dashes
|
|
374
|
-
* ```
|
|
375
|
-
*/
|
|
376
239
|
export function rehypePunctilio(options = {}) {
|
|
377
240
|
const { skipTags = DEFAULT_SKIP_TAGS, skipClasses = [], separator = DEFAULT_SEPARATOR, shouldSkipText, ...transformOptions } = options;
|
|
378
241
|
const skipTagSet = new Set(skipTags);
|