jamdesk 1.1.149 → 1.1.150
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 +28 -0
- package/dist/__tests__/integration/fix-scan-integration.test.d.ts +2 -0
- package/dist/__tests__/integration/fix-scan-integration.test.d.ts.map +1 -0
- package/dist/__tests__/integration/fix-scan-integration.test.js +77 -0
- package/dist/__tests__/integration/fix-scan-integration.test.js.map +1 -0
- package/dist/__tests__/unit/ai-fix-client.test.d.ts +2 -0
- package/dist/__tests__/unit/ai-fix-client.test.d.ts.map +1 -0
- package/dist/__tests__/unit/ai-fix-client.test.js +64 -0
- package/dist/__tests__/unit/ai-fix-client.test.js.map +1 -0
- package/dist/__tests__/unit/docs-config.test.js +66 -0
- package/dist/__tests__/unit/docs-config.test.js.map +1 -1
- package/dist/__tests__/unit/fix-ai-fallback.test.d.ts +2 -0
- package/dist/__tests__/unit/fix-ai-fallback.test.d.ts.map +1 -0
- package/dist/__tests__/unit/fix-ai-fallback.test.js +82 -0
- package/dist/__tests__/unit/fix-ai-fallback.test.js.map +1 -0
- package/dist/__tests__/unit/fix-engine-sync.test.d.ts +2 -0
- package/dist/__tests__/unit/fix-engine-sync.test.d.ts.map +1 -0
- package/dist/__tests__/unit/fix-engine-sync.test.js +16 -0
- package/dist/__tests__/unit/fix-engine-sync.test.js.map +1 -0
- package/dist/__tests__/unit/fix.test.d.ts +2 -0
- package/dist/__tests__/unit/fix.test.d.ts.map +1 -0
- package/dist/__tests__/unit/fix.test.js +61 -0
- package/dist/__tests__/unit/fix.test.js.map +1 -0
- package/dist/__tests__/unit/frontmatter-write.test.d.ts +2 -0
- package/dist/__tests__/unit/frontmatter-write.test.d.ts.map +1 -0
- package/dist/__tests__/unit/frontmatter-write.test.js +31 -0
- package/dist/__tests__/unit/frontmatter-write.test.js.map +1 -0
- package/dist/__tests__/unit/heading-extractor-sync.test.d.ts +2 -0
- package/dist/__tests__/unit/heading-extractor-sync.test.d.ts.map +1 -0
- package/dist/__tests__/unit/heading-extractor-sync.test.js +16 -0
- package/dist/__tests__/unit/heading-extractor-sync.test.js.map +1 -0
- package/dist/__tests__/unit/missing-description-scan.test.d.ts +2 -0
- package/dist/__tests__/unit/missing-description-scan.test.d.ts.map +1 -0
- package/dist/__tests__/unit/missing-description-scan.test.js +36 -0
- package/dist/__tests__/unit/missing-description-scan.test.js.map +1 -0
- package/dist/commands/fix.d.ts +97 -0
- package/dist/commands/fix.d.ts.map +1 -0
- package/dist/commands/fix.js +331 -0
- package/dist/commands/fix.js.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/ai-fix-client.d.ts +27 -0
- package/dist/lib/ai-fix-client.d.ts.map +1 -0
- package/dist/lib/ai-fix-client.js +45 -0
- package/dist/lib/ai-fix-client.js.map +1 -0
- package/dist/lib/deps.js +1 -1
- package/dist/lib/deps.js.map +1 -1
- package/dist/lib/docs-config.d.ts +1 -1
- package/dist/lib/docs-config.d.ts.map +1 -1
- package/dist/lib/docs-config.js +59 -4
- package/dist/lib/docs-config.js.map +1 -1
- package/dist/lib/fix-engine.d.ts +89 -0
- package/dist/lib/fix-engine.d.ts.map +1 -0
- package/dist/lib/fix-engine.js +236 -0
- package/dist/lib/fix-engine.js.map +1 -0
- package/dist/lib/frontmatter-write.d.ts +4 -0
- package/dist/lib/frontmatter-write.d.ts.map +1 -0
- package/dist/lib/frontmatter-write.js +10 -0
- package/dist/lib/frontmatter-write.js.map +1 -0
- package/dist/lib/heading-extractor.d.ts +63 -0
- package/dist/lib/heading-extractor.d.ts.map +1 -0
- package/dist/lib/heading-extractor.js +171 -0
- package/dist/lib/heading-extractor.js.map +1 -0
- package/dist/lib/missing-description-scan.d.ts +7 -0
- package/dist/lib/missing-description-scan.d.ts.map +1 -0
- package/dist/lib/missing-description-scan.js +20 -0
- package/dist/lib/missing-description-scan.js.map +1 -0
- package/package.json +3 -3
- package/vendored/components/mdx/ApiEndpoint.tsx +1 -1
- package/vendored/components/mdx/OpenApiEndpoint.tsx +7 -2
- package/vendored/components/navigation/SocialFooter.tsx +9 -1
- package/vendored/lib/build/error-parser.ts +6 -3
- package/vendored/lib/firestore-helpers.ts +2 -3
- package/vendored/lib/fix-engine.ts +293 -0
- package/vendored/lib/health-checks.ts +2 -2
- package/vendored/lib/json-ld.ts +98 -6
- package/vendored/lib/render-doc-page.tsx +8 -2
- package/vendored/lib/search.ts +2 -2
- package/vendored/lib/seo.ts +29 -13
- package/vendored/lib/static-artifacts.ts +2 -2
- package/vendored/lib/ui-strings.ts +6 -0
- package/vendored/lib/validate-config.ts +63 -4
- package/vendored/scripts/build-search-index.cjs +2 -2
- package/vendored/shared/types.ts +1 -0
- package/vendored/workspace-package-lock.json +36 -36
|
@@ -257,10 +257,65 @@ function deduplicateErrors(errors: ErrorObject[]): ErrorObject[] {
|
|
|
257
257
|
});
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
+
const NAV_BRANCH_KEYS = [
|
|
261
|
+
'products', 'languages', 'versions', 'tabs',
|
|
262
|
+
'dropdowns', 'groups', 'pages',
|
|
263
|
+
] as const;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Collapse the navigation anyOf noise. When the user's navigation clearly uses
|
|
267
|
+
* one discriminator key (e.g. `tabs`), drop the sibling-branch
|
|
268
|
+
* `required`/`additionalProperties` errors AT `/navigation` and keep the deeper
|
|
269
|
+
* child errors (e.g. /navigation/tabs/0) that say what's actually wrong. No-op
|
|
270
|
+
* when navigation is absent or the intent is ambiguous (0 or >1 known keys).
|
|
271
|
+
*
|
|
272
|
+
* IMPORTANT: key the predicate on `instancePath` + `keyword` + `params`, NOT
|
|
273
|
+
* `schemaPath`. Ajv resolves the `$ref: "#/definitions/navigationSchema"`, so
|
|
274
|
+
* the nav-branch errors carry schemaPaths like `#/anyOf/0/required` — the
|
|
275
|
+
* string "navigationSchema" never appears in them. (Verified by compiling the
|
|
276
|
+
* real schema against a malformed-tabs config.) `instancePath` is the stable
|
|
277
|
+
* signal: every sibling-branch red herring sits exactly at `/navigation`,
|
|
278
|
+
* while the actionable child error sits at `/navigation/<key>/...`.
|
|
279
|
+
* Runs BEFORE `filterAnyOfNoise`, so schemaPaths are still `#/anyOf/N/...` here.
|
|
280
|
+
*/
|
|
281
|
+
export function filterNavigationAnyOfNoise(
|
|
282
|
+
errors: ErrorObject[],
|
|
283
|
+
navigation: Record<string, unknown> | undefined,
|
|
284
|
+
): ErrorObject[] {
|
|
285
|
+
if (!navigation) return errors;
|
|
286
|
+
const present = NAV_BRANCH_KEYS.filter((k) => k in navigation);
|
|
287
|
+
// Only collapse noise when the user's intent is unambiguous — exactly one
|
|
288
|
+
// discriminator key. Zero keys or multiple keys (itself invalid) → leave
|
|
289
|
+
// the raw errors so we never hide the real problem.
|
|
290
|
+
if (present.length !== 1) return errors;
|
|
291
|
+
const usedKey = present[0];
|
|
292
|
+
|
|
293
|
+
return errors.filter((err) => {
|
|
294
|
+
// Keep everything except the two red-herring classes AT /navigation.
|
|
295
|
+
// Child errors like /navigation/tabs/0 have a deeper instancePath -> kept.
|
|
296
|
+
if (err.instancePath !== '/navigation') return true;
|
|
297
|
+
// Drop sibling-branch "missing required <otherKey>" noise (e.g. products).
|
|
298
|
+
if (err.keyword === 'required') {
|
|
299
|
+
const missing =
|
|
300
|
+
(err.params as { missingProperty?: string }).missingProperty;
|
|
301
|
+
return !(missing && missing !== usedKey &&
|
|
302
|
+
(NAV_BRANCH_KEYS as readonly string[]).includes(missing));
|
|
303
|
+
}
|
|
304
|
+
// Drop "unknown property <usedKey>" flagged by non-matching sibling
|
|
305
|
+
// branches (e.g. additionalProperty "tabs").
|
|
306
|
+
if (err.keyword === 'additionalProperties') {
|
|
307
|
+
const extra =
|
|
308
|
+
(err.params as { additionalProperty?: string }).additionalProperty;
|
|
309
|
+
return extra !== usedKey;
|
|
310
|
+
}
|
|
311
|
+
return true;
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
260
315
|
/**
|
|
261
316
|
* Format validation errors into user-friendly messages
|
|
262
317
|
*/
|
|
263
|
-
export function formatValidationErrors(errors: ErrorObject[] | null | undefined): string {
|
|
318
|
+
export function formatValidationErrors(errors: ErrorObject[] | null | undefined, navigation?: Record<string, unknown>): string {
|
|
264
319
|
if (!errors || errors.length === 0) {
|
|
265
320
|
return 'Unknown validation error';
|
|
266
321
|
}
|
|
@@ -270,8 +325,9 @@ export function formatValidationErrors(errors: ErrorObject[] | null | undefined)
|
|
|
270
325
|
// Safe only because validateConfig pre-checks `config.theme` before Ajv,
|
|
271
326
|
// so a fully-noise error list is unreachable in practice. A new caller
|
|
272
327
|
// that skips the theme pre-check would break this invariant.
|
|
273
|
-
const
|
|
274
|
-
const
|
|
328
|
+
const navFiltered = filterNavigationAnyOfNoise(errors, navigation);
|
|
329
|
+
const filteredErrors = filterAnyOfNoise(navFiltered);
|
|
330
|
+
const effectiveErrors = filteredErrors.length > 0 ? filteredErrors : navFiltered;
|
|
275
331
|
|
|
276
332
|
const messages = effectiveErrors.slice(0, 3).map(err => {
|
|
277
333
|
const path = err.instancePath || 'root';
|
|
@@ -548,7 +604,10 @@ export async function validateConfig(
|
|
|
548
604
|
const valid = validate(config);
|
|
549
605
|
|
|
550
606
|
if (!valid) {
|
|
551
|
-
const errorMessage = formatValidationErrors(
|
|
607
|
+
const errorMessage = formatValidationErrors(
|
|
608
|
+
validate.errors,
|
|
609
|
+
config.navigation as Record<string, unknown> | undefined,
|
|
610
|
+
);
|
|
552
611
|
return {
|
|
553
612
|
valid: false,
|
|
554
613
|
error: `Invalid docs.json: ${errorMessage}`,
|
|
@@ -233,8 +233,8 @@ function getOutputPath() {
|
|
|
233
233
|
|
|
234
234
|
function stripMarkdown(text) {
|
|
235
235
|
return text
|
|
236
|
-
.replace(/```[\s\S]*?```/g, '')
|
|
237
|
-
.replace(/`[^`]
|
|
236
|
+
.replace(/```[\s\S]*?```/g, '') // code blocks (too noisy to index)
|
|
237
|
+
.replace(/`([^`]+)`/g, '$1') // inline code → keep text, drop backticks (config keys like starterQuestions stay searchable)
|
|
238
238
|
.replace(/#{1,6}\s/g, '')
|
|
239
239
|
.replace(/\*\*([^*]+)\*\*/g, '$1')
|
|
240
240
|
.replace(/\*([^*]+)\*/g, '$1')
|
package/vendored/shared/types.ts
CHANGED
|
@@ -25,6 +25,7 @@ export interface BuildParams {
|
|
|
25
25
|
showBranding?: boolean; // Show "Powered by Jamdesk" in footer (defaults to true)
|
|
26
26
|
hostAtDocs?: boolean; // URL structure: true = /docs/*, false = root /*
|
|
27
27
|
autoMigrate?: boolean; // If true, auto-convert deprecated components during build
|
|
28
|
+
aiFix?: boolean; // If true, collect AI anchor-fix suggestions during build
|
|
28
29
|
tarballKey?: string; // R2 key for CLI-uploaded tarball
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"name": "jamdesk-workspace",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"@apidevtools/swagger-parser": "^12.1.0",
|
|
10
|
-
"@babel/standalone": "^
|
|
10
|
+
"@babel/standalone": "^8.0.1",
|
|
11
11
|
"@fortawesome/fontawesome-svg-core": "^7.1.0",
|
|
12
12
|
"@fortawesome/free-brands-svg-icons": "^7.1.0",
|
|
13
13
|
"@fortawesome/free-regular-svg-icons": "^7.1.0",
|
|
@@ -163,12 +163,12 @@
|
|
|
163
163
|
}
|
|
164
164
|
},
|
|
165
165
|
"node_modules/@babel/standalone": {
|
|
166
|
-
"version": "
|
|
167
|
-
"resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-
|
|
168
|
-
"integrity": "sha512-
|
|
166
|
+
"version": "8.0.2",
|
|
167
|
+
"resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-8.0.2.tgz",
|
|
168
|
+
"integrity": "sha512-fxVjA+dyCXC6tZm8sp21egVF0WVpPRnJOhmfG4WavISe2otyfOLleh+owitHWMhILTdjd7W0mfpadS16cj8LBw==",
|
|
169
169
|
"license": "MIT",
|
|
170
170
|
"engines": {
|
|
171
|
-
"node": ">=
|
|
171
|
+
"node": "^22.18.0 || >=24.11.0"
|
|
172
172
|
}
|
|
173
173
|
},
|
|
174
174
|
"node_modules/@braintree/sanitize-url": {
|
|
@@ -1932,9 +1932,9 @@
|
|
|
1932
1932
|
}
|
|
1933
1933
|
},
|
|
1934
1934
|
"node_modules/@types/node": {
|
|
1935
|
-
"version": "25.9.
|
|
1936
|
-
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.
|
|
1937
|
-
"integrity": "sha512-
|
|
1935
|
+
"version": "25.9.4",
|
|
1936
|
+
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.4.tgz",
|
|
1937
|
+
"integrity": "sha512-dszCsrKb5U7ZsVZBWiHFklTloVl0mSEnWH/iZXfZUlI4rzCUnsvGmgqfuVRHL54ugE7/wRuxEIXRa2iMZ+BG6g==",
|
|
1938
1938
|
"license": "MIT",
|
|
1939
1939
|
"dependencies": {
|
|
1940
1940
|
"undici-types": ">=7.24.0 <7.24.7"
|
|
@@ -2145,9 +2145,9 @@
|
|
|
2145
2145
|
}
|
|
2146
2146
|
},
|
|
2147
2147
|
"node_modules/baseline-browser-mapping": {
|
|
2148
|
-
"version": "2.10.
|
|
2149
|
-
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.
|
|
2150
|
-
"integrity": "sha512-
|
|
2148
|
+
"version": "2.10.38",
|
|
2149
|
+
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.38.tgz",
|
|
2150
|
+
"integrity": "sha512-31/02mVB4yuQU6adKk5SlY6m+mxDwUq5KZkyYgnLrrKl7TEm1+3PyDtDBz2kOv/wxZz41GHsvV1A/u6RmiyBvw==",
|
|
2151
2151
|
"license": "Apache-2.0",
|
|
2152
2152
|
"bin": {
|
|
2153
2153
|
"baseline-browser-mapping": "dist/cli.cjs"
|
|
@@ -2169,9 +2169,9 @@
|
|
|
2169
2169
|
}
|
|
2170
2170
|
},
|
|
2171
2171
|
"node_modules/browserslist": {
|
|
2172
|
-
"version": "4.28.
|
|
2173
|
-
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.
|
|
2174
|
-
"integrity": "sha512-
|
|
2172
|
+
"version": "4.28.4",
|
|
2173
|
+
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.4.tgz",
|
|
2174
|
+
"integrity": "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw==",
|
|
2175
2175
|
"funding": [
|
|
2176
2176
|
{
|
|
2177
2177
|
"type": "opencollective",
|
|
@@ -2188,10 +2188,10 @@
|
|
|
2188
2188
|
],
|
|
2189
2189
|
"license": "MIT",
|
|
2190
2190
|
"dependencies": {
|
|
2191
|
-
"baseline-browser-mapping": "^2.10.
|
|
2192
|
-
"caniuse-lite": "^1.0.
|
|
2193
|
-
"electron-to-chromium": "^1.5.
|
|
2194
|
-
"node-releases": "^2.0.
|
|
2191
|
+
"baseline-browser-mapping": "^2.10.38",
|
|
2192
|
+
"caniuse-lite": "^1.0.30001799",
|
|
2193
|
+
"electron-to-chromium": "^1.5.376",
|
|
2194
|
+
"node-releases": "^2.0.48",
|
|
2195
2195
|
"update-browserslist-db": "^1.2.3"
|
|
2196
2196
|
},
|
|
2197
2197
|
"bin": {
|
|
@@ -2939,9 +2939,9 @@
|
|
|
2939
2939
|
"license": "MIT"
|
|
2940
2940
|
},
|
|
2941
2941
|
"node_modules/electron-to-chromium": {
|
|
2942
|
-
"version": "1.5.
|
|
2943
|
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.
|
|
2944
|
-
"integrity": "sha512-
|
|
2942
|
+
"version": "1.5.376",
|
|
2943
|
+
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.376.tgz",
|
|
2944
|
+
"integrity": "sha512-cUVA7/RvbFTEuw/i3obUwDTRIXojaxkResf+ibByPFxjc6XK3VNtcQXV0NSbAlJ0FMjcJGgftVVB4Qo184EXvA==",
|
|
2945
2945
|
"license": "ISC"
|
|
2946
2946
|
},
|
|
2947
2947
|
"node_modules/enhanced-resolve": {
|
|
@@ -2970,9 +2970,9 @@
|
|
|
2970
2970
|
}
|
|
2971
2971
|
},
|
|
2972
2972
|
"node_modules/es-toolkit": {
|
|
2973
|
-
"version": "1.
|
|
2974
|
-
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.
|
|
2975
|
-
"integrity": "sha512-
|
|
2973
|
+
"version": "1.48.1",
|
|
2974
|
+
"resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.48.1.tgz",
|
|
2975
|
+
"integrity": "sha512-wfnXlwd5I75eXRtdD2vuEs50xHHESECDsGD7yiQnfFVNoa5522NwXEbmgo98LfiukSQHs+mBM7/YG3qKJB9/mQ==",
|
|
2976
2976
|
"license": "MIT",
|
|
2977
2977
|
"workspaces": [
|
|
2978
2978
|
"docs",
|
|
@@ -5288,9 +5288,9 @@
|
|
|
5288
5288
|
"license": "MIT"
|
|
5289
5289
|
},
|
|
5290
5290
|
"node_modules/nanoid": {
|
|
5291
|
-
"version": "3.3.
|
|
5292
|
-
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.
|
|
5293
|
-
"integrity": "sha512-
|
|
5291
|
+
"version": "3.3.15",
|
|
5292
|
+
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz",
|
|
5293
|
+
"integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==",
|
|
5294
5294
|
"funding": [
|
|
5295
5295
|
{
|
|
5296
5296
|
"type": "github",
|
|
@@ -5432,9 +5432,9 @@
|
|
|
5432
5432
|
}
|
|
5433
5433
|
},
|
|
5434
5434
|
"node_modules/node-releases": {
|
|
5435
|
-
"version": "2.0.
|
|
5436
|
-
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.
|
|
5437
|
-
"integrity": "sha512-
|
|
5435
|
+
"version": "2.0.48",
|
|
5436
|
+
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.48.tgz",
|
|
5437
|
+
"integrity": "sha512-1uz8041X6LoI6ZSdZacM9lVY28vuzDlSKitnpbSNK0RfKoIJkX29NBPVEFXhnuSuEOA9Ww0xnPJ+ILWbGAv8DA==",
|
|
5438
5438
|
"license": "MIT",
|
|
5439
5439
|
"engines": {
|
|
5440
5440
|
"node": ">=18"
|
|
@@ -6079,9 +6079,9 @@
|
|
|
6079
6079
|
}
|
|
6080
6080
|
},
|
|
6081
6081
|
"node_modules/semver": {
|
|
6082
|
-
"version": "7.8.
|
|
6083
|
-
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.
|
|
6084
|
-
"integrity": "sha512-
|
|
6082
|
+
"version": "7.8.5",
|
|
6083
|
+
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz",
|
|
6084
|
+
"integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==",
|
|
6085
6085
|
"license": "ISC",
|
|
6086
6086
|
"optional": true,
|
|
6087
6087
|
"bin": {
|
|
@@ -6578,9 +6578,9 @@
|
|
|
6578
6578
|
"license": "MIT"
|
|
6579
6579
|
},
|
|
6580
6580
|
"node_modules/uuid": {
|
|
6581
|
-
"version": "14.0.
|
|
6582
|
-
"resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.
|
|
6583
|
-
"integrity": "sha512-
|
|
6581
|
+
"version": "14.0.1",
|
|
6582
|
+
"resolved": "https://registry.npmjs.org/uuid/-/uuid-14.0.1.tgz",
|
|
6583
|
+
"integrity": "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew==",
|
|
6584
6584
|
"funding": [
|
|
6585
6585
|
"https://github.com/sponsors/broofa",
|
|
6586
6586
|
"https://github.com/sponsors/ctavan"
|