metascope 0.8.4 → 0.9.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 (103) hide show
  1. package/dist/bin/cli.js +30426 -29237
  2. package/dist/bin/{jiti-DDHyYNLW.js → jiti-B26uDQuv.js} +2 -2
  3. package/dist/bin/renovate-CEC0BhMB.js +1 -0
  4. package/dist/bin/shared-Ch5JsD6s.js +8 -0
  5. package/dist/bin/shared2-Dhjk_Okb.js +1 -0
  6. package/dist/bin/web-tree-sitter.wasm +0 -0
  7. package/dist/lib/data/license-urls.js +2904 -0
  8. package/dist/lib/file-matching.js +5 -2
  9. package/dist/lib/log.d.ts +0 -1
  10. package/dist/lib/metadata-types.d.ts +16 -9
  11. package/dist/lib/metadata.d.ts +0 -1
  12. package/dist/lib/metadata.js +5 -5
  13. package/dist/lib/package.js +1 -1
  14. package/dist/lib/parsers/configparser-parser.js +14 -12
  15. package/dist/lib/parsers/gemspec-parser.js +41 -42
  16. package/dist/lib/parsers/go-mod-parser.js +51 -45
  17. package/dist/lib/parsers/makefile-config-parser.js +7 -6
  18. package/dist/lib/parsers/properties-parser.js +1 -1
  19. package/dist/lib/parsers/rfc822-header-parser.js +8 -6
  20. package/dist/lib/parsers/setup-py-parser.js +28 -24
  21. package/dist/lib/source.d.ts +6 -2
  22. package/dist/lib/sources/arduino-library-properties.d.ts +0 -1
  23. package/dist/lib/sources/arduino-library-properties.js +6 -7
  24. package/dist/lib/sources/cinder-cinderblock-xml.d.ts +0 -1
  25. package/dist/lib/sources/cinder-cinderblock-xml.js +5 -5
  26. package/dist/lib/sources/code-stats.d.ts +3 -2
  27. package/dist/lib/sources/codemeta-json.d.ts +0 -1
  28. package/dist/lib/sources/codemeta-json.js +21 -20
  29. package/dist/lib/sources/dependency-updates.d.ts +17 -8
  30. package/dist/lib/sources/dependency-updates.js +38 -34
  31. package/dist/lib/sources/file-stats.d.ts +7 -4
  32. package/dist/lib/sources/git-config.d.ts +0 -1
  33. package/dist/lib/sources/git-stats.d.ts +47 -24
  34. package/dist/lib/sources/git-stats.js +51 -33
  35. package/dist/lib/sources/github-actions.d.ts +0 -1
  36. package/dist/lib/sources/github-actions.js +4 -3
  37. package/dist/lib/sources/github.d.ts +156 -78
  38. package/dist/lib/sources/github.js +11 -8
  39. package/dist/lib/sources/go-go-mod.d.ts +0 -1
  40. package/dist/lib/sources/go-goreleaser-yaml.d.ts +0 -1
  41. package/dist/lib/sources/go-goreleaser-yaml.js +5 -3
  42. package/dist/lib/sources/java-pom-xml.d.ts +0 -1
  43. package/dist/lib/sources/java-pom-xml.js +12 -12
  44. package/dist/lib/sources/license-file.d.ts +0 -1
  45. package/dist/lib/sources/metadata-file.d.ts +0 -1
  46. package/dist/lib/sources/metadata-file.js +9 -10
  47. package/dist/lib/sources/metascope.d.ts +9 -5
  48. package/dist/lib/sources/node-npm-registry.d.ts +21 -11
  49. package/dist/lib/sources/node-npm-registry.js +12 -6
  50. package/dist/lib/sources/node-package-json.d.ts +0 -1
  51. package/dist/lib/sources/obsidian-plugin-manifest-json.d.ts +17 -9
  52. package/dist/lib/sources/obsidian-plugin-manifest-json.js +2 -2
  53. package/dist/lib/sources/obsidian-plugin-registry.d.ts +3 -2
  54. package/dist/lib/sources/obsidian-plugin-registry.js +2 -1
  55. package/dist/lib/sources/openframeworks-addon-config-mk.d.ts +0 -1
  56. package/dist/lib/sources/openframeworks-install-xml.d.ts +0 -1
  57. package/dist/lib/sources/openframeworks-install-xml.js +3 -3
  58. package/dist/lib/sources/processing-library-properties.d.ts +0 -1
  59. package/dist/lib/sources/processing-library-properties.js +9 -10
  60. package/dist/lib/sources/processing-sketch-properties.d.ts +0 -1
  61. package/dist/lib/sources/processing-sketch-properties.js +13 -20
  62. package/dist/lib/sources/publiccode-yaml.d.ts +0 -1
  63. package/dist/lib/sources/publiccode-yaml.js +61 -58
  64. package/dist/lib/sources/python-pkg-info.d.ts +0 -1
  65. package/dist/lib/sources/python-pkg-info.js +6 -5
  66. package/dist/lib/sources/python-pypi-registry.d.ts +21 -11
  67. package/dist/lib/sources/python-pypi-registry.js +23 -16
  68. package/dist/lib/sources/python-pyproject-toml.d.ts +0 -1
  69. package/dist/lib/sources/python-setup-cfg.d.ts +2 -3
  70. package/dist/lib/sources/python-setup-cfg.js +10 -9
  71. package/dist/lib/sources/python-setup-py.d.ts +0 -1
  72. package/dist/lib/sources/readme-file.d.ts +0 -1
  73. package/dist/lib/sources/readme-file.js +4 -3
  74. package/dist/lib/sources/ruby-gemspec.d.ts +0 -1
  75. package/dist/lib/sources/rust-cargo-toml.d.ts +0 -1
  76. package/dist/lib/sources/rust-cargo-toml.js +1 -1
  77. package/dist/lib/sources/xcode-info-plist.d.ts +0 -1
  78. package/dist/lib/sources/xcode-info-plist.js +29 -31
  79. package/dist/lib/sources/xcode-project-pbxproj.d.ts +0 -1
  80. package/dist/lib/sources/xcode-project-pbxproj.js +17 -16
  81. package/dist/lib/templates/codemeta-json.d.ts +1 -0
  82. package/dist/lib/templates/codemeta.d.ts +1 -0
  83. package/dist/lib/templates/codemeta.js +98 -89
  84. package/dist/lib/templates/frontmatter.d.ts +2 -1
  85. package/dist/lib/templates/frontmatter.js +1 -1
  86. package/dist/lib/templates/index.d.ts +2 -1
  87. package/dist/lib/templates/index.js +1 -1
  88. package/dist/lib/templates/metadata.d.ts +1 -0
  89. package/dist/lib/templates/project.d.ts +1 -0
  90. package/dist/lib/utilities/codemeta-helpers.js +14 -13
  91. package/dist/lib/utilities/fetch.js +18 -2
  92. package/dist/lib/utilities/formatting.js +1 -1
  93. package/dist/lib/utilities/github.js +2 -2
  94. package/dist/lib/utilities/license-identification.d.ts +9 -4
  95. package/dist/lib/utilities/license-identification.js +37 -23
  96. package/dist/lib/utilities/template-helpers.d.ts +7 -5
  97. package/dist/lib/utilities/template-helpers.js +15 -14
  98. package/dist/lib/utilities/tree-sitter-wasm.d.ts +0 -1
  99. package/dist/lib/utilities/tree-sitter-wasm.js +1 -1
  100. package/package.json +18 -17
  101. package/readme.md +13 -11
  102. package/dist/bin/renovate-CpDMbQZd.js +0 -1
  103. package/dist/bin/shared-Dix5HPlG.js +0 -6
