@extenshi/cli 0.23.1 → 0.25.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/README.md +1 -1
- package/dist/amo-source.d.ts +88 -17
- package/dist/amo-source.d.ts.map +1 -1
- package/dist/amo-source.js +442 -116
- package/dist/amo-source.js.map +1 -1
- package/dist/amowebstore-md.d.ts +26 -0
- package/dist/amowebstore-md.d.ts.map +1 -1
- package/dist/amowebstore-md.js +32 -3
- package/dist/amowebstore-md.js.map +1 -1
- package/dist/auto-update.d.ts +46 -3
- package/dist/auto-update.d.ts.map +1 -1
- package/dist/auto-update.js +94 -19
- package/dist/auto-update.js.map +1 -1
- package/dist/chromewebstore-md.d.ts +7 -0
- package/dist/chromewebstore-md.d.ts.map +1 -1
- package/dist/chromewebstore-md.js +20 -3
- package/dist/chromewebstore-md.js.map +1 -1
- package/dist/cli.js +73 -20
- package/dist/cli.js.map +1 -1
- package/dist/compliance-review.d.ts +5 -1
- package/dist/compliance-review.d.ts.map +1 -1
- package/dist/compliance-review.js +10 -5
- package/dist/compliance-review.js.map +1 -1
- package/dist/cws-policies.d.ts.map +1 -1
- package/dist/cws-policies.js +4 -0
- package/dist/cws-policies.js.map +1 -1
- package/dist/edgewebstore-md.d.ts +14 -0
- package/dist/edgewebstore-md.d.ts.map +1 -1
- package/dist/edgewebstore-md.js +20 -5
- package/dist/edgewebstore-md.js.map +1 -1
- package/dist/evidence-ingest.d.ts +67 -5
- package/dist/evidence-ingest.d.ts.map +1 -1
- package/dist/evidence-ingest.js +146 -21
- package/dist/evidence-ingest.js.map +1 -1
- package/dist/generate-listing.d.ts +18 -6
- package/dist/generate-listing.d.ts.map +1 -1
- package/dist/generate-listing.js +62 -19
- package/dist/generate-listing.js.map +1 -1
- package/dist/json-ld.d.ts +43 -5
- package/dist/json-ld.d.ts.map +1 -1
- package/dist/json-ld.js +53 -1
- package/dist/json-ld.js.map +1 -1
- package/dist/landing-sections.d.ts +21 -3
- package/dist/landing-sections.d.ts.map +1 -1
- package/dist/landing-sections.js +63 -17
- package/dist/landing-sections.js.map +1 -1
- package/dist/listing-checks.d.ts +15 -9
- package/dist/listing-checks.d.ts.map +1 -1
- package/dist/listing-checks.js +54 -46
- package/dist/listing-checks.js.map +1 -1
- package/dist/listing-data-flows.d.ts +140 -0
- package/dist/listing-data-flows.d.ts.map +1 -0
- package/dist/listing-data-flows.js +454 -0
- package/dist/listing-data-flows.js.map +1 -0
- package/dist/listing.d.ts +48 -0
- package/dist/listing.d.ts.map +1 -1
- package/dist/listing.js +201 -23
- package/dist/listing.js.map +1 -1
- package/dist/localize-parity.d.ts +26 -0
- package/dist/localize-parity.d.ts.map +1 -0
- package/dist/localize-parity.js +227 -0
- package/dist/localize-parity.js.map +1 -0
- package/dist/localize.d.ts +6 -0
- package/dist/localize.d.ts.map +1 -1
- package/dist/localize.js +4 -4
- package/dist/localize.js.map +1 -1
- package/dist/media.d.ts.map +1 -1
- package/dist/media.js +1 -2
- package/dist/media.js.map +1 -1
- package/dist/package.d.ts +13 -0
- package/dist/package.d.ts.map +1 -1
- package/dist/package.js +1 -1
- package/dist/package.js.map +1 -1
- package/dist/page.d.ts +16 -0
- package/dist/page.d.ts.map +1 -1
- package/dist/page.js +49 -4
- package/dist/page.js.map +1 -1
- package/dist/permission-justifications.d.ts +19 -1
- package/dist/permission-justifications.d.ts.map +1 -1
- package/dist/permission-justifications.js +129 -0
- package/dist/permission-justifications.js.map +1 -1
- package/dist/png.d.ts +40 -0
- package/dist/png.d.ts.map +1 -0
- package/dist/png.js +266 -0
- package/dist/png.js.map +1 -0
- package/dist/review-checks.d.ts +54 -13
- package/dist/review-checks.d.ts.map +1 -1
- package/dist/review-checks.js +367 -56
- package/dist/review-checks.js.map +1 -1
- package/dist/review-risk.d.ts +8 -3
- package/dist/review-risk.d.ts.map +1 -1
- package/dist/review-risk.js +14 -4
- package/dist/review-risk.js.map +1 -1
- package/dist/review-stores.d.ts +63 -0
- package/dist/review-stores.d.ts.map +1 -0
- package/dist/review-stores.js +92 -0
- package/dist/review-stores.js.map +1 -0
- package/dist/screenshots-scenes.d.ts +13 -0
- package/dist/screenshots-scenes.d.ts.map +1 -1
- package/dist/screenshots-scenes.js +20 -2
- package/dist/screenshots-scenes.js.map +1 -1
- package/dist/screenshots.d.ts +6 -4
- package/dist/screenshots.d.ts.map +1 -1
- package/dist/screenshots.js +31 -11
- package/dist/screenshots.js.map +1 -1
- package/dist/smoke.d.ts +54 -6
- package/dist/smoke.d.ts.map +1 -1
- package/dist/smoke.js +302 -26
- package/dist/smoke.js.map +1 -1
- package/dist/store-assets.d.ts +20 -3
- package/dist/store-assets.d.ts.map +1 -1
- package/dist/store-assets.js +17 -7
- package/dist/store-assets.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What data the PACKAGE moves, for `extenshi generate-listing` — not only what
|
|
3
|
+
* its permissions allow.
|
|
4
|
+
*
|
|
5
|
+
* `privacyPracticesForManifest` (review-checks.ts) answers "which data types
|
|
6
|
+
* does a permission make you declare". That leaves out everything a package
|
|
7
|
+
* does without a sensitive permission: a bundled payment SDK talking to its
|
|
8
|
+
* API, settings in `storage.sync`, the categories the developer already
|
|
9
|
+
* declared to Firefox. A paid extension holding only `storage` therefore got
|
|
10
|
+
* "no Privacy-practices questions" (DX report 2026-10-10, §2 row 8). This
|
|
11
|
+
* module reads those flows from the package and turns them into the same kind
|
|
12
|
+
* of output: QUESTIONS for the dashboard, with the evidence next to each one —
|
|
13
|
+
* never a verdict written on the developer's behalf.
|
|
14
|
+
*
|
|
15
|
+
* Store rules this module encodes, with their sources:
|
|
16
|
+
* - CWS "Privacy practices": data types are disclosed on the dashboard and
|
|
17
|
+
* must match the privacy policy —
|
|
18
|
+
* https://developer.chrome.com/docs/webstore/cws-dashboard-privacy
|
|
19
|
+
* - CWS user data covers data processed or stored only on the device, web
|
|
20
|
+
* browsing activity includes "the domains or URLs the browser interacts
|
|
21
|
+
* with", account numbers are personally identifiable information, and a
|
|
22
|
+
* product that keeps user data only in `storage.sync` still needs a privacy
|
|
23
|
+
* policy — User Data FAQ #3, #4, #14:
|
|
24
|
+
* https://developer.chrome.com/docs/webstore/program-policies/user-data-faq
|
|
25
|
+
* - CWS Limited Use certification —
|
|
26
|
+
* https://developer.chrome.com/docs/webstore/program-policies/limited-use
|
|
27
|
+
* - Edge: Partner Center's Privacy page has a Data usage section and needs a
|
|
28
|
+
* privacy policy URL once personal information is accessed, transmitted or
|
|
29
|
+
* collected — https://learn.microsoft.com/en-us/microsoft-edge/extensions/publish/publish-extension
|
|
30
|
+
* - AMO: "data transmission" is data handled outside the add-on or the local
|
|
31
|
+
* browser; `required` holds `none` OR categories; `technicalAndInteraction`
|
|
32
|
+
* can only be optional —
|
|
33
|
+
* https://extensionworkshop.com/documentation/develop/firefox-builtin-data-consent/ and
|
|
34
|
+
* https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/browser_specific_settings
|
|
35
|
+
* - AMO: listings must disclose when payment is required to enable any
|
|
36
|
+
* functionality; data from private browsing sessions must not be stored —
|
|
37
|
+
* https://extensionworkshop.com/documentation/publish/add-on-policies/
|
|
38
|
+
*/
|
|
39
|
+
import { detectMinifiedFiles } from './amo-source-detect.js';
|
|
40
|
+
import { readLocaleMessages } from './listing.js';
|
|
41
|
+
import { privacyPracticesForManifest, resolveMessage } from './review-checks.js';
|
|
42
|
+
const CODE_FILE_RE = /\.(?:m?js|cjs|html?)$/i;
|
|
43
|
+
/**
|
|
44
|
+
* The names `extenshi-pay-sdk/rollup.config.js` and
|
|
45
|
+
* `extenshi-storage-sdk/rollup.config.js` pass to their build banner
|
|
46
|
+
* (`/*! <name> v<semver> … commit <sha> · built by \`<cmd>\` *\/`), and the
|
|
47
|
+
* file names a vendored copy usually keeps. Either is enough: a bundler may
|
|
48
|
+
* keep the banner but rename the file, or a hand-vendored copy may lose it.
|
|
49
|
+
*/
|
|
50
|
+
const SDKS = [
|
|
51
|
+
{ kind: 'pay', banner: 'ExtenshiPay SDK', file: /(?:^|\/)extenshi-pay[^/]*\.m?js$/i },
|
|
52
|
+
{ kind: 'storage', banner: 'ExtenshiStorage SDK', file: /(?:^|\/)extenshi-storage[^/]*\.m?js$/i },
|
|
53
|
+
];
|
|
54
|
+
/** A Pay publishable key literal (`pk_ext_` + 32 hex) — the SDK cannot run without one. */
|
|
55
|
+
const PAY_KEY_RE = /\bpk_ext_[0-9a-f]{32}\b/;
|
|
56
|
+
/**
|
|
57
|
+
* Read a build banner of the shape this repo's SDKs emit, in the first ~2 KB:
|
|
58
|
+
* `<name> v<semver>`, then `commit <sha>`, then `built by <command>`. The same
|
|
59
|
+
* three pieces `amo-source-detect.ts` requires for "has provenance".
|
|
60
|
+
*/
|
|
61
|
+
export function parseBuildBanner(content) {
|
|
62
|
+
const head = content.slice(0, 2000);
|
|
63
|
+
const named = /^[\s/*!]*([^\n]{1,80}?)\s+v(\d+\.\d+\.\d+[0-9A-Za-z.+-]*)/m.exec(head);
|
|
64
|
+
if (!named)
|
|
65
|
+
return null;
|
|
66
|
+
const name = named[1].replace(/^[\s/*!]+/, '').trim();
|
|
67
|
+
if (!name)
|
|
68
|
+
return null;
|
|
69
|
+
const rest = head.slice(named.index + named[0].length);
|
|
70
|
+
const commit = /commit\s+([0-9a-f]{7,40})/i.exec(rest)?.[1];
|
|
71
|
+
const built = /built by\s+(?:`([^`]+)`|([^\n*]+?))\s*(?:\*\/|\*|\)|$)/im.exec(rest);
|
|
72
|
+
const buildCommand = (built?.[1] ?? built?.[2])?.trim();
|
|
73
|
+
return { name, version: named[2], ...(commit ? { commit } : {}), ...(buildCommand ? { buildCommand } : {}) };
|
|
74
|
+
}
|
|
75
|
+
function detectSdkBundles(files) {
|
|
76
|
+
const out = [];
|
|
77
|
+
for (const [path, content] of files) {
|
|
78
|
+
if (!/\.(?:m?js|cjs)$/i.test(path))
|
|
79
|
+
continue;
|
|
80
|
+
for (const sdk of SDKS) {
|
|
81
|
+
const at = content.indexOf(`${sdk.banner} v`);
|
|
82
|
+
if (at < 0 && !sdk.file.test(path))
|
|
83
|
+
continue;
|
|
84
|
+
// From the name on: a bundler may inline the banner after other code.
|
|
85
|
+
const banner = at >= 0 ? parseBuildBanner(content.slice(at)) : null;
|
|
86
|
+
out.push({ kind: sdk.kind, path, ...(banner ?? {}) });
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return out.sort((a, b) => a.path.localeCompare(b.path));
|
|
91
|
+
}
|
|
92
|
+
const STORAGE_AREA_RE = /\bstorage\s*\.\s*(sync|local|session|managed)\b/g;
|
|
93
|
+
/**
|
|
94
|
+
* Hosts named in `http(s)://` literals. Namespace URIs (`www.w3.org/2000/svg`),
|
|
95
|
+
* loopback and documentation domains are never requests; everything else is
|
|
96
|
+
* listed as found — a link the user opens and a request that carries data look
|
|
97
|
+
* the same to a static read, so the developer decides which is which.
|
|
98
|
+
*/
|
|
99
|
+
const URL_HOST_RE = /\bhttps?:\/\/([a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+)/gi;
|
|
100
|
+
const NOT_A_DESTINATION_RE = /(?:^|\.)(?:w3\.org|example\.(?:com|org|net))$|^(?:localhost|127\.0\.0\.1|0\.0\.0\.0)$/;
|
|
101
|
+
/** `/*! … *\/` licence/build banners at the top of a bundle name their homepage, not a destination. */
|
|
102
|
+
function withoutLeadingBanner(content) {
|
|
103
|
+
return content.replace(/^\s*\/\*[\s\S]*?\*\//, '');
|
|
104
|
+
}
|
|
105
|
+
function strings(raw) {
|
|
106
|
+
return Array.isArray(raw) ? raw.filter((v) => typeof v === 'string' && v.trim() !== '') : [];
|
|
107
|
+
}
|
|
108
|
+
export function detectDataFlows(manifest, files, opts = {}) {
|
|
109
|
+
const storage = new Map();
|
|
110
|
+
const hosts = new Map();
|
|
111
|
+
const payKeyFiles = [];
|
|
112
|
+
for (const [path, content] of files) {
|
|
113
|
+
if (!CODE_FILE_RE.test(path))
|
|
114
|
+
continue;
|
|
115
|
+
for (const m of content.matchAll(STORAGE_AREA_RE)) {
|
|
116
|
+
const area = m[1];
|
|
117
|
+
storage.set(area, (storage.get(area) ?? new Set()).add(path));
|
|
118
|
+
}
|
|
119
|
+
for (const m of withoutLeadingBanner(content).matchAll(URL_HOST_RE)) {
|
|
120
|
+
const host = m[1].toLowerCase();
|
|
121
|
+
if (NOT_A_DESTINATION_RE.test(host))
|
|
122
|
+
continue;
|
|
123
|
+
hosts.set(host, (hosts.get(host) ?? new Set()).add(path));
|
|
124
|
+
}
|
|
125
|
+
if (PAY_KEY_RE.test(content))
|
|
126
|
+
payKeyFiles.push(path);
|
|
127
|
+
}
|
|
128
|
+
const sdks = detectSdkBundles(files);
|
|
129
|
+
const dcp = manifest.browser_specific_settings?.gecko?.data_collection_permissions;
|
|
130
|
+
const hasPay = sdks.some((s) => s.kind === 'pay') || payKeyFiles.length > 0;
|
|
131
|
+
const order = ['sync', 'local', 'session', 'managed'];
|
|
132
|
+
return {
|
|
133
|
+
sdks,
|
|
134
|
+
payKeyFiles: payKeyFiles.sort(),
|
|
135
|
+
storage: order
|
|
136
|
+
.filter((area) => storage.has(area))
|
|
137
|
+
.map((area) => ({ area, files: [...storage.get(area)].sort() })),
|
|
138
|
+
hosts: [...hosts.entries()]
|
|
139
|
+
.map(([host, where]) => ({ host, files: [...where].sort() }))
|
|
140
|
+
.sort((a, b) => a.host.localeCompare(b.host)),
|
|
141
|
+
firefoxDataCollection: dcp ? { required: strings(dcp.required), optional: strings(dcp.optional) } : null,
|
|
142
|
+
paid: opts.payment ? opts.payment === 'required' : hasPay,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
// ── Formatting helpers ───────────────────────────────────────────────────────
|
|
146
|
+
function fileList(files, max = 3) {
|
|
147
|
+
const shown = files.slice(0, max).map((f) => `\`${f}\``);
|
|
148
|
+
return files.length > max ? `${shown.join(', ')} +${files.length - max} more` : shown.join(', ');
|
|
149
|
+
}
|
|
150
|
+
function sdkLabel(sdk) {
|
|
151
|
+
const name = sdk.name ?? (sdk.kind === 'pay' ? 'ExtenshiPay SDK' : 'ExtenshiStorage SDK');
|
|
152
|
+
return sdk.version ? `${name} v${sdk.version}` : name;
|
|
153
|
+
}
|
|
154
|
+
function paySdk(flows) {
|
|
155
|
+
return flows.sdks.find((s) => s.kind === 'pay');
|
|
156
|
+
}
|
|
157
|
+
/** "ExtenshiPay SDK v0.8.0 (`libs/extenshi-pay.esm.min.js`)", or the key that proves it is wired in. */
|
|
158
|
+
export function payEvidence(flows) {
|
|
159
|
+
const sdk = paySdk(flows);
|
|
160
|
+
if (sdk)
|
|
161
|
+
return `${sdkLabel(sdk)} (\`${sdk.path}\`)`;
|
|
162
|
+
if (flows.payKeyFiles.length > 0)
|
|
163
|
+
return `an ExtenshiPay publishable key (${fileList(flows.payKeyFiles)})`;
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
const PAY_SDK_SENDS = 'https://docs.extenshi.io/developers/pay-sdk#what-the-sdk-sends';
|
|
167
|
+
// ── CWS / Edge "Data usage" ──────────────────────────────────────────────────
|
|
168
|
+
/**
|
|
169
|
+
* Firefox data_collection_permissions category → the Chrome Web Store data type
|
|
170
|
+
* covering the same data. Only categories whose definitions line up one to one
|
|
171
|
+
* (Extension Workshop's taxonomy vs the CWS dashboard list); `searchTerms` and
|
|
172
|
+
* `bookmarksInfo` have no CWS counterpart and are reported as declared instead.
|
|
173
|
+
*/
|
|
174
|
+
const FIREFOX_TO_CWS = {
|
|
175
|
+
personallyIdentifyingInfo: 'Personally identifiable information',
|
|
176
|
+
healthInfo: 'Health information',
|
|
177
|
+
financialAndPaymentInfo: 'Financial and payment information',
|
|
178
|
+
authenticationInfo: 'Authentication information',
|
|
179
|
+
personalCommunications: 'Personal communications',
|
|
180
|
+
locationInfo: 'Location',
|
|
181
|
+
browsingActivity: 'Web history',
|
|
182
|
+
websiteActivity: 'User activity',
|
|
183
|
+
websiteContent: 'Website content',
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* Data-usage questions for CWS / Edge, from permissions (the existing
|
|
187
|
+
* checklist), the Pay SDK, storage areas and the Firefox declaration.
|
|
188
|
+
*/
|
|
189
|
+
export function buildDataUsage(manifest, flows) {
|
|
190
|
+
const rows = new Map();
|
|
191
|
+
const add = (dataType, certain, reason) => {
|
|
192
|
+
const row = rows.get(dataType) ?? { dataType, certain, reasons: [] };
|
|
193
|
+
// Once a type certainly applies, its "if …" reasons no longer qualify it.
|
|
194
|
+
if (certain && !row.certain) {
|
|
195
|
+
row.certain = true;
|
|
196
|
+
row.reasons = [];
|
|
197
|
+
}
|
|
198
|
+
else if (!certain && row.certain)
|
|
199
|
+
return;
|
|
200
|
+
row.reasons.push(reason);
|
|
201
|
+
rows.set(dataType, row);
|
|
202
|
+
};
|
|
203
|
+
for (const { dataType, permission } of privacyPracticesForManifest(manifest)) {
|
|
204
|
+
add(dataType, true, `the \`${permission}\` permission — its API reads this data`);
|
|
205
|
+
}
|
|
206
|
+
const pay = payEvidence(flows);
|
|
207
|
+
if (pay) {
|
|
208
|
+
add('Financial and payment information', true, `${pay} creates checkouts and checks this installation's purchase and license with the Extenshi API`);
|
|
209
|
+
add('Personally identifiable information', false, 'if you treat the random installation id the Pay SDK ties each purchase to (`endUserRef`) as the ' +
|
|
210
|
+
"buyer's account — CWS counts account numbers as personally identifiable information");
|
|
211
|
+
add('Authentication information', false, 'if license recovery is enabled for your app — the Pay SDK then sends a claim secret held by the installation');
|
|
212
|
+
}
|
|
213
|
+
const kept = flows.storage.filter((s) => s.area !== 'managed');
|
|
214
|
+
if (kept.length > 0) {
|
|
215
|
+
add('Web history', false, `if what you keep in ${kept.map((s) => `\`storage.${s.area}\``).join(' / ')} includes hostnames or ` +
|
|
216
|
+
'URLs (for example per-site settings) — CWS counts the domains a user visits as web browsing ' +
|
|
217
|
+
'activity even when the data never leaves the device');
|
|
218
|
+
}
|
|
219
|
+
const declared = flows.firefoxDataCollection;
|
|
220
|
+
for (const [list, values] of [
|
|
221
|
+
['required', declared?.required ?? []],
|
|
222
|
+
['optional', declared?.optional ?? []],
|
|
223
|
+
]) {
|
|
224
|
+
for (const category of values) {
|
|
225
|
+
const dataType = FIREFOX_TO_CWS[category];
|
|
226
|
+
if (dataType)
|
|
227
|
+
add(dataType, true, `declared to Firefox as \`${category}\` (\`data_collection_permissions.${list}\`)`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const facts = [];
|
|
231
|
+
for (const sdk of flows.sdks) {
|
|
232
|
+
const provenance = [
|
|
233
|
+
sdk.commit ? `commit ${sdk.commit}` : '',
|
|
234
|
+
sdk.buildCommand ? `built by \`${sdk.buildCommand}\`` : '',
|
|
235
|
+
]
|
|
236
|
+
.filter(Boolean)
|
|
237
|
+
.join(', ');
|
|
238
|
+
facts.push(`Bundled SDK: ${sdkLabel(sdk)} — \`${sdk.path}\`${provenance ? ` (${provenance})` : ''}`);
|
|
239
|
+
}
|
|
240
|
+
if (pay)
|
|
241
|
+
facts.push('What the Pay SDK sends: a random installation id (`endUserRef`), the SKU, the UI language and checkout ' +
|
|
242
|
+
'session ids; license recovery adds a claim secret. Card details and the buyer email are entered on ' +
|
|
243
|
+
`hosted pages, not in the extension — ${PAY_SDK_SENDS}`);
|
|
244
|
+
for (const s of flows.storage)
|
|
245
|
+
facts.push(`\`storage.${s.area}\` is used in ${fileList(s.files)}`);
|
|
246
|
+
if (flows.hosts.length > 0)
|
|
247
|
+
facts.push(`Remote hosts named in the code: ${flows.hosts.map((h) => `\`${h.host}\` (${fileList(h.files, 2)})`).join(', ')}. ` +
|
|
248
|
+
'A page the user opens is not collection; a request that carries user data is.');
|
|
249
|
+
const unmapped = [...(declared?.required ?? []), ...(declared?.optional ?? [])].filter((c) => c !== 'none' && c !== 'technicalAndInteraction' && !FIREFOX_TO_CWS[c]);
|
|
250
|
+
if (unmapped.length > 0)
|
|
251
|
+
facts.push(`Declared to Firefox with no one-to-one Chrome Web Store data type: ${unmapped.map((c) => `\`${c}\``).join(', ')} — decide which type covers it.`);
|
|
252
|
+
const sorted = [...rows.values()].sort((a, b) => Number(b.certain) - Number(a.certain) || a.dataType.localeCompare(b.dataType));
|
|
253
|
+
return { rows: sorted, facts };
|
|
254
|
+
}
|
|
255
|
+
/** Is a privacy policy URL required by what was found? `'conditional'` when only conditional rows exist. */
|
|
256
|
+
export function privacyPolicyNeed(usage) {
|
|
257
|
+
if (usage.rows.some((r) => r.certain))
|
|
258
|
+
return 'required';
|
|
259
|
+
return usage.rows.length > 0 ? 'conditional' : 'none';
|
|
260
|
+
}
|
|
261
|
+
/** The Data usage block shared by CHROMEWEBSTORE.md and EDGE.md. */
|
|
262
|
+
export function renderDataUsage(usage) {
|
|
263
|
+
const lines = [];
|
|
264
|
+
if (usage.rows.length === 0) {
|
|
265
|
+
lines.push('_No data-usage questions follow from the package — no permission, bundled SDK, storage area or ' +
|
|
266
|
+
'Firefox declaration implies one. Re-check if the extension sends data some other way._');
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
lines.push('Each line is a question the package raises — tick the type only if it is true:', '');
|
|
270
|
+
// Conditional reasons start with "if …"; a row with only those reads "only if …".
|
|
271
|
+
for (const row of usage.rows) {
|
|
272
|
+
lines.push(`- **${row.dataType}** — ${row.certain ? '' : 'only '}${row.reasons.join('; ')}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (usage.facts.length > 0) {
|
|
276
|
+
lines.push('', 'Found in the package:', '', ...usage.facts.map((f) => `- ${f}`));
|
|
277
|
+
}
|
|
278
|
+
return lines.join('\n');
|
|
279
|
+
}
|
|
280
|
+
// ── AMO data_collection_permissions ──────────────────────────────────────────
|
|
281
|
+
/** MDN `browser_specific_settings` — the values each list may hold. */
|
|
282
|
+
const FIREFOX_PERSONAL_CATEGORIES = [
|
|
283
|
+
'authenticationInfo',
|
|
284
|
+
'bookmarksInfo',
|
|
285
|
+
'browsingActivity',
|
|
286
|
+
'financialAndPaymentInfo',
|
|
287
|
+
'healthInfo',
|
|
288
|
+
'locationInfo',
|
|
289
|
+
'personalCommunications',
|
|
290
|
+
'personallyIdentifyingInfo',
|
|
291
|
+
'searchTerms',
|
|
292
|
+
'websiteActivity',
|
|
293
|
+
'websiteContent',
|
|
294
|
+
];
|
|
295
|
+
const REQUIRED_ALLOWED = new Set(['none', ...FIREFOX_PERSONAL_CATEGORIES]);
|
|
296
|
+
const OPTIONAL_ALLOWED = new Set([...FIREFOX_PERSONAL_CATEGORIES, 'technicalAndInteraction']);
|
|
297
|
+
export function reviewAmoDataCollection(flows) {
|
|
298
|
+
const problems = [];
|
|
299
|
+
const questions = [];
|
|
300
|
+
const declared = flows.firefoxDataCollection;
|
|
301
|
+
const required = declared?.required ?? [];
|
|
302
|
+
const optional = declared?.optional ?? [];
|
|
303
|
+
if (required.includes('none') && required.length > 1)
|
|
304
|
+
problems.push('`required` holds `none` next to other categories — it must be `["none"]` alone or list only the categories collected.');
|
|
305
|
+
if (optional.includes('none'))
|
|
306
|
+
problems.push('`none` is only valid in `required`; remove it from `optional`.');
|
|
307
|
+
if (required.includes('technicalAndInteraction'))
|
|
308
|
+
problems.push('`technicalAndInteraction` can only be `optional` — move it out of `required`.');
|
|
309
|
+
const unknownRequired = required.filter((c) => !REQUIRED_ALLOWED.has(c) && c !== 'technicalAndInteraction');
|
|
310
|
+
const unknownOptional = optional.filter((c) => !OPTIONAL_ALLOWED.has(c) && c !== 'none');
|
|
311
|
+
for (const [list, unknown] of [
|
|
312
|
+
['required', unknownRequired],
|
|
313
|
+
['optional', unknownOptional],
|
|
314
|
+
])
|
|
315
|
+
if (unknown.length > 0)
|
|
316
|
+
problems.push(`\`${list}\` has values Firefox does not know: ${unknown.map((c) => `\`${c}\``).join(', ')}.`);
|
|
317
|
+
const pay = payEvidence(flows);
|
|
318
|
+
const declaresNone = required.length === 1 && required[0] === 'none';
|
|
319
|
+
if (pay && !required.includes('financialAndPaymentInfo') && !optional.includes('financialAndPaymentInfo'))
|
|
320
|
+
questions.push(`${pay} sends purchase and license requests to the Extenshi API — data handled outside the add-on is ` +
|
|
321
|
+
`transmission to AMO. ${declaresNone ? '`none` says nothing leaves the add-on; ' : ''}declare ` +
|
|
322
|
+
'`financialAndPaymentInfo`, or tell the reviewer why it does not apply.');
|
|
323
|
+
if (declaresNone && !pay && flows.hosts.length > 0)
|
|
324
|
+
questions.push(`\`none\` says nothing leaves the add-on, and the code names ${flows.hosts
|
|
325
|
+
.map((h) => `\`${h.host}\``)
|
|
326
|
+
.join(', ')} — if any request there carries user data, declare its category instead.`);
|
|
327
|
+
return { problems, questions };
|
|
328
|
+
}
|
|
329
|
+
// ── Reviewer / certification notes ───────────────────────────────────────────
|
|
330
|
+
/**
|
|
331
|
+
* The keys a macOS tester presses: `MacCtrl` is Control, and plain `Ctrl` — in
|
|
332
|
+
* the `mac` binding or in a `default` used on macOS — becomes Command (Chrome
|
|
333
|
+
* commands API reference, "On macOS Ctrl is automatically converted into
|
|
334
|
+
* Command"). `\bCtrl\b` does not match inside `MacCtrl`.
|
|
335
|
+
*/
|
|
336
|
+
function macReading(key) {
|
|
337
|
+
return key.replace(/\bCtrl\b/g, 'Command').replace(/\bMacCtrl\b/g, 'Control');
|
|
338
|
+
}
|
|
339
|
+
/** Publisher's `amoListingSchema` caps `approvalNotes` at 3,000 characters. */
|
|
340
|
+
export const AMO_APPROVAL_NOTES_MAX = 3000;
|
|
341
|
+
/** Long lists in a note are summarised; the AMO "Source code" section keeps the full inventory. */
|
|
342
|
+
const MAX_LISTED = 5;
|
|
343
|
+
function shortcutFacts(manifest, files) {
|
|
344
|
+
const commands = manifest.commands;
|
|
345
|
+
if (!commands || typeof commands !== 'object' || Array.isArray(commands))
|
|
346
|
+
return [];
|
|
347
|
+
const locale = typeof manifest.default_locale === 'string' ? manifest.default_locale : undefined;
|
|
348
|
+
let messages = null;
|
|
349
|
+
const describe = (raw) => {
|
|
350
|
+
if (typeof raw !== 'string' || !raw.trim())
|
|
351
|
+
return undefined;
|
|
352
|
+
const placeholder = /^__MSG_([A-Za-z0-9_@]+)__$/.exec(raw.trim());
|
|
353
|
+
if (!placeholder)
|
|
354
|
+
return raw.trim();
|
|
355
|
+
// Parsed once, and only when a description is localized.
|
|
356
|
+
if (messages === null)
|
|
357
|
+
messages = locale ? readLocaleMessages(files).get(locale) : undefined;
|
|
358
|
+
return messages ? resolveMessage(messages, placeholder[1])?.trim() : undefined;
|
|
359
|
+
};
|
|
360
|
+
const out = [];
|
|
361
|
+
for (const [name, raw] of Object.entries(commands)) {
|
|
362
|
+
if (!raw || typeof raw !== 'object')
|
|
363
|
+
continue;
|
|
364
|
+
const cmd = raw;
|
|
365
|
+
const keys = cmd.suggested_key && typeof cmd.suggested_key === 'object' ? cmd.suggested_key : {};
|
|
366
|
+
const def = typeof keys.default === 'string' ? keys.default : undefined;
|
|
367
|
+
const mac = typeof keys.mac === 'string' ? keys.mac : undefined;
|
|
368
|
+
if (!def && !mac)
|
|
369
|
+
continue;
|
|
370
|
+
const label = describe(cmd.description) ?? `\`${name}\``;
|
|
371
|
+
const macKey = macReading(mac ?? def);
|
|
372
|
+
if (!def)
|
|
373
|
+
out.push(`${label} — macOS ${macKey}`);
|
|
374
|
+
else
|
|
375
|
+
out.push(`${label} — ${def}${macKey !== def ? ` (macOS: ${macKey})` : ''}`);
|
|
376
|
+
}
|
|
377
|
+
return out;
|
|
378
|
+
}
|
|
379
|
+
function summarised(items) {
|
|
380
|
+
return items.length > MAX_LISTED
|
|
381
|
+
? `${items.slice(0, MAX_LISTED).join('; ')}; +${items.length - MAX_LISTED} more`
|
|
382
|
+
: items.join('; ');
|
|
383
|
+
}
|
|
384
|
+
/** Keep the facts, in order, that fit `max` characters as `- ` bullets; say so when some do not. */
|
|
385
|
+
function fitFacts(facts, max) {
|
|
386
|
+
const trimmed = `Trimmed to the ${max}-character reviewer-notes limit — the rest is in the sections above.`;
|
|
387
|
+
const size = (list) => list.map((f) => `- ${f}`).join('\n').length;
|
|
388
|
+
if (size(facts) <= max)
|
|
389
|
+
return [...facts];
|
|
390
|
+
const out = [];
|
|
391
|
+
for (const fact of facts) {
|
|
392
|
+
if (size([...out, fact, trimmed]) > max)
|
|
393
|
+
break;
|
|
394
|
+
out.push(fact);
|
|
395
|
+
}
|
|
396
|
+
return [...out, trimmed];
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Reviewer / certification notes: payment, private browsing, keyboard
|
|
400
|
+
* shortcuts as macOS testers press them, and vendored minified files with the
|
|
401
|
+
* provenance their build banner states.
|
|
402
|
+
*/
|
|
403
|
+
export function buildReviewerNotes(manifest, files, flows, opts = {}) {
|
|
404
|
+
const facts = [];
|
|
405
|
+
const prompts = [];
|
|
406
|
+
if (flows.paid) {
|
|
407
|
+
const pay = payEvidence(flows);
|
|
408
|
+
facts.push(pay
|
|
409
|
+
? `Payments: ${pay} handles checkout and licensing; some features need a purchase.`
|
|
410
|
+
: 'Payments: some features need a purchase.');
|
|
411
|
+
prompts.push('How a reviewer reaches the paid features: trial length, a test license, or which features stay free.');
|
|
412
|
+
}
|
|
413
|
+
if (typeof manifest.incognito === 'string') {
|
|
414
|
+
facts.push(`Private browsing: the manifest sets \`"incognito": "${manifest.incognito}"\`.`);
|
|
415
|
+
prompts.push('What the extension does in private windows — and that nothing from them is stored.');
|
|
416
|
+
}
|
|
417
|
+
const shortcuts = shortcutFacts(manifest, files);
|
|
418
|
+
if (shortcuts.length > 0)
|
|
419
|
+
facts.push(`Keyboard shortcuts: ${summarised(shortcuts)}.`);
|
|
420
|
+
const minified = detectMinifiedFiles(files);
|
|
421
|
+
const withBanner = [];
|
|
422
|
+
const withoutBanner = [];
|
|
423
|
+
for (const f of minified) {
|
|
424
|
+
const banner = f.hasProvenanceBanner ? parseBuildBanner(files.get(f.path) ?? '') : null;
|
|
425
|
+
if (!banner) {
|
|
426
|
+
withoutBanner.push(`\`${f.path}\``);
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
const provenance = [
|
|
430
|
+
banner.commit ? `commit ${banner.commit}` : '',
|
|
431
|
+
banner.buildCommand ? `built by \`${banner.buildCommand}\`` : '',
|
|
432
|
+
]
|
|
433
|
+
.filter(Boolean)
|
|
434
|
+
.join(', ');
|
|
435
|
+
withBanner.push(`\`${f.path}\` is ${banner.name} v${banner.version}${provenance ? ` (${provenance})` : ''}`);
|
|
436
|
+
}
|
|
437
|
+
if (withBanner.length > 0)
|
|
438
|
+
facts.push(`Minified vendored files: ${summarised(withBanner)}.`);
|
|
439
|
+
if (withoutBanner.length > 0)
|
|
440
|
+
prompts.push(`Where the source of ${withoutBanner.join(', ')} is: a path in the source archive (e.g. \`vendor-src/<name>/\`), or the upstream package and version.`);
|
|
441
|
+
if (opts.lint)
|
|
442
|
+
prompts.push('Warnings from `web-ext lint` you are not fixing (for example in a vendored SDK) — each with the reason.');
|
|
443
|
+
return { facts: opts.maxFactsChars ? fitFacts(facts, opts.maxFactsChars) : facts, prompts };
|
|
444
|
+
}
|
|
445
|
+
/** Facts as bullets, then prompts as guidance lines, then the store's own closing guidance. */
|
|
446
|
+
export function renderReviewerNotes(notes, closing) {
|
|
447
|
+
const blocks = [];
|
|
448
|
+
if (notes.facts.length > 0)
|
|
449
|
+
blocks.push(notes.facts.map((f) => `- ${f}`).join('\n'));
|
|
450
|
+
for (const p of [...notes.prompts, closing])
|
|
451
|
+
blocks.push(`_${p}_`);
|
|
452
|
+
return blocks.join('\n\n');
|
|
453
|
+
}
|
|
454
|
+
//# sourceMappingURL=listing-data-flows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listing-data-flows.js","sourceRoot":"","sources":["../src/listing-data-flows.ts"],"names":[],"mappings":"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"}
|
package/dist/listing.d.ts
CHANGED
|
@@ -58,6 +58,19 @@ export interface Listing {
|
|
|
58
58
|
* wrote.
|
|
59
59
|
*/
|
|
60
60
|
appliesToAllLocales?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* True when a per-locale draft did not say which locale is the default, so
|
|
63
|
+
* `defaultLocale` is our guess. `mergeListings` then lets the package's own
|
|
64
|
+
* `default_locale` decide: alphabetical order once made `ar` the default of
|
|
65
|
+
* an English-first listing.
|
|
66
|
+
*/
|
|
67
|
+
defaultLocaleInferred?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Problems with the input that did not stop the check but change what it
|
|
70
|
+
* read — text that was ignored, a default that was guessed. Reported next to
|
|
71
|
+
* the findings so a clean result is not mistaken for a full one.
|
|
72
|
+
*/
|
|
73
|
+
warnings?: string[];
|
|
61
74
|
}
|
|
62
75
|
interface MessagesFile {
|
|
63
76
|
[key: string]: {
|
|
@@ -90,6 +103,12 @@ export declare function listingFromArtifact(manifest: Manifest, files: FileMap):
|
|
|
90
103
|
* { "name": "…", "shortDescription": "…", "description": "…" }
|
|
91
104
|
* { "defaultLocale": "en", "locales": { "en": { … }, "ru": { … } } }
|
|
92
105
|
*
|
|
106
|
+
* They do not mix. With `locales` present every locale — the default one
|
|
107
|
+
* included — has to sit inside it, and top-level text is ignored with a
|
|
108
|
+
* warning: applying it to a locale would mean guessing which one the developer
|
|
109
|
+
* meant, and checking the guess would report findings against the wrong
|
|
110
|
+
* translation.
|
|
111
|
+
*
|
|
93
112
|
* Throws on a file that is not an object or that yields no usable text — unlike
|
|
94
113
|
* the artifact path, the developer explicitly pointed at this file, so silence
|
|
95
114
|
* would look like a passing check.
|
|
@@ -120,6 +139,35 @@ export declare function listingFromCatalog(text: {
|
|
|
120
139
|
shortDescription?: string;
|
|
121
140
|
description?: string;
|
|
122
141
|
}): Listing | null;
|
|
142
|
+
/**
|
|
143
|
+
* Read a multi-locale listing markdown — the one-file-per-project shape:
|
|
144
|
+
*
|
|
145
|
+
* ## en (default)
|
|
146
|
+
* - **Name:** Tab Sorter
|
|
147
|
+
* - **Summary:** Groups the tabs in your window by site.
|
|
148
|
+
* - **Description:**
|
|
149
|
+
*
|
|
150
|
+
* The full description, as many paragraphs as it takes.
|
|
151
|
+
*
|
|
152
|
+
* ## ru
|
|
153
|
+
* - **Name:** …
|
|
154
|
+
*
|
|
155
|
+
* Name and Summary are one line each; the Description runs to the next locale
|
|
156
|
+
* heading. Anything before the first locale heading (notes, tables) and any
|
|
157
|
+
* `##` section that carries no labelled field is ignored, which is also what
|
|
158
|
+
* keeps a CHROMEWEBSTORE.md — whose headings are field names, not locales —
|
|
159
|
+
* out of this parser.
|
|
160
|
+
*
|
|
161
|
+
* Returns the same object a per-locale `listing.json` holds, plus what was
|
|
162
|
+
* skipped, or `null` when the file has no locale block at all.
|
|
163
|
+
*/
|
|
164
|
+
export declare function listingDraftFromLocalesMd(md: string): {
|
|
165
|
+
draft: {
|
|
166
|
+
defaultLocale?: string;
|
|
167
|
+
locales: Record<string, Record<string, string>>;
|
|
168
|
+
};
|
|
169
|
+
warnings: string[];
|
|
170
|
+
} | null;
|
|
123
171
|
/**
|
|
124
172
|
* Assemble the listing to check: the package's localized name/description,
|
|
125
173
|
* overlaid with the draft file when one was passed.
|
package/dist/listing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listing.d.ts","sourceRoot":"","sources":["../src/listing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAE3D,2FAA2F;AAC3F,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAA;AAE5D,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC7B,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAA;IACd,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,OAAO;IACvB,MAAM,EAAE,aAAa,CAAA;IACrB,kDAAkD;IAClD,aAAa,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"listing.d.ts","sourceRoot":"","sources":["../src/listing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAE3D,2FAA2F;AAC3F,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAAA;AAE5D,sFAAsF;AACtF,MAAM,WAAW,aAAa;IAC7B,0EAA0E;IAC1E,MAAM,EAAE,MAAM,CAAA;IACd,2BAA2B;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,OAAO;IACvB,MAAM,EAAE,aAAa,CAAA;IACrB,kDAAkD;IAClD,aAAa,EAAE,MAAM,CAAA;IACrB,sDAAsD;IACtD,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB;AAUD,UAAU,YAAY;IACrB,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAA;CAChD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAe5E;AA8BD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAgCtF;AA6CD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAqEtD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CA8D/E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACxC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG,OAAO,GAAG,IAAI,CAkBjB;AAiBD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,MAAM,GAAG;IACtD,KAAK,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;KAAE,CAAA;IAClF,QAAQ,EAAE,MAAM,EAAE,CAAA;CAClB,GAAG,IAAI,CAgEP;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC9B,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,OAAO,EACd,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,GACtB,OAAO,GAAG,IAAI,CAmDhB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,OAAO,GAAG,IAAI,EACvB,WAAW,CAAC,EAAE,MAAM,EACpB,WAAW,CAAC,EAAE,OAAO,GACnB,MAAM,EAAE,CAoBV"}
|