@pure-ds/core 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/CSS-INTELLISENSE-LIMITATION.md +98 -0
  2. package/CSS-INTELLISENSE-QUICK-REF.md +238 -0
  3. package/INTELLISENSE.md +384 -0
  4. package/LICENSE +15 -0
  5. package/custom-elements-manifest.config.js +30 -0
  6. package/custom-elements.json +2003 -0
  7. package/dist/types/index.d.ts +2 -0
  8. package/dist/types/packages/pds-configurator/src/figma-export.d.ts +13 -0
  9. package/dist/types/packages/pds-configurator/src/figma-export.d.ts.map +1 -0
  10. package/dist/types/packages/pds-configurator/src/pds-config-form.d.ts +2 -0
  11. package/dist/types/packages/pds-configurator/src/pds-config-form.d.ts.map +1 -0
  12. package/dist/types/packages/pds-configurator/src/pds-configurator.d.ts +2 -0
  13. package/dist/types/packages/pds-configurator/src/pds-configurator.d.ts.map +1 -0
  14. package/dist/types/packages/pds-configurator/src/pds-demo.d.ts +2 -0
  15. package/dist/types/packages/pds-configurator/src/pds-demo.d.ts.map +1 -0
  16. package/dist/types/pds.config.d.ts +13 -0
  17. package/dist/types/pds.config.d.ts.map +1 -0
  18. package/dist/types/pds.d.ts +408 -0
  19. package/dist/types/public/assets/js/app.d.ts +2 -0
  20. package/dist/types/public/assets/js/app.d.ts.map +1 -0
  21. package/dist/types/public/assets/js/pds.d.ts +23 -0
  22. package/dist/types/public/assets/js/pds.d.ts.map +1 -0
  23. package/dist/types/public/assets/pds/components/pds-calendar.d.ts +23 -0
  24. package/dist/types/public/assets/pds/components/pds-calendar.d.ts.map +1 -0
  25. package/dist/types/public/assets/pds/components/pds-drawer.d.ts +2 -0
  26. package/dist/types/public/assets/pds/components/pds-drawer.d.ts.map +1 -0
  27. package/dist/types/public/assets/pds/components/pds-icon.d.ts +53 -0
  28. package/dist/types/public/assets/pds/components/pds-icon.d.ts.map +1 -0
  29. package/dist/types/public/assets/pds/components/pds-jsonform.d.ts +104 -0
  30. package/dist/types/public/assets/pds/components/pds-jsonform.d.ts.map +1 -0
  31. package/dist/types/public/assets/pds/components/pds-richtext.d.ts +121 -0
  32. package/dist/types/public/assets/pds/components/pds-richtext.d.ts.map +1 -0
  33. package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts +61 -0
  34. package/dist/types/public/assets/pds/components/pds-scrollrow.d.ts.map +1 -0
  35. package/dist/types/public/assets/pds/components/pds-splitpanel.d.ts +1 -0
  36. package/dist/types/public/assets/pds/components/pds-splitpanel.d.ts.map +1 -0
  37. package/dist/types/public/assets/pds/components/pds-tabstrip.d.ts +39 -0
  38. package/dist/types/public/assets/pds/components/pds-tabstrip.d.ts.map +1 -0
  39. package/dist/types/public/assets/pds/components/pds-toaster.d.ts +111 -0
  40. package/dist/types/public/assets/pds/components/pds-toaster.d.ts.map +1 -0
  41. package/dist/types/public/assets/pds/components/pds-upload.d.ts +83 -0
  42. package/dist/types/public/assets/pds/components/pds-upload.d.ts.map +1 -0
  43. package/dist/types/src/js/app.d.ts +2 -0
  44. package/dist/types/src/js/app.d.ts.map +1 -0
  45. package/dist/types/src/js/common/ask.d.ts +22 -0
  46. package/dist/types/src/js/common/ask.d.ts.map +1 -0
  47. package/dist/types/src/js/common/common.d.ts +3 -0
  48. package/dist/types/src/js/common/common.d.ts.map +1 -0
  49. package/dist/types/src/js/common/font-loader.d.ts +24 -0
  50. package/dist/types/src/js/common/font-loader.d.ts.map +1 -0
  51. package/dist/types/src/js/common/msg.d.ts +3 -0
  52. package/dist/types/src/js/common/msg.d.ts.map +1 -0
  53. package/dist/types/src/js/lit.d.ts +25 -0
  54. package/dist/types/src/js/lit.d.ts.map +1 -0
  55. package/dist/types/src/js/pds-configurator/figma-export.d.ts +13 -0
  56. package/dist/types/src/js/pds-configurator/figma-export.d.ts.map +1 -0
  57. package/dist/types/src/js/pds-configurator/pds-config-form.d.ts +2 -0
  58. package/dist/types/src/js/pds-configurator/pds-config-form.d.ts.map +1 -0
  59. package/dist/types/src/js/pds-configurator/pds-configurator.d.ts +2 -0
  60. package/dist/types/src/js/pds-configurator/pds-configurator.d.ts.map +1 -0
  61. package/dist/types/src/js/pds-configurator/pds-demo.d.ts +2 -0
  62. package/dist/types/src/js/pds-configurator/pds-demo.d.ts.map +1 -0
  63. package/dist/types/src/js/pds-core/pds-config.d.ts +758 -0
  64. package/dist/types/src/js/pds-core/pds-config.d.ts.map +1 -0
  65. package/dist/types/src/js/pds-core/pds-enhancer-metadata.d.ts +6 -0
  66. package/dist/types/src/js/pds-core/pds-enhancer-metadata.d.ts.map +1 -0
  67. package/dist/types/src/js/pds-core/pds-enhancers.d.ts +14 -0
  68. package/dist/types/src/js/pds-core/pds-enhancers.d.ts.map +1 -0
  69. package/dist/types/src/js/pds-core/pds-enums.d.ts +87 -0
  70. package/dist/types/src/js/pds-core/pds-enums.d.ts.map +1 -0
  71. package/dist/types/src/js/pds-core/pds-generator.d.ts +741 -0
  72. package/dist/types/src/js/pds-core/pds-generator.d.ts.map +1 -0
  73. package/dist/types/src/js/pds-core/pds-ontology.d.ts +48 -0
  74. package/dist/types/src/js/pds-core/pds-ontology.d.ts.map +1 -0
  75. package/dist/types/src/js/pds-core/pds-paths.d.ts +37 -0
  76. package/dist/types/src/js/pds-core/pds-paths.d.ts.map +1 -0
  77. package/dist/types/src/js/pds-core/pds-query.d.ts +102 -0
  78. package/dist/types/src/js/pds-core/pds-query.d.ts.map +1 -0
  79. package/dist/types/src/js/pds-core/pds-registry.d.ts +40 -0
  80. package/dist/types/src/js/pds-core/pds-registry.d.ts.map +1 -0
  81. package/dist/types/src/js/pds.d.ts +109 -0
  82. package/dist/types/src/js/pds.d.ts.map +1 -0
  83. package/dist/types/src/pds-core/pds-api.d.ts +31 -0
  84. package/dist/types/src/pds-core/pds-api.d.ts.map +1 -0
  85. package/package.json +104 -0
  86. package/packages/pds-cli/README.md +15 -0
  87. package/packages/pds-cli/bin/generate-css-data.js +565 -0
  88. package/packages/pds-cli/bin/generate-manifest.js +352 -0
  89. package/packages/pds-cli/bin/pds-build-icons.js +152 -0
  90. package/packages/pds-cli/bin/pds-dx.js +114 -0
  91. package/packages/pds-cli/bin/pds-static.js +556 -0
  92. package/packages/pds-cli/bin/pds.js +127 -0
  93. package/packages/pds-cli/bin/postinstall.js +380 -0
  94. package/packages/pds-cli/bin/sync-assets.js +252 -0
  95. package/packages/pds-cli/lib/asset-roots.js +47 -0
  96. package/packages/pds-cli/lib/fs-writer.js +75 -0
  97. package/pds.css-data.json +5 -0
  98. package/pds.html-data.json +5 -0
  99. package/public/assets/js/app.js +5719 -0
  100. package/public/assets/js/lit.js +131 -0
  101. package/public/assets/js/pds.js +3423 -0
  102. package/public/assets/pds/components/pds-calendar.js +837 -0
  103. package/public/assets/pds/components/pds-drawer.js +857 -0
  104. package/public/assets/pds/components/pds-icon.js +338 -0
  105. package/public/assets/pds/components/pds-jsonform.js +1775 -0
  106. package/public/assets/pds/components/pds-richtext.js +1035 -0
  107. package/public/assets/pds/components/pds-scrollrow.js +331 -0
  108. package/public/assets/pds/components/pds-splitpanel.js +401 -0
  109. package/public/assets/pds/components/pds-tabstrip.js +251 -0
  110. package/public/assets/pds/components/pds-toaster.js +446 -0
  111. package/public/assets/pds/components/pds-upload.js +657 -0
  112. package/public/assets/pds/custom-elements.json +2003 -0
  113. package/public/assets/pds/icons/pds-icons.svg +498 -0
  114. package/public/assets/pds/pds-css-complete.json +1861 -0
  115. package/public/assets/pds/pds.css-data.json +2152 -0
  116. package/public/assets/pds/vscode-custom-data.json +824 -0
  117. package/readme.md +1870 -0
  118. package/src/js/pds-core/pds-config.js +1162 -0
  119. package/src/js/pds-core/pds-enhancer-metadata.js +75 -0
  120. package/src/js/pds-core/pds-enhancers.js +357 -0
  121. package/src/js/pds-core/pds-enums.js +86 -0
  122. package/src/js/pds-core/pds-generator.js +5317 -0
  123. package/src/js/pds-core/pds-ontology.js +256 -0
  124. package/src/js/pds-core/pds-paths.js +109 -0
  125. package/src/js/pds-core/pds-query.js +571 -0
  126. package/src/js/pds-core/pds-registry.js +129 -0
  127. package/src/js/pds-core/pds.d.ts +129 -0
  128. package/src/js/pds.d.ts +408 -0
  129. package/src/js/pds.js +1579 -0
