UNPKG

5.43 kBJavaScriptView Raw
1'use strict';
2
3var uniq = require('lodash/uniq');
4var uniqWith = require('lodash/uniqWith');
5
6var parsersDb = {
7 '.bash': { parserName: 'coffeeParser' },
8 '.c': { parserName: 'defaultParser' },
9 '.cjsx': { parserName: 'coffeeParser' },
10 '.coffee': { parserName: 'coffeeParser' },
11 '.cpp': { parserName: 'defaultParser' },
12 '.cr': { parserName: 'coffeeParser' },
13 '.cs': { parserName: 'defaultParser' },
14 '.cson': { parserName: 'coffeeParser' },
15 '.css': { parserName: 'defaultParser' },
16 '.ejs': { parserName: 'ejsParser' },
17 '.erb': { parserName: 'ejsParser' },
18 '.erl': { parserName: 'erlangParser' },
19 '.es': { parserName: 'defaultParser' },
20 '.es6': { parserName: 'defaultParser' },
21 '.go': { parserName: 'defaultParser' },
22 '.h': { parserName: 'defaultParser' },
23 '.haml': { parserName: 'hamlParser' },
24 '.handlebars': { parserName: 'hbsParser' },
25 '.hbs': { parserName: 'hbsParser' },
26 '.hgn': { parserName: 'hbsParser' },
27 '.hogan': { parserName: 'hbsParser' },
28 '.hrl': { parserName: 'erlangParser' },
29 '.hs': { parserName: 'haskellParser' },
30 '.htm': { parserName: 'twigParser' },
31 '.html': { parserName: 'twigParser' },
32 '.jade': { parserName: 'jadeParser' },
33 '.java': { parserName: 'defaultParser' },
34 '.kt': { parserName: 'defaultParser' },
35 '.js': { parserName: 'defaultParser' },
36 '.jsx': { parserName: 'defaultParser' },
37 '.less': { parserName: 'defaultParser' },
38 '.m': { parserName: 'defaultParser' },
39 '.mm': { parserName: 'defaultParser' },
40 '.mustache': { parserName: 'hbsParser' },
41 '.njk': { parserName: 'twigParser' },
42 '.pas': { parserName: 'pascalParser' },
43 '.php': { parserName: 'defaultParser', includedFiles: ['.html', '.js', '.css'] },
44 '.pl': { parserName: 'coffeeParser' },
45 '.pm': { parserName: 'coffeeParser' },
46 '.pug': { parserName: 'jadeParser' },
47 '.py': { parserName: 'pythonParser' },
48 '.rb': { parserName: 'coffeeParser' },
49 '.sass': { parserName: 'defaultParser' },
50 '.scala': { parserName: 'defaultParser' },
51 '.scss': { parserName: 'defaultParser' },
52 '.sh': { parserName: 'coffeeParser' },
53 '.sql': { parserName: ['defaultParser', 'haskellParser'] },
54 '.ss': { parserName: 'ssParser' },
55 '.styl': { parserName: 'defaultParser' },
56 '.swift': { parserName: 'defaultParser' },
57 '.ts': { parserName: 'defaultParser' },
58 '.tsx': { parserName: 'defaultParser' },
59 '.twig': { parserName: 'twigParser' },
60 '.vue': { parserName: 'twigParser', includedFiles: ['.html', '.js', '.css'] },
61 '.yaml': { parserName: 'coffeeParser', includedFiles: ['.yml'] },
62 '.zsh': { parserName: 'coffeeParser' },
63};
64
65// Support for associating an extension with a parser
66function associateExtWithParser(parsers) {
67 var keys = Object.keys(parsers);
68 if (keys.length === 0) {
69 return;
70 }
71 keys.forEach(function (ext) {
72 if (ext.length <= 1 || ext[0] !== '.') {
73 throw new Error('Cannot register extension: invalid extension ' + ext);
74 }
75 var parser = parsers[ext];
76 if (!parser || !parser.parserName) {
77 throw new Error('Cannot register extension: parser name missing.');
78 }
79 });
80
81 // Add any additional parsers.
82 Object.assign(parsersDb, parsers);
83}
84
85function isExtSupported(ext) {
86 return Boolean(parsersDb[ext]);
87}
88
89function parse(options) {
90 var ext = options.ext;
91 var content = options.content;
92 var fileName = options.fileName;
93 var customTags = options.customTags;
94 var withInlineFiles = options.withInlineFiles || false;
95 var associateParser = options.associateParser || {};
96
97 // Associate extensions with bundled parsers
98 associateExtWithParser(associateParser);
99
100 if (!isExtSupported(ext)) {
101 throw new Error('extension ' + ext + ' is not supported.');
102 }
103 if (customTags && !Array.isArray(customTags)) {
104 throw new TypeError('`customTags` must be an array');
105 }
106 var parseOptions = {
107 customTags: customTags
108 };
109 var originalParser = parsersDb[ext];
110 var parsers = [].concat(originalParser.parserName);
111
112 var includedFiles = originalParser.includedFiles || [];
113 if (withInlineFiles) {
114 includedFiles.forEach(function (ext) {
115 parsers.push(parsersDb[ext].parserName);
116 });
117 parsers = uniq(parsers);
118 }
119
120 var parsed = parsers
121 .map(function (parser) {
122 var parserFactory = require('./parsers/' + parser);
123 return parserFactory(parseOptions)(content, fileName);
124 })
125 .reduce(function (items, item) {
126 // flatten
127 return items.concat(item);
128 }, [])
129 .sort(function (item1, item2) {
130 return item1.line - item2.line;
131 });
132
133 return uniqWith(parsed, function (a, b) {
134 return a.line === b.line
135 && a.kind === b.kind
136 && a.text === b.text;
137 });
138}
139
140/* legacy parse method, kept for backwards compatibility */
141function parseLegacy(ext, content, fileName, customTags, withInlineFiles) {
142 return parse({
143 ext: ext,
144 content: content,
145 fileName: fileName,
146 customTags: customTags,
147 withInlineFiles: withInlineFiles
148 });
149}
150
151exports.associateExtWithParser = associateExtWithParser;
152exports.isExtSupported = isExtSupported;
153exports.parse = parse;
154exports.parseLegacy = parseLegacy;