jamdesk 1.1.147 → 1.1.148
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/package.json +1 -1
- package/vendored/components/ConsentGate.tsx +87 -0
- package/vendored/lib/consent-gating.ts +119 -0
- package/vendored/lib/docs-types.ts +5 -1
- package/vendored/lib/layout-helpers.tsx +43 -6
- package/vendored/lib/validate-config.ts +3 -0
- package/vendored/schema/docs-schema.json +21 -2
- package/vendored/workspace-package-lock.json +87 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jamdesk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.148",
|
|
4
4
|
"description": "CLI for Jamdesk — build, preview, and deploy documentation sites from MDX. Dev server with hot reload, 50+ components, OpenAPI support, AI search, and Mintlify migration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jamdesk",
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// builder/build-service/components/ConsentGate.tsx
|
|
2
|
+
'use client';
|
|
3
|
+
|
|
4
|
+
import { useEffect, useRef } from 'react';
|
|
5
|
+
import type { GatedScript } from '../lib/consent-gating';
|
|
6
|
+
|
|
7
|
+
const POLL_MS = 1000;
|
|
8
|
+
|
|
9
|
+
function hasConsent(key: string, value: string): boolean {
|
|
10
|
+
try {
|
|
11
|
+
return window.localStorage.getItem(key) === value;
|
|
12
|
+
} catch {
|
|
13
|
+
// Storage unavailable (private mode / blocked iframe) → treat as no consent
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function injectScripts(scripts: GatedScript[]): void {
|
|
19
|
+
for (const s of scripts) {
|
|
20
|
+
const el = document.createElement('script');
|
|
21
|
+
el.setAttribute('data-jd-consent-script', s.id);
|
|
22
|
+
if (s.kind === 'src' && s.src) {
|
|
23
|
+
el.src = s.src;
|
|
24
|
+
for (const [name, val] of Object.entries(s.attrs ?? {})) el.setAttribute(name, val);
|
|
25
|
+
} else if (s.kind === 'inline' && s.code) {
|
|
26
|
+
el.textContent = s.code;
|
|
27
|
+
} else {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
(s.appendTo === 'head' ? document.head : document.body).appendChild(el);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Consent gate for analytics/tracking scripts (integrations.cookies).
|
|
36
|
+
* Renders nothing. Injects the given scripts once localStorage[consentKey]
|
|
37
|
+
* equals consentValue — immediately on mount if consent pre-exists, else via
|
|
38
|
+
* a storage listener (cross-tab) + poll (same-tab CMP writes don't fire
|
|
39
|
+
* storage events). Scripts are injected at most once per page load; consent
|
|
40
|
+
* revocation takes effect on the next page load.
|
|
41
|
+
*/
|
|
42
|
+
export function ConsentGate({
|
|
43
|
+
consentKey,
|
|
44
|
+
consentValue,
|
|
45
|
+
scripts,
|
|
46
|
+
}: {
|
|
47
|
+
consentKey: string;
|
|
48
|
+
consentValue: string;
|
|
49
|
+
scripts: GatedScript[];
|
|
50
|
+
}) {
|
|
51
|
+
// scripts is a fresh array identity each render (built server-side, serialized
|
|
52
|
+
// across the RSC boundary). Hold it in a ref so the effect doesn't list it as
|
|
53
|
+
// a dependency — otherwise a parent re-render before consent arrives would
|
|
54
|
+
// tear down and restart the polling window. Content is stable per page.
|
|
55
|
+
const scriptsRef = useRef(scripts);
|
|
56
|
+
scriptsRef.current = scripts;
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
if ((window as any).__jdConsentInjected) return;
|
|
60
|
+
let intervalId: ReturnType<typeof setInterval> | undefined;
|
|
61
|
+
|
|
62
|
+
const stop = () => {
|
|
63
|
+
if (intervalId !== undefined) clearInterval(intervalId);
|
|
64
|
+
window.removeEventListener('storage', check);
|
|
65
|
+
};
|
|
66
|
+
const check = () => {
|
|
67
|
+
if ((window as any).__jdConsentInjected) { stop(); return; }
|
|
68
|
+
if (!hasConsent(consentKey, consentValue)) return;
|
|
69
|
+
(window as any).__jdConsentInjected = true;
|
|
70
|
+
stop();
|
|
71
|
+
injectScripts(scriptsRef.current);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
check();
|
|
75
|
+
if (!(window as any).__jdConsentInjected) {
|
|
76
|
+
// Diagnostics: wrong key/value otherwise fails silently forever.
|
|
77
|
+
console.debug(
|
|
78
|
+
`[Jamdesk] Consent gating active — analytics withheld until localStorage["${consentKey}"] equals the configured value.`,
|
|
79
|
+
);
|
|
80
|
+
window.addEventListener('storage', check);
|
|
81
|
+
intervalId = setInterval(check, POLL_MS);
|
|
82
|
+
}
|
|
83
|
+
return stop;
|
|
84
|
+
}, [consentKey, consentValue]);
|
|
85
|
+
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// builder/build-service/lib/consent-gating.ts
|
|
2
|
+
// Consent gating for analytics/tracking scripts (integrations.cookies) and
|
|
3
|
+
// CMP loader validation (integrations.osano / integrations.termly).
|
|
4
|
+
// Pure module — no DOM, no React — so the server layout and tests share it.
|
|
5
|
+
import type { IntegrationsConfig } from './docs-types';
|
|
6
|
+
|
|
7
|
+
export interface GatedScript {
|
|
8
|
+
/** Stable id — used as DOM marker (data-jd-consent-script) and React key */
|
|
9
|
+
id: string;
|
|
10
|
+
kind: 'inline' | 'src';
|
|
11
|
+
/** Inline JS source (kind: 'inline') */
|
|
12
|
+
code?: string;
|
|
13
|
+
/** External src (kind: 'src') */
|
|
14
|
+
src?: string;
|
|
15
|
+
/** Extra attributes set via setAttribute (kind: 'src'); '' = boolean attr */
|
|
16
|
+
attrs?: Record<string, string>;
|
|
17
|
+
appendTo: 'head' | 'body';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Tracking-ID guards: these values get interpolated into inline JS / URLs, so
|
|
21
|
+
// they must be strictly validated (same posture as the existing Crisp guard).
|
|
22
|
+
// /i is intentional: tolerate lowercase-typed IDs (alphanumerics + hyphen
|
|
23
|
+
// can't break out of the inline JS string regardless of case).
|
|
24
|
+
const GA4_ID_RE = /^G-[A-Z0-9]+$/i;
|
|
25
|
+
const GTM_ID_RE = /^GTM-[A-Z0-9]+$/i;
|
|
26
|
+
const CRISP_ID_RE = /^[a-f0-9-]{36}$/; // mirrors layout-helpers.tsx guard
|
|
27
|
+
|
|
28
|
+
// CMP loader URL pins. Defense-in-depth: schema validates these too, but the
|
|
29
|
+
// renderer must not trust config blobs from R2. Path charset includes '.' so
|
|
30
|
+
// every schema-valid Osano URL also passes here (schema only pins prefix/suffix).
|
|
31
|
+
const OSANO_SRC_RE = /^https:\/\/cmp\.osano\.com\/[A-Za-z0-9._/-]+\/osano\.js$/;
|
|
32
|
+
const TERMLY_SRC_RE =
|
|
33
|
+
/^https:\/\/app\.termly\.io\/resource-blocker\/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(\?autoBlock=(on|off))?$/;
|
|
34
|
+
|
|
35
|
+
export function isConsentGatingEnabled(integrations: IntegrationsConfig | undefined): boolean {
|
|
36
|
+
const c = integrations?.cookies;
|
|
37
|
+
return typeof c?.key === 'string' && c.key.length > 0 &&
|
|
38
|
+
typeof c?.value === 'string' && c.value.length > 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Validated CMP script srcs to render ungated in <head> (Osano first). */
|
|
42
|
+
export function getCmpScriptSrcs(integrations: IntegrationsConfig | undefined): string[] {
|
|
43
|
+
const srcs: string[] = [];
|
|
44
|
+
const osano = integrations?.osano?.scriptSource;
|
|
45
|
+
if (osano && OSANO_SRC_RE.test(osano)) srcs.push(osano);
|
|
46
|
+
const termly = integrations?.termly?.scriptSource;
|
|
47
|
+
if (termly && TERMLY_SRC_RE.test(termly)) srcs.push(termly);
|
|
48
|
+
return srcs;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Build serializable descriptors for every analytics/tracking script.
|
|
53
|
+
* Emitted unconditionally — the caller is responsible for the prod gate:
|
|
54
|
+
* layout-helpers renders <ConsentGate> (and thus calls this) only when
|
|
55
|
+
* NODE_ENV === 'production', matching the dev-suppression the direct render
|
|
56
|
+
* paths already apply to Plausible/Crisp/customJs/first-party analytics.
|
|
57
|
+
*/
|
|
58
|
+
export function buildGatedScripts({
|
|
59
|
+
integrations,
|
|
60
|
+
customJs,
|
|
61
|
+
analyticsScript,
|
|
62
|
+
}: {
|
|
63
|
+
integrations: IntegrationsConfig | undefined;
|
|
64
|
+
customJs: string | null;
|
|
65
|
+
analyticsScript: string | null;
|
|
66
|
+
}): GatedScript[] {
|
|
67
|
+
const scripts: GatedScript[] = [];
|
|
68
|
+
const i = integrations ?? {};
|
|
69
|
+
|
|
70
|
+
if (i.plausible?.scriptUrl) {
|
|
71
|
+
// Proxy mode — mirrors PlausibleScript's scriptUrl branch in layout-helpers
|
|
72
|
+
scripts.push({ id: 'plausible-proxy', kind: 'src', src: i.plausible.scriptUrl, attrs: { async: '' }, appendTo: 'head' });
|
|
73
|
+
scripts.push({
|
|
74
|
+
id: 'plausible-proxy-init', kind: 'inline', appendTo: 'head',
|
|
75
|
+
code: 'window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};plausible.init()',
|
|
76
|
+
});
|
|
77
|
+
} else if (i.plausible?.domain) {
|
|
78
|
+
const baseServer = (i.plausible.server || 'https://plausible.io').replace(/\/+$/, '');
|
|
79
|
+
const attrs: Record<string, string> = { defer: '', 'data-domain': i.plausible.domain };
|
|
80
|
+
if (i.plausible.server) attrs['data-api'] = `${baseServer}/api/event`;
|
|
81
|
+
scripts.push({ id: 'plausible', kind: 'src', src: `${baseServer}/js/script.js`, attrs, appendTo: 'head' });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// GTM/GA4 here are raw inline equivalents of the standard snippets. The
|
|
85
|
+
// ungated direct renders use @next/third-parties (ConditionalGTM/ConditionalGA)
|
|
86
|
+
// instead; these descriptors deliberately bypass it because they're injected
|
|
87
|
+
// client-side at consent time, not at SSR. Functionally equivalent for tracking,
|
|
88
|
+
// but they carry NO Next.js CSP nonce and GTM omits the <noscript> iframe
|
|
89
|
+
// fallback (irrelevant — no-JS clients can't trigger the consent gate anyway).
|
|
90
|
+
if (i.gtm?.tagId && GTM_ID_RE.test(i.gtm.tagId)) {
|
|
91
|
+
scripts.push({
|
|
92
|
+
id: 'gtm', kind: 'inline', appendTo: 'head',
|
|
93
|
+
code: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','${i.gtm.tagId}');`,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (i.ga4?.measurementId && GA4_ID_RE.test(i.ga4.measurementId)) {
|
|
98
|
+
scripts.push({
|
|
99
|
+
id: 'ga4-loader', kind: 'src', appendTo: 'head', attrs: { async: '' },
|
|
100
|
+
src: `https://www.googletagmanager.com/gtag/js?id=${i.ga4.measurementId}`,
|
|
101
|
+
});
|
|
102
|
+
scripts.push({
|
|
103
|
+
id: 'ga4-init', kind: 'inline', appendTo: 'head',
|
|
104
|
+
code: `window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','${i.ga4.measurementId}');`,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (i.crisp?.websiteId && CRISP_ID_RE.test(i.crisp.websiteId)) {
|
|
109
|
+
scripts.push({
|
|
110
|
+
id: 'crisp', kind: 'inline', appendTo: 'body',
|
|
111
|
+
code: `window.$crisp=[];window.CRISP_WEBSITE_ID="${i.crisp.websiteId}";(function(){var d=document;var s=d.createElement("script");s.src="https://client.crisp.chat/l.js";s.async=1;d.getElementsByTagName("head")[0].appendChild(s)})();`,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (customJs) scripts.push({ id: 'custom-js', kind: 'inline', code: customJs, appendTo: 'body' });
|
|
116
|
+
if (analyticsScript) scripts.push({ id: 'jd-analytics', kind: 'inline', code: analyticsScript, appendTo: 'body' });
|
|
117
|
+
|
|
118
|
+
return scripts;
|
|
119
|
+
}
|
|
@@ -644,7 +644,10 @@ export interface NewsletterConfig {
|
|
|
644
644
|
}
|
|
645
645
|
|
|
646
646
|
/**
|
|
647
|
-
* Analytics and integration configurations
|
|
647
|
+
* Analytics and integration configurations.
|
|
648
|
+
* Implemented: ga4, gtm, plausible, crisp, osano, termly, cookies (consent
|
|
649
|
+
* gating), analytics opt-out via AnalyticsConfig. Others remain config-only
|
|
650
|
+
* stubs accepted for Mintlify compatibility.
|
|
648
651
|
*/
|
|
649
652
|
export interface IntegrationsConfig {
|
|
650
653
|
ga4?: { measurementId: string };
|
|
@@ -664,6 +667,7 @@ export interface IntegrationsConfig {
|
|
|
664
667
|
logrocket?: { appId: string };
|
|
665
668
|
mixpanel?: { projectToken: string };
|
|
666
669
|
osano?: { scriptSource: string };
|
|
670
|
+
termly?: { scriptSource: string };
|
|
667
671
|
pirsch?: { id: string };
|
|
668
672
|
posthog?: { apiKey: string; apiHost?: string };
|
|
669
673
|
plausible?: { domain?: string; server?: string; scriptUrl?: string };
|
|
@@ -25,6 +25,8 @@ import type { BackgroundConfig, DocsConfig, FontConfig, LanguageCode } from '@/l
|
|
|
25
25
|
import { LinkPrefixProvider } from '@/lib/link-prefix-context';
|
|
26
26
|
import { ProjectSlugProvider } from '@/lib/project-slug-context';
|
|
27
27
|
import { getAnalyticsScript } from '@/lib/analytics-script';
|
|
28
|
+
import { isConsentGatingEnabled, buildGatedScripts, getCmpScriptSrcs } from '@/lib/consent-gating';
|
|
29
|
+
import { ConsentGate } from '@/components/ConsentGate';
|
|
28
30
|
import { AgentDirective } from './agent-directive';
|
|
29
31
|
import { fetchCustomCss, fetchCustomJs } from '@/lib/r2-content';
|
|
30
32
|
import { toHreflang } from '@/lib/language-utils';
|
|
@@ -429,6 +431,21 @@ export async function DocsChrome({
|
|
|
429
431
|
? getAnalyticsScript(resolvedProjectSlug)
|
|
430
432
|
: null;
|
|
431
433
|
|
|
434
|
+
// integrations.cookies consent gating: when key+value are configured, all
|
|
435
|
+
// analytics/tracking scripts are withheld until the CMP writes
|
|
436
|
+
// localStorage[key] === value (ConsentGate injects them client-side).
|
|
437
|
+
const consentGating = isConsentGatingEnabled(config.integrations);
|
|
438
|
+
// CMP loaders (Osano/Termly) are NEVER gated — they ARE the consent banner.
|
|
439
|
+
const cmpScriptSrcs = process.env.NODE_ENV === 'production'
|
|
440
|
+
? getCmpScriptSrcs(config.integrations)
|
|
441
|
+
: [];
|
|
442
|
+
// Preconnect origins are best-effort: getCmpScriptSrcs only returns
|
|
443
|
+
// regex-validated absolute https URLs (so new URL can't throw today), but
|
|
444
|
+
// guard anyway — a malformed preconnect must never 500 the whole render.
|
|
445
|
+
const cmpPreconnectOrigins = cmpScriptSrcs
|
|
446
|
+
.map((src) => { try { return new URL(src).origin; } catch { return null; } })
|
|
447
|
+
.filter((origin): origin is string => origin !== null);
|
|
448
|
+
|
|
432
449
|
// Global banner: only emit the pre-paint no-flash guard for a dismissible
|
|
433
450
|
// banner (a non-dismissible banner is never hidden, so the guard would risk
|
|
434
451
|
// hiding a mandatory message via a stale dismissal hash). Trimmed content
|
|
@@ -457,6 +474,15 @@ export async function DocsChrome({
|
|
|
457
474
|
return (
|
|
458
475
|
<html lang={toHreflang(lang)} dir={dir} suppressHydrationWarning data-scroll-behavior="smooth" data-scroll-locked="true">
|
|
459
476
|
<head>
|
|
477
|
+
{/* CMP scripts must be first + synchronous: auto-blocking CMPs
|
|
478
|
+
(Osano/Termly) need to intercept later scripts. Never gated.
|
|
479
|
+
preconnect first: the sync fetch is render-blocking. */}
|
|
480
|
+
{cmpPreconnectOrigins.map((origin) => (
|
|
481
|
+
<link key={`pc-${origin}`} rel="preconnect" href={origin} />
|
|
482
|
+
))}
|
|
483
|
+
{cmpScriptSrcs.map((src) => (
|
|
484
|
+
<script key={src} src={src} />
|
|
485
|
+
))}
|
|
460
486
|
{/*
|
|
461
487
|
SSR scroll lock — prevents Chrome's same-tab cross-origin "preserve
|
|
462
488
|
scroll" heuristic from scrolling #content-scroll-container on first
|
|
@@ -674,7 +700,7 @@ export async function DocsChrome({
|
|
|
674
700
|
{customCss}
|
|
675
701
|
</style>
|
|
676
702
|
)}
|
|
677
|
-
{process.env.NODE_ENV === 'production' && (config.integrations?.plausible?.domain || config.integrations?.plausible?.scriptUrl) && (
|
|
703
|
+
{!consentGating && process.env.NODE_ENV === 'production' && (config.integrations?.plausible?.domain || config.integrations?.plausible?.scriptUrl) && (
|
|
678
704
|
<PlausibleScript
|
|
679
705
|
domain={config.integrations.plausible.domain}
|
|
680
706
|
server={config.integrations.plausible.server}
|
|
@@ -684,7 +710,7 @@ export async function DocsChrome({
|
|
|
684
710
|
</head>
|
|
685
711
|
<body className={fontClassName} data-theme={themeName || 'jam'} data-decoration={decoration || undefined} suppressHydrationWarning>
|
|
686
712
|
{!embed && <AgentDirective hostAtDocs={!!config.hostAtDocs} />}
|
|
687
|
-
{config.integrations?.gtm?.tagId && (
|
|
713
|
+
{!consentGating && config.integrations?.gtm?.tagId && (
|
|
688
714
|
<ConditionalGTM gtmId={config.integrations.gtm.tagId} />
|
|
689
715
|
)}
|
|
690
716
|
<ThemeProvider
|
|
@@ -712,7 +738,7 @@ export async function DocsChrome({
|
|
|
712
738
|
client" warning in `jamdesk dev`. Same pattern as the
|
|
713
739
|
project-subdomain hydration suppressor in <head>.
|
|
714
740
|
*/}
|
|
715
|
-
{process.env.NODE_ENV === 'production' && config.integrations?.crisp?.websiteId &&
|
|
741
|
+
{!consentGating && process.env.NODE_ENV === 'production' && config.integrations?.crisp?.websiteId &&
|
|
716
742
|
/^[a-f0-9-]{36}$/.test(config.integrations.crisp.websiteId) && (
|
|
717
743
|
<script
|
|
718
744
|
dangerouslySetInnerHTML={{
|
|
@@ -720,15 +746,26 @@ export async function DocsChrome({
|
|
|
720
746
|
}}
|
|
721
747
|
/>
|
|
722
748
|
)}
|
|
723
|
-
{process.env.NODE_ENV === 'production' && customJs && (
|
|
749
|
+
{!consentGating && process.env.NODE_ENV === 'production' && customJs && (
|
|
724
750
|
<script dangerouslySetInnerHTML={{ __html: customJs }} />
|
|
725
751
|
)}
|
|
726
|
-
{process.env.NODE_ENV === 'production' && analyticsScript && (
|
|
752
|
+
{!consentGating && process.env.NODE_ENV === 'production' && analyticsScript && (
|
|
727
753
|
<script dangerouslySetInnerHTML={{ __html: analyticsScript }} />
|
|
728
754
|
)}
|
|
729
|
-
{config.integrations?.ga4?.measurementId && (
|
|
755
|
+
{!consentGating && config.integrations?.ga4?.measurementId && (
|
|
730
756
|
<ConditionalGA gaId={config.integrations.ga4.measurementId} />
|
|
731
757
|
)}
|
|
758
|
+
{consentGating && process.env.NODE_ENV === 'production' && (
|
|
759
|
+
<ConsentGate
|
|
760
|
+
consentKey={config.integrations!.cookies!.key!}
|
|
761
|
+
consentValue={config.integrations!.cookies!.value!}
|
|
762
|
+
scripts={buildGatedScripts({
|
|
763
|
+
integrations: config.integrations,
|
|
764
|
+
customJs,
|
|
765
|
+
analyticsScript,
|
|
766
|
+
})}
|
|
767
|
+
/>
|
|
768
|
+
)}
|
|
732
769
|
<JdReadySentinel />
|
|
733
770
|
</body>
|
|
734
771
|
</html>
|
|
@@ -36,6 +36,9 @@ export interface IntegrationsConfig {
|
|
|
36
36
|
ga4?: { measurementId: string };
|
|
37
37
|
gtm?: { tagId: string };
|
|
38
38
|
plausible?: { domain?: string; server?: string; scriptUrl?: string };
|
|
39
|
+
osano?: { scriptSource: string };
|
|
40
|
+
termly?: { scriptSource: string };
|
|
41
|
+
cookies?: { key?: string; value?: string };
|
|
39
42
|
[key: string]: unknown;
|
|
40
43
|
}
|
|
41
44
|
|
|
@@ -1258,6 +1258,19 @@
|
|
|
1258
1258
|
],
|
|
1259
1259
|
"additionalProperties": false
|
|
1260
1260
|
},
|
|
1261
|
+
"termly": {
|
|
1262
|
+
"type": "object",
|
|
1263
|
+
"properties": {
|
|
1264
|
+
"scriptSource": {
|
|
1265
|
+
"type": "string",
|
|
1266
|
+
"pattern": "^https://app\\.termly\\.io/resource-blocker/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}(\\?autoBlock=(on|off))?$"
|
|
1267
|
+
}
|
|
1268
|
+
},
|
|
1269
|
+
"required": [
|
|
1270
|
+
"scriptSource"
|
|
1271
|
+
],
|
|
1272
|
+
"additionalProperties": false
|
|
1273
|
+
},
|
|
1261
1274
|
"pirsch": {
|
|
1262
1275
|
"type": "object",
|
|
1263
1276
|
"properties": {
|
|
@@ -1345,12 +1358,18 @@
|
|
|
1345
1358
|
"type": "object",
|
|
1346
1359
|
"properties": {
|
|
1347
1360
|
"key": {
|
|
1348
|
-
"type": "string"
|
|
1361
|
+
"type": "string",
|
|
1362
|
+
"minLength": 1
|
|
1349
1363
|
},
|
|
1350
1364
|
"value": {
|
|
1351
|
-
"type": "string"
|
|
1365
|
+
"type": "string",
|
|
1366
|
+
"minLength": 1
|
|
1352
1367
|
}
|
|
1353
1368
|
},
|
|
1369
|
+
"required": [
|
|
1370
|
+
"key",
|
|
1371
|
+
"value"
|
|
1372
|
+
],
|
|
1354
1373
|
"additionalProperties": false
|
|
1355
1374
|
}
|
|
1356
1375
|
},
|
|
@@ -373,6 +373,9 @@
|
|
|
373
373
|
"cpu": [
|
|
374
374
|
"arm"
|
|
375
375
|
],
|
|
376
|
+
"libc": [
|
|
377
|
+
"glibc"
|
|
378
|
+
],
|
|
376
379
|
"license": "LGPL-3.0-or-later",
|
|
377
380
|
"optional": true,
|
|
378
381
|
"os": [
|
|
@@ -389,6 +392,9 @@
|
|
|
389
392
|
"cpu": [
|
|
390
393
|
"arm64"
|
|
391
394
|
],
|
|
395
|
+
"libc": [
|
|
396
|
+
"glibc"
|
|
397
|
+
],
|
|
392
398
|
"license": "LGPL-3.0-or-later",
|
|
393
399
|
"optional": true,
|
|
394
400
|
"os": [
|
|
@@ -405,6 +411,9 @@
|
|
|
405
411
|
"cpu": [
|
|
406
412
|
"ppc64"
|
|
407
413
|
],
|
|
414
|
+
"libc": [
|
|
415
|
+
"glibc"
|
|
416
|
+
],
|
|
408
417
|
"license": "LGPL-3.0-or-later",
|
|
409
418
|
"optional": true,
|
|
410
419
|
"os": [
|
|
@@ -421,6 +430,9 @@
|
|
|
421
430
|
"cpu": [
|
|
422
431
|
"riscv64"
|
|
423
432
|
],
|
|
433
|
+
"libc": [
|
|
434
|
+
"glibc"
|
|
435
|
+
],
|
|
424
436
|
"license": "LGPL-3.0-or-later",
|
|
425
437
|
"optional": true,
|
|
426
438
|
"os": [
|
|
@@ -437,6 +449,9 @@
|
|
|
437
449
|
"cpu": [
|
|
438
450
|
"s390x"
|
|
439
451
|
],
|
|
452
|
+
"libc": [
|
|
453
|
+
"glibc"
|
|
454
|
+
],
|
|
440
455
|
"license": "LGPL-3.0-or-later",
|
|
441
456
|
"optional": true,
|
|
442
457
|
"os": [
|
|
@@ -453,6 +468,9 @@
|
|
|
453
468
|
"cpu": [
|
|
454
469
|
"x64"
|
|
455
470
|
],
|
|
471
|
+
"libc": [
|
|
472
|
+
"glibc"
|
|
473
|
+
],
|
|
456
474
|
"license": "LGPL-3.0-or-later",
|
|
457
475
|
"optional": true,
|
|
458
476
|
"os": [
|
|
@@ -469,6 +487,9 @@
|
|
|
469
487
|
"cpu": [
|
|
470
488
|
"arm64"
|
|
471
489
|
],
|
|
490
|
+
"libc": [
|
|
491
|
+
"musl"
|
|
492
|
+
],
|
|
472
493
|
"license": "LGPL-3.0-or-later",
|
|
473
494
|
"optional": true,
|
|
474
495
|
"os": [
|
|
@@ -485,6 +506,9 @@
|
|
|
485
506
|
"cpu": [
|
|
486
507
|
"x64"
|
|
487
508
|
],
|
|
509
|
+
"libc": [
|
|
510
|
+
"musl"
|
|
511
|
+
],
|
|
488
512
|
"license": "LGPL-3.0-or-later",
|
|
489
513
|
"optional": true,
|
|
490
514
|
"os": [
|
|
@@ -501,6 +525,9 @@
|
|
|
501
525
|
"cpu": [
|
|
502
526
|
"arm"
|
|
503
527
|
],
|
|
528
|
+
"libc": [
|
|
529
|
+
"glibc"
|
|
530
|
+
],
|
|
504
531
|
"license": "Apache-2.0",
|
|
505
532
|
"optional": true,
|
|
506
533
|
"os": [
|
|
@@ -523,6 +550,9 @@
|
|
|
523
550
|
"cpu": [
|
|
524
551
|
"arm64"
|
|
525
552
|
],
|
|
553
|
+
"libc": [
|
|
554
|
+
"glibc"
|
|
555
|
+
],
|
|
526
556
|
"license": "Apache-2.0",
|
|
527
557
|
"optional": true,
|
|
528
558
|
"os": [
|
|
@@ -545,6 +575,9 @@
|
|
|
545
575
|
"cpu": [
|
|
546
576
|
"ppc64"
|
|
547
577
|
],
|
|
578
|
+
"libc": [
|
|
579
|
+
"glibc"
|
|
580
|
+
],
|
|
548
581
|
"license": "Apache-2.0",
|
|
549
582
|
"optional": true,
|
|
550
583
|
"os": [
|
|
@@ -567,6 +600,9 @@
|
|
|
567
600
|
"cpu": [
|
|
568
601
|
"riscv64"
|
|
569
602
|
],
|
|
603
|
+
"libc": [
|
|
604
|
+
"glibc"
|
|
605
|
+
],
|
|
570
606
|
"license": "Apache-2.0",
|
|
571
607
|
"optional": true,
|
|
572
608
|
"os": [
|
|
@@ -589,6 +625,9 @@
|
|
|
589
625
|
"cpu": [
|
|
590
626
|
"s390x"
|
|
591
627
|
],
|
|
628
|
+
"libc": [
|
|
629
|
+
"glibc"
|
|
630
|
+
],
|
|
592
631
|
"license": "Apache-2.0",
|
|
593
632
|
"optional": true,
|
|
594
633
|
"os": [
|
|
@@ -611,6 +650,9 @@
|
|
|
611
650
|
"cpu": [
|
|
612
651
|
"x64"
|
|
613
652
|
],
|
|
653
|
+
"libc": [
|
|
654
|
+
"glibc"
|
|
655
|
+
],
|
|
614
656
|
"license": "Apache-2.0",
|
|
615
657
|
"optional": true,
|
|
616
658
|
"os": [
|
|
@@ -633,6 +675,9 @@
|
|
|
633
675
|
"cpu": [
|
|
634
676
|
"arm64"
|
|
635
677
|
],
|
|
678
|
+
"libc": [
|
|
679
|
+
"musl"
|
|
680
|
+
],
|
|
636
681
|
"license": "Apache-2.0",
|
|
637
682
|
"optional": true,
|
|
638
683
|
"os": [
|
|
@@ -655,6 +700,9 @@
|
|
|
655
700
|
"cpu": [
|
|
656
701
|
"x64"
|
|
657
702
|
],
|
|
703
|
+
"libc": [
|
|
704
|
+
"musl"
|
|
705
|
+
],
|
|
658
706
|
"license": "Apache-2.0",
|
|
659
707
|
"optional": true,
|
|
660
708
|
"os": [
|
|
@@ -929,6 +977,9 @@
|
|
|
929
977
|
"cpu": [
|
|
930
978
|
"arm64"
|
|
931
979
|
],
|
|
980
|
+
"libc": [
|
|
981
|
+
"glibc"
|
|
982
|
+
],
|
|
932
983
|
"license": "MIT",
|
|
933
984
|
"optional": true,
|
|
934
985
|
"os": [
|
|
@@ -945,6 +996,9 @@
|
|
|
945
996
|
"cpu": [
|
|
946
997
|
"arm64"
|
|
947
998
|
],
|
|
999
|
+
"libc": [
|
|
1000
|
+
"musl"
|
|
1001
|
+
],
|
|
948
1002
|
"license": "MIT",
|
|
949
1003
|
"optional": true,
|
|
950
1004
|
"os": [
|
|
@@ -961,6 +1015,9 @@
|
|
|
961
1015
|
"cpu": [
|
|
962
1016
|
"x64"
|
|
963
1017
|
],
|
|
1018
|
+
"libc": [
|
|
1019
|
+
"glibc"
|
|
1020
|
+
],
|
|
964
1021
|
"license": "MIT",
|
|
965
1022
|
"optional": true,
|
|
966
1023
|
"os": [
|
|
@@ -977,6 +1034,9 @@
|
|
|
977
1034
|
"cpu": [
|
|
978
1035
|
"x64"
|
|
979
1036
|
],
|
|
1037
|
+
"libc": [
|
|
1038
|
+
"musl"
|
|
1039
|
+
],
|
|
980
1040
|
"license": "MIT",
|
|
981
1041
|
"optional": true,
|
|
982
1042
|
"os": [
|
|
@@ -1316,6 +1376,9 @@
|
|
|
1316
1376
|
"cpu": [
|
|
1317
1377
|
"arm64"
|
|
1318
1378
|
],
|
|
1379
|
+
"libc": [
|
|
1380
|
+
"glibc"
|
|
1381
|
+
],
|
|
1319
1382
|
"license": "MIT",
|
|
1320
1383
|
"optional": true,
|
|
1321
1384
|
"os": [
|
|
@@ -1332,6 +1395,9 @@
|
|
|
1332
1395
|
"cpu": [
|
|
1333
1396
|
"arm64"
|
|
1334
1397
|
],
|
|
1398
|
+
"libc": [
|
|
1399
|
+
"musl"
|
|
1400
|
+
],
|
|
1335
1401
|
"license": "MIT",
|
|
1336
1402
|
"optional": true,
|
|
1337
1403
|
"os": [
|
|
@@ -1348,6 +1414,9 @@
|
|
|
1348
1414
|
"cpu": [
|
|
1349
1415
|
"x64"
|
|
1350
1416
|
],
|
|
1417
|
+
"libc": [
|
|
1418
|
+
"glibc"
|
|
1419
|
+
],
|
|
1351
1420
|
"license": "MIT",
|
|
1352
1421
|
"optional": true,
|
|
1353
1422
|
"os": [
|
|
@@ -1364,6 +1433,9 @@
|
|
|
1364
1433
|
"cpu": [
|
|
1365
1434
|
"x64"
|
|
1366
1435
|
],
|
|
1436
|
+
"libc": [
|
|
1437
|
+
"musl"
|
|
1438
|
+
],
|
|
1367
1439
|
"license": "MIT",
|
|
1368
1440
|
"optional": true,
|
|
1369
1441
|
"os": [
|
|
@@ -2867,9 +2939,9 @@
|
|
|
2867
2939
|
"license": "MIT"
|
|
2868
2940
|
},
|
|
2869
2941
|
"node_modules/electron-to-chromium": {
|
|
2870
|
-
"version": "1.5.
|
|
2871
|
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.
|
|
2872
|
-
"integrity": "sha512-
|
|
2942
|
+
"version": "1.5.374",
|
|
2943
|
+
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.374.tgz",
|
|
2944
|
+
"integrity": "sha512-HCF5i7izveksHSGqa7mhDh6tr3Uz9Dar2RAjwuh69bw3QGPVObjQIgLwQWeO/Rxp9/r0KdboKy9RbpQDl97fjg==",
|
|
2873
2945
|
"license": "ISC"
|
|
2874
2946
|
},
|
|
2875
2947
|
"node_modules/enhanced-resolve": {
|
|
@@ -3865,6 +3937,9 @@
|
|
|
3865
3937
|
"cpu": [
|
|
3866
3938
|
"arm64"
|
|
3867
3939
|
],
|
|
3940
|
+
"libc": [
|
|
3941
|
+
"glibc"
|
|
3942
|
+
],
|
|
3868
3943
|
"license": "MPL-2.0",
|
|
3869
3944
|
"optional": true,
|
|
3870
3945
|
"os": [
|
|
@@ -3885,6 +3960,9 @@
|
|
|
3885
3960
|
"cpu": [
|
|
3886
3961
|
"arm64"
|
|
3887
3962
|
],
|
|
3963
|
+
"libc": [
|
|
3964
|
+
"musl"
|
|
3965
|
+
],
|
|
3888
3966
|
"license": "MPL-2.0",
|
|
3889
3967
|
"optional": true,
|
|
3890
3968
|
"os": [
|
|
@@ -3905,6 +3983,9 @@
|
|
|
3905
3983
|
"cpu": [
|
|
3906
3984
|
"x64"
|
|
3907
3985
|
],
|
|
3986
|
+
"libc": [
|
|
3987
|
+
"glibc"
|
|
3988
|
+
],
|
|
3908
3989
|
"license": "MPL-2.0",
|
|
3909
3990
|
"optional": true,
|
|
3910
3991
|
"os": [
|
|
@@ -3925,6 +4006,9 @@
|
|
|
3925
4006
|
"cpu": [
|
|
3926
4007
|
"x64"
|
|
3927
4008
|
],
|
|
4009
|
+
"libc": [
|
|
4010
|
+
"musl"
|
|
4011
|
+
],
|
|
3928
4012
|
"license": "MPL-2.0",
|
|
3929
4013
|
"optional": true,
|
|
3930
4014
|
"os": [
|