metascope 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.DS_Store +0 -0
- package/dist/bin/cli.js +14 -14
- package/dist/lib/{chunk-DrSxFLj_.js → _virtual/_rolldown/runtime.js} +1 -1
- package/dist/lib/file-matching.js +152 -0
- package/dist/lib/index.d.ts +11 -1496
- package/dist/lib/index.js +6 -6215
- package/dist/lib/log.d.ts +11 -0
- package/dist/lib/log.js +20 -0
- package/dist/lib/metadata-types.d.ts +151 -0
- package/dist/lib/metadata-types.js +30 -0
- package/dist/lib/metadata.d.ts +16 -0
- package/dist/lib/metadata.js +235 -0
- package/dist/lib/package.js +5 -0
- package/dist/lib/parsers/configparser-parser.js +43 -0
- package/dist/lib/parsers/gemspec-parser.js +256 -0
- package/dist/lib/parsers/go-mod-parser.js +153 -0
- package/dist/lib/parsers/makefile-config-parser.js +102 -0
- package/dist/lib/parsers/properties-parser.js +31 -0
- package/dist/lib/parsers/rfc822-header-parser.js +48 -0
- package/dist/lib/parsers/setup-py-parser.js +173 -0
- package/dist/lib/source.d.ts +17 -0
- package/dist/lib/source.js +34 -0
- package/dist/lib/sources/arduino-library-properties.d.ts +45 -0
- package/dist/lib/sources/arduino-library-properties.js +208 -0
- package/dist/lib/sources/cinder-cinderblock-xml.d.ts +21 -0
- package/dist/lib/sources/cinder-cinderblock-xml.js +134 -0
- package/dist/lib/sources/code-stats.d.ts +14 -0
- package/dist/lib/sources/code-stats.js +40 -0
- package/dist/lib/sources/codemeta-json.d.ts +117 -0
- package/dist/lib/sources/codemeta-json.js +226 -0
- package/dist/lib/sources/dependency-updates.d.ts +22 -0
- package/dist/lib/sources/dependency-updates.js +132 -0
- package/dist/lib/sources/file-stats.d.ts +12 -0
- package/dist/lib/sources/file-stats.js +48 -0
- package/dist/lib/sources/git-config.d.ts +8 -0
- package/dist/lib/sources/git-config.js +21 -0
- package/dist/lib/sources/git-stats.d.ts +35 -0
- package/dist/lib/sources/git-stats.js +130 -0
- package/dist/lib/sources/github.d.ts +94 -0
- package/dist/lib/sources/github.js +399 -0
- package/dist/lib/sources/go-go-mod.d.ts +19 -0
- package/dist/lib/sources/go-go-mod.js +38 -0
- package/dist/lib/sources/go-goreleaser-yaml.d.ts +19 -0
- package/dist/lib/sources/go-goreleaser-yaml.js +152 -0
- package/dist/lib/sources/java-pom-xml.d.ts +52 -0
- package/dist/lib/sources/java-pom-xml.js +248 -0
- package/dist/lib/sources/license-file.d.ts +10 -0
- package/dist/lib/sources/license-file.js +26 -0
- package/dist/lib/sources/metadata-file.d.ts +14 -0
- package/dist/lib/sources/metadata-file.js +109 -0
- package/dist/lib/sources/metascope.d.ts +14 -0
- package/dist/lib/sources/metascope.js +35 -0
- package/dist/lib/sources/node-npm-registry.d.ts +19 -0
- package/dist/lib/sources/node-npm-registry.js +74 -0
- package/dist/lib/sources/node-package-json.d.ts +7 -0
- package/dist/lib/sources/node-package-json.js +27 -0
- package/dist/lib/sources/obsidian-plugin-manifest-json.d.ts +17 -0
- package/dist/lib/sources/obsidian-plugin-manifest-json.js +34 -0
- package/dist/lib/sources/obsidian-plugin-registry.d.ts +10 -0
- package/dist/lib/sources/obsidian-plugin-registry.js +44 -0
- package/dist/lib/sources/openframeworks-addon-config-mk.d.ts +17 -0
- package/dist/lib/sources/openframeworks-addon-config-mk.js +39 -0
- package/dist/lib/sources/openframeworks-install-xml.d.ts +20 -0
- package/dist/lib/sources/openframeworks-install-xml.js +153 -0
- package/dist/lib/sources/processing-library-properties.d.ts +44 -0
- package/dist/lib/sources/processing-library-properties.js +219 -0
- package/dist/lib/sources/processing-sketch-properties.d.ts +38 -0
- package/dist/lib/sources/processing-sketch-properties.js +185 -0
- package/dist/lib/sources/publiccode-yaml.d.ts +73 -0
- package/dist/lib/sources/publiccode-yaml.js +256 -0
- package/dist/lib/sources/python-pkg-info.d.ts +31 -0
- package/dist/lib/sources/python-pkg-info.js +115 -0
- package/dist/lib/sources/python-pypi-registry.d.ts +19 -0
- package/dist/lib/sources/python-pypi-registry.js +101 -0
- package/dist/lib/sources/python-pyproject-toml.d.ts +7 -0
- package/dist/lib/sources/python-pyproject-toml.js +30 -0
- package/dist/lib/sources/python-setup-cfg.d.ts +28 -0
- package/dist/lib/sources/python-setup-cfg.js +106 -0
- package/dist/lib/sources/python-setup-py.d.ts +28 -0
- package/dist/lib/sources/python-setup-py.js +48 -0
- package/dist/lib/sources/readme-file.d.ts +11 -0
- package/dist/lib/sources/readme-file.js +55 -0
- package/dist/lib/sources/ruby-gemspec.d.ts +44 -0
- package/dist/lib/sources/ruby-gemspec.js +62 -0
- package/dist/lib/sources/rust-cargo-toml.d.ts +40 -0
- package/dist/lib/sources/rust-cargo-toml.js +159 -0
- package/dist/lib/sources/xcode-info-plist.d.ts +22 -0
- package/dist/lib/sources/xcode-info-plist.js +199 -0
- package/dist/lib/sources/xcode-project-pbxproj.d.ts +21 -0
- package/dist/lib/sources/xcode-project-pbxproj.js +222 -0
- package/dist/lib/templates/codemeta.d.ts +47 -0
- package/dist/lib/templates/codemeta.js +494 -0
- package/dist/lib/templates/frontmatter.d.ts +87 -0
- package/dist/lib/templates/frontmatter.js +111 -0
- package/dist/lib/templates/index.d.ts +181 -0
- package/dist/lib/templates/index.js +22 -0
- package/dist/lib/templates/metadata.d.ts +17 -0
- package/dist/lib/templates/metadata.js +35 -0
- package/dist/lib/templates/project.d.ts +39 -0
- package/dist/lib/templates/project.js +51 -0
- package/dist/lib/utilities/codemeta-helpers.d.ts +39 -0
- package/dist/lib/utilities/codemeta-helpers.js +83 -0
- package/dist/lib/utilities/fetch.js +43 -0
- package/dist/lib/utilities/formatting.js +28 -0
- package/dist/lib/utilities/license-identification.js +141 -0
- package/dist/lib/utilities/schema-primitives.js +47 -0
- package/dist/lib/utilities/template-helpers.d.ts +135 -0
- package/dist/lib/utilities/template-helpers.js +310 -0
- package/dist/lib/utilities/tree-sitter-wasm.js +30 -0
- package/package.json +6 -6
- package/readme.md +62 -15
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
import { defineTemplate } from "../metadata-types.js";
|
|
2
|
+
import { collectArrayField, collectField, firstOf, nonEmpty, stripUndefined } from "../utilities/template-helpers.js";
|
|
3
|
+
import { deduplicateDependencies, deduplicatePersonsOrOrgs, toDependencyLd, toPersonOrOrgLd, toSpdxLicenseUrl } from "../utilities/codemeta-helpers.js";
|
|
4
|
+
import { basename, relative } from "node:path";
|
|
5
|
+
import is from "@sindresorhus/is";
|
|
6
|
+
//#region src/lib/templates/codemeta.ts
|
|
7
|
+
/**
|
|
8
|
+
* CodeMeta 3.0 JSON-LD template.
|
|
9
|
+
*
|
|
10
|
+
* Generates a valid codemeta.json (https://codemeta.github.io/) by cascading
|
|
11
|
+
* data from all available metascope sources.
|
|
12
|
+
*
|
|
13
|
+
* ## Cascade strategy
|
|
14
|
+
*
|
|
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.
|
|
20
|
+
*
|
|
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.
|
|
24
|
+
*
|
|
25
|
+
* ## Software type inference
|
|
26
|
+
*
|
|
27
|
+
* Set `INFER_TARGET_PRODUCT` to `true` to enable heuristic inference of
|
|
28
|
+
* `targetProduct` from available signals (bin field, browser field, etc.).
|
|
29
|
+
*/
|
|
30
|
+
const codemeta = defineTemplate(({ arduinoLibraryProperties, cinderCinderblockXml, codemetaJson: codemetaRaw, codeStats, fileStats, github: githubRaw, gitStats: gitRaw, goGoMod, javaPomXml, licenseFile, metascope, nodeNpmRegistry: npmRaw, nodePackageJson, obsidianPluginManifestJson, openframeworksAddonConfigMk, openframeworksInstallXml, processingLibraryProperties, publiccodeYaml, pythonPkgInfo, pythonPypiRegistry: pypiRaw, pythonPyprojectToml, pythonSetupCfg, pythonSetupPy, readmeFile, rubyGemspec, rustCargoToml, xcodeInfoPlist }) => {
|
|
31
|
+
const cm = firstOf(codemetaRaw);
|
|
32
|
+
const github = firstOf(githubRaw);
|
|
33
|
+
const git = firstOf(gitRaw);
|
|
34
|
+
const npm = firstOf(npmRaw);
|
|
35
|
+
const pypi = firstOf(pypiRaw);
|
|
36
|
+
const package_ = firstOf(nodePackageJson);
|
|
37
|
+
const pyproject = firstOf(pythonPyprojectToml);
|
|
38
|
+
const setupPy = firstOf(pythonSetupPy);
|
|
39
|
+
const setupCfg = firstOf(pythonSetupCfg);
|
|
40
|
+
const pkgInfo = firstOf(pythonPkgInfo);
|
|
41
|
+
const cargo = firstOf(rustCargoToml);
|
|
42
|
+
const gem = firstOf(rubyGemspec);
|
|
43
|
+
const pom = firstOf(javaPomXml);
|
|
44
|
+
const goMod = firstOf(goGoMod);
|
|
45
|
+
const arduino = firstOf(arduinoLibraryProperties);
|
|
46
|
+
const processing = firstOf(processingLibraryProperties);
|
|
47
|
+
const ofAddon = firstOf(openframeworksAddonConfigMk);
|
|
48
|
+
const ofInstall = firstOf(openframeworksInstallXml);
|
|
49
|
+
const cinder = firstOf(cinderCinderblockXml);
|
|
50
|
+
const xcode = firstOf(xcodeInfoPlist);
|
|
51
|
+
const obsidian = firstOf(obsidianPluginManifestJson);
|
|
52
|
+
const publiccode = firstOf(publiccodeYaml);
|
|
53
|
+
const loc = firstOf(codeStats);
|
|
54
|
+
const readmeFileFirst = firstOf(readmeFile);
|
|
55
|
+
const fileStatsFirst = firstOf(fileStats);
|
|
56
|
+
const poetry = pyproject?.data.tool?.poetry;
|
|
57
|
+
const name = package_?.data.name ?? pyproject?.data.project?.name ?? poetry?.name ?? setupPy?.data.name ?? setupCfg?.data.name ?? pkgInfo?.data.name ?? cargo?.data.name ?? gem?.data.name ?? pom?.data.name ?? goMod?.data.module ?? arduino?.data.name ?? processing?.data.name ?? ofAddon?.data.name ?? ofInstall?.data.name ?? cinder?.data.name ?? xcode?.data.name ?? obsidian?.data.name ?? publiccode?.data.name ?? cm?.data.name ?? readmeFileFirst?.data.name ?? fileStatsFirst?.data.folderName;
|
|
58
|
+
const description = package_?.data.description ?? pyproject?.data.project?.description ?? poetry?.description ?? setupPy?.data.description ?? setupCfg?.data.description ?? pkgInfo?.data.summary ?? cargo?.data.description ?? gem?.data.summary ?? pom?.data.description ?? arduino?.data.sentence ?? processing?.data.sentence ?? ofAddon?.data.description ?? ofInstall?.data.description ?? cinder?.data.summary ?? xcode?.data.description ?? obsidian?.data.description ?? publiccode?.data.description?.shortDescription ?? cm?.data.description ?? github?.data.description;
|
|
59
|
+
const version = package_?.data.version ?? pyproject?.data.project?.version ?? poetry?.version ?? setupPy?.data.version ?? setupCfg?.data.version ?? pkgInfo?.data.version ?? cargo?.data.version ?? gem?.data.version ?? pom?.data.version ?? arduino?.data.version ?? processing?.data.prettyVersion ?? ofInstall?.data.version ?? cinder?.data.version ?? xcode?.data.version ?? obsidian?.data.version ?? publiccode?.data.softwareVersion ?? cm?.data.version ?? cm?.data.softwareVersion;
|
|
60
|
+
const identifier = pom?.data.identifier ?? cinder?.data.id ?? obsidian?.data.id ?? xcode?.data.identifier ?? package_?.data.name ?? cm?.data.identifier;
|
|
61
|
+
const ecosystemAuthors = [
|
|
62
|
+
...package_?.data.author ? [toPersonOrOrgLd({
|
|
63
|
+
email: package_.data.author.email,
|
|
64
|
+
name: package_.data.author.name,
|
|
65
|
+
url: package_.data.author.url
|
|
66
|
+
})] : [],
|
|
67
|
+
...(pyproject?.data.project?.authors ?? []).map((a) => is.plainObject(a) ? toPersonOrOrgLd({
|
|
68
|
+
email: a.email,
|
|
69
|
+
name: a.name
|
|
70
|
+
}) : toPersonOrOrgLd({ name: a })),
|
|
71
|
+
...setupPy?.data.author ? [toPersonOrOrgLd({
|
|
72
|
+
email: setupPy.data.author_email,
|
|
73
|
+
name: setupPy.data.author
|
|
74
|
+
})] : [],
|
|
75
|
+
...setupCfg?.data.author ? [toPersonOrOrgLd({
|
|
76
|
+
email: setupCfg.data.author_email,
|
|
77
|
+
name: setupCfg.data.author
|
|
78
|
+
})] : [],
|
|
79
|
+
...(cargo?.data.authors ?? []).map((a) => toPersonOrOrgLd({
|
|
80
|
+
email: a.email,
|
|
81
|
+
name: a.name
|
|
82
|
+
})),
|
|
83
|
+
...gemspecAuthors(gem),
|
|
84
|
+
...(pom?.data.developers ?? []).map((d) => toPersonOrOrgLd({
|
|
85
|
+
affiliation: d.organization,
|
|
86
|
+
email: d.email,
|
|
87
|
+
name: d.name,
|
|
88
|
+
url: d.url
|
|
89
|
+
})),
|
|
90
|
+
...(arduino?.data.authors ?? []).map((a) => toPersonOrOrgLd({
|
|
91
|
+
email: a.email,
|
|
92
|
+
name: a.name
|
|
93
|
+
})),
|
|
94
|
+
...(processing?.data.authors ?? []).map((a) => toPersonOrOrgLd({
|
|
95
|
+
name: a.name,
|
|
96
|
+
url: a.url
|
|
97
|
+
})),
|
|
98
|
+
...ofAddon?.data.author ? [toPersonOrOrgLd({ name: ofAddon.data.author })] : [],
|
|
99
|
+
...ofInstall?.data.author ? [toPersonOrOrgLd({ name: ofInstall.data.author })] : [],
|
|
100
|
+
...(cinder?.data.author ?? []).map((a) => toPersonOrOrgLd({ name: a })),
|
|
101
|
+
...xcode?.data.author ? [toPersonOrOrgLd({
|
|
102
|
+
email: xcode.data.authorEmail,
|
|
103
|
+
name: xcode.data.author
|
|
104
|
+
})] : [],
|
|
105
|
+
...obsidian?.data.author ? [toPersonOrOrgLd({
|
|
106
|
+
name: obsidian.data.author,
|
|
107
|
+
url: obsidian.data.authorUrl
|
|
108
|
+
})] : [],
|
|
109
|
+
...(publiccode?.data.contacts ?? []).map((c) => toPersonOrOrgLd({
|
|
110
|
+
affiliation: c.affiliation,
|
|
111
|
+
email: c.email,
|
|
112
|
+
name: c.name
|
|
113
|
+
}))
|
|
114
|
+
];
|
|
115
|
+
const cmAuthors = cm?.data.author?.map((p) => toPersonOrOrgLd({
|
|
116
|
+
affiliation: p.affiliation,
|
|
117
|
+
email: p.email,
|
|
118
|
+
familyName: p.familyName,
|
|
119
|
+
givenName: p.givenName,
|
|
120
|
+
id: p.id,
|
|
121
|
+
name: p.name,
|
|
122
|
+
type: p.type,
|
|
123
|
+
url: p.url
|
|
124
|
+
}));
|
|
125
|
+
const author = resolvePersonsOrOrgs(ecosystemAuthors, cmAuthors);
|
|
126
|
+
const ecosystemContributors = [...collectArrayField(nodePackageJson, (d) => d.contributors?.map((c) => is.plainObject(c) ? toPersonOrOrgLd({
|
|
127
|
+
email: c.email,
|
|
128
|
+
name: c.name,
|
|
129
|
+
url: c.url
|
|
130
|
+
}) : toPersonOrOrgLd({ name: c }))), ...(pom?.data.contributors ?? []).map((c) => toPersonOrOrgLd({
|
|
131
|
+
affiliation: c.organization,
|
|
132
|
+
email: c.email,
|
|
133
|
+
name: c.name,
|
|
134
|
+
url: c.url
|
|
135
|
+
}))];
|
|
136
|
+
const cmContributors = cm?.data.contributor?.map((p) => toPersonOrOrgLd({
|
|
137
|
+
affiliation: p.affiliation,
|
|
138
|
+
email: p.email,
|
|
139
|
+
familyName: p.familyName,
|
|
140
|
+
givenName: p.givenName,
|
|
141
|
+
id: p.id,
|
|
142
|
+
name: p.name,
|
|
143
|
+
type: p.type,
|
|
144
|
+
url: p.url
|
|
145
|
+
}));
|
|
146
|
+
const contributor = resolvePersonsOrOrgs(ecosystemContributors, cmContributors);
|
|
147
|
+
const ecosystemMaintainers = [
|
|
148
|
+
...collectArrayField(nodePackageJson, (d) => d.maintainers?.map((c) => is.plainObject(c) ? toPersonOrOrgLd({
|
|
149
|
+
email: c.email,
|
|
150
|
+
name: c.name,
|
|
151
|
+
url: c.url
|
|
152
|
+
}) : toPersonOrOrgLd({ name: c }))),
|
|
153
|
+
...(pyproject?.data.project?.maintainers ?? []).map((m) => is.plainObject(m) ? toPersonOrOrgLd({
|
|
154
|
+
email: m.email,
|
|
155
|
+
name: m.name
|
|
156
|
+
}) : toPersonOrOrgLd({ name: m })),
|
|
157
|
+
...setupPy?.data.maintainer ? [toPersonOrOrgLd({
|
|
158
|
+
email: setupPy.data.maintainer_email,
|
|
159
|
+
name: setupPy.data.maintainer
|
|
160
|
+
})] : [],
|
|
161
|
+
...setupCfg?.data.maintainer ? [toPersonOrOrgLd({
|
|
162
|
+
email: setupCfg.data.maintainer_email,
|
|
163
|
+
name: setupCfg.data.maintainer
|
|
164
|
+
})] : [],
|
|
165
|
+
...pkgInfo?.data.maintainer ? [toPersonOrOrgLd({
|
|
166
|
+
email: pkgInfo.data.maintainer_email,
|
|
167
|
+
name: pkgInfo.data.maintainer
|
|
168
|
+
})] : [],
|
|
169
|
+
...arduino?.data.maintainer ? [toPersonOrOrgLd({
|
|
170
|
+
email: arduino.data.maintainer.email,
|
|
171
|
+
name: arduino.data.maintainer.name
|
|
172
|
+
})] : []
|
|
173
|
+
];
|
|
174
|
+
const cmMaintainers = cm?.data.maintainer?.map((p) => toPersonOrOrgLd({
|
|
175
|
+
affiliation: p.affiliation,
|
|
176
|
+
email: p.email,
|
|
177
|
+
familyName: p.familyName,
|
|
178
|
+
givenName: p.givenName,
|
|
179
|
+
id: p.id,
|
|
180
|
+
name: p.name,
|
|
181
|
+
type: p.type,
|
|
182
|
+
url: p.url
|
|
183
|
+
}));
|
|
184
|
+
const maintainer = resolvePersonsOrOrgs(ecosystemMaintainers, cmMaintainers);
|
|
185
|
+
const ecosystemCopyrightHolders = [...publiccode?.data.mainCopyrightOwner ? [toPersonOrOrgLd({ name: publiccode.data.mainCopyrightOwner })] : [], ...xcode?.data.copyrightHolder ? [toPersonOrOrgLd({ name: xcode.data.copyrightHolder })] : []];
|
|
186
|
+
const cmCopyrightHolders = cm?.data.copyrightHolder?.map((p) => toPersonOrOrgLd({
|
|
187
|
+
affiliation: p.affiliation,
|
|
188
|
+
email: p.email,
|
|
189
|
+
familyName: p.familyName,
|
|
190
|
+
givenName: p.givenName,
|
|
191
|
+
id: p.id,
|
|
192
|
+
name: p.name,
|
|
193
|
+
type: p.type,
|
|
194
|
+
url: p.url
|
|
195
|
+
}));
|
|
196
|
+
const copyrightHolder = resolvePersonsOrOrgs(ecosystemCopyrightHolders, cmCopyrightHolders);
|
|
197
|
+
const funder = resolvePersonsOrOrgs([], cm?.data.funder?.map((p) => toPersonOrOrgLd({
|
|
198
|
+
affiliation: p.affiliation,
|
|
199
|
+
email: p.email,
|
|
200
|
+
familyName: p.familyName,
|
|
201
|
+
givenName: p.givenName,
|
|
202
|
+
id: p.id,
|
|
203
|
+
name: p.name,
|
|
204
|
+
type: p.type,
|
|
205
|
+
url: p.url
|
|
206
|
+
})));
|
|
207
|
+
const codeRepository = github?.data.url ?? cargo?.data.repository ?? pom?.data.scmUrl ?? goMod?.data.repository_url ?? publiccode?.data.url ?? arduino?.data.repository ?? cinder?.data.git ?? cm?.data.codeRepository ?? repositoryUrlFromPackageJson(package_?.data.repository) ?? caseInsensitiveLookup(pyproject?.data.project?.urls, "repository") ?? poetry?.repository;
|
|
208
|
+
const programmingLanguage = nonEmpty([...github?.data.primaryLanguage ? [github.data.primaryLanguage] : [], ...cm?.data.programmingLanguage ?? []]) ?? nonEmpty(Object.keys(github?.data.languages ?? {})) ?? loc?.data.total?.languages.slice(0, 1);
|
|
209
|
+
const runtimePlatform = nonEmpty([
|
|
210
|
+
...Object.keys(package_?.data.engines ?? {}),
|
|
211
|
+
...goMod?.data.go_version ? [`go ${goMod.data.go_version}`] : [],
|
|
212
|
+
...cargo?.data.rustVersion ? [`rust ${cargo.data.rustVersion}`] : [],
|
|
213
|
+
...pyproject?.data.project?.requiresPython ? [`python ${pyproject.data.project.requiresPython}`] : [],
|
|
214
|
+
...setupPy?.data.python_requires ? [`python ${setupPy.data.python_requires}`] : [],
|
|
215
|
+
...gem?.data.required_ruby_version ? [`ruby ${gem.data.required_ruby_version}`] : [],
|
|
216
|
+
...pom?.data.javaVersion ? [`java ${pom.data.javaVersion}`] : [],
|
|
217
|
+
...cm?.data.runtimePlatform ?? []
|
|
218
|
+
]);
|
|
219
|
+
const operatingSystem = nonEmpty([
|
|
220
|
+
...cm?.data.operatingSystem ?? [],
|
|
221
|
+
...publiccode?.data.platforms ?? [],
|
|
222
|
+
...ofInstall?.data.operatingSystems ?? [],
|
|
223
|
+
...cinder?.data.supports ?? [],
|
|
224
|
+
...xcode?.data.operatingSystems ?? []
|
|
225
|
+
]);
|
|
226
|
+
const applicationCategory = cm?.data.applicationCategory ?? xcode?.data.applicationCategory ?? arduino?.data.category ?? publiccode?.data.softwareType;
|
|
227
|
+
const applicationSubCategory = cm?.data.applicationSubCategory;
|
|
228
|
+
const runtimeDeps = collectRuntimeDeps({
|
|
229
|
+
arduino,
|
|
230
|
+
cargo,
|
|
231
|
+
cinder,
|
|
232
|
+
gem,
|
|
233
|
+
goGoMod,
|
|
234
|
+
javaPomXml,
|
|
235
|
+
nodePackageJson,
|
|
236
|
+
ofAddon,
|
|
237
|
+
ofInstall,
|
|
238
|
+
pkgInfo,
|
|
239
|
+
publiccode,
|
|
240
|
+
pyproject,
|
|
241
|
+
rubyGemspec,
|
|
242
|
+
setupCfg,
|
|
243
|
+
setupPy
|
|
244
|
+
});
|
|
245
|
+
const softwareRequirements = runtimeDeps.length > 0 ? deduplicateDependencies(runtimeDeps) : cm?.data.softwareRequirements?.map((d) => toDependencyLd(d.name ?? d.identifier ?? "", d.version, d.identifier, d.runtimePlatform));
|
|
246
|
+
const developmentDeps = collectDevelopmentDeps({
|
|
247
|
+
cargo,
|
|
248
|
+
gem,
|
|
249
|
+
javaPomXml,
|
|
250
|
+
nodePackageJson,
|
|
251
|
+
rubyGemspec
|
|
252
|
+
});
|
|
253
|
+
const softwareSuggestions = developmentDeps.length > 0 ? deduplicateDependencies(developmentDeps) : cm?.data.softwareSuggestions?.map((d) => toDependencyLd(d.name ?? d.identifier ?? "", d.version, d.identifier, d.runtimePlatform));
|
|
254
|
+
const dateCreated = git?.data.commitDateFirst ?? github?.data.createdAt ?? cm?.data.dateCreated;
|
|
255
|
+
const dateModified = git?.data.commitDateLast ?? github?.data.pushedAt ?? cm?.data.dateModified;
|
|
256
|
+
const datePublished = npm?.data.publishDateLatest ?? pypi?.data.publishDateLatest ?? publiccode?.data.releaseDate ?? github?.data.releaseDateLatest ?? git?.data.tagVersionDateLatest ?? cm?.data.datePublished;
|
|
257
|
+
const copyrightYear = xcode?.data.copyrightYear ?? pom?.data.inceptionYear ?? (cm?.data.copyrightYear === void 0 ? void 0 : String(cm.data.copyrightYear));
|
|
258
|
+
const rawLicense = package_?.data.license ?? cargo?.data.license ?? resolvePythonLicense(pyproject?.data.project?.license) ?? setupPy?.data.license ?? setupCfg?.data.license ?? gem?.data.license ?? firstPomLicense(pom) ?? arduino?.data.license ?? cinder?.data.license ?? publiccode?.data.license ?? github?.data.licenseSpdxId ?? collectField(licenseFile, (d) => d.spdxId)[0] ?? resolveCmLicense(cm?.data.license);
|
|
259
|
+
const license = is.nonEmptyStringAndNotWhitespace(rawLicense) ? toSpdxLicenseUrl(rawLicense) : void 0;
|
|
260
|
+
const isAccessibleForFree = cm?.data.isAccessibleForFree ?? (github?.data.isPrivate === false ? true : void 0);
|
|
261
|
+
const keywords = nonEmpty(deduplicateStrings([
|
|
262
|
+
...package_?.data.keywords ?? [],
|
|
263
|
+
...pyproject?.data.project?.keywords ?? [],
|
|
264
|
+
...poetry?.keywords ?? [],
|
|
265
|
+
...setupPy?.data.keywords ?? [],
|
|
266
|
+
...setupCfg?.data.keywords ?? [],
|
|
267
|
+
...pkgInfo?.data.keywords ?? [],
|
|
268
|
+
...cargo?.data.keywords ?? [],
|
|
269
|
+
...ofAddon?.data.tags ?? [],
|
|
270
|
+
...publiccode?.data.categories ?? [],
|
|
271
|
+
...github?.data.topics ?? [],
|
|
272
|
+
...cm?.data.keywords ?? []
|
|
273
|
+
]));
|
|
274
|
+
const url = stripReadmeFragment(package_?.data.homepage) ?? caseInsensitiveLookup(pyproject?.data.project?.urls, "homepage") ?? poetry?.homepage ?? cargo?.data.homepage ?? setupPy?.data.url ?? setupCfg?.data.url ?? pkgInfo?.data.home_page ?? gem?.data.homepage ?? pom?.data.url ?? arduino?.data.url ?? processing?.data.url ?? ofAddon?.data.url ?? ofInstall?.data.siteUrl ?? cinder?.data.url ?? xcode?.data.url ?? publiccode?.data.landingUrl ?? github?.data.homepageUrl ?? cm?.data.url ?? caseInsensitiveLookup(pyproject?.data.project?.urls, "repository") ?? poetry?.repository;
|
|
275
|
+
const downloadUrl = ofInstall?.data.downloadUrl ?? processing?.data.download ?? npm?.data.url ?? pypi?.data.url ?? cm?.data.downloadUrl;
|
|
276
|
+
const issueTracker = bugsUrlFromPackageJson(package_?.data.bugs) ?? pom?.data.issueManagementUrl ?? cm?.data.issueTracker ?? (github?.data.hasIssuesEnabled ? `${github.data.url}/issues` : void 0);
|
|
277
|
+
const continuousIntegration = pom?.data.ciManagementUrl ?? cm?.data.continuousIntegration;
|
|
278
|
+
const softwareHelp = cargo?.data.documentation ?? cm?.data.softwareHelp;
|
|
279
|
+
const developmentStatus = publiccode?.data.developmentStatus ?? cm?.data.developmentStatus;
|
|
280
|
+
const funding = cm?.data.funding;
|
|
281
|
+
const buildInstructions = cm?.data.buildInstructions;
|
|
282
|
+
const readme = readmeUrl(firstOf(readmeFile), codeRepository, github?.data.defaultBranch ?? git?.data.branchCurrent, firstOf(metascope)?.data.options.path) ?? cm?.data.readme;
|
|
283
|
+
const releaseNotes = cm?.data.releaseNotes;
|
|
284
|
+
const installUrl = cm?.data.installUrl;
|
|
285
|
+
const relatedLink = cm?.data.relatedLink;
|
|
286
|
+
const targetProduct = void 0;
|
|
287
|
+
return stripUndefined({
|
|
288
|
+
"@context": "https://w3id.org/codemeta/3.0",
|
|
289
|
+
"@type": "SoftwareSourceCode",
|
|
290
|
+
applicationCategory,
|
|
291
|
+
applicationSubCategory,
|
|
292
|
+
author,
|
|
293
|
+
buildInstructions,
|
|
294
|
+
codeRepository,
|
|
295
|
+
continuousIntegration,
|
|
296
|
+
contributor,
|
|
297
|
+
copyrightHolder,
|
|
298
|
+
copyrightYear: is.nonEmptyStringAndNotWhitespace(copyrightYear) ? Number.parseInt(copyrightYear, 10) || void 0 : void 0,
|
|
299
|
+
dateCreated: toDateOnly(dateCreated),
|
|
300
|
+
dateModified: toDateOnly(dateModified),
|
|
301
|
+
datePublished: toDateOnly(datePublished),
|
|
302
|
+
description,
|
|
303
|
+
developmentStatus,
|
|
304
|
+
downloadUrl,
|
|
305
|
+
funder,
|
|
306
|
+
funding,
|
|
307
|
+
identifier,
|
|
308
|
+
installUrl,
|
|
309
|
+
isAccessibleForFree,
|
|
310
|
+
issueTracker,
|
|
311
|
+
keywords,
|
|
312
|
+
license,
|
|
313
|
+
maintainer,
|
|
314
|
+
name,
|
|
315
|
+
operatingSystem,
|
|
316
|
+
programmingLanguage,
|
|
317
|
+
readme,
|
|
318
|
+
relatedLink,
|
|
319
|
+
releaseNotes,
|
|
320
|
+
runtimePlatform,
|
|
321
|
+
softwareHelp,
|
|
322
|
+
softwareRequirements,
|
|
323
|
+
softwareSuggestions,
|
|
324
|
+
targetProduct,
|
|
325
|
+
url,
|
|
326
|
+
version
|
|
327
|
+
});
|
|
328
|
+
});
|
|
329
|
+
/**
|
|
330
|
+
* Extract authors from a gemspec record.
|
|
331
|
+
* Gemspec has `authors: string[]` and a separate `email: string | string[]`.
|
|
332
|
+
* We pair them by index where possible.
|
|
333
|
+
*/
|
|
334
|
+
function gemspecAuthors(gem) {
|
|
335
|
+
if (gem === void 0) return [];
|
|
336
|
+
const emails = gem.data.email === void 0 ? [] : Array.isArray(gem.data.email) ? gem.data.email : [gem.data.email];
|
|
337
|
+
return gem.data.authors.map((authorName, index) => toPersonOrOrgLd({
|
|
338
|
+
email: emails[index],
|
|
339
|
+
name: authorName
|
|
340
|
+
}));
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Takes ecosystem persons (which may include undefined) and codemeta fallback persons.
|
|
344
|
+
* Uses ecosystem if any are present, otherwise falls back.
|
|
345
|
+
* Always deduplicates by name.
|
|
346
|
+
*/
|
|
347
|
+
function resolvePersonsOrOrgs(ecosystemPersons, fallbackPersons) {
|
|
348
|
+
const ecosystem = ecosystemPersons.filter((p) => p !== void 0);
|
|
349
|
+
if (ecosystem.length > 0) return deduplicatePersonsOrOrgs(ecosystem);
|
|
350
|
+
return deduplicatePersonsOrOrgs((fallbackPersons ?? []).filter((p) => p !== void 0));
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Collect runtime dependencies from all ecosystem sources.
|
|
354
|
+
*/
|
|
355
|
+
function collectRuntimeDeps(sources) {
|
|
356
|
+
const deps = [];
|
|
357
|
+
deps.push(...collectArrayField(sources.nodePackageJson, (d) => objectEntriesToDeps(d.dependencies)));
|
|
358
|
+
deps.push(...(sources.pyproject?.data.project?.dependencies ?? []).map((dep) => parsePep508Dep(dep)));
|
|
359
|
+
deps.push(...(sources.setupPy?.data.install_requires ?? []).map((dep) => parsePep508Dep(dep)));
|
|
360
|
+
deps.push(...(sources.setupCfg?.data.install_requires ?? []).map((dep) => parsePep508Dep(dep)));
|
|
361
|
+
deps.push(...(sources.pkgInfo?.data.requires_dist ?? []).map((dep) => parsePep508Dep(dep)));
|
|
362
|
+
deps.push(...(sources.cargo?.data.dependencies ?? []).map((d) => toDependencyLd(d.name, d.version)));
|
|
363
|
+
deps.push(...collectArrayField(sources.rubyGemspec, (d) => d.dependencies.filter((dep) => dep.type === "runtime").map((dep) => toDependencyLd(dep.name, dep.requirements.join(", ")))));
|
|
364
|
+
deps.push(...collectArrayField(sources.javaPomXml, (d) => d.dependencies.map((dep) => toDependencyLd(dep.artifactId, dep.version, `${dep.groupId}:${dep.artifactId}`))));
|
|
365
|
+
deps.push(...collectArrayField(sources.goGoMod, (d) => d.dependencies.map((dep) => toDependencyLd(dep.module, dep.version))));
|
|
366
|
+
deps.push(...(sources.arduino?.data.depends ?? []).map((d) => toDependencyLd(d.name, d.versionConstraint)));
|
|
367
|
+
deps.push(...(sources.ofAddon?.data.dependencies ?? []).map((d) => toDependencyLd(d)));
|
|
368
|
+
deps.push(...(sources.ofInstall?.data.requirements ?? []).map((d) => toDependencyLd(d)));
|
|
369
|
+
deps.push(...(sources.cinder?.data.requires ?? []).map((d) => toDependencyLd(d)));
|
|
370
|
+
deps.push(...(sources.publiccode?.data.dependencies ?? []).map((d) => toDependencyLd(d.name, d.version)));
|
|
371
|
+
return deps;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Collect dev dependencies from ecosystem sources.
|
|
375
|
+
*/
|
|
376
|
+
function collectDevelopmentDeps(sources) {
|
|
377
|
+
const deps = [];
|
|
378
|
+
deps.push(...collectArrayField(sources.nodePackageJson, (d) => objectEntriesToDeps(d.devDependencies)));
|
|
379
|
+
deps.push(...(sources.cargo?.data.devDependencies ?? []).map((d) => toDependencyLd(d.name, d.version)));
|
|
380
|
+
deps.push(...collectArrayField(sources.rubyGemspec, (d) => d.dependencies.filter((dep) => dep.type === "development").map((dep) => toDependencyLd(dep.name, dep.requirements.join(", ")))));
|
|
381
|
+
deps.push(...collectArrayField(sources.javaPomXml, (d) => d.devDependencies.map((dep) => toDependencyLd(dep.artifactId, dep.version, `${dep.groupId}:${dep.artifactId}`))));
|
|
382
|
+
return deps;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Convert a Record<name, version> dependency map to CodemetaDependencyLd[].
|
|
386
|
+
*/
|
|
387
|
+
function objectEntriesToDeps(deps) {
|
|
388
|
+
if (deps === void 0) return void 0;
|
|
389
|
+
return Object.entries(deps).map(([depName, depVersion]) => toDependencyLd(depName, depVersion));
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Parse a PEP 508 dependency string ("package>=1.0") into a CodemetaDependencyLd.
|
|
393
|
+
*/
|
|
394
|
+
function parsePep508Dep(dep) {
|
|
395
|
+
const trimmed = dep.trim();
|
|
396
|
+
const nameMatch = /^[\w.-]+/.exec(trimmed);
|
|
397
|
+
if (nameMatch) {
|
|
398
|
+
const depVersion = trimmed.slice(nameMatch[0].length).trim();
|
|
399
|
+
return toDependencyLd(nameMatch[0], depVersion.length > 0 ? depVersion : void 0);
|
|
400
|
+
}
|
|
401
|
+
return toDependencyLd(trimmed);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Extract URL from package.json repository field (string or {url}).
|
|
405
|
+
*/
|
|
406
|
+
function repositoryUrlFromPackageJson(repository) {
|
|
407
|
+
if (repository === void 0) return void 0;
|
|
408
|
+
if (typeof repository === "string") return repository;
|
|
409
|
+
return repository.url;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Extract URL from package.json bugs field.
|
|
413
|
+
*/
|
|
414
|
+
function bugsUrlFromPackageJson(bugs) {
|
|
415
|
+
if (bugs === void 0) return void 0;
|
|
416
|
+
return bugs.url;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Extract the first license name from a POM record.
|
|
420
|
+
*/
|
|
421
|
+
function firstPomLicense(pom) {
|
|
422
|
+
const pomLicense = pom?.data.licenses[0];
|
|
423
|
+
return pomLicense?.name ?? pomLicense?.url;
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Resolve Python pyproject.toml license field to a string.
|
|
427
|
+
* Can be a string (SPDX ID) or `{ spdx?: string; text?: string; file?: string }`.
|
|
428
|
+
*/
|
|
429
|
+
function resolvePythonLicense(pythonLicense) {
|
|
430
|
+
if (pythonLicense === void 0) return void 0;
|
|
431
|
+
if (typeof pythonLicense === "string") return pythonLicense;
|
|
432
|
+
return pythonLicense.spdx ?? pythonLicense.text;
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Resolve codemeta license field (string or string[]) to first string.
|
|
436
|
+
*/
|
|
437
|
+
function resolveCmLicense(cmLicense) {
|
|
438
|
+
if (cmLicense === void 0) return void 0;
|
|
439
|
+
return Array.isArray(cmLicense) ? cmLicense[0] : cmLicense;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Deduplicate strings case-insensitively, preserving first occurrence casing.
|
|
443
|
+
*/
|
|
444
|
+
function deduplicateStrings(strings) {
|
|
445
|
+
const seen = /* @__PURE__ */ new Map();
|
|
446
|
+
for (const s of strings) {
|
|
447
|
+
const key = s.toLowerCase().trim();
|
|
448
|
+
if (key.length > 0 && !seen.has(key)) seen.set(key, s);
|
|
449
|
+
}
|
|
450
|
+
return [...seen.values()];
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Case-insensitive lookup in a string record (e.g. pyproject.toml `[project.urls]`).
|
|
454
|
+
*/
|
|
455
|
+
function caseInsensitiveLookup(record, key) {
|
|
456
|
+
if (record === void 0) return void 0;
|
|
457
|
+
const lowerKey = key.toLowerCase();
|
|
458
|
+
for (const [k, v] of Object.entries(record)) if (k.toLowerCase() === lowerKey) return v;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Strip the `#readme` fragment that npm's normalize-package-data appends to
|
|
462
|
+
* homepage URLs derived from repository URLs.
|
|
463
|
+
*/
|
|
464
|
+
function stripReadmeFragment(url) {
|
|
465
|
+
if (url === void 0) return void 0;
|
|
466
|
+
return url.endsWith("#readme") ? url.slice(0, -7) : url;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Truncate an ISO 8601 date-time to just the date portion (YYYY-MM-DD).
|
|
470
|
+
* CodeMeta dates are `schema:Date`, not `schema:DateTime`.
|
|
471
|
+
*/
|
|
472
|
+
function toDateOnly(value) {
|
|
473
|
+
if (value === void 0) return void 0;
|
|
474
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) return value;
|
|
475
|
+
const match = /^(\d{4}-\d{2}-\d{2})T/.exec(value);
|
|
476
|
+
if (match) return match[1];
|
|
477
|
+
return value;
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Build a URL for the project's README.
|
|
481
|
+
* Prefers a web URL on the remote service (e.g. GitHub blob link) when a
|
|
482
|
+
* code repository URL is available, otherwise falls back to the local source path.
|
|
483
|
+
*/
|
|
484
|
+
function readmeUrl(readmeRecord, repoUrl, defaultBranch, basePath) {
|
|
485
|
+
if (readmeRecord === void 0) return void 0;
|
|
486
|
+
const repoRelativePath = basePath === void 0 ? basename(readmeRecord.source) : relative(basePath, readmeRecord.source).replaceAll("\\", "/");
|
|
487
|
+
if (is.nonEmptyStringAndNotWhitespace(repoUrl) && repoUrl.includes("github.com")) {
|
|
488
|
+
const branch = defaultBranch ?? "main";
|
|
489
|
+
return `${repoUrl.replace(/\.git$/, "")}/blob/${branch}/${repoRelativePath}`;
|
|
490
|
+
}
|
|
491
|
+
return repoRelativePath;
|
|
492
|
+
}
|
|
493
|
+
//#endregion
|
|
494
|
+
export { codemeta };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Template } from "../metadata-types.js";
|
|
2
|
+
//#region src/lib/templates/frontmatter.d.ts
|
|
3
|
+
type TemplateDataFrontmatter = ReturnType<typeof frontmatter>;
|
|
4
|
+
/**
|
|
5
|
+
* A compact, non-nested, polyglot overview of the project.
|
|
6
|
+
* Designed for Obsidian frontmatter — flat keys with natural language names,
|
|
7
|
+
* blending all available sources into a single trackable snapshot.
|
|
8
|
+
*/
|
|
9
|
+
declare const frontmatter: Template<{
|
|
10
|
+
Name: string | null;
|
|
11
|
+
ID: string | null;
|
|
12
|
+
Description: string | null;
|
|
13
|
+
Author: string[] | null;
|
|
14
|
+
Contributor: string[] | null;
|
|
15
|
+
Maintainer: string[] | null;
|
|
16
|
+
Version: string | null;
|
|
17
|
+
Account: string | null;
|
|
18
|
+
Public: boolean;
|
|
19
|
+
Fork: boolean;
|
|
20
|
+
Published: boolean;
|
|
21
|
+
Status: "unknown" | "maintainer" | "author" | "observer";
|
|
22
|
+
Tags: string[] | null;
|
|
23
|
+
Aliases: (string | null | undefined)[] | null;
|
|
24
|
+
License: string[] | null;
|
|
25
|
+
Language: string[] | null;
|
|
26
|
+
'Secondary Language': string[] | null;
|
|
27
|
+
'Repo Path': string | null;
|
|
28
|
+
'VS Code Path': string | null;
|
|
29
|
+
'Readme Path': string | null;
|
|
30
|
+
'Homepage URL': string | null;
|
|
31
|
+
'Repo URL': string | null;
|
|
32
|
+
'Issues URL': string | null;
|
|
33
|
+
'Readme URL': string | null;
|
|
34
|
+
'Package URL': string | null;
|
|
35
|
+
Created: string | null;
|
|
36
|
+
'First Commit Date': string | null;
|
|
37
|
+
'Latest Commit Date': string | null;
|
|
38
|
+
'Latest Push Date': string | null;
|
|
39
|
+
'Latest Release Date': string | null;
|
|
40
|
+
'Latest Release Version': string | null;
|
|
41
|
+
Stars: number | null;
|
|
42
|
+
Watchers: number | null;
|
|
43
|
+
Contributors: number | null;
|
|
44
|
+
Forks: number | null;
|
|
45
|
+
'Downloads Total': number | null;
|
|
46
|
+
'Downloads Monthly': number | null;
|
|
47
|
+
Releases: number | null;
|
|
48
|
+
'Issues Open': number | null;
|
|
49
|
+
'Issues Closed': number | null;
|
|
50
|
+
'PRs Open': number | null;
|
|
51
|
+
'PRs Merged': number | null;
|
|
52
|
+
'PRs Closed': number | null;
|
|
53
|
+
'Vulnerability Alerts': number | null;
|
|
54
|
+
'Lines of Code': number | null;
|
|
55
|
+
'Total Files': number | null;
|
|
56
|
+
'Total Size MB': number | null;
|
|
57
|
+
'Tracked Files': number | null;
|
|
58
|
+
'Tracked Size MB': number | null;
|
|
59
|
+
'GitHub Size MB': number | null;
|
|
60
|
+
Dependencies: string[] | null;
|
|
61
|
+
'Dev Dependencies': string[] | null;
|
|
62
|
+
'Major Updates': number;
|
|
63
|
+
'Minor Updates': number;
|
|
64
|
+
'Patch Updates': number;
|
|
65
|
+
'Total Updates': number;
|
|
66
|
+
Libyears: number;
|
|
67
|
+
Runtime: string[] | null;
|
|
68
|
+
'Operating System': string[] | null;
|
|
69
|
+
'Forked From': string | null;
|
|
70
|
+
'Fork Ahead': number | null;
|
|
71
|
+
'Fork Behind': number | null;
|
|
72
|
+
'Template From': string | null;
|
|
73
|
+
Organization: boolean;
|
|
74
|
+
Monorepo: boolean;
|
|
75
|
+
'Git Commits': number | null;
|
|
76
|
+
'Git Dirty Files': number | null;
|
|
77
|
+
'Git Remotes Ahead': number | null;
|
|
78
|
+
'Git Remotes Behind': number | null;
|
|
79
|
+
'Git LFS': boolean;
|
|
80
|
+
'Git Tags': number | null;
|
|
81
|
+
'Git Current Branch': string | null;
|
|
82
|
+
'Git Branches': number | null;
|
|
83
|
+
'Git Remotes': number | null;
|
|
84
|
+
'Git Submodules': number;
|
|
85
|
+
}>;
|
|
86
|
+
//#endregion
|
|
87
|
+
export { TemplateDataFrontmatter };
|