metascope 0.1.0 → 0.2.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.
Files changed (111) hide show
  1. package/dist/.DS_Store +0 -0
  2. package/dist/bin/cli.js +14 -14
  3. package/dist/lib/{chunk-DrSxFLj_.js → _virtual/_rolldown/runtime.js} +1 -1
  4. package/dist/lib/file-matching.js +152 -0
  5. package/dist/lib/index.d.ts +11 -1496
  6. package/dist/lib/index.js +6 -6215
  7. package/dist/lib/log.d.ts +11 -0
  8. package/dist/lib/log.js +20 -0
  9. package/dist/lib/metadata-types.d.ts +151 -0
  10. package/dist/lib/metadata-types.js +30 -0
  11. package/dist/lib/metadata.d.ts +16 -0
  12. package/dist/lib/metadata.js +235 -0
  13. package/dist/lib/package.js +5 -0
  14. package/dist/lib/parsers/configparser-parser.js +43 -0
  15. package/dist/lib/parsers/gemspec-parser.js +256 -0
  16. package/dist/lib/parsers/go-mod-parser.js +153 -0
  17. package/dist/lib/parsers/makefile-config-parser.js +102 -0
  18. package/dist/lib/parsers/properties-parser.js +31 -0
  19. package/dist/lib/parsers/rfc822-header-parser.js +48 -0
  20. package/dist/lib/parsers/setup-py-parser.js +173 -0
  21. package/dist/lib/source.d.ts +17 -0
  22. package/dist/lib/source.js +34 -0
  23. package/dist/lib/sources/arduino-library-properties.d.ts +45 -0
  24. package/dist/lib/sources/arduino-library-properties.js +208 -0
  25. package/dist/lib/sources/cinder-cinderblock-xml.d.ts +21 -0
  26. package/dist/lib/sources/cinder-cinderblock-xml.js +134 -0
  27. package/dist/lib/sources/code-stats.d.ts +14 -0
  28. package/dist/lib/sources/code-stats.js +40 -0
  29. package/dist/lib/sources/codemeta-json.d.ts +117 -0
  30. package/dist/lib/sources/codemeta-json.js +226 -0
  31. package/dist/lib/sources/dependency-updates.d.ts +22 -0
  32. package/dist/lib/sources/dependency-updates.js +132 -0
  33. package/dist/lib/sources/file-stats.d.ts +12 -0
  34. package/dist/lib/sources/file-stats.js +48 -0
  35. package/dist/lib/sources/git-config.d.ts +8 -0
  36. package/dist/lib/sources/git-config.js +21 -0
  37. package/dist/lib/sources/git-stats.d.ts +35 -0
  38. package/dist/lib/sources/git-stats.js +130 -0
  39. package/dist/lib/sources/github.d.ts +94 -0
  40. package/dist/lib/sources/github.js +399 -0
  41. package/dist/lib/sources/go-go-mod.d.ts +19 -0
  42. package/dist/lib/sources/go-go-mod.js +38 -0
  43. package/dist/lib/sources/go-goreleaser-yaml.d.ts +19 -0
  44. package/dist/lib/sources/go-goreleaser-yaml.js +152 -0
  45. package/dist/lib/sources/java-pom-xml.d.ts +52 -0
  46. package/dist/lib/sources/java-pom-xml.js +248 -0
  47. package/dist/lib/sources/license-file.d.ts +10 -0
  48. package/dist/lib/sources/license-file.js +26 -0
  49. package/dist/lib/sources/metadata-file.d.ts +14 -0
  50. package/dist/lib/sources/metadata-file.js +109 -0
  51. package/dist/lib/sources/metascope.d.ts +14 -0
  52. package/dist/lib/sources/metascope.js +35 -0
  53. package/dist/lib/sources/node-npm-registry.d.ts +19 -0
  54. package/dist/lib/sources/node-npm-registry.js +74 -0
  55. package/dist/lib/sources/node-package-json.d.ts +7 -0
  56. package/dist/lib/sources/node-package-json.js +27 -0
  57. package/dist/lib/sources/obsidian-plugin-manifest-json.d.ts +17 -0
  58. package/dist/lib/sources/obsidian-plugin-manifest-json.js +34 -0
  59. package/dist/lib/sources/obsidian-plugin-registry.d.ts +10 -0
  60. package/dist/lib/sources/obsidian-plugin-registry.js +44 -0
  61. package/dist/lib/sources/openframeworks-addon-config-mk.d.ts +17 -0
  62. package/dist/lib/sources/openframeworks-addon-config-mk.js +39 -0
  63. package/dist/lib/sources/openframeworks-install-xml.d.ts +20 -0
  64. package/dist/lib/sources/openframeworks-install-xml.js +153 -0
  65. package/dist/lib/sources/processing-library-properties.d.ts +44 -0
  66. package/dist/lib/sources/processing-library-properties.js +219 -0
  67. package/dist/lib/sources/processing-sketch-properties.d.ts +38 -0
  68. package/dist/lib/sources/processing-sketch-properties.js +185 -0
  69. package/dist/lib/sources/publiccode-yaml.d.ts +73 -0
  70. package/dist/lib/sources/publiccode-yaml.js +256 -0
  71. package/dist/lib/sources/python-pkg-info.d.ts +31 -0
  72. package/dist/lib/sources/python-pkg-info.js +115 -0
  73. package/dist/lib/sources/python-pypi-registry.d.ts +19 -0
  74. package/dist/lib/sources/python-pypi-registry.js +101 -0
  75. package/dist/lib/sources/python-pyproject-toml.d.ts +7 -0
  76. package/dist/lib/sources/python-pyproject-toml.js +30 -0
  77. package/dist/lib/sources/python-setup-cfg.d.ts +28 -0
  78. package/dist/lib/sources/python-setup-cfg.js +106 -0
  79. package/dist/lib/sources/python-setup-py.d.ts +28 -0
  80. package/dist/lib/sources/python-setup-py.js +48 -0
  81. package/dist/lib/sources/readme-file.d.ts +11 -0
  82. package/dist/lib/sources/readme-file.js +55 -0
  83. package/dist/lib/sources/ruby-gemspec.d.ts +44 -0
  84. package/dist/lib/sources/ruby-gemspec.js +62 -0
  85. package/dist/lib/sources/rust-cargo-toml.d.ts +40 -0
  86. package/dist/lib/sources/rust-cargo-toml.js +159 -0
  87. package/dist/lib/sources/xcode-info-plist.d.ts +22 -0
  88. package/dist/lib/sources/xcode-info-plist.js +199 -0
  89. package/dist/lib/sources/xcode-project-pbxproj.d.ts +21 -0
  90. package/dist/lib/sources/xcode-project-pbxproj.js +222 -0
  91. package/dist/lib/templates/codemeta.d.ts +47 -0
  92. package/dist/lib/templates/codemeta.js +494 -0
  93. package/dist/lib/templates/frontmatter.d.ts +87 -0
  94. package/dist/lib/templates/frontmatter.js +111 -0
  95. package/dist/lib/templates/index.d.ts +181 -0
  96. package/dist/lib/templates/index.js +22 -0
  97. package/dist/lib/templates/metadata.d.ts +17 -0
  98. package/dist/lib/templates/metadata.js +35 -0
  99. package/dist/lib/templates/project.d.ts +39 -0
  100. package/dist/lib/templates/project.js +51 -0
  101. package/dist/lib/utilities/codemeta-helpers.d.ts +39 -0
  102. package/dist/lib/utilities/codemeta-helpers.js +83 -0
  103. package/dist/lib/utilities/fetch.js +43 -0
  104. package/dist/lib/utilities/formatting.js +28 -0
  105. package/dist/lib/utilities/license-identification.js +141 -0
  106. package/dist/lib/utilities/schema-primitives.js +47 -0
  107. package/dist/lib/utilities/template-helpers.d.ts +135 -0
  108. package/dist/lib/utilities/template-helpers.js +310 -0
  109. package/dist/lib/utilities/tree-sitter-wasm.js +30 -0
  110. package/package.json +6 -6
  111. package/readme.md +62 -15
