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,106 @@
1
+ import { getMatches } from "../file-matching.js";
2
+ import { defineSource } from "../source.js";
3
+ import { nonEmptyString, optionalUrl, stringArray } from "../utilities/schema-primitives.js";
4
+ import { splitCommaSeparated } from "../utilities/template-helpers.js";
5
+ import { parseConfigparser, splitMultiline } from "../parsers/configparser-parser.js";
6
+ import { readFile } from "node:fs/promises";
7
+ import { resolve } from "node:path";
8
+ import { z } from "zod";
9
+ //#region src/lib/sources/python-setup-cfg.ts
10
+ const setupCfgDataSchema = z.object({
11
+ author: nonEmptyString,
12
+ author_email: nonEmptyString,
13
+ classifiers: stringArray,
14
+ description: nonEmptyString,
15
+ download_url: optionalUrl,
16
+ extras_require: z.record(z.string(), z.array(z.string())),
17
+ install_requires: stringArray,
18
+ keywords: z.array(z.string()).optional(),
19
+ license: nonEmptyString,
20
+ long_description: nonEmptyString,
21
+ maintainer: nonEmptyString,
22
+ maintainer_email: nonEmptyString,
23
+ name: nonEmptyString,
24
+ project_urls: z.record(z.string(), z.string()),
25
+ python_requires: nonEmptyString,
26
+ url: optionalUrl,
27
+ version: nonEmptyString
28
+ });
29
+ /** Simple string attributes to extract from [metadata]. */
30
+ const STRING_ATTRS = new Set([
31
+ "author",
32
+ "author_email",
33
+ "description",
34
+ "download_url",
35
+ "license",
36
+ "long_description",
37
+ "maintainer",
38
+ "maintainer_email",
39
+ "name",
40
+ "url",
41
+ "version"
42
+ ]);
43
+ /**
44
+ * Parse a setup.cfg file and return structured metadata.
45
+ *
46
+ * Extracts fields from the `[metadata]` and `[options]` sections,
47
+ * including multi-line values like classifiers and install_requires.
48
+ */
49
+ function parse(source) {
50
+ const sections = parseConfigparser(source);
51
+ const metadata = sections.metadata ?? {};
52
+ const options = sections.options ?? {};
53
+ const data = {
54
+ author: void 0,
55
+ author_email: void 0,
56
+ classifiers: [],
57
+ description: void 0,
58
+ download_url: void 0,
59
+ extras_require: {},
60
+ install_requires: [],
61
+ keywords: void 0,
62
+ license: void 0,
63
+ long_description: void 0,
64
+ maintainer: void 0,
65
+ maintainer_email: void 0,
66
+ name: void 0,
67
+ project_urls: {},
68
+ python_requires: void 0,
69
+ url: void 0,
70
+ version: void 0
71
+ };
72
+ for (const key of STRING_ATTRS) {
73
+ const value = metadata[key];
74
+ if (value) Object.assign(data, { [key]: value });
75
+ }
76
+ if (metadata.classifiers) data.classifiers = splitMultiline(metadata.classifiers);
77
+ if (metadata.keywords) data.keywords = splitCommaSeparated(metadata.keywords);
78
+ if (metadata.project_urls) for (const line of splitMultiline(metadata.project_urls)) {
79
+ const eqIndex = line.indexOf("=");
80
+ if (eqIndex > 0) {
81
+ const label = line.slice(0, eqIndex).trim();
82
+ const url = line.slice(eqIndex + 1).trim();
83
+ if (url) data.project_urls[label] = url;
84
+ }
85
+ }
86
+ if (options.install_requires) data.install_requires = splitMultiline(options.install_requires);
87
+ if (options.python_requires) data.python_requires = options.python_requires;
88
+ const extrasSection = sections["options.extras_require"];
89
+ if (extrasSection) for (const [key, value] of Object.entries(extrasSection)) data.extras_require[key] = splitMultiline(value);
90
+ return setupCfgDataSchema.parse(data);
91
+ }
92
+ const pythonSetupCfgSource = defineSource({
93
+ async discover(context) {
94
+ return getMatches(context.options, ["setup.cfg"]);
95
+ },
96
+ key: "pythonSetupCfg",
97
+ async parse(input, context) {
98
+ return {
99
+ data: parse(await readFile(resolve(context.options.path, input), "utf8")),
100
+ source: input
101
+ };
102
+ },
103
+ phase: 1
104
+ });
105
+ //#endregion
106
+ export { pythonSetupCfgSource };
@@ -0,0 +1,28 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/lib/sources/python-setup-py.d.ts
5
+ /** Parsed setup.py metadata */
6
+ declare const setupPyDataSchema: z.ZodObject<{
7
+ author: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
8
+ author_email: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
9
+ classifiers: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
10
+ description: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
11
+ download_url: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
12
+ extras_require: z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>;
13
+ install_requires: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
14
+ keywords: z.ZodOptional<z.ZodArray<z.ZodString>>;
15
+ license: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
16
+ long_description: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
17
+ maintainer: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
18
+ maintainer_email: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
19
+ name: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
20
+ project_urls: z.ZodRecord<z.ZodString, z.ZodString>;
21
+ python_requires: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
22
+ url: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
23
+ version: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
24
+ }, z.core.$strip>;
25
+ type SetupPyData = z.infer<typeof setupPyDataSchema>;
26
+ type PythonSetupPyData = OneOrMany<SourceRecord<SetupPyData>> | undefined;
27
+ //#endregion
28
+ export { PythonSetupPyData };
@@ -0,0 +1,48 @@
1
+ import { getMatches } from "../file-matching.js";
2
+ import { defineSource } from "../source.js";
3
+ import { nonEmptyString, optionalUrl, stringArray } from "../utilities/schema-primitives.js";
4
+ import { parseSetupPy } from "../parsers/setup-py-parser.js";
5
+ import { readFile } from "node:fs/promises";
6
+ import { resolve } from "node:path";
7
+ import { z } from "zod";
8
+ //#region src/lib/sources/python-setup-py.ts
9
+ /** Parsed setup.py metadata */
10
+ const setupPyDataSchema = z.object({
11
+ author: nonEmptyString,
12
+ author_email: nonEmptyString,
13
+ classifiers: stringArray,
14
+ description: nonEmptyString,
15
+ download_url: optionalUrl,
16
+ extras_require: z.record(z.string(), z.array(z.string())),
17
+ install_requires: stringArray,
18
+ keywords: z.array(z.string()).optional(),
19
+ license: nonEmptyString,
20
+ long_description: nonEmptyString,
21
+ maintainer: nonEmptyString,
22
+ maintainer_email: nonEmptyString,
23
+ name: nonEmptyString,
24
+ project_urls: z.record(z.string(), z.string()),
25
+ python_requires: nonEmptyString,
26
+ url: optionalUrl,
27
+ version: nonEmptyString
28
+ });
29
+ /** Parse setup.py content and validate through the Zod schema. */
30
+ async function parse(content) {
31
+ const data = await parseSetupPy(content);
32
+ return setupPyDataSchema.parse(data);
33
+ }
34
+ const pythonSetupPySource = defineSource({
35
+ async discover(context) {
36
+ return getMatches(context.options, ["setup.py"]);
37
+ },
38
+ key: "pythonSetupPy",
39
+ async parse(input, context) {
40
+ return {
41
+ data: await parse(await readFile(resolve(context.options.path, input), "utf8")),
42
+ source: input
43
+ };
44
+ },
45
+ phase: 1
46
+ });
47
+ //#endregion
48
+ export { pythonSetupPySource };
@@ -0,0 +1,11 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/lib/sources/readme-file.d.ts
5
+ declare const readmeSchema: z.ZodObject<{
6
+ name: z.ZodString;
7
+ }, z.core.$strip>;
8
+ type Readme = z.infer<typeof readmeSchema>;
9
+ type ReadmeFileData = OneOrMany<SourceRecord<Readme>> | undefined;
10
+ //#endregion
11
+ export { ReadmeFileData };
@@ -0,0 +1,55 @@
1
+ import { getMatches } from "../file-matching.js";
2
+ import { defineSource } from "../source.js";
3
+ import { readFile } from "node:fs/promises";
4
+ import { resolve } from "node:path";
5
+ import { z } from "zod";
6
+ import remarkParse from "remark-parse";
7
+ import { unified } from "unified";
8
+ //#region src/lib/sources/readme-file.ts
9
+ const readmeSchema = z.object({ name: z.string() });
10
+ /**
11
+ * Recursively extract plain text from mdast phrasing content.
12
+ */
13
+ function extractText(nodes) {
14
+ return nodes.map((node) => {
15
+ if ("value" in node) return node.value;
16
+ if ("children" in node) return extractText(node.children);
17
+ return "";
18
+ }).join("").trim();
19
+ }
20
+ /**
21
+ * Extract the text content of the first H1 heading from markdown.
22
+ */
23
+ function extractFirstH1(markdown) {
24
+ const tree = unified().use(remarkParse).parse(markdown);
25
+ for (const node of tree.children) if (node.type === "heading" && node.depth === 1) {
26
+ const text = extractText(node.children);
27
+ if (text.length > 0) return text;
28
+ }
29
+ }
30
+ /**
31
+ * Parse a README file's content.
32
+ * @param content - Raw file content (markdown).
33
+ * @returns Parsed metadata, or `undefined` if no H1 heading is found.
34
+ */
35
+ function parse(content) {
36
+ const name = extractFirstH1(content);
37
+ if (!name) return void 0;
38
+ return readmeSchema.parse({ name });
39
+ }
40
+ const readmeFileSource = defineSource({
41
+ async discover(context) {
42
+ return getMatches(context.options, ["README", "README.*"]);
43
+ },
44
+ key: "readmeFile",
45
+ async parse(input, context) {
46
+ const data = parse(await readFile(resolve(context.options.path, input), "utf8"));
47
+ if (data !== void 0) return {
48
+ data,
49
+ source: input
50
+ };
51
+ },
52
+ phase: 1
53
+ });
54
+ //#endregion
55
+ export { readmeFileSource };
@@ -0,0 +1,44 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/lib/sources/ruby-gemspec.d.ts
5
+ /** @public */
6
+ declare const gemSpecSchema: z.ZodObject<{
7
+ authors: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
8
+ bindir: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
9
+ cert_chain: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
10
+ dependencies: z.ZodArray<z.ZodObject<{
11
+ name: z.ZodString;
12
+ requirements: z.ZodArray<z.ZodString>;
13
+ type: z.ZodEnum<{
14
+ development: "development";
15
+ runtime: "runtime";
16
+ }>;
17
+ }, z.core.$strip>>;
18
+ description: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
19
+ email: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
20
+ executables: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
21
+ extensions: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
22
+ extra: z.ZodRecord<z.ZodString, z.ZodUnknown>;
23
+ extra_rdoc_files: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
24
+ files: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
25
+ homepage: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
26
+ license: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
27
+ licenses: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
28
+ metadata: z.ZodRecord<z.ZodString, z.ZodString>;
29
+ name: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
30
+ platform: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
31
+ post_install_message: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
32
+ rdoc_options: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
33
+ require_paths: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
34
+ required_ruby_version: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
35
+ required_rubygems_version: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
36
+ signing_key: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
37
+ summary: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
38
+ test_files: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
39
+ version: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
40
+ }, z.core.$strip>;
41
+ type GemSpec = z.infer<typeof gemSpecSchema>;
42
+ type RubyGemspecData = OneOrMany<SourceRecord<GemSpec>> | undefined;
43
+ //#endregion
44
+ export { RubyGemspecData };
@@ -0,0 +1,62 @@
1
+ import { getMatches } from "../file-matching.js";
2
+ import { defineSource } from "../source.js";
3
+ import { nonEmptyString, optionalUrl, stringArray } from "../utilities/schema-primitives.js";
4
+ import { parseGemspec } from "../parsers/gemspec-parser.js";
5
+ import { readFile } from "node:fs/promises";
6
+ import { resolve } from "node:path";
7
+ import { z } from "zod";
8
+ //#region src/lib/sources/ruby-gemspec.ts
9
+ const gemSpecDependencySchema = z.object({
10
+ name: z.string(),
11
+ requirements: z.array(z.string()),
12
+ type: z.enum(["development", "runtime"])
13
+ });
14
+ /** @public */
15
+ const gemSpecSchema = z.object({
16
+ authors: stringArray,
17
+ bindir: nonEmptyString,
18
+ cert_chain: stringArray,
19
+ dependencies: z.array(gemSpecDependencySchema),
20
+ description: nonEmptyString,
21
+ email: z.union([z.string(), z.array(z.string())]).optional(),
22
+ executables: stringArray,
23
+ extensions: stringArray,
24
+ extra: z.record(z.string(), z.unknown()),
25
+ extra_rdoc_files: stringArray,
26
+ files: stringArray,
27
+ homepage: optionalUrl,
28
+ license: nonEmptyString,
29
+ licenses: stringArray,
30
+ metadata: z.record(z.string(), z.string()),
31
+ name: nonEmptyString,
32
+ platform: nonEmptyString,
33
+ post_install_message: nonEmptyString,
34
+ rdoc_options: stringArray,
35
+ require_paths: stringArray,
36
+ required_ruby_version: nonEmptyString,
37
+ required_rubygems_version: nonEmptyString,
38
+ signing_key: nonEmptyString,
39
+ summary: nonEmptyString,
40
+ test_files: stringArray,
41
+ version: nonEmptyString
42
+ });
43
+ /** Parse gemspec content and validate through the Zod schema. */
44
+ async function parse(content) {
45
+ const raw = await parseGemspec(content);
46
+ return gemSpecSchema.parse(raw);
47
+ }
48
+ const rubyGemspecSource = defineSource({
49
+ async discover(context) {
50
+ return getMatches(context.options, ["*.gemspec"]);
51
+ },
52
+ key: "rubyGemspec",
53
+ async parse(input, context) {
54
+ return {
55
+ data: await parse(await readFile(resolve(context.options.path, input), "utf8")),
56
+ source: input
57
+ };
58
+ },
59
+ phase: 1
60
+ });
61
+ //#endregion
62
+ export { rubyGemspecSource };
@@ -0,0 +1,40 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/lib/sources/rust-cargo-toml.d.ts
5
+ declare const cargoTomlSchema: z.ZodObject<{
6
+ authors: z.ZodArray<z.ZodObject<{
7
+ email: z.ZodOptional<z.ZodString>;
8
+ name: z.ZodString;
9
+ }, z.core.$strip>>;
10
+ buildDependencies: z.ZodArray<z.ZodObject<{
11
+ name: z.ZodString;
12
+ version: z.ZodOptional<z.ZodString>;
13
+ }, z.core.$strip>>;
14
+ categories: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
15
+ dependencies: z.ZodArray<z.ZodObject<{
16
+ name: z.ZodString;
17
+ version: z.ZodOptional<z.ZodString>;
18
+ }, z.core.$strip>>;
19
+ description: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
20
+ devDependencies: z.ZodArray<z.ZodObject<{
21
+ name: z.ZodString;
22
+ version: z.ZodOptional<z.ZodString>;
23
+ }, z.core.$strip>>;
24
+ documentation: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
25
+ edition: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
26
+ homepage: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
27
+ keywords: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
28
+ license: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
29
+ licenseFile: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
30
+ name: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
31
+ readme: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
32
+ repository: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
33
+ rustVersion: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
34
+ version: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
35
+ workspaceMembers: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
36
+ }, z.core.$strip>;
37
+ type CargoToml = z.infer<typeof cargoTomlSchema>;
38
+ type RustCargoTomlData = OneOrMany<SourceRecord<CargoToml>> | undefined;
39
+ //#endregion
40
+ export { RustCargoTomlData };
@@ -0,0 +1,159 @@
1
+ import { getMatches } from "../file-matching.js";
2
+ import { defineSource } from "../source.js";
3
+ import { nonEmptyString, optionalUrl, stringArray } from "../utilities/schema-primitives.js";
4
+ import { readFile } from "node:fs/promises";
5
+ import { resolve } from "node:path";
6
+ import is from "@sindresorhus/is";
7
+ import { z } from "zod";
8
+ import { parse } from "smol-toml";
9
+ //#region src/lib/sources/rust-cargo-toml.ts
10
+ /**
11
+ * Source for Rust `Cargo.toml` manifest files.
12
+ * These are TOML files used by the Cargo package manager. Metadata lives
13
+ * primarily in the `[package]` table, with dependencies in `[dependencies]`,
14
+ * `[dev-dependencies]`, and `[build-dependencies]`.
15
+ *
16
+ * Uses `smol-toml` for TOML parsing.
17
+ * @see https://doc.rust-lang.org/cargo/reference/manifest.html
18
+ */
19
+ const cargoTomlAuthorEntrySchema = z.object({
20
+ email: z.string().optional(),
21
+ name: z.string()
22
+ });
23
+ const cargoTomlDependencyEntrySchema = z.object({
24
+ name: z.string(),
25
+ version: z.string().optional()
26
+ });
27
+ const cargoTomlSchema = z.object({
28
+ authors: z.array(cargoTomlAuthorEntrySchema),
29
+ buildDependencies: z.array(cargoTomlDependencyEntrySchema),
30
+ categories: stringArray,
31
+ dependencies: z.array(cargoTomlDependencyEntrySchema),
32
+ description: nonEmptyString,
33
+ devDependencies: z.array(cargoTomlDependencyEntrySchema),
34
+ documentation: optionalUrl,
35
+ edition: nonEmptyString,
36
+ homepage: optionalUrl,
37
+ keywords: stringArray,
38
+ license: nonEmptyString,
39
+ licenseFile: nonEmptyString,
40
+ name: nonEmptyString,
41
+ readme: nonEmptyString,
42
+ repository: optionalUrl,
43
+ rustVersion: nonEmptyString,
44
+ version: nonEmptyString,
45
+ workspaceMembers: stringArray
46
+ });
47
+ /**
48
+ * Parse a `Cargo.toml` content string into a structured object.
49
+ * Returns undefined if the TOML is malformed.
50
+ */
51
+ function parse$1(content) {
52
+ let data;
53
+ try {
54
+ const parsed = parse(content);
55
+ if (!is.plainObject(parsed)) return void 0;
56
+ data = parsed;
57
+ } catch {
58
+ return;
59
+ }
60
+ const packageData = is.plainObject(data.package) ? data.package : {};
61
+ const workspace = is.plainObject(data.workspace) ? data.workspace : void 0;
62
+ return cargoTomlSchema.parse({
63
+ authors: parseAuthors(packageData.authors),
64
+ buildDependencies: parseDependencies(is.plainObject(data["build-dependencies"]) ? data["build-dependencies"] : {}),
65
+ categories: toStringArray(packageData.categories),
66
+ dependencies: parseDependencies(is.plainObject(data.dependencies) ? data.dependencies : {}),
67
+ description: nonEmpty(packageData.description),
68
+ devDependencies: parseDependencies(is.plainObject(data["dev-dependencies"]) ? data["dev-dependencies"] : {}),
69
+ documentation: nonEmpty(packageData.documentation),
70
+ edition: nonEmpty(packageData.edition),
71
+ homepage: nonEmpty(packageData.homepage),
72
+ keywords: toStringArray(packageData.keywords),
73
+ license: nonEmpty(packageData.license),
74
+ licenseFile: nonEmpty(packageData["license-file"]),
75
+ name: nonEmpty(packageData.name),
76
+ readme: nonEmpty(packageData.readme),
77
+ repository: nonEmpty(packageData.repository),
78
+ rustVersion: nonEmpty(packageData["rust-version"]),
79
+ version: nonEmpty(packageData.version),
80
+ workspaceMembers: toStringArray(workspace?.members)
81
+ });
82
+ }
83
+ /** Return a trimmed string, or undefined if not a non-empty string. */
84
+ function nonEmpty(value) {
85
+ if (typeof value !== "string") return void 0;
86
+ const trimmed = value.trim();
87
+ return trimmed.length > 0 ? trimmed : void 0;
88
+ }
89
+ /** Convert an unknown value to a string array, filtering non-strings. */
90
+ function toStringArray(value) {
91
+ if (!Array.isArray(value)) return [];
92
+ return value.filter((v) => typeof v === "string" && v.trim().length > 0);
93
+ }
94
+ /**
95
+ * Parse `authors` field entries. Each entry is `"Name <email>"` or `"Name"`.
96
+ */
97
+ function parseAuthors(value) {
98
+ if (!Array.isArray(value)) return [];
99
+ const results = [];
100
+ for (const entry of value) {
101
+ if (typeof entry !== "string") continue;
102
+ const trimmed = entry.trim();
103
+ if (trimmed.length === 0) continue;
104
+ const bracketIndex = trimmed.indexOf("<");
105
+ if (bracketIndex !== -1) {
106
+ const closeBracket = trimmed.indexOf(">", bracketIndex);
107
+ if (closeBracket !== -1) {
108
+ const name = trimmed.slice(0, bracketIndex).trim();
109
+ const email = trimmed.slice(bracketIndex + 1, closeBracket).trim();
110
+ results.push({
111
+ email: email.length > 0 ? email : void 0,
112
+ name
113
+ });
114
+ continue;
115
+ }
116
+ }
117
+ results.push({
118
+ email: void 0,
119
+ name: trimmed
120
+ });
121
+ }
122
+ return results;
123
+ }
124
+ /**
125
+ * Parse a dependencies table into name/version entries.
126
+ * Handles both `dep = "version"` and `dep = { version = "..." }` forms.
127
+ */
128
+ function parseDependencies(table) {
129
+ const results = [];
130
+ for (const [name, value] of Object.entries(table)) if (typeof value === "string") results.push({
131
+ name,
132
+ version: value
133
+ });
134
+ else if (is.plainObject(value)) results.push({
135
+ name,
136
+ version: nonEmpty(value.version)
137
+ });
138
+ else results.push({
139
+ name,
140
+ version: void 0
141
+ });
142
+ return results;
143
+ }
144
+ const rustCargoTomlSource = defineSource({
145
+ async discover(context) {
146
+ return getMatches(context.options, ["Cargo.toml"]);
147
+ },
148
+ key: "rustCargoToml",
149
+ async parse(input, context) {
150
+ const data = parse$1(await readFile(resolve(context.options.path, input), "utf8"));
151
+ if (data !== void 0) return {
152
+ data,
153
+ source: input
154
+ };
155
+ },
156
+ phase: 1
157
+ });
158
+ //#endregion
159
+ export { rustCargoTomlSource };
@@ -0,0 +1,22 @@
1
+ import { OneOrMany, SourceRecord } from "../source.js";
2
+ import { z } from "zod";
3
+
4
+ //#region src/lib/sources/xcode-info-plist.d.ts
5
+ declare const infoPlistSchema: z.ZodObject<{
6
+ applicationCategory: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
7
+ author: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
8
+ authorEmail: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
9
+ copyrightHolder: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
10
+ copyrightYear: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
11
+ description: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
12
+ identifier: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
13
+ name: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
14
+ operatingSystems: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
15
+ processorRequirements: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
16
+ url: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
17
+ version: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
18
+ }, z.core.$strip>;
19
+ type InfoPlist = z.infer<typeof infoPlistSchema>;
20
+ type XcodeInfoPlistData = OneOrMany<SourceRecord<InfoPlist>> | undefined;
21
+ //#endregion
22
+ export { XcodeInfoPlistData };