mnfst 0.5.80 → 0.5.82
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 +1 -1
- package/lib/manifest.accordion.css +4 -4
- package/lib/manifest.appwrite.auth.js +66 -33
- package/lib/manifest.avatar.css +8 -8
- package/lib/manifest.button.css +7 -7
- package/lib/manifest.checkbox.css +5 -5
- package/lib/manifest.code.css +152 -193
- package/lib/manifest.code.js +841 -881
- package/lib/manifest.code.min.css +1 -1
- package/lib/manifest.colorpicker.css +11 -11
- package/lib/manifest.components.js +25 -155
- package/lib/manifest.css +278 -230
- package/lib/manifest.data.js +46 -2
- package/lib/manifest.dialog.css +2 -2
- package/lib/manifest.divider.css +2 -2
- package/lib/manifest.dropdown.css +9 -9
- package/lib/manifest.form.css +10 -10
- package/lib/manifest.input.css +9 -9
- package/lib/manifest.integrity.json +26 -0
- package/lib/manifest.js +60 -5
- package/lib/manifest.markdown.js +192 -79
- package/lib/manifest.min.css +1 -1
- package/lib/manifest.radio.css +1 -1
- package/lib/manifest.range.css +7 -7
- package/lib/manifest.resize.css +1 -1
- package/lib/manifest.router.js +49 -76
- package/lib/manifest.schema.json +1 -1
- package/lib/manifest.sidebar.css +5 -6
- package/lib/manifest.slides.css +5 -5
- package/lib/manifest.svg.js +75 -5
- package/lib/manifest.switch.css +4 -4
- package/lib/manifest.table.css +4 -4
- package/lib/manifest.theme.css +46 -41
- package/lib/manifest.toast.css +7 -7
- package/lib/manifest.tooltip.css +3 -3
- package/lib/manifest.tooltips.js +41 -0
- package/lib/manifest.typography.css +124 -69
- package/lib/manifest.utilities.css +48 -54
- package/lib/manifest.utilities.js +9 -29
- package/package.json +4 -7
- package/lib/manifest.export.js +0 -535
- package/lib/manifest.virtual.js +0 -319
package/lib/manifest.data.js
CHANGED
|
@@ -12,7 +12,9 @@ async function ensureManifest() {
|
|
|
12
12
|
try {
|
|
13
13
|
const manifestUrl = (document.querySelector('link[rel="manifest"]')?.getAttribute('href')) || '/manifest.json';
|
|
14
14
|
const response = await fetch(manifestUrl);
|
|
15
|
-
|
|
15
|
+
const manifest = await response.json();
|
|
16
|
+
interpolateManifest(manifest);
|
|
17
|
+
return manifest;
|
|
16
18
|
} catch (error) {
|
|
17
19
|
console.error('[Manifest Data] Failed to load manifest:', error);
|
|
18
20
|
return null;
|
|
@@ -36,6 +38,33 @@ function interpolateEnvVars(str) {
|
|
|
36
38
|
});
|
|
37
39
|
}
|
|
38
40
|
|
|
41
|
+
// Recursively walk a manifest object and interpolate every string value in
|
|
42
|
+
// place. Object keys are left untouched. Called once at manifest-load time so
|
|
43
|
+
// downstream consumers (auth, data, appwrite) read already-resolved values.
|
|
44
|
+
function interpolateManifest(obj) {
|
|
45
|
+
if (obj === null || typeof obj !== 'object') return obj;
|
|
46
|
+
if (Array.isArray(obj)) {
|
|
47
|
+
for (let i = 0; i < obj.length; i++) {
|
|
48
|
+
const v = obj[i];
|
|
49
|
+
if (typeof v === 'string') {
|
|
50
|
+
obj[i] = interpolateEnvVars(v);
|
|
51
|
+
} else if (v !== null && typeof v === 'object') {
|
|
52
|
+
interpolateManifest(v);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return obj;
|
|
56
|
+
}
|
|
57
|
+
for (const key of Object.keys(obj)) {
|
|
58
|
+
const v = obj[key];
|
|
59
|
+
if (typeof v === 'string') {
|
|
60
|
+
obj[key] = interpolateEnvVars(v);
|
|
61
|
+
} else if (v !== null && typeof v === 'object') {
|
|
62
|
+
interpolateManifest(v);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return obj;
|
|
66
|
+
}
|
|
67
|
+
|
|
39
68
|
// Helper to get nested value from object
|
|
40
69
|
function getNestedValue(obj, path) {
|
|
41
70
|
return path.split('.').reduce((current, key) => {
|
|
@@ -179,6 +208,7 @@ function getQueries(dataSource) {
|
|
|
179
208
|
window.ManifestDataConfig = {
|
|
180
209
|
ensureManifest,
|
|
181
210
|
interpolateEnvVars,
|
|
211
|
+
interpolateManifest,
|
|
182
212
|
getNestedValue,
|
|
183
213
|
getDefaultLocale,
|
|
184
214
|
parseContentPath,
|
|
@@ -1202,6 +1232,13 @@ window.ManifestDataStore = {
|
|
|
1202
1232
|
|
|
1203
1233
|
/* Manifest Data Sources - File Loaders */
|
|
1204
1234
|
|
|
1235
|
+
// Key names that would walk into Object's prototype chain if used as nested-
|
|
1236
|
+
// path segments. Rejecting them in setNestedValue and deepMergeWithFallback
|
|
1237
|
+
// prevents a CSV row like `__proto__.polluted, true` (or a malicious JSON
|
|
1238
|
+
// locale file containing `{"__proto__": {...}}`) from polluting
|
|
1239
|
+
// Object.prototype and silently affecting every plain object on the page.
|
|
1240
|
+
const POLLUTING_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
|
|
1241
|
+
|
|
1205
1242
|
// Dynamic js-yaml loader
|
|
1206
1243
|
let jsyaml = null;
|
|
1207
1244
|
let yamlLoadingPromise = null;
|
|
@@ -1336,6 +1373,7 @@ function deepMergeWithFallback(currentData, fallbackData) {
|
|
|
1336
1373
|
!Array.isArray(currentData) && !Array.isArray(fallbackData)) {
|
|
1337
1374
|
const merged = { ...fallbackData };
|
|
1338
1375
|
for (const key in currentData) {
|
|
1376
|
+
if (POLLUTING_KEYS.has(key)) continue;
|
|
1339
1377
|
if (key.startsWith('_')) {
|
|
1340
1378
|
// Preserve metadata from current locale
|
|
1341
1379
|
merged[key] = currentData[key];
|
|
@@ -1363,6 +1401,9 @@ function deepMergeWithFallback(currentData, fallbackData) {
|
|
|
1363
1401
|
// Numeric path segments (e.g. cards.0.title) create real arrays so x-for="card in $x....cards" works.
|
|
1364
1402
|
function setNestedValue(obj, path, value) {
|
|
1365
1403
|
const keys = path.split('.');
|
|
1404
|
+
// Drop the whole row if any segment would walk into the prototype chain.
|
|
1405
|
+
// `foo.constructor.prototype.polluted` is just as dangerous as `__proto__.polluted`.
|
|
1406
|
+
if (keys.some(k => POLLUTING_KEYS.has(k))) return;
|
|
1366
1407
|
let current = obj;
|
|
1367
1408
|
|
|
1368
1409
|
for (let i = 0; i < keys.length - 1; i++) {
|
|
@@ -11813,7 +11854,10 @@ async function initializeDataSourcesPlugin() {
|
|
|
11813
11854
|
const manifestData = manifest;
|
|
11814
11855
|
// Remove internal properties that shouldn't be exposed
|
|
11815
11856
|
const { data, appwrite, components, preloadedComponents, ...publicManifest } = manifestData;
|
|
11816
|
-
|
|
11857
|
+
// allowDuringInit: setIsInitializing(true) is active, so without this
|
|
11858
|
+
// flag updateStore short-circuits and $x.manifest stays unpopulated.
|
|
11859
|
+
window.ManifestDataStore.dataSourceCache.set(`manifest:${locale}`, publicManifest);
|
|
11860
|
+
updateStore('manifest', publicManifest, { loading: false, error: null, ready: true, allowDuringInit: true });
|
|
11817
11861
|
|
|
11818
11862
|
const store = Alpine.store('data');
|
|
11819
11863
|
Alpine.store('data', {
|
package/lib/manifest.dialog.css
CHANGED
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
min-height: 200px;
|
|
42
42
|
max-height: 90vh;
|
|
43
43
|
margin: auto;
|
|
44
|
-
color: var(--color-content-stark,
|
|
45
|
-
background-color: var(--color-popover-surface,
|
|
44
|
+
color: var(--color-content-stark, darkslategray);
|
|
45
|
+
background-color: var(--color-popover-surface, white);
|
|
46
46
|
border: 0 none;
|
|
47
47
|
border-radius: calc(var(--radius, 0.5rem) * 2);
|
|
48
48
|
box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
package/lib/manifest.divider.css
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
margin: var(--spacing-field-padding, 0.625rem) 0;
|
|
13
13
|
white-space: nowrap;
|
|
14
14
|
font-size: 0.875rem;
|
|
15
|
-
color: var(--color-content-neutral,
|
|
15
|
+
color: var(--color-content-neutral, gray);
|
|
16
16
|
|
|
17
17
|
/* Lines before and after content */
|
|
18
18
|
&:before,
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
flex: 1;
|
|
23
23
|
width: auto;
|
|
24
24
|
height: 1px;
|
|
25
|
-
background-color: var(--color-line,
|
|
25
|
+
background-color: var(--color-line, color-mix(darkslategray 10%, transparent))
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
/* Space between lines and content */
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
padding: 0.25rem;
|
|
46
46
|
z-index: 50;
|
|
47
47
|
list-style: none;
|
|
48
|
-
background: var(--color-popover-surface,
|
|
48
|
+
background: var(--color-popover-surface, white);
|
|
49
49
|
border: 0 none;
|
|
50
50
|
border-radius: var(--radius, 0.5rem);
|
|
51
51
|
box-shadow: rgba(15, 15, 15, 0.05) 0px 0px 0px 1px, rgba(15, 15, 15, 0.1) 0px 3px 6px, rgba(15, 15, 15, 0.2) 0px 9px 24px;
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
padding-inline-start: 0.5rem;
|
|
64
64
|
padding-inline-end: 0.5rem;
|
|
65
65
|
font-weight: normal;
|
|
66
|
-
color: var(--color-content-stark,
|
|
66
|
+
color: var(--color-content-stark, darkslategray);
|
|
67
67
|
text-align: start;
|
|
68
68
|
text-decoration: none;
|
|
69
69
|
text-overflow: ellipsis;
|
|
@@ -75,14 +75,14 @@
|
|
|
75
75
|
user-select: none;
|
|
76
76
|
|
|
77
77
|
&:hover {
|
|
78
|
-
color: var(--color-field-inverse,
|
|
78
|
+
color: var(--color-field-inverse, darkslategray);
|
|
79
79
|
text-decoration: inherit;
|
|
80
|
-
background-color: var(--color-field-surface,
|
|
80
|
+
background-color: var(--color-field-surface, color-mix(darkslategray 10%, transparent));
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
&:active {
|
|
84
|
-
color: var(--color-field-inverse,
|
|
85
|
-
background-color: var(--color-field-surface,
|
|
84
|
+
color: var(--color-field-inverse, darkslategray);
|
|
85
|
+
background-color: var(--color-field-surface, color-mix(darkslategray 10%, transparent));
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
& span,
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
/* Titles */
|
|
100
100
|
& small {
|
|
101
101
|
padding: 0.25rem 0.5rem;
|
|
102
|
-
color: var(--color-content-neutral,
|
|
102
|
+
color: var(--color-content-neutral, gray);
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/* Horizontal rules (offset to ignore menu padding) */
|
|
@@ -109,7 +109,7 @@
|
|
|
109
109
|
margin-inline-start: calc(0.25rem * -1);
|
|
110
110
|
margin-top: 0.25rem;
|
|
111
111
|
margin-bottom: 0.25rem;
|
|
112
|
-
background-color: var(--color-line,
|
|
112
|
+
background-color: var(--color-line, color-mix(darkslategray 10%, transparent));
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
/* Labels */
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
|
|
147
147
|
/* Dark theme */
|
|
148
148
|
:where(.dark menu[popover]) :where(li, a, button, label):hover {
|
|
149
|
-
background-color: var(--color-field-surface-hover,
|
|
149
|
+
background-color: var(--color-field-surface-hover, color-mix(darkslategray 15%, transparent));
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
/* Nested menu alignment */
|
package/lib/manifest.form.css
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
:where(form):not(.unstyle) {
|
|
48
48
|
display: flex;
|
|
49
49
|
flex-direction: column;
|
|
50
|
-
gap: calc(var(--spacing) * 4);
|
|
50
|
+
gap: calc(var(--spacing, 0.25rem) * 4);
|
|
51
51
|
width: 100%
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -55,25 +55,25 @@
|
|
|
55
55
|
:where(fieldset):not(.unstyle) {
|
|
56
56
|
display: flex;
|
|
57
57
|
flex-direction: column;
|
|
58
|
-
gap: 0.375ch calc(var(--spacing) * 2);
|
|
58
|
+
gap: 0.375ch calc(var(--spacing, 0.25rem) * 2);
|
|
59
59
|
width: 100%;
|
|
60
60
|
|
|
61
61
|
&:has([type=radio], [type=checkbox]) {
|
|
62
|
-
gap: calc(var(--spacing) * 2);
|
|
62
|
+
gap: calc(var(--spacing, 0.25rem) * 2);
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
:where(fieldset:has(legend)):not(.unstyle) {
|
|
67
67
|
padding: 1ch 1.5ch 1.5ch 1.5ch;
|
|
68
68
|
border-radius: var(--radius, 0.5rem);
|
|
69
|
-
border-color: var(--color-line,
|
|
69
|
+
border-color: var(--color-line, color-mix(darkslategray 10%, transparent));
|
|
70
70
|
border-style: solid;
|
|
71
71
|
border-width: 1px;
|
|
72
72
|
|
|
73
73
|
& :where(legend) {
|
|
74
74
|
padding: 0 1.5ch;
|
|
75
75
|
font-size: 0.875rem;
|
|
76
|
-
color: var(--color-content-subtle,
|
|
76
|
+
color: var(--color-content-subtle, darkgray);
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
flex-direction: column;
|
|
98
98
|
gap: 0.2ch;
|
|
99
99
|
width: 100%;
|
|
100
|
-
text-indent: calc(var(--radius) / 2);
|
|
100
|
+
text-indent: calc(var(--radius, 0.5rem) / 2);
|
|
101
101
|
cursor: pointer;
|
|
102
102
|
|
|
103
103
|
/* Prevent text indentation of bare label text nodes from being inherited */
|
|
@@ -107,7 +107,7 @@
|
|
|
107
107
|
|
|
108
108
|
/* Indent label text in spans */
|
|
109
109
|
:where(span:first-of-type) {
|
|
110
|
-
padding-inline-start: calc(var(--radius) / 2)
|
|
110
|
+
padding-inline-start: calc(var(--radius, 0.5rem) / 2)
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
:where(button, [role=button], [type=button], [type=submit], select, input:not([role=button], [type=checkbox], [type=radio], [type=file], [type=search]), textarea) {
|
|
@@ -136,13 +136,13 @@
|
|
|
136
136
|
|
|
137
137
|
/* Size buttons and inputs */
|
|
138
138
|
& :where(.label, button, input:not([type=checkbox], [type=radio]), select, textarea) {
|
|
139
|
-
width: calc(var(--spacing-field-height) * 8);
|
|
139
|
+
width: calc(var(--spacing-field-height, 2.25rem) * 8);
|
|
140
140
|
max-width: 50%;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
/* Focus state for .label wrapper for search and file inputs */
|
|
144
144
|
& .label:focus-within {
|
|
145
|
-
box-shadow: 0 0 0 2px color-mix(in oklch, var(--color-content-stark) 35%, transparent)
|
|
145
|
+
box-shadow: 0 0 0 2px color-mix(in oklch, var(--color-content-stark, darkslategray) 35%, transparent)
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
/* Align textarea label to top */
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
align-items: start;
|
|
151
151
|
|
|
152
152
|
:where(data) {
|
|
153
|
-
padding-top: calc(var(--spacing))
|
|
153
|
+
padding-top: calc(var(--spacing, 0.25rem))
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
}
|
package/lib/manifest.input.css
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
:where(input:not([type=range], [type=color]), textarea, label:has([type=search], [type=file]), .label:has([type=search], [type=file])):not(.unstyle) {
|
|
6
6
|
width: 100%;
|
|
7
7
|
max-width: 100%;
|
|
8
|
-
color: var(--color-field-inverse,
|
|
9
|
-
background-color: var(--color-field-surface,
|
|
8
|
+
color: var(--color-field-inverse, darkslategray);
|
|
9
|
+
background-color: var(--color-field-surface, color-mix(darkslategray 10%, transparent));
|
|
10
10
|
border-width: 0;
|
|
11
11
|
border-style: solid;
|
|
12
12
|
border-color: transparent;
|
|
@@ -16,23 +16,23 @@
|
|
|
16
16
|
appearance: none;
|
|
17
17
|
|
|
18
18
|
&:hover {
|
|
19
|
-
background-color: var(--color-field-surface-hover,
|
|
19
|
+
background-color: var(--color-field-surface-hover, color-mix(darkslategray 15%, transparent))
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
&:active {
|
|
23
|
-
background-color: var(--color-field-surface-hover,
|
|
23
|
+
background-color: var(--color-field-surface-hover, color-mix(darkslategray 15%, transparent))
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
&:focus-visible {
|
|
27
|
-
background-color: var(--color-field-surface,
|
|
27
|
+
background-color: var(--color-field-surface, color-mix(darkslategray 10%, transparent))
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
&::placeholder {
|
|
31
|
-
color: color-mix(in oklch, var(--color-field-inverse,
|
|
31
|
+
color: color-mix(in oklch, var(--color-field-inverse, darkslategray) 65%, transparent)
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
&::selection {
|
|
35
|
-
background-color: color-mix(in oklch, var(--color-field-surface,
|
|
35
|
+
background-color: color-mix(in oklch, var(--color-field-surface, color-mix(darkslategray 10%, transparent)) 80%, var(--color-field-inverse, darkslategray))
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
&[type=file] {
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
/* Additional styles for label with file input */
|
|
92
92
|
:where(label, .label):has([type=file]):not(.unstyle) {
|
|
93
93
|
justify-content: center;
|
|
94
|
-
gap: var(--spacing, 0.
|
|
94
|
+
gap: var(--spacing, 0.25rem);
|
|
95
95
|
height: var(--spacing-field-height, 2.25rem);
|
|
96
96
|
cursor: pointer
|
|
97
97
|
}
|
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
width: var(--spacing-field-height, 2.25rem);
|
|
109
109
|
height: 100%;
|
|
110
110
|
margin-inline-end: 0;
|
|
111
|
-
color: var(--color-content-subtle,
|
|
111
|
+
color: var(--color-content-subtle, darkgray)
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest.appwrite.auth.js": "sha384-to37ssZJXGeOS6+rf2VI47ox2mEqgsi5oQ1E5vv8XU/lDspbDFE1KHEMm8TxBhxW",
|
|
3
|
+
"manifest.appwrite.data.js": "sha384-00ulLT+GAIuPHA/rRT9p98vYlsyDzkyKXtg86BDQ6FGQa5vVVN+W6kuforniBAsz",
|
|
4
|
+
"manifest.appwrite.presence.js": "sha384-uxRpx9/Jj0kGtklH5QmUlAzD3zdSvFRfK6bcJQqxl+Bsf5tOo4zgwqJTQgtZoHQP",
|
|
5
|
+
"manifest.code.js": "sha384-7u03iKpTAimcMkf82glkELWzwDWRmlB9iYOC9tJ40gPH1QwyzdtFWA3OaSScJsFM",
|
|
6
|
+
"manifest.color.js": "sha384-Z9G/lzt0vVMxjz4wkPuGG1X9mmQAJR15aOoGX3ephf7r2wnlUWet5GLgkUMtT4vt",
|
|
7
|
+
"manifest.colorpicker.js": "sha384-0EVn+Ha06h7FIvOxc6WjZYnKYXzi+zba08yKvczSEGTRkWRxyKN2TFrZHI1SDCXu",
|
|
8
|
+
"manifest.colors.js": "sha384-u8iD6kapVj4OjeCILxBkYQKgXtDQ7LdEodILkQuknzPMwzSMBmDHN25UuzxepHby",
|
|
9
|
+
"manifest.components.js": "sha384-3dCTD5EwCZTiX+1obYtDNM3WWwPh2JDQUQQsdRUUK3gs6FXjse1ShkKaT/2jsNaI",
|
|
10
|
+
"manifest.data.js": "sha384-+wfMPBlMsmLJ7EJWGJMTKGAhLaLCyOVX+Nq+ps3Lly58QC9Dp3XRHK5yangII0yq",
|
|
11
|
+
"manifest.dropdowns.js": "sha384-WMrFoSpKfJuo81dyrwhVrDO8rq+rDwh2x8x4nH01BY5ZHkvjE+/SaT2gWCI0zOn+",
|
|
12
|
+
"manifest.icons.js": "sha384-uOkboYrovjCpl22eey3Jaxpey+pOnot5NDnRRumcRxiR7IOVaRh1i20gYnWXR5dW",
|
|
13
|
+
"manifest.localization.js": "sha384-eKdBIMEAwsugPP2p2fuPzQUkU44f1+Y0JgukMJ1KXLQY1/AYvpcGsEiritVDElsN",
|
|
14
|
+
"manifest.markdown.js": "sha384-5dpYLup1j/JLmoVvE1Qn47rwYwtU6kH2PvuiNzU1nqa0LMRWZhdnKhKO7I3I0cyI",
|
|
15
|
+
"manifest.resize.js": "sha384-Ak5gf44ERfh9pOSAD1qZzJSysslpwBCkevIlz7R3dszTUyzUKGKGF4pn5arOtgG0",
|
|
16
|
+
"manifest.router.js": "sha384-n6xmIfWnYzd/0kkVTFuHhFzHuxiDgZ1Lg1W0yB6/w3Myw5pQ6PgE6SJBHfVsO7/D",
|
|
17
|
+
"manifest.slides.js": "sha384-3uRTkyK9XPLmnxI2+igZlpi4EyPlU/7IHj5j3BZJJ2KN455vXyk99fiXV3feO/XY",
|
|
18
|
+
"manifest.svg.js": "sha384-nc+3spSGNS2l+82maL/OFz2iOGUhLZ0kqeooj28CEcdElM4OZa34e0tbnokZHVI6",
|
|
19
|
+
"manifest.tabs.js": "sha384-v6Ti0zHfdLhkFHbTMg0FH6uMrThuBvZrL2PQgVBeeXhDjuN7x4MtoNWogPbAQTaD",
|
|
20
|
+
"manifest.tailwind.js": "sha384-aHLvl2oSuUgy06VaBqhhByn5wWxqvnqxw6KCwehakKUS00F/s/Nb62umeASS6Y4P",
|
|
21
|
+
"manifest.toasts.js": "sha384-ytd5rDbax/Ou9z23uedFXPZbxDPsk2E/pxCTq4WLvfv+os1qTI6kELp0kPp07g24",
|
|
22
|
+
"manifest.tooltips.js": "sha384-Hhip5ZN66xhDw3m0XBrKLKLpcVRz3Z9RszPKqo6xvFF0mrUgQBVZ+mZjZsXgOOjS",
|
|
23
|
+
"manifest.url.parameters.js": "sha384-FIufiClqDx1rJpU/QUc9z/D43qClQ6Qm8rBahipbJl9BDHUvhrOsUDegmTWW7Tuf",
|
|
24
|
+
"manifest.utilities.js": "sha384-Q98oZClq/iRKFmuwHolisLgEitsTZiEPHxUW29liKlnL1Gx+YGq8MMivYbDlGDD6",
|
|
25
|
+
"manifest.js": "sha384-M0y6toAEVWcozOx0D6eVdOiYOgF4f3nJyNmvfvh+/sr8gcMiugytOIC9FZ22NC8H"
|
|
26
|
+
}
|
package/lib/manifest.js
CHANGED
|
@@ -175,6 +175,41 @@
|
|
|
175
175
|
const DEFAULT_VERSION = 'latest';
|
|
176
176
|
const ALPINE_CDN_URL = 'https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js';
|
|
177
177
|
|
|
178
|
+
// SRI integrity map: { 'manifest.foo.min.js': 'sha384-...', ... }
|
|
179
|
+
// Inlined by build.mjs's emitIntegrityMap() step. Empty in source so the
|
|
180
|
+
// unbuilt loader works in dev (where files are served from the local
|
|
181
|
+
// project, same-origin, no SRI needed). Built artifact in lib/ carries
|
|
182
|
+
// the populated map. Looked up by the filename suffix of every script URL
|
|
183
|
+
// addScript() injects — when the file is in the map, the matching
|
|
184
|
+
// integrity + crossorigin attributes are set, and the browser refuses to
|
|
185
|
+
// execute the script if the bytes don't match (defends against CDN
|
|
186
|
+
// poisoning / npm hijack).
|
|
187
|
+
const INTEGRITY = {
|
|
188
|
+
"manifest.appwrite.auth.js": "sha384-to37ssZJXGeOS6+rf2VI47ox2mEqgsi5oQ1E5vv8XU/lDspbDFE1KHEMm8TxBhxW",
|
|
189
|
+
"manifest.appwrite.data.js": "sha384-00ulLT+GAIuPHA/rRT9p98vYlsyDzkyKXtg86BDQ6FGQa5vVVN+W6kuforniBAsz",
|
|
190
|
+
"manifest.appwrite.presence.js": "sha384-uxRpx9/Jj0kGtklH5QmUlAzD3zdSvFRfK6bcJQqxl+Bsf5tOo4zgwqJTQgtZoHQP",
|
|
191
|
+
"manifest.code.js": "sha384-7u03iKpTAimcMkf82glkELWzwDWRmlB9iYOC9tJ40gPH1QwyzdtFWA3OaSScJsFM",
|
|
192
|
+
"manifest.color.js": "sha384-Z9G/lzt0vVMxjz4wkPuGG1X9mmQAJR15aOoGX3ephf7r2wnlUWet5GLgkUMtT4vt",
|
|
193
|
+
"manifest.colorpicker.js": "sha384-0EVn+Ha06h7FIvOxc6WjZYnKYXzi+zba08yKvczSEGTRkWRxyKN2TFrZHI1SDCXu",
|
|
194
|
+
"manifest.colors.js": "sha384-u8iD6kapVj4OjeCILxBkYQKgXtDQ7LdEodILkQuknzPMwzSMBmDHN25UuzxepHby",
|
|
195
|
+
"manifest.components.js": "sha384-3dCTD5EwCZTiX+1obYtDNM3WWwPh2JDQUQQsdRUUK3gs6FXjse1ShkKaT/2jsNaI",
|
|
196
|
+
"manifest.data.js": "sha384-+wfMPBlMsmLJ7EJWGJMTKGAhLaLCyOVX+Nq+ps3Lly58QC9Dp3XRHK5yangII0yq",
|
|
197
|
+
"manifest.dropdowns.js": "sha384-WMrFoSpKfJuo81dyrwhVrDO8rq+rDwh2x8x4nH01BY5ZHkvjE+/SaT2gWCI0zOn+",
|
|
198
|
+
"manifest.icons.js": "sha384-uOkboYrovjCpl22eey3Jaxpey+pOnot5NDnRRumcRxiR7IOVaRh1i20gYnWXR5dW",
|
|
199
|
+
"manifest.localization.js": "sha384-eKdBIMEAwsugPP2p2fuPzQUkU44f1+Y0JgukMJ1KXLQY1/AYvpcGsEiritVDElsN",
|
|
200
|
+
"manifest.markdown.js": "sha384-5dpYLup1j/JLmoVvE1Qn47rwYwtU6kH2PvuiNzU1nqa0LMRWZhdnKhKO7I3I0cyI",
|
|
201
|
+
"manifest.resize.js": "sha384-Ak5gf44ERfh9pOSAD1qZzJSysslpwBCkevIlz7R3dszTUyzUKGKGF4pn5arOtgG0",
|
|
202
|
+
"manifest.router.js": "sha384-n6xmIfWnYzd/0kkVTFuHhFzHuxiDgZ1Lg1W0yB6/w3Myw5pQ6PgE6SJBHfVsO7/D",
|
|
203
|
+
"manifest.slides.js": "sha384-3uRTkyK9XPLmnxI2+igZlpi4EyPlU/7IHj5j3BZJJ2KN455vXyk99fiXV3feO/XY",
|
|
204
|
+
"manifest.svg.js": "sha384-nc+3spSGNS2l+82maL/OFz2iOGUhLZ0kqeooj28CEcdElM4OZa34e0tbnokZHVI6",
|
|
205
|
+
"manifest.tabs.js": "sha384-v6Ti0zHfdLhkFHbTMg0FH6uMrThuBvZrL2PQgVBeeXhDjuN7x4MtoNWogPbAQTaD",
|
|
206
|
+
"manifest.tailwind.js": "sha384-aHLvl2oSuUgy06VaBqhhByn5wWxqvnqxw6KCwehakKUS00F/s/Nb62umeASS6Y4P",
|
|
207
|
+
"manifest.toasts.js": "sha384-ytd5rDbax/Ou9z23uedFXPZbxDPsk2E/pxCTq4WLvfv+os1qTI6kELp0kPp07g24",
|
|
208
|
+
"manifest.tooltips.js": "sha384-Hhip5ZN66xhDw3m0XBrKLKLpcVRz3Z9RszPKqo6xvFF0mrUgQBVZ+mZjZsXgOOjS",
|
|
209
|
+
"manifest.url.parameters.js": "sha384-FIufiClqDx1rJpU/QUc9z/D43qClQ6Qm8rBahipbJl9BDHUvhrOsUDegmTWW7Tuf",
|
|
210
|
+
"manifest.utilities.js": "sha384-Q98oZClq/iRKFmuwHolisLgEitsTZiEPHxUW29liKlnL1Gx+YGq8MMivYbDlGDD6"
|
|
211
|
+
};
|
|
212
|
+
|
|
178
213
|
// Get base URL for a given version
|
|
179
214
|
function getBaseUrl(version = DEFAULT_VERSION) {
|
|
180
215
|
return `https://cdn.jsdelivr.net/npm/mnfst@${version}/lib`;
|
|
@@ -199,9 +234,7 @@
|
|
|
199
234
|
'slides',
|
|
200
235
|
'resize',
|
|
201
236
|
'colorpicker',
|
|
202
|
-
'url-parameters'
|
|
203
|
-
'virtual',
|
|
204
|
-
'export'
|
|
237
|
+
'url-parameters'
|
|
205
238
|
];
|
|
206
239
|
|
|
207
240
|
// Appwrite integration plugins (opt-in only, never auto-loaded)
|
|
@@ -211,10 +244,16 @@
|
|
|
211
244
|
'appwrite-presence'
|
|
212
245
|
];
|
|
213
246
|
|
|
214
|
-
// Plugin dependencies: plugins that require other plugins to be loaded first
|
|
247
|
+
// Plugin dependencies: plugins that require other plugins to be loaded first.
|
|
248
|
+
// All Appwrite plugins depend on `data` for env-var interpolation at
|
|
249
|
+
// manifest-load time (window.ManifestDataConfig.interpolateManifest); auth
|
|
250
|
+
// and presence also share the data plugin's manifest-fetch plumbing.
|
|
251
|
+
// Localization reads data-source URLs that may carry ${VAR} references.
|
|
215
252
|
const PLUGIN_DEPENDENCIES = {
|
|
253
|
+
'appwrite-auth': ['data'],
|
|
216
254
|
'appwrite-data': ['data'],
|
|
217
|
-
'appwrite-presence': ['data']
|
|
255
|
+
'appwrite-presence': ['data'],
|
|
256
|
+
'localization': ['data']
|
|
218
257
|
};
|
|
219
258
|
|
|
220
259
|
// Derive default plugin list from manifest (only load data/localization/components when manifest needs them)
|
|
@@ -315,6 +354,15 @@
|
|
|
315
354
|
const script = document.createElement('script');
|
|
316
355
|
script.src = url;
|
|
317
356
|
script.async = false; // Ensure scripts execute in order
|
|
357
|
+
// Apply SRI when the file is in the inlined integrity map. The map
|
|
358
|
+
// keys files by basename, so it works whether the URL points at
|
|
359
|
+
// jsDelivr or a user-configured pluginBase mirror — as long as the
|
|
360
|
+
// served bytes match what this loader version was built against.
|
|
361
|
+
const fileName = url.split('/').pop().split('?')[0];
|
|
362
|
+
if (INTEGRITY[fileName]) {
|
|
363
|
+
script.integrity = INTEGRITY[fileName];
|
|
364
|
+
script.crossOrigin = 'anonymous';
|
|
365
|
+
}
|
|
318
366
|
script.onload = () => resolve();
|
|
319
367
|
script.onerror = () => reject(new Error(`Failed to load ${pluginName} from ${url}`));
|
|
320
368
|
document.head.appendChild(script);
|
|
@@ -522,6 +570,13 @@
|
|
|
522
570
|
manifest = await manifestPromise;
|
|
523
571
|
}
|
|
524
572
|
if (manifest && typeof window !== 'undefined') {
|
|
573
|
+
// Resolve ${VAR} env-var references once, at the canonical load
|
|
574
|
+
// point, so downstream plugins (auth, data, appwrite) read
|
|
575
|
+
// already-interpolated values instead of each handling env-var
|
|
576
|
+
// substitution themselves.
|
|
577
|
+
if (window.ManifestDataConfig?.interpolateManifest) {
|
|
578
|
+
window.ManifestDataConfig.interpolateManifest(manifest);
|
|
579
|
+
}
|
|
525
580
|
window.__manifestLoaded = manifest;
|
|
526
581
|
if (window.ManifestComponentsRegistry) {
|
|
527
582
|
window.ManifestComponentsRegistry.manifest = manifest;
|