Browse Source

Moved scans from typorgapher directly to rules

pull/14/head
Vitaly Puzrin 10 years ago
parent
commit
8294a63f8c
  1. 9
      lib/rules_core/typographer.js
  2. 89
      lib/rules_text/replace.js
  3. 128
      lib/rules_text/smartquotes.js
  4. 4
      lib/typographer.js

9
lib/rules_core/typographer.js

@ -2,13 +2,6 @@
module.exports = function typographer(state) { module.exports = function typographer(state) {
if (!state.options.typographer) { return; } if (!state.options.typographer) { return; }
var tokens = state.tokens, tok, i, l;
// Parse inlines state.typographer.process(state);
for (i = 0, l = tokens.length; i < l; i++) {
tok = tokens[i];
if (tok.type === 'inline') {
state.typographer.process(tok, state);
}
}
}; };

89
lib/rules_text/replace.js

@ -6,54 +6,61 @@
var COPY_RE = /\((c|tm|r|p)\)/i; var COPY_RE = /\((c|tm|r|p)\)/i;
var RARE_RE = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/; var RARE_RE = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/;
module.exports = function replace(typographer, blockToken) { module.exports = function replace(state) {
var i, token, text, var i, token, text, inlineTokens, blkIdx,
tokens = blockToken.children, typographer = state.typographer,
options = typographer.options; options = typographer.options;
for (i = tokens.length - 1; i >= 0; i--) { for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {
token = tokens[i];
if (token.type === 'text') {
text = token.content;
if (COPY_RE.test(text)) { if (state.tokens[blkIdx].type !== 'inline') { continue; }
if (options.copyright) {
text = text.replace(/\(c\)/gi, '©');
}
if (options.trademark) {
text = text.replace(/\(tm\)/gi, '™');
}
if (options.registered) {
text = text.replace(/\(r\)/gi, '®');
}
if (options.paragraph) {
text = text.replace(/\(p\)/gi, '§');
}
}
if (RARE_RE.test(text)) { inlineTokens = state.tokens[blkIdx].children;
if (options.plusminus) {
text = text.replace(/\+-/g, '±'); for (i = inlineTokens.length - 1; i >= 0; i--) {
} token = inlineTokens[i];
if (options.ellipsis) { if (token.type === 'text') {
// .., ..., ....... -> … text = token.content;
// but ?..... & !..... -> ?.. & !..
text = text.replace(/\.{2,}/g, '…').replace(/([?!])…/g, '$1..'); if (COPY_RE.test(text)) {
} if (options.copyright) {
if (options.dupes) { text = text.replace(/\(c\)/gi, '©');
text = text.replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ','); }
if (options.trademark) {
text = text.replace(/\(tm\)/gi, '™');
}
if (options.registered) {
text = text.replace(/\(r\)/gi, '®');
}
if (options.paragraph) {
text = text.replace(/\(p\)/gi, '§');
}
} }
if (options.dashes) {
text = text if (RARE_RE.test(text)) {
// em-dash if (options.plusminus) {
.replace(/(^|[^-])---([^-]|$)/mg, '$1\u2014$2') text = text.replace(/\+-/g, '±');
// en-dash }
.replace(/(^|\s)--(\s|$)/mg, '$1\u2013$2') if (options.ellipsis) {
.replace(/(^|[^-\s])--([^-\s]|$)/mg, '$1\u2013$2'); // .., ..., ....... -> …
// but ?..... & !..... -> ?.. & !..
text = text.replace(/\.{2,}/g, '…').replace(/([?!])…/g, '$1..');
}
if (options.dupes) {
text = text.replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ',');
}
if (options.dashes) {
text = text
// em-dash
.replace(/(^|[^-])---([^-]|$)/mg, '$1\u2014$2')
// en-dash
.replace(/(^|\s)--(\s|$)/mg, '$1\u2013$2')
.replace(/(^|[^-\s])--([^-\s]|$)/mg, '$1\u2013$2');
}
} }
}
token.content = text; token.content = text;
}
} }
} }
}; };

