123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- 'use strict';
- let _ = require('lodash');
- let bluebird = require('bluebird');
- let glob = bluebird.promisify(require('glob'));
- let path = require('path');
- let Queue = require('gear').Queue;
- let regex = {},
- headerRegex = /^\s*\/\*((.|\r?\n)*?)\*/;
- const REPLACES = {
- 'case_insensitive': 'cI',
- 'lexemes': 'l',
- 'contains': 'c',
- 'keywords': 'k',
- 'subLanguage': 'sL',
- 'className': 'cN',
- 'begin': 'b',
- 'beginKeywords': 'bK',
- 'end': 'e',
- 'endsWithParent': 'eW',
- 'illegal': 'i',
- 'excludeBegin': 'eB',
- 'excludeEnd': 'eE',
- 'returnBegin': 'rB',
- 'returnEnd': 'rE',
- 'relevance': 'r',
- 'variants': 'v',
- 'IDENT_RE': 'IR',
- 'UNDERSCORE_IDENT_RE': 'UIR',
- 'NUMBER_RE': 'NR',
- 'C_NUMBER_RE': 'CNR',
- 'BINARY_NUMBER_RE': 'BNR',
- 'RE_STARTERS_RE': 'RSR',
- 'BACKSLASH_ESCAPE': 'BE',
- 'APOS_STRING_MODE': 'ASM',
- 'QUOTE_STRING_MODE': 'QSM',
- 'PHRASAL_WORDS_MODE': 'PWM',
- 'C_LINE_COMMENT_MODE': 'CLCM',
- 'C_BLOCK_COMMENT_MODE': 'CBCM',
- 'HASH_COMMENT_MODE': 'HCM',
- 'NUMBER_MODE': 'NM',
- 'C_NUMBER_MODE': 'CNM',
- 'BINARY_NUMBER_MODE': 'BNM',
- 'CSS_NUMBER_MODE': 'CSSNM',
- 'REGEXP_MODE': 'RM',
- 'TITLE_MODE': 'TM',
- 'UNDERSCORE_TITLE_MODE': 'UTM',
- 'COMMENT': 'C',
- 'beginRe': 'bR',
- 'endRe': 'eR',
- 'illegalRe': 'iR',
- 'lexemesRe': 'lR',
- 'terminators': 't',
- 'terminator_end': 'tE'
- };
- regex.replaces = new RegExp(
- `\\b(${Object.keys(REPLACES).join('|')})\\b`, 'g');
- regex.classname = /(block|parentNode)\.cN/g;
- regex.header = /^\s*(\/\*((.|\r?\n)*?)\*\/)?\s*/;
- function replace(from, to) {
- return { regex: from, replace: to };
- }
- function replaceClassNames(match) {
- return REPLACES[match];
- }
- // All meta data, for each language definition, it store within the headers
- // of each file in `src/languages`. `parseHeader` extracts that data and
- // turns it into a useful object -- mainly for categories and what language
- // this definition requires.
- function parseHeader(content) {
- let headers,
- match = content.match(headerRegex);
- if (!match) {
- return null;
- }
- headers = _.compact(match[1].split('\n'));
- return _.reduce(headers, function(result, header) {
- let keyVal = header.trim().split(': '),
- key = keyVal[0],
- value = keyVal[1] || '';
- if(key !== 'Description' && key !== 'Language') {
- value = value.split(/\s*,\s*/);
- }
- result[key] = value;
- return result;
- }, {});
- }
- function filterByQualifiers(blob, languages, categories) {
- if(_.isEmpty(languages) && _.isEmpty(categories)) return true;
- let language = path.basename(blob.name, '.js'),
- fileInfo = parseHeader(blob.result),
- fileCategories = fileInfo.Category || [],
- containsCategory = _.partial(_.includes, categories);
- if(!fileInfo) return false;
- return _.includes(languages, language) ||
- _.some(fileCategories, containsCategory);
- }
- // For the filter task in `tools/tasks.js`, this function will look for
- // categories and languages specificed from the CLI.
- function buildFilterCallback(qualifiers) {
- const result = _.partition(qualifiers, { 0: ':' }),
- languages = result[1],
- categories = _.map(result[0], category => category.slice(1));
- return blob => filterByQualifiers(blob, languages, categories);
- }
- function globDefaults(pattern, encoding) {
- encoding = encoding || 'utf8';
- // The limit option is a fix for issue #636 when the build script would
- // EMFILE error for those systems who had a limit of open files per
- // process.
- //
- // <https://github.com/isagalaev/highlight.js/issues/636>
- return { pattern: pattern, limit: 50, encoding: encoding };
- }
- function getStyleNames() {
- let stylesDir = 'src/styles/',
- options = { ignore: `${stylesDir}default.css` };
- return glob(`${stylesDir}*.css`, options)
- .map(function(style) {
- let basename = path.basename(style, '.css'),
- name = _.startCase(basename),
- pathName = path.relative('src', style);
- return { path: pathName, name: name };
- });
- }
- function toQueue(tasks, registry) {
- return _.map(tasks, task => new Queue({ registry }).tasks(task));
- }
- module.exports = {
- buildFilterCallback: buildFilterCallback,
- getStyleNames: getStyleNames,
- glob: globDefaults,
- parseHeader: parseHeader,
- regex: regex,
- replace: replace,
- replaceClassNames: replaceClassNames,
- toQueue: toQueue
- };
|