metascope 0.6.3 → 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.
Files changed (66) hide show
  1. package/dist/bin/chunk-Bdh3yLIe.js +1 -0
  2. package/dist/bin/cli.js +282 -281
  3. package/dist/bin/dns-CUigd8AG.js +1 -0
  4. package/dist/bin/{jiti-D2Njwwqq.js → jiti-BTBDwj9g.js} +2 -2
  5. package/dist/bin/renovate-DecR7mby.js +1 -0
  6. package/dist/bin/shared-C_yS1qGF.js +5 -0
  7. package/dist/lib/file-matching.js +20 -13
  8. package/dist/lib/log.d.ts +6 -4
  9. package/dist/lib/log.js +5 -3
  10. package/dist/lib/metadata-types.d.ts +33 -21
  11. package/dist/lib/metadata-types.js +8 -9
  12. package/dist/lib/metadata.js +7 -7
  13. package/dist/lib/package.js +1 -1
  14. package/dist/lib/parsers/gemspec-parser.js +16 -14
  15. package/dist/lib/parsers/go-mod-parser.js +13 -10
  16. package/dist/lib/parsers/makefile-config-parser.js +20 -17
  17. package/dist/lib/parsers/properties-parser.js +3 -3
  18. package/dist/lib/parsers/rfc822-header-parser.js +4 -4
  19. package/dist/lib/parsers/setup-py-parser.js +3 -4
  20. package/dist/lib/source.d.ts +1 -0
  21. package/dist/lib/source.js +5 -4
  22. package/dist/lib/sources/arduino-library-properties.js +32 -15
  23. package/dist/lib/sources/cinder-cinderblock-xml.js +21 -9
  24. package/dist/lib/sources/codemeta-json.js +24 -20
  25. package/dist/lib/sources/dependency-updates.js +12 -23
  26. package/dist/lib/sources/git-stats.js +1 -1
  27. package/dist/lib/sources/github-actions.js +9 -2
  28. package/dist/lib/sources/github.js +1 -1
  29. package/dist/lib/sources/go-goreleaser-yaml.js +5 -4
  30. package/dist/lib/sources/java-pom-xml.js +38 -19
  31. package/dist/lib/sources/license-file.d.ts +1 -4
  32. package/dist/lib/sources/license-file.js +1 -4
  33. package/dist/lib/sources/metadata-file.js +15 -12
  34. package/dist/lib/sources/node-npm-registry.js +1 -1
  35. package/dist/lib/sources/openframeworks-addon-config-mk.js +7 -0
  36. package/dist/lib/sources/openframeworks-install-xml.js +24 -14
  37. package/dist/lib/sources/processing-library-properties.js +25 -10
  38. package/dist/lib/sources/processing-sketch-properties.js +51 -7
  39. package/dist/lib/sources/publiccode-yaml.js +37 -5
  40. package/dist/lib/sources/python-pkg-info.js +2 -2
  41. package/dist/lib/sources/python-setup-cfg.js +2 -2
  42. package/dist/lib/sources/readme-file.js +9 -2
  43. package/dist/lib/sources/ruby-gemspec.js +1 -0
  44. package/dist/lib/sources/rust-cargo-toml.js +29 -10
  45. package/dist/lib/sources/xcode-info-plist.js +48 -24
  46. package/dist/lib/sources/xcode-project-pbxproj.js +22 -12
  47. package/dist/lib/templates/codemeta-json.d.ts +4 -5
  48. package/dist/lib/templates/codemeta-json.js +4 -5
  49. package/dist/lib/templates/codemeta.js +30 -30
  50. package/dist/lib/templates/frontmatter.d.ts +1 -1
  51. package/dist/lib/templates/index.d.ts +1 -1
  52. package/dist/lib/templates/metadata.d.ts +2 -2
  53. package/dist/lib/templates/metadata.js +3 -3
  54. package/dist/lib/utilities/codemeta-helpers.d.ts +3 -2
  55. package/dist/lib/utilities/codemeta-helpers.js +14 -12
  56. package/dist/lib/utilities/fetch.js +2 -2
  57. package/dist/lib/utilities/formatting.js +4 -3
  58. package/dist/lib/utilities/github.js +3 -3
  59. package/dist/lib/utilities/license-identification.d.ts +25 -0
  60. package/dist/lib/utilities/license-identification.js +132 -29
  61. package/dist/lib/utilities/schema-primitives.js +11 -10
  62. package/dist/lib/utilities/template-helpers.js +3 -3
  63. package/package.json +19 -18
  64. package/readme.md +23 -19
  65. package/dist/.DS_Store +0 -0
  66. package/dist/bin/chunk-BjEoQXZ0.js +0 -1