128
lib/rules_text/smartquotes.js

@ -20,82 +20,90 @@ function replaceAt(str, index, ch) {
return str.substr(0, index) + ch + str.substr(index + 1); return str.substr(0, index) + ch + str.substr(index + 1);
} }
var stack = [];
module.exports = function smartquotes(typographer, blockToken) { module.exports = function smartquotes(state) {
/*eslint max-depth:0*/ /*eslint max-depth:0*/
var i, token, text, t, pos, max, thisLevel, lastSpace, nextSpace, item, canOpen, canClose, j, isSingle, chars, var i, token, text, t, pos, max, thisLevel, lastSpace, nextSpace, item,
canOpen, canClose, j, isSingle, chars, blkIdx, tokens,
typographer = state.typographer,
options = typographer.options, options = typographer.options,
tokens = blockToken.children; stack = [];
stack.length = 0;
for (i = 0; i < tokens.length; i++) { for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {
token = tokens[i];
if (token.type !== 'text' || QUOTE_TEST_RE.test(token.text)) { continue; } if (state.tokens[blkIdx].type !== 'inline') { continue; }
thisLevel = tokens[i].level; tokens = state.tokens[blkIdx].children;
stack.length = 0;
for (j = stack.length - 1; j >= 0; j--) { for (i = 0; i < tokens.length; i++) {
if (stack[j].level <= thisLevel) { break; } token = tokens[i];
}
stack.length = j + 1; if (token.type !== 'text' || QUOTE_TEST_RE.test(token.text)) { continue; }
text = token.content; thisLevel = tokens[i].level;
pos = 0;
max = text.length; for (j = stack.length - 1; j >= 0; j--) {
if (stack[j].level <= thisLevel) { break; }
/*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 + 1;
isSingle = (t[0] === "'");
nextSpace = !isLetter(text, pos);
if (!nextSpace && !lastSpace) {
// middle of word
if (isSingle) {
token.content = replaceAt(token.content, t.index, APOSTROPHE);
}
continue;
} }
stack.length = j + 1;
text = token.content;
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 + 1;
isSingle = (t[0] === "'");
nextSpace = !isLetter(text, pos);
if (!nextSpace && !lastSpace) {
// middle of word
if (isSingle) {
token.content = replaceAt(token.content, t.index, APOSTROPHE);
}
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];
chars = isSingle ? options.singleQuotes : options.doubleQuotes; if (stack[j].level < thisLevel) { break; }
if (chars) { if (item.single === isSingle && stack[j].level === thisLevel) {
tokens[item.token].content = replaceAt(tokens[item.token].content, item.pos, chars[0]); item = stack[j];
token.content = replaceAt(token.content, t.index, chars[1]); chars = isSingle ? options.singleQuotes : options.doubleQuotes;
if (chars) {
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;
continue OUTER;
} }
stack.length = j;
continue OUTER;
} }
} }
}
if (canOpen) { if (canOpen) {
stack.push({ stack.push({
token: i, token: i,
pos: t.index, pos: t.index,
single: isSingle, single: isSingle,
level: thisLevel level: thisLevel
}); });
} else if (canClose && isSingle) { } else if (canClose && isSingle) {
token.content = replaceAt(token.content, t.index, APOSTROPHE); token.content = replaceAt(token.content, t.index, APOSTROPHE);
}
} }
} }
} }

4
lib/typographer.js

@ -33,13 +33,13 @@ Typographer.prototype.set = function (options) {
}; };
Typographer.prototype.process = function (token) { Typographer.prototype.process = function (state) {
var i, l, rules; var i, l, rules;
rules = this.ruler.getRules(''); rules = this.ruler.getRules('');
for (i = 0, l = rules.length; i < l; i++) { for (i = 0, l = rules.length; i < l; i++) {
rules[i](this, token); rules[i](state);
} }
}; };

Loading…
Cancel
Save