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