@@ -44,14 +44,14 @@ function parse$1(content, format) {
44
44
  return;
45
45
  }
46
46
  if (data === void 0) return;
47
- const repository = isString(data.repository) ? normalizeRepoUrl(data.repository) : void 0;
48
- const homepage = nonEmpty(data.homepage) ?? nonEmpty(data.url) ?? repository ?? nonEmpty(data.website);
47
+ const repo = isString(data.repository) ? normalizeRepoUrl(data.repository) : void 0;
48
+ const homepage = nonEmpty(data.homepage) ?? nonEmpty(data.url) ?? repo ?? nonEmpty(data.website);
49
49
  const keywords = parseKeywords(data.keywords) ?? parseKeywords(data.tags) ?? parseKeywords(data.topics) ?? [];
50
50
  return metadataSchema.parse({
51
51
  description: data.description,
52
52
  homepage,
53
53
  keywords,
54
- repository
54
+ repository: repo
55
55
  });
56
56
  }
57
57
  /** Return a trimmed string if the value is a non-empty string, else undefined. */
@@ -98,13 +98,12 @@ const metadataFileSource = defineSource({
98
98
  key: "metadataFile",
99
99
  async parse(input, context) {
100
100
  const format = getFormat(input);
101
- if (format !== void 0) {
102
- const data = parse$1(await readFile(resolve(context.options.path, input), "utf8"), format);
103
- if (data !== void 0) return {
104
- data,
105
- source: input
106
- };
107
- }
101
+ if (format === void 0) return;
102
+ const data = parse$1(await readFile(resolve(context.options.path, input), "utf8"), format);
103
+ return data === void 0 ? void 0 : {
104
+ data,
105
+ source: input
106
+ };
108
107
  },
109
108
  phase: 1
110
109
  });
@@ -1,12 +1,16 @@
1
1
  import { SourceRecord } from "../source.js";
2
2
  import { GetMetadataBaseOptions } from "../metadata-types.js";
3
-
4
3
  //#region src/lib/sources/metascope.d.ts
5
4
  type MetascopeInfo = {
6
- /** Total scan duration in milliseconds. */durationMs: number; /** Resolved options used for this scan (credentials excluded). */
7
- options: Omit<GetMetadataBaseOptions, 'credentials'>; /** ISO 8601 timestamp of when the scan was performed. */
8
- scannedAt: string; /** Version of the metascope library used. */
9
- version: string; /** Workspaces Resolved */
5
+ /** Total scan duration in milliseconds. */
6
+ durationMs: number;
7
+ /** Resolved options used for this scan (credentials excluded). */
8
+ options: Omit<GetMetadataBaseOptions, 'credentials'>;
9
+ /** ISO 8601 timestamp of when the scan was performed. */
10
+ scannedAt: string;
11
+ /** Version of the metascope library used. */
12
+ version: string;
13
+ /** Workspaces Resolved */
10
14
  workspaceDirectories: string[];
11
15
  };
12
16
  type MetascopeData = SourceRecord<MetascopeInfo> | undefined;
@@ -1,17 +1,27 @@
1
1
  import { OneOrMany, SourceRecord } from "../source.js";
2
-
3
2
  //#region src/lib/sources/node-npm-registry.d.ts
