@gxp-dev/tools 2.0.63 → 2.0.64
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.
- package/README.md +32 -31
- package/bin/gx-devtools.js +74 -54
- package/bin/lib/cli.js +23 -21
- package/bin/lib/commands/add-dependency.js +366 -325
- package/bin/lib/commands/assets.js +137 -139
- package/bin/lib/commands/build.js +169 -174
- package/bin/lib/commands/datastore.js +181 -183
- package/bin/lib/commands/dev.js +127 -131
- package/bin/lib/commands/extensions.js +147 -149
- package/bin/lib/commands/extract-config.js +73 -67
- package/bin/lib/commands/index.js +12 -12
- package/bin/lib/commands/init.js +342 -240
- package/bin/lib/commands/publish.js +69 -75
- package/bin/lib/commands/socket.js +69 -69
- package/bin/lib/commands/ssl.js +14 -14
- package/bin/lib/constants.js +10 -24
- package/bin/lib/tui/App.tsx +761 -705
- package/bin/lib/tui/components/AIPanel.tsx +191 -171
- package/bin/lib/tui/components/CommandInput.tsx +394 -343
- package/bin/lib/tui/components/GeminiPanel.tsx +175 -151
- package/bin/lib/tui/components/Header.tsx +23 -21
- package/bin/lib/tui/components/LogPanel.tsx +244 -220
- package/bin/lib/tui/components/TabBar.tsx +50 -48
- package/bin/lib/tui/components/WelcomeScreen.tsx +126 -71
- package/bin/lib/tui/index.tsx +37 -39
- package/bin/lib/tui/services/AIService.ts +518 -462
- package/bin/lib/tui/services/ExtensionService.ts +140 -129
- package/bin/lib/tui/services/GeminiService.ts +367 -337
- package/bin/lib/tui/services/ServiceManager.ts +344 -322
- package/bin/lib/tui/services/SocketService.ts +168 -168
- package/bin/lib/tui/services/ViteService.ts +88 -88
- package/bin/lib/tui/services/index.ts +47 -22
- package/bin/lib/utils/ai-scaffold.js +291 -280
- package/bin/lib/utils/extract-config.js +157 -140
- package/bin/lib/utils/files.js +82 -86
- package/bin/lib/utils/index.js +7 -7
- package/bin/lib/utils/paths.js +34 -34
- package/bin/lib/utils/prompts.js +194 -169
- package/bin/lib/utils/ssl.js +79 -81
- package/browser-extensions/README.md +0 -1
- package/browser-extensions/chrome/background.js +244 -237
- package/browser-extensions/chrome/content.js +32 -29
- package/browser-extensions/chrome/devtools.html +7 -7
- package/browser-extensions/chrome/devtools.js +19 -19
- package/browser-extensions/chrome/inspector.js +802 -767
- package/browser-extensions/chrome/manifest.json +71 -63
- package/browser-extensions/chrome/panel.html +674 -636
- package/browser-extensions/chrome/panel.js +722 -712
- package/browser-extensions/chrome/popup.html +586 -543
- package/browser-extensions/chrome/popup.js +282 -244
- package/browser-extensions/chrome/rules.json +1 -1
- package/browser-extensions/chrome/test-chrome.html +216 -136
- package/browser-extensions/chrome/test-mixed-content.html +284 -189
- package/browser-extensions/chrome/test-uri-pattern.html +221 -198
- package/browser-extensions/firefox/README.md +9 -6
- package/browser-extensions/firefox/background.js +221 -218
- package/browser-extensions/firefox/content.js +55 -52
- package/browser-extensions/firefox/debug-errors.html +386 -228
- package/browser-extensions/firefox/debug-https.html +153 -105
- package/browser-extensions/firefox/devtools.html +7 -7
- package/browser-extensions/firefox/devtools.js +23 -20
- package/browser-extensions/firefox/inspector.js +802 -767
- package/browser-extensions/firefox/manifest.json +68 -68
- package/browser-extensions/firefox/panel.html +674 -636
- package/browser-extensions/firefox/panel.js +722 -712
- package/browser-extensions/firefox/popup.html +572 -535
- package/browser-extensions/firefox/popup.js +281 -236
- package/browser-extensions/firefox/test-gramercy.html +170 -125
- package/browser-extensions/firefox/test-imports.html +59 -55
- package/browser-extensions/firefox/test-masking.html +231 -140
- package/browser-extensions/firefox/test-uri-pattern.html +221 -198
- package/dist/tui/App.d.ts +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +154 -150
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/components/AIPanel.d.ts.map +1 -1
- package/dist/tui/components/AIPanel.js +42 -35
- package/dist/tui/components/AIPanel.js.map +1 -1
- package/dist/tui/components/CommandInput.d.ts +1 -1
- package/dist/tui/components/CommandInput.d.ts.map +1 -1
- package/dist/tui/components/CommandInput.js +92 -62
- package/dist/tui/components/CommandInput.js.map +1 -1
- package/dist/tui/components/GeminiPanel.d.ts.map +1 -1
- package/dist/tui/components/GeminiPanel.js +37 -30
- package/dist/tui/components/GeminiPanel.js.map +1 -1
- package/dist/tui/components/Header.d.ts.map +1 -1
- package/dist/tui/components/Header.js +1 -1
- package/dist/tui/components/Header.js.map +1 -1
- package/dist/tui/components/LogPanel.d.ts +1 -1
- package/dist/tui/components/LogPanel.d.ts.map +1 -1
- package/dist/tui/components/LogPanel.js +26 -24
- package/dist/tui/components/LogPanel.js.map +1 -1
- package/dist/tui/components/TabBar.d.ts +2 -2
- package/dist/tui/components/TabBar.d.ts.map +1 -1
- package/dist/tui/components/TabBar.js +11 -11
- package/dist/tui/components/TabBar.js.map +1 -1
- package/dist/tui/components/WelcomeScreen.d.ts.map +1 -1
- package/dist/tui/components/WelcomeScreen.js +6 -6
- package/dist/tui/components/WelcomeScreen.js.map +1 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +8 -8
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/services/AIService.d.ts +2 -2
- package/dist/tui/services/AIService.d.ts.map +1 -1
- package/dist/tui/services/AIService.js +165 -125
- package/dist/tui/services/AIService.js.map +1 -1
- package/dist/tui/services/ExtensionService.d.ts +1 -1
- package/dist/tui/services/ExtensionService.d.ts.map +1 -1
- package/dist/tui/services/ExtensionService.js +33 -26
- package/dist/tui/services/ExtensionService.js.map +1 -1
- package/dist/tui/services/GeminiService.d.ts +1 -1
- package/dist/tui/services/GeminiService.d.ts.map +1 -1
- package/dist/tui/services/GeminiService.js +87 -76
- package/dist/tui/services/GeminiService.js.map +1 -1
- package/dist/tui/services/ServiceManager.d.ts +3 -3
- package/dist/tui/services/ServiceManager.d.ts.map +1 -1
- package/dist/tui/services/ServiceManager.js +72 -58
- package/dist/tui/services/ServiceManager.js.map +1 -1
- package/dist/tui/services/SocketService.d.ts.map +1 -1
- package/dist/tui/services/SocketService.js +32 -32
- package/dist/tui/services/SocketService.js.map +1 -1
- package/dist/tui/services/ViteService.d.ts.map +1 -1
- package/dist/tui/services/ViteService.js +26 -28
- package/dist/tui/services/ViteService.js.map +1 -1
- package/dist/tui/services/index.d.ts +6 -6
- package/dist/tui/services/index.d.ts.map +1 -1
- package/dist/tui/services/index.js +6 -6
- package/dist/tui/services/index.js.map +1 -1
- package/mcp/gxp-api-server.js +83 -81
- package/package.json +109 -93
- package/runtime/PortalContainer.vue +258 -234
- package/runtime/dev-tools/DevToolsModal.vue +153 -155
- package/runtime/dev-tools/LayoutSwitcher.vue +144 -140
- package/runtime/dev-tools/MockDataEditor.vue +456 -433
- package/runtime/dev-tools/SocketSimulator.vue +379 -371
- package/runtime/dev-tools/StoreInspector.vue +517 -455
- package/runtime/dev-tools/index.js +5 -5
- package/runtime/fallback-layouts/PrivateLayout.vue +2 -2
- package/runtime/fallback-layouts/PublicLayout.vue +2 -2
- package/runtime/fallback-layouts/SystemLayout.vue +2 -2
- package/runtime/gxpStringsPlugin.js +159 -134
- package/runtime/index.html +17 -19
- package/runtime/main.js +24 -22
- package/runtime/mock-api/auth-middleware.js +15 -15
- package/runtime/mock-api/image-generator.js +46 -46
- package/runtime/mock-api/index.js +55 -55
- package/runtime/mock-api/response-generator.js +116 -105
- package/runtime/mock-api/route-generator.js +107 -84
- package/runtime/mock-api/socket-triggers.js +94 -93
- package/runtime/mock-api/spec-loader.js +79 -80
- package/runtime/package.json +3 -0
- package/runtime/server.js +68 -68
- package/runtime/stores/gxpPortalConfigStore.js +204 -186
- package/runtime/stores/index.js +2 -2
- package/runtime/vite-inspector-plugin.js +858 -707
- package/runtime/vite-source-tracker-plugin.js +132 -113
- package/runtime/vite.config.js +191 -139
- package/scripts/launch-chrome.js +41 -41
- package/scripts/pack-chrome.js +38 -39
- package/socket-events/AiSessionMessageCreated.json +17 -17
- package/socket-events/SocialStreamPostCreated.json +23 -23
- package/socket-events/SocialStreamPostVariantCompleted.json +22 -22
- package/template/.claude/agents/gxp-developer.md +100 -99
- package/template/.claude/settings.json +7 -7
- package/template/AGENTS.md +30 -23
- package/template/GEMINI.md +20 -20
- package/template/README.md +70 -53
- package/template/app-manifest.json +2 -4
- package/template/configuration.json +10 -10
- package/template/default-styling.css +1 -1
- package/template/index.html +18 -20
- package/template/main.js +24 -22
- package/template/src/DemoPage.vue +415 -362
- package/template/src/Plugin.vue +76 -85
- package/template/src/stores/index.js +3 -3
- package/template/src/stores/test-data.json +164 -172
- package/template/theme-layouts/AdditionalStyling.css +50 -50
- package/template/theme-layouts/PrivateLayout.vue +8 -12
- package/template/theme-layouts/PublicLayout.vue +8 -12
- package/template/theme-layouts/SystemLayout.vue +8 -12
- package/template/vite.extend.js +45 -0
- package/template/vite.config.js +0 -409
|
@@ -23,90 +23,101 @@
|
|
|
23
23
|
* This correctly handles > characters inside quoted attribute values
|
|
24
24
|
*/
|
|
25
25
|
function parseTagsFromHtml(html) {
|
|
26
|
-
const tags = []
|
|
27
|
-
let i = 0
|
|
26
|
+
const tags = []
|
|
27
|
+
let i = 0
|
|
28
28
|
|
|
29
29
|
const VOID_ELEMENTS = new Set([
|
|
30
|
-
"br",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
30
|
+
"br",
|
|
31
|
+
"hr",
|
|
32
|
+
"img",
|
|
33
|
+
"input",
|
|
34
|
+
"meta",
|
|
35
|
+
"link",
|
|
36
|
+
"area",
|
|
37
|
+
"base",
|
|
38
|
+
"col",
|
|
39
|
+
"embed",
|
|
40
|
+
"param",
|
|
41
|
+
"source",
|
|
42
|
+
"track",
|
|
43
|
+
"wbr",
|
|
44
|
+
])
|
|
34
45
|
|
|
35
46
|
while (i < html.length) {
|
|
36
47
|
// Look for tag start
|
|
37
48
|
if (html[i] === "<") {
|
|
38
|
-
const tagStart = i
|
|
39
|
-
i
|
|
49
|
+
const tagStart = i
|
|
50
|
+
i++
|
|
40
51
|
|
|
41
52
|
// Check for closing tag
|
|
42
|
-
const isClosing = html[i] === "/"
|
|
43
|
-
if (isClosing) i
|
|
53
|
+
const isClosing = html[i] === "/"
|
|
54
|
+
if (isClosing) i++
|
|
44
55
|
|
|
45
56
|
// Skip if not a valid tag start (could be < in text or comment)
|
|
46
57
|
if (!/[a-zA-Z]/.test(html[i])) {
|
|
47
|
-
continue
|
|
58
|
+
continue
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
// Parse tag name
|
|
51
|
-
let tagName = ""
|
|
62
|
+
let tagName = ""
|
|
52
63
|
while (i < html.length && /[a-zA-Z0-9-]/.test(html[i])) {
|
|
53
|
-
tagName += html[i]
|
|
54
|
-
i
|
|
64
|
+
tagName += html[i]
|
|
65
|
+
i++
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
// Parse attributes (skip whitespace and attributes until we hit > or />)
|
|
58
|
-
let attrs = ""
|
|
59
|
-
let inDoubleQuote = false
|
|
60
|
-
let inSingleQuote = false
|
|
61
|
-
let foundEnd = false
|
|
62
|
-
let isSelfClosing = false
|
|
69
|
+
let attrs = ""
|
|
70
|
+
let inDoubleQuote = false
|
|
71
|
+
let inSingleQuote = false
|
|
72
|
+
let foundEnd = false
|
|
73
|
+
let isSelfClosing = false
|
|
63
74
|
|
|
64
75
|
while (i < html.length && !foundEnd) {
|
|
65
|
-
const char = html[i]
|
|
76
|
+
const char = html[i]
|
|
66
77
|
|
|
67
78
|
if (inDoubleQuote) {
|
|
68
|
-
attrs += char
|
|
79
|
+
attrs += char
|
|
69
80
|
if (char === '"') {
|
|
70
|
-
inDoubleQuote = false
|
|
81
|
+
inDoubleQuote = false
|
|
71
82
|
}
|
|
72
|
-
i
|
|
83
|
+
i++
|
|
73
84
|
} else if (inSingleQuote) {
|
|
74
|
-
attrs += char
|
|
85
|
+
attrs += char
|
|
75
86
|
if (char === "'") {
|
|
76
|
-
inSingleQuote = false
|
|
87
|
+
inSingleQuote = false
|
|
77
88
|
}
|
|
78
|
-
i
|
|
89
|
+
i++
|
|
79
90
|
} else if (char === '"') {
|
|
80
|
-
attrs += char
|
|
81
|
-
inDoubleQuote = true
|
|
82
|
-
i
|
|
91
|
+
attrs += char
|
|
92
|
+
inDoubleQuote = true
|
|
93
|
+
i++
|
|
83
94
|
} else if (char === "'") {
|
|
84
|
-
attrs += char
|
|
85
|
-
inSingleQuote = true
|
|
86
|
-
i
|
|
95
|
+
attrs += char
|
|
96
|
+
inSingleQuote = true
|
|
97
|
+
i++
|
|
87
98
|
} else if (char === "/" && html[i + 1] === ">") {
|
|
88
|
-
isSelfClosing = true
|
|
89
|
-
i += 2
|
|
90
|
-
foundEnd = true
|
|
99
|
+
isSelfClosing = true
|
|
100
|
+
i += 2
|
|
101
|
+
foundEnd = true
|
|
91
102
|
} else if (char === ">") {
|
|
92
|
-
i
|
|
93
|
-
foundEnd = true
|
|
103
|
+
i++
|
|
104
|
+
foundEnd = true
|
|
94
105
|
} else {
|
|
95
|
-
attrs += char
|
|
96
|
-
i
|
|
106
|
+
attrs += char
|
|
107
|
+
i++
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
110
|
|
|
100
111
|
if (!foundEnd) {
|
|
101
112
|
// Malformed tag, skip
|
|
102
|
-
continue
|
|
113
|
+
continue
|
|
103
114
|
}
|
|
104
115
|
|
|
105
|
-
const fullMatch = html.substring(tagStart, i)
|
|
116
|
+
const fullMatch = html.substring(tagStart, i)
|
|
106
117
|
|
|
107
118
|
// Check for void elements
|
|
108
119
|
if (!isSelfClosing && VOID_ELEMENTS.has(tagName.toLowerCase())) {
|
|
109
|
-
isSelfClosing = true
|
|
120
|
+
isSelfClosing = true
|
|
110
121
|
}
|
|
111
122
|
|
|
112
123
|
tags.push({
|
|
@@ -116,71 +127,71 @@ function parseTagsFromHtml(html) {
|
|
|
116
127
|
fullMatch,
|
|
117
128
|
isClosing,
|
|
118
129
|
isSelfClosing,
|
|
119
|
-
})
|
|
130
|
+
})
|
|
120
131
|
} else {
|
|
121
|
-
i
|
|
132
|
+
i++
|
|
122
133
|
}
|
|
123
134
|
}
|
|
124
135
|
|
|
125
|
-
return tags
|
|
136
|
+
return tags
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
/**
|
|
129
140
|
* Create the source tracker plugin
|
|
130
141
|
*/
|
|
131
142
|
export function gxpSourceTrackerPlugin(options = {}) {
|
|
132
|
-
const { enabled = true, attrName = "data-gxp-expr" } = options
|
|
143
|
+
const { enabled = true, attrName = "data-gxp-expr" } = options
|
|
133
144
|
|
|
134
145
|
return {
|
|
135
146
|
name: "gxp-source-tracker",
|
|
136
147
|
enforce: "pre",
|
|
137
148
|
|
|
138
149
|
apply(config, { command }) {
|
|
139
|
-
return enabled && command === "serve"
|
|
150
|
+
return enabled && command === "serve"
|
|
140
151
|
},
|
|
141
152
|
|
|
142
153
|
transform(code, id) {
|
|
143
154
|
if (!id.endsWith(".vue")) {
|
|
144
|
-
return null
|
|
155
|
+
return null
|
|
145
156
|
}
|
|
146
157
|
|
|
147
|
-
const templateMatch = code.match(/<template>([\s\S]*?)<\/template>/)
|
|
158
|
+
const templateMatch = code.match(/<template>([\s\S]*?)<\/template>/)
|
|
148
159
|
if (!templateMatch) {
|
|
149
|
-
return null
|
|
160
|
+
return null
|
|
150
161
|
}
|
|
151
162
|
|
|
152
163
|
// Debug: log which file we're processing
|
|
153
|
-
const fileName = id.split("/").pop()
|
|
154
|
-
console.log(`[GxP Source Tracker] Processing: ${fileName}`)
|
|
164
|
+
const fileName = id.split("/").pop()
|
|
165
|
+
console.log(`[GxP Source Tracker] Processing: ${fileName}`)
|
|
155
166
|
|
|
156
|
-
let template = templateMatch[1]
|
|
157
|
-
let modified = false
|
|
167
|
+
let template = templateMatch[1]
|
|
168
|
+
let modified = false
|
|
158
169
|
|
|
159
170
|
// Process each element that has {{ expression }} as its content
|
|
160
171
|
// Strategy: Find each {{ expression }} and trace back to find its parent element
|
|
161
172
|
|
|
162
|
-
const exprPattern = /\{\{([\s\S]*?)\}\}/g
|
|
163
|
-
let match
|
|
173
|
+
const exprPattern = /\{\{([\s\S]*?)\}\}/g
|
|
174
|
+
let match
|
|
164
175
|
|
|
165
176
|
// Map to track which elements we've already added attributes to
|
|
166
177
|
// Key: element start position, Value: array of expressions
|
|
167
|
-
const elementExpressions = new Map()
|
|
178
|
+
const elementExpressions = new Map()
|
|
168
179
|
|
|
169
180
|
while ((match = exprPattern.exec(template)) !== null) {
|
|
170
|
-
const exprStart = match.index
|
|
171
|
-
const expression = match[1].trim()
|
|
181
|
+
const exprStart = match.index
|
|
182
|
+
const expression = match[1].trim()
|
|
172
183
|
|
|
173
184
|
// Find the opening tag that contains this expression
|
|
174
185
|
// Look backwards from the expression to find the nearest unclosed tag
|
|
175
|
-
const beforeExpr = template.substring(0, exprStart)
|
|
186
|
+
const beforeExpr = template.substring(0, exprStart)
|
|
176
187
|
|
|
177
188
|
// Use state-machine parser for reliable tag parsing
|
|
178
|
-
const tags = parseTagsFromHtml(beforeExpr)
|
|
189
|
+
const tags = parseTagsFromHtml(beforeExpr)
|
|
179
190
|
|
|
180
191
|
// Walk through tags to find the immediate parent (last unclosed tag)
|
|
181
|
-
const stack = []
|
|
192
|
+
const stack = []
|
|
182
193
|
for (const tag of tags) {
|
|
183
|
-
if (tag.isSelfClosing) continue
|
|
194
|
+
if (tag.isSelfClosing) continue
|
|
184
195
|
|
|
185
196
|
if (tag.isClosing) {
|
|
186
197
|
// Pop from stack
|
|
@@ -189,152 +200,160 @@ export function gxpSourceTrackerPlugin(options = {}) {
|
|
|
189
200
|
stack[stack.length - 1].tagName.toLowerCase() ===
|
|
190
201
|
tag.tagName.toLowerCase()
|
|
191
202
|
) {
|
|
192
|
-
stack.pop()
|
|
203
|
+
stack.pop()
|
|
193
204
|
}
|
|
194
205
|
} else {
|
|
195
|
-
stack.push(tag)
|
|
206
|
+
stack.push(tag)
|
|
196
207
|
}
|
|
197
208
|
}
|
|
198
209
|
|
|
199
210
|
// The last item in the stack is our parent element
|
|
200
211
|
if (stack.length > 0) {
|
|
201
|
-
const parentTagInfo = stack[stack.length - 1]
|
|
212
|
+
const parentTagInfo = stack[stack.length - 1]
|
|
202
213
|
|
|
203
214
|
// Skip script/style tags
|
|
204
215
|
if (
|
|
205
216
|
["script", "style"].includes(parentTagInfo.tagName.toLowerCase())
|
|
206
217
|
) {
|
|
207
|
-
continue
|
|
218
|
+
continue
|
|
208
219
|
}
|
|
209
220
|
|
|
210
221
|
// Skip if already has data-gxp-expr in the original attrs
|
|
211
222
|
if (parentTagInfo.attrs.includes(attrName)) {
|
|
212
|
-
continue
|
|
223
|
+
continue
|
|
213
224
|
}
|
|
214
225
|
|
|
215
226
|
// Add this expression to the parent element's list
|
|
216
|
-
const key = parentTagInfo.start
|
|
227
|
+
const key = parentTagInfo.start
|
|
217
228
|
if (!elementExpressions.has(key)) {
|
|
218
229
|
elementExpressions.set(key, {
|
|
219
230
|
tagInfo: parentTagInfo,
|
|
220
231
|
expressions: [],
|
|
221
|
-
})
|
|
232
|
+
})
|
|
222
233
|
}
|
|
223
|
-
elementExpressions.get(key).expressions.push(expression)
|
|
234
|
+
elementExpressions.get(key).expressions.push(expression)
|
|
224
235
|
}
|
|
225
236
|
}
|
|
226
237
|
|
|
227
238
|
// Now build replacements for each element that has expressions
|
|
228
|
-
const replacements = []
|
|
239
|
+
const replacements = []
|
|
229
240
|
|
|
230
241
|
for (const [start, data] of elementExpressions) {
|
|
231
|
-
const { tagInfo, expressions } = data
|
|
242
|
+
const { tagInfo, expressions } = data
|
|
232
243
|
|
|
233
244
|
// Only add expressions that are direct children (not from nested elements)
|
|
234
245
|
// For now, take all unique expressions
|
|
235
|
-
const uniqueExprs = [...new Set(expressions)]
|
|
236
|
-
const exprValue = uniqueExprs.join("; ")
|
|
246
|
+
const uniqueExprs = [...new Set(expressions)]
|
|
247
|
+
const exprValue = uniqueExprs.join("; ")
|
|
237
248
|
|
|
238
|
-
const oldOpenTag = tagInfo.fullMatch
|
|
249
|
+
const oldOpenTag = tagInfo.fullMatch
|
|
239
250
|
// Insert the attribute before the closing > or />
|
|
240
|
-
let newOpenTag
|
|
251
|
+
let newOpenTag
|
|
241
252
|
if (oldOpenTag.endsWith("/>")) {
|
|
242
|
-
newOpenTag =
|
|
253
|
+
newOpenTag =
|
|
254
|
+
oldOpenTag.slice(0, -2) +
|
|
255
|
+
` ${attrName}="${escapeAttr(exprValue)}"/>`
|
|
243
256
|
} else {
|
|
244
|
-
newOpenTag =
|
|
257
|
+
newOpenTag =
|
|
258
|
+
oldOpenTag.slice(0, -1) + ` ${attrName}="${escapeAttr(exprValue)}">`
|
|
245
259
|
}
|
|
246
260
|
|
|
247
261
|
replacements.push({
|
|
248
262
|
start: tagInfo.start,
|
|
249
263
|
oldText: oldOpenTag,
|
|
250
264
|
newText: newOpenTag,
|
|
251
|
-
})
|
|
265
|
+
})
|
|
252
266
|
|
|
253
|
-
modified = true
|
|
267
|
+
modified = true
|
|
254
268
|
}
|
|
255
269
|
|
|
256
270
|
// Apply replacements in reverse order to preserve indices
|
|
257
|
-
replacements.sort((a, b) => b.start - a.start)
|
|
271
|
+
replacements.sort((a, b) => b.start - a.start)
|
|
258
272
|
for (const r of replacements) {
|
|
259
273
|
template =
|
|
260
274
|
template.substring(0, r.start) +
|
|
261
275
|
r.newText +
|
|
262
|
-
template.substring(r.start + r.oldText.length)
|
|
276
|
+
template.substring(r.start + r.oldText.length)
|
|
263
277
|
}
|
|
264
278
|
|
|
265
279
|
// Also handle v-html, v-text directives using state-machine approach
|
|
266
|
-
template = addAttrToDirective(template, "v-html", attrName)
|
|
267
|
-
template = addAttrToDirective(template, "v-text", attrName)
|
|
268
|
-
template = addAttrToDirective(template, ":textContent", attrName)
|
|
280
|
+
template = addAttrToDirective(template, "v-html", attrName)
|
|
281
|
+
template = addAttrToDirective(template, "v-text", attrName)
|
|
282
|
+
template = addAttrToDirective(template, ":textContent", attrName)
|
|
269
283
|
|
|
270
284
|
if (!modified && !template.includes(attrName)) {
|
|
271
|
-
console.log(
|
|
272
|
-
|
|
273
|
-
);
|
|
274
|
-
return null;
|
|
285
|
+
console.log(`[GxP Source Tracker] No expressions found in: ${fileName}`)
|
|
286
|
+
return null
|
|
275
287
|
}
|
|
276
288
|
|
|
277
289
|
console.log(
|
|
278
|
-
`[GxP Source Tracker] Added data-gxp-expr to ${elementExpressions.size} elements in: ${fileName}
|
|
279
|
-
)
|
|
290
|
+
`[GxP Source Tracker] Added data-gxp-expr to ${elementExpressions.size} elements in: ${fileName}`,
|
|
291
|
+
)
|
|
280
292
|
const newCode = code.replace(
|
|
281
293
|
/<template>[\s\S]*?<\/template>/,
|
|
282
|
-
`<template>${template}</template
|
|
283
|
-
)
|
|
294
|
+
`<template>${template}</template>`,
|
|
295
|
+
)
|
|
284
296
|
|
|
285
297
|
return {
|
|
286
298
|
code: newCode,
|
|
287
299
|
map: null,
|
|
288
|
-
}
|
|
300
|
+
}
|
|
289
301
|
},
|
|
290
|
-
}
|
|
302
|
+
}
|
|
291
303
|
}
|
|
292
304
|
|
|
293
305
|
/**
|
|
294
306
|
* Add data-gxp-expr attribute to elements with a specific directive
|
|
295
307
|
*/
|
|
296
308
|
function addAttrToDirective(template, directive, attrName) {
|
|
297
|
-
const tags = parseTagsFromHtml(template)
|
|
298
|
-
const replacements = []
|
|
309
|
+
const tags = parseTagsFromHtml(template)
|
|
310
|
+
const replacements = []
|
|
299
311
|
|
|
300
312
|
for (const tag of tags) {
|
|
301
|
-
if (tag.isClosing) continue
|
|
302
|
-
if (tag.fullMatch.includes(attrName)) continue
|
|
313
|
+
if (tag.isClosing) continue
|
|
314
|
+
if (tag.fullMatch.includes(attrName)) continue
|
|
303
315
|
|
|
304
316
|
// Check if this tag has the directive
|
|
305
|
-
const directivePattern = new RegExp(
|
|
306
|
-
|
|
317
|
+
const directivePattern = new RegExp(
|
|
318
|
+
`${escapeRegex(directive)}="([^"]*)"`,
|
|
319
|
+
"g",
|
|
320
|
+
)
|
|
321
|
+
const match = directivePattern.exec(tag.attrs)
|
|
307
322
|
if (match) {
|
|
308
|
-
const exprValue = `${directive}:${match[1]}
|
|
309
|
-
let newOpenTag
|
|
323
|
+
const exprValue = `${directive}:${match[1]}`
|
|
324
|
+
let newOpenTag
|
|
310
325
|
if (tag.fullMatch.endsWith("/>")) {
|
|
311
|
-
newOpenTag =
|
|
326
|
+
newOpenTag =
|
|
327
|
+
tag.fullMatch.slice(0, -2) +
|
|
328
|
+
` ${attrName}="${escapeAttr(exprValue)}"/>`
|
|
312
329
|
} else {
|
|
313
|
-
newOpenTag =
|
|
330
|
+
newOpenTag =
|
|
331
|
+
tag.fullMatch.slice(0, -1) +
|
|
332
|
+
` ${attrName}="${escapeAttr(exprValue)}">`
|
|
314
333
|
}
|
|
315
334
|
|
|
316
335
|
replacements.push({
|
|
317
336
|
start: tag.start,
|
|
318
337
|
oldText: tag.fullMatch,
|
|
319
338
|
newText: newOpenTag,
|
|
320
|
-
})
|
|
339
|
+
})
|
|
321
340
|
}
|
|
322
341
|
}
|
|
323
342
|
|
|
324
343
|
// Apply replacements in reverse order
|
|
325
|
-
replacements.sort((a, b) => b.start - a.start)
|
|
344
|
+
replacements.sort((a, b) => b.start - a.start)
|
|
326
345
|
for (const r of replacements) {
|
|
327
346
|
template =
|
|
328
347
|
template.substring(0, r.start) +
|
|
329
348
|
r.newText +
|
|
330
|
-
template.substring(r.start + r.oldText.length)
|
|
349
|
+
template.substring(r.start + r.oldText.length)
|
|
331
350
|
}
|
|
332
351
|
|
|
333
|
-
return template
|
|
352
|
+
return template
|
|
334
353
|
}
|
|
335
354
|
|
|
336
355
|
function escapeRegex(str) {
|
|
337
|
-
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
|
356
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
|
|
338
357
|
}
|
|
339
358
|
|
|
340
359
|
function escapeAttr(str) {
|
|
@@ -343,7 +362,7 @@ function escapeAttr(str) {
|
|
|
343
362
|
.replace(/"/g, """)
|
|
344
363
|
.replace(/'/g, "'")
|
|
345
364
|
.replace(/</g, "<")
|
|
346
|
-
.replace(/>/g, ">")
|
|
365
|
+
.replace(/>/g, ">")
|
|
347
366
|
}
|
|
348
367
|
|
|
349
|
-
export default gxpSourceTrackerPlugin
|
|
368
|
+
export default gxpSourceTrackerPlugin
|