linguist-js 2.4.2 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +1 -0
- package/dist/helpers/load-data.js +11 -2
- package/dist/index.js +34 -22
- package/dist/types.d.ts +1 -0
- package/ext/documentation.yml +17 -0
- package/ext/generated.rb +351 -0
- package/ext/heuristics.yml +669 -0
- package/ext/languages.yml +7480 -0
- package/ext/vendor.yml +165 -0
- package/package.json +8 -5
- package/readme.md +5 -1
package/dist/cli.js
CHANGED
|
@@ -19,6 +19,7 @@ commander_1.program
|
|
|
19
19
|
.option('-j|--json [bool]', 'Display the output as JSON', false)
|
|
20
20
|
.option('-t|--tree <traversal>', 'Which part of the output JSON to display (dot-delimited)')
|
|
21
21
|
.option('-q|--quick [bool]', 'Skip complex language analysis (alias for -{A|I|H|S}=false)', false)
|
|
22
|
+
.option('-o|--offline [bool]', 'Use packaged data files instead of fetching latest from GitHub', false)
|
|
22
23
|
.option('-V|--keepVendored [bool]', 'Prevent skipping over vendored/generated files', false)
|
|
23
24
|
.option('-B|--keepBinary [bool]', 'Prevent skipping over binary files', false)
|
|
24
25
|
.option('-r|--relativePaths [bool]', 'Convert absolute file paths to relative', false)
|
|
@@ -3,11 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
7
|
+
const path_1 = __importDefault(require("path"));
|
|
6
8
|
const cross_fetch_1 = __importDefault(require("cross-fetch"));
|
|
7
9
|
const node_cache_1 = __importDefault(require("node-cache"));
|
|
8
10
|
const cache = new node_cache_1.default({});
|
|
9
|
-
|
|
10
|
-
async function loadFile(file) {
|
|
11
|
+
async function loadWebFile(file) {
|
|
11
12
|
// Return cache if it exists
|
|
12
13
|
const cachedContent = cache.get(file);
|
|
13
14
|
if (cachedContent)
|
|
@@ -18,4 +19,12 @@ async function loadFile(file) {
|
|
|
18
19
|
cache.set(file, fileContent);
|
|
19
20
|
return fileContent;
|
|
20
21
|
}
|
|
22
|
+
async function loadLocalFile(file) {
|
|
23
|
+
const filePath = path_1.default.resolve(__dirname, '../../ext', file);
|
|
24
|
+
return promises_1.default.readFile(filePath).then(buffer => buffer.toString());
|
|
25
|
+
}
|
|
26
|
+
/** Load a data file from github-linguist. */
|
|
27
|
+
async function loadFile(file, offline = false) {
|
|
28
|
+
return offline ? loadLocalFile(file) : loadWebFile(file);
|
|
29
|
+
}
|
|
21
30
|
exports.default = loadFile;
|
package/dist/index.js
CHANGED
|
@@ -20,11 +20,11 @@ async function analyse(input, opts = {}) {
|
|
|
20
20
|
input = [input !== null && input !== void 0 ? input : []].flat();
|
|
21
21
|
opts.fileContent = [(_a = opts.fileContent) !== null && _a !== void 0 ? _a : []].flat();
|
|
22
22
|
// Load data from github-linguist web repo
|
|
23
|
-
const langData = await (0, load_data_1.default)('languages.yml').then(js_yaml_1.default.load);
|
|
24
|
-
const vendorData = await (0, load_data_1.default)('vendor.yml').then(js_yaml_1.default.load);
|
|
25
|
-
const docData = await (0, load_data_1.default)('documentation.yml').then(js_yaml_1.default.load);
|
|
26
|
-
const heuristicsData = await (0, load_data_1.default)('heuristics.yml').then(js_yaml_1.default.load);
|
|
27
|
-
const generatedData = await (0, load_data_1.default)('generated.rb').then(text => { var _a; return (_a = text.match(/(?<=name\.match\(\/).+?(?=(?<!\\)\/)/gm)) !== null && _a !== void 0 ? _a : []; });
|
|
23
|
+
const langData = await (0, load_data_1.default)('languages.yml', opts.offline).then(js_yaml_1.default.load);
|
|
24
|
+
const vendorData = await (0, load_data_1.default)('vendor.yml', opts.offline).then(js_yaml_1.default.load);
|
|
25
|
+
const docData = await (0, load_data_1.default)('documentation.yml', opts.offline).then(js_yaml_1.default.load);
|
|
26
|
+
const heuristicsData = await (0, load_data_1.default)('heuristics.yml', opts.offline).then(js_yaml_1.default.load);
|
|
27
|
+
const generatedData = await (0, load_data_1.default)('generated.rb', opts.offline).then(text => { var _a; return (_a = text.match(/(?<=name\.match\(\/).+?(?=(?<!\\)\/)/gm)) !== null && _a !== void 0 ? _a : []; });
|
|
28
28
|
const vendorPaths = [...vendorData, ...docData, ...generatedData];
|
|
29
29
|
// Setup main variables
|
|
30
30
|
const fileAssociations = {};
|
|
@@ -86,8 +86,9 @@ async function analyse(input, opts = {}) {
|
|
|
86
86
|
if (!useRawContent && opts.checkAttributes) {
|
|
87
87
|
for (const folder of folders) {
|
|
88
88
|
// Skip if folder is marked in gitattributes
|
|
89
|
-
if (relPath(folder) && gitignores.ignores(relPath(folder)))
|
|
89
|
+
if (relPath(folder) && gitignores.ignores(relPath(folder))) {
|
|
90
90
|
continue;
|
|
91
|
+
}
|
|
91
92
|
// Parse gitignores
|
|
92
93
|
const ignoresFile = path_1.default.join(folder, '.gitignore');
|
|
93
94
|
if (opts.checkIgnored && fs_1.default.existsSync(ignoresFile)) {
|
|
@@ -101,10 +102,12 @@ async function analyse(input, opts = {}) {
|
|
|
101
102
|
// Explicit text/binary associations
|
|
102
103
|
const contentTypeMatches = attributesData.matchAll(/^(\S+).*?(-?binary|-?text)(?!=auto)/gm);
|
|
103
104
|
for (const [_line, path, type] of contentTypeMatches) {
|
|
104
|
-
if (['text', '-binary'].includes(type))
|
|
105
|
+
if (['text', '-binary'].includes(type)) {
|
|
105
106
|
customText.add(path);
|
|
106
|
-
|
|
107
|
+
}
|
|
108
|
+
if (['-text', 'binary'].includes(type)) {
|
|
107
109
|
customBinary.add(path);
|
|
110
|
+
}
|
|
108
111
|
}
|
|
109
112
|
// Custom vendor options
|
|
110
113
|
const vendorMatches = attributesData.matchAll(/^(\S+).*[^-]linguist-(vendored|generated|documentation)(?!=false)/gm);
|
|
@@ -117,8 +120,9 @@ async function analyse(input, opts = {}) {
|
|
|
117
120
|
// If specified language is an alias, associate it with its full name
|
|
118
121
|
if (!langData[forcedLang]) {
|
|
119
122
|
const overrideLang = Object.entries(langData).find(entry => { var _a; return (_a = entry[1].aliases) === null || _a === void 0 ? void 0 : _a.includes(forcedLang.toLowerCase()); });
|
|
120
|
-
if (overrideLang)
|
|
123
|
+
if (overrideLang) {
|
|
121
124
|
forcedLang = overrideLang[0];
|
|
125
|
+
}
|
|
122
126
|
}
|
|
123
127
|
const fullPath = relPath(folder) + '/' + path;
|
|
124
128
|
overrides[fullPath] = forcedLang;
|
|
@@ -154,11 +158,11 @@ async function analyse(input, opts = {}) {
|
|
|
154
158
|
if (useRawContent) {
|
|
155
159
|
firstLine = (_e = (_d = (_c = opts.fileContent) === null || _c === void 0 ? void 0 : _c[files.indexOf(file)]) === null || _d === void 0 ? void 0 : _d.split('\n')[0]) !== null && _e !== void 0 ? _e : null;
|
|
156
160
|
}
|
|
157
|
-
else {
|
|
158
|
-
if (!fs_1.default.existsSync(file) || fs_1.default.lstatSync(file).isDirectory())
|
|
159
|
-
continue;
|
|
161
|
+
else if (fs_1.default.existsSync(file) && !fs_1.default.lstatSync(file).isDirectory()) {
|
|
160
162
|
firstLine = await (0, read_file_1.default)(file, true).catch(() => null);
|
|
161
163
|
}
|
|
164
|
+
else
|
|
165
|
+
continue;
|
|
162
166
|
// Skip if file is unreadable
|
|
163
167
|
if (firstLine === null)
|
|
164
168
|
continue;
|
|
@@ -175,10 +179,11 @@ async function analyse(input, opts = {}) {
|
|
|
175
179
|
const matchesLang = firstLine.toLowerCase().match(langMatcher(lang));
|
|
176
180
|
const matchesAlias = (_g = data.aliases) === null || _g === void 0 ? void 0 : _g.some(lang => firstLine.toLowerCase().match(langMatcher(lang)));
|
|
177
181
|
// Add language
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
if (
|
|
182
|
+
const interpretorCheck = opts.checkShebang && matchesInterpretor;
|
|
183
|
+
const modelineCheck = opts.checkModeline && (matchesLang || matchesAlias);
|
|
184
|
+
if (interpretorCheck || modelineCheck) {
|
|
181
185
|
matches.push(lang);
|
|
186
|
+
}
|
|
182
187
|
}
|
|
183
188
|
if (matches.length) {
|
|
184
189
|
// Add explicitly-identified language
|
|
@@ -213,12 +218,14 @@ async function analyse(input, opts = {}) {
|
|
|
213
218
|
for (const lang in langData) {
|
|
214
219
|
// Check if extension is a match
|
|
215
220
|
const matchesExt = (_j = langData[lang].extensions) === null || _j === void 0 ? void 0 : _j.some(ext => file.toLowerCase().endsWith(ext.toLowerCase()));
|
|
216
|
-
if (matchesExt)
|
|
221
|
+
if (matchesExt) {
|
|
217
222
|
addResult(file, lang);
|
|
223
|
+
}
|
|
218
224
|
}
|
|
219
225
|
// Fallback to null if no language matches
|
|
220
|
-
if (!fileAssociations[file])
|
|
226
|
+
if (!fileAssociations[file]) {
|
|
221
227
|
addResult(file, null);
|
|
228
|
+
}
|
|
222
229
|
}
|
|
223
230
|
// Narrow down file associations to the best fit
|
|
224
231
|
for (const file in fileAssociations) {
|
|
@@ -280,16 +287,19 @@ async function analyse(input, opts = {}) {
|
|
|
280
287
|
const categories = ['data', 'markup', 'programming', 'prose'];
|
|
281
288
|
const hiddenCategories = categories.filter(cat => !opts.categories.includes(cat));
|
|
282
289
|
for (const [file, lang] of Object.entries(results.files.results)) {
|
|
283
|
-
if (!hiddenCategories.some(cat => { var _a; return lang && ((_a = langData[lang]) === null || _a === void 0 ? void 0 : _a.type) === cat; }))
|
|
290
|
+
if (!hiddenCategories.some(cat => { var _a; return lang && ((_a = langData[lang]) === null || _a === void 0 ? void 0 : _a.type) === cat; })) {
|
|
284
291
|
continue;
|
|
292
|
+
}
|
|
285
293
|
delete results.files.results[file];
|
|
286
|
-
if (lang)
|
|
294
|
+
if (lang) {
|
|
287
295
|
delete results.languages.results[lang];
|
|
296
|
+
}
|
|
288
297
|
}
|
|
289
298
|
for (const category of hiddenCategories) {
|
|
290
299
|
for (const [lang, { type }] of Object.entries(results.languages.results)) {
|
|
291
|
-
if (type === category)
|
|
300
|
+
if (type === category) {
|
|
292
301
|
delete results.languages.results[lang];
|
|
302
|
+
}
|
|
293
303
|
}
|
|
294
304
|
}
|
|
295
305
|
}
|
|
@@ -298,8 +308,9 @@ async function analyse(input, opts = {}) {
|
|
|
298
308
|
const newMap = {};
|
|
299
309
|
for (const [file, lang] of Object.entries(results.files.results)) {
|
|
300
310
|
let relPath = path_1.default.relative(process.cwd(), file).replace(/\\/g, '/');
|
|
301
|
-
if (!relPath.startsWith('../'))
|
|
311
|
+
if (!relPath.startsWith('../')) {
|
|
302
312
|
relPath = './' + relPath;
|
|
313
|
+
}
|
|
303
314
|
newMap[relPath] = lang;
|
|
304
315
|
}
|
|
305
316
|
results.files.results = newMap;
|
|
@@ -323,8 +334,9 @@ async function analyse(input, opts = {}) {
|
|
|
323
334
|
// Add language and bytes data to corresponding section
|
|
324
335
|
const { type } = langData[lang];
|
|
325
336
|
(_s = (_v = results.languages.results)[lang]) !== null && _s !== void 0 ? _s : (_v[lang] = { type, bytes: 0, color: langData[lang].color });
|
|
326
|
-
if (opts.childLanguages)
|
|
337
|
+
if (opts.childLanguages) {
|
|
327
338
|
results.languages.results[lang].parent = langData[lang].group;
|
|
339
|
+
}
|
|
328
340
|
results.languages.results[lang].bytes += fileSize;
|
|
329
341
|
results.languages.bytes += fileSize;
|
|
330
342
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
- ^[Dd]ocs?/
|
|
2
|
+
- (^|/)[Dd]ocumentation/
|
|
3
|
+
- (^|/)[Gg]roovydoc/
|
|
4
|
+
- (^|/)[Jj]avadoc/
|
|
5
|
+
- ^[Mm]an/
|
|
6
|
+
- ^[Ee]xamples/
|
|
7
|
+
- ^[Dd]emos?/
|
|
8
|
+
- (^|/)inst/doc/- (^|/)CITATION(\.cff|(S)?(\.(bib|md))?)$
|
|
9
|
+
- (^|/)CHANGE(S|LOG)?(\.|$)
|
|
10
|
+
- (^|/)CONTRIBUTING(\.|$)
|
|
11
|
+
- (^|/)COPYING(\.|$)
|
|
12
|
+
- (^|/)INSTALL(\.|$)
|
|
13
|
+
- (^|/)LICEN[CS]E(\.|$)
|
|
14
|
+
- (^|/)[Ll]icen[cs]e(\.|$)
|
|
15
|
+
- (^|/)README(\.|$)
|
|
16
|
+
- (^|/)[Rr]eadme(\.|$)
|
|
17
|
+
- ^[Ss]amples?/
|
package/ext/generated.rb
ADDED
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
module Linguist
|
|
2
|
+
class Generated
|
|
3
|
+
def self.generated?(name, data)
|
|
4
|
+
new(name, data).generated?
|
|
5
|
+
end
|
|
6
|
+
def initialize(name, data)
|
|
7
|
+
@name = name
|
|
8
|
+
@extname = File.extname(name)
|
|
9
|
+
@_data = data
|
|
10
|
+
end attr_reader :name, :extname
|
|
11
|
+
def data
|
|
12
|
+
@data ||= @_data.respond_to?(:call) ? @_data.call() : @_data
|
|
13
|
+
end
|
|
14
|
+
def lines
|
|
15
|
+
@lines ||= data ? data.split("\n", -1) : []
|
|
16
|
+
end
|
|
17
|
+
def generated?
|
|
18
|
+
xcode_file? ||
|
|
19
|
+
intellij_file? ||
|
|
20
|
+
cocoapods? ||
|
|
21
|
+
carthage_build? ||
|
|
22
|
+
generated_graphql_relay? ||
|
|
23
|
+
generated_net_designer_file? ||
|
|
24
|
+
generated_net_specflow_feature_file? ||
|
|
25
|
+
composer_lock? ||
|
|
26
|
+
cargo_lock? ||
|
|
27
|
+
node_modules? ||
|
|
28
|
+
go_vendor? ||
|
|
29
|
+
go_lock? ||
|
|
30
|
+
poetry_lock? ||
|
|
31
|
+
esy_lock? ||
|
|
32
|
+
npm_shrinkwrap_or_package_lock? ||
|
|
33
|
+
terraform_lock? ||
|
|
34
|
+
generated_yarn_plugnplay? ||
|
|
35
|
+
godeps? ||
|
|
36
|
+
generated_by_zephir? ||
|
|
37
|
+
minified_files? ||
|
|
38
|
+
has_source_map? ||
|
|
39
|
+
source_map? ||
|
|
40
|
+
compiled_coffeescript? ||
|
|
41
|
+
generated_parser? ||
|
|
42
|
+
generated_net_docfile? ||
|
|
43
|
+
generated_postscript? ||
|
|
44
|
+
compiled_cython_file? ||
|
|
45
|
+
pipenv_lock? ||
|
|
46
|
+
generated_go? ||
|
|
47
|
+
generated_protocol_buffer_from_go? ||
|
|
48
|
+
generated_protocol_buffer? ||
|
|
49
|
+
generated_javascript_protocol_buffer? ||
|
|
50
|
+
generated_apache_thrift? ||
|
|
51
|
+
generated_jni_header? ||
|
|
52
|
+
vcr_cassette? ||
|
|
53
|
+
generated_antlr? ||
|
|
54
|
+
generated_module? ||
|
|
55
|
+
generated_unity3d_meta? ||
|
|
56
|
+
generated_racc? ||
|
|
57
|
+
generated_jflex? ||
|
|
58
|
+
generated_grammarkit? ||
|
|
59
|
+
generated_roxygen2? ||
|
|
60
|
+
generated_html? ||
|
|
61
|
+
generated_jison? ||
|
|
62
|
+
generated_grpc_cpp? ||
|
|
63
|
+
generated_dart? ||
|
|
64
|
+
generated_perl_ppport_header? ||
|
|
65
|
+
generated_gamemakerstudio? ||
|
|
66
|
+
generated_gimp? ||
|
|
67
|
+
generated_visualstudio6? ||
|
|
68
|
+
generated_haxe? ||
|
|
69
|
+
generated_jooq? ||
|
|
70
|
+
generated_pascal_tlb?
|
|
71
|
+
end
|
|
72
|
+
def xcode_file?
|
|
73
|
+
['.nib', '.xcworkspacedata', '.xcuserstate'].include?(extname)
|
|
74
|
+
end
|
|
75
|
+
def intellij_file?
|
|
76
|
+
!!name.match(/(?:^|\/)\.idea\//)
|
|
77
|
+
end
|
|
78
|
+
def cocoapods?
|
|
79
|
+
!!name.match(/(^Pods|\/Pods)\//)
|
|
80
|
+
end
|
|
81
|
+
def carthage_build?
|
|
82
|
+
!!name.match(/(^|\/)Carthage\/Build\//)
|
|
83
|
+
end
|
|
84
|
+
def maybe_minified?
|
|
85
|
+
['.js', '.css'].include? extname.downcase
|
|
86
|
+
end
|
|
87
|
+
def minified_files?
|
|
88
|
+
if maybe_minified? and lines.any?
|
|
89
|
+
(lines.inject(0) { |n, l| n += l.length } / lines.length) > 110
|
|
90
|
+
else
|
|
91
|
+
false
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
def has_source_map?
|
|
95
|
+
return false unless maybe_minified?
|
|
96
|
+
lines.last(2).any? { |l| l.match(/^\/[*\/][\#@] source(?:Mapping)?URL|sourceURL=/) }
|
|
97
|
+
end
|
|
98
|
+
def source_map?
|
|
99
|
+
return false unless extname.downcase == '.map' name =~ /(\.css|\.js)\.map$/i ||
|
|
100
|
+
lines[0] =~ /^{"version":\d+,/ ||
|
|
101
|
+
lines[0] =~ /^\/\*\* Begin line maps\. \*\*\/{/
|
|
102
|
+
end
|
|
103
|
+
def compiled_coffeescript?
|
|
104
|
+
return false unless extname == '.js'
|
|
105
|
+
if lines[0] =~ /^\/\/ Generated by /
|
|
106
|
+
return true
|
|
107
|
+
end if lines[0] == '(function() {' &&
|
|
108
|
+
lines[-2] == '}).call(this);' &&
|
|
109
|
+
lines[-1] == '' score = 0 lines.each do |line|
|
|
110
|
+
if line =~ /var /
|
|
111
|
+
score += 1 * line.gsub(/(_fn|_i|_len|_ref|_results)/).count
|
|
112
|
+
score += 3 * line.gsub(/(__bind|__extends|__hasProp|__indexOf|__slice)/).count
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
score >= 3
|
|
116
|
+
else
|
|
117
|
+
false
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
def generated_net_docfile?
|
|
121
|
+
return false unless extname.downcase == ".xml"
|
|
122
|
+
return false unless lines.count > 3
|
|
123
|
+
return lines[1].include?("<doc>") &&
|
|
124
|
+
lines[2].include?("<assembly>") &&
|
|
125
|
+
lines[-2].include?("</doc>")
|
|
126
|
+
end
|
|
127
|
+
def generated_net_designer_file?
|
|
128
|
+
!!name.match(/\.designer\.(cs|vb)$/i)
|
|
129
|
+
end
|
|
130
|
+
def generated_net_specflow_feature_file?
|
|
131
|
+
!!name.match(/\.feature\.cs$/i)
|
|
132
|
+
end
|
|
133
|
+
def generated_parser?
|
|
134
|
+
return false unless extname == '.js'
|
|
135
|
+
if lines[0..4].join('') =~ /^(?:[^\/]|\/[^\*])*\/\*(?:[^\*]|\*[^\/])*Generated by PEG.js/
|
|
136
|
+
return true
|
|
137
|
+
end false
|
|
138
|
+
end
|
|
139
|
+
def generated_postscript?
|
|
140
|
+
return false unless ['.ps', '.eps', '.pfa'].include? extname
|
|
141
|
+
return true if data =~ /(\n|\r\n|\r)\s*(?:currentfile eexec\s+|\/sfnts\s+\[\1<)\h{8,}\1/
|
|
142
|
+
creator = lines[0..9].find {|line| line =~ /^%%Creator: /}
|
|
143
|
+
return false if creator.nil?
|
|
144
|
+
return true if creator =~ /[0-9]|draw|mpage|ImageMagick|inkscape|MATLAB/ ||
|
|
145
|
+
creator =~ /PCBNEW|pnmtops|\(Unknown\)|Serif Affinity|Filterimage -tops/
|
|
146
|
+
!!creator.include?("EAGLE") and lines[0..4].find {|line| line =~ /^%%Title: EAGLE Drawing /}
|
|
147
|
+
end def generated_go?
|
|
148
|
+
return false unless extname == '.go'
|
|
149
|
+
return false unless lines.count > 1 return lines.first(40).any? { |l| l.include? "Code generated by" }
|
|
150
|
+
end
|
|
151
|
+
def generated_protocol_buffer_from_go?
|
|
152
|
+
return false unless extname == '.proto'
|
|
153
|
+
return false unless lines.count > 1 return lines.first(20).any? { |l| l.include? "This file was autogenerated by go-to-protobuf" }
|
|
154
|
+
end PROTOBUF_EXTENSIONS = ['.py', '.java', '.h', '.cc', '.cpp', '.m', '.rb', '.php']
|
|
155
|
+
def generated_protocol_buffer?
|
|
156
|
+
return false unless PROTOBUF_EXTENSIONS.include?(extname)
|
|
157
|
+
return false unless lines.count > 1 return lines.first(3).any? { |l| l.include?("Generated by the protocol buffer compiler. DO NOT EDIT!") }
|
|
158
|
+
end
|
|
159
|
+
def generated_javascript_protocol_buffer?
|
|
160
|
+
return false unless extname == ".js"
|
|
161
|
+
return false unless lines.count > 6 return lines[5].include?("GENERATED CODE -- DO NOT EDIT!")
|
|
162
|
+
end APACHE_THRIFT_EXTENSIONS = ['.rb', '.py', '.go', '.js', '.m', '.java', '.h', '.cc', '.cpp', '.php']
|
|
163
|
+
def generated_apache_thrift?
|
|
164
|
+
return false unless APACHE_THRIFT_EXTENSIONS.include?(extname)
|
|
165
|
+
return lines.first(6).any? { |l| l.include?("Autogenerated by Thrift Compiler") }
|
|
166
|
+
end
|
|
167
|
+
def generated_jni_header?
|
|
168
|
+
return false unless extname == '.h'
|
|
169
|
+
return false unless lines.count > 2 return lines[0].include?("/* DO NOT EDIT THIS FILE - it is machine generated */") &&
|
|
170
|
+
lines[1].include?("#include <jni.h>")
|
|
171
|
+
end
|
|
172
|
+
def node_modules?
|
|
173
|
+
!!name.match(/node_modules\//)
|
|
174
|
+
end
|
|
175
|
+
def go_vendor?
|
|
176
|
+
!!name.match(/vendor\/((?!-)[-0-9A-Za-z]+(?<!-)\.)+(com|edu|gov|in|me|net|org|fm|io)/)
|
|
177
|
+
end
|
|
178
|
+
def go_lock?
|
|
179
|
+
!!name.match(/(Gopkg|glide)\.lock/)
|
|
180
|
+
end
|
|
181
|
+
def poetry_lock?
|
|
182
|
+
!!name.match(/poetry\.lock/)
|
|
183
|
+
end
|
|
184
|
+
def esy_lock?
|
|
185
|
+
!!name.match(/(^|\/)(\w+\.)?esy.lock$/)
|
|
186
|
+
end
|
|
187
|
+
def npm_shrinkwrap_or_package_lock?
|
|
188
|
+
!!name.match(/npm-shrinkwrap\.json/) || !!name.match(/package-lock\.json/)
|
|
189
|
+
end
|
|
190
|
+
def generated_yarn_plugnplay?
|
|
191
|
+
!!name.match(/(^|\/)\.pnp\..*$/)
|
|
192
|
+
end
|
|
193
|
+
def godeps?
|
|
194
|
+
!!name.match(/Godeps\//)
|
|
195
|
+
end
|
|
196
|
+
def composer_lock?
|
|
197
|
+
!!name.match(/composer\.lock/)
|
|
198
|
+
end
|
|
199
|
+
def generated_by_zephir?
|
|
200
|
+
!!name.match(/.\.zep\.(?:c|h|php)$/)
|
|
201
|
+
end
|
|
202
|
+
def cargo_lock?
|
|
203
|
+
!!name.match(/Cargo\.lock/)
|
|
204
|
+
end
|
|
205
|
+
def vcr_cassette?
|
|
206
|
+
return false unless extname == '.yml'
|
|
207
|
+
return false unless lines.count > 2
|
|
208
|
+
return lines[-2].include?("recorded_with: VCR")
|
|
209
|
+
end
|
|
210
|
+
def generated_antlr?
|
|
211
|
+
return false unless extname == '.g'
|
|
212
|
+
return false unless lines.count > 2
|
|
213
|
+
return lines[1].include?("generated by Xtest")
|
|
214
|
+
end
|
|
215
|
+
def compiled_cython_file?
|
|
216
|
+
return false unless ['.c', '.cpp'].include? extname
|
|
217
|
+
return false unless lines.count > 1
|
|
218
|
+
return lines[0].include?("Generated by Cython")
|
|
219
|
+
end
|
|
220
|
+
def pipenv_lock?
|
|
221
|
+
!!name.match(/Pipfile\.lock/)
|
|
222
|
+
end
|
|
223
|
+
def terraform_lock?
|
|
224
|
+
!!name.match(/(?:^|\/)\.terraform\.lock\.hcl$/)
|
|
225
|
+
end
|
|
226
|
+
def generated_module?
|
|
227
|
+
return false unless extname == '.mod'
|
|
228
|
+
return false unless lines.count > 1
|
|
229
|
+
return lines[0].include?("PCBNEW-LibModule-V") ||
|
|
230
|
+
lines[0].include?("GFORTRAN module version '")
|
|
231
|
+
end
|
|
232
|
+
def generated_unity3d_meta?
|
|
233
|
+
return false unless extname == '.meta'
|
|
234
|
+
return false unless lines.count > 1
|
|
235
|
+
return lines[0].include?("fileFormatVersion: ")
|
|
236
|
+
end
|
|
237
|
+
def generated_racc?
|
|
238
|
+
return false unless extname == '.rb'
|
|
239
|
+
return false unless lines.count > 2
|
|
240
|
+
return lines[2].start_with?("# This file is automatically generated by Racc")
|
|
241
|
+
end
|
|
242
|
+
def generated_jflex?
|
|
243
|
+
return false unless extname == '.java'
|
|
244
|
+
return false unless lines.count > 1
|
|
245
|
+
return lines[0].start_with?("/* The following code was generated by JFlex ")
|
|
246
|
+
end
|
|
247
|
+
def generated_grammarkit?
|
|
248
|
+
return false unless extname == '.java'
|
|
249
|
+
return false unless lines.count > 1
|
|
250
|
+
return lines[0].start_with?("// This is a generated file. Not intended for manual editing.")
|
|
251
|
+
end
|
|
252
|
+
def generated_roxygen2?
|
|
253
|
+
return false unless extname == '.Rd'
|
|
254
|
+
return false unless lines.count > 1 return lines[0].include?("% Generated by roxygen2: do not edit by hand")
|
|
255
|
+
end
|
|
256
|
+
def generated_jison?
|
|
257
|
+
return false unless extname == '.js'
|
|
258
|
+
return false unless lines.count > 1
|
|
259
|
+
return lines[0].start_with?("/* parser generated by jison ") ||
|
|
260
|
+
lines[0].start_with?("/* generated by jison-lex ")
|
|
261
|
+
end
|
|
262
|
+
def generated_grpc_cpp?
|
|
263
|
+
return false unless %w{.cpp .hpp .h .cc}.include? extname
|
|
264
|
+
return false unless lines.count > 1
|
|
265
|
+
return lines[0].start_with?("// Generated by the gRPC")
|
|
266
|
+
end
|
|
267
|
+
def generated_dart?
|
|
268
|
+
return false unless extname == '.dart'
|
|
269
|
+
return false unless lines.count > 1
|
|
270
|
+
return lines.first.downcase =~ /generated code\W{2,3}do not modify/
|
|
271
|
+
end
|
|
272
|
+
def generated_perl_ppport_header?
|
|
273
|
+
return false unless name.match(/ppport\.h$/)
|
|
274
|
+
return false unless lines.count > 10
|
|
275
|
+
return lines[8].include?("Automatically created by Devel::PPPort")
|
|
276
|
+
end
|
|
277
|
+
def generated_graphql_relay?
|
|
278
|
+
!!name.match(/__generated__\//)
|
|
279
|
+
end
|
|
280
|
+
def generated_gamemakerstudio?
|
|
281
|
+
return false unless ['.yy', '.yyp'].include? extname
|
|
282
|
+
return false unless lines.count > 3
|
|
283
|
+
return lines[2].match(/\"modelName\"\:\s*\"GM/) ||
|
|
284
|
+
lines[0] =~ /^\d\.\d\.\d.+\|\{/
|
|
285
|
+
end
|
|
286
|
+
def generated_gimp?
|
|
287
|
+
return false unless ['.c', '.h'].include? extname
|
|
288
|
+
return false unless lines.count > 0
|
|
289
|
+
return lines[0].match(/\/\* GIMP [a-zA-Z0-9\- ]+ C\-Source image dump \(.+?\.c\) \*\//) ||
|
|
290
|
+
lines[0].match(/\/\* GIMP header image file format \([a-zA-Z0-9\- ]+\)\: .+?\.h \*\//)
|
|
291
|
+
end
|
|
292
|
+
def generated_visualstudio6?
|
|
293
|
+
return false unless extname.downcase == '.dsp'
|
|
294
|
+
lines.first(3).any? { |l| l.include? '# Microsoft Developer Studio Generated Build File' }
|
|
295
|
+
end HAXE_EXTENSIONS = ['.js', '.py', '.lua', '.cpp', '.h', '.java', '.cs', '.php']
|
|
296
|
+
def generated_haxe?
|
|
297
|
+
return false unless HAXE_EXTENSIONS.include?(extname)
|
|
298
|
+
return lines.first(3).any? { |l| l.include?("Generated by Haxe") }
|
|
299
|
+
end
|
|
300
|
+
def generated_html?
|
|
301
|
+
return false unless ['.html', '.htm', '.xhtml'].include? extname.downcase
|
|
302
|
+
return false unless lines.count > 1
|
|
303
|
+
return true if lines[0..1].any? do |line|
|
|
304
|
+
line.match(/<!-- Generated by pkgdown: do not edit by hand -->/)
|
|
305
|
+
end
|
|
306
|
+
return true if lines.count > 2 && lines[2].start_with?('<!-- This is an automatically generated file.')
|
|
307
|
+
return true if lines[0..30].any? do |line|
|
|
308
|
+
line.match(/<!--\s+Generated by Doxygen\s+[.0-9]+\s*-->/i)
|
|
309
|
+
end
|
|
310
|
+
matches = lines[0..30].join(' ').scan(/<meta(\s+[^>]++)>/i)
|
|
311
|
+
return false if matches.empty?
|
|
312
|
+
return matches.map {|x| extract_html_meta(x) }.any? do |attr|
|
|
313
|
+
attr["name"].to_s.downcase == 'generator' &&
|
|
314
|
+
[attr["content"], attr["value"]].any? do |cv|
|
|
315
|
+
!cv.nil? &&
|
|
316
|
+
cv.match(/^
|
|
317
|
+
( org \s+ mode
|
|
318
|
+
| j?latex2html
|
|
319
|
+
| groff
|
|
320
|
+
| makeinfo
|
|
321
|
+
| texi2html
|
|
322
|
+
| ronn
|
|
323
|
+
) \b
|
|
324
|
+
/ix)
|
|
325
|
+
end
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
def generated_jooq?
|
|
329
|
+
return false unless extname.downcase == '.java'
|
|
330
|
+
lines.first(2).any? { |l| l.include? 'This file is generated by jOOQ.' }
|
|
331
|
+
end
|
|
332
|
+
def generated_pascal_tlb?
|
|
333
|
+
!!name.match(/_tlb\.pas$/i)
|
|
334
|
+
end
|
|
335
|
+
def extract_html_meta(match)
|
|
336
|
+
(match.last.sub(/\/\Z/, "").strip.scan(/
|
|
337
|
+
(?<=^|\s)
|
|
338
|
+
(name|content|value)
|
|
339
|
+
\s* = \s*
|
|
340
|
+
( "[^"]+"
|
|
341
|
+
| '[^']+'
|
|
342
|
+
| [^\s"']+
|
|
343
|
+
)
|
|
344
|
+
/ix)).map do |match|
|
|
345
|
+
key = match[0].downcase
|
|
346
|
+
val = match[1].gsub(/\A["']|["']\Z/, '')
|
|
347
|
+
[key, val]
|
|
348
|
+
end.select { |x| x.length == 2 }.to_h
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
end
|