@@ -0,0 +1,352 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Generate Custom Elements Manifest
5
+ * Creates custom-elements.json with metadata for all PDS components
6
+ */
7
+
8
+ import { writeFile, mkdir, readFile } from 'fs/promises';
9
+ import { existsSync } from 'fs';
10
+ import path from 'path';
11
+ import { fileURLToPath, pathToFileURL } from 'url';
12
+ import { execSync } from 'child_process';
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = path.dirname(__filename);
16
+ const repoRoot = path.resolve(__dirname, '../../../');
17
+
18
+ // Colors for terminal output
19
+ const COLORS = {
20
+ reset: '\x1b[0m',
21
+ bold: '\x1b[1m',
22
+ green: '\x1b[32m',
23
+ yellow: '\x1b[33m',
24
+ blue: '\x1b[34m',
25
+ red: '\x1b[31m',
26
+ };
27
+
28
+ const shouldLogToStderr = () => process.env.PDS_LOG_STREAM === 'stderr' || process.env.PDS_POSTINSTALL === '1';
29
+ const log = (msg, color = 'reset') => {
30
+ const colorCode = COLORS[color] || '';
31
+ const text = `${colorCode}${msg}${COLORS.reset}`;
32
+ if (shouldLogToStderr()) {
33
+ process.stderr.write(`${text}\n`);
34
+ } else {
35
+ console.log(text);
36
+ }
37
+ };
38
+
39
+ async function copyBundledManifest(targetDir) {
40
+ try {
41
+ const sourceManifest = path.join(repoRoot, 'custom-elements.json');
42
+ if (!existsSync(sourceManifest)) {
43
+ log('⚠️ Packaged custom-elements.json not found; skipping manifest copy.', 'yellow');
44
+ return false;
45
+ }
46
+
47
+ if (targetDir) {
48
+ await mkdir(targetDir, { recursive: true });
49
+ const manifestContent = await readFile(sourceManifest, 'utf-8');
50
+ const manifestTarget = path.join(targetDir, 'custom-elements.json');
51
+ await writeFile(manifestTarget, manifestContent, 'utf-8');
52
+ log(`✅ Manifest copied to ${path.relative(process.cwd(), manifestTarget)}`, 'green');
53
+ } else {
54
+ log('✅ Packaged custom-elements.json is available', 'green');
55
+ }
56
+
57
+ const packagedVscodeData = path.join(repoRoot, 'public/assets/pds/vscode-custom-data.json');
58
+ if (targetDir && existsSync(packagedVscodeData)) {
59
+ const vscodeContent = await readFile(packagedVscodeData, 'utf-8');
60
+ const vscodeTarget = path.join(targetDir, 'vscode-custom-data.json');
61
+ await writeFile(vscodeTarget, vscodeContent, 'utf-8');
62
+ log(`✅ VS Code custom data copied to ${path.relative(process.cwd(), vscodeTarget)}`, 'green');
63
+ }
64
+
65
+ return true;
66
+ } catch (error) {
67
+ log(`❌ Failed to copy packaged manifest: ${error?.message || error}`, 'red');
68
+ return false;
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Convert Custom Elements Manifest to VS Code Custom Data format
74
+ */
75
+ async function convertToVSCodeFormat(manifest) {
76
+ const tags = [];
77
+
78
+ // Load icon configuration
79
+ let availableIcons = [];
80
+ try {
81
+ const configPath = path.join(repoRoot, 'src/js/pds-core/pds-config.js');
82
+ const { presets } = await import(pathToFileURL(configPath).href);
83
+
84
+ // Get icons from default preset
85
+ const iconConfig = presets?.default?.icons?.include || {};
86
+
87
+ // Extract all icon names from all categories
88
+ availableIcons = Array.from(new Set(
89
+ Object.values(iconConfig).flat()
90
+ )).filter(Boolean).sort();
91
+
92
+ if (availableIcons.length > 0) {
93
+ log(`🎨 Found ${availableIcons.length} icons in configuration`, 'blue');
94
+ }
95
+ } catch (error) {
96
+ log(`⚠️ Could not load icon configuration: ${error.message}`, 'yellow');
97
+ }
98
+
99
+ // Load enhancers for data attribute autocomplete
100
+ let enhancerAttributes = [];
101
+ try {
102
+ const pdsPath = path.join(repoRoot, 'src/js/pds.js');
103
+ const pdsModule = await import(pathToFileURL(pdsPath).href);
104
+ const enhancers = pdsModule?.PDS?.defaultEnhancers || [];
105
+
106
+ for (const enhancer of enhancers) {
107
+ // Extract data-* attributes from selectors
108
+ const selectorMatch = enhancer.selector.match(/\[data-([^\]]+)\]/);
109
+ if (selectorMatch) {
110
+ const attrName = `data-${selectorMatch[1]}`;
111
+ let demoCode = '';
112
+
113
+ // Get demo HTML if available
114
+ if (enhancer.demoHtml) {
115
+ try {
116
+ demoCode = typeof enhancer.demoHtml === 'function'
117
+ ? enhancer.demoHtml()
118
+ : enhancer.demoHtml;
119
+ // Clean up the demo code
120
+ demoCode = demoCode.trim().replace(/\n\s+/g, '\n').replace(/\n{3,}/g, '\n\n');
121
+ } catch (e) {
122
+ demoCode = '';
123
+ }
124
+ }
125
+
126
+ enhancerAttributes.push({
127
+ name: attrName,
128
+ description: enhancer.description || `Progressive enhancement: ${enhancer.selector}`,
129
+ demoCode: demoCode,
130
+ selector: enhancer.selector
131
+ });
132
+ }
133
+ }
134
+
135
+ if (enhancerAttributes.length > 0) {
136
+ log(`🔧 Found ${enhancerAttributes.length} enhancement attributes`, 'blue');
137
+ }
138
+ } catch (error) {
139
+ log(`⚠️ Could not load enhancers: ${error.message}`, 'yellow');
140
+ }
141
+
142
+ manifest.modules?.forEach(module => {
143
+ module.declarations?.forEach(declaration => {
144
+ if (declaration.tagName && declaration.customElement) {
145
+ const tag = {
146
+ name: declaration.tagName,
147
+ description: declaration.description || `${declaration.name} component`
148
+ };
149
+
150
+ // Add attributes
151
+ if (declaration.attributes && declaration.attributes.length > 0) {
152
+ tag.attributes = declaration.attributes.map(attr => {
153
+ const attribute = {
154
+ name: attr.name,
155
+ description: attr.description || ''
156
+ };
157
+
158
+ // Special handling for pds-icon's icon attribute - add available icon names
159
+ if (declaration.tagName === 'pds-icon' && attr.name === 'icon' && availableIcons.length > 0) {
160
+ attribute.values = availableIcons.map(iconName => ({
161
+ name: iconName,
162
+ description: `${iconName} icon`
163
+ }));
164
+ }
165
+ // Check if type indicates enum values
166
+ else if (attr.type?.text) {
167
+ const typeText = attr.type.text;
168
+ // Match patterns like "bottom" | "top" | "left" | "right"
169
+ const enumMatch = typeText.match(/"([^"]+)"/g);
170
+ if (enumMatch && enumMatch.length > 1) {
171
+ attribute.values = enumMatch.map(val => ({ name: val.replace(/"/g, '') }));
172
+ }
173
+ }
174
+
175
+ // Add boolean value set for boolean types
176
+ if (attr.type?.text === 'boolean') {
177
+ attribute.valueSet = 'v';
178
+ }
179
+
180
+ return attribute;
181
+ });
182
+ }
183
+
184
+ tags.push(tag);
185
+ }
186
+ });
187
+ });
188
+
189
+ // Build global attributes for data-* enhancements
190
+ const globalAttributes = enhancerAttributes.map(attr => {
191
+ const description = attr.demoCode
192
+ ? `${attr.description}\n\nExample:\n${attr.demoCode}`
193
+ : attr.description;
194
+
195
+ return {
196
+ name: attr.name,
197
+ description: description,
198
+ valueSet: 'v' // Boolean-like attributes
199
+ };
200
+ });
201
+
202
+ return {
203
+ version: 1.1,
204
+ tags,
205
+ globalAttributes: globalAttributes.length > 0 ? globalAttributes : undefined
206
+ };
207
+ }
208
+
209
+ /**
210
+ * Create pds.html-data.json in project root
211
+ */
212
+ async function createHtmlDataConfig(vscodeDataPath) {
213
+ const config = {
214
+ "html.customData": [vscodeDataPath]
215
+ };
216
+
217
+ const configPath = path.join(repoRoot, 'pds.html-data.json');
218
+ await writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
219
+ log(`✅ Created pds.html-data.json`, 'green');
220
+ return configPath;
221
+ }
222
+
223
+ /**
224
+ * Reload VS Code window
225
+ */
226
+ function reloadVSCode() {
227
+ // Note: Automatic reload would require VS Code extension API
228
+ // For now, just inform the user to reload manually
229
+ log('⚠️ Please reload VS Code to activate the updated custom data:', 'yellow');
230
+ log(' Press Ctrl+Shift+P → "Developer: Reload Window"', 'blue');
231
+ }
232
+
233
+ /**
234
+ * Analyze components and generate manifest
235
+ */
236
+ async function generateManifest(targetDir) {
237
+ try {
238
+ log('📋 Generating Custom Elements Manifest...', 'bold');
239
+
240
+ const analyzerInstalled = existsSync(path.join(repoRoot, 'node_modules/@custom-elements-manifest/analyzer'));
241
+ const runningFromPostinstall = process.env.PDS_POSTINSTALL === '1';
242
+
243
+ if (!analyzerInstalled || runningFromPostinstall) {
244
+ if (!analyzerInstalled) {
245
+ const color = runningFromPostinstall ? 'blue' : 'yellow';
246
+ log('ℹ️ Using packaged Custom Elements manifest (analyzer not available).', color);
247
+ if (!runningFromPostinstall) {
248
+ log(' Install @custom-elements-manifest/analyzer to enable manifest regeneration.', 'yellow');
249
+ }
250
+ } else {
251
+ log('ℹ️ Skipping analyzer during postinstall; using packaged manifest.', 'blue');
252
+ }
253
+ return copyBundledManifest(targetDir);
254
+ }
255
+
256
+ // Run the analyzer
257
+ const configPath = path.join(repoRoot, 'custom-elements-manifest.config.js');
258
+
259
+ log('🔍 Analyzing components...', 'blue');
260
+
261
+ try {
262
+ execSync(`npx cem analyze --config ${configPath}`, {
263
+ cwd: repoRoot,
264
+ stdio: 'inherit'
265
+ });
266
+
267
+ // Post-process: Remove private members from the generated manifest
268
+ const sourceManifest = path.join(repoRoot, 'custom-elements.json');
269
+ if (existsSync(sourceManifest)) {
270
+ log('🧹 Cleaning private members from manifest...', 'blue');
271
+ const manifestContent = await readFile(sourceManifest, 'utf-8');
272
+ const manifest = JSON.parse(manifestContent);
273
+
274
+ // Filter out private members from all declarations
275
+ manifest.modules?.forEach(module => {
276
+ module.declarations?.forEach(declaration => {
277
+ if (declaration.members) {
278
+ declaration.members = declaration.members.filter(member => {
279
+ // Keep only public members (exclude private and those starting with #)
280
+ return member.privacy !== 'private' && !member.name?.startsWith('#');
281
+ });
282
+ }
283
+ });
284
+ });
285
+
286
+ // Write cleaned manifest back
287
+ await writeFile(sourceManifest, JSON.stringify(manifest, null, 2), 'utf-8');
288
+ log('✅ Private members removed', 'green');
289
+ }
290
+
291
+ // Copy manifest to target directory if specified
292
+ if (targetDir) {
293
+ const targetManifest = path.join(targetDir, 'custom-elements.json');
294
+
295
+ if (existsSync(sourceManifest)) {
296
+ await mkdir(path.dirname(targetManifest), { recursive: true });
297
+ const manifestContent = await readFile(sourceManifest, 'utf-8');
298
+ await writeFile(targetManifest, manifestContent, 'utf-8');
299
+ log(`✅ Manifest copied to ${path.relative(process.cwd(), targetManifest)}`, 'green');
300
+ }
301
+ }
302
+
303
+ log('✅ Custom Elements Manifest generated', 'green');
304
+
305
+ // Step 1: Generate VS Code custom data file
306
+ log('🔧 Generating VS Code custom data...', 'blue');
307
+ const manifestContent = await readFile(sourceManifest, 'utf-8');
308
+ const manifest = JSON.parse(manifestContent);
309
+ const vscodeData = await convertToVSCodeFormat(manifest);
310
+
311
+ // Write to both locations
312
+ const vscodeDataPath = path.join(repoRoot, 'public/assets/pds/vscode-custom-data.json');
313
+ await mkdir(path.dirname(vscodeDataPath), { recursive: true });
314
+ await writeFile(vscodeDataPath, JSON.stringify(vscodeData, null, 2), 'utf-8');
315
+ log(`✅ VS Code custom data generated at ${path.relative(repoRoot, vscodeDataPath)}`, 'green');
316
+
317
+ // Also copy to target directory if specified
318
+ if (targetDir) {
319
+ const targetVSCodeData = path.join(targetDir, 'vscode-custom-data.json');
320
+ await writeFile(targetVSCodeData, JSON.stringify(vscodeData, null, 2), 'utf-8');
321
+ log(`✅ VS Code custom data copied to ${path.relative(process.cwd(), targetVSCodeData)}`, 'green');
322
+ }
323
+
324
+ // Step 2: Create pds.html-data.json in project root
325
+ const relativePath = 'public/assets/pds/vscode-custom-data.json';
326
+ await createHtmlDataConfig(relativePath);
327
+
328
+ // Step 3: Reload VS Code window
329
+ log('🔄 Reloading VS Code...', 'blue');
330
+ reloadVSCode();
331
+
332
+ return true;
333
+ } catch (error) {
334
+ log(`❌ Manifest generation failed: ${error.message}`, 'red');
335
+ return false;
336
+ }
337
+
338
+ } catch (error) {
339
+ log(`❌ Error: ${error.message}`, 'red');
340
+ return false;
341
+ }
342
+ }
343
+
344
+ export { generateManifest };
345
+
346
+ // Run if called directly
347
+ if (process.argv[1] && process.argv[1].endsWith('generate-manifest.js')) {
348
+ const targetDir = process.argv[2] || null;
349
+ generateManifest(targetDir).then(success => {
350
+ process.exit(success ? 0 : 1);
351
+ });
352
+ }
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * PDS Build Icons CLI
5
+ *
6
+ * Rebuilds the SVG sprite (pds-icons.svg) into the consumer app's configured static root.
7
+ * Output path: [public.root]/icons/pds-icons.svg
8
+ *
9
+ * Usage: node node_modules/@pure-ds/core/packages/pds-cli/bin/pds-build-icons.js
10
+ */
11
+
12
+ import { readFile, writeFile, mkdir, access } from 'fs/promises';
13
+ import path from 'path';
14
+ import { fileURLToPath, pathToFileURL } from 'url';
15
+ import { resolvePublicAssetDirectory, ensurePdsPath } from '../lib/asset-roots.js';
16
+
17
+ const __filename = fileURLToPath(import.meta.url);
18
+ const __dirname = path.dirname(__filename);
19
+ const repoRoot = path.resolve(__dirname, '../../../');
20
+
21
+ const COLORS = {
22
+ reset: '\x1b[0m',
23
+ bold: '\x1b[1m',
24
+ green: '\x1b[32m',
25
+ yellow: '\x1b[33m',
26
+ blue: '\x1b[34m',
27
+ red: '\x1b[31m',
28
+ };
29
+ const shouldLogToStderr = () => process.env.PDS_LOG_STREAM === 'stderr' || process.env.PDS_POSTINSTALL === '1';
30
+ const log = (msg, color = 'reset') => {
31
+ const colorCode = COLORS[color] || '';
32
+ const text = `${colorCode}${msg}${COLORS.reset}`;
33
+ if (shouldLogToStderr()) {
34
+ process.stderr.write(`${text}\n`);
35
+ } else {
36
+ console.log(text);
37
+ }
38
+ };
39
+
40
+ async function loadConsumerConfig() {
41
+ const cwd = process.cwd();
42
+ for (const fname of ['pds.config.js', 'pds-config.js']) {
43
+ const p = path.join(cwd, fname);
44
+ try { await access(p); } catch { continue; }
45
+ const mod = await import(pathToFileURL(p).href);
46
+ return mod.config || mod.default || mod.presets?.default || null;
47
+ }
48
+ const internal = await import(pathToFileURL(path.join(repoRoot, 'src/js/pds-core/pds-config.js')).href);
49
+ return internal.presets?.default || null;
50
+ }
51
+
52
+ async function fetchText(url) {
53
+ const res = await fetch(url);
54
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
55
+ return res.text();
56
+ }
57
+
58
+ async function fetchIcon(set, name, weight = 'regular', variant = 'outline') {
59
+ switch (set) {
60
+ case 'phosphor':
61
+ return fetchText(`https://unpkg.com/@phosphor-icons/core@2.1.1/assets/${weight}/${name}.svg`);
62
+ case 'lucide':
63
+ return fetchText(`https://unpkg.com/lucide-static@latest/icons/${name}.svg`);
64
+ case 'heroicons':
65
+ return fetchText(`https://unpkg.com/heroicons@2.0.18/24/${variant}/${name}.svg`);
66
+ case 'tabler':
67
+ return fetchText(`https://unpkg.com/@tabler/icons@latest/icons/outline/${name}.svg`);
68
+ default:
69
+ throw new Error(`Unknown icon set: ${set}`);
70
+ }
71
+ }
72
+
73
+ function svgToSymbol(svgContent, id) {
74
+ const viewBox = (svgContent.match(/viewBox="([^"]+)"/) || [])[1] || '0 0 256 256';
75
+ const inner = (svgContent.match(/<svg[^>]*>([\s\S]*?)<\/svg>/) || [])[1] || '';
76
+ const clean = inner.replace(/fill="[^"]*"/g, 'fill="currentColor"')
77
+ .replace(/stroke="[^"]*"/g, 'stroke="currentColor"');
78
+ return ` <symbol id="${id}" viewBox="${viewBox}">\n${clean.trim().split('\n').map(l=>` ${l}`).join('\n')}\n </symbol>`;
79
+ }
80
+
81
+ async function main() {
82
+ try {
83
+ log('\n🎨 PDS Build Icons • starting...', 'bold');
84
+ const config = await loadConsumerConfig();
85
+
86
+ const envRoot = process.env.PDS_STATIC_ROOT;
87
+ let staticRoot;
88
+ if (envRoot && typeof envRoot === 'string') {
89
+ const resolved = path.isAbsolute(envRoot)
90
+ ? envRoot
91
+ : path.resolve(process.cwd(), envRoot);
92
+ staticRoot = ensurePdsPath(resolved);
93
+ } else {
94
+ staticRoot = resolvePublicAssetDirectory(config);
95
+ }
96
+
97
+ const outDir = path.join(staticRoot, 'icons');
98
+ const outFile = path.join(outDir, 'pds-icons.svg');
99
+
100
+ // Determine icon set configuration (consumer overrides internal defaults)
101
+ const internal = await import(pathToFileURL(path.join(repoRoot, 'src/js/pds-core/pds-config.js')).href);
102
+ const internalIcons = internal.presets?.default?.icons || {};
103
+ const consumerIcons = config?.icons || {};
104
+ const set = consumerIcons.set || internalIcons.set || 'phosphor';
105
+ const weight = consumerIcons.weight || internalIcons.weight || 'regular';
106
+ const include = consumerIcons.include || internalIcons.include || {};
107
+
108
+ const names = Array.from(new Set(Object.values(include).flat()))
109
+ .filter(Boolean);
110
+ log(`📦 Icon set: ${set}`, 'blue');
111
+ if (set === 'phosphor') log(`⚖️ Weight: ${weight}`, 'blue');
112
+ log(`📝 Total icons: ${names.length}`, 'blue');
113
+
114
+ const symbols = [];
115
+ let ok = 0, fail = 0;
116
+ for (const name of names) {
117
+ try {
118
+ const svg = await fetchIcon(set, name, weight);
119
+ symbols.push(svgToSymbol(svg, name));
120
+ ok++; log(` ✓ ${name}`, 'green');
121
+ } catch (e) {
122
+ fail++; log(` ✗ ${name}: ${e?.message || e}`, 'red');
123
+ }
124
+ }
125
+
126
+ const sprite = `<?xml version="1.0" encoding="UTF-8"?>\n<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none">\n${symbols.join('\n\n')}\n</svg>\n`;
127
+
128
+ await mkdir(outDir, { recursive: true });
129
+ await writeFile(outFile, sprite, 'utf-8');
130
+
131
+ log('\n────────────────────────────────────────────', 'bold');
132
+ log('✅ Icons sprite built', 'green');
133
+ log(`📁 Output: ${path.relative(process.cwd(), outFile)}`);
134
+ log(`✓ ${ok} icons included${fail?`, ✗ ${fail} failed`:''}`);
135
+ log('────────────────────────────────────────────\n', 'bold');
136
+ } catch (err) {
137
+ console.error('❌ pds:build-icons failed:', err?.message || err);
138
+ process.exit(1);
139
+ }
140
+ }
141
+
142
+ // Execute when run directly from Node or via bin entry (including symlinks on macOS/Linux)
143
+ if (process.argv[1]) {
144
+ const scriptPath = fileURLToPath(import.meta.url);
145
+ const argPath = process.argv[1];
146
+ // Check if this is the main module being executed
147
+ if (argPath === scriptPath || argPath.endsWith('pds-build-icons.js') || argPath.endsWith('pds-build-icons')) {
148
+ main();
149
+ }
150
+ }
151
+
152
+ export { main as runPdsBuildIcons };
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * PDS Developer Experience (DX) Script
5
+ * Runs all IntelliSense and tooling generation:
6
+ * - Custom Elements Manifest (HTML IntelliSense)
7
+ * - CSS Custom Data (CSS IntelliSense)
8
+ *
9
+ * This provides complete IDE support for consuming projects
10
+ */
11
+
12
+ import { generateManifest } from './generate-manifest.js';
13
+ import { generateCSSData } from './generate-css-data.js';
14
+
15
+ // Colors for terminal output
16
+ const COLORS = {
17
+ reset: '\x1b[0m',
18
+ bold: '\x1b[1m',
19
+ green: '\x1b[32m',
20
+ yellow: '\x1b[33m',
21
+ blue: '\x1b[34m',
22
+ red: '\x1b[31m',
23
+ cyan: '\x1b[36m',
24
+ magenta: '\x1b[35m',
25
+ };
26
+ const log = (msg, color = 'reset') => console.log(`${COLORS[color]}${msg}${COLORS.reset}`);
27
+
28
+ /**
29
+ * Run all DX tooling generation
30
+ */
31
+ async function generateDXTools(targetDir) {
32
+ try {
33
+ log('\n╔════════════════════════════════════════════════════════════╗', 'cyan');
34
+ log('║ 🚀 PDS Developer Experience (DX) Tool Generator ║', 'cyan');
35
+ log('╚════════════════════════════════════════════════════════════╝\n', 'cyan');
36
+
37
+ let allSuccess = true;
38
+
39
+ // Step 1: Generate Custom Elements Manifest (HTML IntelliSense)
40
+ log('┌─────────────────────────────────────────────────────────┐', 'blue');
41
+ log('│ Step 1: HTML IntelliSense (Custom Elements Manifest) │', 'blue');
42
+ log('└─────────────────────────────────────────────────────────┘\n', 'blue');
43
+
44
+ const manifestSuccess = await generateManifest(targetDir);
45
+ if (!manifestSuccess) {
46
+ log('⚠️ Custom Elements Manifest generation had issues', 'yellow');
47
+ allSuccess = false;
48
+ }
49
+
50
+ log('\n'); // Spacing between steps
51
+
52
+ // Step 2: Generate CSS Custom Data (CSS IntelliSense)
53
+ log('┌─────────────────────────────────────────────────────────┐', 'blue');
54
+ log('│ Step 2: CSS IntelliSense (CSS Custom Data) │', 'blue');
55
+ log('└─────────────────────────────────────────────────────────┘\n', 'blue');
56
+
57
+ const cssDataSuccess = await generateCSSData(targetDir);
58
+ if (!cssDataSuccess) {
59
+ log('⚠️ CSS custom data generation had issues', 'yellow');
60
+ allSuccess = false;
61
+ }
62
+
63
+ // Summary
64
+ log('\n╔════════════════════════════════════════════════════════════╗', allSuccess ? 'green' : 'yellow');
65
+ log(`║ ${allSuccess ? '✅ All DX Tools Generated Successfully!' : '⚠️ DX Tools Generated with Warnings'} ║`, allSuccess ? 'green' : 'yellow');
66
+ log('╚════════════════════════════════════════════════════════════╝\n', allSuccess ? 'green' : 'yellow');
67
+
68
+ if (allSuccess) {
69
+ log('📦 Generated files:', 'bold');
70
+ log(' HTML: custom-elements.json, vscode-custom-data.json', 'cyan');
71
+ log(' CSS: pds.css-data.json, pds-css-complete.json', 'cyan');
72
+ log('\n💡 VS Code Setup:', 'bold');
73
+ log(' Add to .vscode/settings.json:', 'blue');
74
+ log(' {', 'cyan');
75
+ log(' "html.customData": ["./pds.html-data.json"],', 'cyan');
76
+ log(' "css.customData": ["./pds.css-data.json"]', 'cyan');
77
+ log(' }', 'cyan');
78
+ log('\n🔄 Reload VS Code:', 'bold');
79
+ log(' Press Ctrl+Shift+P → "Developer: Reload Window"', 'blue');
80
+ }
81
+
82
+ return allSuccess;
83
+ } catch (error) {
84
+ log(`\n❌ Fatal error in DX tool generation: ${error.message}`, 'red');
85
+ console.error(error);
86
+ return false;
87
+ }
88
+ }
89
+
90
+ // Run if called directly
91
+ if (import.meta.url === `file://${process.argv[1]}`) {
92
+ const targetDir = process.argv[2] || null;
93
+
94
+ if (process.argv.includes('--help') || process.argv.includes('-h')) {
95
+ log('PDS Developer Experience Tool Generator', 'bold');
96
+ log('\nUsage:', 'cyan');
97
+ log(' pds-dx [target-directory]', 'blue');
98
+ log('\nDescription:', 'cyan');
99
+ log(' Generates all IntelliSense data for IDE support:', 'blue');
100
+ log(' - Custom Elements Manifest (HTML autocomplete)', 'blue');
101
+ log(' - CSS Custom Data (CSS tokens & classes)', 'blue');
102
+ log('\nExamples:', 'cyan');
103
+ log(' pds-dx # Generate in default location', 'blue');
104
+ log(' pds-dx public/assets/pds # Generate in specific directory', 'blue');
105
+ log(' npm run pds:dx # Run via npm script', 'blue');
106
+ process.exit(0);
107
+ }
108
+
109
+ generateDXTools(targetDir).then(success => {
110
+ process.exit(success ? 0 : 1);
111
+ });
112
+ }
113
+
114
+ export { generateDXTools };