myaidev-method 0.2.23 → 0.2.24

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 (29) hide show
  1. package/bin/cli.js +55 -2
  2. package/dist/server/.tsbuildinfo +1 -1
  3. package/package.json +6 -1
  4. package/src/config/workflows.js +28 -44
  5. package/src/lib/config-manager.js +470 -0
  6. package/src/lib/content-generator.js +427 -0
  7. package/src/lib/html-conversion-utils.js +843 -0
  8. package/src/lib/seo-optimizer.js +515 -0
  9. package/src/lib/wordpress-client.js +633 -0
  10. package/src/lib/workflow-installer.js +3 -3
  11. package/src/scripts/html-conversion-cli.js +526 -0
  12. package/src/scripts/init/configure.js +436 -0
  13. package/src/scripts/init/install.js +460 -0
  14. package/src/scripts/utils/file-utils.js +404 -0
  15. package/src/scripts/utils/logger.js +300 -0
  16. package/src/scripts/utils/write-content.js +293 -0
  17. package/src/templates/claude/agents/visual-content-generator.md +129 -4
  18. package/src/templates/claude/commands/myai-convert-html.md +186 -0
  19. package/src/templates/diagrams/architecture.d2 +52 -0
  20. package/src/templates/diagrams/flowchart.d2 +42 -0
  21. package/src/templates/diagrams/sequence.d2 +47 -0
  22. package/src/templates/docs/content-creation-guide.md +164 -0
  23. package/src/templates/docs/deployment-guide.md +336 -0
  24. package/src/templates/docs/visual-generation-guide.md +248 -0
  25. package/src/templates/docs/wordpress-publishing-guide.md +208 -0
  26. package/src/templates/infographics/comparison-table.html +347 -0
  27. package/src/templates/infographics/data-chart.html +268 -0
  28. package/src/templates/infographics/process-flow.html +365 -0
  29. /package/src/scripts/{wordpress-health-check.js → wordpress/wordpress-health-check.js} +0 -0
@@ -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
+ }