4
3
  type NodeNpmRegistryInfo = {
5
- /** Deprecation message, if the package is deprecated. */deprecated?: string; /** Downloads in the last month. */
6
- downloadsMonthly?: number; /** All-time total downloads. */
7
- downloadsTotal?: number; /** Downloads in the last week. */
8
- downloadsWeekly?: number; /** Downloads in the last year. */
9
- downloadsYearly?: number; /** Number of files in the published package. */
10
- fileCount?: number; /** Whether the package exposes TypeScript types. */
11
- hasTypes?: boolean; /** ISO 8601 date the package was last published. */
12
- publishDateLatest?: string; /** Unpacked size of the published package in bytes. */
13
- unpackedSizeBytes?: number; /** The npmjs.com URL for the package. */
14
- url?: string; /** Latest published version string. */
4
+ /** Deprecation message, if the package is deprecated. */
5
+ deprecated?: string;
6
+ /** Downloads in the last month. */
7
+ downloadsMonthly?: number;
8
+ /** All-time total downloads. */
9
+ downloadsTotal?: number;
10
+ /** Downloads in the last week. */
11
+ downloadsWeekly?: number;
12
+ /** Downloads in the last year. */
13
+ downloadsYearly?: number;
14
+ /** Number of files in the published package. */
15
+ fileCount?: number;
16
+ /** Whether the package exposes TypeScript types. */
17
+ hasTypes?: boolean;
18
+ /** ISO 8601 date the package was last published. */
19
+ publishDateLatest?: string;
20
+ /** Unpacked size of the published package in bytes. */
21
+ unpackedSizeBytes?: number;
22
+ /** The npmjs.com URL for the package. */
23
+ url?: string;
24
+ /** Latest published version string. */
15
25
  versionLatest?: string;
16
26
  };
17
27
  type NodeNpmRegistryData = OneOrMany<SourceRecord<NodeNpmRegistryInfo>> | undefined;
