Skip to content

Commit 9274f41

Browse files
committed
Fix collapsing of backslashes with other escapes
Closes GH-14.
1 parent cf7cf8f commit 9274f41

File tree

4 files changed

+30
-3
lines changed

4 files changed

+30
-3
lines changed

lib/unsafe.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ module.exports = [
8282
},
8383
// A backslash can start an escape (when followed by punctuation) or a
8484
// hard break (when followed by an eol).
85-
{character: '\\', after: '[!-/:-@[-`{-~]'},
85+
{character: '\\', after: '[!-/:-@[-`{-~]', collapse: false},
8686
{character: '\\', after: '[\\r\\n]', inConstruct: 'phrasing'},
8787
// A right bracket can exit labels.
8888
{

lib/util/safe.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,21 @@ function safe(context, input, config) {
3030
expression = compilePattern(pattern)
3131

3232
while ((match = expression.exec(value))) {
33-
before = 'before' in pattern || pattern.atBreak
34-
after = 'after' in pattern
33+
// Often, patterns which depend on a character before or after it, such
34+
// as `!` when followed by `[` (for an image), do not have to be escaped
35+
// when the other character has to be escaped as well.
36+
// But in the case of a backslash, such as `\` when followed by `*`, that
37+
// is not correct: both have to be escaped.
38+
// This is a naïve “fix” for that though, but this seems the simplest for
39+
// now.
40+
if (pattern.collapse === false) {
41+
before = false
42+
after = false
43+
} else {
44+
before = 'before' in pattern || pattern.atBreak
45+
after = 'after' in pattern
46+
}
47+
3548
position = match.index + (before ? match[1].length : 0)
3649

3750
if (positions.indexOf(position) === -1) {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"remark-preset-wooorm": "^8.0.0",
5353
"tape": "^5.0.0",
5454
"tinyify": "^3.0.0",
55+
"unist-util-remove-position": "^3.0.0",
5556
"xo": "^0.37.0"
5657
},
5758
"scripts": {

test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var test = require('tape')
2+
var remove = require('unist-util-remove-position')
23
var from = require('mdast-util-from-markdown')
34
var to = require('.')
45

@@ -2760,5 +2761,17 @@ test('roundtrip', function (t) {
27602761
t.equal(to(from(step1)), step2, 'should roundtrip backslashes (1)')
27612762
t.equal(to(from(step2)), step2, 'should roundtrip backslashes (2)')
27622763

2764+
doc = '\\\\\\*a\n'
2765+
2766+
t.equal(to(from(doc)), doc, 'should not collapse escapes (1)')
2767+
2768+
doc = '\\\\*a\\\\\\*'
2769+
2770+
t.deepEqual(
2771+
remove(from(doc)),
2772+
remove(from(to(from(doc)))),
2773+
'should not collapse escapes (2)'
2774+
)
2775+
27632776
t.end()
27642777
})

0 commit comments

Comments
 (0)