@@ -0,0 +1,219 @@
1
+ import { getMatches } from "../file-matching.js";
2
+ import { parseProperties } from "../parsers/properties-parser.js";
3
+ import { defineSource } from "../source.js";
4
+ import { nonEmptyString, optionalUrl } from "../utilities/schema-primitives.js";
5
+ import { splitCommaSeparated } from "../utilities/template-helpers.js";
6
+ import { readFile } from "node:fs/promises";
7
+ import { resolve } from "node:path";
8
+ import { z } from "zod";
9
+ //#region src/lib/sources/processing-library-properties.ts
10
+ const processingLibraryPropertiesAuthorEntrySchema = z.object({
11
+ name: z.string(),
12
+ url: z.string().optional()
13
+ });
14
+ /** Canonical Processing library categories. */
15
+ const CANONICAL_CATEGORIES = [
16
+ "3D",
17
+ "Animation",
18
+ "Compilations",
19
+ "Data",
20
+ "Fabrication",
21
+ "Geometry",
22
+ "GUI",
23
+ "Hardware",
24
+ "I/O",
25
+ "Language",
26
+ "Math",
27
+ "Simulation",
28
+ "Sound",
29
+ "Utilities",
30
+ "Typography",
31
+ "Video & Vision"
32
+ ];
33
+ /** Map from letters-only lowercase to canonical category form. */
34
+ const CATEGORY_MAP = new Map(CANONICAL_CATEGORIES.map((cat) => [cat.replaceAll(/[^a-z]/gi, "").toLowerCase(), cat]));
35
+ CATEGORY_MAP.set("3d", "3D");
36
+ const processingLibraryPropertiesSchema = z.object({
37
+ authors: z.array(processingLibraryPropertiesAuthorEntrySchema),
38
+ categories: z.array(z.enum(CANONICAL_CATEGORIES)),
39
+ download: optionalUrl,
40
+ id: nonEmptyString,
41
+ maxRevision: z.number(),
42
+ minRevision: z.number(),
43
+ name: nonEmptyString,
44
+ paragraph: nonEmptyString,
45
+ prettyVersion: nonEmptyString,
46
+ raw: z.record(z.string(), z.string()),
47
+ sentence: nonEmptyString,
48
+ type: nonEmptyString,
49
+ url: optionalUrl,
50
+ version: z.number()
51
+ });
52
+ /**
53
+ * Parse a Processing `library.properties` content string into a structured object.
54
+ */
55
+ function parse(content) {
56
+ const raw = parseProperties(content);
57
+ const versionRaw = get(raw, "version") ?? "0";
58
+ const versionParsed = Number.parseInt(versionRaw, 10);
59
+ const prettyVersionRaw = get(raw, "prettyVersion");
60
+ const prettyVersion = prettyVersionRaw ? stripInlineComment(prettyVersionRaw) : void 0;
61
+ const minRevisionRaw = get(raw, "minRevision");
62
+ const minParsed = minRevisionRaw ? Number.parseInt(minRevisionRaw, 10) : 0;
63
+ const maxRevisionRaw = get(raw, "maxRevision");
64
+ const maxParsed = maxRevisionRaw ? Number.parseInt(maxRevisionRaw, 10) : 0;
65
+ return processingLibraryPropertiesSchema.parse({
66
+ authors: parseAuthors(get(raw, "authors") ?? get(raw, "authorList") ?? ""),
67
+ categories: parseCategories(get(raw, "categories") ?? get(raw, "category") ?? ""),
68
+ download: nonEmpty(get(raw, "download")),
69
+ id: nonEmpty(get(raw, "id")),
70
+ maxRevision: Number.isNaN(maxParsed) ? 0 : maxParsed,
71
+ minRevision: Number.isNaN(minParsed) ? 0 : minParsed,
72
+ name: nonEmpty(get(raw, "name")),
73
+ paragraph: nonEmpty(get(raw, "paragraph")),
74
+ prettyVersion: nonEmpty(prettyVersion),
75
+ raw,
76
+ sentence: nonEmpty(get(raw, "sentence")),
77
+ type: nonEmpty(get(raw, "type")),
78
+ url: nonEmpty(unescapeUrl(get(raw, "url") ?? "")),
79
+ version: Number.isNaN(versionParsed) ? 0 : versionParsed
80
+ });
81
+ }
82
+ /** Helper to get a value from the raw record. */
83
+ function get(raw, key) {
84
+ return raw[key];
85
+ }
86
+ /** Return a trimmed string, or undefined if empty/whitespace-only. */
87
+ function nonEmpty(value) {
88
+ if (value === void 0) return void 0;
89
+ const trimmed = value.trim();
90
+ return trimmed.length > 0 ? trimmed : void 0;
91
+ }
92
+ /**
93
+ * Strip trailing inline comments from a value.
94
+ * Matches the pattern ` # comment text` (space-hash-space).
95
+ */
96
+ function stripInlineComment(value) {
97
+ const index = value.indexOf(" # ");
98
+ return index === -1 ? value : value.slice(0, index).trim();
99
+ }
100
+ /**
101
+ * Unescape backslash-escaped colons in URLs.
102
+ * Some Processing fixtures use `https\://` instead of `https://`.
103
+ */
104
+ function unescapeUrl(value) {
105
+ return value.replaceAll(String.raw`\:`, ":");
106
+ }
107
+ /**
108
+ * Parse a Processing authors/authorList value into AuthorEntry[].
109
+ * Preserves original order of appearance.
110
+ */
111
+ function parseAuthors(value) {
112
+ const trimmed = value.trim();
113
+ if (trimmed.length === 0) return [];
114
+ const results = [];
115
+ let cursor = 0;
116
+ while (cursor < trimmed.length) {
117
+ const bracketStart = trimmed.indexOf("[", cursor);
118
+ if (bracketStart === -1) {
119
+ addPlainAuthors(trimmed.slice(cursor), results);
120
+ break;
121
+ }
122
+ if (bracketStart > cursor) addPlainAuthors(trimmed.slice(cursor, bracketStart), results);
123
+ const bracketEnd = trimmed.indexOf("]", bracketStart);
124
+ if (bracketEnd === -1) {
125
+ addPlainAuthors(trimmed.slice(bracketStart), results);
126
+ break;
127
+ }
128
+ const parenStart = trimmed.indexOf("(", bracketEnd);
129
+ if (parenStart === -1 || parenStart !== bracketEnd + 1) {
130
+ addPlainAuthors(trimmed.slice(bracketStart, bracketEnd + 1), results);
131
+ cursor = bracketEnd + 1;
132
+ continue;
133
+ }
134
+ const parenEnd = trimmed.indexOf(")", parenStart);
135
+ if (parenEnd === -1) {
136
+ addPlainAuthors(trimmed.slice(bracketStart), results);
137
+ break;
138
+ }
139
+ const namesPart = trimmed.slice(bracketStart + 1, bracketEnd).trim();
140
+ const url = nonEmpty(unescapeUrl(trimmed.slice(parenStart + 1, parenEnd).trim()));
141
+ const names = splitCommaSeparated(namesPart);
142
+ for (const name of names) results.push({
143
+ name,
144
+ url
145
+ });
146
+ cursor = parenEnd + 1;
147
+ }
148
+ return results;
149
+ }
150
+ /**
151
+ * Split plain text on ` and `, `,`, `&` to extract author names.
152
+ * Filters out bare "others" entries.
153
+ */
154
+ function addPlainAuthors(text, results) {
155
+ const parts = text.split(/\band\b|,|&/).map((s) => s.trim()).filter((s) => s.length > 0 && s.toLowerCase() !== "others");
156
+ for (const name of parts) results.push({
157
+ name,
158
+ url: void 0
159
+ });
160
+ }
161
+ /**
162
+ * Parse and normalize a comma-separated categories value.
163
+ */
164
+ function parseCategories(value) {
165
+ const trimmed = value.trim();
166
+ if (trimmed.length === 0) return [];
167
+ const results = [];
168
+ for (const part of trimmed.split(",")) {
169
+ const stripped = part.trim().replaceAll(/^"|"$/g, "").trim();
170
+ if (stripped.length === 0) continue;
171
+ const key = stripped.replaceAll(/[^a-z0-9]/gi, "").toLowerCase();
172
+ if (key.length === 0) continue;
173
+ const canonical = CATEGORY_MAP.get(key);
174
+ if (canonical && !results.includes(canonical)) results.push(canonical);
175
+ }
176
+ return results;
177
+ }
178
+ /** Processing-specific fields that distinguish from Arduino. */
179
+ const PROCESSING_SPECIFIC_FIELDS = new Set([
180
+ "authorList",
181
+ "authors",
182
+ "dependencies",
183
+ "minrevision",
184
+ "prettyversion"
185
+ ]);
186
+ /** Arduino-exclusive fields that rule out Processing. */
187
+ const ARDUINO_EXCLUSIVE_FIELDS = new Set([
188
+ "architectures",
189
+ "depends",
190
+ "maintainer"
191
+ ]);
192
+ /**
193
+ * Validate that a library.properties file is Processing (not Arduino).
194
+ */
195
+ function isProcessingLibraryProperties(content) {
196
+ const raw = parseProperties(content);
197
+ const keys = new Set(Object.keys(raw).map((k) => k.toLowerCase()));
198
+ if (!keys.has("name") || !keys.has("version")) return false;
199
+ for (const field of ARDUINO_EXCLUSIVE_FIELDS) if (keys.has(field)) return false;
200
+ for (const field of PROCESSING_SPECIFIC_FIELDS) if (keys.has(field)) return true;
201
+ return false;
202
+ }
203
+ const processingLibraryPropertiesSource = defineSource({
204
+ async discover(context) {
205
+ return getMatches(context.options, ["library.properties"]);
206
+ },
207
+ key: "processingLibraryProperties",
208
+ async parse(input, context) {
209
+ const content = await readFile(resolve(context.options.path, input), "utf8");
210
+ if (!isProcessingLibraryProperties(content)) return;
211
+ return {
212
+ data: parse(content),
213
+ source: input
214
+ };
215
+ },
216
+ phase: 1
217
+ });
218
+ //#endregion
219
+ export { processingLibraryPropertiesSource };
@@ -0,0 +1,38 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/lib/sources/processing-sketch-properties.d.ts
5
+ declare const processingSketchPropertiesSchema: z.ZodObject<{
6
+ authors: z.ZodArray<z.ZodObject<{
7
+ name: z.ZodString;
8
+ url: z.ZodOptional<z.ZodString>;
9
+ }, z.core.$strip>>;
10
+ component: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
11
+ download: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
12
+ main: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
13
+ manifestLabel: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
14
+ manifestOrientation: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
15
+ manifestPackage: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
16
+ manifestPermissions: z.ZodArray<z.ZodString>;
17
+ manifestSdkMin: z.ZodOptional<z.ZodNumber>;
18
+ manifestSdkTarget: z.ZodOptional<z.ZodNumber>;
19
+ manifestVersionCode: z.ZodOptional<z.ZodNumber>;
20
+ manifestVersionName: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
21
+ maxRevision: z.ZodNumber;
22
+ minRevision: z.ZodNumber;
23
+ mode: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
24
+ modeId: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
25
+ name: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
26
+ paragraph: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
27
+ prettyVersion: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
28
+ raw: z.ZodRecord<z.ZodString, z.ZodString>;
29
+ sentence: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
30
+ templates: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
31
+ url: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
32
+ version: z.ZodNumber;
33
+ zipfilename: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
34
+ }, z.core.$strip>;
35
+ type ProcessingSketchProperties = z.infer<typeof processingSketchPropertiesSchema>;
36
+ type ProcessingSketchPropertiesData = OneOrMany<SourceRecord<ProcessingSketchProperties>> | undefined;
37
+ //#endregion
38
+ export { ProcessingSketchPropertiesData };
@@ -0,0 +1,185 @@
1
+ import { getMatches } from "../file-matching.js";
2
+ import { parseProperties } from "../parsers/properties-parser.js";
3
+ import { defineSource } from "../source.js";
4
+ import { nonEmptyString, optionalUrl } from "../utilities/schema-primitives.js";
5
+ import { splitCommaSeparated } from "../utilities/template-helpers.js";
6
+ import { readFile } from "node:fs/promises";
7
+ import { resolve } from "node:path";
8
+ import { z } from "zod";
9
+ //#region src/lib/sources/processing-sketch-properties.ts
10
+ const processingSketchPropertiesAuthorEntrySchema = z.object({
11
+ name: z.string(),
12
+ url: z.string().optional()
13
+ });
14
+ const processingSketchPropertiesSchema = z.object({
15
+ authors: z.array(processingSketchPropertiesAuthorEntrySchema),
16
+ component: nonEmptyString,
17
+ download: optionalUrl,
18
+ main: nonEmptyString,
19
+ manifestLabel: nonEmptyString,
20
+ manifestOrientation: nonEmptyString,
21
+ manifestPackage: nonEmptyString,
22
+ manifestPermissions: z.array(z.string()),
23
+ manifestSdkMin: z.number().optional(),
24
+ manifestSdkTarget: z.number().optional(),
25
+ manifestVersionCode: z.number().optional(),
26
+ manifestVersionName: nonEmptyString,
27
+ maxRevision: z.number(),
28
+ minRevision: z.number(),
29
+ mode: nonEmptyString,
30
+ modeId: nonEmptyString,
31
+ name: nonEmptyString,
32
+ paragraph: nonEmptyString,
33
+ prettyVersion: nonEmptyString,
34
+ raw: z.record(z.string(), z.string()),
35
+ sentence: nonEmptyString,
36
+ templates: nonEmptyString,
37
+ url: optionalUrl,
38
+ version: z.number(),
39
+ zipfilename: nonEmptyString
40
+ });
41
+ /**
42
+ * Parse a Processing `sketch.properties` content string into a structured object.
43
+ */
44
+ function parse(content) {
45
+ const raw = parseProperties(content);
46
+ const versionRaw = raw.version ?? "0";
47
+ const versionParsed = Number.parseInt(versionRaw, 10);
48
+ const prettyVersionRaw = raw.prettyVersion;
49
+ const prettyVersion = prettyVersionRaw ? stripInlineComment(prettyVersionRaw) : void 0;
50
+ const minRevisionRaw = raw.minRevision;
51
+ const minParsed = minRevisionRaw ? Number.parseInt(minRevisionRaw, 10) : 0;
52
+ const maxRevisionRaw = raw.maxRevision;
53
+ const maxParsed = maxRevisionRaw ? Number.parseInt(maxRevisionRaw, 10) : 0;
54
+ const manifestVersionCodeRaw = raw["manifest.version.code"];
55
+ const manifestVersionCode = manifestVersionCodeRaw ? Number.parseInt(manifestVersionCodeRaw, 10) : void 0;
56
+ const manifestSdkTargetRaw = raw["manifest.sdk.target"];
57
+ const manifestSdkTarget = manifestSdkTargetRaw ? Number.parseInt(manifestSdkTargetRaw, 10) : void 0;
58
+ const manifestSdkMinRaw = raw["manifest.sdk.min"];
59
+ const manifestSdkMin = manifestSdkMinRaw ? Number.parseInt(manifestSdkMinRaw, 10) : void 0;
60
+ const manifestPermissions = splitCommaSeparated(raw["manifest.permissions"] ?? "");
61
+ return processingSketchPropertiesSchema.parse({
62
+ authors: parseAuthors(raw.authors ?? raw.authorList ?? ""),
63
+ component: nonEmpty(raw.component),
64
+ download: nonEmpty(unescapeUrl(raw.download ?? "")),
65
+ main: nonEmpty(raw.main),
66
+ manifestLabel: nonEmpty(raw["manifest.label"]),
67
+ manifestOrientation: nonEmpty(raw["manifest.orientation"]),
68
+ manifestPackage: nonEmpty(raw["manifest.package"]),
69
+ manifestPermissions,
70
+ manifestSdkMin: Number.isNaN(manifestSdkMin) ? void 0 : manifestSdkMin,
71
+ manifestSdkTarget: Number.isNaN(manifestSdkTarget) ? void 0 : manifestSdkTarget,
72
+ manifestVersionCode: Number.isNaN(manifestVersionCode) ? void 0 : manifestVersionCode,
73
+ manifestVersionName: nonEmpty(raw["manifest.version.name"]),
74
+ maxRevision: Number.isNaN(maxParsed) ? 0 : maxParsed,
75
+ minRevision: Number.isNaN(minParsed) ? 0 : minParsed,
76
+ mode: nonEmpty(raw.mode),
77
+ modeId: nonEmpty(raw["mode.id"]),
78
+ name: nonEmpty(raw.name),
79
+ paragraph: nonEmpty(raw.paragraph),
80
+ prettyVersion: nonEmpty(prettyVersion),
81
+ raw,
82
+ sentence: nonEmpty(raw.sentence),
83
+ templates: nonEmpty(raw.templates),
84
+ url: nonEmpty(unescapeUrl(raw.url ?? "")),
85
+ version: Number.isNaN(versionParsed) ? 0 : versionParsed,
86
+ zipfilename: nonEmpty(raw.zipfilename)
87
+ });
88
+ }
89
+ /** Return a trimmed string, or undefined if empty/whitespace-only. */
90
+ function nonEmpty(value) {
91
+ if (value === void 0) return void 0;
92
+ const trimmed = value.trim();
93
+ return trimmed.length > 0 ? trimmed : void 0;
94
+ }
95
+ /**
96
+ * Strip trailing inline comments from a value.
97
+ * Matches the pattern ` # comment text` (space-hash-space).
98
+ */
99
+ function stripInlineComment(value) {
100
+ const index = value.indexOf(" # ");
101
+ return index === -1 ? value : value.slice(0, index).trim();
102
+ }
103
+ /**
104
+ * Unescape backslash-escaped colons in URLs.
105
+ */
106
+ function unescapeUrl(value) {
107
+ return value.replaceAll(String.raw`\:`, ":");
108
+ }
109
+ /**
110
+ * Parse an authors/authorList value into AuthorEntry[].
111
+ */
112
+ function parseAuthors(value) {
113
+ const trimmed = value.trim();
114
+ if (trimmed.length === 0) return [];
115
+ const results = [];
116
+ let cursor = 0;
117
+ while (cursor < trimmed.length) {
118
+ const bracketStart = trimmed.indexOf("[", cursor);
119
+ if (bracketStart === -1) {
120
+ addPlainAuthors(trimmed.slice(cursor), results);
121
+ break;
122
+ }
123
+ if (bracketStart > cursor) addPlainAuthors(trimmed.slice(cursor, bracketStart), results);
124
+ const bracketEnd = trimmed.indexOf("]", bracketStart);
125
+ if (bracketEnd === -1) {
126
+ addPlainAuthors(trimmed.slice(bracketStart), results);
127
+ break;
128
+ }
129
+ const parenStart = trimmed.indexOf("(", bracketEnd);
130
+ if (parenStart === -1 || parenStart !== bracketEnd + 1) {
131
+ addPlainAuthors(trimmed.slice(bracketStart, bracketEnd + 1), results);
132
+ cursor = bracketEnd + 1;
133
+ continue;
134
+ }
135
+ const parenEnd = trimmed.indexOf(")", parenStart);
136
+ if (parenEnd === -1) {
137
+ addPlainAuthors(trimmed.slice(bracketStart), results);
138
+ break;
139
+ }
140
+ const namesPart = trimmed.slice(bracketStart + 1, bracketEnd).trim();
141
+ const url = nonEmpty(unescapeUrl(trimmed.slice(parenStart + 1, parenEnd).trim()));
142
+ const names = splitCommaSeparated(namesPart);
143
+ for (const name of names) results.push({
144
+ name,
145
+ url
146
+ });
147
+ cursor = parenEnd + 1;
148
+ }
149
+ return results;
150
+ }
151
+ /**
152
+ * Split plain text on ` and `, `,`, `&` to extract author names.
153
+ */
154
+ function addPlainAuthors(text, results) {
155
+ const parts = text.split(/\band\b|,|&/).map((s) => s.trim()).filter((s) => s.length > 0 && s.toLowerCase() !== "others");
156
+ for (const name of parts) results.push({
157
+ name,
158
+ url: void 0
159
+ });
160
+ }
161
+ /**
162
+ * Validate that a sketch.properties file is a Processing sketch.
163
+ * Checks for at least one known Processing sketch key.
164
+ */
165
+ function isProcessingSketchProperties(content) {
166
+ const raw = parseProperties(content);
167
+ return Object.keys(raw).some((k) => k === "main" || k === "mode" || k === "mode.id" || k.startsWith("manifest."));
168
+ }
169
+ const processingSketchPropertiesSource = defineSource({
170
+ async discover(context) {
171
+ return getMatches(context.options, ["sketch.properties"]);
172
+ },
173
+ key: "processingSketchProperties",
174
+ async parse(input, context) {
175
+ const content = await readFile(resolve(context.options.path, input), "utf8");
176
+ if (!isProcessingSketchProperties(content)) return;
177
+ return {
178
+ data: parse(content),
179
+ source: input
180
+ };
181
+ },
182
+ phase: 1
183
+ });
184
+ //#endregion
185
+ export { processingSketchPropertiesSource };
@@ -0,0 +1,73 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/lib/sources/publiccode-yaml.d.ts
5
+ declare const publiccodeSchema: z.ZodObject<{
6
+ applicationSuite: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
7
+ availableLanguages: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
8
+ categories: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
9
+ contacts: z.ZodArray<z.ZodObject<{
10
+ affiliation: z.ZodOptional<z.ZodString>;
11
+ email: z.ZodOptional<z.ZodString>;
12
+ name: z.ZodString;
13
+ phone: z.ZodOptional<z.ZodString>;
14
+ }, z.core.$strip>>;
15
+ contractors: z.ZodArray<z.ZodObject<{
16
+ name: z.ZodString;
17
+ until: z.ZodOptional<z.ZodString>;
18
+ website: z.ZodOptional<z.ZodString>;
19
+ }, z.core.$strip>>;
20
+ dependencies: z.ZodArray<z.ZodObject<{
21
+ category: z.ZodEnum<{
22
+ hardware: "hardware";
23
+ open: "open";
24
+ proprietary: "proprietary";
25
+ }>;
26
+ name: z.ZodString;
27
+ optional: z.ZodOptional<z.ZodBoolean>;
28
+ version: z.ZodOptional<z.ZodString>;
29
+ versionMax: z.ZodOptional<z.ZodString>;
30
+ versionMin: z.ZodOptional<z.ZodString>;
31
+ }, z.core.$strip>>;
32
+ description: z.ZodOptional<z.ZodObject<{
33
+ documentation: z.ZodOptional<z.ZodString>;
34
+ features: z.ZodArray<z.ZodString>;
35
+ genericName: z.ZodOptional<z.ZodString>;
36
+ localisedName: z.ZodOptional<z.ZodString>;
37
+ longDescription: z.ZodOptional<z.ZodString>;
38
+ shortDescription: z.ZodOptional<z.ZodString>;
39
+ }, z.core.$strip>>;
40
+ descriptions: z.ZodRecord<z.ZodString, z.ZodObject<{
41
+ documentation: z.ZodOptional<z.ZodString>;
42
+ features: z.ZodArray<z.ZodString>;
43
+ genericName: z.ZodOptional<z.ZodString>;
44
+ localisedName: z.ZodOptional<z.ZodString>;
45
+ longDescription: z.ZodOptional<z.ZodString>;
46
+ shortDescription: z.ZodOptional<z.ZodString>;
47
+ }, z.core.$strip>>;
48
+ developmentStatus: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
49
+ inputTypes: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
50
+ isBasedOn: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
51
+ landingUrl: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
52
+ license: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
53
+ localisationReady: z.ZodOptional<z.ZodBoolean>;
54
+ logo: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
55
+ mainCopyrightOwner: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
56
+ maintenanceType: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
57
+ monochromeLogo: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
58
+ name: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
59
+ outputTypes: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
60
+ platforms: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
61
+ publiccodeYmlVersion: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
62
+ releaseDate: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
63
+ repoOwner: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
64
+ roadmap: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
65
+ softwareType: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
66
+ softwareVersion: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
67
+ url: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
68
+ usedBy: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
69
+ }, z.core.$strip>;
70
+ type Publiccode = z.infer<typeof publiccodeSchema>;
71
+ type PubliccodeYamlData = OneOrMany<SourceRecord<Publiccode>> | undefined;
72
+ //#endregion
73
+ export { PubliccodeYamlData };