Skip to content

Commit

Permalink
Fix error on loose quotes
Browse files Browse the repository at this point in the history
Closes GH-13.
  • Loading branch information
wooorm committed Jan 16, 2025
1 parent b83f07b commit 5dc1e0e
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 5 deletions.
10 changes: 9 additions & 1 deletion lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export default function retextQuotes(options) {
/** @type {Array<Marker>} */
const stack = []

// eslint-disable-next-line complexity
visit(paragraph, 'PunctuationNode', function (node, index, parent) {
const actual = toString(node)
const style = check(actual, straight, smart)
Expand All @@ -112,7 +113,14 @@ export default function retextQuotes(options) {
expected = preferred === 'smart' ? '’' : "'"
} else {
const markers = preferred === 'smart' ? smart : straight
expected = markers[(stack.length - 1) % markers.length]

// Loose closing quote, looks like an apostrophe.
if (stack.length === 0 && (actual === '’' || actual === "'")) return

expected =
markers[
(stack.length === 0 ? 0 : stack.length - 1) % markers.length
]

if (expected.length > 1) {
expected = expected.charAt(style.type === 'open' ? 0 : 1)
Expand Down
66 changes: 62 additions & 4 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,75 @@ test('retextQuotes', async function (t) {
}
)

await t.test('should detect nesting correctly w/ 3 pairs', async function () {
await t.test('should detect nesting correctly w/ 1 pair', async function () {
const file = await retext()
.use(retextQuotes, {smart: ['“”', '‘’', '«»']})
.process('A sentence “with ‘multiple «nested “quotes”»’”.')
.use(retextQuotes, {smart: ['“”']})
.process(
`A sentence with “quotes”.
A sentence with “nested “quotes””.
A sentence with “multiple “nested “quotes”””.
Mismatched closing” quotes.
Mismatched closing’ quotes.
Mismatched “opening quotes.
Mismatched ‘opening quotes.
`
)

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

await t.test('should detect nesting correctly w/ 2 pairs', async function () {
const file = await retext().use(retextQuotes, {smart: ['“”', '‘’']})
.process(`A sentence with “quotes”.
A sentence with “nested ‘quotes’”.
A sentence with “multiple ‘nested “quotes”’”.
Mismatched closing” quotes.
Mismatched closing’ quotes.
Mismatched “opening quotes.
Mismatched ‘opening quotes.
`)

assert.deepEqual(file.messages.map(String), [
'13:12-13:13: Unexpected `‘` at this level of nesting, expected `“`'
])
})

await t.test('should detect nesting correctly w/ 3 pairs', async function () {
const file = await retext().use(retextQuotes, {smart: ['“”', '‘’', '«»']})
.process(`A sentence with “quotes”.
A sentence with “nested ‘quotes’”.
A sentence with “multiple ‘nested «quotes»’”.
Mismatched closing” quotes.
Mismatched closing’ quotes.
Mismatched “opening quotes.
Mismatched ‘opening quotes.
`)

assert.deepEqual(file.messages.map(String), [
'13:12-13:13: Unexpected `‘` at this level of nesting, expected `“`'
])
})

await t.test('should deal with funky nesting', async function () {
const file = await retext().use(retextQuotes).process(soManyOpenings)

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

Expand Down

0 comments on commit 5dc1e0e

Please sign in to comment.