Skip to content

Commit

Permalink
fix(template) Add stack to check for balanced inline blocks
Browse files Browse the repository at this point in the history
Signed-off-by: Jerome Simeon <[email protected]>
  • Loading branch information
jeromesimeon committed Sep 30, 2020
1 parent e1fa245 commit 011b3ee
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 0 deletions.
15 changes: 15 additions & 0 deletions packages/markdown-it-template/lib/template_inline.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ const FORMULA_RE = require('./template_re').FORMULA_RE;
const getBlockAttributes = require('./template_re').getBlockAttributes;

function template_inline(state, silent) {
// Maintain a stack for template block open/close
if (!state.templates) {
state.templates = [];
}

let ch, match, max, token, attrs,
pos = state.pos;

Expand Down Expand Up @@ -55,6 +60,9 @@ function template_inline(state, silent) {
if (!names.inlines.includes(block)) {
return false;
}
// Push open block to template stack
state.templates.push(block);

token = state.push('inline_block_' + block + '_open', 'span', 1);
token.content = match[0];
token.attrs = attrs;
Expand All @@ -72,11 +80,18 @@ function template_inline(state, silent) {
if (!names.inlines.includes(block)) {
return false;
}
// Check if template close block matches open in stack
const top = state.templates.pop();
if (top !== block) {
state.templates.push(top);
return false;
}

token = state.push('inline_block_' + block + '_close', 'span', -1);
token.content = match[0];
state.pos += match[0].length;

//state.templates.push(block);
return true;
} else if (ch === 0x25/* % */) {
match = state.src.slice(pos).match(FORMULA_RE);
Expand Down
2 changes: 2 additions & 0 deletions packages/markdown-it-template/test/data/inline1.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<p>This is a contract between <span class="variable" name="seller">seller</span> and <span class="variable" name="buyer">buyer</span> for the amount of <span class="variable" name="amount">amount</span> <span class="variable" name="currency">currency</span><span name="forceMajeure" class="if_inline">, even in the presence of force majeure{{/with}}</span>.</p>
<p>This is a contract between <span class="variable" name="seller">seller</span> and <span class="variable" name="buyer">buyer</span> for the amount of <span class="variable" name="amount">amount</span> <span class="variable" name="currency">currency</span><span name="forceMajeure" class="optional_inline">, even in the presence of force majeure</span>{{/with}}.</p>
1 change: 1 addition & 0 deletions packages/markdown-it-template/test/data/inline1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"type":"paragraph_open","tag":"p","attrs":null,"map":[0,1],"nesting":1,"level":0,"children":null,"content":"","markup":"","info":"","meta":null,"block":true,"hidden":false},{"type":"inline","tag":"","attrs":null,"map":[0,1],"nesting":0,"level":1,"children":[{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":0,"children":null,"content":"This is a contract between ","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"variable","tag":"variable","attrs":[["name","seller"]],"map":null,"nesting":0,"level":0,"children":null,"content":"{{seller}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":0,"children":null,"content":" and ","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"variable","tag":"variable","attrs":[["name","buyer"]],"map":null,"nesting":0,"level":0,"children":null,"content":"{{buyer}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":0,"children":null,"content":" for the amount of ","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"variable","tag":"variable","attrs":[["name","amount"]],"map":null,"nesting":0,"level":0,"children":null,"content":"{{amount}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":0,"children":null,"content":" ","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"variable","tag":"variable","attrs":[["name","currency"]],"map":null,"nesting":0,"level":0,"children":null,"content":"{{currency}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"inline_block_if_open","tag":"span","attrs":[["name","forceMajeure"]],"map":null,"nesting":1,"level":0,"children":null,"content":"{{#if forceMajeure}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":1,"children":null,"content":", even in the presence of force majeure{{/with}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"inline_block_if_close","tag":"span","attrs":null,"map":null,"nesting":-1,"level":0,"children":null,"content":"{{/if}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":0,"children":null,"content":".","markup":"","info":"","meta":null,"block":false,"hidden":false}],"content":"This is a contract between {{seller}} and {{buyer}} for the amount of {{amount}} {{currency}}{{#if forceMajeure}}, even in the presence of force majeure{{/with}}{{/if}}.","markup":"","info":"","meta":null,"block":true,"hidden":false},{"type":"paragraph_close","tag":"p","attrs":null,"map":null,"nesting":-1,"level":0,"children":null,"content":"","markup":"","info":"","meta":null,"block":true,"hidden":false},{"type":"paragraph_open","tag":"p","attrs":null,"map":[2,3],"nesting":1,"level":0,"children":null,"content":"","markup":"","info":"","meta":null,"block":true,"hidden":false},{"type":"inline","tag":"","attrs":null,"map":[2,3],"nesting":0,"level":1,"children":[{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":0,"children":null,"content":"This is a contract between ","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"variable","tag":"variable","attrs":[["name","seller"]],"map":null,"nesting":0,"level":0,"children":null,"content":"{{seller}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":0,"children":null,"content":" and ","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"variable","tag":"variable","attrs":[["name","buyer"]],"map":null,"nesting":0,"level":0,"children":null,"content":"{{buyer}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":0,"children":null,"content":" for the amount of ","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"variable","tag":"variable","attrs":[["name","amount"]],"map":null,"nesting":0,"level":0,"children":null,"content":"{{amount}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":0,"children":null,"content":" ","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"variable","tag":"variable","attrs":[["name","currency"]],"map":null,"nesting":0,"level":0,"children":null,"content":"{{currency}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"inline_block_optional_open","tag":"span","attrs":[["name","forceMajeure"]],"map":null,"nesting":1,"level":0,"children":null,"content":"{{#optional forceMajeure}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":1,"children":null,"content":", even in the presence of force majeure","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"inline_block_optional_close","tag":"span","attrs":null,"map":null,"nesting":-1,"level":0,"children":null,"content":"{{/optional}}","markup":"","info":"","meta":null,"block":false,"hidden":false},{"type":"text","tag":"","attrs":null,"map":null,"nesting":0,"level":0,"children":null,"content":"{{/with}}.","markup":"","info":"","meta":null,"block":false,"hidden":false}],"content":"This is a contract between {{seller}} and {{buyer}} for the amount of {{amount}} {{currency}}{{#optional forceMajeure}}, even in the presence of force majeure{{/optional}}{{/with}}.","markup":"","info":"","meta":null,"block":true,"hidden":false},{"type":"paragraph_close","tag":"p","attrs":null,"map":null,"nesting":-1,"level":0,"children":null,"content":"","markup":"","info":"","meta":null,"block":true,"hidden":false}]
3 changes: 3 additions & 0 deletions packages/markdown-it-template/test/data/inline1.tem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This is a contract between {{seller}} and {{buyer}} for the amount of {{amount}} {{currency}}{{#if forceMajeure}}, even in the presence of force majeure{{/with}}{{/if}}.

This is a contract between {{seller}} and {{buyer}} for the amount of {{amount}} {{currency}}{{#optional forceMajeure}}, even in the presence of force majeure{{/optional}}{{/with}}.
1 change: 1 addition & 0 deletions packages/markdown-it-template/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const MarkdownItTemplate = require('../lib');
const mdit = new MarkdownIt({html:true}).use(MarkdownItTemplate);

const tests = [
{ 'name' : 'inline1' },
{ 'name' : 'clause1' },
{ 'name' : 'clause2' },
{ 'name' : 'clause3' },
Expand Down
1 change: 1 addition & 0 deletions packages/markdown-template/test/data/test13/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"$class":"org.test.MyClause","seller":"Steve","buyer":"Betty","amount":3131,"currency":"EUR","forceMajeure":true,"clauseId":"cf1cc82b-17c7-47da-ba65-0952dd5dd168"}
1 change: 1 addition & 0 deletions packages/markdown-template/test/data/test13/grammar.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"$class":"org.accordproject.commonmark.Document","xmlns":"http://commonmark.org/xml/1.0","nodes":[{"$class":"org.accordproject.templatemark.ClauseDefinition","name":"top","elementType":"org.test.MyClause","nodes":[{"$class":"org.accordproject.commonmark.Paragraph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"This is a contract between "},{"$class":"org.accordproject.templatemark.VariableDefinition","name":"seller","elementType":"String"},{"$class":"org.accordproject.commonmark.Text","text":" and "},{"$class":"org.accordproject.templatemark.VariableDefinition","name":"buyer","elementType":"String"},{"$class":"org.accordproject.commonmark.Text","text":" for the amount of "},{"$class":"org.accordproject.templatemark.VariableDefinition","name":"amount","elementType":"Double"},{"$class":"org.accordproject.commonmark.Text","text":" "},{"$class":"org.accordproject.templatemark.EnumVariableDefinition","enumValues":["AED","AFN","ALL","AMD","ANG","AOA","ARS","AUD","AWG","AZN","BAM","BBD","BDT","BGN","BHD","BIF","BMD","BND","BOB","BOV","BRL","BSD","BTN","BWP","BYN","BZD","CAD","CDF","CHE","CHF","CHW","CLF","CLP","CNY","COP","COU","CRC","CUC","CUP","CVE","CZK","DJF","DKK","DOP","DZD","EGP","ERN","ETB","EUR","FJD","FKP","GBP","GEL","GHS","GIP","GMD","GNF","GTQ","GYD","HKD","HNL","HRK","HTG","HUF","IDR","ILS","INR","IQD","IRR","ISK","JMD","JOD","JPY","KES","KGS","KHR","KMF","KPW","KRW","KWD","KYD","KZT","LAK","LBP","LKR","LRD","LSL","LYD","MAD","MDL","MGA","MKD","MMK","MNT","MOP","MRU","MUR","MVR","MWK","MXN","MXV","MYR","MZN","NAD","NGN","NIO","NOK","NPR","NZD","OMR","PAB","PEN","PGK","PHP","PKR","PLN","PYG","QAR","RON","RSD","RUB","RWF","SAR","SBD","SCR","SDG","SEK","SGD","SHP","SLL","SOS","SRD","SSP","STN","SVC","SYP","SZL","THB","TJS","TMT","TND","TOP","TRY","TTD","TWD","TZS","UAH","UGX","USD","USN","UYI","UYU","UZS","VEF","VND","VUV","WST","XAF","XAG","XAU","XBA","XBB","XBC","XBD","XCD","XDR","XOF","XPD","XPF","XPT","XSU","XTS","XUA","XXX","YER","ZAR","ZMW","ZWL"],"name":"currency","elementType":"org.accordproject.money.CurrencyCode"},{"$class":"org.accordproject.templatemark.ConditionalDefinition","whenTrue":[{"$class":"org.accordproject.commonmark.Text","text":", even in the presence of force majeure{{/with}}"}],"whenFalse":[],"name":"forceMajeure"},{"$class":"org.accordproject.commonmark.Text","text":"."}]}]}]}
1 change: 1 addition & 0 deletions packages/markdown-template/test/data/test13/grammar.tem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is a contract between {{seller}} and {{buyer}} for the amount of {{amount}} {{currency}}{{#if forceMajeure}}, even in the presence of force majeure{{/with}}{{/if}}.
15 changes: 15 additions & 0 deletions packages/markdown-template/test/data/test13/model.cto
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace org.test

import org.accordproject.cicero.contract.* from https://models.accordproject.org/cicero/contract.cto
import org.accordproject.money.CurrencyCode from https://models.accordproject.org/[email protected]

/**
* The template model
*/
asset MyClause extends AccordClause {
o String seller
o String buyer
o Double amount
o CurrencyCode currency
o Boolean forceMajeure
}
1 change: 1 addition & 0 deletions packages/markdown-template/test/data/test13/sample.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This is a contract between "Steve" and "Betty" for the amount of 3131.0 EUR, even in the presence of force majeure{{/with}}.

0 comments on commit 011b3ee

Please sign in to comment.