@storystick/preview 0.0.0-stage → 0.2.0-rc.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 (245) hide show
  1. package/LICENSE +112 -0
  2. package/PUBLIC-API.md +55 -0
  3. package/README.md +42 -2
  4. package/dist/.source-hash +1 -0
  5. package/dist/authoring/runtime-contract.d.ts +89 -0
  6. package/dist/authoring/runtime-contract.js +28 -0
  7. package/dist/channel-taxonomy.d.ts +17 -0
  8. package/dist/channel-taxonomy.js +46 -0
  9. package/dist/context-command.d.ts +18 -0
  10. package/dist/context-command.js +38 -0
  11. package/dist/dev/suspicious-codeword-detector.d.ts +15 -0
  12. package/dist/dev/suspicious-codeword-detector.js +220 -0
  13. package/dist/dev/suspicious-codeword-detector.noop.d.ts +3 -0
  14. package/dist/dev/suspicious-codeword-detector.noop.js +4 -0
  15. package/dist/framework/browser-context.d.ts +2 -0
  16. package/dist/framework/browser-context.js +2 -0
  17. package/dist/framework/generation-refresh.d.ts +23 -0
  18. package/dist/framework/generation-refresh.js +82 -0
  19. package/dist/framework/generation-signal.d.ts +8 -0
  20. package/dist/framework/generation-signal.js +17 -0
  21. package/dist/framework/projection-generation-watch.d.ts +5 -0
  22. package/dist/framework/projection-generation-watch.js +53 -0
  23. package/dist/framework/render-receipt.d.ts +8 -0
  24. package/dist/framework/render-receipt.js +10 -0
  25. package/dist/framework/runtime-adapter-store.d.ts +30 -0
  26. package/dist/framework/runtime-adapter-store.js +81 -0
  27. package/dist/grant-coordinator.d.ts +53 -0
  28. package/dist/grant-coordinator.js +329 -0
  29. package/dist/grant-lifecycle.d.ts +52 -0
  30. package/dist/grant-lifecycle.js +74 -0
  31. package/dist/identity/__test-adapter.d.ts +34 -0
  32. package/dist/identity/__test-adapter.js +59 -0
  33. package/dist/identity/browser-context-gate.d.ts +4 -0
  34. package/dist/identity/browser-context-gate.js +22 -0
  35. package/dist/identity/browser-context.d.ts +13 -0
  36. package/dist/identity/browser-context.js +22 -0
  37. package/dist/identity/carriers/postmessage.d.ts +84 -0
  38. package/dist/identity/carriers/postmessage.js +177 -0
  39. package/dist/identity/carriers/storage-state.d.ts +41 -0
  40. package/dist/identity/carriers/storage-state.js +99 -0
  41. package/dist/identity/carriers/storage.d.ts +39 -0
  42. package/dist/identity/carriers/storage.js +182 -0
  43. package/dist/identity/carriers/url.d.ts +19 -0
  44. package/dist/identity/carriers/url.js +38 -0
  45. package/dist/identity/identity-state-machine.d.ts +70 -0
  46. package/dist/identity/identity-state-machine.js +244 -0
  47. package/dist/identity/identity-types.d.ts +192 -0
  48. package/dist/identity/identity-types.js +22 -0
  49. package/dist/identity/index.d.ts +18 -0
  50. package/dist/identity/index.js +16 -0
  51. package/dist/identity/preview-cookie.d.ts +9 -0
  52. package/dist/identity/preview-cookie.js +12 -0
  53. package/dist/identity/preview-draft.d.ts +6 -0
  54. package/dist/identity/preview-draft.js +25 -0
  55. package/dist/identity/preview-identity.d.ts +28 -0
  56. package/dist/identity/preview-identity.js +84 -0
  57. package/dist/identity/preview-scope.d.ts +28 -0
  58. package/dist/identity/preview-scope.js +47 -0
  59. package/dist/identity/resolver.d.ts +110 -0
  60. package/dist/identity/resolver.js +334 -0
  61. package/dist/identity/session-query.d.ts +4 -0
  62. package/dist/identity/session-query.js +19 -0
  63. package/dist/index.d.ts +90 -0
  64. package/dist/index.js +788 -0
  65. package/dist/interaction-mode.d.ts +58 -0
  66. package/dist/interaction-mode.js +93 -0
  67. package/dist/nav-handler.d.ts +95 -0
  68. package/dist/nav-handler.js +84 -0
  69. package/dist/overlay-label.d.ts +79 -0
  70. package/dist/overlay-label.js +73 -0
  71. package/dist/provenance/anchor-map.d.ts +95 -0
  72. package/dist/provenance/anchor-map.js +177 -0
  73. package/dist/provenance/carrier-plan.d.ts +51 -0
  74. package/dist/provenance/carrier-plan.js +90 -0
  75. package/dist/provenance/coded-text.d.ts +20 -0
  76. package/dist/provenance/coded-text.js +302 -0
  77. package/dist/provenance/direct-edit-locator.d.ts +29 -0
  78. package/dist/provenance/direct-edit-locator.js +218 -0
  79. package/dist/provenance/editable-leaf.d.ts +134 -0
  80. package/dist/provenance/editable-leaf.js +483 -0
  81. package/dist/provenance/editor-target.d.ts +29 -0
  82. package/dist/provenance/editor-target.js +46 -0
  83. package/dist/provenance/field-leaf-walker.d.ts +21 -0
  84. package/dist/provenance/field-leaf-walker.js +98 -0
  85. package/dist/provenance/frame-dependencies.d.ts +212 -0
  86. package/dist/provenance/frame-dependencies.js +550 -0
  87. package/dist/provenance/index.d.ts +26 -0
  88. package/dist/provenance/index.js +26 -0
  89. package/dist/provenance/local-events.d.ts +1 -0
  90. package/dist/provenance/local-events.js +1 -0
  91. package/dist/provenance/markers.d.ts +21 -0
  92. package/dist/provenance/markers.js +70 -0
  93. package/dist/provenance/multi-frame-anchor-map.d.ts +54 -0
  94. package/dist/provenance/multi-frame-anchor-map.js +109 -0
  95. package/dist/provenance/normalize.d.ts +2 -0
  96. package/dist/provenance/normalize.js +19 -0
  97. package/dist/provenance/overlay-focus-echo.d.ts +17 -0
  98. package/dist/provenance/overlay-focus-echo.js +16 -0
  99. package/dist/provenance/overlay-projection.d.ts +65 -0
  100. package/dist/provenance/overlay-projection.js +201 -0
  101. package/dist/provenance/owner-map.d.ts +55 -0
  102. package/dist/provenance/owner-map.js +239 -0
  103. package/dist/provenance/read-carrier.d.ts +22 -0
  104. package/dist/provenance/read-carrier.js +92 -0
  105. package/dist/provenance/recorder.d.ts +38 -0
  106. package/dist/provenance/recorder.js +82 -0
  107. package/dist/provenance/render-context.d.ts +106 -0
  108. package/dist/provenance/render-context.js +338 -0
  109. package/dist/provenance/reveal-contract.d.ts +44 -0
  110. package/dist/provenance/reveal-contract.js +1 -0
  111. package/dist/provenance/richtext-slice-embed-address.d.ts +20 -0
  112. package/dist/provenance/richtext-slice-embed-address.js +35 -0
  113. package/dist/provenance/runtime-script.d.ts +1 -0
  114. package/dist/provenance/runtime-script.js +2217 -0
  115. package/dist/provenance/sidecar-store.d.ts +63 -0
  116. package/dist/provenance/sidecar-store.js +151 -0
  117. package/dist/provenance/sidecar.d.ts +34 -0
  118. package/dist/provenance/sidecar.js +227 -0
  119. package/dist/provenance/slice-model.d.ts +28 -0
  120. package/dist/provenance/slice-model.js +86 -0
  121. package/dist/provenance/source-identity.d.ts +3 -0
  122. package/dist/provenance/source-identity.js +7 -0
  123. package/dist/provenance/source-map-materializer.d.ts +76 -0
  124. package/dist/provenance/source-map-materializer.js +286 -0
  125. package/dist/provenance/source-registry.d.ts +103 -0
  126. package/dist/provenance/source-registry.js +562 -0
  127. package/dist/provenance/transformed-output-gate.d.ts +161 -0
  128. package/dist/provenance/transformed-output-gate.js +171 -0
  129. package/dist/provenance/types.d.ts +102 -0
  130. package/dist/provenance/types.js +1 -0
  131. package/dist/refresh-policy.d.ts +11 -0
  132. package/dist/refresh-policy.js +14 -0
  133. package/dist/reveal-target.d.ts +8 -0
  134. package/dist/reveal-target.js +47 -0
  135. package/dist/route-paths.d.ts +11 -0
  136. package/dist/route-paths.js +14 -0
  137. package/dist/router-subscriber.d.ts +92 -0
  138. package/dist/router-subscriber.js +44 -0
  139. package/dist/runtime/anchor-types.d.ts +5 -0
  140. package/dist/runtime/anchor-types.js +1 -0
  141. package/dist/runtime/authority-store.d.ts +31 -0
  142. package/dist/runtime/authority-store.js +56 -0
  143. package/dist/runtime/boot.d.ts +52 -0
  144. package/dist/runtime/boot.js +379 -0
  145. package/dist/runtime/content-refresh.d.ts +30 -0
  146. package/dist/runtime/content-refresh.js +68 -0
  147. package/dist/runtime/emit-runtime-error.d.ts +51 -0
  148. package/dist/runtime/emit-runtime-error.js +64 -0
  149. package/dist/runtime/field-proxy.d.ts +112 -0
  150. package/dist/runtime/field-proxy.js +471 -0
  151. package/dist/runtime/form-contract-reporter.d.ts +99 -0
  152. package/dist/runtime/form-contract-reporter.js +391 -0
  153. package/dist/runtime/invalidation-adapter.d.ts +17 -0
  154. package/dist/runtime/invalidation-adapter.js +42 -0
  155. package/dist/runtime/live-query-overlay.d.ts +39 -0
  156. package/dist/runtime/live-query-overlay.js +345 -0
  157. package/dist/runtime/momentary-navigate.d.ts +16 -0
  158. package/dist/runtime/momentary-navigate.js +106 -0
  159. package/dist/runtime/observation-scheduler.d.ts +15 -0
  160. package/dist/runtime/observation-scheduler.js +42 -0
  161. package/dist/runtime/perf-metrics.d.ts +28 -0
  162. package/dist/runtime/perf-metrics.js +90 -0
  163. package/dist/runtime/preview-interaction-policy.d.ts +1 -0
  164. package/dist/runtime/preview-interaction-policy.js +103 -0
  165. package/dist/runtime/preview-overlay-painter.d.ts +27 -0
  166. package/dist/runtime/preview-overlay-painter.js +1732 -0
  167. package/dist/runtime/preview-overlay-sidecar.d.ts +26 -0
  168. package/dist/runtime/preview-overlay-sidecar.js +45 -0
  169. package/dist/runtime/preview-perspective-alignment.d.ts +15 -0
  170. package/dist/runtime/preview-perspective-alignment.js +40 -0
  171. package/dist/runtime/preview-perspective-intent-state.d.ts +23 -0
  172. package/dist/runtime/preview-perspective-intent-state.js +5 -0
  173. package/dist/runtime/preview-transition-state.d.ts +142 -0
  174. package/dist/runtime/preview-transition-state.js +257 -0
  175. package/dist/runtime/render-mode-state.d.ts +51 -0
  176. package/dist/runtime/render-mode-state.js +76 -0
  177. package/dist/runtime/request-id.d.ts +4 -0
  178. package/dist/runtime/request-id.js +8 -0
  179. package/dist/runtime/resolve-schema-field.d.ts +99 -0
  180. package/dist/runtime/resolve-schema-field.js +356 -0
  181. package/dist/runtime/runtime-error-dispatch.d.ts +23 -0
  182. package/dist/runtime/runtime-error-dispatch.js +75 -0
  183. package/dist/runtime/schema-store.d.ts +121 -0
  184. package/dist/runtime/schema-store.js +667 -0
  185. package/dist/runtime/snapshot-assembly.d.ts +104 -0
  186. package/dist/runtime/snapshot-assembly.js +553 -0
  187. package/dist/runtime/snapshot-reporter.d.ts +55 -0
  188. package/dist/runtime/snapshot-reporter.js +375 -0
  189. package/dist/runtime/standalone-overlay-controller.d.ts +33 -0
  190. package/dist/runtime/standalone-overlay-controller.js +281 -0
  191. package/dist/runtime/store.d.ts +307 -0
  192. package/dist/runtime/store.js +1026 -0
  193. package/dist/runtime/windowed-minimap-projection.d.ts +28 -0
  194. package/dist/runtime/windowed-minimap-projection.js +189 -0
  195. package/dist/runtime/workspace-shortcuts.d.ts +30 -0
  196. package/dist/runtime/workspace-shortcuts.js +188 -0
  197. package/dist/sdk-error-copy.d.ts +48 -0
  198. package/dist/sdk-error-copy.js +182 -0
  199. package/dist/select-cursor.d.ts +2 -0
  200. package/dist/select-cursor.js +23 -0
  201. package/dist/server/admission-cookie.d.ts +38 -0
  202. package/dist/server/admission-cookie.js +122 -0
  203. package/dist/server/control-client.d.ts +29 -0
  204. package/dist/server/control-client.js +22 -0
  205. package/dist/server/control-errors.d.ts +22 -0
  206. package/dist/server/control-errors.js +165 -0
  207. package/dist/server/draft-route.d.ts +12 -0
  208. package/dist/server/draft-route.js +45 -0
  209. package/dist/server/extract-token.d.ts +30 -0
  210. package/dist/server/extract-token.js +98 -0
  211. package/dist/server/grant.d.ts +128 -0
  212. package/dist/server/grant.js +395 -0
  213. package/dist/server/ordinary-read-provenance.d.ts +11 -0
  214. package/dist/server/ordinary-read-provenance.js +124 -0
  215. package/dist/server/preview-read-metadata.d.ts +10 -0
  216. package/dist/server/preview-read-metadata.js +27 -0
  217. package/dist/server/provenance-frame-builder.d.ts +53 -0
  218. package/dist/server/provenance-frame-builder.js +102 -0
  219. package/dist/server/provenance-runtime.d.ts +70 -0
  220. package/dist/server/provenance-runtime.js +46 -0
  221. package/dist/server/read-context-command.d.ts +11 -0
  222. package/dist/server/read-context-command.js +53 -0
  223. package/dist/server/read-identity.d.ts +3 -0
  224. package/dist/server/read-identity.js +63 -0
  225. package/dist/server/read-lifecycle.d.ts +17 -0
  226. package/dist/server/read-lifecycle.js +52 -0
  227. package/dist/server/render-frame-provenance.d.ts +133 -0
  228. package/dist/server/render-frame-provenance.js +676 -0
  229. package/dist/server/render-id.d.ts +15 -0
  230. package/dist/server/render-id.js +22 -0
  231. package/dist/server/route-document-provenance.d.ts +77 -0
  232. package/dist/server/route-document-provenance.js +1327 -0
  233. package/dist/server/route-session-cookie.d.ts +33 -0
  234. package/dist/server/route-session-cookie.js +54 -0
  235. package/dist/session-projections.d.ts +33 -0
  236. package/dist/session-projections.js +43 -0
  237. package/dist/session-subscriber.d.ts +124 -0
  238. package/dist/session-subscriber.js +79 -0
  239. package/dist/sha256-fallback.d.ts +30 -0
  240. package/dist/sha256-fallback.js +126 -0
  241. package/dist/types.d.ts +446 -0
  242. package/dist/types.js +85 -0
  243. package/dist/validators.d.ts +61 -0
  244. package/dist/validators.js +110 -0
  245. package/package.json +206 -3
