Skip to content

Commit 5dc1e0e

Browse files
committed
Fix error on loose quotes
Closes GH-13.
1 parent b83f07b commit 5dc1e0e

File tree

2 files changed

+71
-5
lines changed

2 files changed

+71
-5
lines changed

lib/index.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export default function retextQuotes(options) {
8787
/** @type {Array<Marker>} */
8888
const stack = []
8989

90+
// eslint-disable-next-line complexity
9091
visit(paragraph, 'PunctuationNode', function (node, index, parent) {
9192
const actual = toString(node)
9293
const style = check(actual, straight, smart)
@@ -112,7 +113,14 @@ export default function retextQuotes(options) {
112113
expected = preferred === 'smart' ? '’' : "'"
113114
} else {
114115
const markers = preferred === 'smart' ? smart : straight
115-
expected = markers[(stack.length - 1) % markers.length]
116+
117+
// Loose closing quote, looks like an apostrophe.
118+
if (stack.length === 0 && (actual === '’' || actual === "'")) return
119+
120+
expected =
121+
markers[
122+
(stack.length === 0 ? 0 : stack.length - 1) % markers.length
123+
]
116124

117125
if (expected.length > 1) {
118126
expected = expected.charAt(style.type === 'open' ? 0 : 1)

test.js

+62-4
Original file line numberDiff line numberDiff line change
@@ -196,17 +196,75 @@ test('retextQuotes', async function (t) {
196196
}
197197
)
198198

199-
await t.test('should detect nesting correctly w/ 3 pairs', async function () {
199+
await t.test('should detect nesting correctly w/ 1 pair', async function () {
200200
const file = await retext()
201-
.use(retextQuotes, {smart: ['“”', '‘’', '«»']})
202-
.process('A sentence “with ‘multiple «nested “quotes”»’”.')
201+
.use(retextQuotes, {smart: ['“”']})
202+
.process(
203+
`A sentence with “quotes”.
204+
205+
A sentence with “nested “quotes””.
206+
207+
A sentence with “multiple “nested “quotes”””.
208+
209+
Mismatched closing” quotes.
210+
211+
Mismatched closing’ quotes.
212+
213+
Mismatched “opening quotes.
214+
215+
Mismatched ‘opening quotes.
216+
`
217+
)
203218

204219
assert.deepEqual(file.messages.map(String), [])
205220
})
206221

222+
await t.test('should detect nesting correctly w/ 2 pairs', async function () {
223+
const file = await retext().use(retextQuotes, {smart: ['“”', '‘’']})
224+
.process(`A sentence with “quotes”.
225+
226+
A sentence with “nested ‘quotes’”.
227+
228+
A sentence with “multiple ‘nested “quotes”’”.
229+
230+
Mismatched closing” quotes.
231+
232+
Mismatched closing’ quotes.
233+
234+
Mismatched “opening quotes.
235+
236+
Mismatched ‘opening quotes.
237+
`)
238+
239+
assert.deepEqual(file.messages.map(String), [
240+
'13:12-13:13: Unexpected `‘` at this level of nesting, expected `“`'
241+
])
242+
})
243+
244+
await t.test('should detect nesting correctly w/ 3 pairs', async function () {
245+
const file = await retext().use(retextQuotes, {smart: ['“”', '‘’', '«»']})
246+
.process(`A sentence with “quotes”.
247+
248+
A sentence with “nested ‘quotes’”.
249+
250+
A sentence with “multiple ‘nested «quotes»’”.
251+
252+
Mismatched closing” quotes.
253+
254+
Mismatched closing’ quotes.
255+
256+
Mismatched “opening quotes.
257+
258+
Mismatched ‘opening quotes.
259+
`)
260+
261+
assert.deepEqual(file.messages.map(String), [
262+
'13:12-13:13: Unexpected `‘` at this level of nesting, expected `“`'
263+
])
264+
})
265+
207266
await t.test('should deal with funky nesting', async function () {
208267
const file = await retext().use(retextQuotes).process(soManyOpenings)
209-
210268
assert.deepEqual(file.messages.map(String), [])
211269
})
212270

0 commit comments

Comments
 (0)