From f7208c760f5f00b042527080839e9b162c98bcb4 Mon Sep 17 00:00:00 2001 From: Jerome Simeon Date: Wed, 30 Sep 2020 14:03:12 -0400 Subject: [PATCH] fix(template) Properly closes templatemark nodes when building from tokens Signed-off-by: Jerome Simeon --- .../markdown-common/lib/FromMarkdownIt.js | 34 +++++++++++++++---- .../test/TemplateMarkTransformer.js | 2 ++ .../test/data/test14/data.json | 1 + .../test/data/test14/grammar.json | 1 + .../test/data/test14/grammar.tem.md | 1 + .../test/data/test14/model.cto | 15 ++++++++ .../test/data/test14/sample.md | 1 + 7 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 packages/markdown-template/test/data/test14/data.json create mode 100644 packages/markdown-template/test/data/test14/grammar.json create mode 100644 packages/markdown-template/test/data/test14/grammar.tem.md create mode 100644 packages/markdown-template/test/data/test14/model.cto create mode 100644 packages/markdown-template/test/data/test14/sample.md diff --git a/packages/markdown-common/lib/FromMarkdownIt.js b/packages/markdown-common/lib/FromMarkdownIt.js index 38a6aac4..af081142 100644 --- a/packages/markdown-common/lib/FromMarkdownIt.js +++ b/packages/markdown-common/lib/FromMarkdownIt.js @@ -34,6 +34,27 @@ class FromMarkdownIt { } } + /** + * Takes the stack of constructed inline nodes + * properly closing them (if the close token is missing in the markdown) + * returns the final root node for the inline + * + * @param {*[]} rules - the rules for each kind of markdown-it tokens + * @param {*[]} stack - the stack of constructed nodes + * @returns {*} the final inline node + */ + static closeInlines(rules,stack) { + let currentNode = stack.pop(); + while(stack.peek()) { + const rule = Object.values(rules.inlines).find((x) => x.tag === currentNode.$class && x.exit); + if (rule && rule.exit) { + rule.exit(currentNode,null,FromMarkdownIt.inlineCallback(rules)); + } + currentNode = stack.pop(); + } + return mergeAdjacentHtmlNodes(currentNode.nodes,true); + } + /** * Create a callback for inlines * @@ -41,7 +62,11 @@ class FromMarkdownIt { * @returns {*} the callback */ static inlineCallback(rules) { - return (tokens) => FromMarkdownIt.inlineToCommonMark(rules,tokens); + return (tokens) => { + const stack = new Stack(); + FromMarkdownIt.inlineToCommonMark(rules,tokens,stack); // Updates the stack + return FromMarkdownIt.closeInlines(rules,stack); + }; } /** @@ -49,10 +74,9 @@ class FromMarkdownIt { * * @param {*[]} rules - the rules for each kind of markdown-it tokens * @param {*} tokens - the content of the inline node - * @returns {*} the CommonMark nodes + * @param {*[]} stack - the stack of constructed nodes */ - static inlineToCommonMark(rules,tokens) { - let stack = new Stack(); + static inlineToCommonMark(rules,tokens,stack) { const rootNode = { '$class': 'org.accordproject.commonmark.Inline', 'nodes': [], @@ -87,8 +111,6 @@ class FromMarkdownIt { if (rule.enter) { rule.enter(node,token,FromMarkdownIt.inlineCallback(rules)); } } } - - return mergeAdjacentHtmlNodes(rootNode.nodes,true); } /** diff --git a/packages/markdown-template/test/TemplateMarkTransformer.js b/packages/markdown-template/test/TemplateMarkTransformer.js index 6aacafe2..8229b08b 100644 --- a/packages/markdown-template/test/TemplateMarkTransformer.js +++ b/packages/markdown-template/test/TemplateMarkTransformer.js @@ -57,6 +57,8 @@ const successes = [ {name:'test10',kind:'clause'}, {name:'test11',kind:'clause'}, {name:'test12',kind:'clause'}, + {name:'test13',kind:'clause'}, + {name:'test14',kind:'clause'}, {name:'testFormula',kind:'contract'}, {name:'testDateTime',kind:'clause'}, {name:'testDateTime2',kind:'clause'}, diff --git a/packages/markdown-template/test/data/test14/data.json b/packages/markdown-template/test/data/test14/data.json new file mode 100644 index 00000000..8e400e4e --- /dev/null +++ b/packages/markdown-template/test/data/test14/data.json @@ -0,0 +1 @@ +{"$class":"org.test.MyClause","seller":"Steve","buyer":"Betty","amount":3131,"currency":"EUR","forceMajeure":true,"clauseId":"cf1cc82b-17c7-47da-ba65-0952dd5dd168"} \ No newline at end of file diff --git a/packages/markdown-template/test/data/test14/grammar.json b/packages/markdown-template/test/data/test14/grammar.json new file mode 100644 index 00000000..379823f7 --- /dev/null +++ b/packages/markdown-template/test/data/test14/grammar.json @@ -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."}],"whenFalse":[],"name":"forceMajeure"}]}]}]} \ No newline at end of file diff --git a/packages/markdown-template/test/data/test14/grammar.tem.md b/packages/markdown-template/test/data/test14/grammar.tem.md new file mode 100644 index 00000000..7525510d --- /dev/null +++ b/packages/markdown-template/test/data/test14/grammar.tem.md @@ -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. \ No newline at end of file diff --git a/packages/markdown-template/test/data/test14/model.cto b/packages/markdown-template/test/data/test14/model.cto new file mode 100644 index 00000000..1a1ed3df --- /dev/null +++ b/packages/markdown-template/test/data/test14/model.cto @@ -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/money@0.2.0.cto + +/** + * The template model + */ +asset MyClause extends AccordClause { + o String seller + o String buyer + o Double amount + o CurrencyCode currency + o Boolean forceMajeure +} diff --git a/packages/markdown-template/test/data/test14/sample.md b/packages/markdown-template/test/data/test14/sample.md new file mode 100644 index 00000000..64d219ec --- /dev/null +++ b/packages/markdown-template/test/data/test14/sample.md @@ -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. \ No newline at end of file