metascope 0.7.0 → 0.7.2

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 (80) hide show
  1. package/dist/bin/chunk-Bdh3yLIe.js +1 -0
  2. package/dist/bin/cli.js +308 -284
  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-DxDKd5Ft.js +1 -0
  6. package/dist/bin/shared-CTlQdTfh.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.d.ts +10 -10
  23. package/dist/lib/sources/arduino-library-properties.js +32 -15
  24. package/dist/lib/sources/cinder-cinderblock-xml.d.ts +11 -11
  25. package/dist/lib/sources/cinder-cinderblock-xml.js +21 -9
  26. package/dist/lib/sources/codemeta-json.d.ts +66 -66
  27. package/dist/lib/sources/codemeta-json.js +27 -23
  28. package/dist/lib/sources/git-stats.js +1 -1
  29. package/dist/lib/sources/github-actions.js +9 -2
  30. package/dist/lib/sources/github.js +1 -1
  31. package/dist/lib/sources/go-go-mod.d.ts +4 -4
  32. package/dist/lib/sources/go-goreleaser-yaml.d.ts +8 -8
  33. package/dist/lib/sources/go-goreleaser-yaml.js +5 -4
  34. package/dist/lib/sources/java-pom-xml.d.ts +12 -12
  35. package/dist/lib/sources/java-pom-xml.js +38 -19
  36. package/dist/lib/sources/metadata-file.d.ts +4 -4
  37. package/dist/lib/sources/metadata-file.js +15 -12
  38. package/dist/lib/sources/node-npm-registry.js +1 -1
  39. package/dist/lib/sources/openframeworks-addon-config-mk.d.ts +7 -7
  40. package/dist/lib/sources/openframeworks-addon-config-mk.js +7 -0
  41. package/dist/lib/sources/openframeworks-install-xml.d.ts +10 -10
  42. package/dist/lib/sources/openframeworks-install-xml.js +24 -14
  43. package/dist/lib/sources/processing-library-properties.d.ts +8 -8
  44. package/dist/lib/sources/processing-library-properties.js +25 -10
  45. package/dist/lib/sources/processing-sketch-properties.d.ts +16 -16
  46. package/dist/lib/sources/processing-sketch-properties.js +51 -7
  47. package/dist/lib/sources/publiccode-yaml.d.ts +23 -23
  48. package/dist/lib/sources/publiccode-yaml.js +37 -5
  49. package/dist/lib/sources/python-pkg-info.d.ts +18 -18
  50. package/dist/lib/sources/python-pkg-info.js +2 -2
  51. package/dist/lib/sources/python-setup-cfg.d.ts +14 -14
  52. package/dist/lib/sources/python-setup-cfg.js +2 -2
  53. package/dist/lib/sources/python-setup-py.d.ts +14 -14
  54. package/dist/lib/sources/readme-file.js +9 -2
  55. package/dist/lib/sources/ruby-gemspec.d.ts +22 -22
  56. package/dist/lib/sources/ruby-gemspec.js +1 -0
  57. package/dist/lib/sources/rust-cargo-toml.d.ts +14 -14
  58. package/dist/lib/sources/rust-cargo-toml.js +29 -10
  59. package/dist/lib/sources/xcode-info-plist.d.ts +12 -12
  60. package/dist/lib/sources/xcode-info-plist.js +48 -24
  61. package/dist/lib/sources/xcode-project-pbxproj.d.ts +8 -8
  62. package/dist/lib/sources/xcode-project-pbxproj.js +22 -12
  63. package/dist/lib/templates/codemeta-json.d.ts +4 -5
  64. package/dist/lib/templates/codemeta-json.js +4 -5
  65. package/dist/lib/templates/codemeta.js +30 -30
  66. package/dist/lib/templates/metadata.d.ts +2 -2
  67. package/dist/lib/templates/metadata.js +3 -3
  68. package/dist/lib/utilities/codemeta-helpers.d.ts +3 -2
  69. package/dist/lib/utilities/codemeta-helpers.js +14 -12
  70. package/dist/lib/utilities/fetch.js +2 -2
  71. package/dist/lib/utilities/formatting.js +4 -3
  72. package/dist/lib/utilities/github.js +3 -3
  73. package/dist/lib/utilities/license-identification.d.ts +3 -1
  74. package/dist/lib/utilities/license-identification.js +21 -25
  75. package/dist/lib/utilities/schema-primitives.js +16 -13
  76. package/dist/lib/utilities/template-helpers.js +3 -3
  77. package/package.json +14 -14
  78. package/readme.md +7 -3
  79. package/dist/.DS_Store +0 -0
  80. package/dist/bin/chunk-BjEoQXZ0.js +0 -1
