@adobe/helix-md2jcr 1.1.34 → 1.1.36

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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [1.1.36](https://github.com/adobe/helix-md2jcr/compare/v1.1.35...v1.1.36) (2025-09-29)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * model fields of component = tab should not be included in model fields ([#155](https://github.com/adobe/helix-md2jcr/issues/155)) ([ad3ecc4](https://github.com/adobe/helix-md2jcr/commit/ad3ecc4bb86acbc6cbf8a3ca842ba92572efc49b)), closes [#154](https://github.com/adobe/helix-md2jcr/issues/154)
7
+
8
+ ## [1.1.35](https://github.com/adobe/helix-md2jcr/compare/v1.1.34...v1.1.35) (2025-09-23)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * support html comments generated with createComment api ([#153](https://github.com/adobe/helix-md2jcr/issues/153)) ([dc8d06e](https://github.com/adobe/helix-md2jcr/commit/dc8d06e62643c738db639cc3276bd77f040d9ae7))
14
+
1
15
  ## [1.1.34](https://github.com/adobe/helix-md2jcr/compare/v1.1.33...v1.1.34) (2025-09-16)
2
16
 
3
17
 
@@ -0,0 +1,190 @@
1
+ # Modeling Guide
2
+
3
+ This document provides guidance on modeling content in the Helix MD2JCR system, with a focus on field hinting and its applications.
4
+
5
+ ## Field Hinting
6
+
7
+ Field hinting is a powerful feature in the Helix MD2JCR system that allows you to explicitly specify which field in a component model should receive specific content from your markdown. This is particularly useful when the automatic field resolution doesn't match your intended content structure or when you need precise control over field mapping.
8
+
9
+ ### Purpose of Field Hinting
10
+
11
+ Field hinting serves several important purposes:
12
+
13
+ 1. **Precise Field Mapping**: When content doesn't naturally flow into the expected fields based on the model's field order, field hints allow you to explicitly direct content to specific fields.
14
+
15
+ 2. **Content Structure Control**: In complex components with multiple fields of the same type (e.g., multiple text fields), field hints ensure content goes to the correct field.
16
+
17
+ 3. **Sequential Field Mapping**: Field hints allow you to skip ahead to a specific field in the model's field sequence, but content must still be processed in the order it appears in the markdown.
18
+
19
+ ### How Field Hinting Works
20
+
21
+ Field hints are implemented as HTML comments in your markdown content with the following syntax:
22
+
23
+ ```html
24
+ <!-- field: fieldName -->
25
+ ```
26
+
27
+ The system recognizes these comments and uses them to direct the following content to the specified field. The field hint affects the next content node that would normally be processed.
28
+
29
+
30
+ ## Examples
31
+
32
+ ### Basic Blocks
33
+
34
+ Basic blocks typically have a simple field structure where each row corresponds to a single model field. Field hints are generally not useful for basic blocks since the automatic field resolution works well with this straightforward one-to-one mapping.
35
+
36
+ #### Example: Custom Block
37
+
38
+ Consider a custom block with the following model:
39
+
40
+ ```json
41
+ {
42
+ "id": "custom",
43
+ "fields": [
44
+ {
45
+ "component": "text",
46
+ "name": "classes"
47
+ },
48
+ {
49
+ "component": "richtext",
50
+ "name": "p_1"
51
+ },
52
+ {
53
+ "component": "reference",
54
+ "name": "p_2"
55
+ },
56
+ {
57
+ "component": "text",
58
+ "name": "p_2Alt"
59
+ },
60
+ {
61
+ "component": "text",
62
+ "name": "p_3"
63
+ }
64
+ ]
65
+ }
66
+ ```
67
+
68
+ **Without field hints** (automatic resolution):
69
+ ```markdown
70
+ +-------------------------------------------------------+
71
+ | Custom (greedy) |
72
+ +=======================================================+
73
+ | All text up to image is included: |
74
+ | ``` |
75
+ | console.log("hello") |
76
+ | ``` |
77
+ | <a href="www.google.com">Google</a> |
78
+ | |
79
+ | ![Image][image0] |
80
+ | |
81
+ | After image there's more text |
82
+ +-------------------------------------------------------+
83
+ ```
84
+
85
+ **With field hints** (explicit control skipping optional fields):
86
+ ```markdown
87
+ +-------------------------------------------------------+
88
+ | Custom (greedy) |
89
+ +=======================================================+
90
+ | <!-- field: p_3 --> |
91
+ | After image there's more text |
92
+ +-------------------------------------------------------+
93
+ ```
94
+
95
+ ### Container Blocks
96
+
97
+ Container blocks are more complex and often benefit significantly from field hinting, especially when they have multiple fields of similar types.
98
+
99
+ #### Example: Teaser Component
100
+
101
+ Consider a teaser component with the following model:
102
+
103
+ ```json
104
+ {
105
+ "id": "teaser",
106
+ "fields": [
107
+ {
108
+ "component": "reference",
109
+ "name": "image",
110
+ "label": "Image"
111
+ },
112
+ {
113
+ "component": "text",
114
+ "name": "teaserText_subtitle",
115
+ "label": "Sub title"
116
+ },
117
+ {
118
+ "component": "text",
119
+ "name": "teaserText_title",
120
+ "label": "Title"
121
+ },
122
+ {
123
+ "component": "text",
124
+ "name": "teaserText_titleType",
125
+ "label": "Heading Type"
126
+ },
127
+ {
128
+ "component": "richtext",
129
+ "name": "teaserText_description",
130
+ "label": "Description"
131
+ },
132
+ {
133
+ "component": "text",
134
+ "name": "teaserText_cta",
135
+ "label": "CTA"
136
+ },
137
+ {
138
+ "component": "text",
139
+ "name": "teaserText_ctaText",
140
+ "label": "CTA Text"
141
+ }
142
+ ]
143
+ }
144
+ ```
145
+
146
+ **Without field hints** (automatic resolution):
147
+ ```markdown
148
+ +-------------------------------------------------+
149
+ | Teaser |
150
+ +=================================================+
151
+ | ![A group of people sitting on a stage][image0] |
152
+ +-------------------------------------------------+
153
+ | Adobe Experience Cloud |
154
+ | ## Welcome to AEM |
155
+ | Join us in this ask me everything session ... |
156
+ +-------------------------------------------------+
157
+ ```
158
+
159
+ **With field hints** (explicit control):
160
+ ```markdown
161
+ +-------------------------------------------------+
162
+ | Teaser |
163
+ +=================================================+
164
+ | ![A group of people sitting on a stage][image0] |
165
+ +-------------------------------------------------+
166
+ | <!-- field:teaserText_title --> |
167
+ | ## Welcome to AEM |
168
+ | Join us in this ask me everything session ... |
169
+ | <!-- field:teaserText_cta --> |
170
+ | **[Adobe](www.adobe.com)** |
171
+ +-------------------------------------------------+
172
+ ```
173
+
174
+ ### Best Practices
175
+
176
+ 1. **Use field hints sparingly**: Only use field hints when automatic resolution doesn't work as expected or when you need precise control.
177
+
178
+ 2. **Be explicit with field names**: Use the exact field names as defined in your model to avoid mapping errors.
179
+
180
+ 3. **Consider content flow**: Must place field hints immediately before the content you want to map to that field.
181
+
182
+ 4. **Test your mappings**: Verify that your field hints correctly map content to the intended fields by checking the generated JCR output.
183
+
184
+ ### Common Use Cases
185
+
186
+ 1. **Multiple text fields**: When a component has multiple text fields and you want to ensure content goes to the correct one.
187
+
188
+ 2. **Rich text with mixed content**: When you have a rich text field that should contain specific content, followed by other field types.
189
+
190
+ Field hinting provides the flexibility and control needed to create complex, well-structured content while maintaining the simplicity of markdown authoring.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-md2jcr",
3
- "version": "1.1.34",
3
+ "version": "1.1.36",
4
4
  "description": "Helix Service that converts markdown to JCR content structure",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -34,6 +34,7 @@ class FieldGroup {
34
34
  const suffixes = ['Alt', 'MimeType', 'Type', 'Text', 'Title'];
35
35
 
36
36
  this.model.fields
37
+ .filter((field) => field.component !== 'tab')
37
38
  .filter((field) => field.name !== 'classes')
38
39
  .forEach((field) => {
39
40
  if (field.name.includes('_')) {
@@ -49,6 +49,7 @@ function getField(model, fieldName) {
49
49
  function getModelFieldNames(model) {
50
50
  return model
51
51
  ? model.fields
52
+ .filter((f) => f.component !== 'tab')
52
53
  .map((f) => f.name)
53
54
  .filter((f) => f !== 'classes')
54
55
  : [];
@@ -197,8 +197,31 @@ function extractKeyValueProperties(row, model, fieldResolver, fieldGroup, proper
197
197
  }
198
198
  }
199
199
 
200
+ /**
201
+ * Check if the node is a field name hint.
202
+ * @param {Node} node - the node to check
203
+ * @returns {boolean} - true if the node is a field name hint, false otherwise
204
+ */
200
205
  function isFieldNameHint(node) {
201
- return node.type === 'html' && node.value?.startsWith('<!-- field:') && node.value?.endsWith(' -->');
206
+ // get the node value and remove all whitespace from the value to test if it is a field name hint
207
+ if (node.type === 'html') {
208
+ const value = node.value.replace(/\s/g, '');
209
+ return value?.startsWith('<!--field:') && value?.endsWith('-->');
210
+ }
211
+ return false;
212
+ }
213
+
214
+ /**
215
+ * Get the field name hint value from the node.
216
+ * @param {Node} node - the node to get the field name hint value from
217
+ * @returns {string} - the field name hint value or null if the node is not a field name hint
218
+ */
219
+ function fieldHintValue(node) {
220
+ if (node.type === 'html') {
221
+ const value = node.value.replace(/\s/g, '');
222
+ return value.split('<!--field:')[1].split('-->')[0].trim();
223
+ }
224
+ return null;
202
225
  }
203
226
 
204
227
  function processCell(cell, fieldGroup, fieldResolver, properties) {
@@ -223,7 +246,7 @@ function processCell(cell, fieldGroup, fieldResolver, properties) {
223
246
 
224
247
  // if we see a property name hint, parse it and continue, unset it if not
225
248
  if (isFieldNameHint(node)) {
226
- nextFieldName = node.value.split('<!-- field:')[1].split(' -->')[0].trim();
249
+ nextFieldName = fieldHintValue(node);
227
250
  // eslint-disable-next-line no-continue
228
251
  continue;
229
252
  }