myaidev-method 0.2.23 → 0.2.24-2

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 (60) hide show
  1. package/.claude-plugin/plugin.json +251 -0
  2. package/PLUGIN_ARCHITECTURE.md +276 -0
  3. package/README.md +204 -0
  4. package/USER_GUIDE.md +436 -9
  5. package/bin/cli.js +370 -38
  6. package/dist/server/.tsbuildinfo +1 -1
  7. package/extension.json +174 -0
  8. package/hooks/hooks.json +221 -0
  9. package/marketplace.json +179 -0
  10. package/package.json +24 -7
  11. package/skills/content-verifier/SKILL.md +178 -0
  12. package/skills/content-writer/SKILL.md +151 -0
  13. package/skills/coolify-deployer/SKILL.md +207 -0
  14. package/skills/openstack-manager/SKILL.md +213 -0
  15. package/skills/security-auditor/SKILL.md +180 -0
  16. package/skills/security-tester/SKILL.md +171 -0
  17. package/skills/sparc-architect/SKILL.md +146 -0
  18. package/skills/sparc-coder/SKILL.md +136 -0
  19. package/skills/sparc-documenter/SKILL.md +195 -0
  20. package/skills/sparc-reviewer/SKILL.md +179 -0
  21. package/skills/sparc-tester/SKILL.md +156 -0
  22. package/skills/visual-generator/SKILL.md +147 -0
  23. package/skills/wordpress-publisher/SKILL.md +150 -0
  24. package/src/config/workflows.js +28 -44
  25. package/src/lib/ascii-banner.js +214 -0
  26. package/src/lib/config-manager.js +470 -0
  27. package/src/lib/content-coordinator.js +2562 -0
  28. package/src/lib/content-generator.js +427 -0
  29. package/src/lib/html-conversion-utils.js +843 -0
  30. package/src/lib/installation-detector.js +266 -0
  31. package/src/lib/seo-optimizer.js +515 -0
  32. package/src/lib/visual-config-utils.js +1 -1
  33. package/src/lib/visual-generation-utils.js +34 -14
  34. package/src/lib/wordpress-client.js +633 -0
  35. package/src/lib/workflow-installer.js +3 -3
  36. package/src/scripts/generate-visual-cli.js +39 -10
  37. package/src/scripts/html-conversion-cli.js +526 -0
  38. package/src/scripts/init/configure.js +436 -0
  39. package/src/scripts/init/install.js +460 -0
  40. package/src/scripts/ping.js +0 -1
  41. package/src/scripts/utils/file-utils.js +404 -0
  42. package/src/scripts/utils/logger.js +300 -0
  43. package/src/scripts/utils/write-content.js +293 -0
  44. package/src/templates/claude/agents/content-production-coordinator.md +689 -15
  45. package/src/templates/claude/agents/visual-content-generator.md +129 -4
  46. package/src/templates/claude/commands/myai-content-enrichment.md +227 -0
  47. package/src/templates/claude/commands/myai-content-writer.md +48 -37
  48. package/src/templates/claude/commands/myai-convert-html.md +186 -0
  49. package/src/templates/claude/commands/myai-coordinate-content.md +347 -11
  50. package/src/templates/diagrams/architecture.d2 +52 -0
  51. package/src/templates/diagrams/flowchart.d2 +42 -0
  52. package/src/templates/diagrams/sequence.d2 +47 -0
  53. package/src/templates/docs/content-creation-guide.md +164 -0
  54. package/src/templates/docs/deployment-guide.md +336 -0
  55. package/src/templates/docs/visual-generation-guide.md +248 -0
  56. package/src/templates/docs/wordpress-publishing-guide.md +208 -0
  57. package/src/templates/infographics/comparison-table.html +347 -0
  58. package/src/templates/infographics/data-chart.html +268 -0
  59. package/src/templates/infographics/process-flow.html +365 -0
  60. /package/src/scripts/{wordpress-health-check.js → wordpress/wordpress-health-check.js} +0 -0
