multisite-cms-mcp 1.0.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.
- package/README.md +126 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +201 -0
- package/dist/tools/get-conversion-guide.d.ts +7 -0
- package/dist/tools/get-conversion-guide.d.ts.map +1 -0
- package/dist/tools/get-conversion-guide.js +529 -0
- package/dist/tools/get-example.d.ts +7 -0
- package/dist/tools/get-example.d.ts.map +1 -0
- package/dist/tools/get-example.js +673 -0
- package/dist/tools/get-schema.d.ts +5 -0
- package/dist/tools/get-schema.d.ts.map +1 -0
- package/dist/tools/get-schema.js +148 -0
- package/dist/tools/validate-manifest.d.ts +5 -0
- package/dist/tools/validate-manifest.d.ts.map +1 -0
- package/dist/tools/validate-manifest.js +146 -0
- package/dist/tools/validate-package.d.ts +5 -0
- package/dist/tools/validate-package.d.ts.map +1 -0
- package/dist/tools/validate-package.js +190 -0
- package/dist/tools/validate-template.d.ts +7 -0
- package/dist/tools/validate-template.d.ts.map +1 -0
- package/dist/tools/validate-template.js +234 -0
- package/package.json +49 -0
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getExample = getExample;
|
|
4
|
+
const EXAMPLES = {
|
|
5
|
+
manifest_basic: `# Basic manifest.json
|
|
6
|
+
|
|
7
|
+
A minimal manifest with static pages only:
|
|
8
|
+
|
|
9
|
+
\`\`\`json
|
|
10
|
+
{
|
|
11
|
+
"pages": [
|
|
12
|
+
{
|
|
13
|
+
"path": "/",
|
|
14
|
+
"file": "pages/index.html",
|
|
15
|
+
"title": "Home",
|
|
16
|
+
"editable": true
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"path": "/about",
|
|
20
|
+
"file": "pages/about.html",
|
|
21
|
+
"title": "About Us",
|
|
22
|
+
"editable": true
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"path": "/contact",
|
|
26
|
+
"file": "pages/contact.html",
|
|
27
|
+
"title": "Contact",
|
|
28
|
+
"editable": true
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"defaultHeadHtml": "<link href='https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap' rel='stylesheet'>"
|
|
32
|
+
}
|
|
33
|
+
\`\`\`
|
|
34
|
+
|
|
35
|
+
**Key points:**
|
|
36
|
+
- Each page has a unique \`path\` (the URL)
|
|
37
|
+
- \`file\` points to the HTML file in pages/ folder
|
|
38
|
+
- \`editable: true\` allows inline editing in the CMS
|
|
39
|
+
- \`defaultHeadHtml\` is injected into all pages`,
|
|
40
|
+
manifest_custom_paths: `# manifest.json with Custom CMS Paths
|
|
41
|
+
|
|
42
|
+
When your site uses different URLs than the defaults:
|
|
43
|
+
|
|
44
|
+
\`\`\`json
|
|
45
|
+
{
|
|
46
|
+
"pages": [
|
|
47
|
+
{
|
|
48
|
+
"path": "/",
|
|
49
|
+
"file": "pages/index.html",
|
|
50
|
+
"title": "Home",
|
|
51
|
+
"editable": true
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"path": "/about",
|
|
55
|
+
"file": "pages/about.html",
|
|
56
|
+
"title": "About",
|
|
57
|
+
"editable": true
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"cmsTemplates": {
|
|
61
|
+
"blogIndex": "templates/insights_index.html",
|
|
62
|
+
"blogIndexPath": "/insights",
|
|
63
|
+
"blogPost": "templates/insights_detail.html",
|
|
64
|
+
"blogPostPath": "/insights",
|
|
65
|
+
"team": "templates/leadership.html",
|
|
66
|
+
"teamPath": "/about/leadership",
|
|
67
|
+
"downloads": "templates/resources.html",
|
|
68
|
+
"downloadsPath": "/resources",
|
|
69
|
+
"authorsIndex": "templates/contributors.html",
|
|
70
|
+
"authorDetail": "templates/contributor.html",
|
|
71
|
+
"authorsPath": "/contributors"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
\`\`\`
|
|
75
|
+
|
|
76
|
+
**Path Configuration:**
|
|
77
|
+
- \`blogIndexPath: "/insights"\` → Blog listing at /insights
|
|
78
|
+
- \`blogPostPath: "/insights"\` → Posts at /insights/post-slug
|
|
79
|
+
- \`teamPath: "/about/leadership"\` → Team page at /about/leadership
|
|
80
|
+
- Both blogIndexPath and blogPostPath should usually match`,
|
|
81
|
+
blog_index_template: `# Blog Index Template
|
|
82
|
+
|
|
83
|
+
Lists all blog posts with filtering options:
|
|
84
|
+
|
|
85
|
+
\`\`\`html
|
|
86
|
+
<main class="blog-page">
|
|
87
|
+
<header class="page-header">
|
|
88
|
+
<h1 data-edit-key="blog-page-title">Our Blog</h1>
|
|
89
|
+
<p data-edit-key="blog-page-intro">Latest articles and insights</p>
|
|
90
|
+
</header>
|
|
91
|
+
|
|
92
|
+
<!-- Featured Post (first featured article) -->
|
|
93
|
+
{{#each blogs featured=true limit=1}}
|
|
94
|
+
<article class="featured-post">
|
|
95
|
+
{{#if mainImage}}
|
|
96
|
+
<img src="{{mainImage}}" alt="{{name}}" class="featured-image">
|
|
97
|
+
{{/if}}
|
|
98
|
+
<div class="featured-content">
|
|
99
|
+
<h2><a href="{{url}}">{{name}}</a></h2>
|
|
100
|
+
<p class="excerpt">{{postSummary}}</p>
|
|
101
|
+
<div class="meta">
|
|
102
|
+
{{#if author}}
|
|
103
|
+
<span class="author">By {{author.name}}</span>
|
|
104
|
+
{{/if}}
|
|
105
|
+
<time>{{publishedAt}}</time>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</article>
|
|
109
|
+
{{/each}}
|
|
110
|
+
|
|
111
|
+
<!-- All Posts Grid -->
|
|
112
|
+
<div class="posts-grid">
|
|
113
|
+
{{#each blogs limit=12}}
|
|
114
|
+
<article class="post-card">
|
|
115
|
+
{{#if thumbnailImage}}
|
|
116
|
+
<img src="{{thumbnailImage}}" alt="{{name}}">
|
|
117
|
+
{{else}}
|
|
118
|
+
{{#if mainImage}}
|
|
119
|
+
<img src="{{mainImage}}" alt="{{name}}">
|
|
120
|
+
{{/if}}
|
|
121
|
+
{{/if}}
|
|
122
|
+
<div class="card-content">
|
|
123
|
+
<h3><a href="{{url}}">{{name}}</a></h3>
|
|
124
|
+
<p>{{postSummary}}</p>
|
|
125
|
+
{{#if author}}
|
|
126
|
+
<span class="byline">{{author.name}}</span>
|
|
127
|
+
{{/if}}
|
|
128
|
+
</div>
|
|
129
|
+
</article>
|
|
130
|
+
{{/each}}
|
|
131
|
+
</div>
|
|
132
|
+
</main>
|
|
133
|
+
\`\`\`
|
|
134
|
+
|
|
135
|
+
**Key patterns:**
|
|
136
|
+
- \`{{#each blogs featured=true limit=1}}\` for featured post
|
|
137
|
+
- \`{{#each blogs limit=12}}\` for post grid
|
|
138
|
+
- Always wrap images in \`{{#if mainImage}}\`
|
|
139
|
+
- Use \`{{url}}\` for links to post detail page`,
|
|
140
|
+
blog_post_template: `# Blog Post Detail Template
|
|
141
|
+
|
|
142
|
+
Single blog post with author information:
|
|
143
|
+
|
|
144
|
+
\`\`\`html
|
|
145
|
+
<article class="blog-post">
|
|
146
|
+
{{#if mainImage}}
|
|
147
|
+
<img src="{{mainImage}}" alt="{{name}}" class="hero-image">
|
|
148
|
+
{{/if}}
|
|
149
|
+
|
|
150
|
+
<header class="post-header">
|
|
151
|
+
<h1>{{name}}</h1>
|
|
152
|
+
|
|
153
|
+
<div class="post-meta">
|
|
154
|
+
{{#if author}}
|
|
155
|
+
<div class="author-info">
|
|
156
|
+
{{#if author.picture}}
|
|
157
|
+
<img src="{{author.picture}}" alt="{{author.name}}" class="author-avatar">
|
|
158
|
+
{{/if}}
|
|
159
|
+
<a href="{{author.url}}" class="author-name">{{author.name}}</a>
|
|
160
|
+
</div>
|
|
161
|
+
{{/if}}
|
|
162
|
+
<time datetime="{{publishedAt}}">{{publishedAt}}</time>
|
|
163
|
+
</div>
|
|
164
|
+
</header>
|
|
165
|
+
|
|
166
|
+
{{#if postSummary}}
|
|
167
|
+
<p class="lead">{{postSummary}}</p>
|
|
168
|
+
{{/if}}
|
|
169
|
+
|
|
170
|
+
<div class="post-content">
|
|
171
|
+
{{{postBody}}}
|
|
172
|
+
</div>
|
|
173
|
+
|
|
174
|
+
{{#if author}}
|
|
175
|
+
<aside class="author-box">
|
|
176
|
+
{{#if author.picture}}
|
|
177
|
+
<img src="{{author.picture}}" alt="{{author.name}}">
|
|
178
|
+
{{/if}}
|
|
179
|
+
<div class="author-details">
|
|
180
|
+
<h3>About <a href="{{author.url}}">{{author.name}}</a></h3>
|
|
181
|
+
{{{author.bio}}}
|
|
182
|
+
<div class="social-links">
|
|
183
|
+
{{#if author.twitterProfileLink}}
|
|
184
|
+
<a href="{{author.twitterProfileLink}}">Twitter</a>
|
|
185
|
+
{{/if}}
|
|
186
|
+
{{#if author.linkedinProfileLink}}
|
|
187
|
+
<a href="{{author.linkedinProfileLink}}">LinkedIn</a>
|
|
188
|
+
{{/if}}
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
</aside>
|
|
192
|
+
{{/if}}
|
|
193
|
+
</article>
|
|
194
|
+
\`\`\`
|
|
195
|
+
|
|
196
|
+
**IMPORTANT:**
|
|
197
|
+
- \`{{{postBody}}}\` uses TRIPLE braces (contains HTML)
|
|
198
|
+
- \`{{{author.bio}}}\` uses TRIPLE braces (contains HTML)
|
|
199
|
+
- Everything else uses double braces`,
|
|
200
|
+
team_template: `# Team Members Template
|
|
201
|
+
|
|
202
|
+
\`\`\`html
|
|
203
|
+
<section class="team-section">
|
|
204
|
+
<header class="section-header">
|
|
205
|
+
<h1 data-edit-key="team-page-title">Our Team</h1>
|
|
206
|
+
<p data-edit-key="team-page-intro">Meet the people behind our success</p>
|
|
207
|
+
</header>
|
|
208
|
+
|
|
209
|
+
<div class="team-grid">
|
|
210
|
+
{{#each team sort="order" order="asc"}}
|
|
211
|
+
<div class="team-member">
|
|
212
|
+
{{#if photo}}
|
|
213
|
+
<img src="{{photo}}" alt="{{name}}" class="member-photo">
|
|
214
|
+
{{/if}}
|
|
215
|
+
<h3>{{name}}</h3>
|
|
216
|
+
{{#if role}}
|
|
217
|
+
<p class="role">{{role}}</p>
|
|
218
|
+
{{/if}}
|
|
219
|
+
{{#if bio}}
|
|
220
|
+
<div class="bio">{{{bio}}}</div>
|
|
221
|
+
{{/if}}
|
|
222
|
+
{{#if email}}
|
|
223
|
+
<a href="mailto:{{email}}" class="email">{{email}}</a>
|
|
224
|
+
{{/if}}
|
|
225
|
+
</div>
|
|
226
|
+
{{/each}}
|
|
227
|
+
</div>
|
|
228
|
+
</section>
|
|
229
|
+
\`\`\`
|
|
230
|
+
|
|
231
|
+
**Key points:**
|
|
232
|
+
- \`sort="order" order="asc"\` maintains manual ordering
|
|
233
|
+
- \`{{{bio}}}\` uses triple braces for HTML content
|
|
234
|
+
- \`{{photo}}\` not \`{{picture}}\` (that's for authors)`,
|
|
235
|
+
downloads_template: `# Downloads Template
|
|
236
|
+
|
|
237
|
+
\`\`\`html
|
|
238
|
+
<section class="downloads-section">
|
|
239
|
+
<header class="section-header">
|
|
240
|
+
<h1 data-edit-key="downloads-title">Resources</h1>
|
|
241
|
+
<p data-edit-key="downloads-intro">Download our guides and materials</p>
|
|
242
|
+
</header>
|
|
243
|
+
|
|
244
|
+
<div class="downloads-list">
|
|
245
|
+
{{#each downloads sort="order" order="asc"}}
|
|
246
|
+
<div class="download-item">
|
|
247
|
+
<div class="download-info">
|
|
248
|
+
<h3>{{title}}</h3>
|
|
249
|
+
{{#if description}}
|
|
250
|
+
<p>{{description}}</p>
|
|
251
|
+
{{/if}}
|
|
252
|
+
{{#if category}}
|
|
253
|
+
<span class="category">{{category}}</span>
|
|
254
|
+
{{/if}}
|
|
255
|
+
</div>
|
|
256
|
+
<a href="{{fileUrl}}" class="download-btn" download>
|
|
257
|
+
Download
|
|
258
|
+
</a>
|
|
259
|
+
</div>
|
|
260
|
+
{{/each}}
|
|
261
|
+
</div>
|
|
262
|
+
</section>
|
|
263
|
+
\`\`\`
|
|
264
|
+
|
|
265
|
+
**Note:** Downloads uses \`{{title}}\` not \`{{name}}\``,
|
|
266
|
+
authors_template: `# Authors Index Template
|
|
267
|
+
|
|
268
|
+
\`\`\`html
|
|
269
|
+
<section class="authors-section">
|
|
270
|
+
<header class="section-header">
|
|
271
|
+
<h1 data-edit-key="authors-title">Our Authors</h1>
|
|
272
|
+
</header>
|
|
273
|
+
|
|
274
|
+
<div class="authors-grid">
|
|
275
|
+
{{#each authors}}
|
|
276
|
+
<a href="{{url}}" class="author-card">
|
|
277
|
+
{{#if picture}}
|
|
278
|
+
<img src="{{picture}}" alt="{{name}}" class="author-photo">
|
|
279
|
+
{{/if}}
|
|
280
|
+
<h3>{{name}}</h3>
|
|
281
|
+
{{#if bio}}
|
|
282
|
+
<p class="bio-preview">{{{bio}}}</p>
|
|
283
|
+
{{/if}}
|
|
284
|
+
</a>
|
|
285
|
+
{{/each}}
|
|
286
|
+
</div>
|
|
287
|
+
</section>
|
|
288
|
+
\`\`\``,
|
|
289
|
+
author_detail_template: `# Author Detail Template
|
|
290
|
+
|
|
291
|
+
\`\`\`html
|
|
292
|
+
<article class="author-detail">
|
|
293
|
+
<header class="author-header">
|
|
294
|
+
{{#if picture}}
|
|
295
|
+
<img src="{{picture}}" alt="{{name}}" class="author-photo-large">
|
|
296
|
+
{{/if}}
|
|
297
|
+
<h1>{{name}}</h1>
|
|
298
|
+
|
|
299
|
+
<div class="social-links">
|
|
300
|
+
{{#if email}}
|
|
301
|
+
<a href="mailto:{{email}}">Email</a>
|
|
302
|
+
{{/if}}
|
|
303
|
+
{{#if twitterProfileLink}}
|
|
304
|
+
<a href="{{twitterProfileLink}}">Twitter</a>
|
|
305
|
+
{{/if}}
|
|
306
|
+
{{#if linkedinProfileLink}}
|
|
307
|
+
<a href="{{linkedinProfileLink}}">LinkedIn</a>
|
|
308
|
+
{{/if}}
|
|
309
|
+
</div>
|
|
310
|
+
</header>
|
|
311
|
+
|
|
312
|
+
{{#if bio}}
|
|
313
|
+
<div class="author-bio">{{{bio}}}</div>
|
|
314
|
+
{{/if}}
|
|
315
|
+
|
|
316
|
+
<section class="author-articles">
|
|
317
|
+
<h2>Articles by {{name}}</h2>
|
|
318
|
+
<div class="articles-grid">
|
|
319
|
+
{{#each blogs where="author.slug:{{slug}}" limit=10}}
|
|
320
|
+
<a href="{{url}}" class="article-card">
|
|
321
|
+
{{#if thumbnailImage}}
|
|
322
|
+
<img src="{{thumbnailImage}}" alt="{{name}}">
|
|
323
|
+
{{/if}}
|
|
324
|
+
<h3>{{name}}</h3>
|
|
325
|
+
<p>{{postSummary}}</p>
|
|
326
|
+
</a>
|
|
327
|
+
{{/each}}
|
|
328
|
+
</div>
|
|
329
|
+
</section>
|
|
330
|
+
</article>
|
|
331
|
+
\`\`\`
|
|
332
|
+
|
|
333
|
+
**Special:** \`where="author.slug:{{slug}}"\` filters blogs by this author`,
|
|
334
|
+
custom_collection_template: `# Custom Collection Template
|
|
335
|
+
|
|
336
|
+
For user-defined collections:
|
|
337
|
+
|
|
338
|
+
\`\`\`html
|
|
339
|
+
<!-- Index Template: templates/products_index.html -->
|
|
340
|
+
<section class="products-section">
|
|
341
|
+
<h1 data-edit-key="products-title">Our Products</h1>
|
|
342
|
+
|
|
343
|
+
<div class="products-grid">
|
|
344
|
+
{{#each products sort="order" order="asc"}}
|
|
345
|
+
<article class="product-card">
|
|
346
|
+
{{#if image}}
|
|
347
|
+
<img src="{{image}}" alt="{{name}}">
|
|
348
|
+
{{/if}}
|
|
349
|
+
<h3><a href="{{url}}">{{name}}</a></h3>
|
|
350
|
+
{{#if price}}
|
|
351
|
+
<span class="price">\${{price}}</span>
|
|
352
|
+
{{/if}}
|
|
353
|
+
{{#if description}}
|
|
354
|
+
<p>{{description}}</p>
|
|
355
|
+
{{/if}}
|
|
356
|
+
</article>
|
|
357
|
+
{{/each}}
|
|
358
|
+
</div>
|
|
359
|
+
</section>
|
|
360
|
+
\`\`\`
|
|
361
|
+
|
|
362
|
+
**In manifest.json:**
|
|
363
|
+
\`\`\`json
|
|
364
|
+
{
|
|
365
|
+
"cmsTemplates": {
|
|
366
|
+
"collectionPaths": {
|
|
367
|
+
"products": "/shop"
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
\`\`\`
|
|
372
|
+
|
|
373
|
+
This serves the products collection at /shop instead of /products`,
|
|
374
|
+
form_handling: `# Form Handling
|
|
375
|
+
|
|
376
|
+
Forms are automatically captured by the CMS:
|
|
377
|
+
|
|
378
|
+
\`\`\`html
|
|
379
|
+
<form data-form-name="contact" class="contact-form">
|
|
380
|
+
<div class="form-group">
|
|
381
|
+
<label for="name">Name</label>
|
|
382
|
+
<input type="text" name="name" id="name" required>
|
|
383
|
+
</div>
|
|
384
|
+
|
|
385
|
+
<div class="form-group">
|
|
386
|
+
<label for="email">Email</label>
|
|
387
|
+
<input type="email" name="email" id="email" required>
|
|
388
|
+
</div>
|
|
389
|
+
|
|
390
|
+
<div class="form-group">
|
|
391
|
+
<label for="message">Message</label>
|
|
392
|
+
<textarea name="message" id="message" required></textarea>
|
|
393
|
+
</div>
|
|
394
|
+
|
|
395
|
+
<button type="submit">Send Message</button>
|
|
396
|
+
</form>
|
|
397
|
+
|
|
398
|
+
<script>
|
|
399
|
+
document.querySelectorAll('form[data-form-name]').forEach(form => {
|
|
400
|
+
form.addEventListener('submit', async (e) => {
|
|
401
|
+
e.preventDefault();
|
|
402
|
+
|
|
403
|
+
const formData = new FormData(form);
|
|
404
|
+
const data = Object.fromEntries(formData);
|
|
405
|
+
|
|
406
|
+
const response = await fetch('/api/forms/submit', {
|
|
407
|
+
method: 'POST',
|
|
408
|
+
headers: { 'Content-Type': 'application/json' },
|
|
409
|
+
body: JSON.stringify({
|
|
410
|
+
formName: form.dataset.formName,
|
|
411
|
+
data: data
|
|
412
|
+
})
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
if (response.ok) {
|
|
416
|
+
form.reset();
|
|
417
|
+
alert('Thank you! Your message has been sent.');
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
</script>
|
|
422
|
+
\`\`\`
|
|
423
|
+
|
|
424
|
+
**Key points:**
|
|
425
|
+
- Add \`data-form-name="xxx"\` to identify the form
|
|
426
|
+
- All \`name\` attributes are captured as fields
|
|
427
|
+
- Tenant context is handled automatically by the system`,
|
|
428
|
+
asset_paths: `# Asset Path Rules
|
|
429
|
+
|
|
430
|
+
**ALL asset paths must use /public/ prefix:**
|
|
431
|
+
|
|
432
|
+
\`\`\`html
|
|
433
|
+
<!-- CSS -->
|
|
434
|
+
<link rel="stylesheet" href="/public/css/style.css">
|
|
435
|
+
<link rel="stylesheet" href="/public/css/components/header.css">
|
|
436
|
+
|
|
437
|
+
<!-- JavaScript -->
|
|
438
|
+
<script src="/public/js/main.js"></script>
|
|
439
|
+
<script src="/public/js/vendor/swiper.min.js"></script>
|
|
440
|
+
|
|
441
|
+
<!-- Images -->
|
|
442
|
+
<img src="/public/images/logo.png" alt="Logo">
|
|
443
|
+
<img src="/public/images/team/john.jpg" alt="John">
|
|
444
|
+
|
|
445
|
+
<!-- Favicon -->
|
|
446
|
+
<link rel="icon" href="/public/images/favicon.ico">
|
|
447
|
+
\`\`\`
|
|
448
|
+
|
|
449
|
+
**In CSS files:**
|
|
450
|
+
\`\`\`css
|
|
451
|
+
/* Correct */
|
|
452
|
+
background-image: url('/public/images/hero-bg.jpg');
|
|
453
|
+
|
|
454
|
+
/* Wrong - will break */
|
|
455
|
+
background-image: url('../images/hero-bg.jpg');
|
|
456
|
+
background-image: url('images/hero-bg.jpg');
|
|
457
|
+
\`\`\`
|
|
458
|
+
|
|
459
|
+
**Common conversions:**
|
|
460
|
+
- \`href="css/style.css"\` → \`href="/public/css/style.css"\`
|
|
461
|
+
- \`src="../images/logo.png"\` → \`src="/public/images/logo.png"\`
|
|
462
|
+
- \`url('../fonts/custom.woff')\` → \`url('/public/fonts/custom.woff')\``,
|
|
463
|
+
data_edit_keys: `# Inline Editing with data-edit-key
|
|
464
|
+
|
|
465
|
+
Make text editable in the CMS visual editor:
|
|
466
|
+
|
|
467
|
+
\`\`\`html
|
|
468
|
+
<!-- Unique, descriptive keys -->
|
|
469
|
+
<h1 data-edit-key="home-hero-title">Welcome to Our Company</h1>
|
|
470
|
+
<p data-edit-key="home-hero-subtitle">We provide excellent services</p>
|
|
471
|
+
|
|
472
|
+
<!-- Hierarchical naming for sections -->
|
|
473
|
+
<section class="about">
|
|
474
|
+
<h2 data-edit-key="about-section-title">About Us</h2>
|
|
475
|
+
<p data-edit-key="about-section-paragraph-1">First paragraph...</p>
|
|
476
|
+
<p data-edit-key="about-section-paragraph-2">Second paragraph...</p>
|
|
477
|
+
</section>
|
|
478
|
+
|
|
479
|
+
<!-- For different pages, prefix with page name -->
|
|
480
|
+
<h1 data-edit-key="contact-page-title">Contact Us</h1>
|
|
481
|
+
<p data-edit-key="contact-intro">Get in touch with our team</p>
|
|
482
|
+
\`\`\`
|
|
483
|
+
|
|
484
|
+
**Naming conventions:**
|
|
485
|
+
- \`{page}-{section}-{element}\`
|
|
486
|
+
- Examples: \`home-hero-title\`, \`about-team-heading\`, \`contact-form-intro\`
|
|
487
|
+
- Must be unique across the entire site
|
|
488
|
+
- Use lowercase with hyphens`,
|
|
489
|
+
each_loop: `# {{#each}} Loop Syntax
|
|
490
|
+
|
|
491
|
+
**Basic loop:**
|
|
492
|
+
\`\`\`html
|
|
493
|
+
{{#each blogs}}
|
|
494
|
+
<article>
|
|
495
|
+
<h2>{{name}}</h2>
|
|
496
|
+
<p>{{postSummary}}</p>
|
|
497
|
+
</article>
|
|
498
|
+
{{/each}}
|
|
499
|
+
\`\`\`
|
|
500
|
+
|
|
501
|
+
**With limit:**
|
|
502
|
+
\`\`\`html
|
|
503
|
+
{{#each blogs limit=6}}
|
|
504
|
+
...
|
|
505
|
+
{{/each}}
|
|
506
|
+
\`\`\`
|
|
507
|
+
|
|
508
|
+
**Featured only:**
|
|
509
|
+
\`\`\`html
|
|
510
|
+
{{#each blogs featured=true}}
|
|
511
|
+
...
|
|
512
|
+
{{/each}}
|
|
513
|
+
\`\`\`
|
|
514
|
+
|
|
515
|
+
**Combined:**
|
|
516
|
+
\`\`\`html
|
|
517
|
+
{{#each blogs featured=true limit=3}}
|
|
518
|
+
...
|
|
519
|
+
{{/each}}
|
|
520
|
+
\`\`\`
|
|
521
|
+
|
|
522
|
+
**With sorting:**
|
|
523
|
+
\`\`\`html
|
|
524
|
+
{{#each team sort="order" order="asc"}}
|
|
525
|
+
...
|
|
526
|
+
{{/each}}
|
|
527
|
+
\`\`\`
|
|
528
|
+
|
|
529
|
+
**Loop variables:**
|
|
530
|
+
\`\`\`html
|
|
531
|
+
{{#each blogs limit=5}}
|
|
532
|
+
<article class="{{#if @first}}featured{{/if}} {{#if @last}}last{{/if}}">
|
|
533
|
+
<span class="position">Item {{@index}}</span>
|
|
534
|
+
<h2>{{name}}</h2>
|
|
535
|
+
</article>
|
|
536
|
+
{{/each}}
|
|
537
|
+
\`\`\`
|
|
538
|
+
|
|
539
|
+
- \`{{@first}}\` - true for first item
|
|
540
|
+
- \`{{@last}}\` - true for last item
|
|
541
|
+
- \`{{@index}}\` - zero-based index (0, 1, 2...)`,
|
|
542
|
+
conditional_if: `# Conditional Rendering
|
|
543
|
+
|
|
544
|
+
**{{#if}} - Render if truthy:**
|
|
545
|
+
\`\`\`html
|
|
546
|
+
{{#if mainImage}}
|
|
547
|
+
<img src="{{mainImage}}" alt="{{name}}">
|
|
548
|
+
{{/if}}
|
|
549
|
+
\`\`\`
|
|
550
|
+
|
|
551
|
+
**{{#if}} with {{else}}:**
|
|
552
|
+
\`\`\`html
|
|
553
|
+
{{#if thumbnailImage}}
|
|
554
|
+
<img src="{{thumbnailImage}}" alt="{{name}}">
|
|
555
|
+
{{else}}
|
|
556
|
+
<div class="placeholder">No image</div>
|
|
557
|
+
{{/if}}
|
|
558
|
+
\`\`\`
|
|
559
|
+
|
|
560
|
+
**{{#unless}} - Render if falsy:**
|
|
561
|
+
\`\`\`html
|
|
562
|
+
{{#unless featured}}
|
|
563
|
+
<span class="regular-post">Regular</span>
|
|
564
|
+
{{/unless}}
|
|
565
|
+
\`\`\`
|
|
566
|
+
|
|
567
|
+
**Nested conditionals:**
|
|
568
|
+
\`\`\`html
|
|
569
|
+
{{#if author}}
|
|
570
|
+
<div class="author-info">
|
|
571
|
+
{{#if author.picture}}
|
|
572
|
+
<img src="{{author.picture}}" alt="{{author.name}}">
|
|
573
|
+
{{/if}}
|
|
574
|
+
<span>{{author.name}}</span>
|
|
575
|
+
</div>
|
|
576
|
+
{{/if}}
|
|
577
|
+
\`\`\`
|
|
578
|
+
|
|
579
|
+
**Multiple conditions (check both):**
|
|
580
|
+
\`\`\`html
|
|
581
|
+
{{#if mainImage}}
|
|
582
|
+
{{#if featured}}
|
|
583
|
+
<img src="{{mainImage}}" class="featured-image">
|
|
584
|
+
{{/if}}
|
|
585
|
+
{{/if}}
|
|
586
|
+
\`\`\``,
|
|
587
|
+
nested_fields: `# Nested Field Access
|
|
588
|
+
|
|
589
|
+
**Author fields in blog templates:**
|
|
590
|
+
\`\`\`html
|
|
591
|
+
{{#each blogs}}
|
|
592
|
+
<article>
|
|
593
|
+
<h2>{{name}}</h2>
|
|
594
|
+
|
|
595
|
+
{{#if author}}
|
|
596
|
+
<div class="author">
|
|
597
|
+
{{#if author.picture}}
|
|
598
|
+
<img src="{{author.picture}}" alt="{{author.name}}">
|
|
599
|
+
{{/if}}
|
|
600
|
+
<span>By {{author.name}}</span>
|
|
601
|
+
|
|
602
|
+
{{#if author.bio}}
|
|
603
|
+
<p class="bio">{{{author.bio}}}</p>
|
|
604
|
+
{{/if}}
|
|
605
|
+
</div>
|
|
606
|
+
{{/if}}
|
|
607
|
+
</article>
|
|
608
|
+
{{/each}}
|
|
609
|
+
\`\`\`
|
|
610
|
+
|
|
611
|
+
**Available nested author fields:**
|
|
612
|
+
- \`{{author.name}}\`
|
|
613
|
+
- \`{{author.slug}}\`
|
|
614
|
+
- \`{{author.picture}}\`
|
|
615
|
+
- \`{{{author.bio}}}\` (triple braces!)
|
|
616
|
+
- \`{{author.email}}\`
|
|
617
|
+
- \`{{author.twitterProfileLink}}\`
|
|
618
|
+
- \`{{author.linkedinProfileLink}}\`
|
|
619
|
+
- \`{{author.url}}\`
|
|
620
|
+
|
|
621
|
+
**Always wrap in {{#if author}}** to handle posts without authors`,
|
|
622
|
+
featured_posts: `# Featured Posts Section
|
|
623
|
+
|
|
624
|
+
**Homepage featured posts (3 most recent):**
|
|
625
|
+
\`\`\`html
|
|
626
|
+
<section class="featured-posts">
|
|
627
|
+
<h2 data-edit-key="home-blog-title">Latest News</h2>
|
|
628
|
+
|
|
629
|
+
{{#each blogs featured=true limit=3}}
|
|
630
|
+
<article class="featured-card {{#if @first}}large{{/if}}">
|
|
631
|
+
{{#if mainImage}}
|
|
632
|
+
<img src="{{mainImage}}" alt="{{name}}">
|
|
633
|
+
{{/if}}
|
|
634
|
+
<div class="card-content">
|
|
635
|
+
<h3><a href="{{url}}">{{name}}</a></h3>
|
|
636
|
+
<p>{{postSummary}}</p>
|
|
637
|
+
{{#if author}}
|
|
638
|
+
<span class="byline">By {{author.name}}</span>
|
|
639
|
+
{{/if}}
|
|
640
|
+
<time>{{publishedAt}}</time>
|
|
641
|
+
</div>
|
|
642
|
+
</article>
|
|
643
|
+
{{/each}}
|
|
644
|
+
|
|
645
|
+
<a href="/blog" class="view-all">View All Posts →</a>
|
|
646
|
+
</section>
|
|
647
|
+
\`\`\`
|
|
648
|
+
|
|
649
|
+
**Hero featured post (single):**
|
|
650
|
+
\`\`\`html
|
|
651
|
+
{{#each blogs featured=true limit=1}}
|
|
652
|
+
<section class="hero-post">
|
|
653
|
+
{{#if mainImage}}
|
|
654
|
+
<div class="hero-image" style="background-image: url('{{mainImage}}')">
|
|
655
|
+
{{/if}}
|
|
656
|
+
<div class="hero-content">
|
|
657
|
+
<span class="label">Featured</span>
|
|
658
|
+
<h1><a href="{{url}}">{{name}}</a></h1>
|
|
659
|
+
<p>{{postSummary}}</p>
|
|
660
|
+
</div>
|
|
661
|
+
{{#if mainImage}}
|
|
662
|
+
</div>
|
|
663
|
+
{{/if}}
|
|
664
|
+
</section>
|
|
665
|
+
{{/each}}
|
|
666
|
+
\`\`\``,
|
|
667
|
+
};
|
|
668
|
+
/**
|
|
669
|
+
* Returns example code for a specific pattern
|
|
670
|
+
*/
|
|
671
|
+
async function getExample(exampleType) {
|
|
672
|
+
return EXAMPLES[exampleType] || `Example not found: ${exampleType}`;
|
|
673
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-schema.d.ts","sourceRoot":"","sources":["../../src/tools/get-schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CA6IjD"}
|