metascope 0.7.0 → 0.7.1
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/bin/chunk-Bdh3yLIe.js +1 -0
- package/dist/bin/cli.js +271 -272
- package/dist/bin/dns-CUigd8AG.js +1 -0
- package/dist/bin/{jiti-D2Njwwqq.js → jiti-BTBDwj9g.js} +2 -2
- package/dist/bin/renovate-DecR7mby.js +1 -0
- package/dist/bin/shared-C_yS1qGF.js +5 -0
- package/dist/lib/file-matching.js +20 -13
- package/dist/lib/log.d.ts +6 -4
- package/dist/lib/log.js +5 -3
- package/dist/lib/metadata-types.d.ts +33 -21
- package/dist/lib/metadata-types.js +8 -9
- package/dist/lib/metadata.js +7 -7
- package/dist/lib/package.js +1 -1
- package/dist/lib/parsers/gemspec-parser.js +16 -14
- package/dist/lib/parsers/go-mod-parser.js +13 -10
- package/dist/lib/parsers/makefile-config-parser.js +20 -17
- package/dist/lib/parsers/properties-parser.js +3 -3
- package/dist/lib/parsers/rfc822-header-parser.js +4 -4
- package/dist/lib/parsers/setup-py-parser.js +3 -4
- package/dist/lib/source.d.ts +1 -0
- package/dist/lib/source.js +5 -4
- package/dist/lib/sources/arduino-library-properties.js +32 -15
- package/dist/lib/sources/cinder-cinderblock-xml.js +21 -9
- package/dist/lib/sources/codemeta-json.js +24 -20
- package/dist/lib/sources/git-stats.js +1 -1
- package/dist/lib/sources/github-actions.js +9 -2
- package/dist/lib/sources/github.js +1 -1
- package/dist/lib/sources/go-goreleaser-yaml.js +5 -4
- package/dist/lib/sources/java-pom-xml.js +38 -19
- package/dist/lib/sources/metadata-file.js +15 -12
- package/dist/lib/sources/node-npm-registry.js +1 -1
- package/dist/lib/sources/openframeworks-addon-config-mk.js +7 -0
- package/dist/lib/sources/openframeworks-install-xml.js +24 -14
- package/dist/lib/sources/processing-library-properties.js +25 -10
- package/dist/lib/sources/processing-sketch-properties.js +51 -7
- package/dist/lib/sources/publiccode-yaml.js +37 -5
- package/dist/lib/sources/python-pkg-info.js +2 -2
- package/dist/lib/sources/python-setup-cfg.js +2 -2
- package/dist/lib/sources/readme-file.js +9 -2
- package/dist/lib/sources/ruby-gemspec.js +1 -0
- package/dist/lib/sources/rust-cargo-toml.js +29 -10
- package/dist/lib/sources/xcode-info-plist.js +48 -24
- package/dist/lib/sources/xcode-project-pbxproj.js +22 -12
- package/dist/lib/templates/codemeta-json.d.ts +4 -5
- package/dist/lib/templates/codemeta-json.js +4 -5
- package/dist/lib/templates/codemeta.js +30 -30
- package/dist/lib/templates/metadata.d.ts +2 -2
- package/dist/lib/templates/metadata.js +3 -3
- package/dist/lib/utilities/codemeta-helpers.d.ts +3 -2
- package/dist/lib/utilities/codemeta-helpers.js +14 -12
- package/dist/lib/utilities/fetch.js +2 -2
- package/dist/lib/utilities/formatting.js +4 -3
- package/dist/lib/utilities/github.js +3 -3
- package/dist/lib/utilities/license-identification.d.ts +3 -1
- package/dist/lib/utilities/license-identification.js +21 -25
- package/dist/lib/utilities/schema-primitives.js +11 -10
- package/dist/lib/utilities/template-helpers.js +3 -3
- package/package.json +12 -12
- package/readme.md +7 -3
- package/dist/.DS_Store +0 -0
- package/dist/bin/chunk-BjEoQXZ0.js +0 -1
|
@@ -29,31 +29,36 @@ function identifyLicense(text) {
|
|
|
29
29
|
const headerMatch = identifyByHeader(text);
|
|
30
30
|
if (headerMatch) return headerMatch;
|
|
31
31
|
const normalizedInput = normalizeInput(text);
|
|
32
|
-
if (normalizedInput.length < 2) return
|
|
32
|
+
if (normalizedInput.length < 2) return;
|
|
33
33
|
const inputBigramsMap = computeBigrams(normalizedInput);
|
|
34
34
|
const inputTotal = normalizedInput.length - 1;
|
|
35
35
|
let bestMatch;
|
|
36
36
|
let bestScore = 0;
|
|
37
|
-
for (const { bigramsMap, normalized, spdxId,
|
|
38
|
-
if (normalizedInput === normalized) return
|
|
39
|
-
confidence: 1,
|
|
40
|
-
spdxId,
|
|
41
|
-
spdxUrl
|
|
42
|
-
};
|
|
37
|
+
for (const { bigramsMap, normalized, spdxId, totalBigrams } of getNormalizedLicenses()) {
|
|
38
|
+
if (normalizedInput === normalized) return buildMatch(spdxId, 1);
|
|
43
39
|
const score = diceCoefficientCached(inputBigramsMap, inputTotal, bigramsMap, totalBigrams);
|
|
44
40
|
if (score > bestScore) {
|
|
45
41
|
bestScore = score;
|
|
46
|
-
bestMatch =
|
|
47
|
-
confidence: score,
|
|
48
|
-
spdxId,
|
|
49
|
-
spdxUrl
|
|
50
|
-
};
|
|
42
|
+
bestMatch = buildMatch(spdxId, score);
|
|
51
43
|
if (bestScore > .98) break;
|
|
52
44
|
}
|
|
53
45
|
}
|
|
54
46
|
if (bestMatch && bestMatch.confidence >= CONFIDENCE_THRESHOLD) return bestMatch;
|
|
55
47
|
}
|
|
56
48
|
/**
|
|
49
|
+
* Build a LicenseMatch for the given SPDX ID with the supplied confidence.
|
|
50
|
+
*/
|
|
51
|
+
function buildMatch(spdxId, confidence) {
|
|
52
|
+
const entry = spdxLicenseList[spdxId];
|
|
53
|
+
return {
|
|
54
|
+
confidence,
|
|
55
|
+
name: entry.name,
|
|
56
|
+
osiApproved: entry.osiApproved,
|
|
57
|
+
spdxId,
|
|
58
|
+
spdxUrl: getLicenseUrl(spdxId)
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
57
62
|
* Convert an SPDX license identifier to its canonical SPDX URL.
|
|
58
63
|
*/
|
|
59
64
|
function spdxIdToUrl(spdxId) {
|
|
@@ -111,7 +116,6 @@ function getNormalizedLicenses() {
|
|
|
111
116
|
bigramsMap: computeBigrams(normalized),
|
|
112
117
|
normalized,
|
|
113
118
|
spdxId,
|
|
114
|
-
spdxUrl: getLicenseUrl(spdxId),
|
|
115
119
|
totalBigrams: normalized.length - 1
|
|
116
120
|
};
|
|
117
121
|
});
|
|
@@ -155,11 +159,7 @@ const HEADER_PATTERNS = [
|
|
|
155
159
|
];
|
|
156
160
|
function identifyByHeader(text) {
|
|
157
161
|
const header = text.slice(0, 500);
|
|
158
|
-
for (const { pattern, spdxId } of HEADER_PATTERNS) if (pattern.test(header)) return
|
|
159
|
-
confidence: 1,
|
|
160
|
-
spdxId,
|
|
161
|
-
spdxUrl: getLicenseUrl(spdxId)
|
|
162
|
-
};
|
|
162
|
+
for (const { pattern, spdxId } of HEADER_PATTERNS) if (pattern.test(header)) return buildMatch(spdxId, 1);
|
|
163
163
|
}
|
|
164
164
|
/**
|
|
165
165
|
* Extracts `http(s)://...` URLs from the raw text, stripping trailing
|
|
@@ -187,7 +187,7 @@ function normalizeUrl(url) {
|
|
|
187
187
|
} catch {
|
|
188
188
|
return;
|
|
189
189
|
}
|
|
190
|
-
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return
|
|
190
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return;
|
|
191
191
|
const host = parsed.hostname.toLowerCase().replace(WWW_PREFIX_REGEX, "");
|
|
192
192
|
let path = parsed.pathname.toLowerCase().replace(LEGALCODE_SUFFIX_REGEX, "");
|
|
193
193
|
path = path.replace(TRAILING_SLASH_REGEX, "");
|
|
@@ -232,17 +232,13 @@ function getUrlIndex() {
|
|
|
232
232
|
}
|
|
233
233
|
function identifyByUrl(text) {
|
|
234
234
|
const matches = text.match(URL_REGEX);
|
|
235
|
-
if (!matches) return
|
|
235
|
+
if (!matches) return;
|
|
236
236
|
const index = getUrlIndex();
|
|
237
237
|
for (const raw of matches) {
|
|
238
238
|
const normalized = normalizeUrl(raw.replace(TRAILING_PUNCTUATION_REGEX, ""));
|
|
239
239
|
if (!normalized) continue;
|
|
240
240
|
const spdxId = index.get(normalized);
|
|
241
|
-
if (spdxId) return
|
|
242
|
-
confidence: 1,
|
|
243
|
-
spdxId,
|
|
244
|
-
spdxUrl: getLicenseUrl(spdxId)
|
|
245
|
-
};
|
|
241
|
+
if (spdxId) return buildMatch(spdxId, 1);
|
|
246
242
|
}
|
|
247
243
|
}
|
|
248
244
|
//#endregion
|
|
@@ -5,13 +5,14 @@ import { z } from "zod";
|
|
|
5
5
|
* Shared Zod schema primitives for parser schemas.
|
|
6
6
|
*
|
|
7
7
|
* These handle common coercions:
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
*
|
|
9
|
+
* - Empty/whitespace-only strings → undefined
|
|
10
|
+
* - URL validation with empty → undefined fallback
|
|
11
|
+
* - String arrays with empty-element filtering
|
|
11
12
|
*/
|
|
12
13
|
/**
|
|
13
|
-
* A string that treats empty or whitespace-only values as undefined.
|
|
14
|
-
*
|
|
14
|
+
* A string that treats empty or whitespace-only values as undefined. Use
|
|
15
|
+
* `.optional()` on the result for optional fields.
|
|
15
16
|
*/
|
|
16
17
|
const nonEmptyString = z.preprocess((value) => {
|
|
17
18
|
if (typeof value !== "string") return;
|
|
@@ -19,9 +20,9 @@ const nonEmptyString = z.preprocess((value) => {
|
|
|
19
20
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
20
21
|
}, z.string().optional());
|
|
21
22
|
/**
|
|
22
|
-
* A URL string that treats empty/whitespace as undefined.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
23
|
+
* A URL string that treats empty/whitespace as undefined. Does not reject
|
|
24
|
+
* invalid URLs — just ensures non-empty. Use z.url() in place of this if strict
|
|
25
|
+
* URL validation is desired.
|
|
25
26
|
*/
|
|
26
27
|
const optionalUrl = nonEmptyString.describe("A URL string");
|
|
27
28
|
/**
|
|
@@ -32,8 +33,8 @@ const stringArray = z.preprocess((value) => {
|
|
|
32
33
|
return value.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
33
34
|
}, z.array(z.string()));
|
|
34
35
|
/**
|
|
35
|
-
* Parse a JSON string into a plain object.
|
|
36
|
-
*
|
|
36
|
+
* Parse a JSON string into a plain object. Returns `undefined` for malformed
|
|
37
|
+
* JSON or non-object values (arrays, primitives).
|
|
37
38
|
*/
|
|
38
39
|
function parseJsonRecord(content) {
|
|
39
40
|
try {
|
|
@@ -53,7 +53,7 @@ const casePoliceDict = {
|
|
|
53
53
|
* regardless of cardinality.
|
|
54
54
|
*/
|
|
55
55
|
function firstOf(value) {
|
|
56
|
-
if (value === void 0) return
|
|
56
|
+
if (value === void 0) return;
|
|
57
57
|
return Array.isArray(value) ? value[0] : value;
|
|
58
58
|
}
|
|
59
59
|
/**
|
|
@@ -104,7 +104,7 @@ function splitCommaSeparated(value) {
|
|
|
104
104
|
* Join an array of strings with a delimiter, filtering out undefined values.
|
|
105
105
|
*/
|
|
106
106
|
function toDelimitedString(source, delimiter = ", ") {
|
|
107
|
-
if (source === void 0) return
|
|
107
|
+
if (source === void 0) return;
|
|
108
108
|
if (Array.isArray(source)) {
|
|
109
109
|
const filtered = source.filter((s) => s !== void 0);
|
|
110
110
|
return filtered.length > 0 ? filtered.join(delimiter) : void 0;
|
|
@@ -213,7 +213,7 @@ function stripUndefined(value) {
|
|
|
213
213
|
hasKeys = true;
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
|
-
if (!hasKeys) return
|
|
216
|
+
if (!hasKeys) return;
|
|
217
217
|
return result;
|
|
218
218
|
}
|
|
219
219
|
return value;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "metascope",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "A CLI tool and TypeScript library to easily extract metadata from all kinds of software repositories.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"metadata",
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
"@types/node": "~22.17.2",
|
|
50
50
|
"@types/plist": "^3.0.5",
|
|
51
51
|
"@types/yargs": "^17.0.35",
|
|
52
|
-
"case-police": "^2.2.
|
|
52
|
+
"case-police": "^2.2.1",
|
|
53
53
|
"defu": "^6.1.7",
|
|
54
|
-
"fast-xml-parser": "^5.
|
|
54
|
+
"fast-xml-parser": "^5.7.2",
|
|
55
55
|
"find-workspaces": "^0.3.1",
|
|
56
56
|
"git-url-parse": "^16.1.0",
|
|
57
57
|
"gray-matter-es": "^0.2.1",
|
|
@@ -60,21 +60,21 @@
|
|
|
60
60
|
"octokit": "^5.0.5",
|
|
61
61
|
"package-json": "^10.0.1",
|
|
62
62
|
"picomatch": "^4.0.4",
|
|
63
|
-
"pkg-types": "^2.3.
|
|
64
|
-
"plist": "^3.1.
|
|
63
|
+
"pkg-types": "^2.3.1",
|
|
64
|
+
"plist": "^3.1.1",
|
|
65
65
|
"pretty-ms": "^9.3.0",
|
|
66
66
|
"read-pkg": "^10.1.0",
|
|
67
67
|
"read-pyproject": "^0.3.2",
|
|
68
68
|
"remark-parse": "^11.0.0",
|
|
69
69
|
"semver": "^7.7.4",
|
|
70
|
-
"simple-git": "^3.
|
|
70
|
+
"simple-git": "^3.36.0",
|
|
71
71
|
"smol-toml": "^1.6.1",
|
|
72
72
|
"spdx-license-list": "^6.11.0",
|
|
73
73
|
"string-ts": "^2.3.1",
|
|
74
74
|
"tinyexec": "^1.1.1",
|
|
75
75
|
"tinyglobby": "^0.2.16",
|
|
76
76
|
"unified": "^11.0.5",
|
|
77
|
-
"updates": "^17.
|
|
77
|
+
"updates": "^17.16.6",
|
|
78
78
|
"web-tree-sitter": "^0.26.8",
|
|
79
79
|
"yaml": "^2.8.3",
|
|
80
80
|
"yargs": "^18.0.0",
|
|
@@ -83,22 +83,22 @@
|
|
|
83
83
|
"devDependencies": {
|
|
84
84
|
"@arethetypeswrong/core": "^0.18.2",
|
|
85
85
|
"@fast-csv/parse": "^5.0.5",
|
|
86
|
-
"@kitschpatrol/shared-config": "^7.
|
|
86
|
+
"@kitschpatrol/shared-config": "^7.5.2",
|
|
87
87
|
"@types/jsonld": "^1.5.15",
|
|
88
88
|
"@types/picomatch": "^4.0.3",
|
|
89
89
|
"@types/semver": "^7.7.1",
|
|
90
90
|
"bumpp": "^11.0.1",
|
|
91
91
|
"jsonld": "^9.0.0",
|
|
92
|
-
"mdat-plugin-cli-help": "^
|
|
92
|
+
"mdat-plugin-cli-help": "^3.0.0",
|
|
93
93
|
"msw": "2.12.14",
|
|
94
94
|
"publint": "^0.3.18",
|
|
95
95
|
"shx": "^0.4.0",
|
|
96
96
|
"tree-sitter-python": "^0.25.0",
|
|
97
97
|
"tree-sitter-ruby": "^0.23.1",
|
|
98
|
-
"tsdown": "^0.21.
|
|
98
|
+
"tsdown": "^0.21.10",
|
|
99
99
|
"tsx": "^4.21.0",
|
|
100
|
-
"typescript": "~6.0.
|
|
101
|
-
"vitest": "^4.1.
|
|
100
|
+
"typescript": "~6.0.3",
|
|
101
|
+
"vitest": "^4.1.5"
|
|
102
102
|
},
|
|
103
103
|
"engines": {
|
|
104
104
|
"node": ">=22.17.0"
|
package/readme.md
CHANGED
|
@@ -583,7 +583,7 @@ The architecture and non-boilerplate parts of the documentation were human-drive
|
|
|
583
583
|
|
|
584
584
|
## Maintainers
|
|
585
585
|
|
|
586
|
-
[
|
|
586
|
+
[kitschpatrol](https://github.com/kitschpatrol)
|
|
587
587
|
|
|
588
588
|
## Acknowledgments
|
|
589
589
|
|
|
@@ -595,7 +595,11 @@ Jacob Peddicord's [askalono](https://github.com/jpeddicord/askalono) project ins
|
|
|
595
595
|
|
|
596
596
|
## Contributing
|
|
597
597
|
|
|
598
|
-
[Issues](https://github.com/kitschpatrol/metascope/issues)
|
|
598
|
+
[Issues](https://github.com/kitschpatrol/metascope/issues) are welcome and appreciated.
|
|
599
|
+
|
|
600
|
+
Please open an issue to discuss changes before submitting a pull request. Unsolicited PRs (especially AI-generated ones) are unlikely to be merged.
|
|
601
|
+
|
|
602
|
+
This repository uses [@kitschpatrol/shared-config](https://github.com/kitschpatrol/shared-config) (via its `ksc` CLI) for linting and formatting, plus [MDAT](https://github.com/kitschpatrol/mdat) for readme placeholder expansion.
|
|
599
603
|
|
|
600
604
|
<!-- /contributing -->
|
|
601
605
|
|
|
@@ -603,6 +607,6 @@ Jacob Peddicord's [askalono](https://github.com/jpeddicord/askalono) project ins
|
|
|
603
607
|
|
|
604
608
|
## License
|
|
605
609
|
|
|
606
|
-
[MIT](license.txt) © Eric Mika
|
|
610
|
+
[MIT](license.txt) © [Eric Mika](https://ericmika.com)
|
|
607
611
|
|
|
608
612
|
<!-- /license -->
|
package/dist/.DS_Store
DELETED
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{createRequire as e}from"node:module";var t=Object.create,n=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,a=Object.getPrototypeOf,o=Object.prototype.hasOwnProperty,s=(e,t)=>()=>(e&&(t=e(e=0)),t),c=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),l=(e,t)=>{let r={};for(var i in e)n(r,i,{get:e[i],enumerable:!0});return t||n(r,Symbol.toStringTag,{value:`Module`}),r},u=(e,t,a,s)=>{if(t&&typeof t==`object`||typeof t==`function`)for(var c=i(t),l=0,u=c.length,d;l<u;l++)d=c[l],!o.call(e,d)&&d!==a&&n(e,d,{get:(e=>t[e]).bind(null,d),enumerable:!(s=r(t,d))||s.enumerable});return e},d=(e,r,i)=>(i=e==null?{}:t(a(e)),u(r||!e||!e.__esModule?n(i,`default`,{value:e,enumerable:!0}):i,e)),f=e=>o.call(e,`module.exports`)?e[`module.exports`]:u(n({},`__esModule`,{value:!0}),e),p=e(import.meta.url);export{f as a,p as i,s as n,d as o,l as r,c as t};
|