@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.
Files changed (256) hide show
  1. package/README.md +195 -12
  2. package/dist/index.d.ts +26 -2
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +113 -12
  5. package/dist/index.js.map +1 -1
  6. package/dist/loader.d.ts.map +1 -1
  7. package/dist/loader.js +35 -3
  8. package/dist/loader.js.map +1 -1
  9. package/dist/markdown/paragraphs.d.ts +14 -0
  10. package/dist/markdown/paragraphs.d.ts.map +1 -0
  11. package/dist/markdown/paragraphs.js +61 -0
  12. package/dist/markdown/paragraphs.js.map +1 -0
  13. package/dist/markdown/remark.d.ts.map +1 -1
  14. package/dist/markdown/remark.js +1 -0
  15. package/dist/markdown/remark.js.map +1 -1
  16. package/dist/markdown/satteri.d.ts.map +1 -1
  17. package/dist/markdown/satteri.js +35 -9
  18. package/dist/markdown/satteri.js.map +1 -1
  19. package/dist/markdown/stamp.d.ts +0 -9
  20. package/dist/markdown/stamp.d.ts.map +1 -1
  21. package/dist/markdown/stamp.js +6 -0
  22. package/dist/markdown/stamp.js.map +1 -1
  23. package/dist/providers/deployment/github.d.ts +27 -0
  24. package/dist/providers/deployment/github.d.ts.map +1 -0
  25. package/dist/providers/deployment/github.js +180 -0
  26. package/dist/providers/deployment/github.js.map +1 -0
  27. package/dist/providers/deployment/simulated.d.ts +10 -0
  28. package/dist/providers/deployment/simulated.d.ts.map +1 -0
  29. package/dist/providers/deployment/simulated.js +29 -0
  30. package/dist/providers/deployment/simulated.js.map +1 -0
  31. package/dist/runtime/auth/session.d.ts +1 -0
  32. package/dist/runtime/auth/session.d.ts.map +1 -1
  33. package/dist/runtime/auth/session.js +16 -0
  34. package/dist/runtime/auth/session.js.map +1 -1
  35. package/dist/runtime/authorization.d.ts +11 -0
  36. package/dist/runtime/authorization.d.ts.map +1 -0
  37. package/dist/runtime/authorization.js +29 -0
  38. package/dist/runtime/authorization.js.map +1 -0
  39. package/dist/runtime/collection-policy.d.ts +11 -0
  40. package/dist/runtime/collection-policy.d.ts.map +1 -0
  41. package/dist/runtime/collection-policy.js +44 -0
  42. package/dist/runtime/collection-policy.js.map +1 -0
  43. package/dist/runtime/config.d.ts +3 -0
  44. package/dist/runtime/config.d.ts.map +1 -1
  45. package/dist/runtime/config.js +4 -1
  46. package/dist/runtime/config.js.map +1 -1
  47. package/dist/runtime/content-errors.d.ts +9 -0
  48. package/dist/runtime/content-errors.d.ts.map +1 -0
  49. package/dist/runtime/content-errors.js +17 -0
  50. package/dist/runtime/content-errors.js.map +1 -0
  51. package/dist/runtime/content.d.ts.map +1 -1
  52. package/dist/runtime/content.js +13 -4
  53. package/dist/runtime/content.js.map +1 -1
  54. package/dist/runtime/deployment-status.d.ts +14 -0
  55. package/dist/runtime/deployment-status.d.ts.map +1 -0
  56. package/dist/runtime/deployment-status.js +57 -0
  57. package/dist/runtime/deployment-status.js.map +1 -0
  58. package/dist/runtime/draft-state.d.ts +16 -0
  59. package/dist/runtime/draft-state.d.ts.map +1 -0
  60. package/dist/runtime/draft-state.js +29 -0
  61. package/dist/runtime/draft-state.js.map +1 -0
  62. package/dist/runtime/i18n.d.ts +97 -0
  63. package/dist/runtime/i18n.d.ts.map +1 -0
  64. package/dist/runtime/i18n.js +190 -0
  65. package/dist/runtime/i18n.js.map +1 -0
  66. package/dist/runtime/index.d.ts +1 -0
  67. package/dist/runtime/index.d.ts.map +1 -1
  68. package/dist/runtime/index.js +1 -0
  69. package/dist/runtime/index.js.map +1 -1
  70. package/dist/runtime/middleware.d.ts.map +1 -1
  71. package/dist/runtime/middleware.js +61 -4
  72. package/dist/runtime/middleware.js.map +1 -1
  73. package/dist/runtime/mutations/contracts.d.ts +12 -0
  74. package/dist/runtime/mutations/contracts.d.ts.map +1 -1
  75. package/dist/runtime/mutations/contracts.js +54 -4
  76. package/dist/runtime/mutations/contracts.js.map +1 -1
  77. package/dist/runtime/mutations/engine.d.ts +2 -0
  78. package/dist/runtime/mutations/engine.d.ts.map +1 -1
  79. package/dist/runtime/mutations/engine.js +220 -57
  80. package/dist/runtime/mutations/engine.js.map +1 -1
  81. package/dist/runtime/providers.d.ts +4 -1
  82. package/dist/runtime/providers.d.ts.map +1 -1
  83. package/dist/runtime/providers.js +18 -1
  84. package/dist/runtime/providers.js.map +1 -1
  85. package/dist/runtime/publish-recovery.d.ts +32 -0
  86. package/dist/runtime/publish-recovery.d.ts.map +1 -0
  87. package/dist/runtime/publish-recovery.js +98 -0
  88. package/dist/runtime/publish-recovery.js.map +1 -0
  89. package/dist/runtime/publish.d.ts +10 -4
  90. package/dist/runtime/publish.d.ts.map +1 -1
  91. package/dist/runtime/publish.js +105 -63
  92. package/dist/runtime/publish.js.map +1 -1
  93. package/dist/runtime/rebuild-webhook.d.ts +4 -0
  94. package/dist/runtime/rebuild-webhook.d.ts.map +1 -1
  95. package/dist/runtime/rebuild-webhook.js +12 -2
  96. package/dist/runtime/rebuild-webhook.js.map +1 -1
  97. package/dist/runtime/request-context.d.ts +7 -1
  98. package/dist/runtime/request-context.d.ts.map +1 -1
  99. package/dist/runtime/request-context.js +7 -1
  100. package/dist/runtime/request-context.js.map +1 -1
  101. package/dist/runtime/rewrite.d.ts.map +1 -1
  102. package/dist/runtime/rewrite.js +28 -2
  103. package/dist/runtime/rewrite.js.map +1 -1
  104. package/dist/runtime/rich-allowlist.js +1 -1
  105. package/dist/runtime/rich-allowlist.js.map +1 -1
  106. package/dist/runtime/routes/admin-entry.d.ts.map +1 -1
  107. package/dist/runtime/routes/admin-entry.js +129 -21
  108. package/dist/runtime/routes/admin-entry.js.map +1 -1
  109. package/dist/runtime/routes/admin.d.ts.map +1 -1
  110. package/dist/runtime/routes/admin.js +28 -14
  111. package/dist/runtime/routes/admin.js.map +1 -1
  112. package/dist/runtime/routes/auth-login.d.ts.map +1 -1
  113. package/dist/runtime/routes/auth-login.js +4 -0
  114. package/dist/runtime/routes/auth-login.js.map +1 -1
  115. package/dist/runtime/routes/auth-logout.d.ts.map +1 -1
  116. package/dist/runtime/routes/auth-logout.js +7 -2
  117. package/dist/runtime/routes/auth-logout.js.map +1 -1
  118. package/dist/runtime/routes/auth-session.d.ts.map +1 -1
  119. package/dist/runtime/routes/auth-session.js +10 -2
  120. package/dist/runtime/routes/auth-session.js.map +1 -1
  121. package/dist/runtime/routes/collection-list.d.ts.map +1 -1
  122. package/dist/runtime/routes/collection-list.js +213 -66
  123. package/dist/runtime/routes/collection-list.js.map +1 -1
  124. package/dist/runtime/routes/deployment.d.ts +5 -0
  125. package/dist/runtime/routes/deployment.d.ts.map +1 -0
  126. package/dist/runtime/routes/deployment.js +38 -0
  127. package/dist/runtime/routes/deployment.js.map +1 -0
  128. package/dist/runtime/routes/draft.d.ts.map +1 -1
  129. package/dist/runtime/routes/draft.js +10 -3
  130. package/dist/runtime/routes/draft.js.map +1 -1
  131. package/dist/runtime/routes/entries.d.ts.map +1 -1
  132. package/dist/runtime/routes/entries.js +87 -43
  133. package/dist/runtime/routes/entries.js.map +1 -1
  134. package/dist/runtime/routes/history.d.ts.map +1 -1
  135. package/dist/runtime/routes/history.js +40 -21
  136. package/dist/runtime/routes/history.js.map +1 -1
  137. package/dist/runtime/routes/mutate.d.ts.map +1 -1
  138. package/dist/runtime/routes/mutate.js +4 -1
  139. package/dist/runtime/routes/mutate.js.map +1 -1
  140. package/dist/runtime/routes/publish.d.ts.map +1 -1
  141. package/dist/runtime/routes/publish.js +127 -33
  142. package/dist/runtime/routes/publish.js.map +1 -1
  143. package/dist/runtime/routes/schema.d.ts.map +1 -1
  144. package/dist/runtime/routes/schema.js +11 -2
  145. package/dist/runtime/routes/schema.js.map +1 -1
  146. package/dist/runtime/routes/studio-home.d.ts.map +1 -1
  147. package/dist/runtime/routes/studio-home.js +41 -20
  148. package/dist/runtime/routes/studio-home.js.map +1 -1
  149. package/dist/runtime/routes/upload.d.ts.map +1 -1
  150. package/dist/runtime/routes/upload.js +3 -0
  151. package/dist/runtime/routes/upload.js.map +1 -1
  152. package/dist/runtime/schema-registry.d.ts +8 -1
  153. package/dist/runtime/schema-registry.d.ts.map +1 -1
  154. package/dist/runtime/schema-registry.js +49 -3
  155. package/dist/runtime/schema-registry.js.map +1 -1
  156. package/dist/runtime/storage/entry-commit.d.ts +8 -0
  157. package/dist/runtime/storage/entry-commit.d.ts.map +1 -0
  158. package/dist/runtime/storage/entry-commit.js +45 -0
  159. package/dist/runtime/storage/entry-commit.js.map +1 -0
  160. package/dist/runtime/storage/filesystem-adapter.d.ts +5 -0
  161. package/dist/runtime/storage/filesystem-adapter.d.ts.map +1 -1
  162. package/dist/runtime/storage/filesystem-adapter.js +12 -3
  163. package/dist/runtime/storage/filesystem-adapter.js.map +1 -1
  164. package/dist/runtime/storage/frontmatter-codec.d.ts +5 -23
  165. package/dist/runtime/storage/frontmatter-codec.d.ts.map +1 -1
  166. package/dist/runtime/storage/frontmatter-codec.js +156 -13
  167. package/dist/runtime/storage/frontmatter-codec.js.map +1 -1
  168. package/dist/runtime/storage/in-memory-adapter.d.ts +7 -0
  169. package/dist/runtime/storage/in-memory-adapter.d.ts.map +1 -1
  170. package/dist/runtime/storage/in-memory-adapter.js +6 -0
  171. package/dist/runtime/storage/in-memory-adapter.js.map +1 -1
  172. package/dist/runtime/storage/markdown-adapter.d.ts.map +1 -1
  173. package/dist/runtime/storage/markdown-adapter.js +18 -20
  174. package/dist/runtime/storage/markdown-adapter.js.map +1 -1
  175. package/dist/runtime/storage/session-overlay-adapter.d.ts +12 -4
  176. package/dist/runtime/storage/session-overlay-adapter.d.ts.map +1 -1
  177. package/dist/runtime/storage/session-overlay-adapter.js +100 -13
  178. package/dist/runtime/storage/session-overlay-adapter.js.map +1 -1
  179. package/dist/runtime/storage/sidecar-meta-store.d.ts +5 -0
  180. package/dist/runtime/storage/sidecar-meta-store.d.ts.map +1 -1
  181. package/dist/runtime/storage/sidecar-meta-store.js +48 -5
  182. package/dist/runtime/storage/sidecar-meta-store.js.map +1 -1
  183. package/dist/runtime/themes/preset-tokens.js +4 -4
  184. package/dist/runtime/themes/preset-tokens.js.map +1 -1
  185. package/dist/runtime/utils.d.ts.map +1 -1
  186. package/dist/runtime/utils.js +3 -4
  187. package/dist/runtime/utils.js.map +1 -1
  188. package/dist/runtime/views/studio-layout.d.ts +3 -0
  189. package/dist/runtime/views/studio-layout.d.ts.map +1 -1
  190. package/dist/runtime/views/studio-layout.js +36 -13
  191. package/dist/runtime/views/studio-layout.js.map +1 -1
  192. package/dist/schema-utils.d.ts +7 -0
  193. package/dist/schema-utils.d.ts.map +1 -1
  194. package/dist/schema-utils.js +143 -0
  195. package/dist/schema-utils.js.map +1 -1
  196. package/dist/types.d.ts +165 -1
  197. package/dist/types.d.ts.map +1 -1
  198. package/package.json +12 -3
  199. package/static/cms/admin-entry.css +144 -13
  200. package/static/cms/admin-entry.js +539 -586
  201. package/static/cms/dev-toolbar/app.js +78 -19
  202. package/static/cms/editor/config.js +35 -15
  203. package/static/cms/editor/content-map.css +8 -1
  204. package/static/cms/editor/content-map.js +62 -23
  205. package/static/cms/editor/deployment-status.js +66 -0
  206. package/static/cms/editor/draft-client.js +87 -0
  207. package/static/cms/editor/guards.js +20 -0
  208. package/static/cms/editor/helpers.js +30 -1
  209. package/static/cms/editor/highlight.js +1 -0
  210. package/static/cms/editor/image-edit.js +44 -1
  211. package/static/cms/editor/image-utils.js +23 -7
  212. package/static/cms/editor/link-follow.js +122 -41
  213. package/static/cms/editor/link-ui.css +10 -1
  214. package/static/cms/editor/linkify.js +2 -0
  215. package/static/cms/editor/md-block-edit.js +140 -37
  216. package/static/cms/editor/md-paragraphs.js +98 -0
  217. package/static/cms/editor/md-serialize.js +1 -1
  218. package/static/cms/editor/panel.js +53 -7
  219. package/static/cms/editor/preview-mode.js +44 -0
  220. package/static/cms/editor/publish-result.js +100 -0
  221. package/static/cms/editor/rich-toolbar.js +58 -15
  222. package/static/cms/editor/sanitize.js +6 -2
  223. package/static/cms/editor/save-queue.js +75 -17
  224. package/static/cms/editor/section-controls/activation.js +3 -0
  225. package/static/cms/editor/section-controls/api.js +25 -7
  226. package/static/cms/editor/section-controls/index.js +60 -8
  227. package/static/cms/editor/section-controls/model.js +39 -4
  228. package/static/cms/editor/section-controls/mutations.js +15 -0
  229. package/static/cms/editor/section-controls/page-context.js +9 -0
  230. package/static/cms/editor/section-controls/pickers.js +53 -2
  231. package/static/cms/editor/section-controls/reorder.js +23 -0
  232. package/static/cms/editor/section-controls/selection.js +6 -0
  233. package/static/cms/editor/section-controls/spacing-drag.js +16 -0
  234. package/static/cms/editor/section-controls/ui-elements.js +7 -0
  235. package/static/cms/editor/section-controls/utils.js +7 -0
  236. package/static/cms/editor/section-controls.css +18 -3
  237. package/static/cms/editor/security.js +13 -2
  238. package/static/cms/editor/stega-hydrate.js +17 -4
  239. package/static/cms/editor/sync.js +475 -56
  240. package/static/cms/editor/text-edit.js +37 -3
  241. package/static/cms/editor/text-link-interactions.js +59 -17
  242. package/static/cms/editor/toast.js +23 -9
  243. package/static/cms/editor/tokens-and-text.css +9 -0
  244. package/static/cms/editor/toolbar.css +5 -0
  245. package/static/cms/editor/toolbar.js +91 -101
  246. package/static/cms/editor.css +1 -1
  247. package/static/cms/editor.js +1 -0
  248. package/static/cms/studio/entry-loader.js +102 -0
  249. package/static/cms/studio/field-model.js +110 -0
  250. package/static/cms/studio/fields.js +319 -0
  251. package/static/cms/studio/history-client.js +74 -0
  252. package/static/cms/studio/mutation-client.js +74 -0
  253. package/static/cms/studio/sync-client.js +107 -0
  254. package/static/cms/studio/upload-client.js +109 -0
  255. package/static/cms/studio-tokens.css +4 -4
  256. 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
- if (typeof window.cmsGetTurnstileToken !== 'function') return null;
8
+ const getToken = /** @type {Window & { cmsGetTurnstileToken?: (action: string) => unknown }} */ (
9
+ window
10
+ ).cmsGetTurnstileToken;
11
+ if (typeof getToken !== 'function') return null;
5
12
  try {
6
- return await window.cmsGetTurnstileToken(action);
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) tagged.push(node);
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 key = stegaDecode(textNode.nodeValue);
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(textNode.nodeValue);
72
- if (typeof key !== 'string' || key.indexOf('::') === -1) continue;
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
  }