@@ -8,45 +8,72 @@ import spdxLicenseList from "spdx-license-list/full.js";
8
8
  * SPDX license URL (e.g. "https://spdx.org/licenses/MIT").
9
9
  *
10
10
  * Handles:
11
- * - Standard license texts (MIT, BSD, Apache, etc.)
12
- * - GNU family licenses via header pattern matching (LGPL, AGPL)
13
- * - Markdown-formatted license files (strips headings, tables, links)
14
- * - YAML front matter stripping
11
+ *
12
+ * - Canonical SPDX / vendor URLs embedded in pointer-style license files
13
+ * - Standard license texts (MIT, BSD, Apache, etc.)
14
+ * - GNU family licenses via header pattern matching (LGPL, AGPL)
15
+ * - Markdown-formatted license files (strips headings, tables, links)
16
+ * - YAML front matter stripping
15
17
  */
18
+ const SPDX_BASE_URL = "https://spdx.org/licenses/";
16
19
  /** Minimum similarity score to consider a match. */
17
20
  const CONFIDENCE_THRESHOLD = .75;
18
21
  /**
19
- * Identify the SPDX license that best matches the given text.
20
- * Returns the best match with confidence score, or undefined if no match
21
- * exceeds the confidence threshold.
22
+ * Identify the SPDX license that best matches the given text. Returns the best
23
+ * match with confidence score, or undefined if no match exceeds the confidence
24
+ * threshold.
22
25
  */
23
26
  function identifyLicense(text) {
27
+ const urlMatch = identifyByUrl(text);
28
+ if (urlMatch) return urlMatch;
24
29
  const headerMatch = identifyByHeader(text);
25
30
  if (headerMatch) return headerMatch;
26
31
  const normalizedInput = normalizeInput(text);
27
- if (normalizedInput.length < 2) return void 0;
32
+ if (normalizedInput.length < 2) return;
28
33
  const inputBigramsMap = computeBigrams(normalizedInput);
29
34
  const inputTotal = normalizedInput.length - 1;
30
35
  let bestMatch;
31
36
  let bestScore = 0;
32
37
  for (const { bigramsMap, normalized, spdxId, totalBigrams } of getNormalizedLicenses()) {
33
- if (normalizedInput === normalized) return {
34
- confidence: 1,
35
- spdxId
36
- };
38
+ if (normalizedInput === normalized) return buildMatch(spdxId, 1);
37
39
  const score = diceCoefficientCached(inputBigramsMap, inputTotal, bigramsMap, totalBigrams);
38
40
  if (score > bestScore) {
39
41
  bestScore = score;
40
- bestMatch = {
41
- confidence: score,
42
- spdxId
43
- };
42
+ bestMatch = buildMatch(spdxId, score);
44
43
  if (bestScore > .98) break;
45
44
  }
46
45
  }
47
46
  if (bestMatch && bestMatch.confidence >= CONFIDENCE_THRESHOLD) return bestMatch;
48
47
  }
