punctilio 1.7.14 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +8 -8
- package/src/tests/index.test.ts +55 -53
- package/src/tests/rehype.test.ts +23 -17
package/README.md
CHANGED
|
@@ -109,7 +109,7 @@ For manual DOM walking or custom transforms, use `transformElement` from `puncti
|
|
|
109
109
|
|
|
110
110
|
## Options
|
|
111
111
|
|
|
112
|
-
`punctilio` doesn
|
|
112
|
+
`punctilio` doesn't enable all transformations by default. Fractions and degrees tend to match too aggressively (perfectly applying the degree transformation requires semantic meaning). Superscript letters and punctuation ligatures have spotty font support. Furthermore, `ligatures = true` can change the meaning of text by collapsing question and exclamation marks.
|
|
113
113
|
|
|
114
114
|
```typescript
|
|
115
115
|
transform(text, {
|
|
@@ -122,7 +122,7 @@ transform(text, {
|
|
|
122
122
|
degrees: false, // 20 C → 20 °C
|
|
123
123
|
superscript: false, // 1st → 1ˢᵗ
|
|
124
124
|
ligatures: false, // ??? → ⁇, ?! → ⁈, !? → ⁉, !!! → !
|
|
125
|
-
nbsp:
|
|
125
|
+
nbsp: true, // non-breaking spaces (after honorifics, between numbers and units, etc.)
|
|
126
126
|
checkIdempotency: true, // verify transform(transform(x)) === transform(x)
|
|
127
127
|
})
|
|
128
128
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -86,7 +86,7 @@ export interface TransformOptions {
|
|
|
86
86
|
* Whether to insert non-breaking spaces in typographically appropriate
|
|
87
87
|
* locations (after short words, between numbers and units, before
|
|
88
88
|
* last words to prevent widows, after honorifics, etc.).
|
|
89
|
-
* Default:
|
|
89
|
+
* Default: true
|
|
90
90
|
*/
|
|
91
91
|
nbsp?: boolean;
|
|
92
92
|
/**
|
package/dist/index.js
CHANGED
|
@@ -32,8 +32,8 @@ export { DEFAULT_SEPARATOR } from "./constants.js";
|
|
|
32
32
|
* 6. degrees (disabled by default)
|
|
33
33
|
* 7. superscript (disabled by default)
|
|
34
34
|
* 8. ligatures (disabled by default)
|
|
35
|
-
* 9.
|
|
36
|
-
* 10.
|
|
35
|
+
* 9. collapseSpaces (collapses multiple spaces into one)
|
|
36
|
+
* 10. nbsp (non-breaking spaces, enabled by default)
|
|
37
37
|
*
|
|
38
38
|
* @param text - The text to transform
|
|
39
39
|
* @param options - Configuration options
|
|
@@ -59,7 +59,7 @@ const defaultOpts = {
|
|
|
59
59
|
degrees: false,
|
|
60
60
|
superscript: false,
|
|
61
61
|
ligatures: false,
|
|
62
|
-
nbsp:
|
|
62
|
+
nbsp: true,
|
|
63
63
|
collapseSpaces: true,
|
|
64
64
|
checkIdempotency: true,
|
|
65
65
|
punctuationStyle: "american",
|
|
@@ -94,12 +94,12 @@ export function transform(text, options = {}) {
|
|
|
94
94
|
if (ligatures) {
|
|
95
95
|
text = ligaturesTransform(text, separatorOpts);
|
|
96
96
|
}
|
|
97
|
-
if (nbsp) {
|
|
98
|
-
text = nbspTransformFn(text, separatorOpts);
|
|
99
|
-
}
|
|
100
97
|
if (collapseSpaces) {
|
|
101
98
|
text = collapseSpacesTransform(text);
|
|
102
99
|
}
|
|
100
|
+
if (nbsp) {
|
|
101
|
+
text = nbspTransformFn(text, separatorOpts);
|
|
102
|
+
}
|
|
103
103
|
assertSeparatorCountPreserved(original, text, separator, "transform");
|
|
104
104
|
if (checkIdempotency) {
|
|
105
105
|
const secondPass = transform(text, { ...options, checkIdempotency: false });
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAA4C,MAAM,aAAa,CAAA;AAElF,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,MAAM,EACN,6BAA6B,GAG9B,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,QAAQ,EACR,cAAc,EACd,WAAW,EACX,YAAY,EACZ,MAAM,EACN,OAAO,EACP,SAAS,EACT,UAAU,EACV,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,eAAe,GAEhB,MAAM,cAAc,CAAA;AACrB,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,kBAAkB,EAClB,+BAA+B,EAC/B,uBAAuB,EACvB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,EACnB,aAAa,EACb,KAAK,EACL,UAAU,EACV,uBAAuB,GAExB,MAAM,WAAW,CAAA;AAkGlB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,SAAS,IAAI,kBAAkB,EAAE,OAAO,IAAI,gBAAgB,EAAE,kBAAkB,IAAI,oBAAoB,EAAE,UAAU,EAAE,cAAc,IAAI,uBAAuB,EAAE,oBAAoB,IAAI,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAC3P,OAAO,EAAE,aAAa,IAAI,eAAe,EAAE,MAAM,WAAW,CAAA;AAC5D,OAAO,EAAE,6BAA6B,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC7E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAElD,OAAO,EAAE,6BAA6B,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,WAAW,GAAkD;IACjE,OAAO,EAAE,IAAI;IACb,SAAS,EAAE,KAAK;IAChB,OAAO,EAAE,KAAK;IACd,WAAW,EAAE,KAAK;IAClB,SAAS,EAAE,KAAK;IAChB,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -134,7 +134,7 @@ export interface TransformOptions {
|
|
|
134
134
|
* Whether to insert non-breaking spaces in typographically appropriate
|
|
135
135
|
* locations (after short words, between numbers and units, before
|
|
136
136
|
* last words to prevent widows, after honorifics, etc.).
|
|
137
|
-
* Default:
|
|
137
|
+
* Default: true
|
|
138
138
|
*/
|
|
139
139
|
nbsp?: boolean
|
|
140
140
|
|
|
@@ -171,8 +171,8 @@ export { DEFAULT_SEPARATOR } from "./constants.js"
|
|
|
171
171
|
* 6. degrees (disabled by default)
|
|
172
172
|
* 7. superscript (disabled by default)
|
|
173
173
|
* 8. ligatures (disabled by default)
|
|
174
|
-
* 9.
|
|
175
|
-
* 10.
|
|
174
|
+
* 9. collapseSpaces (collapses multiple spaces into one)
|
|
175
|
+
* 10. nbsp (non-breaking spaces, enabled by default)
|
|
176
176
|
*
|
|
177
177
|
* @param text - The text to transform
|
|
178
178
|
* @param options - Configuration options
|
|
@@ -198,7 +198,7 @@ const defaultOpts: Required<Omit<TransformOptions, "separator">> = {
|
|
|
198
198
|
degrees: false,
|
|
199
199
|
superscript: false,
|
|
200
200
|
ligatures: false,
|
|
201
|
-
nbsp:
|
|
201
|
+
nbsp: true,
|
|
202
202
|
collapseSpaces: true,
|
|
203
203
|
checkIdempotency: true,
|
|
204
204
|
punctuationStyle: "american",
|
|
@@ -245,14 +245,14 @@ export function transform(text: string, options: TransformOptions = {}): string
|
|
|
245
245
|
text = ligaturesTransform(text, separatorOpts)
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
if (nbsp) {
|
|
249
|
-
text = nbspTransformFn(text, separatorOpts)
|
|
250
|
-
}
|
|
251
|
-
|
|
252
248
|
if (collapseSpaces) {
|
|
253
249
|
text = collapseSpacesTransform(text)
|
|
254
250
|
}
|
|
255
251
|
|
|
252
|
+
if (nbsp) {
|
|
253
|
+
text = nbspTransformFn(text, separatorOpts)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
256
|
assertSeparatorCountPreserved(original, text, separator, "transform")
|
|
257
257
|
|
|
258
258
|
if (checkIdempotency) {
|
package/src/tests/index.test.ts
CHANGED
|
@@ -26,43 +26,43 @@ describe("transform", () => {
|
|
|
26
26
|
it("applies both quote and dash transformations", () => {
|
|
27
27
|
const input = '"Hello," she said - "it\'s pages 1-5."'
|
|
28
28
|
const expected = `${LEFT_DOUBLE_QUOTE}Hello,${RIGHT_DOUBLE_QUOTE} she said${EM_DASH}${LEFT_DOUBLE_QUOTE}it${RIGHT_SINGLE_QUOTE}s pages 1${EN_DASH}5.${RIGHT_DOUBLE_QUOTE}`
|
|
29
|
-
expect(transform(input)).toBe(expected)
|
|
29
|
+
expect(transform(input, { nbsp: false })).toBe(expected)
|
|
30
30
|
})
|
|
31
31
|
|
|
32
32
|
it("handles complex mixed content", () => {
|
|
33
33
|
const input = 'I was born in \'99 - "the best year" - and pages 10-20 are my favorite.'
|
|
34
34
|
const expected = `I was born in ${RIGHT_SINGLE_QUOTE}99${EM_DASH}${LEFT_DOUBLE_QUOTE}the best year${RIGHT_DOUBLE_QUOTE}${EM_DASH}and pages 10${EN_DASH}20 are my favorite.`
|
|
35
|
-
expect(transform(input)).toBe(expected)
|
|
35
|
+
expect(transform(input, { nbsp: false })).toBe(expected)
|
|
36
36
|
})
|
|
37
37
|
|
|
38
38
|
it("preserves separator character", () => {
|
|
39
39
|
const sep = DEFAULT_SEPARATOR
|
|
40
40
|
const input = `"Hello${sep}" - test`
|
|
41
|
-
expect(transform(input, { separator: sep })).toBe(`${LEFT_DOUBLE_QUOTE}Hello${sep}${RIGHT_DOUBLE_QUOTE}${EM_DASH}test`)
|
|
41
|
+
expect(transform(input, { separator: sep, nbsp: false })).toBe(`${LEFT_DOUBLE_QUOTE}Hello${sep}${RIGHT_DOUBLE_QUOTE}${EM_DASH}test`)
|
|
42
42
|
})
|
|
43
43
|
|
|
44
44
|
describe("symbol transforms", () => {
|
|
45
45
|
it("applies symbol transforms by default", () => {
|
|
46
|
-
expect(transform('Wait... 5x5 != 25 (c) 2024')).toBe(`Wait${ELLIPSIS} 5${MULTIPLICATION}5 ${NOT_EQUAL} 25 ${COPYRIGHT} 2024`)
|
|
46
|
+
expect(transform('Wait... 5x5 != 25 (c) 2024', { nbsp: false })).toBe(`Wait${ELLIPSIS} 5${MULTIPLICATION}5 ${NOT_EQUAL} 25 ${COPYRIGHT} 2024`)
|
|
47
47
|
})
|
|
48
48
|
|
|
49
49
|
it("can disable symbol transforms", () => {
|
|
50
|
-
expect(transform('Wait... 5x5 != 25', { symbols: false })).toBe('Wait... 5x5 != 25')
|
|
50
|
+
expect(transform('Wait... 5x5 != 25', { symbols: false, nbsp: false })).toBe('Wait... 5x5 != 25')
|
|
51
51
|
})
|
|
52
52
|
})
|
|
53
53
|
|
|
54
54
|
describe("optional transforms", () => {
|
|
55
55
|
it.each([
|
|
56
|
-
["fractions disabled", "1/2", {}, "1/2"],
|
|
57
|
-
["fractions enabled", "1/2", { fractions: true }, UNICODE_SYMBOLS.FRACTION_1_2],
|
|
58
|
-
["degrees disabled", "20 C", {}, "20 C"],
|
|
59
|
-
["degrees enabled", "20 C", { degrees: true }, `20 ${UNICODE_SYMBOLS.DEGREE}C`],
|
|
60
|
-
["superscript disabled", "1st", {}, "1st"],
|
|
61
|
-
["superscript enabled", "1st", { superscript: true }, `1${UNICODE_SYMBOLS.SUPERSCRIPT_ST}`],
|
|
62
|
-
["ligatures disabled", "??", {}, "??"],
|
|
63
|
-
["ligatures enabled", "??", { ligatures: true }, UNICODE_SYMBOLS.DOUBLE_QUESTION],
|
|
64
|
-
["nbsp
|
|
65
|
-
["nbsp
|
|
56
|
+
["fractions disabled", "1/2", { nbsp: false }, "1/2"],
|
|
57
|
+
["fractions enabled", "1/2", { fractions: true, nbsp: false }, UNICODE_SYMBOLS.FRACTION_1_2],
|
|
58
|
+
["degrees disabled", "20 C", { nbsp: false }, "20 C"],
|
|
59
|
+
["degrees enabled", "20 C", { degrees: true, nbsp: false }, `20 ${UNICODE_SYMBOLS.DEGREE}C`],
|
|
60
|
+
["superscript disabled", "1st", { nbsp: false }, "1st"],
|
|
61
|
+
["superscript enabled", "1st", { superscript: true, nbsp: false }, `1${UNICODE_SYMBOLS.SUPERSCRIPT_ST}`],
|
|
62
|
+
["ligatures disabled", "??", { nbsp: false }, "??"],
|
|
63
|
+
["ligatures enabled", "??", { ligatures: true, nbsp: false }, UNICODE_SYMBOLS.DOUBLE_QUESTION],
|
|
64
|
+
["nbsp enabled (default)", "Dr. Smith", {}, `Dr.${NBSP}Smith`],
|
|
65
|
+
["nbsp disabled", "Dr. Smith", { nbsp: false }, "Dr. Smith"],
|
|
66
66
|
] as const)("%s: %s → %s", (_desc, input, options, expected) => {
|
|
67
67
|
expect(transform(input, options)).toBe(expected)
|
|
68
68
|
})
|
|
@@ -77,7 +77,7 @@ describe("transform", () => {
|
|
|
77
77
|
['"Hello."', "british", periodOutside, "british"],
|
|
78
78
|
['"Hello".', "none", periodOutside, "none"],
|
|
79
79
|
] as const)("handles %s with %s style", (input, style, expected) => {
|
|
80
|
-
expect(transform(input, style ? { punctuationStyle: style } : {})).toBe(expected)
|
|
80
|
+
expect(transform(input, { ...(style ? { punctuationStyle: style } : {}), nbsp: false })).toBe(expected)
|
|
81
81
|
})
|
|
82
82
|
})
|
|
83
83
|
|
|
@@ -88,14 +88,14 @@ describe("transform", () => {
|
|
|
88
88
|
[`a ${NBSP}b`, `a${NBSP}b`, "mixed spaces prefer nbsp"],
|
|
89
89
|
[`a${NBSP} b`, `a${NBSP}b`, "mixed spaces prefer nbsp"],
|
|
90
90
|
])("collapses %s by default", (input, expected) => {
|
|
91
|
-
expect(transform(input)).toBe(expected)
|
|
91
|
+
expect(transform(input, { nbsp: false })).toBe(expected)
|
|
92
92
|
})
|
|
93
93
|
|
|
94
94
|
it.each([
|
|
95
95
|
["hello world", "hello world", "multiple spaces"],
|
|
96
96
|
[`foo${NBSP}${NBSP}bar`, `foo${NBSP}${NBSP}bar`, "multiple nbsp"],
|
|
97
97
|
])("preserves %s when disabled", (input, expected) => {
|
|
98
|
-
expect(transform(input, { collapseSpaces: false })).toBe(expected)
|
|
98
|
+
expect(transform(input, { collapseSpaces: false, nbsp: false })).toBe(expected)
|
|
99
99
|
})
|
|
100
100
|
})
|
|
101
101
|
|
|
@@ -130,8 +130,8 @@ describe("transform", () => {
|
|
|
130
130
|
[`"Hello${DEFAULT_SEPARATOR}" - ${DEFAULT_SEPARATOR}she${DEFAULT_SEPARATOR} said`, 3],
|
|
131
131
|
[`.${DEFAULT_SEPARATOR}.${DEFAULT_SEPARATOR}.`, 2],
|
|
132
132
|
])('preserves %i separators in "%s"', (input, expectedCount) => {
|
|
133
|
-
expect(() => transform(input, { separator: DEFAULT_SEPARATOR })).not.toThrow()
|
|
134
|
-
expect(countSeparators(transform(input, { separator: DEFAULT_SEPARATOR }), DEFAULT_SEPARATOR)).toBe(expectedCount)
|
|
133
|
+
expect(() => transform(input, { separator: DEFAULT_SEPARATOR, nbsp: false })).not.toThrow()
|
|
134
|
+
expect(countSeparators(transform(input, { separator: DEFAULT_SEPARATOR, nbsp: false }), DEFAULT_SEPARATOR)).toBe(expectedCount)
|
|
135
135
|
})
|
|
136
136
|
|
|
137
137
|
it("preserves separator in ellipsis", () => {
|
|
@@ -142,7 +142,7 @@ describe("transform", () => {
|
|
|
142
142
|
|
|
143
143
|
it("preserves consecutive separators", () => {
|
|
144
144
|
const input = `a${DEFAULT_SEPARATOR}${DEFAULT_SEPARATOR}${DEFAULT_SEPARATOR}b`
|
|
145
|
-
expect(transform(input)).toBe(input)
|
|
145
|
+
expect(transform(input, { nbsp: false })).toBe(input)
|
|
146
146
|
})
|
|
147
147
|
})
|
|
148
148
|
|
|
@@ -154,7 +154,7 @@ describe("transform", () => {
|
|
|
154
154
|
'"שלום"',
|
|
155
155
|
"a\u200Bb",
|
|
156
156
|
])('preserves content in "%s"', (input) => {
|
|
157
|
-
expect(transform(input)).toBe(transform(input)) // idempotent
|
|
157
|
+
expect(transform(input, { nbsp: false })).toBe(transform(input, { nbsp: false })) // idempotent
|
|
158
158
|
})
|
|
159
159
|
})
|
|
160
160
|
|
|
@@ -181,7 +181,7 @@ describe("transform", () => {
|
|
|
181
181
|
['5\'10"', `5′10″`],
|
|
182
182
|
['He is 6\'2" tall', `He is 6′2″ tall`],
|
|
183
183
|
])('correctly transforms: "%s"', (input, expected) => {
|
|
184
|
-
expect(transform(input, { symbols: true, degrees: true })).toBe(expected)
|
|
184
|
+
expect(transform(input, { symbols: true, degrees: true, nbsp: false })).toBe(expected)
|
|
185
185
|
})
|
|
186
186
|
})
|
|
187
187
|
|
|
@@ -194,7 +194,7 @@ describe("transform", () => {
|
|
|
194
194
|
"self-aware",
|
|
195
195
|
"high-quality",
|
|
196
196
|
])('preserves compound word: "%s"', (input) => {
|
|
197
|
-
expect(transform(input)).toBe(input)
|
|
197
|
+
expect(transform(input, { nbsp: false })).toBe(input)
|
|
198
198
|
})
|
|
199
199
|
})
|
|
200
200
|
|
|
@@ -207,7 +207,7 @@ describe("transform", () => {
|
|
|
207
207
|
"Claude-3-Opus",
|
|
208
208
|
"Qwen1.5-1.8B",
|
|
209
209
|
])('preserves model name: "%s"', (input) => {
|
|
210
|
-
expect(transform(input)).toBe(input)
|
|
210
|
+
expect(transform(input, { nbsp: false })).toBe(input)
|
|
211
211
|
})
|
|
212
212
|
})
|
|
213
213
|
})
|
|
@@ -216,25 +216,25 @@ describe("transform", () => {
|
|
|
216
216
|
it("handles dialogue with dashes and quotes", () => {
|
|
217
217
|
const input = '"Wait," she said -- "I don\'t think that\'s right."'
|
|
218
218
|
const expected = `${LEFT_DOUBLE_QUOTE}Wait,${RIGHT_DOUBLE_QUOTE} she said${EM_DASH}${LEFT_DOUBLE_QUOTE}I don${RIGHT_SINGLE_QUOTE}t think that${RIGHT_SINGLE_QUOTE}s right.${RIGHT_DOUBLE_QUOTE}`
|
|
219
|
-
expect(transform(input)).toEqual(expected)
|
|
219
|
+
expect(transform(input, { nbsp: false })).toEqual(expected)
|
|
220
220
|
})
|
|
221
221
|
|
|
222
222
|
it("handles technical documentation", () => {
|
|
223
223
|
const input = 'The API returns x != y when a <= b and c >= d. Error tolerance: +-5%.'
|
|
224
224
|
const expected = `The API returns x ${NOT_EQUAL} y when a ≤ b and c ≥ d. Error tolerance: ±5%.`
|
|
225
|
-
expect(transform(input)).toBe(expected)
|
|
225
|
+
expect(transform(input, { nbsp: false })).toBe(expected)
|
|
226
226
|
})
|
|
227
227
|
|
|
228
228
|
it("handles measurement text", () => {
|
|
229
229
|
const input = 'He is 6\'2" tall.'
|
|
230
230
|
const expected = `He is 6${PRIME}2${DOUBLE_PRIME} tall.`
|
|
231
|
-
expect(transform(input, { symbols: true })).toEqual(expected)
|
|
231
|
+
expect(transform(input, { symbols: true, nbsp: false })).toEqual(expected)
|
|
232
232
|
})
|
|
233
233
|
|
|
234
234
|
it("handles copyright notices", () => {
|
|
235
235
|
const input = '(c) 2024 Company(tm). All rights reserved(r).'
|
|
236
236
|
const expected = `${COPYRIGHT} 2024 Company${TRADEMARK}. All rights reserved${REGISTERED}.`
|
|
237
|
-
expect(transform(input)).toEqual(expected)
|
|
237
|
+
expect(transform(input, { nbsp: false })).toEqual(expected)
|
|
238
238
|
})
|
|
239
239
|
})
|
|
240
240
|
|
|
@@ -244,7 +244,7 @@ describe("transform", () => {
|
|
|
244
244
|
// When there's an open quote before a number, the quote after should close
|
|
245
245
|
// not become a prime mark
|
|
246
246
|
const input = '"Number 5"'
|
|
247
|
-
const result = transform(input)
|
|
247
|
+
const result = transform(input, { nbsp: false })
|
|
248
248
|
// The 5" should be a closing quote, not a prime
|
|
249
249
|
expect(result).toBe(`${LEFT_DOUBLE_QUOTE}Number 5${RIGHT_DOUBLE_QUOTE}`)
|
|
250
250
|
})
|
|
@@ -261,7 +261,7 @@ describe("transform", () => {
|
|
|
261
261
|
`${COPYRIGHT} 2024${EM_DASH}Room is 10×12, set to 72 °F`,
|
|
262
262
|
],
|
|
263
263
|
])('handles complex transform: "%s"', (input, expected) => {
|
|
264
|
-
expect(transform(input, { degrees: true })).toBe(expected)
|
|
264
|
+
expect(transform(input, { degrees: true, nbsp: false })).toBe(expected)
|
|
265
265
|
})
|
|
266
266
|
})
|
|
267
267
|
|
|
@@ -273,7 +273,7 @@ describe("transform", () => {
|
|
|
273
273
|
["\t", "\t"],
|
|
274
274
|
[" ", " "],
|
|
275
275
|
])('handles empty/whitespace: "%s"', (input, expected) => {
|
|
276
|
-
expect(transform(input)).toBe(expected)
|
|
276
|
+
expect(transform(input, { nbsp: false })).toBe(expected)
|
|
277
277
|
})
|
|
278
278
|
})
|
|
279
279
|
|
|
@@ -281,19 +281,19 @@ describe("transform", () => {
|
|
|
281
281
|
it("handles long repeated patterns", () => {
|
|
282
282
|
const input = '"Hello" '.repeat(100)
|
|
283
283
|
const expected = `${LEFT_DOUBLE_QUOTE}Hello${RIGHT_DOUBLE_QUOTE} `.repeat(100)
|
|
284
|
-
expect(transform(input)).toEqual(expected)
|
|
284
|
+
expect(transform(input, { nbsp: false })).toEqual(expected)
|
|
285
285
|
})
|
|
286
286
|
|
|
287
287
|
it("handles long continuous text", () => {
|
|
288
288
|
const input = "word ".repeat(1000)
|
|
289
|
-
const result = transform(input)
|
|
289
|
+
const result = transform(input, { nbsp: false })
|
|
290
290
|
expect(result).toBe(input.trim() + " ")
|
|
291
291
|
})
|
|
292
292
|
|
|
293
293
|
it("converts ALL quote pairs in repeated pattern", () => {
|
|
294
294
|
const count = 50
|
|
295
295
|
const input = '"Hello" '.repeat(count)
|
|
296
|
-
const result = transform(input)
|
|
296
|
+
const result = transform(input, { nbsp: false })
|
|
297
297
|
const leftCount = (result.match(new RegExp(LEFT_DOUBLE_QUOTE, "g")) || []).length
|
|
298
298
|
const rightCount = (result.match(new RegExp(RIGHT_DOUBLE_QUOTE, "g")) || []).length
|
|
299
299
|
expect(leftCount).toBe(count)
|
|
@@ -303,7 +303,7 @@ describe("transform", () => {
|
|
|
303
303
|
it("converts ALL dashes in repeated pattern", () => {
|
|
304
304
|
const count = 50
|
|
305
305
|
const input = "pages 1-5 ".repeat(count)
|
|
306
|
-
const result = transform(input)
|
|
306
|
+
const result = transform(input, { nbsp: false })
|
|
307
307
|
const enDashCount = (result.match(/–/g) || []).length
|
|
308
308
|
expect(enDashCount).toBe(count)
|
|
309
309
|
})
|
|
@@ -311,7 +311,7 @@ describe("transform", () => {
|
|
|
311
311
|
it("converts ALL ellipses in repeated pattern", () => {
|
|
312
312
|
const count = 50
|
|
313
313
|
const input = "Wait... ".repeat(count)
|
|
314
|
-
const result = transform(input)
|
|
314
|
+
const result = transform(input, { nbsp: false })
|
|
315
315
|
const ellipsisCount = (result.match(/…/g) || []).length
|
|
316
316
|
expect(ellipsisCount).toBe(count)
|
|
317
317
|
})
|
|
@@ -323,7 +323,7 @@ describe("transform", () => {
|
|
|
323
323
|
['"test\u200Fword"', `${LEFT_DOUBLE_QUOTE}test\u200Fword${RIGHT_DOUBLE_QUOTE}`],
|
|
324
324
|
['"caf\u0065\u0301"', `${LEFT_DOUBLE_QUOTE}caf\u0065\u0301${RIGHT_DOUBLE_QUOTE}`],
|
|
325
325
|
])('handles Unicode edge case', (input, expected) => {
|
|
326
|
-
expect(transform(input)).toBe(expected)
|
|
326
|
+
expect(transform(input, { nbsp: false })).toBe(expected)
|
|
327
327
|
})
|
|
328
328
|
})
|
|
329
329
|
|
|
@@ -336,6 +336,7 @@ describe("transform", () => {
|
|
|
336
336
|
degrees: true,
|
|
337
337
|
superscript: true,
|
|
338
338
|
ligatures: true,
|
|
339
|
+
nbsp: false,
|
|
339
340
|
})).toEqual(expected)
|
|
340
341
|
})
|
|
341
342
|
|
|
@@ -345,6 +346,7 @@ describe("transform", () => {
|
|
|
345
346
|
expect(transform(input, {
|
|
346
347
|
fractions: true,
|
|
347
348
|
degrees: false,
|
|
349
|
+
nbsp: false,
|
|
348
350
|
})).toEqual(expected)
|
|
349
351
|
})
|
|
350
352
|
})
|
|
@@ -357,19 +359,19 @@ describe("transform", () => {
|
|
|
357
359
|
[`"test${sep}word"`, `${LEFT_DOUBLE_QUOTE}test${sep}word${RIGHT_DOUBLE_QUOTE}`],
|
|
358
360
|
[`${sep}${sep}"test"${sep}${sep}`, `${sep}${sep}${LEFT_DOUBLE_QUOTE}test${RIGHT_DOUBLE_QUOTE}${sep}${sep}`],
|
|
359
361
|
])('handles separator in quotes', (input, expected) => {
|
|
360
|
-
expect(transform(input, { separator: sep })).toBe(expected)
|
|
362
|
+
expect(transform(input, { separator: sep, nbsp: false })).toBe(expected)
|
|
361
363
|
})
|
|
362
364
|
|
|
363
365
|
it.each([
|
|
364
366
|
[`word${sep} - ${sep}word`, `word${sep}${EM_DASH}${sep}word`],
|
|
365
367
|
[`1${sep}-${sep}5`, `1${sep}–${sep}5`],
|
|
366
368
|
])('handles separator in dashes', (input, expected) => {
|
|
367
|
-
expect(transform(input, { separator: sep })).toBe(expected)
|
|
369
|
+
expect(transform(input, { separator: sep, nbsp: false })).toBe(expected)
|
|
368
370
|
})
|
|
369
371
|
|
|
370
372
|
it("preserves exact separator count through transform", () => {
|
|
371
373
|
const input = `${sep}text${sep}more${sep}text${sep}`
|
|
372
|
-
const result = transform(input, { separator: sep })
|
|
374
|
+
const result = transform(input, { separator: sep, nbsp: false })
|
|
373
375
|
const inputCount = (input.match(new RegExp(sep, "g")) || []).length
|
|
374
376
|
const resultCount = (result.match(new RegExp(sep, "g")) || []).length
|
|
375
377
|
expect(resultCount).toBe(inputCount)
|
|
@@ -377,7 +379,7 @@ describe("transform", () => {
|
|
|
377
379
|
|
|
378
380
|
it("handles input containing separator character", () => {
|
|
379
381
|
const input = `Text with ${sep} in it`
|
|
380
|
-
expect(() => transform(input, { separator: sep })).not.toThrow()
|
|
382
|
+
expect(() => transform(input, { separator: sep, nbsp: false })).not.toThrow()
|
|
381
383
|
})
|
|
382
384
|
})
|
|
383
385
|
|
|
@@ -399,8 +401,8 @@ describe("transform", () => {
|
|
|
399
401
|
`1–5`,
|
|
400
402
|
`Wait…`,
|
|
401
403
|
`5×5`,
|
|
402
|
-
`20
|
|
403
|
-
`${COPYRIGHT}
|
|
404
|
+
`20${NBSP}°C`,
|
|
405
|
+
`${COPYRIGHT}${NBSP}2024`,
|
|
404
406
|
])('stable for: "%s"', (input) => {
|
|
405
407
|
expect(transform(input)).toBe(input)
|
|
406
408
|
})
|
|
@@ -410,19 +412,19 @@ describe("transform", () => {
|
|
|
410
412
|
it("applies American conventions throughout", () => {
|
|
411
413
|
const input = '"Hello." - word - "World."'
|
|
412
414
|
const expected = `${LEFT_DOUBLE_QUOTE}Hello.${RIGHT_DOUBLE_QUOTE}${EM_DASH}word${EM_DASH}${LEFT_DOUBLE_QUOTE}World.${RIGHT_DOUBLE_QUOTE}`
|
|
413
|
-
expect(transform(input, { punctuationStyle: "american", dashStyle: "american" })).toEqual(expected)
|
|
415
|
+
expect(transform(input, { punctuationStyle: "american", dashStyle: "american", nbsp: false })).toEqual(expected)
|
|
414
416
|
})
|
|
415
417
|
|
|
416
418
|
it("applies British conventions throughout", () => {
|
|
417
419
|
const input = '"Hello." - word - "World."'
|
|
418
420
|
const expected = `${LEFT_DOUBLE_QUOTE}Hello${RIGHT_DOUBLE_QUOTE}. ${EN_DASH} word ${EN_DASH} ${LEFT_DOUBLE_QUOTE}World${RIGHT_DOUBLE_QUOTE}.`
|
|
419
|
-
expect(transform(input, { punctuationStyle: "british", dashStyle: "british" })).toEqual(expected)
|
|
421
|
+
expect(transform(input, { punctuationStyle: "british", dashStyle: "british", nbsp: false })).toEqual(expected)
|
|
420
422
|
})
|
|
421
423
|
|
|
422
424
|
it("applies American punctuation with British dashes", () => {
|
|
423
425
|
const input = '"Hello." - word'
|
|
424
426
|
const expected = `${LEFT_DOUBLE_QUOTE}Hello.${RIGHT_DOUBLE_QUOTE} ${EN_DASH} word`
|
|
425
|
-
expect(transform(input, { punctuationStyle: "american", dashStyle: "british" })).toEqual(expected)
|
|
427
|
+
expect(transform(input, { punctuationStyle: "american", dashStyle: "british", nbsp: false })).toEqual(expected)
|
|
426
428
|
})
|
|
427
429
|
})
|
|
428
430
|
|
|
@@ -470,7 +472,7 @@ describe("transform", () => {
|
|
|
470
472
|
['"test .dot"', `${LEFT_DOUBLE_QUOTE}test .dot${RIGHT_DOUBLE_QUOTE}`],
|
|
471
473
|
['"test |pipe"', `${LEFT_DOUBLE_QUOTE}test |pipe${RIGHT_DOUBLE_QUOTE}`],
|
|
472
474
|
])('handles regex special chars: "%s"', (input, expected) => {
|
|
473
|
-
expect(transform(input)).toBe(expected)
|
|
475
|
+
expect(transform(input, { nbsp: false })).toBe(expected)
|
|
474
476
|
})
|
|
475
477
|
})
|
|
476
478
|
|
|
@@ -485,7 +487,7 @@ describe("transform", () => {
|
|
|
485
487
|
["end...", `end…`],
|
|
486
488
|
["5x", `5×`],
|
|
487
489
|
])('handles boundary: "%s"', (input, expected) => {
|
|
488
|
-
expect(transform(input)).toBe(expected)
|
|
490
|
+
expect(transform(input, { nbsp: false })).toBe(expected)
|
|
489
491
|
})
|
|
490
492
|
})
|
|
491
493
|
|
|
@@ -497,7 +499,7 @@ describe("transform", () => {
|
|
|
497
499
|
] as const
|
|
498
500
|
|
|
499
501
|
it.each(invalidSeparators)("rejects %s separator (%s)", (sep) => {
|
|
500
|
-
expect(() => transform('"Hello"', { separator: sep })).toThrow(
|
|
502
|
+
expect(() => transform('"Hello"', { separator: sep, nbsp: false })).toThrow(
|
|
501
503
|
/Invalid separator.*must be a single character/
|
|
502
504
|
)
|
|
503
505
|
})
|
|
@@ -505,13 +507,13 @@ describe("transform", () => {
|
|
|
505
507
|
const validSeparators = ["\uE000", "|", "\u2603"] // Default, pipe, snowman
|
|
506
508
|
|
|
507
509
|
it.each(validSeparators)("accepts '%s' as separator", (sep) => {
|
|
508
|
-
expect(() => transform('"Hello"', { separator: sep })).not.toThrow()
|
|
510
|
+
expect(() => transform('"Hello"', { separator: sep, nbsp: false })).not.toThrow()
|
|
509
511
|
})
|
|
510
512
|
})
|
|
511
513
|
|
|
512
514
|
describe("regex-special separator characters", () => {
|
|
513
515
|
it.each(REGEX_SPECIAL_CHARS)("handles '%s' as separator", (sep) => {
|
|
514
|
-
expect(transform('"Hello"', { separator: sep })).toEqual(
|
|
516
|
+
expect(transform('"Hello"', { separator: sep, nbsp: false })).toEqual(
|
|
515
517
|
`${LEFT_DOUBLE_QUOTE}Hello${RIGHT_DOUBLE_QUOTE}`
|
|
516
518
|
)
|
|
517
519
|
})
|
|
@@ -523,7 +525,7 @@ describe("transform", () => {
|
|
|
523
525
|
["RTL text", '"שלום"', `${LEFT_DOUBLE_QUOTE}שלום${RIGHT_DOUBLE_QUOTE}`],
|
|
524
526
|
["zero-width space", '"Hello\u200BWorld"', `${LEFT_DOUBLE_QUOTE}Hello\u200BWorld${RIGHT_DOUBLE_QUOTE}`],
|
|
525
527
|
] as const)("preserves %s in input", (_, input, expected) => {
|
|
526
|
-
expect(transform(input)).toEqual(expected)
|
|
528
|
+
expect(transform(input, { nbsp: false })).toEqual(expected)
|
|
527
529
|
})
|
|
528
530
|
})
|
|
529
531
|
|
package/src/tests/rehype.test.ts
CHANGED
|
@@ -49,7 +49,7 @@ describe("rehypePunctilio", () => {
|
|
|
49
49
|
["math symbols", "<p>x != y</p>", `<p>x ${NOT_EQUAL} y</p>`],
|
|
50
50
|
["legal symbols", "<p>(c) 2024</p>", `<p>${COPYRIGHT} 2024</p>`],
|
|
51
51
|
])("transforms %s", async (_name, html, expected) => {
|
|
52
|
-
expect(await processHtml(html)).toEqual(expected)
|
|
52
|
+
expect(await processHtml(html, { nbsp: false })).toEqual(expected)
|
|
53
53
|
})
|
|
54
54
|
})
|
|
55
55
|
|
|
@@ -60,7 +60,7 @@ describe("rehypePunctilio", () => {
|
|
|
60
60
|
["deeply nested", '<div><p><span><strong>"Hello"</strong></span></p></div>', `<div><p><span><strong>${LDQ}Hello${RDQ}</strong></span></p></div>`],
|
|
61
61
|
["attributes", '<p class="intro" id="first">"Hello"</p>', `<p class="intro" id="first">${LDQ}Hello${RDQ}</p>`],
|
|
62
62
|
])("preserves %s", async (_name, html, expected) => {
|
|
63
|
-
expect(await processHtml(html)).toEqual(expected)
|
|
63
|
+
expect(await processHtml(html, { nbsp: false })).toEqual(expected)
|
|
64
64
|
})
|
|
65
65
|
})
|
|
66
66
|
|
|
@@ -71,7 +71,7 @@ describe("rehypePunctilio", () => {
|
|
|
71
71
|
["simple range still converts", "<p>pages <em>1</em>-5</p>", `<p>pages <em>1</em>${EN_DASH}5</p>`],
|
|
72
72
|
["genuine negative at element start", "<p><em>-5</em> degrees</p>", "<p><em>\u22125</em> degrees</p>"],
|
|
73
73
|
])("%s", async (_name, html, expected) => {
|
|
74
|
-
expect(await processHtml(html)).toEqual(expected)
|
|
74
|
+
expect(await processHtml(html, { nbsp: false })).toEqual(expected)
|
|
75
75
|
})
|
|
76
76
|
})
|
|
77
77
|
|
|
@@ -108,15 +108,15 @@ describe("rehypePunctilio", () => {
|
|
|
108
108
|
|
|
109
109
|
describe("transform options passthrough", () => {
|
|
110
110
|
it.each([
|
|
111
|
-
["punctuationStyle american", '<p>"Hello."</p>', { punctuationStyle: "american" as const }, `<p>${LDQ}Hello.${RDQ}</p>`],
|
|
112
|
-
["punctuationStyle british", '<p>"Hello."</p>', { punctuationStyle: "british" as const }, `<p>${LDQ}Hello${RDQ}.</p>`],
|
|
113
|
-
["dashStyle american", "<p>word - word</p>", { dashStyle: "american" as const }, `<p>word${EM_DASH}word</p>`],
|
|
114
|
-
["dashStyle british", "<p>word - word</p>", { dashStyle: "british" as const }, `<p>word ${EN_DASH} word</p>`],
|
|
115
|
-
["symbols enabled", "<p>5x5</p>", { symbols: true }, `<p>5${MULTIPLICATION}5</p>`],
|
|
116
|
-
["symbols disabled", "<p>5x5</p>", { symbols: false }, "<p>5x5</p>"],
|
|
117
|
-
["fractions enabled", "<p>1/2 cup</p>", { fractions: true }, `<p>${FRACTION_1_2} cup</p>`],
|
|
118
|
-
["fractions disabled", "<p>1/2 cup</p>", { fractions: false }, "<p>1/2 cup</p>"],
|
|
119
|
-
["custom separator", '<p>"Hello"</p>', { separator: "\uE001" }, `<p>${LDQ}Hello${RDQ}</p>`],
|
|
111
|
+
["punctuationStyle american", '<p>"Hello."</p>', { punctuationStyle: "american" as const, nbsp: false as const }, `<p>${LDQ}Hello.${RDQ}</p>`],
|
|
112
|
+
["punctuationStyle british", '<p>"Hello."</p>', { punctuationStyle: "british" as const, nbsp: false as const }, `<p>${LDQ}Hello${RDQ}.</p>`],
|
|
113
|
+
["dashStyle american", "<p>word - word</p>", { dashStyle: "american" as const, nbsp: false as const }, `<p>word${EM_DASH}word</p>`],
|
|
114
|
+
["dashStyle british", "<p>word - word</p>", { dashStyle: "british" as const, nbsp: false as const }, `<p>word ${EN_DASH} word</p>`],
|
|
115
|
+
["symbols enabled", "<p>5x5</p>", { symbols: true, nbsp: false as const }, `<p>5${MULTIPLICATION}5</p>`],
|
|
116
|
+
["symbols disabled", "<p>5x5</p>", { symbols: false, nbsp: false as const }, "<p>5x5</p>"],
|
|
117
|
+
["fractions enabled", "<p>1/2 cup</p>", { fractions: true, nbsp: false as const }, `<p>${FRACTION_1_2} cup</p>`],
|
|
118
|
+
["fractions disabled", "<p>1/2 cup</p>", { fractions: false, nbsp: false as const }, "<p>1/2 cup</p>"],
|
|
119
|
+
["custom separator", '<p>"Hello"</p>', { separator: "\uE001", nbsp: false as const }, `<p>${LDQ}Hello${RDQ}</p>`],
|
|
120
120
|
])("respects %s", async (_name, html, options, expected) => {
|
|
121
121
|
expect(await processHtml(html, options)).toEqual(expected)
|
|
122
122
|
})
|
|
@@ -145,7 +145,7 @@ describe("rehypePunctilio", () => {
|
|
|
145
145
|
`<ul><li>${LDQ}First${RDQ}${EM_DASH}important</li><li>Pages 1${EN_DASH}5</li></ul>`,
|
|
146
146
|
],
|
|
147
147
|
])("handles %s", async (_name, html, expected) => {
|
|
148
|
-
expect(await processHtml(html)).toEqual(expected)
|
|
148
|
+
expect(await processHtml(html, { nbsp: false })).toEqual(expected)
|
|
149
149
|
})
|
|
150
150
|
})
|
|
151
151
|
|
|
@@ -157,7 +157,7 @@ describe("rehypePunctilio", () => {
|
|
|
157
157
|
["emoji", '<p>"Hello 👋"</p>', `<p>${LDQ}Hello 👋${RDQ}</p>`],
|
|
158
158
|
["links", '<p><a href="https://example.com">"Link"</a></p>', `<p><a href="https://example.com">${LDQ}Link${RDQ}</a></p>`],
|
|
159
159
|
])("handles %s", async (_name, html, expected) => {
|
|
160
|
-
expect(await processHtml(html)).toEqual(expected)
|
|
160
|
+
expect(await processHtml(html, { nbsp: false })).toEqual(expected)
|
|
161
161
|
})
|
|
162
162
|
|
|
163
163
|
it("is idempotent", async () => {
|
|
@@ -417,8 +417,14 @@ describe("rehypePunctilio", () => {
|
|
|
417
417
|
expect(result).toContain(`5${NBSP}kg`)
|
|
418
418
|
})
|
|
419
419
|
|
|
420
|
-
it("
|
|
420
|
+
it("inserts nbsp by default", async () => {
|
|
421
421
|
const result = await processHtml('<p>Dr. Smith has 5 kg of items.</p>')
|
|
422
|
+
expect(result).toContain(`Dr.${NBSP}Smith`)
|
|
423
|
+
expect(result).toContain(`5${NBSP}kg`)
|
|
424
|
+
})
|
|
425
|
+
|
|
426
|
+
it("does not insert nbsp when option disabled", async () => {
|
|
427
|
+
const result = await processHtml('<p>Dr. Smith has 5 kg of items.</p>', { nbsp: false })
|
|
422
428
|
expect(result).not.toContain(NBSP)
|
|
423
429
|
})
|
|
424
430
|
|
|
@@ -443,13 +449,13 @@ describe("rehypePunctilio", () => {
|
|
|
443
449
|
})
|
|
444
450
|
|
|
445
451
|
it("handles skipped child within non-skipped parent", async () => {
|
|
446
|
-
expect(await processHtml('<div>"Before" <code>"Inside"</code> "After"</div>')).toEqual(
|
|
452
|
+
expect(await processHtml('<div>"Before" <code>"Inside"</code> "After"</div>', { nbsp: false })).toEqual(
|
|
447
453
|
`<div>${LDQ}Before${RDQ} <code>"Inside"</code> ${LDQ}After${RDQ}</div>`
|
|
448
454
|
)
|
|
449
455
|
})
|
|
450
456
|
|
|
451
457
|
it("handles mixed skip and non-skip siblings", async () => {
|
|
452
|
-
expect(await processHtml('<article><p>"Hello"</p><pre>"Code"</pre><p>"World"</p></article>')).toEqual(
|
|
458
|
+
expect(await processHtml('<article><p>"Hello"</p><pre>"Code"</pre><p>"World"</p></article>', { nbsp: false })).toEqual(
|
|
453
459
|
`<article><p>${LDQ}Hello${RDQ}</p><pre>"Code"</pre><p>${LDQ}World${RDQ}</p></article>`
|
|
454
460
|
)
|
|
455
461
|
})
|