@gxp-dev/tools 2.0.62 → 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.
Files changed (182) hide show
  1. package/README.md +32 -31
  2. package/bin/gx-devtools.js +74 -54
  3. package/bin/lib/cli.js +23 -21
  4. package/bin/lib/commands/add-dependency.js +366 -325
  5. package/bin/lib/commands/assets.js +137 -139
  6. package/bin/lib/commands/build.js +169 -174
  7. package/bin/lib/commands/datastore.js +181 -183
  8. package/bin/lib/commands/dev.js +127 -131
  9. package/bin/lib/commands/extensions.js +147 -149
  10. package/bin/lib/commands/extract-config.js +73 -67
  11. package/bin/lib/commands/index.js +12 -12
  12. package/bin/lib/commands/init.js +342 -240
  13. package/bin/lib/commands/publish.js +69 -75
  14. package/bin/lib/commands/socket.js +69 -69
  15. package/bin/lib/commands/ssl.js +14 -14
  16. package/bin/lib/constants.js +10 -24
  17. package/bin/lib/tui/App.tsx +761 -705
  18. package/bin/lib/tui/components/AIPanel.tsx +191 -171
  19. package/bin/lib/tui/components/CommandInput.tsx +394 -343
  20. package/bin/lib/tui/components/GeminiPanel.tsx +175 -151
  21. package/bin/lib/tui/components/Header.tsx +23 -21
  22. package/bin/lib/tui/components/LogPanel.tsx +244 -220
  23. package/bin/lib/tui/components/TabBar.tsx +50 -48
  24. package/bin/lib/tui/components/WelcomeScreen.tsx +126 -71
  25. package/bin/lib/tui/index.tsx +37 -39
  26. package/bin/lib/tui/services/AIService.ts +518 -462
  27. package/bin/lib/tui/services/ExtensionService.ts +140 -129
  28. package/bin/lib/tui/services/GeminiService.ts +367 -337
  29. package/bin/lib/tui/services/ServiceManager.ts +344 -322
  30. package/bin/lib/tui/services/SocketService.ts +168 -168
  31. package/bin/lib/tui/services/ViteService.ts +88 -88
  32. package/bin/lib/tui/services/index.ts +47 -22
  33. package/bin/lib/utils/ai-scaffold.js +291 -280
  34. package/bin/lib/utils/extract-config.js +157 -140
  35. package/bin/lib/utils/files.js +82 -86
  36. package/bin/lib/utils/index.js +7 -7
  37. package/bin/lib/utils/paths.js +34 -34
  38. package/bin/lib/utils/prompts.js +194 -169
  39. package/bin/lib/utils/ssl.js +79 -81
  40. package/browser-extensions/README.md +0 -1
  41. package/browser-extensions/chrome/background.js +244 -237
  42. package/browser-extensions/chrome/content.js +32 -29
  43. package/browser-extensions/chrome/devtools.html +7 -7
  44. package/browser-extensions/chrome/devtools.js +19 -19
  45. package/browser-extensions/chrome/inspector.js +802 -767
  46. package/browser-extensions/chrome/manifest.json +71 -63
  47. package/browser-extensions/chrome/panel.html +674 -636
  48. package/browser-extensions/chrome/panel.js +722 -712
  49. package/browser-extensions/chrome/popup.html +586 -543
  50. package/browser-extensions/chrome/popup.js +282 -244
  51. package/browser-extensions/chrome/rules.json +1 -1
  52. package/browser-extensions/chrome/test-chrome.html +216 -136
  53. package/browser-extensions/chrome/test-mixed-content.html +284 -189
  54. package/browser-extensions/chrome/test-uri-pattern.html +221 -198
  55. package/browser-extensions/firefox/README.md +9 -6
  56. package/browser-extensions/firefox/background.js +221 -218
  57. package/browser-extensions/firefox/content.js +55 -52
  58. package/browser-extensions/firefox/debug-errors.html +386 -228
  59. package/browser-extensions/firefox/debug-https.html +153 -105
  60. package/browser-extensions/firefox/devtools.html +7 -7
  61. package/browser-extensions/firefox/devtools.js +23 -20
  62. package/browser-extensions/firefox/inspector.js +802 -767
  63. package/browser-extensions/firefox/manifest.json +68 -68
  64. package/browser-extensions/firefox/panel.html +674 -636
  65. package/browser-extensions/firefox/panel.js +722 -712
  66. package/browser-extensions/firefox/popup.html +572 -535
  67. package/browser-extensions/firefox/popup.js +281 -236
  68. package/browser-extensions/firefox/test-gramercy.html +170 -125
  69. package/browser-extensions/firefox/test-imports.html +59 -55
  70. package/browser-extensions/firefox/test-masking.html +231 -140
  71. package/browser-extensions/firefox/test-uri-pattern.html +221 -198
  72. package/dist/tui/App.d.ts +1 -1
  73. package/dist/tui/App.d.ts.map +1 -1
  74. package/dist/tui/App.js +154 -150
  75. package/dist/tui/App.js.map +1 -1
  76. package/dist/tui/components/AIPanel.d.ts.map +1 -1
  77. package/dist/tui/components/AIPanel.js +42 -35
  78. package/dist/tui/components/AIPanel.js.map +1 -1
  79. package/dist/tui/components/CommandInput.d.ts +1 -1
  80. package/dist/tui/components/CommandInput.d.ts.map +1 -1
  81. package/dist/tui/components/CommandInput.js +92 -62
  82. package/dist/tui/components/CommandInput.js.map +1 -1
  83. package/dist/tui/components/GeminiPanel.d.ts.map +1 -1
  84. package/dist/tui/components/GeminiPanel.js +37 -30
  85. package/dist/tui/components/GeminiPanel.js.map +1 -1
  86. package/dist/tui/components/Header.d.ts.map +1 -1
  87. package/dist/tui/components/Header.js +1 -1
  88. package/dist/tui/components/Header.js.map +1 -1
  89. package/dist/tui/components/LogPanel.d.ts +1 -1
  90. package/dist/tui/components/LogPanel.d.ts.map +1 -1
  91. package/dist/tui/components/LogPanel.js +26 -24
  92. package/dist/tui/components/LogPanel.js.map +1 -1
  93. package/dist/tui/components/TabBar.d.ts +2 -2
  94. package/dist/tui/components/TabBar.d.ts.map +1 -1
  95. package/dist/tui/components/TabBar.js +11 -11
  96. package/dist/tui/components/TabBar.js.map +1 -1
  97. package/dist/tui/components/WelcomeScreen.d.ts.map +1 -1
  98. package/dist/tui/components/WelcomeScreen.js +6 -6
  99. package/dist/tui/components/WelcomeScreen.js.map +1 -1
  100. package/dist/tui/index.d.ts.map +1 -1
  101. package/dist/tui/index.js +8 -8
  102. package/dist/tui/index.js.map +1 -1
  103. package/dist/tui/services/AIService.d.ts +2 -2
  104. package/dist/tui/services/AIService.d.ts.map +1 -1
  105. package/dist/tui/services/AIService.js +165 -125
  106. package/dist/tui/services/AIService.js.map +1 -1
  107. package/dist/tui/services/ExtensionService.d.ts +1 -1
  108. package/dist/tui/services/ExtensionService.d.ts.map +1 -1
  109. package/dist/tui/services/ExtensionService.js +33 -26
  110. package/dist/tui/services/ExtensionService.js.map +1 -1
  111. package/dist/tui/services/GeminiService.d.ts +1 -1
  112. package/dist/tui/services/GeminiService.d.ts.map +1 -1
  113. package/dist/tui/services/GeminiService.js +87 -76
  114. package/dist/tui/services/GeminiService.js.map +1 -1
  115. package/dist/tui/services/ServiceManager.d.ts +3 -3
  116. package/dist/tui/services/ServiceManager.d.ts.map +1 -1
  117. package/dist/tui/services/ServiceManager.js +72 -58
  118. package/dist/tui/services/ServiceManager.js.map +1 -1
  119. package/dist/tui/services/SocketService.d.ts.map +1 -1
  120. package/dist/tui/services/SocketService.js +32 -32
  121. package/dist/tui/services/SocketService.js.map +1 -1
  122. package/dist/tui/services/ViteService.d.ts.map +1 -1
  123. package/dist/tui/services/ViteService.js +26 -28
  124. package/dist/tui/services/ViteService.js.map +1 -1
  125. package/dist/tui/services/index.d.ts +6 -6
  126. package/dist/tui/services/index.d.ts.map +1 -1
  127. package/dist/tui/services/index.js +6 -6
  128. package/dist/tui/services/index.js.map +1 -1
  129. package/mcp/gxp-api-server.js +83 -81
  130. package/package.json +109 -93
  131. package/runtime/PortalContainer.vue +258 -234
  132. package/runtime/dev-tools/DevToolsModal.vue +153 -155
  133. package/runtime/dev-tools/LayoutSwitcher.vue +144 -140
  134. package/runtime/dev-tools/MockDataEditor.vue +456 -433
  135. package/runtime/dev-tools/SocketSimulator.vue +379 -371
  136. package/runtime/dev-tools/StoreInspector.vue +517 -455
  137. package/runtime/dev-tools/index.js +5 -5
  138. package/runtime/fallback-layouts/PrivateLayout.vue +2 -2
  139. package/runtime/fallback-layouts/PublicLayout.vue +2 -2
  140. package/runtime/fallback-layouts/SystemLayout.vue +2 -2
  141. package/runtime/gxpStringsPlugin.js +159 -134
  142. package/runtime/index.html +17 -19
  143. package/runtime/main.js +24 -22
  144. package/runtime/mock-api/auth-middleware.js +15 -15
  145. package/runtime/mock-api/image-generator.js +46 -46
  146. package/runtime/mock-api/index.js +55 -55
  147. package/runtime/mock-api/response-generator.js +116 -105
  148. package/runtime/mock-api/route-generator.js +107 -84
  149. package/runtime/mock-api/socket-triggers.js +94 -93
  150. package/runtime/mock-api/spec-loader.js +79 -80
  151. package/runtime/package.json +3 -0
  152. package/runtime/server.js +68 -68
  153. package/runtime/stores/gxpPortalConfigStore.js +204 -186
  154. package/runtime/stores/index.js +2 -2
  155. package/runtime/vite-inspector-plugin.js +858 -707
  156. package/runtime/vite-source-tracker-plugin.js +132 -113
  157. package/runtime/vite.config.js +207 -132
  158. package/scripts/launch-chrome.js +41 -41
  159. package/scripts/pack-chrome.js +38 -39
  160. package/socket-events/AiSessionMessageCreated.json +17 -17
  161. package/socket-events/SocialStreamPostCreated.json +23 -23
  162. package/socket-events/SocialStreamPostVariantCompleted.json +22 -22
  163. package/template/.claude/agents/gxp-developer.md +100 -99
  164. package/template/.claude/settings.json +7 -7
  165. package/template/AGENTS.md +30 -23
  166. package/template/GEMINI.md +20 -20
  167. package/template/README.md +70 -53
  168. package/template/app-manifest.json +2 -4
  169. package/template/configuration.json +10 -10
  170. package/template/default-styling.css +1 -1
  171. package/template/index.html +18 -20
  172. package/template/main.js +24 -22
  173. package/template/src/DemoPage.vue +415 -362
  174. package/template/src/Plugin.vue +76 -85
  175. package/template/src/stores/index.js +3 -3
  176. package/template/src/stores/test-data.json +164 -172
  177. package/template/theme-layouts/AdditionalStyling.css +50 -50
  178. package/template/theme-layouts/PrivateLayout.vue +8 -12
  179. package/template/theme-layouts/PublicLayout.vue +8 -12
  180. package/template/theme-layouts/SystemLayout.vue +8 -12
  181. package/template/vite.extend.js +45 -0
  182. 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", "hr", "img", "input", "meta", "link",
