Browse Source

Perf: tweaked typorgapher checks

pull/14/head
Vitaly Puzrin 10 years ago
parent
commit
94871401b8
  1. 46
      lib/rules_text/replace.js
  2. 116
      lib/rules_text/smartquotes.js

46
lib/rules_text/replace.js

@ -3,6 +3,9 @@
'use strict'; 'use strict';
var COPY_RE = /\((c|tm|r|p)\)/i;
var RARE_RE = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/;
module.exports = function replace(t, state) { module.exports = function replace(t, state) {
var i, token, text, var i, token, text,
tokens = state.tokens, tokens = state.tokens,
@ -13,7 +16,7 @@ module.exports = function replace(t, state) {
if (token.type === 'text') { if (token.type === 'text') {
text = token.content; text = token.content;
if (text.indexOf('(') >= 0) { if (COPY_RE.test(text)) {
if (options.copyright) { if (options.copyright) {
text = text.replace(/\(c\)/gi, '©'); text = text.replace(/\(c\)/gi, '©');
} }
@ -28,27 +31,26 @@ module.exports = function replace(t, state) {
} }
} }
if (options.plusminus && text.indexOf('+-') >= 0) { if (RARE_RE.test(text)) {
text = text.replace(/\+-/g, '±'); if (options.plusminus) {
} text = text.replace(/\+-/g, '±');
if (options.ellipsis && text.indexOf('..') >= 0) { }
// .., ..., ....... -> … if (options.ellipsis) {
// but ?..... & !..... -> ?.. & !.. // .., ..., ....... -> …
text = text.replace(/\.{2,}/g, '…').replace(/([?!])…/g, '$1..'); // but ?..... & !..... -> ?.. & !..
} text = text.replace(/\.{2,}/g, '…').replace(/([?!])…/g, '$1..');
if (options.dupes && }
(text.indexOf('????') >= 0 || if (options.dupes) {
text.indexOf('!!!!') >= 0 || text = text.replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ',');
text.indexOf(',,') >= 0)) { }
text = text.replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ','); if (options.dashes) {
} text = text
if (options.dashes && text.indexOf('--') >= 0) { // em-dash
text = text .replace(/(^|[^-])---([^-]|$)/mg, '$1\u2014$2')
// em-dash // en-dash
.replace(/(^|[^-])---([^-]|$)/mg, '$1\u2014$2') .replace(/(^|\s)--(\s|$)/mg, '$1\u2013$2')
// en-dash .replace(/(^|[^-\s])--([^-\s]|$)/mg, '$1\u2013$2');
.replace(/(^|\s)--(\s|$)/mg, '$1\u2013$2') }
.replace(/(^|[^-\s])--([^-\s]|$)/mg, '$1\u2013$2');
} }
token.content = text; token.content = text;

116
lib/rules_text/smartquotes.js

@ -3,20 +3,21 @@
'use strict'; 'use strict';
var quoteReg = /['"]/g; var QUOTE_TEST_RE = /['"]/;
var punctReg = /[-\s()\[\]]/; var QUOTE_RE = /['"]/g;
var apostrophe = '’'; var PUNCT_RE = /[-\s()\[\]]/;
var APOSTROPHE = '’';
// This function returns true if the character at `pos` // This function returns true if the character at `pos`
// could be inside a word. // could be inside a word.
function isLetter(str, pos) { function isLetter(str, pos) {
if (pos < 0 || pos >= str.length) { return false; } if (pos < 0 || pos >= str.length) { return false; }
return !punctReg.test(str[pos]); return !PUNCT_RE.test(str[pos]);
} }
function addQuote(obj, tokenId, posId, str) { function addQuote(obj, tokenId, posId, str) {
if (!obj[tokenId]) { obj[tokenId] = {}; } if (typeof obj[tokenId] === 'undefined') { obj[tokenId] = {}; }
obj[tokenId][posId] = str; obj[tokenId][posId] = str;
} }
@ -31,6 +32,9 @@ module.exports = function smartquotes(typographer, state) {
for (i = 0; i < tokens.length; i++) { for (i = 0; i < tokens.length; i++) {
token = tokens[i]; token = tokens[i];
if (token.type !== 'text' || QUOTE_TEST_RE.test(token.text)) { continue; }
thisLevel = tokens[i].level; thisLevel = tokens[i].level;
for (j = stack.length - 1; j >= 0; j--) { for (j = stack.length - 1; j >= 0; j--) {
@ -38,74 +42,72 @@ module.exports = function smartquotes(typographer, state) {
} }
stack.length = j + 1; stack.length = j + 1;
if (token.type === 'text') { text = token.content;
text = token.content; pos = 0;
pos = 0; max = text.length;
max = text.length;
while (pos < max) {
while (pos < max) { QUOTE_RE.lastIndex = pos;
quoteReg.lastIndex = pos; t = QUOTE_RE.exec(text);
t = quoteReg.exec(text); if (!t) { break; }
if (!t) { break; }
lastSpace = !isLetter(text, t.index - 1);
lastSpace = !isLetter(text, t.index - 1); pos = t.index + t[0].length;
pos = t.index + t[0].length; isSingle = t[0] === "'";
isSingle = t[0] === "'"; nextSpace = !isLetter(text, pos);
nextSpace = !isLetter(text, pos);
if (!nextSpace && !lastSpace) {
if (!nextSpace && !lastSpace) { // middle word
// middle word if (isSingle) {
if (isSingle) { addQuote(replace, i, t.index, APOSTROPHE);
addQuote(replace, i, t.index, apostrophe);
}
continue;
} }
continue;
}
canOpen = !nextSpace; canOpen = !nextSpace;
canClose = !lastSpace; canClose = !lastSpace;
if (canClose) { if (canClose) {
// this could be a closing quote, rewind the stack to get a match // this could be a closing quote, rewind the stack to get a match
for (j = stack.length - 1; j >= 0; j--) { for (j = stack.length - 1; j >= 0; j--) {
item = stack[j];
if (stack[j].level < thisLevel) { break; }
if (item.single === isSingle && stack[j].level === thisLevel) {
item = stack[j]; item = stack[j];
if (stack[j].level < thisLevel) { break; } chars = isSingle ? options.singleQuotes : options.doubleQuotes;
if (item.single === isSingle && stack[j].level === thisLevel) { if (chars) {
item = stack[j]; addQuote(replace, item.token, item.start, chars[0]);
chars = isSingle ? options.singleQuotes : options.doubleQuotes; addQuote(replace, i, t.index, chars[1]);
if (chars) {
addQuote(replace, item.token, item.start, chars[0]);
addQuote(replace, i, t.index, chars[1]);
}
stack.length = j;
canOpen = false; // should be "continue OUTER;", but eslint refuses labels :(
break;
} }
stack.length = j;
canOpen = false; // should be "continue OUTER;", but eslint refuses labels :(
break;
} }
} }
}
if (canOpen) { if (canOpen) {
stack.push({ stack.push({
token: i, token: i,
start: t.index, start: t.index,
end: pos, end: pos,
single: isSingle, single: isSingle,
level: thisLevel level: thisLevel
}); });
} else if (canClose && isSingle) { } else if (canClose && isSingle) {
addQuote(replace, i, t.index, apostrophe); addQuote(replace, i, t.index, APOSTROPHE);
}
} }
} }
} }
fn = function(str, pos) { fn = function(str, pos) {
if (!replace[i][pos]) { return str; } if (typeof replace[i][pos] === 'undefined') { return str; }
return replace[i][pos]; return replace[i][pos];
}; };
for (i = 0; i < tokens.length; i++) { for (i = 0; i < tokens.length; i++) {
if (!replace[i]) { continue; } if (typeof replace[i] === 'undefined') { continue; }
quoteReg.lastIndex = 0; QUOTE_RE.lastIndex = 0;
tokens[i].content = tokens[i].content.replace(quoteReg, fn); tokens[i].content = tokens[i].content.replace(QUOTE_RE, fn);
} }
}; };

Loading…
Cancel
Save