@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.
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 +191 -139
  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
@@ -18,8 +18,8 @@
18
18
  * - gxp-src/v-gxp-src -> assets
19
19
  */
20
20
 
21
- const fs = require("fs");
22
- const path = require("path");
21
+ const fs = require("fs")
22
+ const path = require("path")
23
23
 
24
24
  /**
25
25
  * Extract configuration from all Vue/JS files in the src directory
@@ -33,34 +33,40 @@ function extractConfigFromSource(srcDir) {
33
33
  assets: {},
34
34
  triggerState: {},
35
35
  dependencies: [],
36
- };
36
+ }
37
37
 
38
38
  if (!fs.existsSync(srcDir)) {
39
- console.error(`❌ Source directory not found: ${srcDir}`);
40
- return config;
39
+ console.error(`❌ Source directory not found: ${srcDir}`)
40
+ return config
41
41
  }
42
42
 
43
43
  // Find all .vue and .js files recursively
44
- const files = findFilesRecursive(srcDir, [".vue", ".js", ".ts", ".jsx", ".tsx"]);
44
+ const files = findFilesRecursive(srcDir, [
45
+ ".vue",
46
+ ".js",
47
+ ".ts",
48
+ ".jsx",
49
+ ".tsx",
50
+ ])
45
51
 
46
52
  for (const file of files) {
47
53
  try {
48
- const content = fs.readFileSync(file, "utf-8");
49
- const relativePath = path.relative(srcDir, file);
54
+ const content = fs.readFileSync(file, "utf-8")
55
+ const relativePath = path.relative(srcDir, file)
50
56
 
51
57
  // Extract from JavaScript/TypeScript code
52
- extractFromScript(content, config, relativePath);
58
+ extractFromScript(content, config, relativePath)
53
59
 
54
60
  // Extract from Vue templates
55
61
  if (file.endsWith(".vue")) {
56
- extractFromTemplate(content, config, relativePath);
62
+ extractFromTemplate(content, config, relativePath)
57
63
  }
58
64
  } catch (error) {
59
- console.warn(`⚠ Could not parse ${file}: ${error.message}`);
65
+ console.warn(`⚠ Could not parse ${file}: ${error.message}`)
60
66
  }
61
67
  }
62
68
 
63
- return config;
69
+ return config
64
70
  }
65
71
 
66
72
  /**
@@ -70,30 +76,30 @@ function extractConfigFromSource(srcDir) {
70
76
  * @returns {string[]} Array of file paths
71
77
  */
72
78
  function findFilesRecursive(dir, extensions) {
73
- const files = [];
79
+ const files = []
74
80
 
75
81
  function walk(currentDir) {
76
- const entries = fs.readdirSync(currentDir, { withFileTypes: true });
82
+ const entries = fs.readdirSync(currentDir, { withFileTypes: true })
77
83
 
78
84
  for (const entry of entries) {
79
- const fullPath = path.join(currentDir, entry.name);
85
+ const fullPath = path.join(currentDir, entry.name)
80
86
 
81
87
  if (entry.isDirectory()) {
82
88
  // Skip node_modules and hidden directories
83
89
  if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
84
- walk(fullPath);
90
+ walk(fullPath)
85
91
  }
86
92
  } else if (entry.isFile()) {
87
- const ext = path.extname(entry.name).toLowerCase();
93
+ const ext = path.extname(entry.name).toLowerCase()
88
94
  if (extensions.includes(ext)) {
89
- files.push(fullPath);
95
+ files.push(fullPath)
90
96
  }
91
97
  }
92
98
  }
93
99
  }
94
100
 
95
- walk(dir);
96
- return files;
101
+ walk(dir)
102
+ return files
97
103
  }
98
104
 
99
105
  /**
@@ -104,103 +110,109 @@ function findFilesRecursive(dir, extensions) {
104
110
  */