@@ -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
- * 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]`.
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
- * Returns undefined if the TOML is malformed.
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 void 0;
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 void 0;
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
- * Handles both `dep = "version"` and `dep = { version = "..." }` forms.
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 = [];
@@ -3,18 +3,18 @@ import { z } from "zod";
3
3
 
4
4
  //#region src/lib/sources/xcode-info-plist.d.ts
5
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>>;
6
+ applicationCategory: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
7
+ author: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
8
+ authorEmail: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
9
+ copyrightHolder: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
10
+ copyrightYear: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
11
+ description: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
12
+ identifier: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
13
+ name: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
14
+ operatingSystems: z.ZodDefault<z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>>;
15
+ processorRequirements: z.ZodDefault<z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>>;
16
+ url: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
17
+ version: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
18
18
  }, z.core.$strip>;
19
19
  type InfoPlist = z.infer<typeof infoPlistSchema>;
20
20
  type XcodeInfoPlistData = OneOrMany<SourceRecord<InfoPlist>> | undefined;
@@ -11,9 +11,10 @@ import plist from "plist";
11
11
  * Source and parser for Apple `Info.plist` files.
12
12
  *
13
13
  * Handles three flavors of Info.plist:
14
- * - Standard Apple app/framework bundles (CFBundle* keys)
15
- * - Alfred workflow plists (name, createdby, bundleid, etc.)
16
- * - TextMate bundle plists (name, contactName, contactEmailRot13, etc.)
14
+ *
15
+ * - Standard Apple app/framework bundles (CFBundle* keys)
16
+ * - Alfred workflow plists (name, createdby, bundleid, etc.)
17
+ * - TextMate bundle plists (name, contactName, contactEmailRot13, etc.)
17
18
  *
18
19
  * Uses the `plist` npm package to parse XML plist format.
19
20
  */
@@ -23,23 +24,38 @@ const ALL_RIGHTS_RESERVED_REGEX = /\.\s*all\s+rights\s+reserved\.?/i;
23
24
  const TRAILING_PUNCTUATION_REGEX = /[.,;]+$/;
24
25
  const PROCESSOR_ARCH_REGEX = /^(?:arm|x86|i386)/i;
25
26
  const infoPlistSchema = z.object({
27
+ /** Application category (humanized from UTI). */
26
28
  applicationCategory: nonEmptyString,
29
+ /** Author / creator name. */
27
30
  author: nonEmptyString,
31
+ /** Author email (decoded from ROT13 for TextMate bundles). */
28
32
  authorEmail: nonEmptyString,
33
+ /** Copyright holder name. */
29
34
  copyrightHolder: nonEmptyString,
35
+ /** Copyright year. */
30
36
  copyrightYear: nonEmptyString,
37
+ /** Description / readme text. */
31
38
  description: nonEmptyString,
39
+ /** Bundle identifier (e.g. "com.example.app"). */
32
40
  identifier: nonEmptyString,
41
+ /** Display name of the app or bundle. */
33
42
  name: nonEmptyString,
43
+ /** Inferred operating systems. */
34
44
  operatingSystems: stringArray,
45
+ /** Processor architecture requirements (e.g. "armv7"). */
35
46
  processorRequirements: stringArray,
47
+ /** Homepage URL. */
36
48
  url: optionalUrl,
49
+ /** Version string. */
37
50
  version: nonEmptyString
38
51
  });
39
52
  /** Xcode build variable pattern: $(VAR) or ${VAR}. */
40
53
  const XCODE_VARIABLE_RE = /\$[({][^)}]+[)}]/;
54
+ /** XML comment, including malformed ones with `--` inside. */
55
+ const XML_COMMENT_RE = /<!--[\s\S]*?-->/g;
41
56
  /**
42
- * Map DTPlatformName / CFBundleSupportedPlatforms values to human-readable OS names.
57
+ * Map DTPlatformName / CFBundleSupportedPlatforms values to human-readable OS
58
+ * names.
43
59
  */
44
60
  const PLATFORM_NAME_MAP = {
45
61
  appletvos: "tvOS",
@@ -52,18 +68,12 @@ const PLATFORM_NAME_MAP = {
52
68
  xros: "visionOS"
53
69
  };
54
70
  /**
55
- * Parse an `Info.plist` content string into a structured object.
56
- * Returns undefined if the plist is malformed or not a dictionary.
71
+ * Parse an `Info.plist` content string into a structured object. Returns
72
+ * undefined if the plist is malformed or not a dictionary.
57
73
  */
58
74
  function parse(content) {
59
- let data;
60
- try {
61
- const parsed = plist.parse(content);
62
- if (!is.plainObject(parsed)) return;
63
- data = parsed;
64
- } catch {
65
- return;
66
- }
75
+ const data = tryParsePlist(content) ?? tryParsePlist(content.replaceAll(XML_COMMENT_RE, "").trimStart());
76
+ if (!data) return;
67
77
  const name = getString(data, "CFBundleDisplayName") ?? getString(data, "CFBundleName") ?? getString(data, "name");
68
78
  const description = getString(data, "description");
69
79
  const version = getString(data, "CFBundleShortVersionString") ?? getString(data, "version") ?? getString(data, "CFBundleVersion");
@@ -90,15 +100,27 @@ function parse(content) {
90
100
  });
91
101
  }
92
102
  /**
93
- * Get a string value from a plist dict, returning undefined for
94
- * empty strings, whitespace-only strings, and Xcode variable placeholders.
103
+ * Run `plist.parse` and return the result only if it is a plain-object dict.
104
+ * Returns undefined on any throw or non-dict root.
105
+ */
106
+ function tryParsePlist(content) {
107
+ try {
108
+ const parsed = plist.parse(content);
109
+ return is.plainObject(parsed) ? parsed : void 0;
110
+ } catch {
111
+ return;
112
+ }
113
+ }
114
+ /**
115
+ * Get a string value from a plist dict, returning undefined for empty strings,
116
+ * whitespace-only strings, and Xcode variable placeholders.
95
117
  */
96
118
  function getString(data, key) {
97
119
  const value = data[key];
98
- if (typeof value !== "string") return void 0;
120
+ if (typeof value !== "string") return;
99
121
  const trimmed = value.trim();
100
- if (trimmed.length === 0) return void 0;
101
- if (XCODE_VARIABLE_RE.test(trimmed)) return void 0;
122
+ if (trimmed.length === 0) return;
123
+ if (XCODE_VARIABLE_RE.test(trimmed)) return;
102
124
  return trimmed;
103
125
  }
104
126
  /**
@@ -111,8 +133,8 @@ function rot13(value) {
111
133
  });
112
134
  }
113
135
  /**
114
- * Convert an Apple UTI application category to a human-readable string.
115
- * e.g. "public.app-category.developer-tools" → "Developer Tools"
136
+ * Convert an Apple UTI application category to a human-readable string. e.g.
137
+ * "public.app-category.developer-tools" → "Developer Tools"
116
138
  */
117
139
  function humanizeCategory(uti) {
118
140
  if (!uti.startsWith("public.app-category.")) return uti;
@@ -123,11 +145,12 @@ function humanizeCategory(uti) {
123
145
  */
124
146
  function parseApplicationCategory(data) {
125
147
  const category = getString(data, "LSApplicationCategoryType");
126
- if (!category) return void 0;
148
+ if (!category) return;
127
149
  return humanizeCategory(category);
128
150
  }
129
151
  /**
130
- * Parse copyright information from NSHumanReadableCopyright or CFBundleGetInfoString.
152
+ * Parse copyright information from NSHumanReadableCopyright or
153
+ * CFBundleGetInfoString.
131
154
  */
132
155
  function parseCopyright(data) {
133
156
  const copyrightSource = getString(data, "NSHumanReadableCopyright") ?? getString(data, "CFBundleGetInfoString");
@@ -177,7 +200,8 @@ function parseOperatingSystems(data) {
177
200
  return results;
178
201
  }
179
202
  /**
180
- * Extract processor architecture requirements from UIRequiredDeviceCapabilities.
203
+ * Extract processor architecture requirements from
204
+ * UIRequiredDeviceCapabilities.
181
205
  */
182
206
  function parseProcessorRequirements(data) {
183
207
  const capabilities = data.UIRequiredDeviceCapabilities;
@@ -3,17 +3,17 @@ import { z } from "zod";
3
3
 
4
4
  //#region src/lib/sources/xcode-project-pbxproj.d.ts
5
5
  declare const pbxprojSchema: z.ZodObject<{
6
- copyrightHolder: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
7
- copyrightYear: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
6
+ copyrightHolder: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
7
+ copyrightYear: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
8
8
  dependencies: z.ZodArray<z.ZodObject<{
9
9
  url: z.ZodString;
10
10
  }, z.core.$strip>>;
11
- identifier: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
12
- name: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
13
- operatingSystems: z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>;
14
- organizationName: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
15
- programmingLanguage: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
16
- version: z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>;
11
+ identifier: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
12
+ name: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
13
+ operatingSystems: z.ZodDefault<z.ZodPipe<z.ZodTransform<string[], unknown>, z.ZodArray<z.ZodString>>>;
14
+ organizationName: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
15
+ programmingLanguage: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
16
+ version: z.ZodOptional<z.ZodPipe<z.ZodTransform<string | undefined, unknown>, z.ZodOptional<z.ZodString>>>;
17
17
  }, z.core.$strip>;
18
18
  type Pbxproj = z.infer<typeof pbxprojSchema>;
19
19
  type XcodeProjectPbxprojData = OneOrMany<SourceRecord<Pbxproj>> | undefined;
@@ -9,13 +9,14 @@ import { PBXNativeTarget, XCRemoteSwiftPackageReference, XcodeProject } from "@b
9
9
  /**
10
10
  * Source and parser for Xcode `.pbxproj` project files.
11
11
  *
12
- * Uses the `@bacons/xcode` package to parse the binary/ASCII plist format
13
- * and navigate the Xcode project object graph.
12
+ * Uses the `@bacons/xcode` package to parse the binary/ASCII plist format and
13
+ * navigate the Xcode project object graph.
14
14
  *
15
15
  * Extracts metadata from:
16
- * - Project-level attributes (organizationName)
17
- * - Build settings on the main app target (Release config preferred)
18
- * - Swift Package Manager dependencies
16
+ *
17
+ * - Project-level attributes (organizationName)
18
+ * - Build settings on the main app target (Release config preferred)
19
+ * - Swift Package Manager dependencies
19
20
  */
20
21
  const COPYRIGHT_YEAR_REGEX = /(?:©|\(c\)|copyright)\s*(\d{4})/i;
21
22
  const COPYRIGHT_HOLDER_REGEX = /(?:©|\(c\)|copyright)\s*\d{4}\s*(.+)/i;
@@ -23,14 +24,23 @@ const ALL_RIGHTS_RESERVED_REGEX = /\.\s*all\s+rights\s+reserved\.?/i;
23
24
  const TRAILING_PUNCTUATION_REGEX = /[.,;]+$/;
24
25
  const pbxprojDependencySchema = z.object({ url: z.string() });
25
26
  const pbxprojSchema = z.object({
27
+ /** Copyright holder name. */
26
28
  copyrightHolder: nonEmptyString,
29
+ /** Copyright year. */
27
30
  copyrightYear: nonEmptyString,
31
+ /** Swift Package Manager dependencies. */
28
32
  dependencies: z.array(pbxprojDependencySchema),
33
+ /** Bundle identifier (e.g. "com.example.app"). */
29
34
  identifier: nonEmptyString,
35
+ /** Display name of the app or target. */
30
36
  name: nonEmptyString,
37
+ /** Inferred operating systems with deployment targets. */
31
38
  operatingSystems: stringArray,
39
+ /** Organization name from project attributes. */
32
40
  organizationName: nonEmptyString,
41
+ /** Detected programming language (Swift or Objective-C). */
33
42
  programmingLanguage: nonEmptyString,
43
+ /** Marketing version string. */
34
44
  version: nonEmptyString
35
45
  });
36
46
  /** Xcode build variable pattern: $(VAR) or ${VAR}. */
@@ -71,8 +81,8 @@ const DEPLOYMENT_TARGETS = [
71
81
  }
72
82
  ];
73
83
  /**
74
- * Parse a `.pbxproj` file into a structured object.
75
- * Returns undefined if the file is malformed or cannot be parsed.
84
+ * Parse a `.pbxproj` file into a structured object. Returns undefined if the
85
+ * file is malformed or cannot be parsed.
76
86
  */
77
87
  function parse(filePath) {
78
88
  let project;
@@ -123,15 +133,15 @@ function parse(filePath) {
123
133
  });
124
134
  }
125
135
  /**
126
- * Get a string build setting, filtering out empty strings and unresolved
127
- * Xcode variable placeholders. Handles both string and numeric values.
136
+ * Get a string build setting, filtering out empty strings and unresolved Xcode
137
+ * variable placeholders. Handles both string and numeric values.
128
138
  */
129
139
  function cleanString(value) {
130
140
  if (typeof value === "number") return String(value);
131
- if (typeof value !== "string") return void 0;
141
+ if (typeof value !== "string") return;
132
142
  const trimmed = value.trim();
133
- if (trimmed.length === 0) return void 0;
134
- if (XCODE_VARIABLE_RE.test(trimmed)) return void 0;
143
+ if (trimmed.length === 0) return;
144
+ if (XCODE_VARIABLE_RE.test(trimmed)) return;
135
145
  return trimmed;
136
146
  }
137
147
  /**
@@ -2,11 +2,10 @@ import { Template } from "../metadata-types.js";
2
2
  //#region src/lib/templates/codemeta-json.d.ts
3
3
  type TemplateDataCodemetaJson = ReturnType<typeof codemetaJson>;
4
4
  /**
5
- * A JSON-friendly derivation of the `codemeta` template.
6
- * Produces the same aggregated metadata but parses it through a strict
7
- * schema,stripping JSON-LD artifacts (like `@context` and `@type`) to yield
8
- * plain JSON suitable for consumption by tools that don't care to understand
9
- * JSON-LD.
5
+ * A JSON-friendly derivation of the `codemeta` template. Produces the same
6
+ * aggregated metadata but parses it through a strict schema,stripping JSON-LD
7
+ * artifacts (like `@context` and `@type`) to yield plain JSON suitable for
8
+ * consumption by tools that don't care to understand JSON-LD.
10
9
  *
11
10
  * This template also provides a handy baseline normalization abstraction for
12
11
  * the other templates.
@@ -3,11 +3,10 @@ import { codeMetaJsonDataSchema } from "../sources/codemeta-json.js";
3
3
  import { codemeta } from "./codemeta.js";
4
4
  //#region src/lib/templates/codemeta-json.ts
5
5
  /**
6
- * A JSON-friendly derivation of the `codemeta` template.
7
- * Produces the same aggregated metadata but parses it through a strict
8
- * schema,stripping JSON-LD artifacts (like `@context` and `@type`) to yield
9
- * plain JSON suitable for consumption by tools that don't care to understand
10
- * JSON-LD.
6
+ * A JSON-friendly derivation of the `codemeta` template. Produces the same
7
+ * aggregated metadata but parses it through a strict schema,stripping JSON-LD
8
+ * artifacts (like `@context` and `@type`) to yield plain JSON suitable for
9
+ * consumption by tools that don't care to understand JSON-LD.
11
10
  *
12
11
  * This template also provides a handy baseline normalization abstraction for
13
12
  * the other templates.
@@ -13,14 +13,14 @@ import is from "@sindresorhus/is";
13
13
  * ## Cascade strategy
14
14
  *
15
15
  * For **ecosystem-derived fields** (name, version, description, author,
16
- * license, dependencies, keywords, …) the ecosystem manifest is canonical.
17
- * This keeps the output fresh when e.g. a new dependency is added to
18
- * package.json, and makes the round-trip stable: generate → save as
19
- * codemeta.json → regenerate → identical output.
16
+ * license, dependencies, keywords, …) the ecosystem manifest is canonical. This
17
+ * keeps the output fresh when e.g. a new dependency is added to package.json,
18
+ * and makes the round-trip stable: generate → save as codemeta.json →
19
+ * regenerate → identical output.
20
20
  *
21
21
  * For **codemeta-specific fields** that only exist in codemeta.json
22
- * (developmentStatus, funding, buildInstructions, …) the existing
23
- * codemeta.json is the source of truth.
22
+ * (developmentStatus, funding, buildInstructions, …) the existing codemeta.json
23
+ * is the source of truth.
24
24
  *
25
25
  * ## Software type inference
26
26
  *
@@ -287,7 +287,6 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
287
287
  const releaseNotes = cm?.data.releaseNotes;
288
288
  const installUrl = cm?.data.installUrl;
289
289
  const relatedLink = cm?.data.relatedLink;
290
- const targetProduct = void 0;
291
290
  return stripUndefined({
292
291
  "@context": "https://w3id.org/codemeta/3.0",
293
292
  "@type": "SoftwareSourceCode",
@@ -325,15 +324,14 @@ const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXm
325
324
  softwareHelp,
326
325
  softwareRequirements,
327
326
  softwareSuggestions,
328
- targetProduct,
327
+ targetProduct: void 0,
329
328
  url,
330
329
  version
331
330
  });
332
331
  });
333
332
  /**
334
- * Extract authors from a gemspec record.
335
- * Gemspec has `authors: string[]` and a separate `email: string | string[]`.
336
- * We pair them by index where possible.
333
+ * Extract authors from a gemspec record. Gemspec has `authors: string[]` and a
334
+ * separate `email: string | string[]`. We pair them by index where possible.
337
335
  */
338
336
  function gemspecAuthors(gem) {
339
337
  if (gem === void 0) return [];
@@ -344,9 +342,9 @@ function gemspecAuthors(gem) {
344
342
  }));
345
343
  }
346
344
  /**
347
- * Takes ecosystem persons (which may include undefined) and codemeta fallback persons.
348
- * Uses ecosystem if any are present, otherwise falls back.
349
- * Always deduplicates by name.
345
+ * Takes ecosystem persons (which may include undefined) and codemeta fallback
346
+ * persons. Uses ecosystem if any are present, otherwise falls back. Always
347
+ * deduplicates by name.
350
348
  */
351
349
  function resolvePersonsOrOrgs(ecosystemPersons, fallbackPersons) {
352
350
  const ecosystem = ecosystemPersons.filter((p) => p !== void 0);
@@ -389,11 +387,12 @@ function collectDevelopmentDeps(sources) {
389
387
  * Convert a Record<name, version> dependency map to CodemetaDependencyLd[].
390
388
  */
391
389
  function objectEntriesToDeps(deps) {
392
- if (deps === void 0) return void 0;
390
+ if (deps === void 0) return;
393
391
  return Object.entries(deps).map(([depName, depVersion]) => toDependencyLd(depName, depVersion));
394
392
  }
395
393
  /**
396
- * Parse a PEP 508 dependency string ("package>=1.0") into a CodemetaDependencyLd.
394
+ * Parse a PEP 508 dependency string ("package>=1.0") into a
395
+ * CodemetaDependencyLd.
397
396
  */
398
397
  function parsePep508Dep(dep) {
399
398
  const trimmed = dep.trim();
@@ -408,7 +407,7 @@ function parsePep508Dep(dep) {
408
407
  * Extract URL from package.json repository field (string or {url}).
409
408
  */
410
409
  function repositoryUrlFromPackageJson(repository) {
411
- if (repository === void 0) return void 0;
410
+ if (repository === void 0) return;
412
411
  if (typeof repository === "string") return repository;
413
412
  return repository.url;
414
413
  }
@@ -416,7 +415,7 @@ function repositoryUrlFromPackageJson(repository) {
416
415
  * Extract URL from package.json bugs field.
417
416
  */
418
417
  function bugsUrlFromPackageJson(bugs) {
419
- if (bugs === void 0) return void 0;
418
+ if (bugs === void 0) return;
420
419
  return bugs.url;
421
420
  }
422
421
  /**
@@ -427,11 +426,11 @@ function firstPomLicense(pom) {
427
426
  return pomLicense?.name ?? pomLicense?.url;
428
427
  }
429
428
  /**
430
- * Resolve Python pyproject.toml license field to a string.
431
- * Can be a string (SPDX ID) or `{ spdx?: string; text?: string; file?: string }`.
429
+ * Resolve Python pyproject.toml license field to a string. Can be a string
430
+ * (SPDX ID) or `{ spdx?: string; text?: string; file?: string }`.
432
431
  */
433
432
  function resolvePythonLicense(pythonLicense) {
434
- if (pythonLicense === void 0) return void 0;
433
+ if (pythonLicense === void 0) return;
435
434
  if (typeof pythonLicense === "string") return pythonLicense;
436
435
  return pythonLicense.spdx ?? pythonLicense.text;
437
436
  }
@@ -439,7 +438,7 @@ function resolvePythonLicense(pythonLicense) {
439
438
  * Resolve codemeta license field (string or string[]) to first string.
440
439
  */
441
440
  function resolveCmLicense(cmLicense) {
442
- if (cmLicense === void 0) return void 0;
441
+ if (cmLicense === void 0) return;
443
442
  return Array.isArray(cmLicense) ? cmLicense[0] : cmLicense;
444
443
  }
445
444
  /**
@@ -454,10 +453,11 @@ function deduplicateStrings(strings) {
454
453
  return [...seen.values()];
455
454
  }
456
455
  /**
457
- * Case-insensitive lookup in a string record (e.g. pyproject.toml `[project.urls]`).
456
+ * Case-insensitive lookup in a string record (e.g. pyproject.toml
457
+ * `[project.urls]`).
458
458
  */
459
459
  function caseInsensitiveLookup(record, key) {
460
- if (record === void 0) return void 0;
460
+ if (record === void 0) return;
461
461
  const lowerKey = key.toLowerCase();
462
462
  for (const [k, v] of Object.entries(record)) if (k.toLowerCase() === lowerKey) return v;
463
463
  }
@@ -466,7 +466,7 @@ function caseInsensitiveLookup(record, key) {
466
466
  * homepage URLs derived from repository URLs.
467
467
  */
468
468
  function stripReadmeFragment(url) {
469
- if (url === void 0) return void 0;
469
+ if (url === void 0) return;
470
470
  return url.endsWith("#readme") ? url.slice(0, -7) : url;
471
471
  }
472
472
  /**
@@ -474,19 +474,19 @@ function stripReadmeFragment(url) {
474
474
  * CodeMeta dates are `schema:Date`, not `schema:DateTime`.
475
475
  */
476
476
  function toDateOnly(value) {
477
- if (value === void 0) return void 0;
477
+ if (value === void 0) return;
478
478
  if (DATE_ONLY_REGEX.test(value)) return value;
479
479
  const match = DATETIME_DATE_REGEX.exec(value);
480
480
  if (match) return match[1];
481
481
  return value;
482
482
  }
483
483
  /**
484
- * Build a URL for the project's README.
485
- * Prefers a web URL on the remote service (e.g. GitHub blob link) when a
486
- * code repository URL is available, otherwise falls back to the local source path.
484
+ * Build a URL for the project's README. Prefers a web URL on the remote service
485
+ * (e.g. GitHub blob link) when a code repository URL is available, otherwise
486
+ * falls back to the local source path.
487
487
  */
488
488
  function readmeUrl(readmeRecord, repoUrl, defaultBranch, basePath) {
489
- if (readmeRecord === void 0) return void 0;
489
+ if (readmeRecord === void 0) return;
490
490
  const repoRelativePath = basePath === void 0 ? basename(readmeRecord.source) : relative(basePath, readmeRecord.source).replaceAll("\\", "/");
491
491
  if (is.nonEmptyStringAndNotWhitespace(repoUrl) && repoUrl.includes("github.com")) {
492
492
  const branch = defaultBranch ?? "main";
@@ -2,8 +2,8 @@ import { Template } from "../metadata-types.js";
2
2
  //#region src/lib/templates/metadata.d.ts
3
3
  type TemplateDataMetadata = ReturnType<typeof metadata>;
4
4
  /**
5
- * A minimal metadata template for populating a GitHub repository's
6
- * description, homepage, and topics via metadata.json / metadata.yaml.
5
+ * A minimal metadata template for populating a GitHub repository's description,
6
+ * homepage, and topics via metadata.json / metadata.yaml.
7
7
  *
8
8
  * Builds on the codemeta template for baseline values, then lets any
9
9
  * metadata.json source fields override the result.
@@ -6,15 +6,15 @@ import { codemetaJson } from "./codemeta-json.js";
6
6
  * Strip `git+` prefix and `.git` suffix from a URL.
7
7
  */
8
8
  function normalizeGitUrl(url) {
9
- if (url === void 0) return void 0;
9
+ if (url === void 0) return;
10
10
  let normalized = url;
11
11
  if (normalized.startsWith("git+")) normalized = normalized.slice(4);
12
12
  if (normalized.endsWith(".git")) normalized = normalized.slice(0, -4);
13
13
  return normalized;
14
14
  }
15
15
  /**
16
- * A minimal metadata template for populating a GitHub repository's
17
- * description, homepage, and topics via metadata.json / metadata.yaml.
16
+ * A minimal metadata template for populating a GitHub repository's description,
17
+ * homepage, and topics via metadata.json / metadata.yaml.
18
18
  *
19
19
  * Builds on the codemeta template for baseline values, then lets any
20
20
  * metadata.json source fields override the result.
@@ -2,8 +2,9 @@
2
2
  /**
3
3
  * Helpers for building codemeta JSON-LD objects.
4
4
  *
5
- * Provides type-safe constructors for Person/Organization and SoftwareApplication
6
- * dependency nodes, plus deduplication and license URL normalization.
5
+ * Provides type-safe constructors for Person/Organization and
6
+ * SoftwareApplication dependency nodes, plus deduplication and license URL
7
+ * normalization.
7
8
  */
8
9
  /**
9
10
  * An Organization node in codemeta JSON-LD.