champollion 0.3.3
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/LICENSE +133 -0
- package/README.md +387 -0
- package/bin/cli.js +278 -0
- package/index.js +135 -0
- package/lib/api-key.js +127 -0
- package/lib/autofix.js +432 -0
- package/lib/bridge/method_bridge.py +430 -0
- package/lib/card-source-resolution.mjs +284 -0
- package/lib/cards/cache.js +169 -0
- package/lib/cards/env.js +82 -0
- package/lib/cards/fetch-card-child.js +38 -0
- package/lib/cards/reader.js +435 -0
- package/lib/cards/refresh.js +111 -0
- package/lib/cards/remote.js +387 -0
- package/lib/cldf-export.mjs +540 -0
- package/lib/cldf-terms.mjs +62 -0
- package/lib/command-help.js +790 -0
- package/lib/commands/audit.js +49 -0
- package/lib/commands/card.js +454 -0
- package/lib/commands/doctor.js +559 -0
- package/lib/commands/fonts.js +489 -0
- package/lib/commands/help.js +91 -0
- package/lib/commands/init.js +1259 -0
- package/lib/commands/integrity.js +148 -0
- package/lib/commands/leaderboard.js +478 -0
- package/lib/commands/lint.js +30 -0
- package/lib/commands/models.js +177 -0
- package/lib/commands/plugin.js +103 -0
- package/lib/commands/provenance.js +45 -0
- package/lib/commands/recommend.js +75 -0
- package/lib/commands/register-corpus.js +678 -0
- package/lib/commands/repair-script.js +42 -0
- package/lib/commands/seal-corpus.js +355 -0
- package/lib/commands/seo.js +72 -0
- package/lib/commands/serve.js +147 -0
- package/lib/commands/status.js +265 -0
- package/lib/commands/submit.js +332 -0
- package/lib/commands/sync.js +89 -0
- package/lib/commands/tm.js +573 -0
- package/lib/commands/verify.js +39 -0
- package/lib/commands/watch.js +20 -0
- package/lib/commands/wrap.js +138 -0
- package/lib/commands/xliff.js +327 -0
- package/lib/commercial-eligibility.js +235 -0
- package/lib/concurrent.js +87 -0
- package/lib/config.js +523 -0
- package/lib/contamination-lane.js +76 -0
- package/lib/content-sync.js +731 -0
- package/lib/content.js +733 -0
- package/lib/corpus-registration.mjs +608 -0
- package/lib/cost-report.js +346 -0
- package/lib/diff.js +155 -0
- package/lib/docusaurus-sync.js +1256 -0
- package/lib/flatten.js +55 -0
- package/lib/format.js +954 -0
- package/lib/hash.js +159 -0
- package/lib/icu.js +473 -0
- package/lib/integrity.js +689 -0
- package/lib/license-gate.mjs +478 -0
- package/lib/license-identify.mjs +229 -0
- package/lib/lint.js +629 -0
- package/lib/method-manifest.js +60 -0
- package/lib/methods/anthropic.js +140 -0
- package/lib/methods/apertium.js +163 -0
- package/lib/methods/api.js +316 -0
- package/lib/methods/base.js +184 -0
- package/lib/methods/content-separator.js +45 -0
- package/lib/methods/deepl.js +426 -0
- package/lib/methods/direct-llm.js +586 -0
- package/lib/methods/external.js +332 -0
- package/lib/methods/fetch-with-retry.js +124 -0
- package/lib/methods/gemini.js +147 -0
- package/lib/methods/google-translate.js +402 -0
- package/lib/methods/http-utils.js +122 -0
- package/lib/methods/libretranslate.js +314 -0
- package/lib/methods/llm-coached.js +670 -0
- package/lib/methods/llm.js +592 -0
- package/lib/methods/local.js +76 -0
- package/lib/methods/microsoft-translator.js +331 -0
- package/lib/methods/openai.js +131 -0
- package/lib/methods/openrouter-client.js +327 -0
- package/lib/methods/openrouter-pricing.js +156 -0
- package/lib/methods/provider-env.js +115 -0
- package/lib/methods/provider-pricing.js +310 -0
- package/lib/methods/tilde.js +150 -0
- package/lib/methods/translated.js +229 -0
- package/lib/methods/translation-error.js +80 -0
- package/lib/models.js +258 -0
- package/lib/no-translate.js +233 -0
- package/lib/output.js +238 -0
- package/lib/pairs.js +547 -0
- package/lib/plugins.js +447 -0
- package/lib/provenance.js +323 -0
- package/lib/recommend.js +648 -0
- package/lib/registers.js +1185 -0
- package/lib/repair-script.js +266 -0
- package/lib/scripts.js +994 -0
- package/lib/seal.mjs +464 -0
- package/lib/sealed-qualifier.mjs +211 -0
- package/lib/security.js +59 -0
- package/lib/segment.js +369 -0
- package/lib/seo.js +275 -0
- package/lib/serve.js +854 -0
- package/lib/string-classify.js +85 -0
- package/lib/submit.mjs +344 -0
- package/lib/sync.js +969 -0
- package/lib/tags/bcp47.js +202 -0
- package/lib/tags/resolve.js +314 -0
- package/lib/terminology.js +111 -0
- package/lib/tm-seed.js +294 -0
- package/lib/tm.js +515 -0
- package/lib/translate-pair.js +197 -0
- package/lib/translate.js +203 -0
- package/lib/types.js +230 -0
- package/lib/validate.js +510 -0
- package/lib/verify.js +451 -0
- package/lib/watch.js +145 -0
- package/lib/xliff.js +184 -0
- package/package.json +93 -0
- package/shared/ATTRIBUTION.md +145 -0
- package/shared/CORPORA-CARDS.md +288 -0
- package/shared/DATA-SOVEREIGNTY.md +500 -0
- package/shared/LANGUAGE-CARD-FIELDS.md +532 -0
- package/shared/card-lint-baseline.json +3189 -0
- package/shared/cards-fallback.json +1 -0
- package/shared/catalogue/card-config.json +6091 -0
- package/shared/catalogue/external-results.json +3888 -0
- package/shared/catalogue/gender-guidance.json +1038 -0
- package/shared/catalogue/method-coverage.json +1751 -0
- package/shared/catalogue/metric-coverage.json +170 -0
- package/shared/catalogue/metric-reliability.json +1 -0
- package/shared/catalogue/register-presets.json +3180 -0
- package/shared/catalogue/vitality-scales.json +55 -0
- package/shared/cldr-index.json +1115 -0
- package/shared/code-bridge.json +253 -0
- package/shared/corpora-cards-v1-reference.md +281 -0
- package/shared/curated-dictionary-flags.json +35 -0
- package/shared/curated-endonyms.json +35 -0
- package/shared/curated-fsts.json +51 -0
- package/shared/curated-orthography-conventions.json +26 -0
- package/shared/curated-sil-resources.json +374 -0
- package/shared/curated-tools.json +41 -0
- package/shared/docent/corpus.json +11333 -0
- package/shared/docent/faq.en.json +564 -0
- package/shared/docent/register-blocks.json +60 -0
- package/shared/docent/system-prompt.md +144 -0
- package/shared/domain-taxonomy.json +35 -0
- package/shared/explainers/glossary.json +2975 -0
- package/shared/explainers/tc-features.json +20112 -0
- package/shared/explainers/term-watchlist.json +147 -0
- package/shared/human-services.json +59 -0
- package/shared/license-corrections.json +261 -0
- package/shared/license-evidence.json +13452 -0
- package/shared/licenses.json +6781 -0
- package/shared/method-registry.json +236 -0
- package/shared/metric-registry.json +620 -0
- package/shared/model-aliases.json +7 -0
- package/shared/schemas/champollion-plugin.schema.json +206 -0
- package/shared/schemas/corpora-card.schema.json +957 -0
- package/shared/schemas/domain-taxonomy.schema.json +64 -0
- package/shared/schemas/external-results.schema.json +314 -0
- package/shared/schemas/human-services.schema.json +90 -0
- package/shared/schemas/language-card.schema.json +1308 -0
- package/shared/schemas/licenses.schema.json +155 -0
- package/shared/schemas/method-card.schema.json +412 -0
- package/shared/schemas/method-registry.schema.json +85 -0
- package/shared/schemas/metric-registry.schema.json +96 -0
- package/shared/schemas/metric-reliability.schema.json +178 -0
- package/shared/schemas/model-aliases.schema.json +27 -0
- package/shared/schemas/source-snapshot.schema.json +96 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* license-identify.mjs — turn a raw upstream licence string into an SPDX id,
|
|
3
|
+
* or REFUSE.
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS EXISTS
|
|
6
|
+
* It replaces `toSpdx()` in cli/scripts/populate-licenses.mjs, which wrote
|
|
7
|
+
* 212 of the register's 333 entries. That function was an ordered chain of
|
|
8
|
+
* `String.includes()` tests, and it failed in three ways at once:
|
|
9
|
+
*
|
|
10
|
+
* 1. VERSION FABRICATION. `if (s.includes('by-nc')) return 'CC-BY-NC-4.0'`
|
|
11
|
+
* stamps 4.0 on every BY-NC licence of any version. `nts` and
|
|
12
|
+
* `uclaphoneticslabarchive` are licensed BY-NC-2.0 and were recorded as
|
|
13
|
+
* 4.0 — with the correct URL sitting in the adjacent license_url column.
|
|
14
|
+
*
|
|
15
|
+
* 2. CLAUSE LOSS. There was no `-nd` branch anywhere. A ND licence hit the
|
|
16
|
+
* `by-nc` or `by` test first and came out as CC-BY-NC-4.0 or CC-BY-4.0.
|
|
17
|
+
* Zenodo says `nts` is cc-by-nc-**nd**-2.0; the register says
|
|
18
|
+
* CC-BY-NC-4.0 with allows_redistribution = 1. NoDerivatives vanished
|
|
19
|
+
* because nothing looked for it.
|
|
20
|
+
*
|
|
21
|
+
* 3. RAW PASSTHROUGH. `return raw` shipped unparsed strings as SPDX ids —
|
|
22
|
+
* which is how `hayniecolorterms` carries the literal `"CC"`.
|
|
23
|
+
*
|
|
24
|
+
* The fix is not a longer chain of guesses. It is a parser that reads the
|
|
25
|
+
* version and the clauses out of the string, and returns null when it cannot
|
|
26
|
+
* read them with certainty. A null becomes UNVERIFIED, which quarantines the
|
|
27
|
+
* claim (founder ruling 2026-08-01) rather than inventing a permissive one.
|
|
28
|
+
*
|
|
29
|
+
* THE RULE: never emit an SPDX id containing information the input did not
|
|
30
|
+
* contain. If the input has no version, the output has no version — and an
|
|
31
|
+
* unversioned CC licence is not identifiable, so it is refused.
|
|
32
|
+
*
|
|
33
|
+
* @see cli/scripts/harvest-zenodo-cldf.mjs (authoritative licence evidence)
|
|
34
|
+
* @see docs/LICENSING.md
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/** Canonical SPDX clause order for Creative Commons: BY, NC, ND, SA. */
|
|
38
|
+
const CC_CLAUSE_ORDER = ['by', 'nc', 'nd', 'sa'];
|
|
39
|
+
|
|
40
|
+
/** CC versions that actually exist as SPDX identifiers. */
|
|
41
|
+
const CC_VERSIONS = new Set(['1.0', '2.0', '2.5', '3.0', '4.0']);
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Non-CC licences we accept, keyed by the exact lowercased token. Explicit,
|
|
45
|
+
* because "contains 'mit'" matches "transmitted", "limits" and "submitted" —
|
|
46
|
+
* substring matching on short identifiers is how the old function justified
|
|
47
|
+
* itself and how it went wrong.
|
|
48
|
+
*/
|
|
49
|
+
const EXACT_IDS = new Map(Object.entries({
|
|
50
|
+
'mit': 'MIT',
|
|
51
|
+
'apache-2.0': 'Apache-2.0',
|
|
52
|
+
'apache 2.0': 'Apache-2.0',
|
|
53
|
+
'apache2.0': 'Apache-2.0',
|
|
54
|
+
'apache license 2.0': 'Apache-2.0',
|
|
55
|
+
'gpl-3.0': 'GPL-3.0-only',
|
|
56
|
+
'gpl-3.0-only': 'GPL-3.0-only',
|
|
57
|
+
'gpl-3.0-or-later': 'GPL-3.0-or-later',
|
|
58
|
+
'gpl-3': 'GPL-3.0-only',
|
|
59
|
+
'gpl3': 'GPL-3.0-only',
|
|
60
|
+
'agpl-3.0': 'AGPL-3.0-only',
|
|
61
|
+
'agpl-3.0-only': 'AGPL-3.0-only',
|
|
62
|
+
'agpl-3.0-or-later': 'AGPL-3.0-or-later',
|
|
63
|
+
'lgpl-3.0': 'LGPL-3.0-only',
|
|
64
|
+
'bsd-3-clause': 'BSD-3-Clause',
|
|
65
|
+
'bsd-2-clause': 'BSD-2-Clause',
|
|
66
|
+
'cc0-1.0': 'CC0-1.0',
|
|
67
|
+
'cc0': 'CC0-1.0',
|
|
68
|
+
'unicode-3.0': 'Unicode-3.0',
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
/** URL forms that identify a licence exactly. */
|
|
72
|
+
const EXACT_URLS = [
|
|
73
|
+
[/^https?:\/\/(www\.)?apache\.org\/licenses\/LICENSE-2\.0/i, 'Apache-2.0'],
|
|
74
|
+
[/^https?:\/\/(www\.)?opensource\.org\/licenses\/MIT\b/i, 'MIT'],
|
|
75
|
+
[/^https?:\/\/(www\.)?opensource\.org\/licenses\/GPL-3\.0\b/i, 'GPL-3.0-only'],
|
|
76
|
+
[/^https?:\/\/(www\.)?gnu\.org\/licenses\/gpl-3\.0/i, 'GPL-3.0-only'],
|
|
77
|
+
[/^https?:\/\/(www\.)?gnu\.org\/licenses\/agpl-3\.0/i, 'AGPL-3.0-only'],
|
|
78
|
+
[/creativecommons\.org\/publicdomain\/zero\/1\.0/i, 'CC0-1.0'],
|
|
79
|
+
];
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Identify a licence string.
|
|
83
|
+
*
|
|
84
|
+
* @param {unknown} raw the upstream string (dc:license, a LICENSE header, …)
|
|
85
|
+
* @returns {{spdx: string|null, reason: string, raw: string|null}}
|
|
86
|
+
* `spdx` is null whenever the string cannot be identified exactly; `reason`
|
|
87
|
+
* always explains the outcome so a reviewer can see WHY something is
|
|
88
|
+
* UNVERIFIED without re-deriving it.
|
|
89
|
+
*/
|
|
90
|
+
export function identifyLicense(raw) {
|
|
91
|
+
if (raw == null || raw === '') {
|
|
92
|
+
return { spdx: null, reason: 'no licence string present', raw: null };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// CLDF metadata sometimes carries an object: {url, name, icon}.
|
|
96
|
+
if (typeof raw === 'object') {
|
|
97
|
+
const url = raw.url || raw.href || null;
|
|
98
|
+
if (!url) {
|
|
99
|
+
return { spdx: null, reason: 'licence object with no url', raw: JSON.stringify(raw) };
|
|
100
|
+
}
|
|
101
|
+
const inner = identifyLicense(url);
|
|
102
|
+
return { ...inner, raw: JSON.stringify(raw) };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const text = String(raw).trim();
|
|
106
|
+
const s = text.toLowerCase();
|
|
107
|
+
|
|
108
|
+
for (const [re, spdx] of EXACT_URLS) {
|
|
109
|
+
if (re.test(text)) return { spdx, reason: 'exact URL match', raw: text };
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Creative Commons DEED TITLE, as it appears at the top of a LICENSE file
|
|
113
|
+
// shipped by the dataset itself: "Attribution-ShareAlike 4.0 International".
|
|
114
|
+
// This is an exact form, not a resemblance — the clause words and the version
|
|
115
|
+
// are both read from the title. It is how cli/data/segbo/LICENSE.txt resolves,
|
|
116
|
+
// the file whose existence the register denies ("No LICENSE file found in
|
|
117
|
+
// GitHub repo") while it sits in the tree.
|
|
118
|
+
const deed = /\b(Attribution(?:-(?:NonCommercial|ShareAlike|NoDerivatives|NoDerivs))*)\s+(\d(?:\.\d)?)\s+International/i.exec(text);
|
|
119
|
+
if (deed) {
|
|
120
|
+
const words = deed[1].toLowerCase().split('-');
|
|
121
|
+
const map = {
|
|
122
|
+
attribution: 'by', noncommercial: 'nc',
|
|
123
|
+
sharealike: 'sa', noderivatives: 'nd', noderivs: 'nd',
|
|
124
|
+
};
|
|
125
|
+
const clauses = words.map((w) => map[w]).filter(Boolean);
|
|
126
|
+
let version = deed[2];
|
|
127
|
+
if (!version.includes('.')) version = `${version}.0`;
|
|
128
|
+
if (clauses.length === words.length && CC_VERSIONS.has(version)) {
|
|
129
|
+
const ordered = CC_CLAUSE_ORDER.filter((c) => clauses.includes(c));
|
|
130
|
+
return {
|
|
131
|
+
spdx: `CC-${ordered.map((c) => c.toUpperCase()).join('-')}-${version}`,
|
|
132
|
+
reason: 'exact Creative Commons deed title',
|
|
133
|
+
raw: text.slice(0, 120),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (/^\s*CC0\s+1\.0\s+Universal/im.test(text)) {
|
|
138
|
+
return { spdx: 'CC0-1.0', reason: 'exact CC0 deed title', raw: text.slice(0, 120) };
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (EXACT_IDS.has(s)) {
|
|
142
|
+
return { spdx: EXACT_IDS.get(s), reason: 'exact identifier match', raw: text };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Creative Commons: read the clauses AND the version out of the string.
|
|
146
|
+
// Both a URL (creativecommons.org/licenses/by-nc-sa/3.0/) and a bare id
|
|
147
|
+
// (cc-by-nc-sa-3.0) are handled by the same extraction, so neither can
|
|
148
|
+
// produce a version the input did not state.
|
|
149
|
+
const ccUrl = /creativecommons\.org\/licenses\/([a-z-]+)\/(\d(?:\.\d)?)/i.exec(text);
|
|
150
|
+
const ccId = /^cc-((?:by|nc|nd|sa)(?:-(?:by|nc|nd|sa))*)-(\d(?:\.\d)?)$/i.exec(s);
|
|
151
|
+
const m = ccUrl || ccId;
|
|
152
|
+
if (m) {
|
|
153
|
+
const clauses = m[1].toLowerCase().split('-').filter(Boolean);
|
|
154
|
+
let version = m[2];
|
|
155
|
+
if (!version.includes('.')) version = `${version}.0`;
|
|
156
|
+
|
|
157
|
+
if (!CC_VERSIONS.has(version)) {
|
|
158
|
+
return { spdx: null, reason: `CC version ${version} is not a known SPDX version`, raw: text };
|
|
159
|
+
}
|
|
160
|
+
const unknown = clauses.filter((c) => !CC_CLAUSE_ORDER.includes(c));
|
|
161
|
+
if (unknown.length) {
|
|
162
|
+
return { spdx: null, reason: `unrecognised CC clause(s): ${unknown.join(', ')}`, raw: text };
|
|
163
|
+
}
|
|
164
|
+
if (!clauses.includes('by')) {
|
|
165
|
+
// CC licences without BY exist only in 1.0. Refuse rather than assume.
|
|
166
|
+
return { spdx: null, reason: 'CC licence without a BY clause — needs review', raw: text };
|
|
167
|
+
}
|
|
168
|
+
const ordered = CC_CLAUSE_ORDER.filter((c) => clauses.includes(c));
|
|
169
|
+
return {
|
|
170
|
+
spdx: `CC-${ordered.map((c) => c.toUpperCase()).join('-')}-${version}`,
|
|
171
|
+
reason: 'parsed CC clauses and version from the string',
|
|
172
|
+
raw: text,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// A CC licence we can see but cannot version. This is the `hayniecolorterms`
|
|
177
|
+
// case: the metadata says only "CC". It grants nothing determinable, and the
|
|
178
|
+
// old function shipped the raw string as an SPDX id.
|
|
179
|
+
if (/\bcc\b|creativecommons/i.test(s)) {
|
|
180
|
+
return {
|
|
181
|
+
spdx: null,
|
|
182
|
+
reason: 'Creative Commons licence with no identifiable version — grants nothing determinable',
|
|
183
|
+
raw: text,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return { spdx: null, reason: 'unrecognised licence string', raw: text };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Derive obligation flags from an SPDX id.
|
|
192
|
+
*
|
|
193
|
+
* Structural, not heuristic: every flag reads a clause that is actually present
|
|
194
|
+
* in the identifier. The old `licenseFlags()` set
|
|
195
|
+
* `redistribution: !s.includes('PROPRIETARY')` — i.e. everything on earth was
|
|
196
|
+
* redistributable unless the string happened to contain that one word. Nothing
|
|
197
|
+
* upstream ever says "PROPRIETARY", so the flag was effectively a constant.
|
|
198
|
+
*
|
|
199
|
+
* `noDerivatives` is NEW. The register had no field for it, which is why ND
|
|
200
|
+
* silently vanished from `nts`: there was nowhere to record it even if the
|
|
201
|
+
* parser had seen it.
|
|
202
|
+
*
|
|
203
|
+
* @param {string|null} spdx
|
|
204
|
+
* @returns {{redistribution: boolean|null, attribution: boolean, sharealike: boolean,
|
|
205
|
+
* nonCommercial: boolean, noDerivatives: boolean}}
|
|
206
|
+
*/
|
|
207
|
+
export function deriveFlags(spdx) {
|
|
208
|
+
if (!spdx) {
|
|
209
|
+
// UNVERIFIED grants nothing. `redistribution: null` is "unknown", which is
|
|
210
|
+
// NOT the same as false and must not read as a permission either way.
|
|
211
|
+
return {
|
|
212
|
+
redistribution: null, attribution: false, sharealike: false,
|
|
213
|
+
nonCommercial: false, noDerivatives: false,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
const s = spdx.toUpperCase();
|
|
217
|
+
const nd = /-ND(-|$)/.test(s);
|
|
218
|
+
return {
|
|
219
|
+
// ND permits verbatim redistribution but forbids distributing derivatives.
|
|
220
|
+
// For a project whose whole output is derived data, treating an ND source
|
|
221
|
+
// as redistributable is the error we are removing, so this is false.
|
|
222
|
+
redistribution: !nd,
|
|
223
|
+
attribution: s.startsWith('CC-BY') || s.startsWith('APACHE')
|
|
224
|
+
|| s === 'MIT' || s.startsWith('BSD'),
|
|
225
|
+
sharealike: /-SA(-|$)/.test(s) || s.includes('GPL'),
|
|
226
|
+
nonCommercial: /-NC(-|$)/.test(s),
|
|
227
|
+
noDerivatives: nd,
|
|
228
|
+
};
|
|
229
|
+
}
|