multisite-cms-mcp 1.0.5 → 1.0.6

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.
@@ -1 +1 @@
1
- {"version":3,"file":"get-conversion-guide.d.ts","sourceRoot":"","sources":["../../src/tools/get-conversion-guide.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;AAoe1H;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAkD1E"}
1
+ {"version":3,"file":"get-conversion-guide.d.ts","sourceRoot":"","sources":["../../src/tools/get-conversion-guide.ts"],"names":[],"mappings":"AAAA,KAAK,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;AAsgB1H;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAkD1E"}
@@ -287,6 +287,38 @@ Inside {{#each}}:
287
287
  - \`{{@last}}\` - true for last item
288
288
  - \`{{@index}}\` - zero-based index
289
289
 
290
+ ## Parent Context (\`../\`)
291
+ Inside loops, access the parent scope:
292
+ \`\`\`html
293
+ {{#each blogs}}
294
+ {{#if (eq author.name ../name)}}
295
+ <!-- Only show posts by current author -->
296
+ <h3>{{name}}</h3>
297
+ {{/if}}
298
+ {{/each}}
299
+ \`\`\`
300
+
301
+ - \`../name\` - Parent item's name field
302
+ - \`../slug\` - Parent item's slug
303
+ - \`../fieldName\` - Any field from parent scope
304
+
305
+ **Use cases:**
306
+ - Author pages: filter posts by current author
307
+ - Category pages: filter items by current category
308
+ - Related items: match based on current page
309
+
310
+ ## Equality Comparisons
311
+ Compare two values:
312
+ \`\`\`html
313
+ {{#if (eq author.name ../name)}}
314
+ <!-- True when fields match -->
315
+ {{/if}}
316
+
317
+ {{#eq status "published"}}
318
+ <!-- Compare to literal string -->
319
+ {{/eq}}
320
+ \`\`\`
321
+
290
322
  ## Collection Fields
291
323
 
292
324
  **Blog Posts:**
@@ -444,7 +476,9 @@ Keep external URLs unchanged:
444
476
  - [ ] Templates include header/footer
445
477
  - [ ] {{#each}} loops have {{/each}}
446
478
  - [ ] {{#if}} conditions have {{/if}}
479
+ - [ ] {{#eq}} comparisons have {{/eq}}
447
480
  - [ ] Rich text uses {{{triple braces}}}
481
+ - [ ] Parent refs (../) only inside loops
448
482
  - [ ] Correct field names used
449
483
 
450
484
  ## ✓ Field Names
@@ -1,4 +1,4 @@
1
- type ExampleType = 'manifest_basic' | 'manifest_custom_paths' | 'blog_index_template' | 'blog_post_template' | 'team_template' | 'downloads_template' | 'authors_template' | 'author_detail_template' | 'custom_collection_template' | 'form_handling' | 'asset_paths' | 'data_edit_keys' | 'each_loop' | 'conditional_if' | 'nested_fields' | 'featured_posts';
1
+ type ExampleType = 'manifest_basic' | 'manifest_custom_paths' | 'blog_index_template' | 'blog_post_template' | 'team_template' | 'downloads_template' | 'authors_template' | 'author_detail_template' | 'custom_collection_template' | 'form_handling' | 'asset_paths' | 'data_edit_keys' | 'each_loop' | 'conditional_if' | 'nested_fields' | 'featured_posts' | 'parent_context' | 'equality_comparison';
2
2
  /**
3
3
  * Returns example code for a specific pattern
4
4
  */
@@ -1 +1 @@
1
- {"version":3,"file":"get-example.d.ts","sourceRoot":"","sources":["../../src/tools/get-example.ts"],"names":[],"mappings":"AAAA,KAAK,WAAW,GACZ,gBAAgB,GAChB,uBAAuB,GACvB,qBAAqB,GACrB,oBAAoB,GACpB,eAAe,GACf,oBAAoB,GACpB,kBAAkB,GAClB,wBAAwB,GACxB,4BAA4B,GAC5B,eAAe,GACf,aAAa,GACb,gBAAgB,GAChB,WAAW,GACX,gBAAgB,GAChB,eAAe,GACf,gBAAgB,CAAC;AA0qBrB;;GAEG;AACH,wBAAsB,UAAU,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1E"}
1
+ {"version":3,"file":"get-example.d.ts","sourceRoot":"","sources":["../../src/tools/get-example.ts"],"names":[],"mappings":"AAAA,KAAK,WAAW,GACZ,gBAAgB,GAChB,uBAAuB,GACvB,qBAAqB,GACrB,oBAAoB,GACpB,eAAe,GACf,oBAAoB,GACpB,kBAAkB,GAClB,wBAAwB,GACxB,4BAA4B,GAC5B,eAAe,GACf,aAAa,GACb,gBAAgB,GAChB,WAAW,GACX,gBAAgB,GAChB,eAAe,GACf,gBAAgB,GAChB,gBAAgB,GAChB,qBAAqB,CAAC;AAqxB1B;;GAEG;AACH,wBAAsB,UAAU,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAE1E"}
@@ -664,6 +664,111 @@ Make text editable in the CMS visual editor:
664
664
  </section>
665
665
  {{/each}}
666
666
  \`\`\``,
667
+ parent_context: `# Parent Context References (\`../\`)
668
+
669
+ Inside loops, access the **parent scope** (the page's current item) using \`../\`:
670
+
671
+ **Use Case: Author Detail Page - Show Only This Author's Posts**
672
+ \`\`\`html
673
+ <article class="author-detail">
674
+ <h1>{{name}}</h1>
675
+ <p class="bio">{{{bio}}}</p>
676
+
677
+ <section class="author-articles">
678
+ <h2>Posts by {{name}}</h2>
679
+
680
+ {{#each blogs}}
681
+ {{#if (eq author.name ../name)}}
682
+ <article class="post-card">
683
+ <h3><a href="{{url}}">{{name}}</a></h3>
684
+ <p>{{postSummary}}</p>
685
+ <time>{{publishedAt}}</time>
686
+ </article>
687
+ {{/if}}
688
+ {{/each}}
689
+ </section>
690
+ </article>
691
+ \`\`\`
692
+
693
+ **How It Works:**
694
+ - Inside \`{{#each blogs}}\`, the context is each blog post
695
+ - \`author.name\` = the blog post's author
696
+ - \`../name\` = the parent context (the author being displayed on the page)
697
+ - Only posts where author.name matches ../name are shown
698
+
699
+ **Use Case: Category Page - Highlight Current Category**
700
+ \`\`\`html
701
+ <nav class="category-nav">
702
+ {{#each categories}}
703
+ <a href="{{url}}" class="{{#if (eq slug ../slug)}}active{{/if}}">
704
+ {{name}}
705
+ </a>
706
+ {{/each}}
707
+ </nav>
708
+
709
+ <div class="category-content">
710
+ <h1>{{name}}</h1>
711
+
712
+ {{#each items}}
713
+ {{#if (eq category ../slug)}}
714
+ <div class="item">{{name}}</div>
715
+ {{/if}}
716
+ {{/each}}
717
+ </div>
718
+ \`\`\`
719
+
720
+ **Available Parent Fields:**
721
+ - \`../name\` - Parent item's name
722
+ - \`../slug\` - Parent item's slug
723
+ - \`../fieldName\` - Any field from the parent item
724
+ - \`../nested.field\` - Nested field access in parent`,
725
+ equality_comparison: `# Equality Comparisons
726
+
727
+ Compare two values using \`(eq field1 field2)\` helper:
728
+
729
+ **Compare Two Fields:**
730
+ \`\`\`html
731
+ {{#if (eq author.slug ../slug)}}
732
+ <span class="current-author-badge">✓ Your Post</span>
733
+ {{/if}}
734
+
735
+ {{#if (eq category selectedCategory)}}
736
+ <div class="active">{{name}}</div>
737
+ {{/if}}
738
+ \`\`\`
739
+
740
+ **Compare Field to Literal String (use {{#eq}}):**
741
+ \`\`\`html
742
+ {{#eq status "published"}}
743
+ <span class="badge badge-success">Published</span>
744
+ {{/eq}}
745
+
746
+ {{#eq type "featured"}}
747
+ <div class="featured-highlight">⭐ {{name}}</div>
748
+ {{/eq}}
749
+
750
+ {{#eq category "news"}}
751
+ <span class="news-icon">📰</span>
752
+ {{/eq}}
753
+ \`\`\`
754
+
755
+ **Inside Loops with Parent Context:**
756
+ \`\`\`html
757
+ {{#each blogs}}
758
+ <article class="{{#if (eq author.name ../name)}}highlight{{/if}}">
759
+ <h3>{{name}}</h3>
760
+ {{#if (eq author.name ../name)}}
761
+ <span class="yours">You wrote this!</span>
762
+ {{/if}}
763
+ </article>
764
+ {{/each}}
765
+ \`\`\`
766
+
767
+ **Common Use Cases:**
768
+ - Filter items by current category/author/tag
769
+ - Highlight active menu items
770
+ - Show badges for specific statuses
771
+ - Conditional styling based on relationships`,
667
772
  };
668
773
  /**
669
774
  * Returns example code for a specific pattern
@@ -1 +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"}
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,CA+KjD"}
@@ -128,6 +128,40 @@ Inside \`{{#each}}\` blocks:
128
128
  {{/each}}
129
129
  \`\`\`
130
130
 
131
+ ### Parent Context References (\`../\`)
132
+ Inside loops, access the parent scope (page's current item) using \`../\`:
133
+
134
+ \`\`\`html
135
+ <!-- On author detail page, show only posts by THIS author -->
136
+ {{#each blogs}}
137
+ {{#if (eq author.name ../name)}}
138
+ <h3>{{name}}</h3>
139
+ {{/if}}
140
+ {{/each}}
141
+ \`\`\`
142
+
143
+ - \`../name\` - Parent item's name field
144
+ - \`../slug\` - Parent item's slug
145
+ - \`../fieldName\` - Any field from the parent scope
146
+
147
+ **Use cases:**
148
+ - Author pages: filter posts by current author
149
+ - Category pages: filter items by current category
150
+ - Related items: match based on current detail page
151
+
152
+ ### Equality Comparisons
153
+ Compare two values in conditionals:
154
+
155
+ \`\`\`html
156
+ {{#if (eq author.name ../name)}}
157
+ <!-- True when fields match -->
158
+ {{/if}}
159
+
160
+ {{#eq status "published"}}
161
+ <!-- Compare field to literal string -->
162
+ {{/eq}}
163
+ \`\`\`
164
+
131
165
  ### Rich Text (Triple Braces)
132
166
  For HTML content that should NOT be escaped:
133
167
  \`\`\`html
@@ -1 +1 @@
1
- {"version":3,"file":"validate-template.d.ts","sourceRoot":"","sources":["../../src/tools/validate-template.ts"],"names":[],"mappings":"AAAA,KAAK,YAAY,GAAG,YAAY,GAAG,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,eAAe,GAAG,eAAe,GAAG,cAAc,GAAG,eAAe,GAAG,aAAa,CAAC;AA0E7J;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,YAAY,EAC1B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,CAAC,CAgNjB"}
1
+ {"version":3,"file":"validate-template.d.ts","sourceRoot":"","sources":["../../src/tools/validate-template.ts"],"names":[],"mappings":"AAAA,KAAK,YAAY,GAAG,YAAY,GAAG,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,eAAe,GAAG,eAAe,GAAG,cAAc,GAAG,eAAe,GAAG,aAAa,CAAC;AA0E7J;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,YAAY,EAC1B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,CAAC,CA+OjB"}
@@ -208,6 +208,34 @@ async function validateTemplate(html, templateType, collectionSlug) {
208
208
  if (siteTokens.length > 0) {
209
209
  suggestions.push(`- Found ${siteTokens.length} site token(s) like {{site.site_name}} - these come from manifest.json`);
210
210
  }
211
+ // Validate parent context references (../)
212
+ const parentRefs = html.match(/\{\{\.\.\/([\w.]+)\}\}/g) || [];
213
+ if (parentRefs.length > 0) {
214
+ // Check if they're used inside a loop
215
+ if (eachLoops.length === 0) {
216
+ warnings.push(`- Found ${parentRefs.length} parent reference(s) like {{../name}} but no {{#each}} loop - these only work inside loops`);
217
+ }
218
+ else {
219
+ suggestions.push(`- Found ${parentRefs.length} parent context reference(s) ({{../fieldName}}) - accesses parent scope in loops`);
220
+ }
221
+ }
222
+ // Validate equality helper syntax
223
+ const eqHelpers = html.match(/\{\{#if\s+\(eq\s+[^)]+\)\s*\}\}/g) || [];
224
+ if (eqHelpers.length > 0) {
225
+ suggestions.push(`- Found ${eqHelpers.length} equality comparison(s) like {{#if (eq field1 field2)}} - compares two values`);
226
+ // Check if closing {{/if}} exists for each
227
+ for (const helper of eqHelpers) {
228
+ if (!html.includes('{{/if}}')) {
229
+ errors.push(`- Missing {{/if}} to close: ${helper}`);
230
+ }
231
+ }
232
+ }
233
+ // Validate {{#eq}} blocks
234
+ const eqBlocks = html.match(/\{\{#eq\s+[\w.]+\s+"[^"]+"\s*\}\}/g) || [];
235
+ const eqCloses = (html.match(/\{\{\/eq\}\}/g) || []).length;
236
+ if (eqBlocks.length !== eqCloses) {
237
+ errors.push(`- Unbalanced {{#eq}}: ${eqBlocks.length} opens, ${eqCloses} closes`);
238
+ }
211
239
  // Build result
212
240
  let output = '';
213
241
  if (errors.length === 0 && warnings.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multisite-cms-mcp",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
4
4
  "description": "MCP server for AI-assisted website conversion to CMS format. Provides validation, examples, and schema tools.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {