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.
- package/dist/bin/cli.js +30426 -29237
- package/dist/bin/{jiti-DDHyYNLW.js → jiti-B26uDQuv.js} +2 -2
- package/dist/bin/renovate-CEC0BhMB.js +1 -0
- package/dist/bin/shared-Ch5JsD6s.js +8 -0
- package/dist/bin/shared2-Dhjk_Okb.js +1 -0
- package/dist/bin/web-tree-sitter.wasm +0 -0
- package/dist/lib/data/license-urls.js +2904 -0
- package/dist/lib/file-matching.js +5 -2
- package/dist/lib/log.d.ts +0 -1
- package/dist/lib/metadata-types.d.ts +16 -9
- package/dist/lib/metadata.d.ts +0 -1
- package/dist/lib/metadata.js +5 -5
- package/dist/lib/package.js +1 -1
- package/dist/lib/parsers/configparser-parser.js +14 -12
- package/dist/lib/parsers/gemspec-parser.js +41 -42
- package/dist/lib/parsers/go-mod-parser.js +51 -45
- package/dist/lib/parsers/makefile-config-parser.js +7 -6
- package/dist/lib/parsers/properties-parser.js +1 -1
- package/dist/lib/parsers/rfc822-header-parser.js +8 -6
- package/dist/lib/parsers/setup-py-parser.js +28 -24
- package/dist/lib/source.d.ts +6 -2
- package/dist/lib/sources/arduino-library-properties.d.ts +0 -1
- package/dist/lib/sources/arduino-library-properties.js +6 -7
- package/dist/lib/sources/cinder-cinderblock-xml.d.ts +0 -1
- package/dist/lib/sources/cinder-cinderblock-xml.js +5 -5
- package/dist/lib/sources/code-stats.d.ts +3 -2
- package/dist/lib/sources/codemeta-json.d.ts +0 -1
- package/dist/lib/sources/codemeta-json.js +21 -20
- package/dist/lib/sources/dependency-updates.d.ts +17 -8
- package/dist/lib/sources/dependency-updates.js +38 -34
- package/dist/lib/sources/file-stats.d.ts +7 -4
- package/dist/lib/sources/git-config.d.ts +0 -1
- package/dist/lib/sources/git-stats.d.ts +47 -24
- package/dist/lib/sources/git-stats.js +51 -33
- package/dist/lib/sources/github-actions.d.ts +0 -1
- package/dist/lib/sources/github-actions.js +4 -3
- package/dist/lib/sources/github.d.ts +156 -78
- package/dist/lib/sources/github.js +11 -8
- package/dist/lib/sources/go-go-mod.d.ts +0 -1
- package/dist/lib/sources/go-goreleaser-yaml.d.ts +0 -1
- package/dist/lib/sources/go-goreleaser-yaml.js +5 -3
- package/dist/lib/sources/java-pom-xml.d.ts +0 -1
- package/dist/lib/sources/java-pom-xml.js +12 -12
- package/dist/lib/sources/license-file.d.ts +0 -1
- package/dist/lib/sources/metadata-file.d.ts +0 -1
- package/dist/lib/sources/metadata-file.js +9 -10
- package/dist/lib/sources/metascope.d.ts +9 -5
- package/dist/lib/sources/node-npm-registry.d.ts +21 -11
- package/dist/lib/sources/node-npm-registry.js +12 -6
- package/dist/lib/sources/node-package-json.d.ts +0 -1
- package/dist/lib/sources/obsidian-plugin-manifest-json.d.ts +17 -9
- package/dist/lib/sources/obsidian-plugin-manifest-json.js +2 -2
- package/dist/lib/sources/obsidian-plugin-registry.d.ts +3 -2
- package/dist/lib/sources/obsidian-plugin-registry.js +2 -1
- package/dist/lib/sources/openframeworks-addon-config-mk.d.ts +0 -1
- package/dist/lib/sources/openframeworks-install-xml.d.ts +0 -1
- package/dist/lib/sources/openframeworks-install-xml.js +3 -3
- package/dist/lib/sources/processing-library-properties.d.ts +0 -1
- package/dist/lib/sources/processing-library-properties.js +9 -10
- package/dist/lib/sources/processing-sketch-properties.d.ts +0 -1
- package/dist/lib/sources/processing-sketch-properties.js +13 -20
- package/dist/lib/sources/publiccode-yaml.d.ts +0 -1
- package/dist/lib/sources/publiccode-yaml.js +61 -58
- package/dist/lib/sources/python-pkg-info.d.ts +0 -1
- package/dist/lib/sources/python-pkg-info.js +6 -5
- package/dist/lib/sources/python-pypi-registry.d.ts +21 -11
- package/dist/lib/sources/python-pypi-registry.js +23 -16
- package/dist/lib/sources/python-pyproject-toml.d.ts +0 -1
- package/dist/lib/sources/python-setup-cfg.d.ts +2 -3
- package/dist/lib/sources/python-setup-cfg.js +10 -9
- package/dist/lib/sources/python-setup-py.d.ts +0 -1
- package/dist/lib/sources/readme-file.d.ts +0 -1
- package/dist/lib/sources/readme-file.js +4 -3
- package/dist/lib/sources/ruby-gemspec.d.ts +0 -1
- package/dist/lib/sources/rust-cargo-toml.d.ts +0 -1
- package/dist/lib/sources/rust-cargo-toml.js +1 -1
- package/dist/lib/sources/xcode-info-plist.d.ts +0 -1
- package/dist/lib/sources/xcode-info-plist.js +29 -31
- package/dist/lib/sources/xcode-project-pbxproj.d.ts +0 -1
- package/dist/lib/sources/xcode-project-pbxproj.js +17 -16
- package/dist/lib/templates/codemeta-json.d.ts +1 -0
- package/dist/lib/templates/codemeta.d.ts +1 -0
- package/dist/lib/templates/codemeta.js +98 -89
- package/dist/lib/templates/frontmatter.d.ts +2 -1
- package/dist/lib/templates/frontmatter.js +1 -1
- package/dist/lib/templates/index.d.ts +2 -1
- package/dist/lib/templates/index.js +1 -1
- package/dist/lib/templates/metadata.d.ts +1 -0
- package/dist/lib/templates/project.d.ts +1 -0
- package/dist/lib/utilities/codemeta-helpers.js +14 -13
- package/dist/lib/utilities/fetch.js +18 -2
- package/dist/lib/utilities/formatting.js +1 -1
- package/dist/lib/utilities/github.js +2 -2
- package/dist/lib/utilities/license-identification.d.ts +9 -4
- package/dist/lib/utilities/license-identification.js +37 -23
- package/dist/lib/utilities/template-helpers.d.ts +7 -5
- package/dist/lib/utilities/template-helpers.js +15 -14
- package/dist/lib/utilities/tree-sitter-wasm.d.ts +0 -1
- package/dist/lib/utilities/tree-sitter-wasm.js +1 -1
- package/package.json +18 -17
- package/readme.md +13 -11
- package/dist/bin/renovate-CpDMbQZd.js +0 -1
- package/dist/bin/shared-Dix5HPlG.js +0 -6
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
|
-
|
|
3
2
|
//#region src/lib/sources/python-pypi-registry.d.ts
|
|
4
3
|
type PythonPypiRegistryInfo = {
|
|
5
|
-
/** Total downloads over the last 180 days. */
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
/** Total downloads over the last 180 days. */
|
|
5
|
+
downloads180Days?: number;
|
|
6
|
+
/** Downloads in the last day. */
|
|
7
|
+
downloadsDaily?: number;
|
|
8
|
+
/** Downloads in the last month. */
|
|
9
|
+
downloadsMonthly?: number;
|
|
10
|
+
/** Downloads in the last week. */
|
|
11
|
+
downloadsWeekly?: number;
|
|
12
|
+
/** ISO 8601 date the package was last published. */
|
|
13
|
+
publishDateLatest?: string;
|
|
14
|
+
/** Total number of releases on PyPI. */
|
|
15
|
+
releaseCount?: number;
|
|
16
|
+
/** Size in bytes of the latest release artifact. */
|
|
17
|
+
sizeBytes?: number;
|
|
18
|
+
/** PyPI project URL. */
|
|
19
|
+
url?: string;
|
|
20
|
+
/** Latest published version string. */
|
|
21
|
+
versionLatest?: string;
|
|
22
|
+
/** Whether the latest version has been yanked. */
|
|
23
|
+
yanked?: boolean;
|
|
24
|
+
/** Reason the version was yanked, if provided. */
|
|
15
25
|
yankedReason?: string;
|
|
16
26
|
};
|
|
17
27
|
type PythonPypiRegistryData = OneOrMany<SourceRecord<PythonPypiRegistryInfo>> | undefined;
|
|
@@ -35,8 +35,7 @@ const pythonPypiRegistrySource = defineSource({
|
|
|
35
35
|
log.debug("Skipping Python PyPI registry data source since we're in offline mode");
|
|
36
36
|
return [];
|
|
37
37
|
}
|
|
38
|
-
let packageNames =
|
|
39
|
-
packageNames = ensureArray(context.metadata?.pythonPyprojectToml).filter((value) => !hasPrivateClassifier(value.data.project?.classifiers, value.data.project?.name, context.options.path)).map((value) => value.data.project?.name).filter((value) => value !== void 0);
|
|
38
|
+
let packageNames = ensureArray(context.metadata?.pythonPyprojectToml).filter((value) => !hasPrivateClassifier(value.data.project?.classifiers, value.data.project?.name, context.options.path)).map((value) => value.data.project?.name).filter((value) => value !== void 0);
|
|
40
39
|
if (packageNames.length === 0) packageNames = ensureArray(context.metadata?.pythonSetupCfg).filter((value) => !hasPrivateClassifier(value.data.classifiers, value.data.name, context.options.path)).map((value) => value.data.name).filter((value) => value !== void 0);
|
|
41
40
|
if (packageNames.length === 0) packageNames = ensureArray(context.metadata?.pythonSetupPy).filter((value) => !hasPrivateClassifier(value.data.classifiers, value.data.name, context.options.path)).map((value) => value.data.name).filter((value) => value !== void 0);
|
|
42
41
|
if (packageNames.length === 0) packageNames = ensureArray(context.metadata?.pythonPkgInfo).filter((value) => !hasPrivateClassifier(value.data.classifiers, value.data.name, context.options.path)).map((value) => value.data.name).filter((value) => value !== void 0);
|
|
@@ -61,18 +60,9 @@ const pythonPypiRegistrySource = defineSource({
|
|
|
61
60
|
log.debug("Extracting PyPI metadata...");
|
|
62
61
|
const name = input;
|
|
63
62
|
const [pypiResult, pypistatsRecentResult, pypistatsOverallResult] = await Promise.all([
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}).catch(() => void 0),
|
|
68
|
-
fetchWithRetry(`https://pypistats.org/api/packages/${encodeURIComponent(name)}/recent`).then(async (response) => {
|
|
69
|
-
if (!response.ok) return;
|
|
70
|
-
return pypistatsRecentSchema.parse(await response.json());
|
|
71
|
-
}).catch(() => void 0),
|
|
72
|
-
fetchWithRetry(`https://pypistats.org/api/packages/${encodeURIComponent(name)}/overall?mirrors=false`).then(async (response) => {
|
|
73
|
-
if (!response.ok) return;
|
|
74
|
-
return pypistatsOverallSchema.parse(await response.json());
|
|
75
|
-
}).catch(() => void 0)
|
|
63
|
+
fetchJson(`https://pypi.org/pypi/${encodeURIComponent(name)}/json`, pypiResponseSchema),
|
|
64
|
+
fetchJson(`https://pypistats.org/api/packages/${encodeURIComponent(name)}/recent`, pypistatsRecentSchema),
|
|
65
|
+
fetchJson(`https://pypistats.org/api/packages/${encodeURIComponent(name)}/overall?mirrors=false`, pypistatsOverallSchema)
|
|
76
66
|
]);
|
|
77
67
|
if (!pypiResult) return;
|
|
78
68
|
const latestUploadTime = pypiResult.urls[0]?.upload_time_iso_8601;
|
|
@@ -86,14 +76,18 @@ const pythonPypiRegistrySource = defineSource({
|
|
|
86
76
|
};
|
|
87
77
|
if (pypiResult.info.yanked) {
|
|
88
78
|
info.yanked = true;
|
|
89
|
-
|
|
79
|
+
const yankedReason = pypiResult.info.yanked_reason;
|
|
80
|
+
if (yankedReason !== null && yankedReason !== void 0 && yankedReason !== "") info.yankedReason = yankedReason;
|
|
90
81
|
}
|
|
91
82
|
if (pypistatsRecentResult) {
|
|
92
83
|
info.downloadsDaily = pypistatsRecentResult.data.last_day;
|
|
93
84
|
info.downloadsMonthly = pypistatsRecentResult.data.last_month;
|
|
94
85
|
info.downloadsWeekly = pypistatsRecentResult.data.last_week;
|
|
95
86
|
}
|
|
96
|
-
if (pypistatsOverallResult)
|
|
87
|
+
if (pypistatsOverallResult) {
|
|
88
|
+
const downloads180Days = pypistatsOverallResult.data.reduce((sum, entry) => sum + entry.downloads, 0);
|
|
89
|
+
info.downloads180Days = downloads180Days === 0 || Number.isNaN(downloads180Days) ? void 0 : downloads180Days;
|
|
90
|
+
}
|
|
97
91
|
return {
|
|
98
92
|
data: info,
|
|
99
93
|
source: `https://pypi.org/project/${encodeURIComponent(name)}/`
|
|
@@ -102,6 +96,19 @@ const pythonPypiRegistrySource = defineSource({
|
|
|
102
96
|
phase: 2
|
|
103
97
|
});
|
|
104
98
|
/**
|
|
99
|
+
* Fetch a URL and parse its JSON body with a Zod schema. Returns undefined when
|
|
100
|
+
* the request fails, the response is not OK, or the body doesn't validate.
|
|
101
|
+
*/
|
|
102
|
+
async function fetchJson(url, schema) {
|
|
103
|
+
try {
|
|
104
|
+
const response = await fetchWithRetry(url);
|
|
105
|
+
if (!response.ok) return;
|
|
106
|
+
return schema.parse(await response.json());
|
|
107
|
+
} catch {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
105
112
|
* Check if classifiers contain a "Private ::" prefix, which signals that the
|
|
106
113
|
* package is not intended for publication on PyPI. PyPI itself rejects uploads
|
|
107
114
|
* with this classifier.
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { OneOrMany, SourceRecord } from "../source.js";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
|
|
4
3
|
//#region src/lib/sources/python-setup-cfg.d.ts
|
|
5
|
-
declare const
|
|
4
|
+
declare const setupConfigDataSchema: z.ZodObject<{
|
|
6
5
|
author: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
|
|
7
6
|
author_email: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
|
|
8
7
|
classifiers: z.ZodDefault<z.ZodPreprocess<z.ZodArray<z.ZodString>>>;
|
|
@@ -22,7 +21,7 @@ declare const setupCfgDataSchema: z.ZodObject<{
|
|
|
22
21
|
version: z.ZodOptional<z.ZodPreprocess<z.ZodOptional<z.ZodString>>>;
|
|
23
22
|
}, z.core.$strip>;
|
|
24
23
|
/** Parsed setup.cfg metadata */
|
|
25
|
-
type SetupCfg = z.infer<typeof
|
|
24
|
+
type SetupCfg = z.infer<typeof setupConfigDataSchema>;
|
|
26
25
|
type PythonSetupCfgData = OneOrMany<SourceRecord<SetupCfg>> | undefined;
|
|
27
26
|
//#endregion
|
|
28
27
|
export { PythonSetupCfgData, SetupCfg };
|
|
@@ -5,9 +5,10 @@ import { splitCommaSeparated } from "../utilities/template-helpers.js";
|
|
|
5
5
|
import { parseConfigparser, splitMultiline } from "../parsers/configparser-parser.js";
|
|
6
6
|
import { readFile } from "node:fs/promises";
|
|
7
7
|
import { resolve } from "node:path";
|
|
8
|
+
import is from "@sindresorhus/is";
|
|
8
9
|
import { z } from "zod";
|
|
9
10
|
//#region src/lib/sources/python-setup-cfg.ts
|
|
10
|
-
const
|
|
11
|
+
const setupConfigDataSchema = z.object({
|
|
11
12
|
author: nonEmptyString,
|
|
12
13
|
author_email: nonEmptyString,
|
|
13
14
|
classifiers: stringArray,
|
|
@@ -71,23 +72,23 @@ function parse(source) {
|
|
|
71
72
|
};
|
|
72
73
|
for (const key of STRING_ATTRS) {
|
|
73
74
|
const value = metadata[key];
|
|
74
|
-
if (value) Object.assign(data, { [key]: value });
|
|
75
|
+
if (is.nonEmptyString(value)) Object.assign(data, { [key]: value });
|
|
75
76
|
}
|
|
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)) {
|
|
77
|
+
if (is.nonEmptyString(metadata.classifiers)) data.classifiers = splitMultiline(metadata.classifiers);
|
|
78
|
+
if (is.nonEmptyString(metadata.keywords)) data.keywords = splitCommaSeparated(metadata.keywords);
|
|
79
|
+
if (is.nonEmptyString(metadata.project_urls)) for (const line of splitMultiline(metadata.project_urls)) {
|
|
79
80
|
const eqIndex = line.indexOf("=");
|
|
80
81
|
if (eqIndex > 0) {
|
|
81
82
|
const label = line.slice(0, eqIndex).trim();
|
|
82
83
|
const url = line.slice(eqIndex + 1).trim();
|
|
83
|
-
if (url) data.project_urls[label] = url;
|
|
84
|
+
if (url !== "") data.project_urls[label] = url;
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
|
-
if (options.install_requires) data.install_requires = splitMultiline(options.install_requires);
|
|
87
|
-
if (options.python_requires) data.python_requires = options.python_requires;
|
|
87
|
+
if (is.nonEmptyString(options.install_requires)) data.install_requires = splitMultiline(options.install_requires);
|
|
88
|
+
if (is.nonEmptyString(options.python_requires)) data.python_requires = options.python_requires;
|
|
88
89
|
const extrasSection = sections["options.extras_require"];
|
|
89
90
|
if (extrasSection) for (const [key, value] of Object.entries(extrasSection)) data.extras_require[key] = splitMultiline(value);
|
|
90
|
-
return
|
|
91
|
+
return setupConfigDataSchema.parse(data);
|
|
91
92
|
}
|
|
92
93
|
const pythonSetupCfgSource = defineSource({
|
|
93
94
|
async discover(context) {
|
|
@@ -33,7 +33,8 @@ const markdownParser = unified().use(remarkParse);
|
|
|
33
33
|
*/
|
|
34
34
|
function extractFirstH1(markdown) {
|
|
35
35
|
const tree = markdownParser.parse(markdown);
|
|
36
|
-
for (const node of tree.children)
|
|
36
|
+
for (const node of tree.children) {
|
|
37
|
+
if (node.type !== "heading" || node.depth !== 1) continue;
|
|
37
38
|
const text = extractText(node.children);
|
|
38
39
|
if (text.length > 0) return text;
|
|
39
40
|
}
|
|
@@ -48,7 +49,7 @@ function extractFirstH1(markdown) {
|
|
|
48
49
|
function parse(content) {
|
|
49
50
|
const { content: markdown, data } = matter(content);
|
|
50
51
|
const name = extractFirstH1(markdown);
|
|
51
|
-
if (
|
|
52
|
+
if (name === void 0 || name === "") return;
|
|
52
53
|
return readmeSchema.parse({
|
|
53
54
|
frontmatter: Object.keys(data).length > 0 ? data : void 0,
|
|
54
55
|
name
|
|
@@ -61,7 +62,7 @@ const readmeFileSource = defineSource({
|
|
|
61
62
|
key: "readmeFile",
|
|
62
63
|
async parse(input, context) {
|
|
63
64
|
const data = parse(await readFile(resolve(context.options.path, input), "utf8"));
|
|
64
|
-
|
|
65
|
+
return data === void 0 ? void 0 : {
|
|
65
66
|
data,
|
|
66
67
|
source: input
|
|
67
68
|
};
|
|
@@ -167,7 +167,7 @@ const rustCargoTomlSource = defineSource({
|
|
|
167
167
|
key: "rustCargoToml",
|
|
168
168
|
async parse(input, context) {
|
|
169
169
|
const data = parse$1(await readFile(resolve(context.options.path, input), "utf8"));
|
|
170
|
-
|
|
170
|
+
return data === void 0 ? void 0 : {
|
|
171
171
|
data,
|
|
172
172
|
source: input
|
|
173
173
|
};
|
|
@@ -18,11 +18,11 @@ import { parse } from "plist";
|
|
|
18
18
|
*
|
|
19
19
|
* Uses the `plist` npm package to parse XML plist format.
|
|
20
20
|
*/
|
|
21
|
-
const COPYRIGHT_YEAR_REGEX = /(?:©|\(c\)|copyright)\s*(\d{4})/
|
|
22
|
-
const COPYRIGHT_HOLDER_REGEX = /(?:©|\(c\)|copyright)\s*\d{4}\s*(.+)/
|
|
23
|
-
const ALL_RIGHTS_RESERVED_REGEX = /\.\s*all\s+rights\s+reserved\.?/
|
|
24
|
-
const TRAILING_PUNCTUATION_REGEX = /[.,;]
|
|
25
|
-
const PROCESSOR_ARCH_REGEX = /^(?:arm|x86|i386)/
|
|
21
|
+
const COPYRIGHT_YEAR_REGEX = /(?:©|\(c\)|copyright)\s*(\d{4})/iv;
|
|
22
|
+
const COPYRIGHT_HOLDER_REGEX = /(?:©|\(c\)|copyright)\s*\d{4}\s*(.+)/iv;
|
|
23
|
+
const ALL_RIGHTS_RESERVED_REGEX = /\.\s*all\s+rights\s+reserved\.?/iv;
|
|
24
|
+
const TRAILING_PUNCTUATION_REGEX = /[.,;]+$/v;
|
|
25
|
+
const PROCESSOR_ARCH_REGEX = /^(?:arm|x86|i386)/iv;
|
|
26
26
|
const infoPlistSchema = z.object({
|
|
27
27
|
/** Application category (humanized from UTI). */
|
|
28
28
|
applicationCategory: nonEmptyString,
|
|
@@ -50,9 +50,9 @@ const infoPlistSchema = z.object({
|
|
|
50
50
|
version: nonEmptyString
|
|
51
51
|
});
|
|
52
52
|
/** Xcode build variable pattern: $(VAR) or ${VAR}. */
|
|
53
|
-
const XCODE_VARIABLE_RE = /\$[({][
|
|
53
|
+
const XCODE_VARIABLE_RE = /\$[\(\{][^\)\}]+[\)\}]/v;
|
|
54
54
|
/** XML comment, including malformed ones with `--` inside. */
|
|
55
|
-
const XML_COMMENT_RE = /<!--[\s\S]*?-->/
|
|
55
|
+
const XML_COMMENT_RE = /<!--[\s\S]*?-->/gv;
|
|
56
56
|
/**
|
|
57
57
|
* Map DTPlatformName / CFBundleSupportedPlatforms values to human-readable OS
|
|
58
58
|
* names.
|
|
@@ -81,11 +81,11 @@ function parse$1(content) {
|
|
|
81
81
|
const { copyrightHolder, copyrightYear } = parseCopyright(data);
|
|
82
82
|
const authorName = getString(data, "createdby") ?? getString(data, "contactName");
|
|
83
83
|
const authorEmailRot13 = getString(data, "contactEmailRot13");
|
|
84
|
-
const authorEmail = authorEmailRot13 ? rot13(authorEmailRot13)
|
|
84
|
+
const authorEmail = authorEmailRot13 === void 0 ? void 0 : rot13(authorEmailRot13);
|
|
85
85
|
const url = getString(data, "webaddress");
|
|
86
|
-
const
|
|
86
|
+
const appCategory = parseAppCategory(data);
|
|
87
87
|
return infoPlistSchema.parse({
|
|
88
|
-
applicationCategory,
|
|
88
|
+
applicationCategory: appCategory,
|
|
89
89
|
author: authorName,
|
|
90
90
|
authorEmail,
|
|
91
91
|
copyrightHolder,
|
|
@@ -127,7 +127,7 @@ function getString(data, key) {
|
|
|
127
127
|
* ROT13-decode a string (used by TextMate bundles for obfuscated emails).
|
|
128
128
|
*/
|
|
129
129
|
function rot13(value) {
|
|
130
|
-
return value.replaceAll(/[a-z]/
|
|
130
|
+
return value.replaceAll(/[a-z]/giv, (c) => {
|
|
131
131
|
const base = c <= "Z" ? 65 : 97;
|
|
132
132
|
return String.fromCodePoint((c.codePointAt(0) - base + 13) % 26 + base);
|
|
133
133
|
});
|
|
@@ -143,9 +143,9 @@ function humanizeCategory(uti) {
|
|
|
143
143
|
/**
|
|
144
144
|
* Parse application category from LSApplicationCategoryType.
|
|
145
145
|
*/
|
|
146
|
-
function
|
|
146
|
+
function parseAppCategory(data) {
|
|
147
147
|
const category = getString(data, "LSApplicationCategoryType");
|
|
148
|
-
if (
|
|
148
|
+
if (category === void 0) return;
|
|
149
149
|
return humanizeCategory(category);
|
|
150
150
|
}
|
|
151
151
|
/**
|
|
@@ -154,12 +154,12 @@ function parseApplicationCategory(data) {
|
|
|
154
154
|
*/
|
|
155
155
|
function parseCopyright(data) {
|
|
156
156
|
const copyrightSource = getString(data, "NSHumanReadableCopyright") ?? getString(data, "CFBundleGetInfoString");
|
|
157
|
-
if (
|
|
157
|
+
if (copyrightSource === void 0) return {};
|
|
158
158
|
const copyrightYear = COPYRIGHT_YEAR_REGEX.exec(copyrightSource)?.[1];
|
|
159
|
-
const
|
|
159
|
+
const holderText = COPYRIGHT_HOLDER_REGEX.exec(copyrightSource)?.[1];
|
|
160
160
|
let copyrightHolder;
|
|
161
|
-
if (
|
|
162
|
-
copyrightHolder =
|
|
161
|
+
if (holderText !== void 0) {
|
|
162
|
+
copyrightHolder = holderText.replace(ALL_RIGHTS_RESERVED_REGEX, "").replace(TRAILING_PUNCTUATION_REGEX, "").trim();
|
|
163
163
|
if (copyrightHolder.length === 0) copyrightHolder = void 0;
|
|
164
164
|
}
|
|
165
165
|
return {
|
|
@@ -174,27 +174,25 @@ function parseOperatingSystems(data) {
|
|
|
174
174
|
const results = [];
|
|
175
175
|
const seen = /* @__PURE__ */ new Set();
|
|
176
176
|
function add(value) {
|
|
177
|
-
if (
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
177
|
+
if (seen.has(value)) return;
|
|
178
|
+
seen.add(value);
|
|
179
|
+
results.push(value);
|
|
181
180
|
}
|
|
182
181
|
const minMacOS = getString(data, "LSMinimumSystemVersion");
|
|
183
|
-
if (minMacOS) add(`macOS >= ${minMacOS}`);
|
|
182
|
+
if (minMacOS !== void 0) add(`macOS >= ${minMacOS}`);
|
|
184
183
|
const minIOS = getString(data, "MinimumOSVersion");
|
|
185
|
-
if (minIOS) add(`iOS >= ${minIOS}`);
|
|
184
|
+
if (minIOS !== void 0) add(`iOS >= ${minIOS}`);
|
|
186
185
|
if (results.length > 0) return results;
|
|
187
186
|
const platformName = getString(data, "DTPlatformName");
|
|
188
|
-
if (platformName) {
|
|
187
|
+
if (platformName !== void 0) {
|
|
189
188
|
const os = PLATFORM_NAME_MAP[platformName.toLowerCase()];
|
|
190
|
-
if (os) add(os);
|
|
189
|
+
if (os !== void 0) add(os);
|
|
191
190
|
}
|
|
192
191
|
const supportedPlatforms = data.CFBundleSupportedPlatforms;
|
|
193
|
-
if (Array.isArray(supportedPlatforms)) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}
|
|
192
|
+
if (Array.isArray(supportedPlatforms)) for (const p of supportedPlatforms) {
|
|
193
|
+
if (typeof p !== "string") continue;
|
|
194
|
+
const os = PLATFORM_NAME_MAP[p.toLowerCase()];
|
|
195
|
+
if (os !== void 0) add(os);
|
|
198
196
|
}
|
|
199
197
|
if (data.LSRequiresIPhoneOS === true && !seen.has("iOS")) add("iOS");
|
|
200
198
|
return results;
|
|
@@ -217,7 +215,7 @@ const xcodeInfoPlistSource = defineSource({
|
|
|
217
215
|
key: "xcodeInfoPlist",
|
|
218
216
|
async parse(input, context) {
|
|
219
217
|
const data = parse$1(await readFile(resolve(context.options.path, input), "utf8"));
|
|
220
|
-
|
|
218
|
+
return data === void 0 ? void 0 : {
|
|
221
219
|
data,
|
|
222
220
|
source: input
|
|
223
221
|
};
|
|
@@ -22,10 +22,10 @@ import { PBXNativeTarget, XCRemoteSwiftPackageReference, XcodeProject } from "@m
|
|
|
22
22
|
* - Build settings on the main app target (Release config preferred)
|
|
23
23
|
* - Swift Package Manager dependencies
|
|
24
24
|
*/
|
|
25
|
-
const COPYRIGHT_YEAR_REGEX = /(?:©|\(c\)|copyright)\s*(\d{4})/
|
|
26
|
-
const COPYRIGHT_HOLDER_REGEX = /(?:©|\(c\)|copyright)\s*\d{4}\s*(.+)/
|
|
27
|
-
const ALL_RIGHTS_RESERVED_REGEX = /\.\s*all\s+rights\s+reserved\.?/
|
|
28
|
-
const TRAILING_PUNCTUATION_REGEX = /[.,;]
|
|
25
|
+
const COPYRIGHT_YEAR_REGEX = /(?:©|\(c\)|copyright)\s*(\d{4})/iv;
|
|
26
|
+
const COPYRIGHT_HOLDER_REGEX = /(?:©|\(c\)|copyright)\s*\d{4}\s*(.+)/iv;
|
|
27
|
+
const ALL_RIGHTS_RESERVED_REGEX = /\.\s*all\s+rights\s+reserved\.?/iv;
|
|
28
|
+
const TRAILING_PUNCTUATION_REGEX = /[.,;]+$/v;
|
|
29
29
|
const pbxprojDependencySchema = z.object({ url: z.string() });
|
|
30
30
|
const pbxprojSchema = z.object({
|
|
31
31
|
/** Copyright holder name. */
|
|
@@ -48,7 +48,7 @@ const pbxprojSchema = z.object({
|
|
|
48
48
|
version: nonEmptyString
|
|
49
49
|
});
|
|
50
50
|
/** Xcode build variable pattern: $(VAR) or ${VAR}. */
|
|
51
|
-
const XCODE_VARIABLE_RE = /\$[({][
|
|
51
|
+
const XCODE_VARIABLE_RE = /\$[\(\{][^\)\}]+[\)\}]/v;
|
|
52
52
|
/**
|
|
53
53
|
* Map SDKROOT values to human-readable OS names.
|
|
54
54
|
*/
|
|
@@ -122,8 +122,9 @@ function parse(filePath) {
|
|
|
122
122
|
const { copyrightHolder, copyrightYear } = parseCopyrightString(getSetting(targetSettings, projectSettings, "INFOPLIST_KEY_NSHumanReadableCopyright"));
|
|
123
123
|
const swiftVersion = getSetting(targetSettings, projectSettings, "SWIFT_VERSION");
|
|
124
124
|
let programmingLanguage;
|
|
125
|
-
if (swiftVersion
|
|
126
|
-
|
|
125
|
+
if (swiftVersion === void 0) {
|
|
126
|
+
if (getSetting(targetSettings, projectSettings, "GCC_C_LANGUAGE_STANDARD") !== void 0) programmingLanguage = "Objective-C";
|
|
127
|
+
} else programmingLanguage = "Swift";
|
|
127
128
|
return pbxprojSchema.parse({
|
|
128
129
|
copyrightHolder,
|
|
129
130
|
copyrightYear,
|
|
@@ -171,12 +172,12 @@ function getResolvedSetting(config, targetSettings, projectSettings, key) {
|
|
|
171
172
|
* Parse copyright information from a copyright string.
|
|
172
173
|
*/
|
|
173
174
|
function parseCopyrightString(copyrightSource) {
|
|
174
|
-
if (
|
|
175
|
+
if (copyrightSource === void 0) return {};
|
|
175
176
|
const copyrightYear = COPYRIGHT_YEAR_REGEX.exec(copyrightSource)?.[1];
|
|
176
|
-
const
|
|
177
|
+
const holderText = COPYRIGHT_HOLDER_REGEX.exec(copyrightSource)?.[1];
|
|
177
178
|
let copyrightHolder;
|
|
178
|
-
if (
|
|
179
|
-
copyrightHolder =
|
|
179
|
+
if (holderText !== void 0) {
|
|
180
|
+
copyrightHolder = holderText.replace(ALL_RIGHTS_RESERVED_REGEX, "").replace(TRAILING_PUNCTUATION_REGEX, "").trim();
|
|
180
181
|
if (copyrightHolder.length === 0) copyrightHolder = void 0;
|
|
181
182
|
}
|
|
182
183
|
return {
|
|
@@ -192,7 +193,7 @@ function parseOperatingSystems(targetSettings, projectSettings) {
|
|
|
192
193
|
const seen = /* @__PURE__ */ new Set();
|
|
193
194
|
for (const { key, os } of DEPLOYMENT_TARGETS) {
|
|
194
195
|
const version = getSetting(targetSettings, projectSettings, key);
|
|
195
|
-
if (version) {
|
|
196
|
+
if (version !== void 0) {
|
|
196
197
|
const value = `${os} >= ${version}`;
|
|
197
198
|
if (!seen.has(value)) {
|
|
198
199
|
seen.add(value);
|
|
@@ -202,9 +203,9 @@ function parseOperatingSystems(targetSettings, projectSettings) {
|
|
|
202
203
|
}
|
|
203
204
|
if (results.length === 0) {
|
|
204
205
|
const sdkroot = getSetting(targetSettings, projectSettings, "SDKROOT");
|
|
205
|
-
if (sdkroot && sdkroot !== "auto") {
|
|
206
|
+
if (sdkroot !== void 0 && sdkroot !== "auto") {
|
|
206
207
|
const os = SDKROOT_MAP[sdkroot];
|
|
207
|
-
if (os) results.push(os);
|
|
208
|
+
if (os !== void 0) results.push(os);
|
|
208
209
|
}
|
|
209
210
|
}
|
|
210
211
|
return results;
|
|
@@ -218,7 +219,7 @@ function parseDependencies(root) {
|
|
|
218
219
|
for (const packageReference of packageReferences) {
|
|
219
220
|
if (!XCRemoteSwiftPackageReference.is(packageReference)) continue;
|
|
220
221
|
const url = cleanString(packageReference.props.repositoryURL);
|
|
221
|
-
if (url) results.push({ url });
|
|
222
|
+
if (url !== void 0) results.push({ url });
|
|
222
223
|
}
|
|
223
224
|
return results;
|
|
224
225
|
}
|
|
@@ -229,7 +230,7 @@ const xcodeProjectPbxprojSource = defineSource({
|
|
|
229
230
|
key: "xcodeProjectPbxproj",
|
|
230
231
|
async parse(input, context) {
|
|
231
232
|
const data = parse(resolve(context.options.path, input));
|
|
232
|
-
|
|
233
|
+
return data === void 0 ? void 0 : {
|
|
233
234
|
data,
|
|
234
235
|
source: input
|
|
235
236
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Template } from "../metadata-types.js";
|
|
2
2
|
import { CodemetaDependencyLd, CodemetaPersonOrOrgLd } from "../utilities/codemeta-helpers.js";
|
|
3
|
+
import "../index.js";
|
|
3
4
|
//#region src/lib/templates/codemeta.d.ts
|
|
4
5
|
type TemplateDataCodemeta = ReturnType<typeof codemeta>;
|
|
5
6
|
declare const codemeta: Template<{
|