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.
- package/bin/cli.js +55 -2
- package/dist/server/.tsbuildinfo +1 -1
- package/package.json +6 -1
- package/src/config/workflows.js +28 -44
- package/src/lib/config-manager.js +470 -0
- package/src/lib/content-generator.js +427 -0
- package/src/lib/html-conversion-utils.js +843 -0
- package/src/lib/seo-optimizer.js +515 -0
- package/src/lib/wordpress-client.js +633 -0
- package/src/lib/workflow-installer.js +3 -3
- package/src/scripts/html-conversion-cli.js +526 -0
- package/src/scripts/init/configure.js +436 -0
- package/src/scripts/init/install.js +460 -0
- package/src/scripts/utils/file-utils.js +404 -0
- package/src/scripts/utils/logger.js +300 -0
- package/src/scripts/utils/write-content.js +293 -0
- package/src/templates/claude/agents/visual-content-generator.md +129 -4
- package/src/templates/claude/commands/myai-convert-html.md +186 -0
- package/src/templates/diagrams/architecture.d2 +52 -0
- package/src/templates/diagrams/flowchart.d2 +42 -0
- package/src/templates/diagrams/sequence.d2 +47 -0
- package/src/templates/docs/content-creation-guide.md +164 -0
- package/src/templates/docs/deployment-guide.md +336 -0
- package/src/templates/docs/visual-generation-guide.md +248 -0
- package/src/templates/docs/wordpress-publishing-guide.md +208 -0
- package/src/templates/infographics/comparison-table.html +347 -0
- package/src/templates/infographics/data-chart.html +268 -0
- package/src/templates/infographics/process-flow.html +365 -0
- /package/src/scripts/{wordpress-health-check.js → wordpress/wordpress-health-check.js} +0 -0
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WordPress Client
|
|
3
|
+
* High-level WordPress API client for content publishing
|
|
4
|
+
* Wraps wordpress-admin-utils.js functionality
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { getConfigManager } from './config-manager.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* WordPress Client Class
|
|
11
|
+
*/
|
|
12
|
+
export class WordPressClient {
|
|
13
|
+
constructor(options = {}) {
|
|
14
|
+
this.siteUrl = options.siteUrl || null;
|
|
15
|
+
this.username = options.username || null;
|
|
16
|
+
this.appPassword = options.appPassword || null;
|
|
17
|
+
this.configManager = options.configManager || getConfigManager();
|
|
18
|
+
this.initialized = false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Initialize the client with configuration
|
|
23
|
+
* @returns {Promise<boolean>} True if initialization successful
|
|
24
|
+
*/
|
|
25
|
+
async initialize() {
|
|
26
|
+
if (this.initialized) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const config = await this.configManager.loadAll();
|
|
31
|
+
|
|
32
|
+
this.siteUrl = this.siteUrl || config.WORDPRESS_URL;
|
|
33
|
+
this.username = this.username || config.WORDPRESS_USERNAME;
|
|
34
|
+
this.appPassword = this.appPassword || config.WORDPRESS_APP_PASSWORD;
|
|
35
|
+
this.defaultStatus = config.WORDPRESS_DEFAULT_STATUS || 'draft';
|
|
36
|
+
|
|
37
|
+
// Validate required fields
|
|
38
|
+
if (!this.siteUrl || !this.username || !this.appPassword) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Normalize site URL
|
|
43
|
+
this.siteUrl = this.siteUrl.replace(/\/+$/, '');
|
|
44
|
+
if (!this.siteUrl.startsWith('http')) {
|
|
45
|
+
this.siteUrl = 'https://' + this.siteUrl;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.initialized = true;
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Get authentication header
|
|
54
|
+
* @returns {Object} Headers object with authorization
|
|
55
|
+
*/
|
|
56
|
+
getAuthHeaders() {
|
|
57
|
+
const auth = Buffer.from(`${this.username}:${this.appPassword}`).toString('base64');
|
|
58
|
+
return {
|
|
59
|
+
'Authorization': `Basic ${auth}`,
|
|
60
|
+
'Content-Type': 'application/json'
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Validate connection to WordPress
|
|
66
|
+
* @returns {Promise<{valid: boolean, message: string, user?: Object}>}
|
|
67
|
+
*/
|
|
68
|
+
async validateConnection() {
|
|
69
|
+
const initialized = await this.initialize();
|
|
70
|
+
if (!initialized) {
|
|
71
|
+
return {
|
|
72
|
+
valid: false,
|
|
73
|
+
message: 'WordPress credentials not configured. Run /myai-configure wordpress'
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
const response = await fetch(`${this.siteUrl}/wp-json/wp/v2/users/me`, {
|
|
79
|
+
method: 'GET',
|
|
80
|
+
headers: this.getAuthHeaders()
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
const text = await response.text();
|
|
85
|
+
return {
|
|
86
|
+
valid: false,
|
|
87
|
+
message: `Authentication failed: ${response.status} ${text}`
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const user = await response.json();
|
|
92
|
+
return {
|
|
93
|
+
valid: true,
|
|
94
|
+
message: `Connected as ${user.name} (${user.slug})`,
|
|
95
|
+
user
|
|
96
|
+
};
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return {
|
|
99
|
+
valid: false,
|
|
100
|
+
message: `Connection error: ${error.message}`
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Publish a post to WordPress
|
|
107
|
+
* @param {Object} postData - Post data
|
|
108
|
+
* @param {string} postData.title - Post title
|
|
109
|
+
* @param {string} postData.content - Post content (HTML or markdown)
|
|
110
|
+
* @param {string} [postData.status='draft'] - Post status (draft, publish, pending)
|
|
111
|
+
* @param {string} [postData.excerpt] - Post excerpt
|
|
112
|
+
* @param {number[]} [postData.categories] - Category IDs
|
|
113
|
+
* @param {number[]} [postData.tags] - Tag IDs
|
|
114
|
+
* @param {string} [postData.slug] - URL slug
|
|
115
|
+
* @param {number} [postData.featured_media] - Featured image ID
|
|
116
|
+
* @returns {Promise<{success: boolean, post?: Object, error?: string}>}
|
|
117
|
+
*/
|
|
118
|
+
async publishPost(postData) {
|
|
119
|
+
const initialized = await this.initialize();
|
|
120
|
+
if (!initialized) {
|
|
121
|
+
return {
|
|
122
|
+
success: false,
|
|
123
|
+
error: 'WordPress credentials not configured'
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
const payload = {
|
|
129
|
+
title: postData.title,
|
|
130
|
+
content: this.convertMarkdownToHtml(postData.content),
|
|
131
|
+
status: postData.status || this.defaultStatus,
|
|
132
|
+
excerpt: postData.excerpt || '',
|
|
133
|
+
categories: postData.categories || [],
|
|
134
|
+
tags: postData.tags || [],
|
|
135
|
+
slug: postData.slug || this.generateSlug(postData.title),
|
|
136
|
+
featured_media: postData.featured_media || 0
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const response = await fetch(`${this.siteUrl}/wp-json/wp/v2/posts`, {
|
|
140
|
+
method: 'POST',
|
|
141
|
+
headers: this.getAuthHeaders(),
|
|
142
|
+
body: JSON.stringify(payload)
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (!response.ok) {
|
|
146
|
+
const error = await response.json();
|
|
147
|
+
return {
|
|
148
|
+
success: false,
|
|
149
|
+
error: error.message || `HTTP ${response.status}`
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const post = await response.json();
|
|
154
|
+
return {
|
|
155
|
+
success: true,
|
|
156
|
+
post: {
|
|
157
|
+
id: post.id,
|
|
158
|
+
title: post.title.rendered,
|
|
159
|
+
status: post.status,
|
|
160
|
+
link: post.link,
|
|
161
|
+
editLink: `${this.siteUrl}/wp-admin/post.php?post=${post.id}&action=edit`
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
} catch (error) {
|
|
165
|
+
return {
|
|
166
|
+
success: false,
|
|
167
|
+
error: error.message
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Create a draft post
|
|
174
|
+
* @param {Object} postData - Post data (same as publishPost)
|
|
175
|
+
* @returns {Promise<{success: boolean, post?: Object, error?: string}>}
|
|
176
|
+
*/
|
|
177
|
+
async createDraft(postData) {
|
|
178
|
+
return this.publishPost({ ...postData, status: 'draft' });
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Update an existing post
|
|
183
|
+
* @param {number} postId - Post ID to update
|
|
184
|
+
* @param {Object} data - Data to update
|
|
185
|
+
* @returns {Promise<{success: boolean, post?: Object, error?: string}>}
|
|
186
|
+
*/
|
|
187
|
+
async updatePost(postId, data) {
|
|
188
|
+
const initialized = await this.initialize();
|
|
189
|
+
if (!initialized) {
|
|
190
|
+
return {
|
|
191
|
+
success: false,
|
|
192
|
+
error: 'WordPress credentials not configured'
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
const payload = {};
|
|
198
|
+
|
|
199
|
+
if (data.title) payload.title = data.title;
|
|
200
|
+
if (data.content) payload.content = this.convertMarkdownToHtml(data.content);
|
|
201
|
+
if (data.status) payload.status = data.status;
|
|
202
|
+
if (data.excerpt) payload.excerpt = data.excerpt;
|
|
203
|
+
if (data.categories) payload.categories = data.categories;
|
|
204
|
+
if (data.tags) payload.tags = data.tags;
|
|
205
|
+
if (data.slug) payload.slug = data.slug;
|
|
206
|
+
if (data.featured_media !== undefined) payload.featured_media = data.featured_media;
|
|
207
|
+
|
|
208
|
+
const response = await fetch(`${this.siteUrl}/wp-json/wp/v2/posts/${postId}`, {
|
|
209
|
+
method: 'POST',
|
|
210
|
+
headers: this.getAuthHeaders(),
|
|
211
|
+
body: JSON.stringify(payload)
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (!response.ok) {
|
|
215
|
+
const error = await response.json();
|
|
216
|
+
return {
|
|
217
|
+
success: false,
|
|
218
|
+
error: error.message || `HTTP ${response.status}`
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const post = await response.json();
|
|
223
|
+
return {
|
|
224
|
+
success: true,
|
|
225
|
+
post: {
|
|
226
|
+
id: post.id,
|
|
227
|
+
title: post.title.rendered,
|
|
228
|
+
status: post.status,
|
|
229
|
+
link: post.link,
|
|
230
|
+
editLink: `${this.siteUrl}/wp-admin/post.php?post=${post.id}&action=edit`
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
} catch (error) {
|
|
234
|
+
return {
|
|
235
|
+
success: false,
|
|
236
|
+
error: error.message
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Search for posts
|
|
243
|
+
* @param {string} keyword - Search keyword
|
|
244
|
+
* @param {Object} [options] - Search options
|
|
245
|
+
* @param {string} [options.status] - Filter by status
|
|
246
|
+
* @param {number} [options.perPage=10] - Results per page
|
|
247
|
+
* @returns {Promise<{success: boolean, posts?: Object[], error?: string}>}
|
|
248
|
+
*/
|
|
249
|
+
async searchPosts(keyword, options = {}) {
|
|
250
|
+
const initialized = await this.initialize();
|
|
251
|
+
if (!initialized) {
|
|
252
|
+
return {
|
|
253
|
+
success: false,
|
|
254
|
+
error: 'WordPress credentials not configured'
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
const params = new URLSearchParams({
|
|
260
|
+
search: keyword,
|
|
261
|
+
per_page: String(options.perPage || 10)
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
if (options.status) {
|
|
265
|
+
params.append('status', options.status);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const response = await fetch(
|
|
269
|
+
`${this.siteUrl}/wp-json/wp/v2/posts?${params.toString()}`,
|
|
270
|
+
{
|
|
271
|
+
method: 'GET',
|
|
272
|
+
headers: this.getAuthHeaders()
|
|
273
|
+
}
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
if (!response.ok) {
|
|
277
|
+
const error = await response.json();
|
|
278
|
+
return {
|
|
279
|
+
success: false,
|
|
280
|
+
error: error.message || `HTTP ${response.status}`
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const posts = await response.json();
|
|
285
|
+
return {
|
|
286
|
+
success: true,
|
|
287
|
+
posts: posts.map(p => ({
|
|
288
|
+
id: p.id,
|
|
289
|
+
title: p.title.rendered,
|
|
290
|
+
status: p.status,
|
|
291
|
+
link: p.link,
|
|
292
|
+
date: p.date,
|
|
293
|
+
modified: p.modified
|
|
294
|
+
}))
|
|
295
|
+
};
|
|
296
|
+
} catch (error) {
|
|
297
|
+
return {
|
|
298
|
+
success: false,
|
|
299
|
+
error: error.message
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Get a single post by ID
|
|
306
|
+
* @param {number} postId - Post ID
|
|
307
|
+
* @returns {Promise<{success: boolean, post?: Object, error?: string}>}
|
|
308
|
+
*/
|
|
309
|
+
async getPost(postId) {
|
|
310
|
+
const initialized = await this.initialize();
|
|
311
|
+
if (!initialized) {
|
|
312
|
+
return {
|
|
313
|
+
success: false,
|
|
314
|
+
error: 'WordPress credentials not configured'
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
const response = await fetch(
|
|
320
|
+
`${this.siteUrl}/wp-json/wp/v2/posts/${postId}`,
|
|
321
|
+
{
|
|
322
|
+
method: 'GET',
|
|
323
|
+
headers: this.getAuthHeaders()
|
|
324
|
+
}
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
if (!response.ok) {
|
|
328
|
+
const error = await response.json();
|
|
329
|
+
return {
|
|
330
|
+
success: false,
|
|
331
|
+
error: error.message || `HTTP ${response.status}`
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
const post = await response.json();
|
|
336
|
+
return {
|
|
337
|
+
success: true,
|
|
338
|
+
post: {
|
|
339
|
+
id: post.id,
|
|
340
|
+
title: post.title.rendered,
|
|
341
|
+
content: post.content.rendered,
|
|
342
|
+
status: post.status,
|
|
343
|
+
link: post.link,
|
|
344
|
+
date: post.date,
|
|
345
|
+
modified: post.modified,
|
|
346
|
+
categories: post.categories,
|
|
347
|
+
tags: post.tags
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
} catch (error) {
|
|
351
|
+
return {
|
|
352
|
+
success: false,
|
|
353
|
+
error: error.message
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Delete a post
|
|
360
|
+
* @param {number} postId - Post ID
|
|
361
|
+
* @param {boolean} [force=false] - Permanently delete (skip trash)
|
|
362
|
+
* @returns {Promise<{success: boolean, error?: string}>}
|
|
363
|
+
*/
|
|
364
|
+
async deletePost(postId, force = false) {
|
|
365
|
+
const initialized = await this.initialize();
|
|
366
|
+
if (!initialized) {
|
|
367
|
+
return {
|
|
368
|
+
success: false,
|
|
369
|
+
error: 'WordPress credentials not configured'
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
try {
|
|
374
|
+
const params = force ? '?force=true' : '';
|
|
375
|
+
const response = await fetch(
|
|
376
|
+
`${this.siteUrl}/wp-json/wp/v2/posts/${postId}${params}`,
|
|
377
|
+
{
|
|
378
|
+
method: 'DELETE',
|
|
379
|
+
headers: this.getAuthHeaders()
|
|
380
|
+
}
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
if (!response.ok) {
|
|
384
|
+
const error = await response.json();
|
|
385
|
+
return {
|
|
386
|
+
success: false,
|
|
387
|
+
error: error.message || `HTTP ${response.status}`
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return { success: true };
|
|
392
|
+
} catch (error) {
|
|
393
|
+
return {
|
|
394
|
+
success: false,
|
|
395
|
+
error: error.message
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Get categories
|
|
402
|
+
* @returns {Promise<{success: boolean, categories?: Object[], error?: string}>}
|
|
403
|
+
*/
|
|
404
|
+
async getCategories() {
|
|
405
|
+
const initialized = await this.initialize();
|
|
406
|
+
if (!initialized) {
|
|
407
|
+
return {
|
|
408
|
+
success: false,
|
|
409
|
+
error: 'WordPress credentials not configured'
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
try {
|
|
414
|
+
const response = await fetch(
|
|
415
|
+
`${this.siteUrl}/wp-json/wp/v2/categories?per_page=100`,
|
|
416
|
+
{
|
|
417
|
+
method: 'GET',
|
|
418
|
+
headers: this.getAuthHeaders()
|
|
419
|
+
}
|
|
420
|
+
);
|
|
421
|
+
|
|
422
|
+
if (!response.ok) {
|
|
423
|
+
return {
|
|
424
|
+
success: false,
|
|
425
|
+
error: `HTTP ${response.status}`
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
const categories = await response.json();
|
|
430
|
+
return {
|
|
431
|
+
success: true,
|
|
432
|
+
categories: categories.map(c => ({
|
|
433
|
+
id: c.id,
|
|
434
|
+
name: c.name,
|
|
435
|
+
slug: c.slug,
|
|
436
|
+
count: c.count
|
|
437
|
+
}))
|
|
438
|
+
};
|
|
439
|
+
} catch (error) {
|
|
440
|
+
return {
|
|
441
|
+
success: false,
|
|
442
|
+
error: error.message
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Get tags
|
|
449
|
+
* @returns {Promise<{success: boolean, tags?: Object[], error?: string}>}
|
|
450
|
+
*/
|
|
451
|
+
async getTags() {
|
|
452
|
+
const initialized = await this.initialize();
|
|
453
|
+
if (!initialized) {
|
|
454
|
+
return {
|
|
455
|
+
success: false,
|
|
456
|
+
error: 'WordPress credentials not configured'
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
try {
|
|
461
|
+
const response = await fetch(
|
|
462
|
+
`${this.siteUrl}/wp-json/wp/v2/tags?per_page=100`,
|
|
463
|
+
{
|
|
464
|
+
method: 'GET',
|
|
465
|
+
headers: this.getAuthHeaders()
|
|
466
|
+
}
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
if (!response.ok) {
|
|
470
|
+
return {
|
|
471
|
+
success: false,
|
|
472
|
+
error: `HTTP ${response.status}`
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const tags = await response.json();
|
|
477
|
+
return {
|
|
478
|
+
success: true,
|
|
479
|
+
tags: tags.map(t => ({
|
|
480
|
+
id: t.id,
|
|
481
|
+
name: t.name,
|
|
482
|
+
slug: t.slug,
|
|
483
|
+
count: t.count
|
|
484
|
+
}))
|
|
485
|
+
};
|
|
486
|
+
} catch (error) {
|
|
487
|
+
return {
|
|
488
|
+
success: false,
|
|
489
|
+
error: error.message
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* Create a category
|
|
496
|
+
* @param {string} name - Category name
|
|
497
|
+
* @param {string} [description] - Category description
|
|
498
|
+
* @returns {Promise<{success: boolean, category?: Object, error?: string}>}
|
|
499
|
+
*/
|
|
500
|
+
async createCategory(name, description = '') {
|
|
501
|
+
const initialized = await this.initialize();
|
|
502
|
+
if (!initialized) {
|
|
503
|
+
return {
|
|
504
|
+
success: false,
|
|
505
|
+
error: 'WordPress credentials not configured'
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
try {
|
|
510
|
+
const response = await fetch(
|
|
511
|
+
`${this.siteUrl}/wp-json/wp/v2/categories`,
|
|
512
|
+
{
|
|
513
|
+
method: 'POST',
|
|
514
|
+
headers: this.getAuthHeaders(),
|
|
515
|
+
body: JSON.stringify({
|
|
516
|
+
name,
|
|
517
|
+
description,
|
|
518
|
+
slug: this.generateSlug(name)
|
|
519
|
+
})
|
|
520
|
+
}
|
|
521
|
+
);
|
|
522
|
+
|
|
523
|
+
if (!response.ok) {
|
|
524
|
+
const error = await response.json();
|
|
525
|
+
return {
|
|
526
|
+
success: false,
|
|
527
|
+
error: error.message || `HTTP ${response.status}`
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
const category = await response.json();
|
|
532
|
+
return {
|
|
533
|
+
success: true,
|
|
534
|
+
category: {
|
|
535
|
+
id: category.id,
|
|
536
|
+
name: category.name,
|
|
537
|
+
slug: category.slug
|
|
538
|
+
}
|
|
539
|
+
};
|
|
540
|
+
} catch (error) {
|
|
541
|
+
return {
|
|
542
|
+
success: false,
|
|
543
|
+
error: error.message
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Convert markdown to HTML (basic conversion)
|
|
550
|
+
* @param {string} markdown - Markdown content
|
|
551
|
+
* @returns {string} HTML content
|
|
552
|
+
*/
|
|
553
|
+
convertMarkdownToHtml(markdown) {
|
|
554
|
+
if (!markdown) return '';
|
|
555
|
+
|
|
556
|
+
let html = markdown;
|
|
557
|
+
|
|
558
|
+
// Headers
|
|
559
|
+
html = html.replace(/^######\s+(.+)$/gm, '<h6>$1</h6>');
|
|
560
|
+
html = html.replace(/^#####\s+(.+)$/gm, '<h5>$1</h5>');
|
|
561
|
+
html = html.replace(/^####\s+(.+)$/gm, '<h4>$1</h4>');
|
|
562
|
+
html = html.replace(/^###\s+(.+)$/gm, '<h3>$1</h3>');
|
|
563
|
+
html = html.replace(/^##\s+(.+)$/gm, '<h2>$1</h2>');
|
|
564
|
+
html = html.replace(/^#\s+(.+)$/gm, '<h1>$1</h1>');
|
|
565
|
+
|
|
566
|
+
// Bold and italic
|
|
567
|
+
html = html.replace(/\*\*\*(.+?)\*\*\*/g, '<strong><em>$1</em></strong>');
|
|
568
|
+
html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
|
|
569
|
+
html = html.replace(/\*(.+?)\*/g, '<em>$1</em>');
|
|
570
|
+
|
|
571
|
+
// Links
|
|
572
|
+
html = html.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2">$1</a>');
|
|
573
|
+
|
|
574
|
+
// Images
|
|
575
|
+
html = html.replace(/!\[(.+?)\]\((.+?)\)/g, '<img src="$2" alt="$1">');
|
|
576
|
+
|
|
577
|
+
// Code blocks
|
|
578
|
+
html = html.replace(/```(\w+)?\n([\s\S]+?)```/g, '<pre><code>$2</code></pre>');
|
|
579
|
+
html = html.replace(/`(.+?)`/g, '<code>$1</code>');
|
|
580
|
+
|
|
581
|
+
// Lists
|
|
582
|
+
html = html.replace(/^\*\s+(.+)$/gm, '<li>$1</li>');
|
|
583
|
+
html = html.replace(/^-\s+(.+)$/gm, '<li>$1</li>');
|
|
584
|
+
html = html.replace(/(<li>.*<\/li>\n?)+/g, '<ul>$&</ul>');
|
|
585
|
+
|
|
586
|
+
html = html.replace(/^\d+\.\s+(.+)$/gm, '<li>$1</li>');
|
|
587
|
+
html = html.replace(/(<li>.*<\/li>\n?)+/g, (match) => {
|
|
588
|
+
if (match.includes('<ul>')) return match;
|
|
589
|
+
return '<ol>' + match + '</ol>';
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
// Paragraphs
|
|
593
|
+
html = html.replace(/\n\n+/g, '</p><p>');
|
|
594
|
+
html = '<p>' + html + '</p>';
|
|
595
|
+
html = html.replace(/<p>(<h\d>)/g, '$1');
|
|
596
|
+
html = html.replace(/(<\/h\d>)<\/p>/g, '$1');
|
|
597
|
+
html = html.replace(/<p>(<ul>)/g, '$1');
|
|
598
|
+
html = html.replace(/(<\/ul>)<\/p>/g, '$1');
|
|
599
|
+
html = html.replace(/<p>(<ol>)/g, '$1');
|
|
600
|
+
html = html.replace(/(<\/ol>)<\/p>/g, '$1');
|
|
601
|
+
html = html.replace(/<p>(<pre>)/g, '$1');
|
|
602
|
+
html = html.replace(/(<\/pre>)<\/p>/g, '$1');
|
|
603
|
+
html = html.replace(/<p>\s*<\/p>/g, '');
|
|
604
|
+
|
|
605
|
+
// Line breaks
|
|
606
|
+
html = html.replace(/\n/g, '<br>');
|
|
607
|
+
html = html.replace(/<br><br>/g, '</p><p>');
|
|
608
|
+
|
|
609
|
+
return html;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Generate URL slug from title
|
|
614
|
+
* @param {string} title - Title to slugify
|
|
615
|
+
* @returns {string} URL slug
|
|
616
|
+
*/
|
|
617
|
+
generateSlug(title) {
|
|
618
|
+
return title
|
|
619
|
+
.toLowerCase()
|
|
620
|
+
.trim()
|
|
621
|
+
.replace(/[^\w\s-]/g, '')
|
|
622
|
+
.replace(/[\s_]+/g, '-')
|
|
623
|
+
.replace(/-+/g, '-')
|
|
624
|
+
.replace(/^-+|-+$/g, '');
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Factory function
|
|
629
|
+
export function createWordPressClient(options) {
|
|
630
|
+
return new WordPressClient(options);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
export default WordPressClient;
|
|
@@ -107,7 +107,7 @@ class WorkflowInstaller {
|
|
|
107
107
|
|
|
108
108
|
let installed = 0;
|
|
109
109
|
for (const agent of agents) {
|
|
110
|
-
const sourcePath = path.join(__dirname, '..', 'agents', `${agent}.md`);
|
|
110
|
+
const sourcePath = path.join(__dirname, '..', 'templates', 'claude', 'agents', `${agent}.md`);
|
|
111
111
|
const targetPath = path.join(agentsDir, `${agent}.md`);
|
|
112
112
|
|
|
113
113
|
try {
|
|
@@ -141,7 +141,7 @@ class WorkflowInstaller {
|
|
|
141
141
|
|
|
142
142
|
let installed = 0;
|
|
143
143
|
for (const command of commands) {
|
|
144
|
-
const sourcePath = path.join(__dirname, '..', 'commands', `${command}.md`);
|
|
144
|
+
const sourcePath = path.join(__dirname, '..', 'templates', 'claude', 'commands', `${command}.md`);
|
|
145
145
|
const targetPath = path.join(commandsDir, `${command}.md`);
|
|
146
146
|
|
|
147
147
|
try {
|
|
@@ -240,7 +240,7 @@ class WorkflowInstaller {
|
|
|
240
240
|
|
|
241
241
|
let installed = 0;
|
|
242
242
|
for (const doc of docs) {
|
|
243
|
-
const sourcePath = path.join(__dirname, '..', '
|
|
243
|
+
const sourcePath = path.join(__dirname, '..', 'templates', 'docs', doc);
|
|
244
244
|
const targetPath = path.join(docsDir, doc);
|
|
245
245
|
|
|
246
246
|
try {
|