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.
- package/dist/bin/chunk-Bdh3yLIe.js +1 -0
- package/dist/bin/cli.js +282 -281
- 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/dependency-updates.js +12 -23
- 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/license-file.d.ts +1 -4
- package/dist/lib/sources/license-file.js +1 -4
- 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/frontmatter.d.ts +1 -1
- package/dist/lib/templates/index.d.ts +1 -1
- 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 +25 -0
- package/dist/lib/utilities/license-identification.js +132 -29
- package/dist/lib/utilities/schema-primitives.js +11 -10
- package/dist/lib/utilities/template-helpers.js +3 -3
- package/package.json +19 -18
- package/readme.md +23 -19
- package/dist/.DS_Store +0 -0
- package/dist/bin/chunk-BjEoQXZ0.js +0 -1
|
@@ -7,12 +7,19 @@ import { resolve } from "node:path";
|
|
|
7
7
|
import { z } from "zod";
|
|
8
8
|
//#region src/lib/sources/openframeworks-addon-config-mk.ts
|
|
9
9
|
const openframeworksAddonConfigSchema = z.object({
|
|
10
|
+
/** `ADDON_AUTHOR` from `meta:` section. */
|
|
10
11
|
author: nonEmptyString,
|
|
12
|
+
/** `ADDON_DEPENDENCIES` from `common:` section (space-separated addon names). */
|
|
11
13
|
dependencies: stringArray,
|
|
14
|
+
/** `ADDON_DESCRIPTION` from `meta:` section. */
|
|
12
15
|
description: nonEmptyString,
|
|
16
|
+
/** `ADDON_NAME` from `meta:` section. */
|
|
13
17
|
name: nonEmptyString,
|
|
18
|
+
/** Platform section names that contain at least one variable assignment. */
|
|
14
19
|
platformSections: stringArray,
|
|
20
|
+
/** `ADDON_TAGS` from `meta:` section (quote-aware tokenized). */
|
|
15
21
|
tags: stringArray,
|
|
22
|
+
/** `ADDON_URL` from `meta:` section. */
|
|
16
23
|
url: optionalUrl
|
|
17
24
|
});
|
|
18
25
|
/**
|
|
@@ -19,19 +19,29 @@ import { XMLParser } from "fast-xml-parser";
|
|
|
19
19
|
* content is actually an openFrameworks addon by checking for the `<install>`
|
|
20
20
|
* root element and the presence of "addons" in the file content.
|
|
21
21
|
*
|
|
22
|
-
* Uses `fast-xml-parser` with attribute parsing enabled to read `<lib
|
|
23
|
-
* attributes for operating system inference.
|
|
22
|
+
* Uses `fast-xml-parser` with attribute parsing enabled to read `<lib
|
|
23
|
+
* os="...">` attributes for operating system inference.
|
|
24
24
|
*/
|
|
25
25
|
const openframeworksInstallXmlSchema = z.object({
|
|
26
|
+
/** Addon author name. */
|
|
26
27
|
author: nonEmptyString,
|
|
28
|
+
/** Source code repository URL. */
|
|
27
29
|
codeUrl: optionalUrl,
|
|
30
|
+
/** Description of the addon. */
|
|
28
31
|
description: nonEmptyString,
|
|
32
|
+
/** Download URL. */
|
|
29
33
|
downloadUrl: optionalUrl,
|
|
34
|
+
/** Addon display name. */
|
|
30
35
|
name: nonEmptyString,
|
|
36
|
+
/** Supported operating systems from `<lib os="...">` attributes. */
|
|
31
37
|
operatingSystems: stringArray,
|
|
38
|
+
/** Software dependencies from `<requires>` elements. */
|
|
32
39
|
requirements: stringArray,
|
|
40
|
+
/** Website URL. */
|
|
33
41
|
siteUrl: optionalUrl,
|
|
42
|
+
/** Generic URL (used when no code_url / site_url provided). */
|
|
34
43
|
url: optionalUrl,
|
|
44
|
+
/** Version string. */
|
|
35
45
|
version: nonEmptyString
|
|
36
46
|
});
|
|
37
47
|
/**
|
|
@@ -43,9 +53,9 @@ const LIB_OS_MAP = {
|
|
|
43
53
|
win32: "Windows"
|
|
44
54
|
};
|
|
45
55
|
/**
|
|
46
|
-
* Parse a legacy openFrameworks `install.xml` content string into a structured
|
|
47
|
-
* Returns undefined if the XML is malformed, missing the `<install>`
|
|
48
|
-
* or does not appear to be an openFrameworks addon.
|
|
56
|
+
* Parse a legacy openFrameworks `install.xml` content string into a structured
|
|
57
|
+
* object. Returns undefined if the XML is malformed, missing the `<install>`
|
|
58
|
+
* root element, or does not appear to be an openFrameworks addon.
|
|
49
59
|
*/
|
|
50
60
|
function parse(content) {
|
|
51
61
|
if (!content.toLowerCase().includes("addons")) return;
|
|
@@ -58,12 +68,12 @@ function parse(content) {
|
|
|
58
68
|
let data;
|
|
59
69
|
try {
|
|
60
70
|
const parsed = parser.parse(fixedContent);
|
|
61
|
-
if (!is.plainObject(parsed)) return
|
|
71
|
+
if (!is.plainObject(parsed)) return;
|
|
62
72
|
data = parsed;
|
|
63
73
|
} catch {
|
|
64
74
|
return;
|
|
65
75
|
}
|
|
66
|
-
if (!is.plainObject(data.install)) return
|
|
76
|
+
if (!is.plainObject(data.install)) return;
|
|
67
77
|
const { install } = data;
|
|
68
78
|
return openframeworksInstallXmlSchema.parse({
|
|
69
79
|
author: getString(install.author),
|
|
@@ -79,17 +89,17 @@ function parse(content) {
|
|
|
79
89
|
});
|
|
80
90
|
}
|
|
81
91
|
/**
|
|
82
|
-
* Get a trimmed non-empty string from a parsed XML value.
|
|
83
|
-
*
|
|
92
|
+
* Get a trimmed non-empty string from a parsed XML value. Returns undefined for
|
|
93
|
+
* empty strings, non-strings, or whitespace-only values.
|
|
84
94
|
*/
|
|
85
95
|
function getString(value) {
|
|
86
|
-
if (typeof value !== "string") return
|
|
96
|
+
if (typeof value !== "string") return;
|
|
87
97
|
const trimmed = value.trim();
|
|
88
98
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
89
99
|
}
|
|
90
100
|
/**
|
|
91
|
-
* Extract software requirements from `<requires>`.
|
|
92
|
-
*
|
|
101
|
+
* Extract software requirements from `<requires>`. Handles three variants:
|
|
102
|
+
*
|
|
93
103
|
* 1. Empty — skip
|
|
94
104
|
* 2. Free text — emit as-is
|
|
95
105
|
* 3. Structured `<addon>` children — emit each separately
|
|
@@ -112,8 +122,8 @@ function parseRequirements(install) {
|
|
|
112
122
|
return [];
|
|
113
123
|
}
|
|
114
124
|
/**
|
|
115
|
-
* Extract operating system information from `<lib os="...">` attributes
|
|
116
|
-
*
|
|
125
|
+
* Extract operating system information from `<lib os="...">` attributes found
|
|
126
|
+
* within `<add><link>` sections.
|
|
117
127
|
*/
|
|
118
128
|
function parseOperatingSystems(install) {
|
|
119
129
|
if (!is.plainObject(install.add)) return [];
|
|
@@ -35,23 +35,38 @@ const CANONICAL_CATEGORIES = [
|
|
|
35
35
|
const CATEGORY_MAP = new Map(CANONICAL_CATEGORIES.map((cat) => [cat.replaceAll(/[^a-z]/gi, "").toLowerCase(), cat]));
|
|
36
36
|
CATEGORY_MAP.set("3d", "3D");
|
|
37
37
|
const processingLibraryPropertiesSchema = z.object({
|
|
38
|
+
/** Parsed author entries with optional URLs. */
|
|
38
39
|
authors: z.array(processingLibraryPropertiesAuthorEntrySchema),
|
|
40
|
+
/** Normalized categories. */
|
|
39
41
|
categories: z.array(z.enum(CANONICAL_CATEGORIES)),
|
|
42
|
+
/** Direct download URL for the .zip distribution. */
|
|
40
43
|
download: optionalUrl,
|
|
44
|
+
/** Numeric identifier assigned by Processing contribution manager. */
|
|
41
45
|
id: nonEmptyString,
|
|
46
|
+
/** Maximum Processing revision, or 0 for no upper constraint. */
|
|
42
47
|
maxRevision: z.number(),
|
|
48
|
+
/** Minimum Processing revision, or 0 for no lower constraint. */
|
|
43
49
|
minRevision: z.number(),
|
|
50
|
+
/** Library name. */
|
|
44
51
|
name: nonEmptyString,
|
|
52
|
+
/** Extended description paragraph. */
|
|
45
53
|
paragraph: nonEmptyString,
|
|
54
|
+
/** Human-readable version string. */
|
|
46
55
|
prettyVersion: nonEmptyString,
|
|
56
|
+
/** Raw key-value pairs. */
|
|
47
57
|
raw: z.record(z.string(), z.string()),
|
|
58
|
+
/** One-sentence description. */
|
|
48
59
|
sentence: nonEmptyString,
|
|
60
|
+
/** Contribution type (library, tool, mode, examples). */
|
|
49
61
|
type: nonEmptyString,
|
|
62
|
+
/** Project URL. */
|
|
50
63
|
url: optionalUrl,
|
|
64
|
+
/** Integer release counter. */
|
|
51
65
|
version: z.number()
|
|
52
66
|
});
|
|
53
67
|
/**
|
|
54
|
-
* Parse a Processing `library.properties` content string into a structured
|
|
68
|
+
* Parse a Processing `library.properties` content string into a structured
|
|
69
|
+
* object.
|
|
55
70
|
*/
|
|
56
71
|
function parse(content) {
|
|
57
72
|
const raw = parseProperties(content);
|
|
@@ -86,28 +101,28 @@ function get(raw, key) {
|
|
|
86
101
|
}
|
|
87
102
|
/** Return a trimmed string, or undefined if empty/whitespace-only. */
|
|
88
103
|
function nonEmpty(value) {
|
|
89
|
-
if (value === void 0) return
|
|
104
|
+
if (value === void 0) return;
|
|
90
105
|
const trimmed = value.trim();
|
|
91
106
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
92
107
|
}
|
|
93
108
|
/**
|
|
94
|
-
* Strip trailing inline comments from a value.
|
|
95
|
-
*
|
|
109
|
+
* Strip trailing inline comments from a value. Matches the pattern ` # comment
|
|
110
|
+
* text` (space-hash-space).
|
|
96
111
|
*/
|
|
97
112
|
function stripInlineComment(value) {
|
|
98
113
|
const index = value.indexOf(" # ");
|
|
99
114
|
return index === -1 ? value : value.slice(0, index).trim();
|
|
100
115
|
}
|
|
101
116
|
/**
|
|
102
|
-
* Unescape backslash-escaped colons in URLs.
|
|
103
|
-
*
|
|
117
|
+
* Unescape backslash-escaped colons in URLs. Some Processing fixtures use
|
|
118
|
+
* `https\://` instead of `https://`.
|
|
104
119
|
*/
|
|
105
120
|
function unescapeUrl(value) {
|
|
106
121
|
return value.replaceAll(String.raw`\:`, ":");
|
|
107
122
|
}
|
|
108
123
|
/**
|
|
109
|
-
* Parse a Processing authors/authorList value into AuthorEntry[].
|
|
110
|
-
*
|
|
124
|
+
* Parse a Processing authors/authorList value into AuthorEntry[]. Preserves
|
|
125
|
+
* original order of appearance.
|
|
111
126
|
*/
|
|
112
127
|
function parseAuthors(value) {
|
|
113
128
|
const trimmed = value.trim();
|
|
@@ -149,8 +164,8 @@ function parseAuthors(value) {
|
|
|
149
164
|
return results;
|
|
150
165
|
}
|
|
151
166
|
/**
|
|
152
|
-
* Split plain text on `
|
|
153
|
-
*
|
|
167
|
+
* Split plain text on `and`, `,`, `&` to extract author names. Filters out bare
|
|
168
|
+
* "others" entries.
|
|
154
169
|
*/
|
|
155
170
|
function addPlainAuthors(text, results) {
|
|
156
171
|
const parts = text.split(AUTHOR_SEPARATOR_REGEX).map((s) => s.trim()).filter((s) => s.length > 0 && s.toLowerCase() !== "others");
|
|
@@ -13,34 +13,78 @@ const processingSketchPropertiesAuthorEntrySchema = z.object({
|
|
|
13
13
|
url: z.string().optional()
|
|
14
14
|
});
|
|
15
15
|
const processingSketchPropertiesSchema = z.object({
|
|
16
|
+
/**
|
|
17
|
+
* Parsed author entries with optional URLs. _Unofficial: borrowed from
|
|
18
|
+
* library.properties_
|
|
19
|
+
*/
|
|
16
20
|
authors: z.array(processingSketchPropertiesAuthorEntrySchema),
|
|
21
|
+
/** Contributed component type. */
|
|
17
22
|
component: nonEmptyString,
|
|
23
|
+
/** Direct download URL. _Unofficial: borrowed from library.properties_ */
|
|
18
24
|
download: optionalUrl,
|
|
25
|
+
/** Primary .pde filename for the sketch. */
|
|
19
26
|
main: nonEmptyString,
|
|
27
|
+
/** Android app label. From `manifest.label`. */
|
|
20
28
|
manifestLabel: nonEmptyString,
|
|
29
|
+
/**
|
|
30
|
+
* Android screen orientation, e.g. "unspecified". From
|
|
31
|
+
* `manifest.orientation`.
|
|
32
|
+
*/
|
|
21
33
|
manifestOrientation: nonEmptyString,
|
|
34
|
+
/** Android package name. From `manifest.package`. */
|
|
22
35
|
manifestPackage: nonEmptyString,
|
|
36
|
+
/** Android permission list. From `manifest.permissions`. */
|
|
23
37
|
manifestPermissions: z.array(z.string()),
|
|
38
|
+
/** Android minimum SDK level. From `manifest.sdk.min`. */
|
|
24
39
|
manifestSdkMin: z.number().optional(),
|
|
40
|
+
/** Android target SDK level. From `manifest.sdk.target`. */
|
|
25
41
|
manifestSdkTarget: z.number().optional(),
|
|
42
|
+
/** Android version code integer. From `manifest.version.code`. */
|
|
26
43
|
manifestVersionCode: z.number().optional(),
|
|
44
|
+
/** Android version name string. From `manifest.version.name`. */
|
|
27
45
|
manifestVersionName: nonEmptyString,
|
|
46
|
+
/**
|
|
47
|
+
* Maximum Processing revision, or 0 for no upper constraint. _Unofficial:
|
|
48
|
+
* borrowed from library.properties_
|
|
49
|
+
*/
|
|
28
50
|
maxRevision: z.number(),
|
|
51
|
+
/**
|
|
52
|
+
* Minimum Processing revision, or 0 for no lower constraint. _Unofficial:
|
|
53
|
+
* borrowed from library.properties_
|
|
54
|
+
*/
|
|
29
55
|
minRevision: z.number(),
|
|
56
|
+
/** Mode display name, e.g. "Java", "REPL Mode". */
|
|
30
57
|
mode: nonEmptyString,
|
|
58
|
+
/** Mode identifier, e.g. "processing.mode.java.JavaMode". From `mode.id`. */
|
|
31
59
|
modeId: nonEmptyString,
|
|
60
|
+
/** Sketch name. _Unofficial: borrowed from library.properties_ */
|
|
32
61
|
name: nonEmptyString,
|
|
62
|
+
/**
|
|
63
|
+
* Extended description paragraph. _Unofficial: borrowed from
|
|
64
|
+
* library.properties_
|
|
65
|
+
*/
|
|
33
66
|
paragraph: nonEmptyString,
|
|
67
|
+
/**
|
|
68
|
+
* Human-readable version string. _Unofficial: borrowed from
|
|
69
|
+
* library.properties_
|
|
70
|
+
*/
|
|
34
71
|
prettyVersion: nonEmptyString,
|
|
72
|
+
/** Raw key-value pairs. */
|
|
35
73
|
raw: z.record(z.string(), z.string()),
|
|
74
|
+
/** One-sentence description. _Unofficial: borrowed from library.properties_ */
|
|
36
75
|
sentence: nonEmptyString,
|
|
76
|
+
/** Templates string. */
|
|
37
77
|
templates: nonEmptyString,
|
|
78
|
+
/** Project URL. _Unofficial: borrowed from library.properties_ */
|
|
38
79
|
url: optionalUrl,
|
|
80
|
+
/** Integer release counter. _Unofficial: borrowed from library.properties_ */
|
|
39
81
|
version: z.number(),
|
|
82
|
+
/** Zip file name for contributed content. */
|
|
40
83
|
zipfilename: nonEmptyString
|
|
41
84
|
});
|
|
42
85
|
/**
|
|
43
|
-
* Parse a Processing `sketch.properties` content string into a structured
|
|
86
|
+
* Parse a Processing `sketch.properties` content string into a structured
|
|
87
|
+
* object.
|
|
44
88
|
*/
|
|
45
89
|
function parse(content) {
|
|
46
90
|
const raw = parseProperties(content);
|
|
@@ -89,13 +133,13 @@ function parse(content) {
|
|
|
89
133
|
}
|
|
90
134
|
/** Return a trimmed string, or undefined if empty/whitespace-only. */
|
|
91
135
|
function nonEmpty(value) {
|
|
92
|
-
if (value === void 0) return
|
|
136
|
+
if (value === void 0) return;
|
|
93
137
|
const trimmed = value.trim();
|
|
94
138
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
95
139
|
}
|
|
96
140
|
/**
|
|
97
|
-
* Strip trailing inline comments from a value.
|
|
98
|
-
*
|
|
141
|
+
* Strip trailing inline comments from a value. Matches the pattern ` # comment
|
|
142
|
+
* text` (space-hash-space).
|
|
99
143
|
*/
|
|
100
144
|
function stripInlineComment(value) {
|
|
101
145
|
const index = value.indexOf(" # ");
|
|
@@ -150,7 +194,7 @@ function parseAuthors(value) {
|
|
|
150
194
|
return results;
|
|
151
195
|
}
|
|
152
196
|
/**
|
|
153
|
-
* Split plain text on `
|
|
197
|
+
* Split plain text on `and`, `,`, `&` to extract author names.
|
|
154
198
|
*/
|
|
155
199
|
function addPlainAuthors(text, results) {
|
|
156
200
|
const parts = text.split(AUTHOR_SEPARATOR_REGEX).map((s) => s.trim()).filter((s) => s.length > 0 && s.toLowerCase() !== "others");
|
|
@@ -160,8 +204,8 @@ function addPlainAuthors(text, results) {
|
|
|
160
204
|
});
|
|
161
205
|
}
|
|
162
206
|
/**
|
|
163
|
-
* Validate that a sketch.properties file is a Processing sketch.
|
|
164
|
-
*
|
|
207
|
+
* Validate that a sketch.properties file is a Processing sketch. Checks for at
|
|
208
|
+
* least one known Processing sketch key.
|
|
165
209
|
*/
|
|
166
210
|
function isProcessingSketchProperties(content) {
|
|
167
211
|
const raw = parseProperties(content);
|
|
@@ -10,8 +10,8 @@ import { parse } from "yaml";
|
|
|
10
10
|
* Source and parser for `publiccode.yml` / `publiccode.yaml` files.
|
|
11
11
|
*
|
|
12
12
|
* Publiccode.yml is a metadata standard for public software repositories,
|
|
13
|
-
* primarily used in Europe (Italy, Netherlands, etc.).
|
|
14
|
-
*
|
|
13
|
+
* primarily used in Europe (Italy, Netherlands, etc.). See:
|
|
14
|
+
* https://yml.publiccode.tools/
|
|
15
15
|
*
|
|
16
16
|
* Extracts project metadata including name, version, license, contacts,
|
|
17
17
|
* multi-language descriptions, dependencies, and categorization.
|
|
@@ -48,34 +48,63 @@ const publiccodeDescriptionSchema = z.object({
|
|
|
48
48
|
shortDescription: z.string().optional()
|
|
49
49
|
});
|
|
50
50
|
const publiccodeSchema = z.object({
|
|
51
|
+
/** Application suite this software belongs to. */
|
|
51
52
|
applicationSuite: nonEmptyString,
|
|
53
|
+
/** Available localization languages (BCP 47). */
|
|
52
54
|
availableLanguages: stringArray,
|
|
55
|
+
/** Software categories (e.g. "it-security", "cloud-management"). */
|
|
53
56
|
categories: stringArray,
|
|
57
|
+
/** Maintenance contacts. */
|
|
54
58
|
contacts: z.array(publiccodeContactEntrySchema),
|
|
59
|
+
/** Maintenance contractors. */
|
|
55
60
|
contractors: z.array(publiccodeContractorEntrySchema),
|
|
61
|
+
/** Software dependencies (open, proprietary, hardware). */
|
|
56
62
|
dependencies: z.array(publiccodeDependencyEntrySchema),
|
|
63
|
+
/** Preferred description (English if available, else first language). */
|
|
57
64
|
description: publiccodeDescriptionSchema.optional(),
|
|
65
|
+
/** All localized descriptions keyed by language code. */
|
|
58
66
|
descriptions: z.record(z.string(), publiccodeDescriptionSchema),
|
|
67
|
+
/** Development status (concept, development, beta, stable, obsolete). */
|
|
59
68
|
developmentStatus: nonEmptyString,
|
|
69
|
+
/** Supported input MIME types. */
|
|
60
70
|
inputTypes: stringArray,
|
|
71
|
+
/** URL of upstream software this is based on. */
|
|
61
72
|
isBasedOn: optionalUrl,
|
|
73
|
+
/** Landing page URL. */
|
|
62
74
|
landingUrl: optionalUrl,
|
|
75
|
+
/** SPDX license expression. */
|
|
63
76
|
license: nonEmptyString,
|
|
77
|
+
/** Whether the software supports localization. */
|
|
64
78
|
localisationReady: z.boolean().optional(),
|
|
79
|
+
/** Path or URL to logo image. */
|
|
65
80
|
logo: optionalUrl,
|
|
81
|
+
/** Main copyright holder. */
|
|
66
82
|
mainCopyrightOwner: nonEmptyString,
|
|
83
|
+
/** Maintenance type (internal, community, contract, none). */
|
|
67
84
|
maintenanceType: nonEmptyString,
|
|
85
|
+
/** Path or URL to monochrome logo image. */
|
|
68
86
|
monochromeLogo: optionalUrl,
|
|
87
|
+
/** Software name. */
|
|
69
88
|
name: nonEmptyString,
|
|
89
|
+
/** Supported output MIME types. */
|
|
70
90
|
outputTypes: stringArray,
|
|
91
|
+
/** Supported platforms (e.g. "web", "linux", "mac"). */
|
|
71
92
|
platforms: stringArray,
|
|
93
|
+
/** The publiccode.yml schema version. */
|
|
72
94
|
publiccodeYmlVersion: nonEmptyString,
|
|
95
|
+
/** Release date (YYYY-MM-DD). */
|
|
73
96
|
releaseDate: nonEmptyString,
|
|
97
|
+
/** Repository owner name. */
|
|
74
98
|
repoOwner: nonEmptyString,
|
|
99
|
+
/** Roadmap URL. */
|
|
75
100
|
roadmap: optionalUrl,
|
|
101
|
+
/** Software type (e.g. "standalone/web", "standalone/other"). */
|
|
76
102
|
softwareType: nonEmptyString,
|
|
103
|
+
/** Software version string. */
|
|
77
104
|
softwareVersion: nonEmptyString,
|
|
105
|
+
/** Repository URL. */
|
|
78
106
|
url: optionalUrl,
|
|
107
|
+
/** Organizations using this software. */
|
|
79
108
|
usedBy: stringArray
|
|
80
109
|
});
|
|
81
110
|
/** Coerce YAML values that may be parsed as non-strings back to strings. */
|
|
@@ -115,8 +144,11 @@ function parseDescription(data) {
|
|
|
115
144
|
}
|
|
116
145
|
/**
|
|
117
146
|
* Parse a publiccode.yml / publiccode.yaml file content.
|
|
147
|
+
*
|
|
118
148
|
* @param content - Raw YAML file content.
|
|
119
|
-
*
|
|
149
|
+
*
|
|
150
|
+
* @returns Parsed publiccode metadata, or `undefined` if the content is
|
|
151
|
+
* invalid.
|
|
120
152
|
*/
|
|
121
153
|
function parse$1(content) {
|
|
122
154
|
let data;
|
|
@@ -125,8 +157,8 @@ function parse$1(content) {
|
|
|
125
157
|
} catch {
|
|
126
158
|
return;
|
|
127
159
|
}
|
|
128
|
-
if (!isPlainObject(data)) return
|
|
129
|
-
if (!isNonEmptyString(data.name) && !isNonEmptyString(data.url)) return
|
|
160
|
+
if (!isPlainObject(data)) return;
|
|
161
|
+
if (!isNonEmptyString(data.name) && !isNonEmptyString(data.url)) return;
|
|
130
162
|
const descriptions = {};
|
|
131
163
|
let description;
|
|
132
164
|
if (isPlainObject(data.description)) {
|
|
@@ -51,8 +51,8 @@ const HEADER_MAP = {
|
|
|
51
51
|
* Parse a PKG-INFO or METADATA file and return structured metadata.
|
|
52
52
|
*
|
|
53
53
|
* Handles RFC 822-style headers with multi-value fields (Classifier,
|
|
54
|
-
* Requires-Dist, Project-URL, Platform), continuation lines, and
|
|
55
|
-
*
|
|
54
|
+
* Requires-Dist, Project-URL, Platform), continuation lines, and the body
|
|
55
|
+
* section as long_description.
|
|
56
56
|
*/
|
|
57
57
|
function parse(source) {
|
|
58
58
|
const headers = parseRfc822Headers(source);
|
|
@@ -43,8 +43,8 @@ const STRING_ATTRS = new Set([
|
|
|
43
43
|
/**
|
|
44
44
|
* Parse a setup.cfg file and return structured metadata.
|
|
45
45
|
*
|
|
46
|
-
* Extracts fields from the `[metadata]` and `[options]` sections,
|
|
47
|
-
*
|
|
46
|
+
* Extracts fields from the `[metadata]` and `[options]` sections, including
|
|
47
|
+
* multi-line values like classifiers and install_requires.
|
|
48
48
|
*/
|
|
49
49
|
function parse(source) {
|
|
50
50
|
const sections = parseConfigparser(source);
|
|
@@ -8,7 +8,9 @@ import remarkParse from "remark-parse";
|
|
|
8
8
|
import { unified } from "unified";
|
|
9
9
|
//#region src/lib/sources/readme-file.ts
|
|
10
10
|
const readmeSchema = z.object({
|
|
11
|
+
/** YAML frontmatter key-value pairs, if present. */
|
|
11
12
|
frontmatter: z.record(z.string(), z.unknown()).optional(),
|
|
13
|
+
/** Project name extracted from the first H1 heading. */
|
|
12
14
|
name: z.string()
|
|
13
15
|
});
|
|
14
16
|
/**
|
|
@@ -21,7 +23,10 @@ function extractText(nodes) {
|
|
|
21
23
|
return "";
|
|
22
24
|
}).join("").trim();
|
|
23
25
|
}
|
|
24
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Reusable markdown parser — processor config is stateless, only the AST is
|
|
28
|
+
* per-call.
|
|
29
|
+
*/
|
|
25
30
|
const markdownParser = unified().use(remarkParse);
|
|
26
31
|
/**
|
|
27
32
|
* Extract the text content of the first H1 heading from markdown.
|
|
@@ -35,13 +40,15 @@ function extractFirstH1(markdown) {
|
|
|
35
40
|
}
|
|
36
41
|
/**
|
|
37
42
|
* Parse a README file's content.
|
|
43
|
+
*
|
|
38
44
|
* @param content - Raw file content (markdown).
|
|
45
|
+
*
|
|
39
46
|
* @returns Parsed metadata, or `undefined` if no H1 heading is found.
|
|
40
47
|
*/
|
|
41
48
|
function parse(content) {
|
|
42
49
|
const { content: markdown, data } = matter(content);
|
|
43
50
|
const name = extractFirstH1(markdown);
|
|
44
|
-
if (!name) return
|
|
51
|
+
if (!name) return;
|
|
45
52
|
return readmeSchema.parse({
|
|
46
53
|
frontmatter: Object.keys(data).length > 0 ? data : void 0,
|
|
47
54
|
name
|
|
@@ -21,6 +21,7 @@ const gemSpecSchema = z.object({
|
|
|
21
21
|
email: z.union([z.string(), z.array(z.string())]).optional(),
|
|
22
22
|
executables: stringArray,
|
|
23
23
|
extensions: stringArray,
|
|
24
|
+
/** Any attributes not explicitly modeled above */
|
|
24
25
|
extra: z.record(z.string(), z.unknown()),
|
|
25
26
|
extra_rdoc_files: stringArray,
|
|
26
27
|
files: stringArray,
|
|
@@ -8,12 +8,13 @@ import { z } from "zod";
|
|
|
8
8
|
import { parse } from "smol-toml";
|
|
9
9
|
//#region src/lib/sources/rust-cargo-toml.ts
|
|
10
10
|
/**
|
|
11
|
-
* Source for Rust `Cargo.toml` manifest files.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `[
|
|
11
|
+
* Source for Rust `Cargo.toml` manifest files. These are TOML files used by the
|
|
12
|
+
* Cargo package manager. Metadata lives primarily in the `[package]` table,
|
|
13
|
+
* with dependencies in `[dependencies]`, `[dev-dependencies]`, and
|
|
14
|
+
* `[build-dependencies]`.
|
|
15
15
|
*
|
|
16
16
|
* Uses `smol-toml` for TOML parsing.
|
|
17
|
+
*
|
|
17
18
|
* @see https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
18
19
|
*/
|
|
19
20
|
const cargoTomlAuthorEntrySchema = z.object({
|
|
@@ -25,34 +26,52 @@ const cargoTomlDependencyEntrySchema = z.object({
|
|
|
25
26
|
version: z.string().optional()
|
|
26
27
|
});
|
|
27
28
|
const cargoTomlSchema = z.object({
|
|
29
|
+
/** Parsed author entries from `package.authors`. */
|
|
28
30
|
authors: z.array(cargoTomlAuthorEntrySchema),
|
|
31
|
+
/** Build dependency names and versions from `[build-dependencies]`. */
|
|
29
32
|
buildDependencies: z.array(cargoTomlDependencyEntrySchema),
|
|
33
|
+
/** Category strings from `package.categories`. */
|
|
30
34
|
categories: stringArray,
|
|
35
|
+
/** Dependencies from `[dependencies]`. */
|
|
31
36
|
dependencies: z.array(cargoTomlDependencyEntrySchema),
|
|
37
|
+
/** Description from `package.description`. */
|
|
32
38
|
description: nonEmptyString,
|
|
39
|
+
/** Dev dependency names and versions from `[dev-dependencies]`. */
|
|
33
40
|
devDependencies: z.array(cargoTomlDependencyEntrySchema),
|
|
41
|
+
/** Documentation URL from `package.documentation`. */
|
|
34
42
|
documentation: optionalUrl,
|
|
43
|
+
/** Rust edition from `package.edition`. */
|
|
35
44
|
edition: nonEmptyString,
|
|
45
|
+
/** Homepage URL from `package.homepage`. */
|
|
36
46
|
homepage: optionalUrl,
|
|
47
|
+
/** Keywords from `package.keywords`. */
|
|
37
48
|
keywords: stringArray,
|
|
49
|
+
/** License identifier from `package.license`. */
|
|
38
50
|
license: nonEmptyString,
|
|
51
|
+
/** License file path from `package.license-file`. */
|
|
39
52
|
licenseFile: nonEmptyString,
|
|
53
|
+
/** Package name from `package.name`. */
|
|
40
54
|
name: nonEmptyString,
|
|
55
|
+
/** Readme file path from `package.readme`. */
|
|
41
56
|
readme: nonEmptyString,
|
|
57
|
+
/** Repository URL from `package.repository`. */
|
|
42
58
|
repository: optionalUrl,
|
|
59
|
+
/** Minimum Rust version from `package.rust-version`. */
|
|
43
60
|
rustVersion: nonEmptyString,
|
|
61
|
+
/** Version string from `package.version`. */
|
|
44
62
|
version: nonEmptyString,
|
|
63
|
+
/** Workspace members from `[workspace]`. */
|
|
45
64
|
workspaceMembers: stringArray
|
|
46
65
|
});
|
|
47
66
|
/**
|
|
48
|
-
* Parse a `Cargo.toml` content string into a structured object.
|
|
49
|
-
*
|
|
67
|
+
* Parse a `Cargo.toml` content string into a structured object. Returns
|
|
68
|
+
* undefined if the TOML is malformed.
|
|
50
69
|
*/
|
|
51
70
|
function parse$1(content) {
|
|
52
71
|
let data;
|
|
53
72
|
try {
|
|
54
73
|
const parsed = parse(content);
|
|
55
|
-
if (!is.plainObject(parsed)) return
|
|
74
|
+
if (!is.plainObject(parsed)) return;
|
|
56
75
|
data = parsed;
|
|
57
76
|
} catch {
|
|
58
77
|
return;
|
|
@@ -82,7 +101,7 @@ function parse$1(content) {
|
|
|
82
101
|
}
|
|
83
102
|
/** Return a trimmed string, or undefined if not a non-empty string. */
|
|
84
103
|
function nonEmpty(value) {
|
|
85
|
-
if (typeof value !== "string") return
|
|
104
|
+
if (typeof value !== "string") return;
|
|
86
105
|
const trimmed = value.trim();
|
|
87
106
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
88
107
|
}
|
|
@@ -122,8 +141,8 @@ function parseAuthors(value) {
|
|
|
122
141
|
return results;
|
|
123
142
|
}
|
|
124
143
|
/**
|
|
125
|
-
* Parse a dependencies table into name/version entries.
|
|
126
|
-
*
|
|
144
|
+
* Parse a dependencies table into name/version entries. Handles both `dep =
|
|
145
|
+
* "version"` and `dep = { version = "..." }` forms.
|
|
127
146
|
*/
|
|
128
147
|
function parseDependencies(table) {
|
|
129
148
|
const results = [];
|