@@ -14,9 +14,10 @@
14
14
 
15
15
  import {
16
16
  generateImage,
17
- generateVideoVeo,
17
+ generateVideo,
18
18
  estimateCost,
19
19
  validateAPIKeys,
20
+ FLUX2_MODELS,
20
21
  } from "../lib/visual-generation-utils.js";
21
22
  import {
22
23
  saveImage,
@@ -57,6 +58,7 @@ if (!prompt) {
57
58
  const options = {
58
59
  type: getOption("type", "hero"),
59
60
  service: getOption("service", null),
61
+ model: getOption("model", null),
60
62
  size: getOption("size", "1024x1024"),
61
63
  quality: getOption("quality", "standard"),
62
64
  description: getOption("description", null),
@@ -96,11 +98,24 @@ const options = {
96
98
 
97
99
  // Estimate cost
98
100
  let service = options.service;
99
- if (!service) {
100
- // Auto-select based on available services
101
- const validation = validateAPIKeys();
102
- service = validation.availableServices[0];
103
- console.log(chalk.gray(`Auto-selected service: ${service}`));
101
+
102
+ // Video generation always uses veo3, ignore model/service for cost estimation
103
+ if (options.type === "video") {
104
+ service = "veo3";
105
+ console.log(chalk.gray(`Video generation uses: veo3`));
106
+ } else {
107
+ // For images: if model is specified, it takes precedence over service
108
+ if (options.model && FLUX2_MODELS[options.model]) {
109
+ service = options.model;
110
+ console.log(chalk.gray(`Using model: ${options.model}`));
111
+ }
112
+
113
+ if (!service) {
114
+ // Auto-select based on available services
115
+ const validation = validateAPIKeys();
116
+ service = validation.availableServices[0];
117
+ console.log(chalk.gray(`Auto-selected service: ${service}`));
118
+ }
104
119
  }
105
120
 
106
121
  const cost = estimateCost(service, {
@@ -108,13 +123,20 @@ const options = {
108
123
  size: options.size,
109
124
  });
110
125
 
126
+ // For video, multiply by duration
127
+ const videoDuration = 5; // Default duration
128
+ const finalCost = options.type === "video" ? cost * videoDuration : cost;
129
+
111
130
  // Check budget
112
- const budget = await checkBudgetLimit(cost);
131
+ const budget = await checkBudgetLimit(finalCost);
113
132
  const todayCost = await getTodaysCost();
114
133
  const monthCost = await getMonthCost();
115
134
 
116
135
  console.log(chalk.cyan("💰 Cost Estimate:"));
117
- console.log(chalk.gray(` This generation: $${cost.toFixed(2)}`));
136
+ console.log(chalk.gray(` This generation: $${finalCost.toFixed(2)}`));
137
+ if (options.type === "video") {
138
+ console.log(chalk.gray(` (${videoDuration}s × $${cost.toFixed(2)}/s)`));
139
+ }
118
140
  console.log(
119
141
  chalk.gray(
120
142
  ` Today: $${todayCost.toFixed(2)} / $${budget.dailyBudget.toFixed(2)} (${Math.round((todayCost / budget.dailyBudget) * 100)}%)`,
@@ -177,7 +199,7 @@ const options = {
177
199
  if (options.type === "video") {
178
200
  // Generate video
179
201
  spinner.text = `Generating video using ${service}...`;
180
- result = await generateVideoVeo(prompt, {
202
+ result = await generateVideo(prompt, {
181
203
  duration: 5,
182
204
  aspectRatio: "16:9",
183
205
  });
@@ -198,6 +220,7 @@ const options = {
198
220
  spinner.text = `Generating ${options.type} using ${service}...`;
199
221
  result = await generateImage(prompt, {
200
222
  preferredService: service,
223
+ model: options.model,
201
224
  type: options.type,
202
225
  quality: options.quality,
203
226
  size: options.size,
@@ -330,9 +353,15 @@ function showHelp() {
330
353
  console.log(
331
354
  chalk.gray(" --service=<service> AI service (default: auto-select)"),
332
355
  );
356
+ console.log(
357
+ chalk.gray(" Values: gemini, imagen, dalle, veo"),
358
+ );
359
+ console.log(
360
+ chalk.gray(" --model=<model> Specific model (for fal service)"),
361
+ );
333
362
  console.log(
334
363
  chalk.gray(
335
- " Values: gemini, imagen, dalle, veo, nano-banana-pro, flux-pro, flux-dev",
364
+ " Values: nano-banana-pro, flux-pro, flux-dev",
336
365
  ),
337
366
  );
338
367
  console.log(
@@ -0,0 +1,526 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * HTML Conversion CLI
5
+ *
6
+ * Converts HTML templates to PNG, PDF, or PPTX formats.
7
+ * Supports both HTML templates and D2 diagram language.
8
+ *
9
+ * Usage:
10
+ * node html-conversion-cli.js --template data-chart --data data.json --format png
11
+ * node html-conversion-cli.js --input template.html --output image.png
12
+ * node html-conversion-cli.js --d2 "a -> b" --format png
13
+ * node html-conversion-cli.js --d2-template architecture --data data.json --format svg
14
+ * node html-conversion-cli.js --slides slides/ --output presentation.pptx
15
+ * node html-conversion-cli.js --list-templates
16
+ */
17
+
18
+ import { Command } from 'commander';
19
+ import chalk from 'chalk';
20
+ import ora from 'ora';
21
+ import fs from 'fs-extra';
22
+ import path from 'path';
23
+ import { fileURLToPath } from 'url';
24
+
25
+ import {
26
+ htmlToPng,
27
+ htmlToPdf,
28
+ htmlToPptx,
29
+ d2ToSvg,
30
+ d2ToPng,
31
+ templateToVisual,
32
+ d2TemplateToVisual,
33
+ renderTemplate,
34
+ renderD2Template,
35
+ getAvailableTemplates,
36
+ isD2Available,
37
+ validateHtml,
38
+ validateD2,
39
+ estimateRenderTime
40
+ } from '../lib/html-conversion-utils.js';
41
+
42
+ const __filename = fileURLToPath(import.meta.url);
43
+ const __dirname = path.dirname(__filename);
44
+
45
+ const program = new Command();
46
+
47
+ program
48
+ .name('html-conversion')
49
+ .description('Convert HTML templates to PNG, PDF, or PPTX formats')
50
+ .version('1.0.0');
51
+
52
+ // Template descriptions
53
+ const TEMPLATE_DESCRIPTIONS = {
54
+ html: {
55
+ 'data-chart': 'Bar/pie charts with data visualization',
56
+ 'comparison-table': 'Side-by-side feature comparisons',
57
+ 'process-flow': 'Step-by-step processes (vertical/horizontal/timeline)'
58
+ },
59
+ d2: {
60
+ 'architecture': 'System architecture diagrams',
61
+ 'flowchart': 'Decision flowcharts',
62
+ 'sequence': 'Sequence diagrams'
63
+ }
64
+ };
65
+
66
+ // List templates command
67
+ program
68
+ .command('list')
69
+ .alias('ls')
70
+ .description('List all available templates')
71
+ .action(async () => {
72
+ const templates = getAvailableTemplates();
73
+
74
+ console.log(chalk.bold('\n📋 Available Templates\n'));
75
+
76
+ if (templates.html.length > 0) {
77
+ console.log(chalk.blue.bold('HTML Templates:'));
78
+ templates.html.forEach(name => {
79
+ const desc = TEMPLATE_DESCRIPTIONS.html[name] || 'Custom template';
80
+ console.log(` • ${chalk.green(name)} - ${desc}`);
81
+ });
82
+ console.log();
83
+ }
84
+
85
+ if (templates.d2.length > 0) {
86
+ console.log(chalk.blue.bold('D2 Diagram Templates:'));
87
+ const d2Status = isD2Available()
88
+ ? chalk.green('(D2 CLI installed)')
89
+ : chalk.yellow('(D2 CLI not installed - install with: curl -fsSL https://d2lang.com/install.sh | sh)');
90
+ console.log(` ${d2Status}`);
91
+ templates.d2.forEach(name => {
92
+ const desc = TEMPLATE_DESCRIPTIONS.d2[name] || 'Custom template';
93
+ console.log(` • ${chalk.green(name)} - ${desc}`);
94
+ });
95
+ console.log();
96
+ }
97
+ });
98
+
99
+ // Convert HTML template
100
+ program
101
+ .command('template <name>')
102
+ .description('Convert an HTML template to image or PDF')
103
+ .option('-d, --data <json>', 'JSON data for template variables')
104
+ .option('-f, --format <format>', 'Output format (png, pdf)', 'png')
105
+ .option('-o, --output <file>', 'Output file path')
106
+ .option('-w, --width <pixels>', 'Image width', '800')
107
+ .option('-h, --height <pixels>', 'Image height (optional)')
108
+ .option('--scale <factor>', 'Device scale factor', '2')
109
+ .action(async (name, options) => {
110
+ const spinner = ora(`Converting template ${chalk.cyan(name)}...`).start();
111
+
112
+ try {
113
+ // Parse data
114
+ let data = {};
115
+ if (options.data) {
116
+ if (options.data.startsWith('{') || options.data.startsWith('[')) {
117
+ data = JSON.parse(options.data);
118
+ } else if (await fs.pathExists(options.data)) {
119
+ data = JSON.parse(await fs.readFile(options.data, 'utf-8'));
120
+ } else {
121
+ throw new Error(`Data file not found: ${options.data}`);
122
+ }
123
+ }
124
+
125
+ const result = await templateToVisual(name, data, options.format, {
126
+ width: parseInt(options.width),
127
+ height: options.height ? parseInt(options.height) : undefined,
128
+ deviceScaleFactor: parseFloat(options.scale),
129
+ output: options.output
130
+ });
131
+
132
+ const outputPath = result.path || options.output;
133
+ const size = result.buffer ? result.buffer.length : 0;
134
+
135
+ spinner.succeed(`Template converted: ${chalk.green(outputPath)}`);
136
+ console.log(` Format: ${options.format}`);
137
+ console.log(` Size: ${(size / 1024).toFixed(2)} KB`);
138
+
139
+ } catch (error) {
140
+ spinner.fail(`Conversion failed: ${error.message}`);
141
+ process.exit(1);
142
+ }
143
+ });
144
+
145
+ // Convert D2 diagram
146
+ program
147
+ .command('d2 <script>')
148
+ .description('Convert D2 diagram script to image')
149
+ .option('-f, --format <format>', 'Output format (svg, png)', 'svg')
150
+ .option('-o, --output <file>', 'Output file path')
151
+ .option('-t, --theme <theme>', 'D2 theme (0-300)', '200')
152
+ .option('--layout <engine>', 'Layout engine (dagre, elk, tala)', 'dagre')
153
+ .action(async (script, options) => {
154
+ if (!isD2Available()) {
155
+ console.log(chalk.yellow('\n⚠️ D2 CLI is not installed.'));
156
+ console.log('Install it with: curl -fsSL https://d2lang.com/install.sh | sh');
157
+ console.log('Or on macOS: brew install d2\n');
158
+ process.exit(1);
159
+ }
160
+
161
+ const spinner = ora('Converting D2 diagram...').start();
162
+
163
+ try {
164
+ // Check if script is a file path
165
+ let d2Script = script;
166
+ if (await fs.pathExists(script)) {
167
+ d2Script = await fs.readFile(script, 'utf-8');
168
+ }
169
+
170
+ let result;
171
+ if (options.format === 'png') {
172
+ result = await d2ToPng(d2Script, {
173
+ theme: parseInt(options.theme),
174
+ layout: options.layout,
175
+ outputPath: options.output
176
+ });
177
+ } else {
178
+ result = await d2ToSvg(d2Script, {
179
+ theme: parseInt(options.theme),
180
+ layout: options.layout,
181
+ outputPath: options.output
182
+ });
183
+ }
184
+
185
+ spinner.succeed(`D2 diagram converted: ${chalk.green(result.path)}`);
186
+ console.log(` Format: ${result.format}`);
187
+ console.log(` Size: ${(result.size / 1024).toFixed(2)} KB`);
188
+
189
+ } catch (error) {
190
+ spinner.fail(`D2 conversion failed: ${error.message}`);
191
+ process.exit(1);
192
+ }
193
+ });
194
+
195
+ // Convert D2 template
196
+ program
197
+ .command('d2-template <name>')
198
+ .description('Convert a D2 template to image')
199
+ .option('-d, --data <json>', 'JSON data for template variables')
200
+ .option('-f, --format <format>', 'Output format (svg, png)', 'svg')
201
+ .option('-o, --output <file>', 'Output file path')
202
+ .option('-t, --theme <theme>', 'D2 theme (0-300)', '200')
203
+ .action(async (name, options) => {
204
+ if (!isD2Available()) {
205
+ console.log(chalk.yellow('\n⚠️ D2 CLI is not installed.'));
206
+ console.log('Install it with: curl -fsSL https://d2lang.com/install.sh | sh\n');
207
+ process.exit(1);
208
+ }
209
+
210
+ const spinner = ora(`Converting D2 template ${chalk.cyan(name)}...`).start();
211
+
212
+ try {
213
+ // Parse data
214
+ let data = {};
215
+ if (options.data) {
216
+ if (options.data.startsWith('{') || options.data.startsWith('[')) {
217
+ data = JSON.parse(options.data);
218
+ } else if (await fs.pathExists(options.data)) {
219
+ data = JSON.parse(await fs.readFile(options.data, 'utf-8'));
220
+ } else {
221
+ throw new Error(`Data file not found: ${options.data}`);
222
+ }
223
+ }
224
+
225
+ const result = await d2TemplateToVisual(name, data, options.format, {
226
+ theme: parseInt(options.theme),
227
+ outputPath: options.output
228
+ });
229
+
230
+ spinner.succeed(`D2 template converted: ${chalk.green(result.path)}`);
231
+ console.log(` Format: ${result.format}`);
232
+ console.log(` Size: ${(result.size / 1024).toFixed(2)} KB`);
233
+
234
+ } catch (error) {
235
+ spinner.fail(`D2 template conversion failed: ${error.message}`);
236
+ process.exit(1);
237
+ }
238
+ });
239
+
240
+ // Convert raw HTML
241
+ program
242
+ .command('html <file>')
243
+ .description('Convert raw HTML file to image or PDF')
244
+ .option('-f, --format <format>', 'Output format (png, pdf)', 'png')
245
+ .option('-o, --output <file>', 'Output file path')
246
+ .option('-w, --width <pixels>', 'Image width', '800')
247
+ .option('-h, --height <pixels>', 'Image height (optional)')
248
+ .option('--scale <factor>', 'Device scale factor', '2')
249
+ .option('--full-page', 'Capture full page', false)
250
+ .action(async (file, options) => {
251
+ const spinner = ora(`Converting HTML file ${chalk.cyan(file)}...`).start();
252
+
253
+ try {
254
+ if (!await fs.pathExists(file)) {
255
+ throw new Error(`File not found: ${file}`);
256
+ }
257
+
258
+ const html = await fs.readFile(file, 'utf-8');
259
+
260
+ // Validate HTML
261
+ const validation = validateHtml(html);
262
+ if (!validation.valid) {
263
+ spinner.warn(`HTML validation warnings: ${validation.warnings.join(', ')}`);
264
+ }
265
+
266
+ let result;
267
+ if (options.format === 'pdf') {
268
+ result = await htmlToPdf(html, {
269
+ output: options.output,
270
+ pdfOptions: {
271
+ format: 'A4',
272
+ printBackground: true
273
+ }
274
+ });
275
+ } else {
276
+ result = await htmlToPng(html, {
277
+ width: parseInt(options.width),
278
+ height: options.height ? parseInt(options.height) : undefined,
279
+ deviceScaleFactor: parseFloat(options.scale),
280
+ fullPage: options.fullPage,
281
+ output: options.output
282
+ });
283
+ }
284
+
285
+ const outputPath = result.path || options.output;
286
+ const size = result.buffer ? result.buffer.length : 0;
287
+
288
+ spinner.succeed(`HTML converted: ${chalk.green(outputPath)}`);
289
+ console.log(` Format: ${options.format}`);
290
+ console.log(` Size: ${(size / 1024).toFixed(2)} KB`);
291
+
292
+ } catch (error) {
293
+ spinner.fail(`HTML conversion failed: ${error.message}`);
294
+ process.exit(1);
295
+ }
296
+ });
297
+
298
+ // Generate PPTX from slides
299
+ program
300
+ .command('pptx <input>')
301
+ .description('Generate PPTX from HTML slides or JSON config')
302
+ .option('-o, --output <file>', 'Output PPTX file path')
303
+ .option('--title <title>', 'Presentation title')
304
+ .option('--author <author>', 'Presentation author')
305
+ .action(async (input, options) => {
306
+ const spinner = ora('Generating PPTX presentation...').start();
307
+
308
+ try {
309
+ let slides = [];
310
+
311
+ if (await fs.pathExists(input)) {
312
+ const stat = await fs.stat(input);
313
+
314
+ if (stat.isDirectory()) {
315
+ // Load all HTML files from directory as slides
316
+ const files = await fs.readdir(input);
317
+ const htmlFiles = files.filter(f => f.endsWith('.html')).sort();
318
+
319
+ for (const file of htmlFiles) {
320
+ const html = await fs.readFile(path.join(input, file), 'utf-8');
321
+ slides.push({ html, title: path.basename(file, '.html') });
322
+ }
323
+ } else if (input.endsWith('.json')) {
324
+ // Load JSON configuration
325
+ const config = JSON.parse(await fs.readFile(input, 'utf-8'));
326
+ slides = config.slides || [];
327
+ } else if (input.endsWith('.html')) {
328
+ // Single HTML file
329
+ const html = await fs.readFile(input, 'utf-8');
330
+ slides.push({ html, title: path.basename(input, '.html') });
331
+ }
332
+ } else {
333
+ throw new Error(`Input not found: ${input}`);
334
+ }
335
+
336
+ if (slides.length === 0) {
337
+ throw new Error('No slides found to convert');
338
+ }
339
+
340
+ spinner.text = `Converting ${slides.length} slide(s) to PPTX...`;
341
+
342
+ const result = await htmlToPptx(slides, {
343
+ outputPath: options.output,
344
+ title: options.title || 'Presentation',
345
+ author: options.author,
346
+ width: 1920,
347
+ height: 1080
348
+ });
349
+
350
+ spinner.succeed(`PPTX generated: ${chalk.green(result.path)}`);
351
+ console.log(` Slides: ${result.slideCount}`);
352
+ console.log(` Size: ${(result.size / 1024).toFixed(2)} KB`);
353
+
354
+ } catch (error) {
355
+ spinner.fail(`PPTX generation failed: ${error.message}`);
356
+ process.exit(1);
357
+ }
358
+ });
359
+
360
+ // Preview template
361
+ program
362
+ .command('preview <name>')
363
+ .description('Preview a template with sample data')
364
+ .option('--type <type>', 'Template type (html, d2)', 'html')
365
+ .action(async (name, options) => {
366
+ const spinner = ora(`Loading preview for ${chalk.cyan(name)}...`).start();
367
+
368
+ try {
369
+ let preview;
370
+
371
+ if (options.type === 'd2') {
372
+ if (!isD2Available()) {
373
+ spinner.warn('D2 CLI not installed. Showing raw template.');
374
+ const templates = await getAvailableTemplates();
375
+ const template = templates.d2.find(t => t.name === name);
376
+ if (template) {
377
+ spinner.stop();
378
+ console.log(chalk.blue.bold(`\nTemplate: ${name}`));
379
+ console.log(chalk.gray('─'.repeat(50)));
380
+ console.log(template.content || 'Template content not available');
381
+ }
382
+ return;
383
+ }
384
+ preview = await d2TemplateToVisual(name, getSampleD2Data(name), 'svg');
385
+ } else {
386
+ preview = await templateToVisual(name, getSampleHtmlData(name), 'png', {
387
+ width: 600,
388
+ scale: 1
389
+ });
390
+ }
391
+
392
+ spinner.succeed(`Preview generated: ${chalk.green(preview.path)}`);
393
+ console.log(`Open the file to see the preview.`);
394
+
395
+ } catch (error) {
396
+ spinner.fail(`Preview failed: ${error.message}`);
397
+ process.exit(1);
398
+ }
399
+ });
400
+
401
+ // Default action for --list-templates flag
402
+ program
403
+ .option('--list-templates', 'List all available templates')
404
+ .action(async (options) => {
405
+ if (options.listTemplates) {
406
+ await program.commands.find(c => c.name() === 'list').action();
407
+ }
408
+ });
409
+
410
+ // Sample data helpers
411
+ function getSampleHtmlData(templateName) {
412
+ const samples = {
413
+ 'data-chart': {
414
+ title: 'Q4 Revenue by Region',
415
+ subtitle: 'Year over Year Comparison',
416
+ chartType: 'bar',
417
+ items: [
418
+ { label: 'North America', value: 45, percentage: 90, color: '#3b82f6' },
419
+ { label: 'Europe', value: 32, percentage: 64, color: '#10b981' },
420
+ { label: 'Asia Pacific', value: 28, percentage: 56, color: '#f59e0b' },
421
+ { label: 'Latin America', value: 15, percentage: 30, color: '#ef4444' }
422
+ ],
423
+ showValueInBar: true,
424
+ source: 'Internal Analytics - 2025',
425
+ accentColor: '#3b82f6',
426
+ accentGradient: '#1d4ed8'
427
+ },
428
+ 'comparison-table': {
429
+ title: 'Feature Comparison',
430
+ subtitle: 'Choose the right plan for your needs',
431
+ layout: 'table',
432
+ columns: [
433
+ { name: 'Feature' },
434
+ { name: 'Basic' },
435
+ { name: 'Pro', class: 'highlight', winner: true },
436
+ { name: 'Enterprise' }
437
+ ],
438
+ rows: [
439
+ { feature: 'Users', values: [{ text: '5' }, { text: 'Unlimited', class: 'highlight' }, { text: 'Unlimited' }] },
440
+ { feature: 'Storage', values: [{ text: '10 GB' }, { text: '100 GB', class: 'highlight' }, { text: '1 TB' }] },
441
+ { feature: 'Support', values: [{ text: 'Email' }, { text: '24/7 Chat', class: 'highlight' }, { text: 'Dedicated' }] },
442
+ { feature: 'API Access', values: [{ isCross: true }, { isCheck: true, class: 'highlight' }, { isCheck: true }] },
443
+ { feature: 'Analytics', values: [{ isPartial: true }, { isCheck: true, class: 'highlight' }, { isCheck: true }] }
444
+ ],
445
+ note: 'All plans include a 14-day free trial',
446
+ accentColor: '#3b82f6'
447
+ },
448
+ 'process-flow': {
449
+ title: 'Development Workflow',
450
+ subtitle: 'From idea to production',
451
+ layout: 'vertical',
452
+ steps: [
453
+ { number: 1, title: 'Planning', description: 'Define requirements and create specifications', details: ['User stories', 'Technical specs', 'Timeline'] },
454
+ { number: 2, title: 'Development', description: 'Build features following best practices', details: ['Code reviews', 'Unit tests', 'Documentation'] },
455
+ { number: 3, title: 'Testing', description: 'Ensure quality through comprehensive testing', details: ['Integration tests', 'E2E tests', 'Performance tests'] },
456
+ { number: 4, title: 'Deployment', description: 'Ship to production with confidence', details: ['CI/CD pipeline', 'Monitoring', 'Rollback plan'] }
457
+ ],
458
+ footerText: 'Iterate and improve continuously',
459
+ accentColor: '#3b82f6'
460
+ }
461
+ };
462
+
463
+ return samples[templateName] || { title: 'Sample Template' };
464
+ }
465
+
466
+ function getSampleD2Data(templateName) {
467
+ const samples = {
468
+ 'architecture': {
469
+ title: 'System Architecture',
470
+ direction: 'right',
471
+ components: [
472
+ { id: 'user', label: 'User', shape: 'person' },
473
+ { id: 'web', label: 'Web App', shape: 'rectangle' },
474
+ { id: 'api', label: 'API Gateway', shape: 'rectangle' },
475
+ { id: 'db', label: 'Database', shape: 'cylinder' },
476
+ { id: 'cache', label: 'Cache', shape: 'rectangle' }
477
+ ],
478
+ connections: [
479
+ { from: 'user', to: 'web', label: 'HTTPS' },
480
+ { from: 'web', to: 'api', label: 'REST' },
481
+ { from: 'api', to: 'db', label: 'SQL' },
482
+ { from: 'api', to: 'cache', label: 'Redis' }
483
+ ]
484
+ },
485
+ 'flowchart': {
486
+ title: 'Decision Flowchart',
487
+ direction: 'down',
488
+ nodes: [
489
+ { id: 'start', label: 'Start', shape: 'oval' },
490
+ { id: 'check', label: 'Valid Input?', shape: 'diamond' },
491
+ { id: 'process', label: 'Process Data', shape: 'rectangle' },
492
+ { id: 'error', label: 'Show Error', shape: 'rectangle' },
493
+ { id: 'end', label: 'End', shape: 'oval' }
494
+ ],
495
+ edges: [
496
+ { from: 'start', to: 'check' },
497
+ { from: 'check', to: 'process', label: 'Yes' },
498
+ { from: 'check', to: 'error', label: 'No' },
499
+ { from: 'process', to: 'end' },
500
+ { from: 'error', to: 'check' }
501
+ ]
502
+ },
503
+ 'sequence': {
504
+ title: 'API Request Flow',
505
+ actors: [
506
+ { id: 'client', label: 'Client' },
507
+ { id: 'server', label: 'Server' },
508
+ { id: 'db', label: 'Database' }
509
+ ],
510
+ messages: [
511
+ { from: 'client', to: 'server', label: 'GET /api/users', response: '200 OK' },
512
+ { from: 'server', to: 'db', label: 'SELECT * FROM users', response: 'Result set' }
513
+ ]
514
+ }
515
+ };
516
+
517
+ return samples[templateName] || { title: 'Sample Diagram' };
518
+ }
519
+
520
+ // Parse and run
521
+ program.parse();
522
+
523
+ // If no command specified, show help
524
+ if (process.argv.length === 2) {
525
+ program.help();
526
+ }