|
|
@ -16,19 +16,19 @@ function isLetter(str, pos) { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function addQuote(obj, tokenId, posId, str) { |
|
|
|
if (typeof obj[tokenId] === 'undefined') { obj[tokenId] = {}; } |
|
|
|
obj[tokenId][posId] = str; |
|
|
|
function replaceAt(str, index, ch) { |
|
|
|
return str.substr(0, index) + ch + str.substr(index + 1); |
|
|
|
} |
|
|
|
|
|
|
|
var stack = []; |
|
|
|
|
|
|
|
module.exports = function smartquotes(typographer, state) { |
|
|
|
/*eslint max-depth:0*/ |
|
|
|
var i, token, text, t, pos, max, thisLevel, lastSpace, nextSpace, item, canOpen, canClose, j, isSingle, fn, chars, |
|
|
|
var i, token, text, t, pos, max, thisLevel, lastSpace, nextSpace, item, canOpen, canClose, j, isSingle, chars, |
|
|
|
options = typographer.options, |
|
|
|
replace = {}, |
|
|
|
tokens = state.tokens, |
|
|
|
stack = []; |
|
|
|
tokens = state.tokens; |
|
|
|
|
|
|
|
stack.length = 0; |
|
|
|
|
|
|
|
for (i = 0; i < tokens.length; i++) { |
|
|
|
token = tokens[i]; |
|
|
@ -46,20 +46,22 @@ module.exports = function smartquotes(typographer, state) { |
|
|
|
pos = 0; |
|
|
|
max = text.length; |
|
|
|
|
|
|
|
/*eslint no-labels:0,block-scoped-var:0*/ |
|
|
|
OUTER: |
|
|
|
while (pos < max) { |
|
|
|
QUOTE_RE.lastIndex = pos; |
|
|
|
t = QUOTE_RE.exec(text); |
|
|
|
if (!t) { break; } |
|
|
|
|
|
|
|
lastSpace = !isLetter(text, t.index - 1); |
|
|
|
pos = t.index + t[0].length; |
|
|
|
isSingle = t[0] === "'"; |
|
|
|
pos = t.index + 1; |
|
|
|
isSingle = (t[0] === "'"); |
|
|
|
nextSpace = !isLetter(text, pos); |
|
|
|
|
|
|
|
if (!nextSpace && !lastSpace) { |
|
|
|
// middle word
|
|
|
|
// middle of word
|
|
|
|
if (isSingle) { |
|
|
|
addQuote(replace, i, t.index, APOSTROPHE); |
|
|
|
token.content = replaceAt(token.content, t.index, APOSTROPHE); |
|
|
|
} |
|
|
|
continue; |
|
|
|
} |
|
|
@ -76,12 +78,11 @@ module.exports = function smartquotes(typographer, state) { |
|
|
|
item = stack[j]; |
|
|
|
chars = isSingle ? options.singleQuotes : options.doubleQuotes; |
|
|
|
if (chars) { |
|
|
|
addQuote(replace, item.token, item.start, chars[0]); |
|
|
|
addQuote(replace, i, t.index, chars[1]); |
|
|
|
tokens[item.token].content = replaceAt(tokens[item.token].content, item.pos, chars[0]); |
|
|
|
token.content = replaceAt(token.content, t.index, chars[1]); |
|
|
|
} |
|
|
|
stack.length = j; |
|
|
|
canOpen = false; // should be "continue OUTER;", but eslint refuses labels :(
|
|
|
|
break; |
|
|
|
continue OUTER; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -89,25 +90,13 @@ module.exports = function smartquotes(typographer, state) { |
|
|
|
if (canOpen) { |
|
|
|
stack.push({ |
|
|
|
token: i, |
|
|
|
start: t.index, |
|
|
|
end: pos, |
|
|
|
pos: t.index, |
|
|
|
single: isSingle, |
|
|
|
level: thisLevel |
|
|
|
}); |
|
|
|
} else if (canClose && isSingle) { |
|
|
|
addQuote(replace, i, t.index, APOSTROPHE); |
|
|
|
token.content = replaceAt(token.content, t.index, APOSTROPHE); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn = function(str, pos) { |
|
|
|
if (typeof replace[i][pos] === 'undefined') { return str; } |
|
|
|
return replace[i][pos]; |
|
|
|
}; |
|
|
|
|
|
|
|
for (i = 0; i < tokens.length; i++) { |
|
|
|
if (typeof replace[i] === 'undefined') { continue; } |
|
|
|
QUOTE_RE.lastIndex = 0; |
|
|
|
tokens[i].content = tokens[i].content.replace(QUOTE_RE, fn); |
|
|
|
} |
|
|
|
}; |
|
|
|