@caretcms/core 0.2.0 → 0.4.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 +195 -12
- package/dist/index.d.ts +26 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +113 -12
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +35 -3
- package/dist/loader.js.map +1 -1
- package/dist/markdown/paragraphs.d.ts +14 -0
- package/dist/markdown/paragraphs.d.ts.map +1 -0
- package/dist/markdown/paragraphs.js +61 -0
- package/dist/markdown/paragraphs.js.map +1 -0
- package/dist/markdown/remark.d.ts.map +1 -1
- package/dist/markdown/remark.js +1 -0
- package/dist/markdown/remark.js.map +1 -1
- package/dist/markdown/satteri.d.ts.map +1 -1
- package/dist/markdown/satteri.js +35 -9
- package/dist/markdown/satteri.js.map +1 -1
- package/dist/markdown/stamp.d.ts +0 -9
- package/dist/markdown/stamp.d.ts.map +1 -1
- package/dist/markdown/stamp.js +6 -0
- package/dist/markdown/stamp.js.map +1 -1
- package/dist/providers/deployment/github.d.ts +27 -0
- package/dist/providers/deployment/github.d.ts.map +1 -0
- package/dist/providers/deployment/github.js +180 -0
- package/dist/providers/deployment/github.js.map +1 -0
- package/dist/providers/deployment/simulated.d.ts +10 -0
- package/dist/providers/deployment/simulated.d.ts.map +1 -0
- package/dist/providers/deployment/simulated.js +29 -0
- package/dist/providers/deployment/simulated.js.map +1 -0
- package/dist/runtime/auth/session.d.ts +1 -0
- package/dist/runtime/auth/session.d.ts.map +1 -1
- package/dist/runtime/auth/session.js +16 -0
- package/dist/runtime/auth/session.js.map +1 -1
- package/dist/runtime/authorization.d.ts +11 -0
- package/dist/runtime/authorization.d.ts.map +1 -0
- package/dist/runtime/authorization.js +29 -0
- package/dist/runtime/authorization.js.map +1 -0
- package/dist/runtime/collection-policy.d.ts +11 -0
- package/dist/runtime/collection-policy.d.ts.map +1 -0
- package/dist/runtime/collection-policy.js +44 -0
- package/dist/runtime/collection-policy.js.map +1 -0
- package/dist/runtime/config.d.ts +3 -0
- package/dist/runtime/config.d.ts.map +1 -1
- package/dist/runtime/config.js +4 -1
- package/dist/runtime/config.js.map +1 -1
- package/dist/runtime/content-errors.d.ts +9 -0
- package/dist/runtime/content-errors.d.ts.map +1 -0
- package/dist/runtime/content-errors.js +17 -0
- package/dist/runtime/content-errors.js.map +1 -0
- package/dist/runtime/content.d.ts.map +1 -1
- package/dist/runtime/content.js +13 -4
- package/dist/runtime/content.js.map +1 -1
- package/dist/runtime/deployment-status.d.ts +14 -0
- package/dist/runtime/deployment-status.d.ts.map +1 -0
- package/dist/runtime/deployment-status.js +57 -0
- package/dist/runtime/deployment-status.js.map +1 -0
- package/dist/runtime/draft-state.d.ts +16 -0
- package/dist/runtime/draft-state.d.ts.map +1 -0
- package/dist/runtime/draft-state.js +29 -0
- package/dist/runtime/draft-state.js.map +1 -0
- package/dist/runtime/i18n.d.ts +97 -0
- package/dist/runtime/i18n.d.ts.map +1 -0
- package/dist/runtime/i18n.js +190 -0
- package/dist/runtime/i18n.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/middleware.d.ts.map +1 -1
- package/dist/runtime/middleware.js +61 -4
- package/dist/runtime/middleware.js.map +1 -1
- package/dist/runtime/mutations/contracts.d.ts +12 -0
- package/dist/runtime/mutations/contracts.d.ts.map +1 -1
- package/dist/runtime/mutations/contracts.js +54 -4
- package/dist/runtime/mutations/contracts.js.map +1 -1
- package/dist/runtime/mutations/engine.d.ts +2 -0
- package/dist/runtime/mutations/engine.d.ts.map +1 -1
- package/dist/runtime/mutations/engine.js +220 -57
- package/dist/runtime/mutations/engine.js.map +1 -1
- package/dist/runtime/providers.d.ts +4 -1
- package/dist/runtime/providers.d.ts.map +1 -1
- package/dist/runtime/providers.js +18 -1
- package/dist/runtime/providers.js.map +1 -1
- package/dist/runtime/publish-recovery.d.ts +32 -0
- package/dist/runtime/publish-recovery.d.ts.map +1 -0
- package/dist/runtime/publish-recovery.js +98 -0
- package/dist/runtime/publish-recovery.js.map +1 -0
- package/dist/runtime/publish.d.ts +10 -4
- package/dist/runtime/publish.d.ts.map +1 -1
- package/dist/runtime/publish.js +105 -63
- package/dist/runtime/publish.js.map +1 -1
- package/dist/runtime/rebuild-webhook.d.ts +4 -0
- package/dist/runtime/rebuild-webhook.d.ts.map +1 -1
- package/dist/runtime/rebuild-webhook.js +12 -2
- package/dist/runtime/rebuild-webhook.js.map +1 -1
- package/dist/runtime/request-context.d.ts +7 -1
- package/dist/runtime/request-context.d.ts.map +1 -1
- package/dist/runtime/request-context.js +7 -1
- package/dist/runtime/request-context.js.map +1 -1
- package/dist/runtime/rewrite.d.ts.map +1 -1
- package/dist/runtime/rewrite.js +28 -2
- package/dist/runtime/rewrite.js.map +1 -1
- package/dist/runtime/rich-allowlist.js +1 -1
- package/dist/runtime/rich-allowlist.js.map +1 -1
- package/dist/runtime/routes/admin-entry.d.ts.map +1 -1
- package/dist/runtime/routes/admin-entry.js +129 -21
- package/dist/runtime/routes/admin-entry.js.map +1 -1
- package/dist/runtime/routes/admin.d.ts.map +1 -1
- package/dist/runtime/routes/admin.js +28 -14
- package/dist/runtime/routes/admin.js.map +1 -1
- package/dist/runtime/routes/auth-login.d.ts.map +1 -1
- package/dist/runtime/routes/auth-login.js +4 -0
- package/dist/runtime/routes/auth-login.js.map +1 -1
- package/dist/runtime/routes/auth-logout.d.ts.map +1 -1
- package/dist/runtime/routes/auth-logout.js +7 -2
- package/dist/runtime/routes/auth-logout.js.map +1 -1
- package/dist/runtime/routes/auth-session.d.ts.map +1 -1
- package/dist/runtime/routes/auth-session.js +10 -2
- package/dist/runtime/routes/auth-session.js.map +1 -1
- package/dist/runtime/routes/collection-list.d.ts.map +1 -1
- package/dist/runtime/routes/collection-list.js +213 -66
- package/dist/runtime/routes/collection-list.js.map +1 -1
- package/dist/runtime/routes/deployment.d.ts +5 -0
- package/dist/runtime/routes/deployment.d.ts.map +1 -0
- package/dist/runtime/routes/deployment.js +38 -0
- package/dist/runtime/routes/deployment.js.map +1 -0
- package/dist/runtime/routes/draft.d.ts.map +1 -1
- package/dist/runtime/routes/draft.js +10 -3
- package/dist/runtime/routes/draft.js.map +1 -1
- package/dist/runtime/routes/entries.d.ts.map +1 -1
- package/dist/runtime/routes/entries.js +87 -43
- package/dist/runtime/routes/entries.js.map +1 -1
- package/dist/runtime/routes/history.d.ts.map +1 -1
- package/dist/runtime/routes/history.js +40 -21
- package/dist/runtime/routes/history.js.map +1 -1
- package/dist/runtime/routes/mutate.d.ts.map +1 -1
- package/dist/runtime/routes/mutate.js +4 -1
- package/dist/runtime/routes/mutate.js.map +1 -1
- package/dist/runtime/routes/publish.d.ts.map +1 -1
- package/dist/runtime/routes/publish.js +127 -33
- package/dist/runtime/routes/publish.js.map +1 -1
- package/dist/runtime/routes/schema.d.ts.map +1 -1
- package/dist/runtime/routes/schema.js +11 -2
- package/dist/runtime/routes/schema.js.map +1 -1
- package/dist/runtime/routes/studio-home.d.ts.map +1 -1
- package/dist/runtime/routes/studio-home.js +41 -20
- package/dist/runtime/routes/studio-home.js.map +1 -1
- package/dist/runtime/routes/upload.d.ts.map +1 -1
- package/dist/runtime/routes/upload.js +3 -0
- package/dist/runtime/routes/upload.js.map +1 -1
- package/dist/runtime/schema-registry.d.ts +8 -1
- package/dist/runtime/schema-registry.d.ts.map +1 -1
- package/dist/runtime/schema-registry.js +49 -3
- package/dist/runtime/schema-registry.js.map +1 -1
- package/dist/runtime/storage/entry-commit.d.ts +8 -0
- package/dist/runtime/storage/entry-commit.d.ts.map +1 -0
- package/dist/runtime/storage/entry-commit.js +45 -0
- package/dist/runtime/storage/entry-commit.js.map +1 -0
- package/dist/runtime/storage/filesystem-adapter.d.ts +5 -0
- package/dist/runtime/storage/filesystem-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/filesystem-adapter.js +12 -3
- package/dist/runtime/storage/filesystem-adapter.js.map +1 -1
- package/dist/runtime/storage/frontmatter-codec.d.ts +5 -23
- package/dist/runtime/storage/frontmatter-codec.d.ts.map +1 -1
- package/dist/runtime/storage/frontmatter-codec.js +156 -13
- package/dist/runtime/storage/frontmatter-codec.js.map +1 -1
- package/dist/runtime/storage/in-memory-adapter.d.ts +7 -0
- package/dist/runtime/storage/in-memory-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/in-memory-adapter.js +6 -0
- package/dist/runtime/storage/in-memory-adapter.js.map +1 -1
- package/dist/runtime/storage/markdown-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/markdown-adapter.js +18 -20
- package/dist/runtime/storage/markdown-adapter.js.map +1 -1
- package/dist/runtime/storage/session-overlay-adapter.d.ts +12 -4
- package/dist/runtime/storage/session-overlay-adapter.d.ts.map +1 -1
- package/dist/runtime/storage/session-overlay-adapter.js +100 -13
- package/dist/runtime/storage/session-overlay-adapter.js.map +1 -1
- package/dist/runtime/storage/sidecar-meta-store.d.ts +5 -0
- package/dist/runtime/storage/sidecar-meta-store.d.ts.map +1 -1
- package/dist/runtime/storage/sidecar-meta-store.js +48 -5
- package/dist/runtime/storage/sidecar-meta-store.js.map +1 -1
- package/dist/runtime/themes/preset-tokens.js +4 -4
- package/dist/runtime/themes/preset-tokens.js.map +1 -1
- package/dist/runtime/utils.d.ts.map +1 -1
- package/dist/runtime/utils.js +3 -4
- package/dist/runtime/utils.js.map +1 -1
- package/dist/runtime/views/studio-layout.d.ts +3 -0
- package/dist/runtime/views/studio-layout.d.ts.map +1 -1
- package/dist/runtime/views/studio-layout.js +36 -13
- package/dist/runtime/views/studio-layout.js.map +1 -1
- package/dist/schema-utils.d.ts +7 -0
- package/dist/schema-utils.d.ts.map +1 -1
- package/dist/schema-utils.js +143 -0
- package/dist/schema-utils.js.map +1 -1
- package/dist/types.d.ts +165 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -3
- package/static/cms/admin-entry.css +144 -13
- package/static/cms/admin-entry.js +539 -586
- package/static/cms/dev-toolbar/app.js +78 -19
- package/static/cms/editor/config.js +35 -15
- package/static/cms/editor/content-map.css +8 -1
- package/static/cms/editor/content-map.js +62 -23
- package/static/cms/editor/deployment-status.js +66 -0
- package/static/cms/editor/draft-client.js +87 -0
- package/static/cms/editor/guards.js +20 -0
- package/static/cms/editor/helpers.js +30 -1
- package/static/cms/editor/highlight.js +1 -0
- package/static/cms/editor/image-edit.js +44 -1
- package/static/cms/editor/image-utils.js +23 -7
- package/static/cms/editor/link-follow.js +122 -41
- package/static/cms/editor/link-ui.css +10 -1
- package/static/cms/editor/linkify.js +2 -0
- package/static/cms/editor/md-block-edit.js +140 -37
- package/static/cms/editor/md-paragraphs.js +98 -0
- package/static/cms/editor/md-serialize.js +1 -1
- package/static/cms/editor/panel.js +53 -7
- package/static/cms/editor/preview-mode.js +44 -0
- package/static/cms/editor/publish-result.js +100 -0
- package/static/cms/editor/rich-toolbar.js +58 -15
- package/static/cms/editor/sanitize.js +6 -2
- package/static/cms/editor/save-queue.js +75 -17
- package/static/cms/editor/section-controls/activation.js +3 -0
- package/static/cms/editor/section-controls/api.js +25 -7
- package/static/cms/editor/section-controls/index.js +60 -8
- package/static/cms/editor/section-controls/model.js +39 -4
- package/static/cms/editor/section-controls/mutations.js +15 -0
- package/static/cms/editor/section-controls/page-context.js +9 -0
- package/static/cms/editor/section-controls/pickers.js +53 -2
- package/static/cms/editor/section-controls/reorder.js +23 -0
- package/static/cms/editor/section-controls/selection.js +6 -0
- package/static/cms/editor/section-controls/spacing-drag.js +16 -0
- package/static/cms/editor/section-controls/ui-elements.js +7 -0
- package/static/cms/editor/section-controls/utils.js +7 -0
- package/static/cms/editor/section-controls.css +18 -3
- package/static/cms/editor/security.js +13 -2
- package/static/cms/editor/stega-hydrate.js +17 -4
- package/static/cms/editor/sync.js +475 -56
- package/static/cms/editor/text-edit.js +37 -3
- package/static/cms/editor/text-link-interactions.js +59 -17
- package/static/cms/editor/toast.js +23 -9
- package/static/cms/editor/tokens-and-text.css +9 -0
- package/static/cms/editor/toolbar.css +5 -0
- package/static/cms/editor/toolbar.js +91 -101
- package/static/cms/editor.css +1 -1
- package/static/cms/editor.js +1 -0
- package/static/cms/studio/entry-loader.js +102 -0
- package/static/cms/studio/field-model.js +110 -0
- package/static/cms/studio/fields.js +319 -0
- package/static/cms/studio/history-client.js +74 -0
- package/static/cms/studio/mutation-client.js +74 -0
- package/static/cms/studio/sync-client.js +107 -0
- package/static/cms/studio/upload-client.js +109 -0
- package/static/cms/studio-tokens.css +4 -4
- package/static/cms/studio.css +24 -0
|
@@ -1,33 +1,40 @@
|
|
|
1
1
|
import { SPACING_Y_VALUES } from './constants.js';
|
|
2
2
|
|
|
3
|
+
/** @param {string} key @returns {string} */
|
|
3
4
|
export function humanizeSectionKey(key) {
|
|
4
5
|
const short = key.startsWith('home.') ? key.slice('home.'.length) : key;
|
|
5
6
|
return short.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
|
|
6
7
|
}
|
|
7
8
|
|
|
9
|
+
/** @param {unknown} value @returns {string | undefined} */
|
|
8
10
|
export function normalizeSpacingY(value) {
|
|
9
11
|
if (typeof value !== 'string') return undefined;
|
|
10
12
|
return SPACING_Y_VALUES.includes(value) && value !== 'default' ? value : undefined;
|
|
11
13
|
}
|
|
12
14
|
|
|
15
|
+
/** @param {unknown} value @returns {string} */
|
|
13
16
|
export function spacingToken(value) {
|
|
14
17
|
return normalizeSpacingY(value) || 'default';
|
|
15
18
|
}
|
|
16
19
|
|
|
20
|
+
/** @param {unknown} value @returns {number} */
|
|
17
21
|
export function spacingIndex(value) {
|
|
18
22
|
const idx = SPACING_Y_VALUES.indexOf(spacingToken(value));
|
|
19
23
|
return idx === -1 ? 0 : idx;
|
|
20
24
|
}
|
|
21
25
|
|
|
26
|
+
/** @param {unknown} value @returns {string} */
|
|
22
27
|
export function spacingButtonLabel(value) {
|
|
23
28
|
const token = spacingToken(value);
|
|
24
29
|
return token === 'default' ? 'Space' : `Space:${token}`;
|
|
25
30
|
}
|
|
26
31
|
|
|
32
|
+
/** @param {unknown} value @returns {value is Record<string, unknown>} */
|
|
27
33
|
export function isRecord(value) {
|
|
28
34
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
29
35
|
}
|
|
30
36
|
|
|
37
|
+
/** @param {string} key @returns {string} */
|
|
31
38
|
export function generateSectionId(key) {
|
|
32
39
|
return `sec-${key.replace(/\./g, '-')}-${Date.now().toString(36)}-${Math.random()
|
|
33
40
|
.toString(36)
|
|
@@ -25,7 +25,6 @@
|
|
|
25
25
|
.cms-section-editable.cms-section-disabled-preview .cms-section-chip {
|
|
26
26
|
opacity: 1;
|
|
27
27
|
transform: translateY(0);
|
|
28
|
-
pointer-events: auto;
|
|
29
28
|
}
|
|
30
29
|
|
|
31
30
|
.cms-highlight-all .cms-section-editable {
|
|
@@ -57,7 +56,6 @@
|
|
|
57
56
|
.cms-section-controls:focus-within {
|
|
58
57
|
opacity: 1;
|
|
59
58
|
transform: translateY(0);
|
|
60
|
-
pointer-events: auto;
|
|
61
59
|
}
|
|
62
60
|
|
|
63
61
|
.cms-section-chip {
|
|
@@ -112,6 +110,14 @@
|
|
|
112
110
|
padding: 5px 7px;
|
|
113
111
|
cursor: pointer;
|
|
114
112
|
transition: all 0.16s ease;
|
|
113
|
+
pointer-events: none;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.cms-section-editable:hover .cms-section-btn,
|
|
117
|
+
.cms-section-editable.cms-section-active .cms-section-btn,
|
|
118
|
+
.cms-section-controls:focus-within .cms-section-btn,
|
|
119
|
+
.cms-section-editable.cms-section-disabled-preview .cms-section-btn {
|
|
120
|
+
pointer-events: auto;
|
|
115
121
|
}
|
|
116
122
|
|
|
117
123
|
.cms-section-btn:hover {
|
|
@@ -173,7 +179,6 @@ body.cms-section-dragging .cms-section-controls {
|
|
|
173
179
|
.cms-section-editable.cms-section-active .cms-section-boundary-actions,
|
|
174
180
|
body.cms-spacing-dragging .cms-section-boundary-actions {
|
|
175
181
|
opacity: 1;
|
|
176
|
-
pointer-events: auto;
|
|
177
182
|
}
|
|
178
183
|
|
|
179
184
|
.cms-section-insert-handle {
|
|
@@ -189,6 +194,7 @@ body.cms-spacing-dragging .cms-section-boundary-actions {
|
|
|
189
194
|
cursor: pointer;
|
|
190
195
|
box-shadow: 0 8px 18px rgba(0, 0, 0, 0.26);
|
|
191
196
|
transition: border-color 0.16s ease, transform 0.16s ease, background 0.16s ease;
|
|
197
|
+
pointer-events: none;
|
|
192
198
|
}
|
|
193
199
|
|
|
194
200
|
.cms-section-insert-plus {
|
|
@@ -224,6 +230,15 @@ body.cms-spacing-dragging .cms-section-boundary-actions {
|
|
|
224
230
|
cursor: ns-resize;
|
|
225
231
|
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
|
|
226
232
|
transition: border-color 0.16s ease, color 0.16s ease, background 0.16s ease;
|
|
233
|
+
pointer-events: none;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.cms-section-editable:hover .cms-section-insert-handle,
|
|
237
|
+
.cms-section-editable.cms-section-active .cms-section-insert-handle,
|
|
238
|
+
.cms-section-editable:hover .cms-section-gap-handle,
|
|
239
|
+
.cms-section-editable.cms-section-active .cms-section-gap-handle,
|
|
240
|
+
body.cms-spacing-dragging .cms-section-gap-handle {
|
|
241
|
+
pointer-events: auto;
|
|
227
242
|
}
|
|
228
243
|
|
|
229
244
|
.cms-section-gap-grip {
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
import { CLOUD, getCloudSessionToken, isCloudMode } from './config.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} action
|
|
5
|
+
* @returns {Promise<string | null>}
|
|
6
|
+
*/
|
|
3
7
|
async function getTurnstileToken(action) {
|
|
4
|
-
|
|
8
|
+
const getToken = /** @type {Window & { cmsGetTurnstileToken?: (action: string) => unknown }} */ (
|
|
9
|
+
window
|
|
10
|
+
).cmsGetTurnstileToken;
|
|
11
|
+
if (typeof getToken !== 'function') return null;
|
|
5
12
|
try {
|
|
6
|
-
|
|
13
|
+
const token = await getToken(action);
|
|
14
|
+
return typeof token === 'string' && token.trim() ? token.trim() : null;
|
|
7
15
|
} catch {
|
|
8
16
|
return null;
|
|
9
17
|
}
|
|
10
18
|
}
|
|
11
19
|
|
|
12
20
|
export async function mutateHeaders() {
|
|
21
|
+
/** @type {Record<string, string>} */
|
|
13
22
|
const headers = { 'Content-Type': 'application/json', 'x-caret-request': '1' };
|
|
14
23
|
if (isCloudMode()) {
|
|
15
24
|
if (CLOUD?.publicToken) headers['x-caret-token'] = CLOUD.publicToken;
|
|
@@ -24,6 +33,7 @@ export async function mutateHeaders() {
|
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
export function readHeaders() {
|
|
36
|
+
/** @type {Record<string, string>} */
|
|
27
37
|
const headers = {};
|
|
28
38
|
if (isCloudMode()) {
|
|
29
39
|
if (CLOUD?.publicToken) headers['x-caret-token'] = CLOUD.publicToken;
|
|
@@ -34,6 +44,7 @@ export function readHeaders() {
|
|
|
34
44
|
}
|
|
35
45
|
|
|
36
46
|
export async function uploadHeaders() {
|
|
47
|
+
/** @type {Record<string, string>} */
|
|
37
48
|
const headers = { 'x-caret-request': '1' };
|
|
38
49
|
if (isCloudMode()) {
|
|
39
50
|
if (CLOUD?.publicToken) headers['x-caret-token'] = CLOUD.publicToken;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* Decode logic mirrors runtime/stega.ts (the editor bundle is hand-authored JS,
|
|
13
13
|
* separate from the TS runtime, so the few lines are intentionally duplicated).
|
|
14
14
|
*/
|
|
15
|
+
import { parseCaretAttr } from './helpers.js';
|
|
15
16
|
|
|
16
17
|
const TAG_BASE = 0xe0000;
|
|
17
18
|
const TAG_MAX = 0xe007f;
|
|
@@ -19,12 +20,14 @@ const START = String.fromCodePoint(TAG_BASE + 0x00);
|
|
|
19
20
|
const END = String.fromCodePoint(TAG_BASE + 0x01);
|
|
20
21
|
const TAG_RE = /[\u{E0000}-\u{E007F}]/gu;
|
|
21
22
|
|
|
23
|
+
/** @param {string} b64 @returns {string} */
|
|
22
24
|
function fromBase64(b64) {
|
|
23
25
|
const binary = atob(b64);
|
|
24
26
|
const bytes = Uint8Array.from(binary, (c) => c.charCodeAt(0));
|
|
25
27
|
return new TextDecoder().decode(bytes);
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
/** @param {string} value @returns {unknown} */
|
|
28
31
|
export function stegaDecode(value) {
|
|
29
32
|
const start = value.indexOf(START);
|
|
30
33
|
if (start === -1) return undefined;
|
|
@@ -43,6 +46,7 @@ export function stegaDecode(value) {
|
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
|
|
49
|
+
/** @param {string} value @returns {string} */
|
|
46
50
|
export function stegaClean(value) {
|
|
47
51
|
return value.replace(TAG_RE, '');
|
|
48
52
|
}
|
|
@@ -51,28 +55,37 @@ export function stegaClean(value) {
|
|
|
51
55
|
* Find every stega-tagged text node under `root`, decode its key, strip the
|
|
52
56
|
* invisible characters, and tag the containing element with `data-caret`.
|
|
53
57
|
* Returns the number of elements newly promoted.
|
|
58
|
+
* @param {Node | null} [root]
|
|
59
|
+
* @returns {number}
|
|
54
60
|
*/
|
|
55
61
|
export function hydrateStega(root) {
|
|
56
62
|
const scope = root || document.body;
|
|
57
63
|
if (!scope) return 0;
|
|
58
64
|
|
|
59
65
|
const walker = document.createTreeWalker(scope, NodeFilter.SHOW_TEXT);
|
|
66
|
+
/** @type {Text[]} */
|
|
60
67
|
const tagged = [];
|
|
61
68
|
let node = walker.nextNode();
|
|
62
69
|
while (node) {
|
|
63
|
-
if (node.nodeValue && node.nodeValue.indexOf(START) !== -1)
|
|
70
|
+
if (node instanceof Text && node.nodeValue && node.nodeValue.indexOf(START) !== -1) {
|
|
71
|
+
tagged.push(node);
|
|
72
|
+
}
|
|
64
73
|
node = walker.nextNode();
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
let promoted = 0;
|
|
68
77
|
for (const textNode of tagged) {
|
|
69
|
-
const
|
|
78
|
+
const value = textNode.nodeValue || '';
|
|
79
|
+
const key = stegaDecode(value);
|
|
70
80
|
// Always strip the invisible characters so they never affect layout/copy.
|
|
71
|
-
textNode.nodeValue = stegaClean(
|
|
72
|
-
if (typeof key !== 'string'
|
|
81
|
+
textNode.nodeValue = stegaClean(value);
|
|
82
|
+
if (typeof key !== 'string') continue;
|
|
83
|
+
const binding = parseCaretAttr(key);
|
|
84
|
+
if (!binding?.collection || !binding.id) continue;
|
|
73
85
|
|
|
74
86
|
const el = textNode.parentElement;
|
|
75
87
|
if (!el || el.hasAttribute('data-caret')) continue; // explicit attr wins
|
|
88
|
+
if (el.closest('script, style, template, noscript')) continue;
|
|
76
89
|
el.setAttribute('data-caret', key);
|
|
77
90
|
promoted++;
|
|
78
91
|
}
|