diff --git a/lib/rules_core/smartquotes.js b/lib/rules_core/smartquotes.js index 3d5cfcc..948f595 100644 --- a/lib/rules_core/smartquotes.js +++ b/lib/rules_core/smartquotes.js @@ -50,17 +50,15 @@ function process_inlines(tokens, state) { pos = t.index + 1; isSingle = (t[0] === "'"); - lastChar = t.index - 1 >= 0 ? text.charCodeAt(t.index - 1) : -1; - nextChar = pos < max ? text.charCodeAt(pos) : -1; + // treat begin/end of the line as a whitespace + lastChar = t.index - 1 >= 0 ? text.charCodeAt(t.index - 1) : 0x20; + nextChar = pos < max ? text.charCodeAt(pos) : 0x20; - isLastPunctChar = lastChar >= 0 && - (isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar))); - isNextPunctChar = nextChar >= 0 && - (isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar))); + isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar)); + isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar)); - // begin/end of the line counts as a whitespace too - isLastWhiteSpace = lastChar < 0 || isWhiteSpace(lastChar); - isNextWhiteSpace = nextChar < 0 || isWhiteSpace(nextChar); + isLastWhiteSpace = isWhiteSpace(lastChar); + isNextWhiteSpace = isWhiteSpace(nextChar); if (isNextWhiteSpace) { canOpen = false; @@ -87,7 +85,8 @@ function process_inlines(tokens, state) { if (canOpen && canClose) { // treat this as the middle of the word - canOpen = canClose = false; + canOpen = false; + canClose = isNextPunctChar; } if (!canOpen && !canClose) { diff --git a/lib/rules_inline/emphasis.js b/lib/rules_inline/emphasis.js index b90971d..9fae5d4 100644 --- a/lib/rules_inline/emphasis.js +++ b/lib/rules_inline/emphasis.js @@ -19,7 +19,8 @@ function scanDelims(state, start) { max = state.posMax, marker = state.src.charCodeAt(start); - lastChar = start > 0 ? state.src.charCodeAt(start - 1) : -1; + // treat beginning of the line as a whitespace + lastChar = start > 0 ? state.src.charCodeAt(start - 1) : 0x20; while (pos < max && state.src.charCodeAt(pos) === marker) { pos++; } @@ -29,16 +30,14 @@ function scanDelims(state, start) { count = pos - start; - nextChar = pos < max ? state.src.charCodeAt(pos) : -1; + // treat end of the line as a whitespace + nextChar = pos < max ? state.src.charCodeAt(pos) : 0x20; - isLastPunctChar = lastChar >= 0 && - (isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar))); - isNextPunctChar = nextChar >= 0 && - (isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar))); + isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar)); + isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar)); - // begin/end of the line counts as a whitespace too - isLastWhiteSpace = lastChar < 0 || isWhiteSpace(lastChar); - isNextWhiteSpace = nextChar < 0 || isWhiteSpace(nextChar); + isLastWhiteSpace = isWhiteSpace(lastChar); + isNextWhiteSpace = isWhiteSpace(nextChar); if (isNextWhiteSpace) { can_open = false; @@ -59,7 +58,8 @@ function scanDelims(state, start) { if (marker === 0x5F /* _ */) { if (can_open && can_close) { // "_" inside a word can neither open nor close an emphasis - can_open = can_close = false; + can_open = false; + can_close = isNextPunctChar; } } diff --git a/lib/rules_inline/strikethrough.js b/lib/rules_inline/strikethrough.js index f54adfe..5787687 100644 --- a/lib/rules_inline/strikethrough.js +++ b/lib/rules_inline/strikethrough.js @@ -19,7 +19,8 @@ function scanDelims(state, start) { max = state.posMax, marker = state.src.charCodeAt(start); - lastChar = start > 0 ? state.src.charCodeAt(start - 1) : -1; + // treat beginning of the line as a whitespace + lastChar = start > 0 ? state.src.charCodeAt(start - 1) : 0x20; while (pos < max && state.src.charCodeAt(pos) === marker) { pos++; } @@ -29,16 +30,14 @@ function scanDelims(state, start) { count = pos - start; - nextChar = pos < max ? state.src.charCodeAt(pos) : -1; + // treat end of the line as a whitespace + nextChar = pos < max ? state.src.charCodeAt(pos) : 0x20; - isLastPunctChar = lastChar >= 0 && - (isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar))); - isNextPunctChar = nextChar >= 0 && - (isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar))); + isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar)); + isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar)); - // begin/end of the line counts as a whitespace too - isLastWhiteSpace = lastChar < 0 || isWhiteSpace(lastChar); - isNextWhiteSpace = nextChar < 0 || isWhiteSpace(nextChar); + isLastWhiteSpace = isWhiteSpace(lastChar); + isNextWhiteSpace = isWhiteSpace(nextChar); if (isNextWhiteSpace) { can_open = false; diff --git a/test/fixtures/markdown-it/commonmark_extras.txt b/test/fixtures/markdown-it/commonmark_extras.txt index f00e96f..def578e 100644 --- a/test/fixtures/markdown-it/commonmark_extras.txt +++ b/test/fixtures/markdown-it/commonmark_extras.txt @@ -61,6 +61,14 @@ just a funny little fence . +Underscore between punctuation chars should be able to close emphasis. + +. +_(hai)_. +. +
(hai).
+. + Coverage. Directive can terminate paragraph. . diff --git a/test/fixtures/markdown-it/smartquotes.txt b/test/fixtures/markdown-it/smartquotes.txt index 42be5d3..4257879 100644 --- a/test/fixtures/markdown-it/smartquotes.txt +++ b/test/fixtures/markdown-it/smartquotes.txt @@ -82,3 +82,11 @@ users' stuff .users’ stuff
. + +Quotes between punctuation chars: + +. +"(hai)". +. +“(hai)”.
+.