UNPKG

tipograph

Version:

A little javascript library and command line tool that makes your written content more typographically correct.

180 lines (153 loc) 5.69 kB
import * as formats from './formats/index'; import * as languages from './languages/index'; import * as presets from './presets/index'; import * as post from './post/index'; import * as quotes from './quotes'; import { find } from './changes'; var defaultOptions = { format: 'plain', language: 'english', presets: Object.keys(presets), options: {}, }; function getFormat(option) { if (typeof option === 'string') { if (typeof formats[option] !== 'undefined') { return formats[option](); } else { throw new Error( 'Unsupported format: ' + option + '. Choose one from ' + Object.keys(formats).join(', ') + ' or pass a function.' ); } } else if (typeof option === 'function') { return option(); } else { throw new Error('Format option must be either string or function.'); } } function getLanguage(option) { if (typeof option === 'string') { if (typeof languages[option] !== 'undefined') { return languages[option]; } else { throw new Error( 'Unsupported language: ' + option + '. Choose one from ' + Object.keys(languages).join(', ') + ' or pass a object.' ); } } else if (typeof option === 'object') { if (typeof option.quotes === 'undefined') { option.quotes = languages['english'].quotes; } if (typeof option.dash === 'undefined') { option.dash = languages['english'].dash; } if (typeof option.rules === 'undefined') { option.rules = languages['english'].rules; } // TODO: check correct option interface return option; } else { throw new Error('Language option must be either string or object.'); } } function getPresets(option, language, options) { if (Array.isArray(option)) { return option.map(function (preset) { if (typeof preset === 'string' && typeof presets[preset] === 'undefined') { throw new Error( 'Unsupported preset: ' + preset + '. Choose one from ' + Object.keys(presets).join(', ') + '.' ); } else if (typeof preset === 'function') { return preset(language, options); } else { return presets[preset](language, options); } }); } else { throw new Error('Presets option must be either array containing a preset name or preset definition.'); } } function getPost(option) { if (typeof post[option] !== 'undefined') { return post[option]; } else if (typeof option === 'undefined') { return null; } else if (typeof option === 'string') { throw new Error( 'Unsupported postprocessing format: ' + option + '. Choose one from ' + Object.keys(post).join(', ') + ' or pass a object.' ); } else { throw new Error('Post option must be string corresponding to an available postprocessing format.'); } } export default function tipograph(options) { options = Object.assign({}, defaultOptions, options); var format = getFormat(options.format); var language = getLanguage(options.language); var pipeline = getPresets(options.presets, language, options.options); var postMap = getPost(options.post); return function (input, callback) { if (typeof input !== 'string') { throw new Error('Only strings are supported as input.'); } // preprocess input var processed = format(input); var tokens = []; var content = ''; // concatenate tokens but replace each formatting token with a placeholder for (var i = 0; i < processed.length; i++) { if (processed[i].transform) { content += processed[i].content; } else { content += '\u200B<tipograph[' + tokens.length + ']>\u200B'; tokens.push(processed[i].content); } } // apply transformations for (var p = 0; p < pipeline.length; p++) { for (var r = 0; r < pipeline[p].length; r++) { var rule = pipeline[p][r]; content = content.replace(rule[0], rule[1]); } } // replace placeholders with their original content content = content.replace(/\u200B<tipograph\[(\d+)\]>\u200B/g, function (match, index) { return tokens[index]; }); if (postMap !== null) { var postprocessed = ''; for (var j = 0; j < content.length; j++) { if (typeof postMap[content[j]] === 'string') { postprocessed += postMap[content[j]]; } else { postprocessed += content[j]; } } content = postprocessed; } if (typeof callback === 'function') { var changes = find(input, content); return callback(content, changes); } else { return content; } }; } tipograph.extend = function (extensions) { var names = Object.keys(presets); if (Array.isArray(extensions)) { return names.concat(extensions); } else if (typeof extensions !== 'undefined') { throw new Error('Presets can be extended only with an array of custom presets'); } else { return names; } }; // deprecated tipograph.presets = tipograph.extend; // export some internals tipograph.quotes = quotes; tipograph.languages = languages;