@@ -0,0 +1,338 @@
1
+ import { isPreviewReadContext } from '@storystick/types/preview-query-targeting';
2
+ import { previewProvenanceDocumentPathKey, readPreviewProvenanceDocumentPathKey, } from '@storystick/types/internal/preview-provenance';
3
+ export function serializePreviewProvenanceSidecar(sidecar) {
4
+ return JSON.stringify(sidecar).replace(/</g, '\\u003c');
5
+ }
6
+ export function withPreviewProvenanceContext(context, attrsByKey) {
7
+ if (!attrsByKey)
8
+ return context;
9
+ const base = isRecord(context) ? context : {};
10
+ return {
11
+ ...base,
12
+ __ssPreviewProvenance: { attrsByKey },
13
+ };
14
+ }
15
+ export function withPreviewProvenanceRouteFrame(value, frame) {
16
+ if (!frame)
17
+ return value;
18
+ const base = isRecord(value) ? value : {};
19
+ return {
20
+ ...base,
21
+ __ssPreviewRouteFrame: frame,
22
+ };
23
+ }
24
+ export function readPreviewProvenanceRouteFrame(value) {
25
+ if (!isRecord(value))
26
+ return null;
27
+ const frame = value
28
+ .__ssPreviewRouteFrame;
29
+ if (!isRecord(frame))
30
+ return null;
31
+ if (frame.type !== 'storystick.preview.route-frame')
32
+ return null;
33
+ if (frame.version !== 1)
34
+ return null;
35
+ if (typeof frame.frameId !== 'string' || frame.frameId.length === 0) {
36
+ return null;
37
+ }
38
+ if (typeof frame.routeHash !== 'string' || frame.routeHash.length === 0) {
39
+ return null;
40
+ }
41
+ const publicSidecar = isRecord(frame.publicSidecar) &&
42
+ frame.publicSidecar.type === 'storystick.preview.public-sidecar'
43
+ ? frame.publicSidecar
44
+ : null;
45
+ if ((!frame.sessionId || typeof frame.sessionId !== 'string') &&
46
+ !isPreviewReadContext(publicSidecar?.dependencySet?.readContext))
47
+ return null;
48
+ return {
49
+ type: 'storystick.preview.route-frame',
50
+ version: 1,
51
+ frameId: frame.frameId,
52
+ ...(typeof frame.sessionId === 'string' ? { sessionId: frame.sessionId } : {}),
53
+ routeHash: frame.routeHash,
54
+ publicSidecar,
55
+ };
56
+ }
57
+ export function withPreviewProvenanceRouteRender(value, render) {
58
+ if (!render)
59
+ return value;
60
+ const base = isRecord(value) ? value : {};
61
+ return {
62
+ ...base,
63
+ __ssPreviewRouteRender: render,
64
+ };
65
+ }
66
+ export function readPreviewProvenanceRouteRender(value) {
67
+ if (!isRecord(value))
68
+ return null;
69
+ const render = value
70
+ .__ssPreviewRouteRender;
71
+ if (!isRecord(render))
72
+ return null;
73
+ if (render.type !== 'storystick.preview.route-render')
74
+ return null;
75
+ if (render.version !== 1)
76
+ return null;
77
+ const frame = readPreviewProvenanceRouteFrame({
78
+ __ssPreviewRouteFrame: render.frame,
79
+ });
80
+ if (frame === null)
81
+ return null;
82
+ if (!isRecord(render.document))
83
+ return null;
84
+ return {
85
+ type: 'storystick.preview.route-render',
86
+ version: 1,
87
+ frame,
88
+ document: render.document,
89
+ };
90
+ }
91
+ export function previewProvenanceAttrs(context, key) {
92
+ if (!isRecord(context))
93
+ return {};
94
+ const holder = context;
95
+ return withPreviewCarrierHydrationSuppression(holder.__ssPreviewProvenance?.attrsByKey[key]);
96
+ }
97
+ export function buildSliceProvenance(context, slice) {
98
+ if (!isRecord(context))
99
+ return undefined;
100
+ if (typeof slice._key !== 'string' || slice._key.length === 0)
101
+ return undefined;
102
+ const attrsByKey = context.__ssPreviewProvenance
103
+ ?.attrsByKey;
104
+ if (!attrsByKey)
105
+ return undefined;
106
+ const fields = {};
107
+ const arrays = {};
108
+ const paths = {};
109
+ let found = false;
110
+ for (const [key, attrs] of Object.entries(attrsByKey)) {
111
+ const parsed = parseSlicePathKey(key);
112
+ if (!parsed || parsed.sliceKey !== slice._key)
113
+ continue;
114
+ const hydratedAttrs = withPreviewCarrierHydrationSuppression(attrs);
115
+ paths[previewPathKey(parsed.path)] = hydratedAttrs;
116
+ copyStructuredPathToConvenienceViews(parsed.path, hydratedAttrs, fields, arrays);
117
+ found = true;
118
+ }
119
+ return found ? { fields, arrays, paths } : undefined;
120
+ }
121
+ export function buildDocumentProvenance(context, document) {
122
+ if (!isRecord(context))
123
+ return undefined;
124
+ if (typeof document.documentId !== 'string' ||
125
+ document.documentId.length === 0) {
126
+ return undefined;
127
+ }
128
+ const attrsByKey = context.__ssPreviewProvenance
129
+ ?.attrsByKey;
130
+ if (!attrsByKey)
131
+ return undefined;
132
+ const fields = {};
133
+ const paths = {};
134
+ let found = false;
135
+ for (const [key, attrs] of Object.entries(attrsByKey)) {
136
+ const parsed = parseDocumentPathKey(key);
137
+ if (!parsed || parsed.documentId !== document.documentId)
138
+ continue;
139
+ const hydratedAttrs = withPreviewCarrierHydrationSuppression(attrs);
140
+ paths[previewPathKey(parsed.path)] = hydratedAttrs;
141
+ copyDocumentPathToConvenienceViews(parsed.path, hydratedAttrs, fields);
142
+ found = true;
143
+ }
144
+ return found ? { fields, paths } : undefined;
145
+ }
146
+ function withPreviewCarrierHydrationSuppression(attrs) {
147
+ if (!attrs || typeof attrs['data-ss-p'] !== 'string')
148
+ return attrs ?? {};
149
+ return {
150
+ ...attrs,
151
+ suppressHydrationWarning: true,
152
+ };
153
+ }
154
+ export function fieldSegment(name) {
155
+ return { type: 'field', name };
156
+ }
157
+ export function arrayItemSegment(field, key) {
158
+ return { type: 'arrayItem', field, key };
159
+ }
160
+ export function richTextTextNodeSegment(index) {
161
+ return { type: 'richTextTextNode', index };
162
+ }
163
+ export function previewPathKey(path) {
164
+ return encodePathPayload(normalizePath(path));
165
+ }
166
+ export function slicePathKey(slice, path) {
167
+ const payload = {
168
+ v: 2,
169
+ sliceKey: slice._key,
170
+ path: normalizePath(path),
171
+ };
172
+ return `route:slice:v2:${encodePathPayload(payload)}`;
173
+ }
174
+ export function sliceFieldKey(slice, field) {
175
+ return slicePathKey(slice, [fieldSegment(field)]);
176
+ }
177
+ export function sliceArrayFieldKey(slice, arrayName, itemKey, field) {
178
+ return slicePathKey(slice, [
179
+ arrayItemSegment(arrayName, itemKey),
180
+ fieldSegment(field),
181
+ ]);
182
+ }
183
+ export function documentPathKey(document, path) {
184
+ return previewProvenanceDocumentPathKey(document.documentId, normalizePath(path));
185
+ }
186
+ export function documentFieldKey(document, field) {
187
+ return documentPathKey(document, [fieldSegment(field)]);
188
+ }
189
+ function parseSlicePathKey(key) {
190
+ const prefix = 'route:slice:v2:';
191
+ if (!key.startsWith(prefix))
192
+ return parseLegacyFlatSlicePathKey(key);
193
+ const payload = decodePathPayload(key.slice(prefix.length));
194
+ if (!isRecord(payload))
195
+ return null;
196
+ if (payload.v !== 2 || typeof payload.sliceKey !== 'string')
197
+ return null;
198
+ const path = normalizePath(payload.path);
199
+ if (path.length === 0)
200
+ return null;
201
+ return { sliceKey: payload.sliceKey, path };
202
+ }
203
+ function parseLegacyFlatSlicePathKey(key) {
204
+ const prefix = 'route:slice:';
205
+ if (!key.startsWith(prefix))
206
+ return null;
207
+ const rest = key.slice(prefix.length);
208
+ const separator = rest.indexOf(':');
209
+ if (separator <= 0)
210
+ return null;
211
+ const sliceKey = rest.slice(0, separator);
212
+ const slug = rest.slice(separator + 1);
213
+ if (sliceKey.length === 0 || slug.length === 0)
214
+ return null;
215
+ const parts = slug.split('_').filter((part) => part.length > 0);
216
+ if (parts.length === 0)
217
+ return null;
218
+ if (parts.length === 1) {
219
+ return { sliceKey, path: [fieldSegment(parts[0])] };
220
+ }
221
+ if (parts.length >= 3) {
222
+ return {
223
+ sliceKey,
224
+ path: [
225
+ arrayItemSegment(parts[0], parts.slice(1, -1).join('_')),
226
+ fieldSegment(parts[parts.length - 1]),
227
+ ],
228
+ };
229
+ }
230
+ return { sliceKey, path: [fieldSegment(slug)] };
231
+ }
232
+ function parseDocumentPathKey(key) {
233
+ const payload = readPreviewProvenanceDocumentPathKey(key);
234
+ if (!payload)
235
+ return null;
236
+ const path = normalizePath(payload.path);
237
+ if (path.length === 0)
238
+ return null;
239
+ return { documentId: payload.documentId, path };
240
+ }
241
+ function copyStructuredPathToConvenienceViews(path, attrs, fields, arrays) {
242
+ if (path.length === 1) {
243
+ const [field] = path;
244
+ if (field?.type === 'field' && isSafeRecordKey(field.name)) {
245
+ fields[field.name] = attrs;
246
+ }
247
+ return;
248
+ }
249
+ if (path.length !== 2)
250
+ return;
251
+ const [arrayItem, field] = path;
252
+ if (arrayItem?.type !== 'arrayItem' ||
253
+ field?.type !== 'field' ||
254
+ !isSafeRecordKey(arrayItem.field) ||
255
+ !isSafeRecordKey(arrayItem.key) ||
256
+ !isSafeRecordKey(field.name)) {
257
+ return;
258
+ }
259
+ let arrayItems = hasOwn(arrays, arrayItem.field)
260
+ ? arrays[arrayItem.field]
261
+ : undefined;
262
+ if (!arrayItems) {
263
+ arrayItems = {};
264
+ arrays[arrayItem.field] = arrayItems;
265
+ }
266
+ let itemFields = hasOwn(arrayItems, arrayItem.key)
267
+ ? arrayItems[arrayItem.key]
268
+ : undefined;
269
+ if (!itemFields) {
270
+ itemFields = {};
271
+ arrayItems[arrayItem.key] = itemFields;
272
+ }
273
+ itemFields[field.name] = attrs;
274
+ }
275
+ function copyDocumentPathToConvenienceViews(path, attrs, fields) {
276
+ if (path.length !== 1)
277
+ return;
278
+ const [field] = path;
279
+ if (field?.type === 'field' && isSafeRecordKey(field.name)) {
280
+ fields[field.name] = attrs;
281
+ }
282
+ }
283
+ function normalizePath(value) {
284
+ if (!Array.isArray(value))
285
+ return [];
286
+ const path = [];
287
+ for (const segment of value) {
288
+ if (!isRecord(segment))
289
+ return [];
290
+ if (segment.type === 'field' &&
291
+ typeof segment.name === 'string' &&
292
+ segment.name.length > 0) {
293
+ path.push({ type: 'field', name: segment.name });
294
+ continue;
295
+ }
296
+ if (segment.type === 'arrayItem' &&
297
+ typeof segment.field === 'string' &&
298
+ segment.field.length > 0 &&
299
+ typeof segment.key === 'string' &&
300
+ segment.key.length > 0) {
301
+ path.push({ type: 'arrayItem', field: segment.field, key: segment.key });
302
+ continue;
303
+ }
304
+ if (segment.type === 'richTextTextNode' &&
305
+ typeof segment.index === 'number' &&
306
+ Number.isInteger(segment.index) &&
307
+ segment.index >= 0) {
308
+ path.push({ type: 'richTextTextNode', index: segment.index });
309
+ continue;
310
+ }
311
+ return [];
312
+ }
313
+ return path;
314
+ }
315
+ function encodePathPayload(value) {
316
+ return encodeURIComponent(JSON.stringify(value));
317
+ }
318
+ function decodePathPayload(value) {
319
+ try {
320
+ return JSON.parse(decodeURIComponent(value));
321
+ }
322
+ catch {
323
+ return null;
324
+ }
325
+ }
326
+ function isRecord(value) {
327
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
328
+ }
329
+ function hasOwn(record, key) {
330
+ return Object.prototype.hasOwnProperty.call(record, key);
331
+ }
332
+ function isSafeRecordKey(key) {
333
+ return (typeof key === 'string' &&
334
+ key.length > 0 &&
335
+ key !== '__proto__' &&
336
+ key !== 'constructor' &&
337
+ key !== 'prototype');
338
+ }
@@ -0,0 +1,44 @@
1
+ import type { ProvenanceId } from './types.js';
2
+ export interface PreviewV2SourceIdentityRequest {
3
+ documentId: string;
4
+ anchoredPath: string;
5
+ sliceKey?: string;
6
+ expectedSourceKey?: string;
7
+ expectedSourceKind?: ProvenanceId['sourceKind'];
8
+ richTextTextNodeIndex?: number;
9
+ richTextSliceEmbedIndex?: number;
10
+ richTextSliceEmbedKey?: string;
11
+ }
12
+ export interface PreviewV2SourceIdentity {
13
+ sourceKey: string;
14
+ sourceKind: ProvenanceId['sourceKind'];
15
+ frameId: string;
16
+ routeHash: string;
17
+ variantId: string | null;
18
+ codeVersion: string;
19
+ renderId: string;
20
+ markerIds: readonly string[];
21
+ sourceMapBytes: number | null;
22
+ sourceMapLookupMs: number | null;
23
+ }
24
+ export interface PreviewV2RevealSourceRequest extends PreviewV2SourceIdentityRequest {
25
+ behavior?: {
26
+ scroll?: boolean;
27
+ flash?: boolean;
28
+ durationMs?: number;
29
+ };
30
+ }
31
+ export interface PreviewV2RevealSliceRequest {
32
+ documentId: string;
33
+ sliceKey: string;
34
+ behavior?: {
35
+ scroll?: boolean;
36
+ flash?: boolean;
37
+ durationMs?: number;
38
+ };
39
+ }
40
+ export interface PreviewRevealCommands {
41
+ resolvePreviewV2SourceIdentity: (request: PreviewV2SourceIdentityRequest) => PreviewV2SourceIdentity | null;
42
+ revealPreviewV2Source: (request: PreviewV2RevealSourceRequest) => boolean;
43
+ revealPreviewV2Slice: (request: PreviewV2RevealSliceRequest) => boolean;
44
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,20 @@
1
+ export interface PreviewRichTextSliceEmbedAddress {
2
+ readonly rootPath: string;
3
+ readonly index: number;
4
+ readonly navigationPath: string;
5
+ }
6
+ /**
7
+ * Rich-text slice embeds are addressed as editorial slice instances:
8
+ * `<richtextField>[embedOrdinal]`, e.g. `body[0]` or `meta.body[2]`.
9
+ *
10
+ * The ordinal counts only `sliceEmbed` atoms, not ProseMirror `content[]`
11
+ * nodes. This deliberately avoids leaking `attrs.data` or paragraph nodes
12
+ * into the Studio/provenance contract.
13
+ */
14
+ export declare function parsePreviewRichTextSliceEmbedAddress(path: string, expectedIndex?: number): PreviewRichTextSliceEmbedAddress | null;
15
+ export declare function formatPreviewRichTextSliceEmbedPath(rootPath: string, index: number): string | null;
16
+ export declare const richTextSliceEmbedAddressFromPath: typeof parsePreviewRichTextSliceEmbedAddress;
17
+ export declare function richTextSliceEmbedKeyFromAnchors(anchors: ReadonlyArray<{
18
+ pathPrefix: string;
19
+ key: string;
20
+ }> | undefined, rootPath: string): string | undefined;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Rich-text slice embeds are addressed as editorial slice instances:
3
+ * `<richtextField>[embedOrdinal]`, e.g. `body[0]` or `meta.body[2]`.
4
+ *
5
+ * The ordinal counts only `sliceEmbed` atoms, not ProseMirror `content[]`
6
+ * nodes. This deliberately avoids leaking `attrs.data` or paragraph nodes
7
+ * into the Studio/provenance contract.
8
+ */
9
+ export function parsePreviewRichTextSliceEmbedAddress(path, expectedIndex) {
10
+ const match = /^(body|.*\.body)\[(\d+)\](?:\.|$)/.exec(path);
11
+ if (match === null)
12
+ return null;
13
+ const index = Number.parseInt(match[2], 10);
14
+ if (!Number.isInteger(index) || index < 0)
15
+ return null;
16
+ if (expectedIndex !== undefined && index !== expectedIndex)
17
+ return null;
18
+ const rootPath = match[1];
19
+ return {
20
+ rootPath,
21
+ index,
22
+ navigationPath: `${rootPath}[${index}]`,
23
+ };
24
+ }
25
+ export function formatPreviewRichTextSliceEmbedPath(rootPath, index) {
26
+ if (rootPath.length === 0)
27
+ return null;
28
+ if (!Number.isInteger(index) || index < 0)
29
+ return null;
30
+ return `${rootPath}[${index}]`;
31
+ }
32
+ export const richTextSliceEmbedAddressFromPath = parsePreviewRichTextSliceEmbedAddress;
33
+ export function richTextSliceEmbedKeyFromAnchors(anchors, rootPath) {
34
+ return anchors?.find(anchor => anchor.pathPrefix === rootPath)?.key;
35
+ }
@@ -0,0 +1 @@
1
+ export declare const previewProvenanceRuntimeScript: string;