mnfst 0.5.266 → 0.5.268
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/lib/manifest.data.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest.appwrite.auth.js": "sha384-gWLSeVPqCLMiUZB8MU7GqMg3x2yULFUsp8nTTZrPp/9Dlkix42rBn9yIimvwrHqZ",
|
|
3
|
-
"manifest.appwrite.data.js": "sha384-
|
|
3
|
+
"manifest.appwrite.data.js": "sha384-RH/7vbH/n5AA9HcChWPgenc/CLjTw0WmXhExvd9rPvpvLTHcn7a6XnbFj7WgTvh7",
|
|
4
4
|
"manifest.appwrite.presences.js": "sha384-/CagPsgWhO1sWEevCNGJmZ/ezRK9YCjLjvF7hxNSM4gVlJmEVtfSLfF7wnsRq441",
|
|
5
5
|
"manifest.bindings.js": "sha384-lPtMf8Ykaic9gNVZKq8Scia1881ZeMAyxer3WCIkUNwwrgzGBWto1OXADUwjvORF",
|
|
6
6
|
"manifest.charts.js": "sha384-AFbP7mQnigy7DU1s+YE30yKTeQAKfgNazhbfSNbfd9ZpLgeulZKaPi/fAq3gJHDO",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"manifest.combobox.js": "sha384-/lJo6vaxKjgnBSRs/dzkhK1dzGk3GBw8FISoNJZB70mwAVwu1k5veZyBXjOb4keS",
|
|
12
12
|
"manifest.components.js": "sha384-BUFA8h+G5Plr82sV7bKzO42pPoiRZwRQcKj1lt2ROFiKjjlkayU/vmkAFqEsdBA+",
|
|
13
13
|
"manifest.computed.js": "sha384-GYML/e81gQfN+iDbqhPUgny8bINCyL+SrbTofoGk4hlCnLLjv51mCv42JMqq+ku5",
|
|
14
|
-
"manifest.data.js": "sha384-
|
|
14
|
+
"manifest.data.js": "sha384-0zOYRKpPT5mGZjqprhfxadWH+wgMRZD6EfWoSUNToxUu8khleX0Is2yF8pItoLZ5",
|
|
15
15
|
"manifest.datepicker.js": "sha384-EzlMwvIxlla/0BuyhAEqxN0M8TGcWIWgEIg840V0akKQQK1uY648wPWMkobvtq/o",
|
|
16
16
|
"manifest.defer.js": "sha384-5cHzFTbx+cZmGpk9FuiUtW3ciC9NvvHwJeHP7xL5yiZVp9PhMWVdQ7L9y6ju2yoo",
|
|
17
17
|
"manifest.device.js": "sha384-YeQaS56L8IILqrQNBSeAOLwIh5DuAOrE60cYLK1+46qJtUrXlAvqGe2j5mbV4Vq7",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"manifest.export.js": "sha384-C4W5LrGQFnSILRWoWOCliajUK6rAzNW+EliogRx72vD1cUOYScSdfzHNbjSWv5XU",
|
|
21
21
|
"manifest.icons.js": "sha384-kKOINpX70YzNO3FvkV6umrmO3f0KIu0DNbwB+ej55a7y/lhU7v/myQtXL0bwCTbt",
|
|
22
22
|
"manifest.localization.js": "sha384-EImsIw8Z3l13V5eH9ZJF/yfsOfIvR1oPRNSArANkPji7V8O3IRf6zMwsNiAGj3Hk",
|
|
23
|
-
"manifest.markdown.js": "sha384-
|
|
23
|
+
"manifest.markdown.js": "sha384-icbpHC8dIijEJSaW3CODo4Ft7dBQz53pUh/2OYVBEFrLQbrFs370D+eMygJx5cW8",
|
|
24
24
|
"manifest.native.js": "sha384-YeQaS56L8IILqrQNBSeAOLwIh5DuAOrE60cYLK1+46qJtUrXlAvqGe2j5mbV4Vq7",
|
|
25
25
|
"manifest.payments.js": "sha384-8pofk2zhxtapPMpwnFyTelPMrYhShNhDCE722uQh/EYFvZFuPLmSdgunqsarVQjv",
|
|
26
26
|
"manifest.rich.text.js": "sha384-ZBV9jXmu2nmprEHicddRE/m7nR4RPZtVc969Jte0+EJYBcVph7itkjcgN/61PyeC",
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
"manifest.slides.js": "sha384-3uRTkyK9XPLmnxI2+igZlpi4EyPlU/7IHj5j3BZJJ2KN455vXyk99fiXV3feO/XY",
|
|
29
29
|
"manifest.status.js": "sha384-ofu7nBnVIGZ1U1o2R9d2H3V8aEMPUCVbl5FO3gIToXqi0oa36fTviEdh5UU7Kitw",
|
|
30
30
|
"manifest.svg.js": "sha384-qr/8H9+2cIhSXNbRWRtIdrDlTOxKlNJqwEefHvCYoiBNW/kKhPTFa109Orv/EBnb",
|
|
31
|
-
"manifest.sw.js": "sha384-
|
|
31
|
+
"manifest.sw.js": "sha384-hH5Xmqs5NY7oWLl+NYD6exIoqg9TDi8HPHB3Jg/sWnHEZUJWNJwlXlMkAvbCSfu5",
|
|
32
32
|
"manifest.tabs.js": "sha384-otU09H7jnawVKQdLAYpMCd3jx00tgyPVr42D2hLIBzN5dG4se505YesavdnMqEi1",
|
|
33
33
|
"manifest.tailwind.js": "sha384-yuP3LEvWU+QVjxjkZ0YhErtC9RrGmhOmHjjFjhS9obqZbp5/KTIEnSR0CXDvHE0B",
|
|
34
|
-
"manifest.toasts.js": "sha384-
|
|
34
|
+
"manifest.toasts.js": "sha384-UpOz9fAdGeGUhL0NamBg5iPepEfIy73p9HYdcxfOQC5b7CVsl7Our0skdZzaLNcC",
|
|
35
35
|
"manifest.tooltips.js": "sha384-hXGp5j0s6p2kGZY/hqLPEbaUv68ca63kFCjYiZqK3DcC12mpHTBy1vz3kuApyf4p",
|
|
36
36
|
"manifest.url.parameters.js": "sha384-J2aSVBOPsoqsbafHndrWLHEDpKb4AKJAoQnVmKA4gZh5P/8HHjFWHO/lkusmG84l",
|
|
37
37
|
"manifest.utilities.js": "sha384-h17EquaRtNcEW0yfhk7R+a+2+CzTlBxPuFryO6i9NV/OiIRMihREoyzQ77QawoQ7",
|
package/lib/manifest.markdown.js
CHANGED
|
@@ -15,15 +15,35 @@ if (typeof window !== 'undefined') {
|
|
|
15
15
|
});
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
//
|
|
19
|
-
// directive attributes to survive, but reject on* event handlers.
|
|
18
|
+
// .safe: HTML only (no SVG/MathML, custom elements, directives or handlers), minus page-level styling, forms and media
|
|
20
19
|
const MARKDOWN_PURIFY_CONFIG = {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
USE_PROFILES: { html: true },
|
|
21
|
+
FORBID_TAGS: ['style', 'form', 'template', 'dialog', 'video', 'audio'],
|
|
22
|
+
FORBID_ATTR: ['style', 'popover', 'popovertarget', 'popovertargetaction', 'formaction', 'command', 'commandfor', 'autoplay', 'background'],
|
|
23
|
+
ALLOW_DATA_ATTR: false,
|
|
24
|
+
SANITIZE_NAMED_PROPS: true
|
|
26
25
|
};
|
|
26
|
+
// Callout classes only; any other class could compile to a utility (fixed inset-0 …)
|
|
27
|
+
const MARKDOWN_SAFE_CLASSES = new Set(['brand', 'accent', 'positive', 'negative', 'frame']);
|
|
28
|
+
|
|
29
|
+
function restrictSafeClasses(html) {
|
|
30
|
+
const t = document.createElement('template');
|
|
31
|
+
t.innerHTML = html;
|
|
32
|
+
t.content.querySelectorAll('input[type="image" i]').forEach(el => el.remove());
|
|
33
|
+
t.content.querySelectorAll('[class]').forEach(el => {
|
|
34
|
+
const keep = el.tagName === 'ASIDE' ? [...el.classList].filter(c => MARKDOWN_SAFE_CLASSES.has(c)) : [];
|
|
35
|
+
if (keep.length) el.setAttribute('class', keep.join(' '));
|
|
36
|
+
else el.removeAttribute('class');
|
|
37
|
+
});
|
|
38
|
+
// Ids carry DOMPurify's user-content- prefix; follow it in in-content anchors
|
|
39
|
+
t.content.querySelectorAll('a[href^="#"]').forEach(a => {
|
|
40
|
+
const raw = a.getAttribute('href').slice(1);
|
|
41
|
+
let id;
|
|
42
|
+
try { id = decodeURIComponent(raw); } catch { id = raw; }
|
|
43
|
+
if (id && t.content.getElementById('user-content-' + id)) a.setAttribute('href', '#user-content-' + id);
|
|
44
|
+
});
|
|
45
|
+
return t.innerHTML;
|
|
46
|
+
}
|
|
27
47
|
|
|
28
48
|
// Shared DOMPurify loader on window (svg.js or markdown, whichever loads first).
|
|
29
49
|
// A top-level `let purifyPromise` would collide with svg.js's identical one.
|
|
@@ -64,7 +84,7 @@ async function maybeSanitizeMarkdownHtml(html, safe) {
|
|
|
64
84
|
if (!safe) return html;
|
|
65
85
|
try {
|
|
66
86
|
const DOMPurify = await window.ManifestDOMPurify.load();
|
|
67
|
-
return DOMPurify.sanitize(html, MARKDOWN_PURIFY_CONFIG);
|
|
87
|
+
return restrictSafeClasses(DOMPurify.sanitize(html, MARKDOWN_PURIFY_CONFIG));
|
|
68
88
|
} catch {
|
|
69
89
|
// Loader failure — escape rather than emit un-sanitized HTML (.safe was asked for).
|
|
70
90
|
const escaped = String(html)
|
|
@@ -243,10 +263,10 @@ async function configureMarked(marked) {
|
|
|
243
263
|
|
|
244
264
|
const iconHtml = iconValue ? `<span x-icon="${escapeForAttribute(iconValue)}"></span>` : '';
|
|
245
265
|
|
|
246
|
-
// Count top-level elements
|
|
247
|
-
const temp = document.createElement('
|
|
266
|
+
// Count top-level elements (inert parse: content isn't sanitized yet)
|
|
267
|
+
const temp = document.createElement('template');
|
|
248
268
|
temp.innerHTML = parsedContent;
|
|
249
|
-
const elementCount = temp.children.length;
|
|
269
|
+
const elementCount = temp.content.children.length;
|
|
250
270
|
|
|
251
271
|
// Wrap only when there's an icon plus 2+ elements (icon needs a sibling wrapper).
|
|
252
272
|
const needsWrapper = elementCount >= 2 && iconValue;
|
|
@@ -282,10 +302,10 @@ function renderXCodeGroup(markdown) {
|
|
|
282
302
|
|
|
283
303
|
// Enable task-list checkboxes by removing marked's disabled attribute.
|
|
284
304
|
function enableCheckboxes(html) {
|
|
285
|
-
const temp = document.createElement('
|
|
305
|
+
const temp = document.createElement('template');
|
|
286
306
|
temp.innerHTML = html;
|
|
287
307
|
|
|
288
|
-
const checkboxes = temp.querySelectorAll('input[type="checkbox"]');
|
|
308
|
+
const checkboxes = temp.content.querySelectorAll('input[type="checkbox"]');
|
|
289
309
|
checkboxes.forEach(checkbox => {
|
|
290
310
|
checkbox.removeAttribute('disabled');
|
|
291
311
|
});
|
package/lib/manifest.sw.js
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
|
|
17
17
|
// Build stamps the published version here; unstamped (dev) falls back to the
|
|
18
18
|
// registration URL's `v`, then 'dev'.
|
|
19
|
-
const BUILD_VERSION = '0.5.
|
|
19
|
+
const BUILD_VERSION = '0.5.268';
|
|
20
20
|
const CACHE_PREFIX = 'mnfst-sw:';
|
|
21
21
|
const META_CACHE = CACHE_PREFIX + 'meta';
|
|
22
22
|
// Sized to hold a full precache.json warm-up (PRECACHE_MAX_ENTRIES server-side)
|
package/lib/manifest.toasts.js
CHANGED
|
@@ -81,7 +81,7 @@ function initializeToastPlugin() {
|
|
|
81
81
|
};
|
|
82
82
|
|
|
83
83
|
// Helper function to show toast
|
|
84
|
-
const showToast = (message, { type = '', duration = TOAST_DURATION, dismissible = false, fixed = false, icon = null } = {}) => {
|
|
84
|
+
const showToast = (message, { type = '', duration = TOAST_DURATION, dismissible = false, fixed = false, icon = null, html = false } = {}) => {
|
|
85
85
|
const container = getContainer();
|
|
86
86
|
|
|
87
87
|
// Create toast element
|
|
@@ -99,12 +99,17 @@ function initializeToastPlugin() {
|
|
|
99
99
|
// Create content with optional icon
|
|
100
100
|
const contentHtml = `
|
|
101
101
|
${icon ? '<span class="toast-icon"></span>' : ''}
|
|
102
|
-
<div class="toast-content"
|
|
102
|
+
<div class="toast-content"></div>
|
|
103
103
|
${dismissible || fixed ? '<button class="toast-dismiss-button" aria-label="Dismiss"></button>' : ''}
|
|
104
104
|
`;
|
|
105
105
|
|
|
106
106
|
toast.innerHTML = contentHtml;
|
|
107
107
|
|
|
108
|
+
// Text by default; author markup and the html opt-in render as HTML
|
|
109
|
+
const content = toast.querySelector('.toast-content');
|
|
110
|
+
if (html) content.innerHTML = message;
|
|
111
|
+
else content.textContent = message;
|
|
112
|
+
|
|
108
113
|
// Add icon if specified
|
|
109
114
|
if (icon) {
|
|
110
115
|
const iconContainer = toast.querySelector('.toast-icon');
|
|
@@ -188,6 +193,7 @@ function initializeToastPlugin() {
|
|
|
188
193
|
dismissible: modifiers.includes('dismiss'),
|
|
189
194
|
fixed: modifiers.includes('fixed')
|
|
190
195
|
};
|
|
196
|
+
const htmlOptIn = modifiers.includes('html');
|
|
191
197
|
|
|
192
198
|
// Find duration modifier (any number)
|
|
193
199
|
const durationModifier = modifiers.find(mod => !isNaN(mod));
|
|
@@ -198,7 +204,7 @@ function initializeToastPlugin() {
|
|
|
198
204
|
}
|
|
199
205
|
|
|
200
206
|
// Static text (author HTML included) shows as written; expressions
|
|
201
|
-
// evaluate on every click. Empty results (null, false, '') show nothing.
|
|
207
|
+
// evaluate on every click as text unless .html. Empty results (null, false, '') show nothing.
|
|
202
208
|
const src = expression.trim();
|
|
203
209
|
const evaluate = expressionResolver(el, src, evaluateLater);
|
|
204
210
|
if (evaluate && src.startsWith('$x.')) evaluate(() => {}); // starts the source loading
|
|
@@ -211,12 +217,12 @@ function initializeToastPlugin() {
|
|
|
211
217
|
originalClick.call(el, e);
|
|
212
218
|
}
|
|
213
219
|
// Show toast after original handler
|
|
214
|
-
if (!evaluate) { showToast(expression, options); return; }
|
|
220
|
+
if (!evaluate) { showToast(expression, { ...options, html: true }); return; }
|
|
215
221
|
// After the element's other click listeners, so state they change shows
|
|
216
222
|
setTimeout(() => evaluate((v, asText) => {
|
|
217
|
-
if (asText) { showToast(expression, options); return; }
|
|
223
|
+
if (asText) { showToast(expression, { ...options, html: true }); return; }
|
|
218
224
|
const message = v == null || v === false ? '' : String(v);
|
|
219
|
-
if (message !== '') showToast(message, options);
|
|
225
|
+
if (message !== '') showToast(message, { ...options, html: htmlOptIn });
|
|
220
226
|
}));
|
|
221
227
|
};
|
|
222
228
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mnfst",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.268",
|
|
4
4
|
"private": false,
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"templates/starter",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"test:e2e:sw": "node tests/e2e/sw.e2e.mjs",
|
|
49
49
|
"test:e2e:settle": "node tests/e2e/render-settle.e2e.mjs",
|
|
50
50
|
"test:e2e:magic": "node tests/e2e/magic-one-arg.e2e.mjs",
|
|
51
|
+
"test:e2e:markdown-safe": "node tests/e2e/markdown-safe.e2e.mjs",
|
|
51
52
|
"test:e2e:upload": "node tests/e2e/upload-first-load.e2e.mjs",
|
|
52
53
|
"lint": "echo 'No linting configured'",
|
|
53
54
|
"release:docs": "node scripts/release-bump.mjs packages/docs && cd packages/docs && npm publish --auth-type=web",
|
|
@@ -60,6 +61,7 @@
|
|
|
60
61
|
"@tailwindcss/cli": "^4.2.4",
|
|
61
62
|
"alpinejs": "3.17.5",
|
|
62
63
|
"cssnano": "^7.1.1",
|
|
64
|
+
"dompurify": "3.4.10",
|
|
63
65
|
"entities": "4.5.0",
|
|
64
66
|
"glob": "^11.0.2",
|
|
65
67
|
"happy-dom": "^20.11.6",
|