Skip to content

Commit 011b3ee

Browse files
committed
fix(template) Add stack to check for balanced inline blocks
Signed-off-by: Jerome Simeon <[email protected]>
1 parent e1fa245 commit 011b3ee

File tree

10 files changed

+41
-0
lines changed

10 files changed

+41
-0
lines changed

packages/markdown-it-template/lib/template_inline.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ const FORMULA_RE = require('./template_re').FORMULA_RE;
2525
const getBlockAttributes = require('./template_re').getBlockAttributes;
2626

2727
function template_inline(state, silent) {
28+
// Maintain a stack for template block open/close
29+
if (!state.templates) {
30+
state.templates = [];
31+
}
32+
2833
let ch, match, max, token, attrs,
2934
pos = state.pos;
3035

@@ -55,6 +60,9 @@ function template_inline(state, silent) {
5560
if (!names.inlines.includes(block)) {
5661
return false;
5762
}
63+
// Push open block to template stack
64+
state.templates.push(block);
65+
5866
token = state.push('inline_block_' + block + '_open', 'span', 1);
5967
token.content = match[0];
6068
token.attrs = attrs;
@@ -72,11 +80,18 @@ function template_inline(state, silent) {
7280
if (!names.inlines.includes(block)) {
7381
return false;
7482
}
83+
// Check if template close block matches open in stack
84+
const top = state.templates.pop();
85+
if (top !== block) {
86+
state.templates.push(top);
87+
return false;
88+
}
7589

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

94+
//state.templates.push(block);
8095
return true;
8196
} else if (ch === 0x25/* % */) {
8297
match = state.src.slice(pos).match(FORMULA_RE);
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<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>
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="optional_inline">, even in the presence of force majeure</span>{{/with}}.</p>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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}]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
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}}.
2+
3+
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}}.

packages/markdown-it-template/test/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const MarkdownItTemplate = require('../lib');
2929
const mdit = new MarkdownIt({html:true}).use(MarkdownItTemplate);
3030

3131
const tests = [
32+
{ 'name' : 'inline1' },
3233
{ 'name' : 'clause1' },
3334
{ 'name' : 'clause2' },
3435
{ 'name' : 'clause3' },
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"$class":"org.test.MyClause","seller":"Steve","buyer":"Betty","amount":3131,"currency":"EUR","forceMajeure":true,"clauseId":"cf1cc82b-17c7-47da-ba65-0952dd5dd168"}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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":"."}]}]}]}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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}}.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace org.test
2+
3+
import org.accordproject.cicero.contract.* from https://models.accordproject.org/cicero/contract.cto
4+
import org.accordproject.money.CurrencyCode from https://models.accordproject.org/[email protected]
5+
6+
/**
7+
* The template model
8+
*/
9+
asset MyClause extends AccordClause {
10+
o String seller
11+
o String buyer
12+
o Double amount
13+
o CurrencyCode currency
14+
o Boolean forceMajeure
15+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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 commit comments

Comments
 (0)