Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/TemplateMarkInterpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,13 @@ function getJsonPath(rootData: any, currentNode: any, paths: string[]): string {
if (obj && obj.$class) {
if (NAVIGATION_NODES.indexOf(obj.$class) >= 0) {
if(obj.name !== 'top') { // HACK!!
withPath.push(`['${obj.name}']`);
// For primitive optional definitions, do not navigate into the
// property scope — variables inside should resolve from the parent context
const isOptional = OPTIONAL_DEFINITION_RE.test(obj.$class);
const isPrimitive = isOptional && obj.elementType && (ModelUtil as any).isPrimitiveType(obj.elementType);
if (!isPrimitive) {
Comment on lines +158 to +161
Comment on lines +158 to +161
withPath.push(`['${obj.name}']`);
}
}
}
}
Expand Down Expand Up @@ -244,6 +250,16 @@ async function generateOptionalBlocks(modelManager: ModelManager, clauseLibrary:
if (variableValues.length > 0) {
// Optional property exists, process whenSome with the property value as context
const optionalPropertyValue = variableValues[0];

// For primitive optional values (string, number, boolean), skip
// pre-processing and let the normal traverse handle it with the
// full parent data context. This allows named variables like {{age}}
// to resolve correctly inside {{#optional age}}...{{/optional}}.
const isPrimitive = typeof optionalPropertyValue !== 'object' || optionalPropertyValue === null;
if (isPrimitive) {
continue;
}

if (context.whenSome && context.whenSome.length > 0) {
// Create a paragraph wrapper for the whenSome content
const whenSomeParagraph = {
Expand Down
209 changes: 199 additions & 10 deletions test/__snapshots__/TemplateMarkInterpreter.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,135 @@ exports[`templatemark interpreter should generate clause-optional 1`] = `
}
`;

exports[`templatemark interpreter should generate conditional-variables 1`] = `
{
"$class": "org.accordproject.commonmark@0.5.0.Document",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Paragraph",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Paragraph",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Hello ",
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "String",
"name": "name",
"value": "Alice",
},
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": ".",
},
],
},
{
"$class": "org.accordproject.commonmark@0.5.0.Paragraph",
"nodes": [
{
"$class": "org.accordproject.ciceromark@0.6.0.Conditional",
"isTrue": true,
"name": "age",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "You are ",
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "Integer",
"name": "age",
"value": "30",
},
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": " years old.",
},
],
"whenFalse": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Age unknown.",
},
],
"whenTrue": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "You are ",
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "Integer",
"name": "age",
"value": "30",
},
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": " years old.",
},
],
},
],
},
{
"$class": "org.accordproject.commonmark@0.5.0.Paragraph",
"nodes": [
{
"$class": "org.accordproject.ciceromark@0.6.0.Conditional",
"isTrue": true,
"name": "isActive",
"nodes": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Active user: ",
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "String",
"name": "name",
"value": "Alice",
},
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": ".",
},
],
"whenFalse": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Inactive.",
},
],
"whenTrue": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Active user: ",
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "String",
"name": "name",
"value": "Alice",
},
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": ".",
},
],
},
],
},
],
},
],
"xmlns": "http://commonmark.org/xml/1.0",
}
`;

exports[`templatemark interpreter should generate formula-now 1`] = `
{
"$class": "org.accordproject.commonmark@0.5.0.Document",
Expand Down Expand Up @@ -2923,12 +3052,23 @@ exports[`templatemark interpreter should generate optional_comprehensive 1`] = `
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "Integer",
"name": "this",
"name": "age",
"value": "30",
},
],
"whenNone": [],
"whenSome": [],
"whenSome": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Age is ",
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "Integer",
"name": "age",
"value": "30",
},
],
},
],
},
Expand Down Expand Up @@ -2990,12 +3130,23 @@ exports[`templatemark interpreter should generate optional_comprehensive 1`] = `
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "Boolean",
"name": "this",
"name": "active",
"value": "true",
},
],
"whenNone": [],
"whenSome": [],
"whenSome": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Status: ",
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "Boolean",
"name": "active",
"value": "true",
},
],
},
],
},
Expand Down Expand Up @@ -3097,7 +3248,7 @@ exports[`templatemark interpreter should generate optional_comprehensive 1`] = `
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "Integer",
"name": "this",
"name": "age",
"value": "25",
},
{
Expand All @@ -3106,7 +3257,22 @@ exports[`templatemark interpreter should generate optional_comprehensive 1`] = `
},
],
"whenNone": [],
"whenSome": [],
"whenSome": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "(",
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "Integer",
"name": "age",
"value": "25",
},
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": " years old)",
},
],
},
],
"whenNone": [],
Expand Down Expand Up @@ -3141,12 +3307,24 @@ exports[`templatemark interpreter should generate optional_comprehensive 1`] = `
"$class": "org.accordproject.ciceromark@0.6.0.FormattedVariable",
"elementType": "DateTime",
"format": "MMMM DD, YYYY",
"name": "this",
"name": "lastVisit",
"value": "December 01, 2023",
},
],
"whenNone": [],
"whenSome": [],
"whenSome": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Last visit: ",
},
{
"$class": "org.accordproject.ciceromark@0.6.0.FormattedVariable",
"elementType": "DateTime",
"format": "MMMM DD, YYYY",
"name": "lastVisit",
"value": "December 01, 2023",
},
],
},
],
},
Expand Down Expand Up @@ -3783,12 +3961,23 @@ exports[`templatemark interpreter should generate optional-nested 1`] = `
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "Integer",
"name": "this",
"name": "age",
"value": "42",
},
],
"whenNone": [],
"whenSome": [],
"whenSome": [
{
"$class": "org.accordproject.commonmark@0.5.0.Text",
"text": "Age is provided as ",
},
{
"$class": "org.accordproject.ciceromark@0.6.0.Variable",
"elementType": "Integer",
"name": "age",
"value": "42",
},
],
},
],
},
Expand Down
6 changes: 6 additions & 0 deletions test/templates/good/conditional-variables/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$class": "test@1.0.0.TemplateData",
"age": 30,
"name": "Alice",
"isActive": true
}
8 changes: 8 additions & 0 deletions test/templates/good/conditional-variables/model.cto
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace test@1.0.0

@template
concept TemplateData {
o Integer age optional
o String name
o Boolean isActive optional
}
5 changes: 5 additions & 0 deletions test/templates/good/conditional-variables/template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Hello {{name}}.

{{#if age}}You are {{age}} years old.{{else}}Age unknown.{{/if}}

{{#if isActive}}Active user: {{name}}.{{else}}Inactive.{{/if}}
2 changes: 1 addition & 1 deletion test/templates/good/optional-nested/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Order total: {{% return '£' + order.orderLines.map(ol => ol.price * ol.quantity

### Verification
Checking logic for top-level optionals:
{{#optional age}}Age is provided as {{this}}{{else}}Age is hidden{{/optional}}
{{#optional age}}Age is provided as {{age}}{{else}}Age is hidden{{/optional}}



Expand Down
10 changes: 5 additions & 5 deletions test/templates/good/optional_comprehensive/template.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@

### Scalar Optional Cases

1. Integer: {{#optional age}}Age is {{this}}{{else}}No age{{/optional}}
2. String: {{#optional middleName}}Middle name: {{this}}{{else}}No middle name{{/optional}}
3. Boolean: {{#optional active}}Status: {{this}}{{else}}Status unknown{{/optional}}
1. Integer: {{#optional age}}Age is {{age}}{{else}}No age{{/optional}}
2. String: {{#optional middleName}}Middle name: {{middleName}}{{else}}No middle name{{/optional}}
3. Boolean: {{#optional active}}Status: {{active}}{{else}}Status unknown{{/optional}}

### Object Optional Cases

{{#optional address}}Address: {{street}}, {{city}}{{else}}No address provided{{/optional}}

### Nested Optional Within Optional

{{#optional person}}Person: {{name}} {{#optional age}}({{this}} years old){{/optional}}{{else}}No person{{/optional}}
{{#optional person}}Person: {{name}} {{#optional age}}({{age}} years old){{/optional}}{{else}}No person{{/optional}}

### Formatted Optional

{{#optional lastVisit}}Last visit: {{this as "MMMM DD, YYYY"}}{{else}}Never visited{{/optional}}
{{#optional lastVisit}}Last visit: {{lastVisit as "MMMM DD, YYYY"}}{{else}}Never visited{{/optional}}

Complete.
Loading