@@ -18,20 +18,26 @@ const nodeNpmRegistrySource = defineSource({
18
18
  log.debug(`Missing nodePackageJson in source context metadata for ${context.options.path}, extracting it now...`);
19
19
  packages = ensureArray(await nodePackageJsonSource.extract(context));
20
20
  }
21
- return packages.filter((packageJson) => {
22
- if (packageJson.data.private === true || packageJson.data.publishConfig?.access === "restricted") {
23
- log.debug(`Skipping NPM registry lookup for "${packageJson.data.name}" in "${context.options.path}" because it is a private package`);
21
+ return packages.filter((package_) => {
22
+ if (package_.data.private === true || package_.data.publishConfig?.access === "restricted") {
23
+ log.debug(`Skipping NPM registry lookup for "${package_.data.name}" in "${context.options.path}" because it is a private package`);
24
24
  return false;
25
25
  }
26
26
  return true;
27
- }).map((packageJson) => packageJson.data.name);
27
+ }).map((package_) => package_.data.name);
28
28
  },
29
29
  key: "nodeNpmRegistry",
30
30
  async parse(input) {
31
31
  log.debug("Extracting npm metadata...");
32
32
  const name = input;
33
33
  const [metadata, downloadsWeekly, downloadsMonthly, downloadsYearly, downloadsTotal] = await Promise.all([
34
- packageJson(name, { fullMetadata: true }).catch(() => void 0),
34
+ (async () => {
35
+ try {
36
+ return await packageJson(name, { fullMetadata: true });
37
+ } catch {
38
+ return;
39
+ }
40
+ })(),
35
41
  fetchDownloads(name, "last-week"),
36
42
  fetchDownloads(name, "last-month"),
37
43
  fetchDownloads(name, "last-year"),
@@ -45,7 +51,7 @@ const nodeNpmRegistrySource = defineSource({
45
51
  data: {
46
52
  deprecated: typeof metadata.deprecated === "string" ? metadata.deprecated : void 0,
47
53
  downloadsMonthly,
48
- downloadsTotal: downloadsTotal || void 0,
54
+ downloadsTotal: downloadsTotal === void 0 || downloadsTotal === 0 ? void 0 : downloadsTotal,
49
55
  downloadsWeekly,
50
56
  downloadsYearly,
51
57
  fileCount: typeof distribution?.fileCount === "number" ? distribution.fileCount : void 0,
@@ -1,6 +1,5 @@
1
1
  import { OneOrMany, SourceRecord } from "../source.js";
2
2
  import { NormalizedPackageJson } from "read-pkg";
3
-
4
3
  //#region src/lib/sources/node-package-json.d.ts
5
4
  type NodePackageJsonData = OneOrMany<SourceRecord<NormalizedPackageJson>> | undefined;
6
5
  //#endregion
@@ -1,15 +1,23 @@
1
1
  import { OneOrMany, SourceRecord } from "../source.js";
2
-
3
2
  //#region src/lib/sources/obsidian-plugin-manifest-json.d.ts
4
3
  type ObsidianManifest = {
5
- /** Plugin author name. */author?: string; /** URL for the plugin author. */
6
- authorUrl?: string; /** Plugin description. */
7
- description?: string; /** URL for funding or sponsorship. */
8
- fundingUrl?: string; /** Unique plugin identifier. */
9
- id: string; /** Whether the plugin is desktop-only. */
10
- isDesktopOnly?: boolean; /** Minimum Obsidian app version required. */
11
- minAppVersion?: string; /** Display name of the plugin. */
12
- name?: string; /** Plugin version string. */
4
+ /** Plugin author name. */
5
+ author?: string;
6
+ /** URL for the plugin author. */
7
+ authorUrl?: string;
8
+ /** Plugin description. */
9
+ description?: string;
10
+ /** URL for funding or sponsorship. */
11
+ fundingUrl?: string;
12
+ /** Unique plugin identifier. */
13
+ id: string;
14
+ /** Whether the plugin is desktop-only. */
15
+ isDesktopOnly?: boolean;
16
+ /** Minimum Obsidian app version required. */
17
+ minAppVersion?: string;
18
+ /** Display name of the plugin. */
19
+ name?: string;
20
+ /** Plugin version string. */
13
21
  version?: string;
14
22
  };
15
23
  type ObsidianPluginManifestJsonData = OneOrMany<SourceRecord<ObsidianManifest>> | undefined;
@@ -23,10 +23,10 @@ const obsidianPluginManifestJsonSource = defineSource({
23
23
  async parse(input, context) {
24
24
  const content = await readFile(resolve(context.options.path, input), "utf8");
25
25
  const parsed = manifestSchema.safeParse(JSON.parse(content));
26
- if (parsed.success) return {
26
+ return parsed.success ? {
27
27
  data: parsed.data,
28
28
  source: input
29
- };
29
+ } : void 0;
30
30
  },
31
31
  phase: 1
32
32
  });
@@ -1,8 +1,9 @@
1
1
  import { OneOrMany, SourceRecord } from "../source.js";
2
-
3
2
  //#region src/lib/sources/obsidian-plugin-registry.d.ts
4
3
  type ObsidianPluginRegistryInfo = {
5
- /** Total community download count. */downloadCount?: number; /** Obsidian plugin directory URL. */
4
+ /** Total community download count. */
5
+ downloadCount?: number;
6
+ /** Obsidian plugin directory URL. */
6
7
  url?: string;
7
8
  };
8
9
  type ObsidianPluginRegistryData = OneOrMany<SourceRecord<ObsidianPluginRegistryInfo>> | undefined;
@@ -30,9 +30,10 @@ const obsidianPluginRegistrySource = defineSource({
30
30
  data: { url },
31
31
  source: url
32
32
  };
33
+ const downloads = pluginStatsSchema.parse(await response.json())[pluginId]?.downloads;
33
34
  return {
34
35
  data: {
35
- downloadCount: pluginStatsSchema.parse(await response.json())[pluginId]?.downloads || void 0,
36
+ downloadCount: downloads === void 0 || downloads === 0 ? void 0 : downloads,
36
37
  url
37
38
  },
38
39
  source: url
@@ -1,6 +1,5 @@
1
1
  import { OneOrMany, SourceRecord } from "../source.js";
2
2
  import { z } from "zod";
3
-
4
3
  //#region src/lib/sources/openframeworks-addon-config-mk.d.ts
5
4
  declare const openframeworksAddonConfigSchema: z.ZodObject<{
6
5
  author: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
@@ -1,6 +1,5 @@
1
1
  import { OneOrMany, SourceRecord } from "../source.js";
2
2
  import { z } from "zod";
3
-
4
3
  //#region src/lib/sources/openframeworks-install-xml.d.ts
5
4
  declare const openframeworksInstallXmlSchema: z.ZodObject<{
6
5
  author: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
@@ -115,7 +115,7 @@ function parseRequirements(install) {
115
115
  const results = [];
116
116
  for (const addon of ensureArray(requires.addon)) {
117
117
  const name = getString(addon);
118
- if (name) results.push(name);
118
+ if (name !== void 0 && name !== "") results.push(name);
119
119
  }
120
120
  return results;
121
121
  }
@@ -135,7 +135,7 @@ function parseOperatingSystems(install) {
135
135
  for (const library of ensureArray(link.lib)) {
136
136
  if (!is.plainObject(library)) continue;
137
137
  const os = getString(library["@_os"]);
138
- if (os) {
138
+ if (os !== void 0 && os !== "") {
139
139
  const mapped = LIB_OS_MAP[os.toLowerCase()] ?? os;
140
140
  if (!seen.has(mapped)) {
141
141
  seen.add(mapped);
@@ -152,7 +152,7 @@ const openframeworksInstallXmlSource = defineSource({
152
152
  key: "openframeworksInstallXml",
153
153
  async parse(input, context) {
154
154
  const data = parse(await readFile(resolve(context.options.path, input), "utf8"));
155
- if (data !== void 0) return {
155
+ return data === void 0 ? void 0 : {
156
156
  data,
157
157
  source: input
158
158
  };
@@ -1,6 +1,5 @@
1
1
  import { OneOrMany, SourceRecord } from "../source.js";
2
2
  import { z } from "zod";
3
-
4
3
  //#region src/lib/sources/processing-library-properties.d.ts
5
4
  declare const processingLibraryPropertiesSchema: z.ZodObject<{
6
5
  authors: z.ZodArray<z.ZodObject<{
@@ -7,7 +7,7 @@ import { readFile } from "node:fs/promises";
7
7
  import { resolve } from "node:path";
8
8
  import { z } from "zod";
9
9
  //#region src/lib/sources/processing-library-properties.ts
10
- const AUTHOR_SEPARATOR_REGEX = /\band\b|,|&/;
10
+ const AUTHOR_SEPARATOR_REGEX = /\band\b|,|&/v;
11
11
  const processingLibraryPropertiesAuthorEntrySchema = z.object({
12
12
  name: z.string(),
13
13
  url: z.string().optional()
@@ -32,8 +32,7 @@ const CANONICAL_CATEGORIES = [
32
32
  "Video & Vision"
33
33
  ];
34
34
  /** Map from letters-only lowercase to canonical category form. */
35
- const CATEGORY_MAP = new Map(CANONICAL_CATEGORIES.map((cat) => [cat.replaceAll(/[^a-z]/gi, "").toLowerCase(), cat]));
36
- CATEGORY_MAP.set("3d", "3D");
35
+ const CATEGORY_MAP = new Map([...CANONICAL_CATEGORIES.map((cat) => [cat.replaceAll(/[^a-z]/giv, "").toLowerCase(), cat]), ["3d", "3D"]]);
37
36
  const processingLibraryPropertiesSchema = z.object({
38
37
  /** Parsed author entries with optional URLs. */
39
38
  authors: z.array(processingLibraryPropertiesAuthorEntrySchema),
@@ -71,13 +70,13 @@ const processingLibraryPropertiesSchema = z.object({
71
70
  function parse(content) {
72
71
  const raw = parseProperties(content);
73
72
  const versionRaw = get(raw, "version") ?? "0";
74
- const versionParsed = Number.parseInt(versionRaw, 10);
73
+ const versionParsed = Math.trunc(Number(versionRaw));
75
74
  const prettyVersionRaw = get(raw, "prettyVersion");
76
- const prettyVersion = prettyVersionRaw ? stripInlineComment(prettyVersionRaw) : void 0;
75
+ const prettyVersion = prettyVersionRaw !== void 0 && prettyVersionRaw !== "" ? stripInlineComment(prettyVersionRaw) : void 0;
77
76
  const minRevisionRaw = get(raw, "minRevision");
78
- const minParsed = minRevisionRaw ? Number.parseInt(minRevisionRaw, 10) : 0;
77
+ const minParsed = minRevisionRaw !== void 0 && minRevisionRaw !== "" ? Math.trunc(Number(minRevisionRaw)) : 0;
79
78
  const maxRevisionRaw = get(raw, "maxRevision");
80
- const maxParsed = maxRevisionRaw ? Number.parseInt(maxRevisionRaw, 10) : 0;
79
+ const maxParsed = maxRevisionRaw !== void 0 && maxRevisionRaw !== "" ? Math.trunc(Number(maxRevisionRaw)) : 0;
81
80
  return processingLibraryPropertiesSchema.parse({
82
81
  authors: parseAuthors(get(raw, "authors") ?? get(raw, "authorList") ?? ""),
83
82
  categories: parseCategories(get(raw, "categories") ?? get(raw, "category") ?? ""),
@@ -182,12 +181,12 @@ function parseCategories(value) {
182
181
  if (trimmed.length === 0) return [];
183
182
  const results = [];
184
183
  for (const part of trimmed.split(",")) {
185
- const stripped = part.trim().replaceAll(/^"|"$/g, "").trim();
184
+ const stripped = part.trim().replaceAll(/^"|"$/gv, "").trim();
186
185
  if (stripped.length === 0) continue;
187
- const key = stripped.replaceAll(/[^a-z0-9]/gi, "").toLowerCase();
186
+ const key = stripped.replaceAll(/[^a-z0-9]/giv, "").toLowerCase();
188
187
  if (key.length === 0) continue;
189
188
  const canonical = CATEGORY_MAP.get(key);
190
- if (canonical && !results.includes(canonical)) results.push(canonical);
189
+ if (canonical !== void 0 && !results.includes(canonical)) results.push(canonical);
191
190
  }
192
191
  return results;
193
192
  }
@@ -1,6 +1,5 @@
1
1
  import { OneOrMany, SourceRecord } from "../source.js";
2
2
  import { z } from "zod";
3
-
4
3
  //#region src/lib/sources/processing-sketch-properties.d.ts
5
4
  declare const processingSketchPropertiesSchema: z.ZodObject<{
6
5
  authors: z.ZodArray<z.ZodObject<{
@@ -7,7 +7,7 @@ import { readFile } from "node:fs/promises";
7
7
  import { resolve } from "node:path";
8
8
  import { z } from "zod";
9
9
  //#region src/lib/sources/processing-sketch-properties.ts
10
- const AUTHOR_SEPARATOR_REGEX = /\band\b|,|&/;
10
+ const AUTHOR_SEPARATOR_REGEX = /\band\b|,|&/v;
11
11
  const processingSketchPropertiesAuthorEntrySchema = z.object({
12
12
  name: z.string(),
13
13
  url: z.string().optional()
@@ -88,20 +88,8 @@ const processingSketchPropertiesSchema = z.object({
88
88
  */
89
89
  function parse(content) {
90
90
  const raw = parseProperties(content);
91
- const versionRaw = raw.version ?? "0";
92
- const versionParsed = Number.parseInt(versionRaw, 10);
93
91
  const prettyVersionRaw = raw.prettyVersion;
94
- const prettyVersion = prettyVersionRaw ? stripInlineComment(prettyVersionRaw) : void 0;
95
- const minRevisionRaw = raw.minRevision;
96
- const minParsed = minRevisionRaw ? Number.parseInt(minRevisionRaw, 10) : 0;
97
- const maxRevisionRaw = raw.maxRevision;
98
- const maxParsed = maxRevisionRaw ? Number.parseInt(maxRevisionRaw, 10) : 0;
99
- const manifestVersionCodeRaw = raw["manifest.version.code"];
100
- const manifestVersionCode = manifestVersionCodeRaw ? Number.parseInt(manifestVersionCodeRaw, 10) : void 0;
101
- const manifestSdkTargetRaw = raw["manifest.sdk.target"];
102
- const manifestSdkTarget = manifestSdkTargetRaw ? Number.parseInt(manifestSdkTargetRaw, 10) : void 0;
103
- const manifestSdkMinRaw = raw["manifest.sdk.min"];
104
- const manifestSdkMin = manifestSdkMinRaw ? Number.parseInt(manifestSdkMinRaw, 10) : void 0;
92
+ const prettyVersion = prettyVersionRaw !== void 0 && prettyVersionRaw !== "" ? stripInlineComment(prettyVersionRaw) : void 0;
105
93
  const manifestPermissions = splitCommaSeparated(raw["manifest.permissions"] ?? "");
106
94
  return processingSketchPropertiesSchema.parse({
107
95
  authors: parseAuthors(raw.authors ?? raw.authorList ?? ""),
@@ -112,12 +100,12 @@ function parse(content) {
112
100
  manifestOrientation: nonEmpty(raw["manifest.orientation"]),
113
101
  manifestPackage: nonEmpty(raw["manifest.package"]),
114
102
  manifestPermissions,
115
- manifestSdkMin: Number.isNaN(manifestSdkMin) ? void 0 : manifestSdkMin,
116
- manifestSdkTarget: Number.isNaN(manifestSdkTarget) ? void 0 : manifestSdkTarget,
117
- manifestVersionCode: Number.isNaN(manifestVersionCode) ? void 0 : manifestVersionCode,
103
+ manifestSdkMin: parseIntegerOr(raw["manifest.sdk.min"], void 0),
104
+ manifestSdkTarget: parseIntegerOr(raw["manifest.sdk.target"], void 0),
105
+ manifestVersionCode: parseIntegerOr(raw["manifest.version.code"], void 0),
118
106
  manifestVersionName: nonEmpty(raw["manifest.version.name"]),
119
- maxRevision: Number.isNaN(maxParsed) ? 0 : maxParsed,
120
- minRevision: Number.isNaN(minParsed) ? 0 : minParsed,
107
+ maxRevision: parseIntegerOr(raw.maxRevision, 0),
108
+ minRevision: parseIntegerOr(raw.minRevision, 0),
121
109
  mode: nonEmpty(raw.mode),
122
110
  modeId: nonEmpty(raw["mode.id"]),
123
111
  name: nonEmpty(raw.name),
@@ -127,10 +115,15 @@ function parse(content) {
127
115
  sentence: nonEmpty(raw.sentence),
128
116
  templates: nonEmpty(raw.templates),
129
117
  url: nonEmpty(unescapeUrl(raw.url ?? "")),
130
- version: Number.isNaN(versionParsed) ? 0 : versionParsed,
118
+ version: parseIntegerOr(raw.version, 0),
131
119
  zipfilename: nonEmpty(raw.zipfilename)
132
120
  });
133
121
  }
122
+ function parseIntegerOr(value, fallback) {
123
+ if (value === void 0 || value === "") return fallback;
124
+ const parsed = Math.trunc(Number(value));
125
+ return Number.isNaN(parsed) ? fallback : parsed;
126
+ }
134
127
  /** Return a trimmed string, or undefined if empty/whitespace-only. */
135
128
  function nonEmpty(value) {
136
129
  if (value === void 0) return;
@@ -1,6 +1,5 @@
1
1
  import { OneOrMany, SourceRecord } from "../source.js";
2
2
  import { z } from "zod";
3
-
4
3
  //#region src/lib/sources/publiccode-yaml.d.ts
5
4
  declare const publiccodeSchema: z.ZodObject<{
6
5
  applicationSuite: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
@@ -126,6 +126,22 @@ function toStringArray(value) {
126
126
  if (!Array.isArray(value)) return [];
127
127
  return value.filter((item) => typeof item === "string");
128
128
  }
129
+ /** Parse a single dependency entry, returning undefined when it lacks a name. */
130
+ function parseDependencyEntry(dependency, category) {
131
+ if (!isPlainObject(dependency) || !isNonEmptyString(dependency.name)) return;
132
+ const entry = {
133
+ category,
134
+ name: dependency.name
135
+ };
136
+ const version = toString(dependency.version);
137
+ if (version !== void 0 && version !== "") entry.version = version;
138
+ const versionMin = toString(dependency.versionMin);
139
+ if (versionMin !== void 0 && versionMin !== "") entry.versionMin = versionMin;
140
+ const versionMax = toString(dependency.versionMax);
141
+ if (versionMax !== void 0 && versionMax !== "") entry.versionMax = versionMax;
142
+ if (typeof dependency.optional === "boolean") entry.optional = dependency.optional;
143
+ return entry;
144
+ }
129
145
  /** Parse a description block from a publiccode description object. */
130
146
  function parseDescription(data) {
131
147
  const features = [];
@@ -134,12 +150,12 @@ function parseDescription(data) {
134
150
  else if (isPlainObject(feature)) for (const [key, value] of Object.entries(feature)) features.push(typeof value === "string" ? `${key}: ${value}` : key);
135
151
  }
136
152
  return {
137
- ...isNonEmptyString(data.documentation) ? { documentation: data.documentation } : {},
153
+ ...isNonEmptyString(data.documentation) && { documentation: data.documentation },
138
154
  features,
139
- ...isNonEmptyString(data.genericName) ? { genericName: data.genericName } : {},
140
- ...isNonEmptyString(data.localisedName) ? { localisedName: data.localisedName } : {},
141
- ...isNonEmptyString(data.longDescription) ? { longDescription: data.longDescription.trim() } : {},
142
- ...isNonEmptyString(data.shortDescription) ? { shortDescription: data.shortDescription.trim() } : {}
155
+ ...isNonEmptyString(data.genericName) && { genericName: data.genericName },
156
+ ...isNonEmptyString(data.localisedName) && { localisedName: data.localisedName },
157
+ ...isNonEmptyString(data.longDescription) && { longDescription: data.longDescription.trim() },
158
+ ...isNonEmptyString(data.shortDescription) && { shortDescription: data.shortDescription.trim() }
143
159
  };
144
160
  }
145
161
  /**
@@ -165,32 +181,30 @@ function parse$1(content) {
165
181
  const descObject = data.description;
166
182
  for (const [lang, langData] of Object.entries(descObject)) if (isPlainObject(langData)) descriptions[lang] = parseDescription(langData);
167
183
  const preferredLang = "en" in descriptions ? "en" : Object.keys(descriptions)[0];
168
- if (preferredLang) description = descriptions[preferredLang];
184
+ if (preferredLang !== void 0 && preferredLang !== "") description = descriptions[preferredLang];
169
185
  }
170
186
  const contacts = [];
171
187
  if (isPlainObject(data.maintenance)) {
172
188
  const { maintenance } = data;
173
- if (Array.isArray(maintenance.contacts)) {
174
- for (const contact of maintenance.contacts) if (isPlainObject(contact) && isNonEmptyString(contact.name)) {
175
- const entry = { name: contact.name };
176
- if (isNonEmptyString(contact.email)) entry.email = contact.email;
177
- if (isNonEmptyString(contact.phone)) entry.phone = contact.phone;
178
- if (isNonEmptyString(contact.affiliation)) entry.affiliation = contact.affiliation;
179
- contacts.push(entry);
180
- }
189
+ if (Array.isArray(maintenance.contacts)) for (const contact of maintenance.contacts) {
190
+ if (!isPlainObject(contact) || !isNonEmptyString(contact.name)) continue;
191
+ const entry = { name: contact.name };
192
+ if (isNonEmptyString(contact.email)) entry.email = contact.email;
193
+ if (isNonEmptyString(contact.phone)) entry.phone = contact.phone;
194
+ if (isNonEmptyString(contact.affiliation)) entry.affiliation = contact.affiliation;
195
+ contacts.push(entry);
181
196
  }
182
197
  }
183
198
  const contractors = [];
184
199
  if (isPlainObject(data.maintenance)) {
185
200
  const { maintenance } = data;
186
- if (Array.isArray(maintenance.contractors)) {
187
- for (const contractor of maintenance.contractors) if (isPlainObject(contractor) && isNonEmptyString(contractor.name)) {
188
- const entry = { name: contractor.name };
189
- const until = toString(contractor.until);
190
- if (until) entry.until = until;
191
- if (isNonEmptyString(contractor.website)) entry.website = contractor.website;
192
- contractors.push(entry);
193
- }
201
+ if (Array.isArray(maintenance.contractors)) for (const contractor of maintenance.contractors) {
202
+ if (!isPlainObject(contractor) || !isNonEmptyString(contractor.name)) continue;
203
+ const entry = { name: contractor.name };
204
+ const until = toString(contractor.until);
205
+ if (until !== void 0 && until !== "") entry.until = until;
206
+ if (isNonEmptyString(contractor.website)) entry.website = contractor.website;
207
+ contractors.push(entry);
194
208
  }
195
209
  }
196
210
  const dependencies = [];
@@ -201,22 +215,10 @@ function parse$1(content) {
201
215
  "proprietary",
202
216
  "hardware"
203
217
  ]) {
204
- const categoryDeps = dependsOn[category];
205
- if (Array.isArray(categoryDeps)) {
206
- for (const dep of categoryDeps) if (isPlainObject(dep) && isNonEmptyString(dep.name)) {
207
- const entry = {
208
- category,
209
- name: dep.name
210
- };
211
- const version = toString(dep.version);
212
- if (version) entry.version = version;
213
- const versionMin = toString(dep.versionMin);
214
- if (versionMin) entry.versionMin = versionMin;
215
- const versionMax = toString(dep.versionMax);
216
- if (versionMax) entry.versionMax = versionMax;
217
- if (typeof dep.optional === "boolean") entry.optional = dep.optional;
218
- dependencies.push(entry);
219
- }
218
+ const categoryDependencies = dependsOn[category];
219
+ if (Array.isArray(categoryDependencies)) for (const dependency of categoryDependencies) {
220
+ const entry = parseDependencyEntry(dependency, category);
221
+ if (entry !== void 0) dependencies.push(entry);
220
222
  }
221
223
  }
222
224
  }
@@ -238,35 +240,36 @@ function parse$1(content) {
238
240
  }
239
241
  const version = toString(data.softwareVersion);
240
242
  const releaseDate = toString(data.releaseDate);
243
+ const publiccodeYmlVersion = toString(data.publiccodeYmlVersion);
241
244
  return publiccodeSchema.parse({
242
- ...isNonEmptyString(data.applicationSuite) ? { applicationSuite: data.applicationSuite } : {},
245
+ ...isNonEmptyString(data.applicationSuite) && { applicationSuite: data.applicationSuite },
243
246
  availableLanguages,
244
247
  categories: toStringArray(data.categories),
245
248
  contacts,
246
249
  contractors,
247
250
  dependencies,
248
- ...description ? { description } : {},
251
+ ...description && { description },
249
252
  descriptions,
250
- ...isNonEmptyString(data.developmentStatus) ? { developmentStatus: data.developmentStatus } : {},
253
+ ...isNonEmptyString(data.developmentStatus) && { developmentStatus: data.developmentStatus },
251
254
  inputTypes: toStringArray(data.inputTypes),
252
- ...isNonEmptyString(data.isBasedOn) ? { isBasedOn: data.isBasedOn } : {},
253
- ...isNonEmptyString(data.landingURL) ? { landingUrl: data.landingURL } : {},
254
- ...license ? { license } : {},
255
- ...localisationReady === void 0 ? {} : { localisationReady },
256
- ...isNonEmptyString(data.logo) ? { logo: data.logo } : {},
257
- ...mainCopyrightOwner ? { mainCopyrightOwner } : {},
258
- ...isPlainObject(data.maintenance) && isNonEmptyString(data.maintenance.type) ? { maintenanceType: data.maintenance.type } : {},
259
- ...isNonEmptyString(data.monochromeLogo) ? { monochromeLogo: data.monochromeLogo } : {},
260
- ...isNonEmptyString(data.name) ? { name: data.name } : {},
255
+ ...isNonEmptyString(data.isBasedOn) && { isBasedOn: data.isBasedOn },
256
+ ...isNonEmptyString(data.landingURL) && { landingUrl: data.landingURL },
257
+ ...license !== void 0 && { license },
258
+ ...localisationReady !== void 0 && { localisationReady },
259
+ ...isNonEmptyString(data.logo) && { logo: data.logo },
260
+ ...mainCopyrightOwner !== void 0 && { mainCopyrightOwner },
261
+ ...isPlainObject(data.maintenance) && isNonEmptyString(data.maintenance.type) && { maintenanceType: data.maintenance.type },
262
+ ...isNonEmptyString(data.monochromeLogo) && { monochromeLogo: data.monochromeLogo },
263
+ ...isNonEmptyString(data.name) && { name: data.name },
261
264
  outputTypes: toStringArray(data.outputTypes),
262
265
  platforms: toStringArray(data.platforms),
263
- ...isNonEmptyString(data.publiccodeYmlVersion) ? { publiccodeYmlVersion: data.publiccodeYmlVersion } : toString(data.publiccodeYmlVersion) ? { publiccodeYmlVersion: toString(data.publiccodeYmlVersion) } : {},
264
- ...releaseDate ? { releaseDate } : {},
265
- ...repoOwner ? { repoOwner } : {},
266
- ...isNonEmptyString(data.roadmap) ? { roadmap: data.roadmap } : {},
267
- ...isNonEmptyString(data.softwareType) ? { softwareType: data.softwareType } : {},
268
- ...version ? { softwareVersion: version } : {},
269
- ...isNonEmptyString(data.url) ? { url: data.url } : {},
266
+ ...publiccodeYmlVersion !== void 0 && publiccodeYmlVersion !== "" && { publiccodeYmlVersion },
267
+ ...releaseDate !== void 0 && releaseDate !== "" && { releaseDate },
268
+ ...repoOwner !== void 0 && { repoOwner },
269
+ ...isNonEmptyString(data.roadmap) && { roadmap: data.roadmap },
270
+ ...isNonEmptyString(data.softwareType) && { softwareType: data.softwareType },
271
+ ...version !== void 0 && version !== "" && { softwareVersion: version },
272
+ ...isNonEmptyString(data.url) && { url: data.url },
270
273
  usedBy: toStringArray(data.usedBy)
271
274
  });
272
275
  }
@@ -277,7 +280,7 @@ const publiccodeYamlSource = defineSource({
277
280
  key: "publiccodeYaml",
278
281
  async parse(input, context) {
279
282
  const data = parse$1(await readFile(resolve(context.options.path, input), "utf8"));
280
- if (data !== void 0) return {
283
+ return data === void 0 ? void 0 : {
281
284
  data,
282
285
  source: input
283
286
  };
@@ -1,6 +1,5 @@
1
1
  import { OneOrMany, SourceRecord } from "../source.js";
2
2
  import { z } from "zod";
3
-
4
3
  //#region src/lib/sources/python-pkg-info.d.ts
5
4
  /** Parsed PKG-INFO / METADATA metadata */
6
5
  declare const pkgInfoDataSchema: z.ZodObject<{
@@ -80,19 +80,20 @@ function parse(source) {
80
80
  };
81
81
  for (const [header, field] of Object.entries(HEADER_MAP)) {
82
82
  const value = headers[header];
83
- if (value && value !== "UNKNOWN") Object.assign(data, { [field]: value });
83
+ if (value !== void 0 && value !== "" && value !== "UNKNOWN") Object.assign(data, { [field]: value });
84
84
  }
85
- if (headers.Summary && headers.Summary !== "UNKNOWN") data.description = headers.Summary;
86
- if (headers.Keywords && headers.Keywords !== "UNKNOWN") data.keywords = splitCommaSeparated(headers.Keywords);
85
+ if (headers.Summary !== void 0 && headers.Summary !== "" && headers.Summary !== "UNKNOWN") data.description = headers.Summary;
86
+ if (headers.Keywords !== void 0 && headers.Keywords !== "" && headers.Keywords !== "UNKNOWN") data.keywords = splitCommaSeparated(headers.Keywords);
87
87
  data.classifiers = splitMultiValues(headers.Classifier);
88
88
  data.platforms = splitMultiValues(headers.Platform);
89
89
  data.requires_dist = splitMultiValues(headers["Requires-Dist"]);
90
- if (headers["Project-URL"]) for (const line of splitMultiValues(headers["Project-URL"])) {
90
+ const projectUrl = headers["Project-URL"];
91
+ if (projectUrl !== void 0 && projectUrl !== "") for (const line of splitMultiValues(projectUrl)) {
91
92
  const commaIndex = line.indexOf(", ");
92
93
  if (commaIndex > 0) {
93
94
  const label = line.slice(0, commaIndex).trim();
94
95
  const url = line.slice(commaIndex + 2).trim();
95
- if (url) data.project_urls[label] = url;
96
+ if (url !== "") data.project_urls[label] = url;
96
97
  }
97
98
  }
98
99
  data.long_description = extractRfc822Body(source);