31
- "area", "base", "col", "embed", "param",
32
- "source", "track", "wbr"
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 = oldOpenTag.slice(0, -2) + ` ${attrName}="${escapeAttr(exprValue)}"/>`;
253
+ newOpenTag =
254
+ oldOpenTag.slice(0, -2) +
255
+ ` ${attrName}="${escapeAttr(exprValue)}"/>`
243
256
  } else {
244
- newOpenTag = oldOpenTag.slice(0, -1) + ` ${attrName}="${escapeAttr(exprValue)}">`;
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
- `[GxP Source Tracker] No expressions found in: ${fileName}`
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(`${escapeRegex(directive)}="([^"]*)"`, "g");
306
- const match = directivePattern.exec(tag.attrs);
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 = tag.fullMatch.slice(0, -2) + ` ${attrName}="${escapeAttr(exprValue)}"/>`;
326
+ newOpenTag =
327
+ tag.fullMatch.slice(0, -2) +
328
+ ` ${attrName}="${escapeAttr(exprValue)}"/>`
312
329
  } else {
313
- newOpenTag = tag.fullMatch.slice(0, -1) + ` ${attrName}="${escapeAttr(exprValue)}">`;
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, "&quot;")
344
363
  .replace(/'/g, "&#39;")
345
364
  .replace(/</g, "&lt;")
346
- .replace(/>/g, "&gt;");
365
+ .replace(/>/g, "&gt;")
347
366
  }
348
367
 
349
- export default gxpSourceTrackerPlugin;
368
+ export default gxpSourceTrackerPlugin