@pinegrow/vite-plugin 3.0.72 → 3.0.73-alpha.1

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.
@@ -0,0 +1,60 @@
1
+ export interface AstroRuntimeBridgeOptions {
2
+ markerAttribute?: string
3
+ root?: Document | Element
4
+ win?: Window
5
+ clearPrevious?: boolean
6
+ }
7
+
8
+ export interface AstroElCacheEntry {
9
+ el: Element
10
+ framework: 'astro'
11
+ isAstro: true
12
+ sourceId: string
13
+ pgId: string
14
+ key: string
15
+ localFile: string | null
16
+ sourceFile: string | null
17
+ nodeType: string | null
18
+ name: string
19
+ sourceRange: {
20
+ start: number | null
21
+ end: number | null
22
+ status: string
23
+ }
24
+ sourceStart: number | null
25
+ sourceEnd: number | null
26
+ sourceRangeStatus: string
27
+ marker: unknown
28
+ editability: unknown
29
+ attributes: unknown[]
30
+ isFragment: false
31
+ isRootFragment: false
32
+ isIsland: false
33
+ rootEl: null
34
+ firstEl: Element
35
+ lastEl: Element
36
+ instance: null
37
+ vnode: null
38
+ }
39
+
40
+ export function createAstroElCacheEntry(input: {
41
+ element: Element
42
+ manifest: unknown
43
+ node: unknown
44
+ }): AstroElCacheEntry
45
+
46
+ export function createAstroRuntimeBridge(manifest: unknown, options?: AstroRuntimeBridgeOptions): {
47
+ manifest: unknown
48
+ scan(root?: Document | Element): unknown
49
+ refresh(options?: AstroRuntimeBridgeOptions): unknown
50
+ }
51
+
52
+ export function ensurePinegrowAstroBridge(win?: Window): unknown
53
+
54
+ export function refreshAstroElCache(manifest: unknown, options?: AstroRuntimeBridgeOptions): unknown
55
+
56
+ export function scanAstroSourceDomMarkers(
57
+ root: Document | Element,
58
+ manifest: unknown,
59
+ options?: AstroRuntimeBridgeOptions
60
+ ): unknown
package/astro.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ import type { AstroIntegration } from 'astro'
2
+ import type { LiveDesignerOptions } from './types'
3
+
4
+ export interface PinegrowAstroModuleOptions {
5
+ /**
6
+ * Pinegrow Live Designer options.
7
+ */
8
+ liveDesigner?: {
9
+ [key in string]?: any
10
+ } & LiveDesignerOptions
11
+ }
12
+
13
+ declare function pinegrowAstro(moduleOptions?: PinegrowAstroModuleOptions): AstroIntegration
14
+
15
+ export { pinegrowAstro }
16
+ export default pinegrowAstro
@@ -0,0 +1,326 @@
1
+ const defaultMarkerAttribute = 'data-pg-source-id'
2
+ const astroFrameworkKey = 'astro'
3
+
4
+ const createFallbackComputed = getter => ({
5
+ get value() {
6
+ return getter()
7
+ },
8
+ })
9
+
10
+ const createFallbackRef = value => ({ value })
11
+
12
+ const readWatchSource = source => {
13
+ if (typeof source === 'function') {
14
+ return source()
15
+ }
16
+
17
+ return source?.value
18
+ }
19
+
20
+ const createFallbackWatch = (source, callback, options = {}) => {
21
+ if (options.immediate && typeof callback === 'function') {
22
+ callback(readWatchSource(source), undefined)
23
+ }
24
+
25
+ return () => {}
26
+ }
27
+
28
+ const createAstroSyntheticInstance = (manifest, node) => ({
29
+ uid: `astro:${node.id}`,
30
+ isMounted: true,
31
+ isUnmounted: false,
32
+ type: {
33
+ __name: node.name || 'AstroElement',
34
+ __file: manifest.sourceFile || null,
35
+ },
36
+ appContext: null,
37
+ })
38
+
39
+ const getDefaultWindow = () => {
40
+ if (typeof window !== 'undefined') {
41
+ return window
42
+ }
43
+
44
+ return null
45
+ }
46
+
47
+ const isMapLike = value =>
48
+ value &&
49
+ typeof value.get === 'function' &&
50
+ typeof value.set === 'function' &&
51
+ typeof value.delete === 'function' &&
52
+ typeof value.entries === 'function'
53
+
54
+ const getMarkerAttribute = (manifest, options = {}) =>
55
+ options.markerAttribute || manifest?.marker?.attribute || defaultMarkerAttribute
56
+
57
+ const getManifestSourceKey = manifest => manifest?.sourceFile || manifest?.id || null
58
+
59
+ const normalizeElCacheEntries = entries => Array.isArray(entries) ? entries : []
60
+
61
+ const createNodeIndex = manifest => {
62
+ const index = new Map()
63
+
64
+ ;(manifest?.nodes || []).forEach(node => {
65
+ if (node?.id) {
66
+ index.set(node.id, node)
67
+ }
68
+ })
69
+
70
+ return index
71
+ }
72
+
73
+ const queryMarkerElements = (root, markerAttribute) => {
74
+ if (!root || typeof root.querySelectorAll !== 'function') {
75
+ return []
76
+ }
77
+
78
+ return Array.from(root.querySelectorAll(`[${markerAttribute}]`))
79
+ }
80
+
81
+ const getElementMarkerId = (element, markerAttribute) => {
82
+ if (!element || typeof element.getAttribute !== 'function') {
83
+ return null
84
+ }
85
+
86
+ return element.getAttribute(markerAttribute)
87
+ }
88
+
89
+ const createAstroElCacheEntry = ({ element, manifest, node }) => {
90
+ const sourceRange = {
91
+ start: node.sourceStart ?? null,
92
+ end: node.sourceEnd ?? null,
93
+ status: node.sourceRangeStatus || 'unknown',
94
+ }
95
+
96
+ return {
97
+ el: element,
98
+ framework: astroFrameworkKey,
99
+ isAstro: true,
100
+ sourceId: node.id,
101
+ pgId: node.id,
102
+ key: node.id,
103
+ localFile: manifest.sourceFile || null,
104
+ sourceFile: manifest.sourceFile || null,
105
+ nodeType: node.type || null,
106
+ name: node.name || '',
107
+ sourceRange,
108
+ sourceStart: sourceRange.start,
109
+ sourceEnd: sourceRange.end,
110
+ sourceRangeStatus: sourceRange.status,
111
+ marker: node.marker || null,
112
+ editability: node.editability || null,
113
+ attributes: node.attributes || [],
114
+ isFragment: false,
115
+ isRootFragment: false,
116
+ isIsland: false,
117
+ rootEl: null,
118
+ firstEl: element,
119
+ lastEl: element,
120
+ instance: createAstroSyntheticInstance(manifest, node),
121
+ vnode: null,
122
+ }
123
+ }
124
+
125
+ const scanAstroSourceDomMarkers = (root, manifest, options = {}) => {
126
+ const markerAttribute = getMarkerAttribute(manifest, options)
127
+ const entries = []
128
+ const missing = []
129
+
130
+ if (manifest?.status !== 'ready') {
131
+ return {
132
+ status: 'unavailable',
133
+ markerAttribute,
134
+ entries,
135
+ missing,
136
+ reason: manifest?.reason || 'Astro source manifest is unavailable.',
137
+ }
138
+ }
139
+
140
+ if (!root || typeof root.querySelectorAll !== 'function') {
141
+ return {
142
+ status: 'unavailable',
143
+ markerAttribute,
144
+ entries,
145
+ missing,
146
+ reason: 'A DOM root with querySelectorAll() is required.',
147
+ }
148
+ }
149
+
150
+ const nodeIndex = createNodeIndex(manifest)
151
+
152
+ queryMarkerElements(root, markerAttribute).forEach(element => {
153
+ const sourceId = getElementMarkerId(element, markerAttribute)
154
+ const node = nodeIndex.get(sourceId)
155
+
156
+ if (!node) {
157
+ missing.push({ element, sourceId })
158
+ return
159
+ }
160
+
161
+ entries.push(createAstroElCacheEntry({ element, manifest, node }))
162
+ })
163
+
164
+ return {
165
+ status: 'ready',
166
+ markerAttribute,
167
+ entries,
168
+ missing,
169
+ }
170
+ }
171
+
172
+ const ensurePinegrowAstroBridge = (win = getDefaultWindow()) => {
173
+ if (!win) {
174
+ return null
175
+ }
176
+
177
+ if (!win.pinegrow) {
178
+ win.pinegrow = {}
179
+ }
180
+
181
+ if (typeof win.pinegrow.reactiveFromContext !== 'function') {
182
+ win.pinegrow.reactiveFromContext = value => value
183
+ }
184
+
185
+ if (typeof win.pinegrow.refFromContext !== 'function') {
186
+ win.pinegrow.refFromContext = createFallbackRef
187
+ }
188
+
189
+ if (typeof win.pinegrow.computedFromContext !== 'function') {
190
+ win.pinegrow.computedFromContext = createFallbackComputed
191
+ }
192
+
193
+ if (typeof win.pinegrow.watchFromContext !== 'function') {
194
+ win.pinegrow.watchFromContext = createFallbackWatch
195
+ }
196
+
197
+ if (!isMapLike(win.pinegrow.elCache)) {
198
+ win.pinegrow.elCache = new Map()
199
+ }
200
+
201
+ if (!win.pinegrow.astro) {
202
+ win.pinegrow.astro = {}
203
+ }
204
+
205
+ if (!isMapLike(win.pinegrow.astro.sourceManifests)) {
206
+ win.pinegrow.astro.sourceManifests = new Map()
207
+ }
208
+
209
+ return win.pinegrow
210
+ }
211
+
212
+ const isAstroEntryForSource = (entry, sourceKey) =>
213
+ entry?.framework === astroFrameworkKey &&
214
+ (entry.localFile === sourceKey || entry.sourceFile === sourceKey)
215
+
216
+ const removeAstroEntriesForManifest = (elCache, manifest) => {
217
+ const sourceKey = getManifestSourceKey(manifest)
218
+ let removed = 0
219
+ const elements = []
220
+
221
+ if (!sourceKey) {
222
+ return { elements, removed }
223
+ }
224
+
225
+ Array.from(elCache.entries()).forEach(([element, entries]) => {
226
+ const currentEntries = normalizeElCacheEntries(entries)
227
+ const nextEntries = currentEntries.filter(entry => !isAstroEntryForSource(entry, sourceKey))
228
+ const removedForElement = currentEntries.length - nextEntries.length
229
+
230
+ removed += removedForElement
231
+
232
+ if (removedForElement) {
233
+ elements.push(element)
234
+ }
235
+
236
+ if (nextEntries.length) {
237
+ elCache.set(element, nextEntries)
238
+ } else {
239
+ elCache.delete(element)
240
+ }
241
+ })
242
+
243
+ return { elements, removed }
244
+ }
245
+
246
+ const upsertAstroEntry = (elCache, entry) => {
247
+ const existingEntries = normalizeElCacheEntries(elCache.get(entry.el))
248
+ const nextEntries = existingEntries.filter(existingEntry =>
249
+ existingEntry.framework !== astroFrameworkKey ||
250
+ existingEntry.sourceId !== entry.sourceId ||
251
+ existingEntry.localFile !== entry.localFile
252
+ )
253
+
254
+ nextEntries.push(entry)
255
+ elCache.set(entry.el, nextEntries)
256
+ }
257
+
258
+ const refreshAstroElCache = (manifest, options = {}) => {
259
+ const win = options.win || getDefaultWindow()
260
+ const root = options.root || win?.document || null
261
+ const pinegrow = ensurePinegrowAstroBridge(win)
262
+ const scan = scanAstroSourceDomMarkers(root, manifest, options)
263
+
264
+ if (!pinegrow) {
265
+ return {
266
+ ...scan,
267
+ cached: 0,
268
+ removed: 0,
269
+ reason: scan.reason || 'A browser window is required.',
270
+ }
271
+ }
272
+
273
+ if (scan.status !== 'ready') {
274
+ return {
275
+ ...scan,
276
+ cached: 0,
277
+ removed: 0,
278
+ }
279
+ }
280
+
281
+ const removal = options.clearPrevious === false
282
+ ? { elements: [], removed: 0 }
283
+ : removeAstroEntriesForManifest(pinegrow.elCache, manifest)
284
+ const updatedElements = new Set(removal.elements)
285
+
286
+ scan.entries.forEach(entry => {
287
+ upsertAstroEntry(pinegrow.elCache, entry)
288
+ updatedElements.add(entry.el)
289
+ })
290
+
291
+ updatedElements.forEach(element => {
292
+ if (pinegrow.elUpdateHanderFn) {
293
+ pinegrow.elUpdateHanderFn(element)
294
+ }
295
+ })
296
+
297
+ const sourceKey = getManifestSourceKey(manifest)
298
+
299
+ if (sourceKey) {
300
+ pinegrow.astro.sourceManifests.set(sourceKey, manifest)
301
+ }
302
+
303
+ return {
304
+ ...scan,
305
+ cached: scan.entries.length,
306
+ removed: removal.removed,
307
+ }
308
+ }
309
+
310
+ const createAstroRuntimeBridge = (manifest, options = {}) => ({
311
+ manifest,
312
+ scan: root => scanAstroSourceDomMarkers(
313
+ root || options.root || options.win?.document || getDefaultWindow()?.document,
314
+ manifest,
315
+ options
316
+ ),
317
+ refresh: refreshOptions => refreshAstroElCache(manifest, { ...options, ...refreshOptions }),
318
+ })
319
+
320
+ export {
321
+ createAstroElCacheEntry,
322
+ createAstroRuntimeBridge,
323
+ ensurePinegrowAstroBridge,
324
+ refreshAstroElCache,
325
+ scanAstroSourceDomMarkers,
326
+ }