Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
close #624
107 lines (84 sloc)
2.63 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Simple typographic replacements | |
| // | |
| // (c) (C) → © | |
| // (tm) (TM) → ™ | |
| // (r) (R) → ® | |
| // +- → ± | |
| // (p) (P) -> § | |
| // ... → … (also ?.... → ?.., !.... → !..) | |
| // ???????? → ???, !!!!! → !!!, `,,` → `,` | |
| // -- → –, --- → — | |
| // | |
| 'use strict'; | |
| // TODO: | |
| // - fractionals 1/2, 1/4, 3/4 -> ½, ¼, ¾ | |
| // - miltiplication 2 x 4 -> 2 × 4 | |
| var RARE_RE = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/; | |
| // Workaround for phantomjs - need regex without /g flag, | |
| // or root check will fail every second time | |
| var SCOPED_ABBR_TEST_RE = /\((c|tm|r|p)\)/i; | |
| var SCOPED_ABBR_RE = /\((c|tm|r|p)\)/ig; | |
| var SCOPED_ABBR = { | |
| c: '©', | |
| r: '®', | |
| p: '§', | |
| tm: '™' | |
| }; | |
| function replaceFn(match, name) { | |
| return SCOPED_ABBR[name.toLowerCase()]; | |
| } | |
| function replace_scoped(inlineTokens) { | |
| var i, token, inside_autolink = 0; | |
| for (i = inlineTokens.length - 1; i >= 0; i--) { | |
| token = inlineTokens[i]; | |
| if (token.type === 'text' && !inside_autolink) { | |
| token.content = token.content.replace(SCOPED_ABBR_RE, replaceFn); | |
| } | |
| if (token.type === 'link_open' && token.info === 'auto') { | |
| inside_autolink--; | |
| } | |
| if (token.type === 'link_close' && token.info === 'auto') { | |
| inside_autolink++; | |
| } | |
| } | |
| } | |
| function replace_rare(inlineTokens) { | |
| var i, token, inside_autolink = 0; | |
| for (i = inlineTokens.length - 1; i >= 0; i--) { | |
| token = inlineTokens[i]; | |
| if (token.type === 'text' && !inside_autolink) { | |
| if (RARE_RE.test(token.content)) { | |
| token.content = token.content | |
| .replace(/\+-/g, '±') | |
| // .., ..., ....... -> … | |
| // but ?..... & !..... -> ?.. & !.. | |
| .replace(/\.{2,}/g, '…').replace(/([?!])…/g, '$1..') | |
| .replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ',') | |
| // em-dash | |
| .replace(/(^|[^-])---(?=[^-]|$)/mg, '$1\u2014') | |
| // en-dash | |
| .replace(/(^|\s)--(?=\s|$)/mg, '$1\u2013') | |
| .replace(/(^|[^-\s])--(?=[^-\s]|$)/mg, '$1\u2013'); | |
| } | |
| } | |
| if (token.type === 'link_open' && token.info === 'auto') { | |
| inside_autolink--; | |
| } | |
| if (token.type === 'link_close' && token.info === 'auto') { | |
| inside_autolink++; | |
| } | |
| } | |
| } | |
| module.exports = function replace(state) { | |
| var blkIdx; | |
| if (!state.md.options.typographer) { return; } | |
| for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) { | |
| if (state.tokens[blkIdx].type !== 'inline') { continue; } | |
| if (SCOPED_ABBR_TEST_RE.test(state.tokens[blkIdx].content)) { | |
| replace_scoped(state.tokens[blkIdx].children); | |
| } | |
| if (RARE_RE.test(state.tokens[blkIdx].content)) { | |
| replace_rare(state.tokens[blkIdx].children); | |
| } | |
| } | |
| }; |