105
111
  function extractFromScript(content, config, sourcePath) {
106
112
  // Extract getString calls: getString('key', 'default') or getString("key", "default")
107
- const getStringRegex = /\.getString\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*['"`]([^'"`]*)['"`])?\s*\)/g;
108
- let match;
113
+ const getStringRegex =
114
+ /\.getString\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*['"`]([^'"`]*)['"`])?\s*\)/g
115
+ let match
109
116
  while ((match = getStringRegex.exec(content)) !== null) {
110
- const key = match[1];
111
- const defaultValue = match[2] || "";
117
+ const key = match[1]
118
+ const defaultValue = match[2] || ""
112
119
  if (!config.strings[key]) {
113
- config.strings[key] = defaultValue;
120
+ config.strings[key] = defaultValue
114
121
  }
115
122
  }
116
123
 
117
124
  // Extract getSetting calls: getSetting('key', 'default') or getSetting('key', value)
118
- const getSettingRegex = /\.getSetting\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*['"`]?([^'"`),]*)['"`]?)?\s*\)/g;
125
+ const getSettingRegex =
126
+ /\.getSetting\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*['"`]?([^'"`),]*)['"`]?)?\s*\)/g
119
127
  while ((match = getSettingRegex.exec(content)) !== null) {
120
- const key = match[1];
121
- let defaultValue = match[2] || "";
128
+ const key = match[1]
129
+ let defaultValue = match[2] || ""
122
130
  // Clean up the default value
123
- defaultValue = defaultValue.trim();
131
+ defaultValue = defaultValue.trim()
124
132
  // Try to parse as JSON for non-string values
125
133
  if (defaultValue && !config.settings[key]) {
126
134
  try {
127
- config.settings[key] = JSON.parse(defaultValue);
135
+ config.settings[key] = JSON.parse(defaultValue)
128
136
  } catch {
129
- config.settings[key] = defaultValue;
137
+ config.settings[key] = defaultValue
130
138
  }
131
139
  } else if (!config.settings[key]) {
132
- config.settings[key] = "";
140
+ config.settings[key] = ""
133
141
  }
134
142
  }
135
143
 
136
144
  // Extract getAsset calls: getAsset('key', 'default')
137
- const getAssetRegex = /\.getAsset\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*['"`]([^'"`]*)['"`])?\s*\)/g;
145
+ const getAssetRegex =
146
+ /\.getAsset\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*['"`]([^'"`]*)['"`])?\s*\)/g
138
147
  while ((match = getAssetRegex.exec(content)) !== null) {
139
- const key = match[1];
140
- const defaultValue = match[2] || "";
148
+ const key = match[1]
149
+ const defaultValue = match[2] || ""
141
150
  if (!config.assets[key]) {
142
- config.assets[key] = defaultValue;
151
+ config.assets[key] = defaultValue
143
152
  }
144
153
  }
145
154
 
146
155
  // Extract getState calls: getState('key', default)
147
- const getStateRegex = /\.getState\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*['"`]?([^'"`),]*)['"`]?)?\s*\)/g;
156
+ const getStateRegex =
157
+ /\.getState\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*['"`]?([^'"`),]*)['"`]?)?\s*\)/g
148
158
  while ((match = getStateRegex.exec(content)) !== null) {
149
- const key = match[1];
150
- let defaultValue = match[2] || "";
151
- defaultValue = defaultValue.trim();
159
+ const key = match[1]
160
+ let defaultValue = match[2] || ""
161
+ defaultValue = defaultValue.trim()
152
162
  if (!config.triggerState[key]) {
153
163
  try {
154
- config.triggerState[key] = JSON.parse(defaultValue);
164
+ config.triggerState[key] = JSON.parse(defaultValue)
155
165
  } catch {
156
- config.triggerState[key] = defaultValue || null;
166
+ config.triggerState[key] = defaultValue || null
157
167
  }
158
168
  }
159
169
  }
160
170
 
161
171
  // Extract callApi calls: callApi('path', 'identifier') or apiGet/apiPost with identifier patterns
162
172
  // Pattern: callApi('/path', 'identifier') or any api method with path
163
- const callApiRegex = /\.(?:callApi|apiGet|apiPost|apiPut|apiPatch|apiDelete)\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*['"`]([^'"`]+)['"`])?\s*\)/g;
173
+ const callApiRegex =
174
+ /\.(?:callApi|apiGet|apiPost|apiPut|apiPatch|apiDelete)\s*\(\s*['"`]([^'"`]+)['"`]\s*(?:,\s*['"`]([^'"`]+)['"`])?\s*\)/g
164
175
  while ((match = callApiRegex.exec(content)) !== null) {
165
- const apiPath = match[1];
166
- const identifier = match[2];
176
+ const apiPath = match[1]
177
+ const identifier = match[2]
167
178
  if (identifier) {
168
179
  // Check if this dependency already exists
169
180
  const exists = config.dependencies.some(
170
- (dep) => dep.identifier === identifier && dep.path === apiPath
171
- );
181
+ (dep) => dep.identifier === identifier && dep.path === apiPath,
182
+ )
172
183
  if (!exists) {
173
184
  config.dependencies.push({
174
185
  identifier: identifier,
175
186
  path: apiPath,
176
- });
187
+ })
177
188
  }
178
189
  }
179
190
  }
180
191
 
181
192
  // Extract listenSocket calls for reference: listenSocket('socketName', 'event', callback)
182
193
  // These help identify what socket events the app expects
183
- const listenSocketRegex = /\.(?:listenSocket|useSocketListener)\s*\(\s*['"`]([^'"`]+)['"`]\s*,\s*['"`]([^'"`]+)['"`]/g;
194
+ const listenSocketRegex =
195
+ /\.(?:listenSocket|useSocketListener)\s*\(\s*['"`]([^'"`]+)['"`]\s*,\s*['"`]([^'"`]+)['"`]/g
184
196
  while ((match = listenSocketRegex.exec(content)) !== null) {
185
- const socketName = match[1];
186
- const eventName = match[2];
197
+ const socketName = match[1]
198
+ const eventName = match[2]
187
199
  // Add as a dependency reference if not 'primary'
188
200
  if (socketName !== "primary") {
189
201
  const exists = config.dependencies.some(
190
- (dep) => dep.identifier === socketName
191
- );
202
+ (dep) => dep.identifier === socketName,
203
+ )
192
204
  if (!exists) {
193
205
  config.dependencies.push({
194
206
  identifier: socketName,
195
207
  path: "",
196
208
  events: { [eventName]: eventName },
197
- });
209
+ })
198
210
  } else {
199
211
  // Add the event to existing dependency
200
- const dep = config.dependencies.find((d) => d.identifier === socketName);
212
+ const dep = config.dependencies.find((d) => d.identifier === socketName)
201
213
  if (dep) {
202
- dep.events = dep.events || {};
203
- dep.events[eventName] = eventName;
214
+ dep.events = dep.events || {}
215
+ dep.events[eventName] = eventName
204
216
  }
205
217
  }
206
218
  }
@@ -215,111 +227,116 @@ function extractFromScript(content, config, sourcePath) {
215
227
  */
216
228
  function extractFromTemplate(content, config, sourcePath) {
217
229
  // Extract template section
218
- const templateMatch = content.match(/<template[^>]*>([\s\S]*?)<\/template>/i);
230
+ const templateMatch = content.match(/<template[^>]*>([\s\S]*?)<\/template>/i)
219
231
  if (!templateMatch) {
220
- return;
232
+ return
221
233
  }
222
234
 
223
- const template = templateMatch[1];
235
+ const template = templateMatch[1]
224
236
 
225
237
  // Extract gxp-string/v-gxp-string without other gxp attributes (pure strings)
226
238
  // Pattern: <tag gxp-string="key">default</tag> or <tag v-gxp-string="'key'">default</tag>
227
239
  // But NOT when gxp-setting, gxp-asset, or gxp-state is present
228
- const pureStringRegex = /<([a-z][a-z0-9-]*)\s+[^>]*(?:v-gxp-string|gxp-string)=["']([^"']+)["'][^>]*>([^<]*)</gi;
229
- let match;
240
+ const pureStringRegex =
241
+ /<([a-z][a-z0-9-]*)\s+[^>]*(?:v-gxp-string|gxp-string)=["']([^"']+)["'][^>]*>([^<]*)</gi
242
+ let match
230
243
  while ((match = pureStringRegex.exec(template)) !== null) {
231
- const fullMatch = match[0];
232
- const key = match[2].replace(/['"]/g, ""); // Remove quotes for v-gxp-string="'key'"
233
- const defaultValue = match[3].trim();
244
+ const fullMatch = match[0]
245
+ const key = match[2].replace(/['"]/g, "") // Remove quotes for v-gxp-string="'key'"
246
+ const defaultValue = match[3].trim()
234
247
 
235
248
  // Check if this element has gxp-setting, gxp-asset, or gxp-state
236
- const hasGxpSetting = /gxp-setting|v-gxp-setting/i.test(fullMatch);
237
- const hasGxpAsset = /gxp-asset|v-gxp-asset/i.test(fullMatch);
238
- const hasGxpState = /gxp-state|v-gxp-state/i.test(fullMatch);
249
+ const hasGxpSetting = /gxp-setting|v-gxp-setting/i.test(fullMatch)
250
+ const hasGxpAsset = /gxp-asset|v-gxp-asset/i.test(fullMatch)
251
+ const hasGxpState = /gxp-state|v-gxp-state/i.test(fullMatch)
239
252
 
240
253
  if (hasGxpSetting) {
241
254
  // gxp-string key with gxp-setting -> settings
242
255
  if (!config.settings[key]) {
243
- config.settings[key] = defaultValue;
256
+ config.settings[key] = defaultValue
244
257
  }
245
258
  } else if (hasGxpAsset) {
246
259
  // gxp-string key with gxp-asset -> assets
247
260
  if (!config.assets[key]) {
248
- config.assets[key] = defaultValue;
261
+ config.assets[key] = defaultValue
249
262
  }
250
263
  } else if (hasGxpState) {
251
264
  // gxp-string key with gxp-state -> triggerState
252
265
  if (!config.triggerState[key]) {
253
- config.triggerState[key] = defaultValue || null;
266
+ config.triggerState[key] = defaultValue || null
254
267
  }
255
268
  } else {
256
269
  // Pure gxp-string -> strings
257
270
  if (!config.strings[key]) {
258
- config.strings[key] = defaultValue;
271
+ config.strings[key] = defaultValue
259
272
  }
260
273
  }
261
274
  }
262
275
 
263
276
  // Extract standalone gxp-setting/v-gxp-setting with value (not using gxp-string for key)
264
277
  // Pattern: <tag gxp-setting="key">default</tag>
265
- const settingRegex = /<([a-z][a-z0-9-]*)\s+[^>]*(?:v-gxp-setting|gxp-setting)=["']([^"']+)["'][^>]*>([^<]*)</gi;
278
+ const settingRegex =
279
+ /<([a-z][a-z0-9-]*)\s+[^>]*(?:v-gxp-setting|gxp-setting)=["']([^"']+)["'][^>]*>([^<]*)</gi
266
280
  while ((match = settingRegex.exec(template)) !== null) {
267
- const key = match[2].replace(/['"]/g, "");
268
- const defaultValue = match[3].trim();
281
+ const key = match[2].replace(/['"]/g, "")
282
+ const defaultValue = match[3].trim()
269
283
  // Only add if key looks like an actual key (not empty)
270
284
  if (key && !config.settings[key]) {
271
- config.settings[key] = defaultValue;
285
+ config.settings[key] = defaultValue
272
286
  }
273
287
  }
274
288
 
275
289
  // Extract standalone gxp-asset/v-gxp-asset with value
276
- const assetRegex = /<([a-z][a-z0-9-]*)\s+[^>]*(?:v-gxp-asset|gxp-asset)=["']([^"']+)["'][^>]*>([^<]*)</gi;
290
+ const assetRegex =
291
+ /<([a-z][a-z0-9-]*)\s+[^>]*(?:v-gxp-asset|gxp-asset)=["']([^"']+)["'][^>]*>([^<]*)</gi
277
292
  while ((match = assetRegex.exec(template)) !== null) {
278
- const key = match[2].replace(/['"]/g, "");
279
- const defaultValue = match[3].trim();
293
+ const key = match[2].replace(/['"]/g, "")
294
+ const defaultValue = match[3].trim()
280
295
  if (key && !config.assets[key]) {
281
- config.assets[key] = defaultValue;
296
+ config.assets[key] = defaultValue
282
297
  }
283
298
  }
284
299
 
285
300
  // Extract gxp-src/v-gxp-src: <img gxp-src="key" src="default" />
286
301
  // Pattern matches self-closing and regular tags with gxp-src and src attributes
287
- const gxpSrcRegex = /<([a-z][a-z0-9-]*)\s+[^>]*(?:v-gxp-src|gxp-src)=["']([^"']+)["'][^>]*src=["']([^"']+)["'][^>]*\/?>/gi;
302
+ const gxpSrcRegex =
303
+ /<([a-z][a-z0-9-]*)\s+[^>]*(?:v-gxp-src|gxp-src)=["']([^"']+)["'][^>]*src=["']([^"']+)["'][^>]*\/?>/gi
288
304
  while ((match = gxpSrcRegex.exec(template)) !== null) {
289
- const key = match[2].replace(/['"]/g, "");
290
- const defaultSrc = match[3];
305
+ const key = match[2].replace(/['"]/g, "")
306
+ const defaultSrc = match[3]
291
307
 
292
308
  // Check if gxp-state is present
293
- const fullMatch = match[0];
294
- const hasGxpState = /gxp-state|v-gxp-state/i.test(fullMatch);
309
+ const fullMatch = match[0]
310
+ const hasGxpState = /gxp-state|v-gxp-state/i.test(fullMatch)
295
311
 
296
312
  if (hasGxpState) {
297
313
  if (!config.triggerState[key]) {
298
- config.triggerState[key] = defaultSrc;
314
+ config.triggerState[key] = defaultSrc
299
315
  }
300
316
  } else {
301
317
  if (!config.assets[key]) {
302
- config.assets[key] = defaultSrc;
318
+ config.assets[key] = defaultSrc
303
319
  }
304
320
  }
305
321
  }
306
322
 
307
323
  // Also try reverse order: src before gxp-src
308
- const gxpSrcReverseRegex = /<([a-z][a-z0-9-]*)\s+[^>]*src=["']([^"']+)["'][^>]*(?:v-gxp-src|gxp-src)=["']([^"']+)["'][^>]*\/?>/gi;
324
+ const gxpSrcReverseRegex =
325
+ /<([a-z][a-z0-9-]*)\s+[^>]*src=["']([^"']+)["'][^>]*(?:v-gxp-src|gxp-src)=["']([^"']+)["'][^>]*\/?>/gi
309
326
  while ((match = gxpSrcReverseRegex.exec(template)) !== null) {
310
- const defaultSrc = match[2];
311
- const key = match[3].replace(/['"]/g, "");
327
+ const defaultSrc = match[2]
328
+ const key = match[3].replace(/['"]/g, "")
312
329
 
313
- const fullMatch = match[0];
314
- const hasGxpState = /gxp-state|v-gxp-state/i.test(fullMatch);
330
+ const fullMatch = match[0]
331
+ const hasGxpState = /gxp-state|v-gxp-state/i.test(fullMatch)
315
332
 
316
333
  if (hasGxpState) {
317
334
  if (!config.triggerState[key]) {
318
- config.triggerState[key] = defaultSrc;
335
+ config.triggerState[key] = defaultSrc
319
336
  }
320
337
  } else {
321
338
  if (!config.assets[key]) {
322
- config.assets[key] = defaultSrc;
339
+ config.assets[key] = defaultSrc
323
340
  }
324
341
  }
325
342
  }
@@ -333,62 +350,62 @@ function extractFromTemplate(content, config, sourcePath) {
333
350
  * @returns {Object} Merged manifest
334
351
  */
335
352
  function mergeConfig(existingManifest, extractedConfig, options = {}) {
336
- const { overwrite = false } = options;
353
+ const { overwrite = false } = options
337
354
 
338
- const merged = { ...existingManifest };
355
+ const merged = { ...existingManifest }
339
356
 
340
357
  // Ensure nested structures exist
341
- if (!merged.strings) merged.strings = {};
342
- if (!merged.strings.default) merged.strings.default = {};
343
- if (!merged.settings) merged.settings = {};
344
- if (!merged.assets) merged.assets = {};
345
- if (!merged.triggerState) merged.triggerState = {};
346
- if (!merged.dependencies) merged.dependencies = [];
358
+ if (!merged.strings) merged.strings = {}
359
+ if (!merged.strings.default) merged.strings.default = {}
360
+ if (!merged.settings) merged.settings = {}
361
+ if (!merged.assets) merged.assets = {}
362
+ if (!merged.triggerState) merged.triggerState = {}
363
+ if (!merged.dependencies) merged.dependencies = []
347
364
 
348
365
  // Merge strings
349
366
  for (const [key, value] of Object.entries(extractedConfig.strings)) {
350
367
  if (overwrite || !merged.strings.default[key]) {
351
- merged.strings.default[key] = value;
368
+ merged.strings.default[key] = value
352
369
  }
353
370
  }
354
371
 
355
372
  // Merge settings
356
373
  for (const [key, value] of Object.entries(extractedConfig.settings)) {
357
374
  if (overwrite || merged.settings[key] === undefined) {
358
- merged.settings[key] = value;
375
+ merged.settings[key] = value
359
376
  }
360
377
  }
361
378
 
362
379
  // Merge assets
363
380
  for (const [key, value] of Object.entries(extractedConfig.assets)) {
364
381
  if (overwrite || !merged.assets[key]) {
365
- merged.assets[key] = value;
382
+ merged.assets[key] = value
366
383
  }
367
384
  }
368
385
 
369
386
  // Merge triggerState
370
387
  for (const [key, value] of Object.entries(extractedConfig.triggerState)) {
371
388
  if (overwrite || merged.triggerState[key] === undefined) {
372
- merged.triggerState[key] = value;
389
+ merged.triggerState[key] = value
373
390
  }
374
391
  }
375
392
 
376
393
  // Merge dependencies (by identifier)
377
394
  for (const dep of extractedConfig.dependencies) {
378
395
  const existingIndex = merged.dependencies.findIndex(
379
- (d) => d.identifier === dep.identifier
380
- );
396
+ (d) => d.identifier === dep.identifier,
397
+ )
381
398
  if (existingIndex === -1) {
382
- merged.dependencies.push(dep);
399
+ merged.dependencies.push(dep)
383
400
  } else if (overwrite) {
384
401
  merged.dependencies[existingIndex] = {
385
402
  ...merged.dependencies[existingIndex],
386
403
  ...dep,
387
- };
404
+ }
388
405
  }
389
406
  }
390
407
 
391
- return merged;
408
+ return merged
392
409
  }
393
410
 
394
411
  /**
@@ -397,67 +414,67 @@ function mergeConfig(existingManifest, extractedConfig, options = {}) {
397
414
  * @returns {string} Summary text
398
415
  */
399
416
  function generateSummary(config) {
400
- const lines = [];
417
+ const lines = []
401
418
 
402
- const stringCount = Object.keys(config.strings).length;
403
- const settingCount = Object.keys(config.settings).length;
404
- const assetCount = Object.keys(config.assets).length;
405
- const stateCount = Object.keys(config.triggerState).length;
406
- const depCount = config.dependencies.length;
419
+ const stringCount = Object.keys(config.strings).length
420
+ const settingCount = Object.keys(config.settings).length
421
+ const assetCount = Object.keys(config.assets).length
422
+ const stateCount = Object.keys(config.triggerState).length
423
+ const depCount = config.dependencies.length
407
424
 
408
- lines.push("📊 Extraction Summary:");
409
- lines.push("");
425
+ lines.push("📊 Extraction Summary:")
426
+ lines.push("")
410
427
 
411
428
  if (stringCount > 0) {
412
- lines.push(`📝 Strings (${stringCount}):`);
429
+ lines.push(`📝 Strings (${stringCount}):`)
413
430
  for (const [key, value] of Object.entries(config.strings)) {
414
- const displayValue = value ? `"${value}"` : "(empty)";
415
- lines.push(` ${key}: ${displayValue}`);
431
+ const displayValue = value ? `"${value}"` : "(empty)"
432
+ lines.push(` ${key}: ${displayValue}`)
416
433
  }
417
- lines.push("");
434
+ lines.push("")
418
435
  }
419
436
 
420
437
  if (settingCount > 0) {
421
- lines.push(`⚙️ Settings (${settingCount}):`);
438
+ lines.push(`⚙️ Settings (${settingCount}):`)
422
439
  for (const [key, value] of Object.entries(config.settings)) {
423
- lines.push(` ${key}: ${JSON.stringify(value)}`);
440
+ lines.push(` ${key}: ${JSON.stringify(value)}`)
424
441
  }
425
- lines.push("");
442
+ lines.push("")
426
443
  }
427
444
 
428
445
  if (assetCount > 0) {
429
- lines.push(`🖼️ Assets (${assetCount}):`);
446
+ lines.push(`🖼️ Assets (${assetCount}):`)
430
447
  for (const [key, value] of Object.entries(config.assets)) {
431
- lines.push(` ${key}: ${value || "(empty)"}`);
448
+ lines.push(` ${key}: ${value || "(empty)"}`)
432
449
  }
433
- lines.push("");
450
+ lines.push("")
434
451
  }
435
452
 
436
453
  if (stateCount > 0) {
437
- lines.push(`🔄 Trigger State (${stateCount}):`);
454
+ lines.push(`🔄 Trigger State (${stateCount}):`)
438
455
  for (const [key, value] of Object.entries(config.triggerState)) {
439
- lines.push(` ${key}: ${JSON.stringify(value)}`);
456
+ lines.push(` ${key}: ${JSON.stringify(value)}`)
440
457
  }
441
- lines.push("");
458
+ lines.push("")
442
459
  }
443
460
 
444
461
  if (depCount > 0) {
445
- lines.push(`🔗 Dependencies (${depCount}):`);
462
+ lines.push(`🔗 Dependencies (${depCount}):`)
446
463
  for (const dep of config.dependencies) {
447
- lines.push(` ${dep.identifier}: ${dep.path || "(no path)"}`);
464
+ lines.push(` ${dep.identifier}: ${dep.path || "(no path)"}`)
448
465
  if (dep.events) {
449
- lines.push(` Events: ${Object.keys(dep.events).join(", ")}`);
466
+ lines.push(` Events: ${Object.keys(dep.events).join(", ")}`)
450
467
  }
451
468
  }
452
- lines.push("");
469
+ lines.push("")
453
470
  }
454
471
 
455
472
  if (stringCount + settingCount + assetCount + stateCount + depCount === 0) {
456
- lines.push(" No configuration found in source files.");
457
- lines.push("");
473
+ lines.push(" No configuration found in source files.")
474
+ lines.push("")
458
475
  }
459
476
 
460
- return lines.join("\n");
477
+ return lines.join("\n")
461
478
  }
462
479
 
463
480
  module.exports = {
@@ -465,4 +482,4 @@ module.exports = {
465
482
  mergeConfig,
466
483
  generateSummary,
467
484
  findFilesRecursive,
468
- };
485
+ }