49
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
+ /**
62
+ * Convert an SPDX license identifier to its canonical SPDX URL.
63
+ */
64
+ function spdxIdToUrl(spdxId) {
65
+ return `${SPDX_BASE_URL}${spdxId}`;
66
+ }
67
+ /**
68
+ * Resolve the canonical URL for an SPDX license ID. Prefers the upstream URL
69
+ * recorded in the SPDX list (e.g. `https://opensource.org/license/mit/`) and
70
+ * falls back to the SPDX registry URL for the handful of entries whose upstream
71
+ * URL is missing at runtime.
72
+ */
73
+ function getLicenseUrl(spdxId) {
74
+ return spdxLicenseList[spdxId]?.url ?? spdxIdToUrl(spdxId);
75
+ }
76
+ /**
50
77
  * Strip YAML front matter (--- delimited blocks at the start of a file).
51
78
  */
52
79
  function stripFrontMatter(text) {
@@ -57,16 +84,15 @@ function stripFrontMatter(text) {
57
84
  return text;
58
85
  }
59
86
  /**
60
- * Normalize license text for comparison.
61
- * Follows SPDX matching guidelines: collapse whitespace, strip copyright lines,
62
- * remove URLs, lowercase.
87
+ * Normalize license text for comparison. Follows SPDX matching guidelines:
88
+ * collapse whitespace, strip copyright lines, remove URLs, lowercase.
63
89
  */
64
90
  function normalizeText(text) {
65
91
  return text.replaceAll(/^#+\s+/gm, "").replaceAll(/^copyright.*$/gim, "").replaceAll(/^\|.*\|$/gm, "").replaceAll(/^[-|:\s]+$/gm, "").replaceAll(/https?:\/\/\S+/g, "").replaceAll(/\S+@\S+/g, "").replaceAll(/[[\]()]/g, " ").replaceAll(/\s+/g, " ").trim().toLowerCase();
66
92
  }
67
93
  /**
68
- * Normalize input text (user-provided license file).
69
- * Applies additional cleanup beyond what reference texts need.
94
+ * Normalize input text (user-provided license file). Applies additional cleanup
95
+ * beyond what reference texts need.
70
96
  */
71
97
  function normalizeInput(text) {
72
98
  return normalizeText(stripFrontMatter(text));
@@ -108,10 +134,10 @@ function diceCoefficientCached(inputBigrams, inputTotal, referenceBigrams, refer
108
134
  }
109
135
  /**
110
136
  * Title-based identification for GNU licenses whose SPDX templates embed
111
- * combined texts (e.g. LGPL-3.0-only = LGPL supplement + full GPL), making
112
- * Dice coefficient unreliable against real-world standalone files.
113
- * Only checks the first 500 characters to avoid matching references in
114
- * unrelated license texts (e.g. CeCILL-2.1 mentions AGPL in its body).
137
+ * combined texts (e.g. LGPL-3.0-only = LGPL supplement + full GPL), making Dice
138
+ * coefficient unreliable against real-world standalone files. Only checks the
139
+ * first 500 characters to avoid matching references in unrelated license texts
140
+ * (e.g. CeCILL-2.1 mentions AGPL in its body).
115
141
  */
116
142
  const HEADER_PATTERNS = [
117
143
  {
@@ -133,10 +159,87 @@ const HEADER_PATTERNS = [
133
159
  ];
134
160
  function identifyByHeader(text) {
135
161
  const header = text.slice(0, 500);
136
- for (const { pattern, spdxId } of HEADER_PATTERNS) if (pattern.test(header)) return {
137
- confidence: 1,
138
- spdxId
139
- };
162
+ for (const { pattern, spdxId } of HEADER_PATTERNS) if (pattern.test(header)) return buildMatch(spdxId, 1);
163
+ }
164
+ /**
165
+ * Extracts `http(s)://...` URLs from the raw text, stripping trailing
166
+ * punctuation that commonly follows a URL in prose (`.`, `,`, `)`, `]`, etc.)
167
+ * but is not part of the URL itself.
168
+ */
169
+ const URL_REGEX = /https?:\/\/[^\s<>"')\]}]+/gi;
170
+ /** Leading `www.` subdomain. */
171
+ const WWW_PREFIX_REGEX = /^www\./;
172
+ /** Trailing `/legalcode` or `/legalcode.<ext>` on Creative Commons URLs. */
173
+ const LEGALCODE_SUFFIX_REGEX = /\/legalcode(?:\.[a-z]+)?$/;
174
+ /** Trailing slashes. */
175
+ const TRAILING_SLASH_REGEX = /\/+$/;
176
+ /** Trailing prose punctuation after a URL extracted from text. */
177
+ const TRAILING_PUNCTUATION_REGEX = /[.,;:!?]+$/;
178
+ /**
179
+ * Normalize a URL for comparison: lowercase host+path, drop scheme, strip
180
+ * `www.`, strip trailing slashes, and strip trailing `/legalcode(.ext)?`
181
+ * suffixes used by Creative Commons canonical URLs.
182
+ */
183
+ function normalizeUrl(url) {
184
+ let parsed;
185
+ try {
186
+ parsed = new URL(url.trim());
187
+ } catch {
188
+ return;
189
+ }
190
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return;
191
+ const host = parsed.hostname.toLowerCase().replace(WWW_PREFIX_REGEX, "");
192
+ let path = parsed.pathname.toLowerCase().replace(LEGALCODE_SUFFIX_REGEX, "");
193
+ path = path.replace(TRAILING_SLASH_REGEX, "");
194
+ return `${host}${path}`;
195
+ }
196
+ /**
197
+ * Rank an SPDX ID by how "current" its form is, higher is preferred. Used to
198
+ * break ties when multiple IDs share a canonical URL.
199
+ */
200
+ function scoreSpdxId(id) {
201
+ if (id.endsWith("+")) return 0;
202
+ if (id.endsWith("-only")) return 3;
203
+ if (id.endsWith("-or-later")) return 2;
204
+ return 1;
205
+ }
206
+ /**
207
+ * When multiple SPDX IDs share a canonical URL (typically deprecated legacy
208
+ * forms alongside current `-only` / `-or-later` variants), pick the current
209
+ * non-deprecated form.
210
+ */
211
+ function preferSpdxId(a, b) {
212
+ const sa = scoreSpdxId(a);
213
+ const sb = scoreSpdxId(b);
214
+ if (sa !== sb) return sa > sb ? a : b;
215
+ return a < b ? a : b;
216
+ }
217
+ /** Lazy index of normalized URL → preferred SPDX ID. */
218
+ let urlIndex;
219
+ function getUrlIndex() {
220
+ if (urlIndex) return urlIndex;
221
+ const index = /* @__PURE__ */ new Map();
222
+ for (const [spdxId, entry] of Object.entries(spdxLicenseList)) {
223
+ index.set(`spdx.org/licenses/${spdxId.toLowerCase()}`, spdxId);
224
+ if (!entry.url) continue;
225
+ const normalized = normalizeUrl(entry.url);
226
+ if (!normalized) continue;
227
+ const existing = index.get(normalized);
228
+ index.set(normalized, existing ? preferSpdxId(existing, spdxId) : spdxId);
229
+ }
230
+ urlIndex = index;
231
+ return index;
232
+ }
233
+ function identifyByUrl(text) {
234
+ const matches = text.match(URL_REGEX);
235
+ if (!matches) return;
236
+ const index = getUrlIndex();
237
+ for (const raw of matches) {
238
+ const normalized = normalizeUrl(raw.replace(TRAILING_PUNCTUATION_REGEX, ""));
239
+ if (!normalized) continue;
240
+ const spdxId = index.get(normalized);
241
+ if (spdxId) return buildMatch(spdxId, 1);
242
+ }
140
243
  }
141
244
  //#endregion
142
245
  export { identifyLicense };
@@ -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
- * - Empty/whitespace-only strings → undefined
9
- * - URL validation with empty → undefined fallback
10
- * - String arrays with empty-element filtering
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
- * Use `.optional()` on the result for optional fields.
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
- * Does not reject invalid URLs — just ensures non-empty.
24
- * Use z.url() in place of this if strict URL validation is desired.
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
- * Returns `undefined` for malformed JSON or non-object values (arrays, primitives).
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 void 0;
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 void 0;
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 void 0;
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.6.3",
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",
@@ -44,14 +44,14 @@
44
44
  "dependencies": {
45
45
  "@bacons/xcode": "1.0.0-alpha.33",
46
46
  "@kitschpatrol/tokei": "^2.0.1",
47
- "@sindresorhus/is": "^7.2.0",
47
+ "@sindresorhus/is": "^8.0.0",
48
48
  "@types/mdast": "^4.0.4",
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.0",
53
- "defu": "^6.1.6",
54
- "fast-xml-parser": "^5.5.10",
52
+ "case-police": "^2.2.1",
53
+ "defu": "^6.1.7",
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.0",
64
- "plist": "^3.1.0",
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.35.2",
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
- "tinyexec": "^1.0.4",
75
- "tinyglobby": "^0.2.15",
74
+ "tinyexec": "^1.1.1",
75
+ "tinyglobby": "^0.2.16",
76
76
  "unified": "^11.0.5",
77
- "updates": "^17.13.5",
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,21 +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.1.0",
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": "^2.1.1",
92
+ "mdat-plugin-cli-help": "^3.0.0",
93
93
  "msw": "2.12.14",
94
94
  "publint": "^0.3.18",
95
+ "shx": "^0.4.0",
95
96
  "tree-sitter-python": "^0.25.0",
96
97
  "tree-sitter-ruby": "^0.23.1",
97
- "tsdown": "^0.21.7",
98
+ "tsdown": "^0.21.10",
98
99
  "tsx": "^4.21.0",
99
- "typescript": "~5.9.3",
100
- "vitest": "^4.1.2"
100
+ "typescript": "~6.0.3",
101
+ "vitest": "^4.1.5"
101
102
  },
102
103
  "engines": {
103
104
  "node": ">=22.17.0"
@@ -112,11 +113,11 @@
112
113
  "bench": "vitest bench --run --no-file-parallelism --compare test/benchmarks/baseline.json",
113
114
  "bench:baseline": "vitest bench --run --no-file-parallelism --outputJson test/benchmarks/baseline.json",
114
115
  "build": "tsdown",
115
- "clean": "git rm -f pnpm-lock.yaml ; git clean -fdX",
116
+ "clean": "shx rm -f pnpm-lock.yaml && git clean -fdX -e !.claude/",
116
117
  "docs": "tsx ./scripts/generate-examples.ts && ksc-prettier fix ./docs",
117
118
  "fix": "ksc fix",
118
119
  "lint": "ksc lint",
119
- "release": "bumpp --commit 'Release: %s' && pnpm run build && NPM_AUTH_TOKEN=$(op read 'op://Personal/npm/token') && pnpm publish",
120
+ "release": "bumpp --commit 'Release: %s' && pnpm build && NPM_AUTH_TOKEN=$(op read 'op://Personal/npm/token') && pnpm publish",
120
121
  "pretest": "tsx scripts/copy-grammars.ts",
121
122
  "test": "vitest run",
122
123
  "test:live": "METASCOPE_TEST_MOCK=false vitest run"
package/readme.md CHANGED
@@ -108,21 +108,21 @@ metascope [path]
108
108
  | ------------------- | ---------------------- | -------- | ------- |
109
109
  | `path` | Project directory path | `string` | `"."` |
110
110
 
111
- | Option | Description | Type | Default |
112
- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------- | ------- |
113
- | `--template`<br>`-t` | Built-in template name (`codemeta`, `codemetaJson`, `frontmatter`, `metadata`, `project`) or path to a custom template file | `string` | |
114
- | `--github-token` | GitHub API token (or set `$GITHUB_TOKEN`) | `string` | |
115
- | `--author-name` | Optional author name(s) for ownership checks in templates | `array` | |
116
- | `--github-account` | Optional GitHub account name(s) for ownership checks in templates | `array` | |
117
- | `--absolute` | Output absolute paths. Use `--no-absolute` for relative paths. | `boolean` | `true` |
118
- | `--offline` | Skip sources requiring network requests | `boolean` | `false` |
119
- | `--sources`<br>`-s` | Only run specific metadata sources (defaults to all) | `array` | |
120
- | `--no-ignore` | Include files ignored by .gitignore in the file tree | `boolean` | `false` |
121
- | `--recursive`<br>`-r` | Search for metadata files recursively in subdirectories | `boolean` | `false` |
122
- | `--workspaces`<br>`-w` | Include workspace-specific metadata in monorepos; pass a `boolean` to enable or disable auto-detection, or pass one or more `string`s to explicitly define workspace paths | | `true` |
123
- | `--verbose` | Run with verbose logging | `boolean` | `false` |
124
- | `--help`<br>`-h` | Show help | `boolean` | |
125
- | `--version`<br>`-v` | Show version number | `boolean` | |
111
+ | Option | Description | Type | Default |
112
+ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------- | ------- |
113
+ | `--template`<br>`-t` | Built-in template name (`codemeta`, `codemetaJson`, `frontmatter`, `metadata`, `project`) or path to a custom template file | `string` | |
114
+ | `--github-token` | GitHub API token (or set `$GITHUB_TOKEN`) | `string` | |
115
+ | `--author-name` | Optional author name(s) for ownership checks in templates | `array` | |
116
+ | `--github-account` | Optional GitHub account name(s) for ownership checks in templates | `array` | |
117
+ | `--absolute` | Output absolute paths. Use `--no-absolute` for relative paths. | `boolean` | `true` |
118
+ | `--offline` | Skip sources requiring network requests | `boolean` | `false` |
119
+ | `--sources`<br>`-s` | Only run specific metadata sources (`arduino-library-properties`, `cinder-cinderblock-xml`, `codemeta-json`, `git-config`, `go-go-mod`, `go-goreleaser-yaml`, `java-pom-xml`, `license-file`, `metadata-file`, `metascope`, `node-package-json`, `obsidian-plugin-manifest-json`, `openframeworks-addon-config-mk`, `openframeworks-install-xml`, `processing-library-properties`, `processing-sketch-properties`, `publiccode-yaml`, `python-pkg-info`, `python-pyproject-toml`, `python-setup-cfg`, `python-setup-py`, `readme-file`, `ruby-gemspec`, `rust-cargo-toml`, `xcode-info-plist`, `xcode-project-pbxproj`, `github-actions`, `code-stats`, `dependency-updates`, `file-stats`, `git-stats`, `github`, `node-npm-registry`, `obsidian-plugin-registry`, `python-pypi-registry`); defaults to all | `array` | |
120
+ | `--no-ignore` | Include files ignored by .gitignore in the file tree | `boolean` | `false` |
121
+ | `--recursive`<br>`-r` | Search for metadata files recursively in subdirectories | `boolean` | `false` |
122
+ | `--workspaces`<br>`-w` | Include workspace-specific metadata in monorepos; pass a `boolean` to enable or disable auto-detection, or pass one or more `string`s to explicitly define workspace paths | | `true` |
123
+ | `--verbose` | Run with verbose logging | `boolean` | `false` |
124
+ | `--help`<br>`-h` | Show help | `boolean` | |
125
+ | `--version`<br>`-v` | Show version number | `boolean` | |
126
126
 
127
127
  <!-- /cli-help -->
128
128
 
@@ -193,7 +193,7 @@ export default defineTemplate(({ codemetaJson, github, gitStats }) => {
193
193
  Extract metadata from only the sources you need, skipping everything else for faster results:
194
194
 
195
195
  ```sh
196
- metascope --sources nodePackageJson gitStats
196
+ metascope --sources node-package-json git-stats
197
197
  ```
198
198
 
199
199
  ##### Pipe compact JSON to another tool
@@ -583,7 +583,7 @@ The architecture and non-boilerplate parts of the documentation were human-drive
583
583
 
584
584
  ## Maintainers
585
585
 
586
- [@kitschpatrol](https://github.com/kitschpatrol)
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) and pull requests are welcome.
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};