@pinegrow/vite-plugin 3.0.0-beta.4 → 3.0.0-beta.41

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 @@
1
+ declare module '@pinegrow/vite-plugin'
@@ -0,0 +1,303 @@
1
+ import { onBeforeMount, onMounted, onBeforeUnmount, getCurrentInstance, ref, reactive, computed } from 'vue'
2
+
3
+ export function usePinegrow() {
4
+ const initCache = () => {
5
+ // conditional
6
+ const winObj = window
7
+
8
+ if (!(winObj?.process?.client && winObj.process.client !== true)) {
9
+ if (!winObj.pinegrow) {
10
+ // conditional
11
+ // console.log('Cache initialized by Pinegrow Vue Plugin!')
12
+ const elCache = reactive(new Map())
13
+
14
+ // const enRichWithComponentName = elCacheObj => {
15
+ // return {
16
+ // name:
17
+ // getComponentName(elCacheObj.instance.type, elCacheObj.localFile) +
18
+ // `${elCacheObj.key !== undefined && elCacheObj.key !== null ? ` (${elCacheObj.key})` : ''}`,
19
+ // ...elCacheObj,
20
+ // }
21
+ // }
22
+
23
+ const enRichWithComponentName = elCacheObj => {
24
+ return {
25
+ name: elCacheObj.instance.type.__name || '',
26
+ ...elCacheObj,
27
+ }
28
+ }
29
+
30
+ const rootFragmentToPgIdComputed = computed(() => {
31
+ const rootEls = new Map()
32
+ for (let [key, value] of elCache.entries()) {
33
+ if (value.instance.isMounted && !value.instance.isUnmounted && value.isRootFragment) {
34
+ rootEls.set(key, value)
35
+ }
36
+ }
37
+ return rootEls
38
+ })
39
+
40
+ const pgIdToElComputed = computed(() => {
41
+ const pgIds = {}
42
+ for (let [key, value] of elCache.entries()) {
43
+ if (
44
+ value.instance.isMounted &&
45
+ !value.instance.isUnmounted &&
46
+ value.pgId &&
47
+ (!value.rootEl || value.isRootFragment)
48
+ ) {
49
+ if (!pgIds[value.pgId]) {
50
+ pgIds[value.pgId] = []
51
+ }
52
+ if (value.key === undefined || value.key === null) {
53
+ pgIds[value.pgId].push(value)
54
+ } else {
55
+ pgIds[value.pgId].push([value.key, value])
56
+ }
57
+ }
58
+ }
59
+ return pgIds
60
+ })
61
+
62
+ const localComponentToElComputed = computed(() => {
63
+ const localComponents = {}
64
+ for (let [key, value] of elCache.entries()) {
65
+ if (
66
+ value.instance.isMounted &&
67
+ !value.instance.isUnmounted &&
68
+ value.localFile &&
69
+ (!value.rootEl || value.isRootFragment)
70
+ ) {
71
+ if (!localComponents[value.localFile]) {
72
+ localComponents[value.localFile] = []
73
+ }
74
+ localComponents[value.localFile].push(enRichWithComponentName(value))
75
+ }
76
+ }
77
+ return localComponents
78
+ })
79
+
80
+ const appTree = computed(() => {
81
+ const appTreeNodes = Object.values(localComponentToElComputed.value).reduce(
82
+ (acc, localComponent) => [...acc, ...localComponent],
83
+ []
84
+ )
85
+ const appTreeNodesSorted = appTreeNodes.sort((a, b) =>
86
+ a.el.compareDocumentPosition(b.el) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
87
+ )
88
+ return appTreeNodesSorted
89
+ })
90
+
91
+ winObj.pinegrow = {
92
+ elCache,
93
+ // // Uncomment these two to test locally
94
+ // elCacheErrHandlerFn,
95
+ // elUpdateHanderFn,
96
+ rootFragmentToPgIdComputed,
97
+ pgIdToElComputed,
98
+ localComponentToElComputed,
99
+ appTree,
100
+ }
101
+ }
102
+ }
103
+ }
104
+
105
+ // pgId & key can be optional
106
+ const pgUpdateElCache = (hook, pgId, rootEl, key, localFile) => async vnode => {
107
+ if (!vnode) return
108
+ if (window?.process?.client && process?.client !== true) return
109
+ if (!window.pinegrow) initCache()
110
+
111
+ let el = vnode.el
112
+ const instance = vnode.component || vnode.ctx || el.__vueParentComponent
113
+
114
+ try {
115
+ if ((key !== null && key !== undefined) || (vnode.key !== null && vnode.key !== undefined)) {
116
+ key = key || vnode.key
117
+ }
118
+ localFile =
119
+ localFile || (vnode.type.__file && !vnode.type.__file.includes('node_modules') && vnode.type.__file)
120
+
121
+ let isRootFragment = false
122
+ let isFragment = el.nodeType !== 1
123
+ let firstEl, lastEl
124
+
125
+ // // Computed props anyway filters out unmounted ones, and we use the local components unmounted hooks to cleanup unmounted nodes. Using the unmounted hook seems to be out of sync when el is reused but instance is remounted.
126
+ // if (hook === 'unmounted') {
127
+ // if (pinegrow.elCache.has(el)) {
128
+ // pinegrow.elCache.delete(el)
129
+ // }
130
+ // for (let [key, value] of pinegrow.elCache.entries()) {
131
+ // if (value.rootEl === rootEl) {
132
+ // pinegrow.elCache.delete(key)
133
+ // }
134
+ // }
135
+ // return
136
+ // }
137
+
138
+ if (pinegrow.elCache.has(el)) {
139
+ // pgId could have been updated
140
+ if (pgId) {
141
+ pinegrow.elCache.get(el).pgId = pgId
142
+ }
143
+ if (key !== null && key !== undefined) {
144
+ pinegrow.elCache.get(el).key = key
145
+ }
146
+ if (localFile) {
147
+ pinegrow.elCache.get(el).localFile = localFile
148
+ }
149
+ } else {
150
+ // Text/comment node
151
+ if (isFragment) {
152
+ if (!rootEl) {
153
+ // root Fragment
154
+ isRootFragment = true
155
+ }
156
+
157
+ function isFragmentEl(instance) {
158
+ // return appRecord.options.types.Fragment === instance.subTree?.type
159
+ return instance.subTree.el.nodeType !== 1
160
+ }
161
+
162
+ function getRootVNodesFromComponentInstance(instance) {
163
+ if (isFragmentEl(instance)) {
164
+ return getFragmentRootVNodes(instance.subTree)
165
+ }
166
+ if (!instance.subTree) return []
167
+ return [instance.subTree]
168
+ }
169
+
170
+ function getFragmentRootVNodes(vnode) {
171
+ if (!vnode.children) return []
172
+
173
+ const list = []
174
+
175
+ for (let i = 0, l = vnode.children.length; i < l; i++) {
176
+ const childVnode = vnode.children[i]
177
+ if (childVnode.component) {
178
+ list.push(...getRootVNodesFromComponentInstance(childVnode.component))
179
+ } else if (childVnode) {
180
+ list.push(childVnode)
181
+ }
182
+ }
183
+
184
+ return list
185
+ }
186
+
187
+ let childVNodes = getRootVNodesFromComponentInstance(instance)
188
+
189
+ if (!childVNodes.length) {
190
+ // For NuxtLayout, no childVNodes are returned, the subTree.children is in fact an object {ctx: {}, default: f}
191
+ if (el.nextElementSibling) {
192
+ const childEl = el.nextElementSibling
193
+ firstEl = lastEl = childEl
194
+ const childInstance = childEl.$ || childEl.__vueParentComponent
195
+ const childVNode = childInstance?.vnode // or subTree?
196
+ if (childVNode) {
197
+ childVNodes.push(childVNode)
198
+ }
199
+ }
200
+ }
201
+
202
+ if (childVNodes.length) {
203
+ // Filter out recursive vnodes text1 -> div, text1 (happens when text1 is the closest to a fragment with div & slot)
204
+ childVNodes = childVNodes.filter(childVNode => childVNode.el !== el)
205
+
206
+ if (childVNodes.length === 1) {
207
+ firstEl = lastEl = childVNodes[0].el
208
+ } else {
209
+ firstEl = childVNodes[0].el
210
+ lastEl = childVNodes[childVNodes.length - 1].el
211
+ }
212
+
213
+ childVNodes.forEach(childVNode => {
214
+ pgUpdateElCache(hook, pgId, isRootFragment ? el : rootEl, key)(childVNode)
215
+ })
216
+ }
217
+ }
218
+
219
+ pinegrow.elCache.set(el, {
220
+ el,
221
+ isRootFragment,
222
+ rootEl,
223
+ vnode,
224
+ instance,
225
+ isFragment,
226
+ firstEl,
227
+ lastEl,
228
+ pgId,
229
+ key,
230
+ localFile,
231
+ })
232
+ }
233
+
234
+ if (pinegrow.elUpdateHanderFn) {
235
+ pinegrow.elUpdateHanderFn(el)
236
+ }
237
+ } catch (err) {
238
+ if (pinegrow.elCacheErrHandlerFn) {
239
+ pinegrow.elCacheErrHandlerFn(vnode, hook, rootEl, pgId, key, el, instance, err.message)
240
+ }
241
+ }
242
+ }
243
+
244
+ const elUpdateHanderFn = el => {
245
+ // if (pinegrow.elCache.has(el)) {
246
+ // const { pgId } = pinegrow.elCache.get(el)
247
+ // if (pgId) {
248
+ // // console.log(`Reselect ${pgId}`)
249
+ // }
250
+ // }
251
+ }
252
+
253
+ const elCacheErrHandlerFn = () => {
254
+ if (message) {
255
+ console.log(message)
256
+ }
257
+ }
258
+
259
+ const cleanupCache = () => {
260
+ // for (let [key, value] of pinegrow.elCache.entries()) {
261
+ // if (value.isFragment && !value.firstEl) {
262
+ // console.log(value)
263
+ // }
264
+ // }
265
+ for (let [key, value] of pinegrow.elCache.entries()) {
266
+ if (value.instance.isUnmounted) {
267
+ pinegrow.elCache.delete(key)
268
+ // console.log(value)
269
+ }
270
+ }
271
+ }
272
+
273
+ // Local Component
274
+ const rootVNode = ref(null)
275
+
276
+ const mountLocalComponent = () => {
277
+ const instance = getCurrentInstance()
278
+ const vnode = instance?.vnode
279
+ const el = vnode?.el
280
+ const localFile = instance.type.__file && !instance.type.__file.includes('node_modules') && instance.type.__file
281
+
282
+ if (instance && vnode && el) {
283
+ rootVNode.value = vnode
284
+ pgUpdateElCache('mounted', null, null, null, localFile)(vnode)
285
+ }
286
+ }
287
+
288
+ const unmountLocalComponent = () => {
289
+ if (rootVNode.value) {
290
+ pgUpdateElCache('unmounted')(rootVNode.value)
291
+ }
292
+ cleanupCache()
293
+ }
294
+
295
+ onBeforeMount(() => initCache())
296
+ onMounted(() => {
297
+ mountLocalComponent()
298
+ })
299
+ onBeforeUnmount(() => unmountLocalComponent())
300
+
301
+ return { pgUpdateElCache }
302
+ }
303
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pinegrow/vite-plugin",
3
- "version": "3.0.0-beta.4",
3
+ "version": "3.0.0-beta.41",
4
4
  "description": "Pinegrow Vite Plugin",
5
5
  "type": "module",
6
6
  "files": [
@@ -8,6 +8,7 @@
8
8
  ],
9
9
  "main": "./dist/index.cjs",
10
10
  "module": "./dist/index.cjs",
11
+ "types": "./types.d.ts",
11
12
  "exports": {
12
13
  ".": {
13
14
  "import": "./dist/index.cjs",
@@ -16,6 +17,9 @@
16
17
  "./dev": {
17
18
  "import": "./src/index.js",
18
19
  "require": "./src/index.js"
20
+ },
21
+ "./vue": {
22
+ "import": "./dist/vue-plugin.js"
19
23
  }
20
24
  },
21
25
  "keywords": [
@@ -33,7 +37,8 @@
33
37
  "increment-beta-version": "npm version prerelease --preid=beta"
34
38
  },
35
39
  "dependencies": {
36
- "node-html-parser": "^5.2.0",
37
- "@pinegrow/tailwind-plugin": "latest"
40
+ "@vue/compiler-sfc": "^3.2.45",
41
+ "magic-string": "^0.27.0",
42
+ "node-html-parser": "^5.2.0"
38
43
  }
39
44
  }