Skip to content

Commit

Permalink
feat(markdown-docx): add formula transformer - #397 (#454)
Browse files Browse the repository at this point in the history
Signed-off-by: k-kumar-01 <[email protected]>
  • Loading branch information
K-Kumar-01 authored Aug 23, 2021
1 parent 58551c9 commit c659152
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Party A"</w:t>
<w:t xml:space="preserve">&quot;Party A&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down Expand Up @@ -114,15 +114,15 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Party B"</w:t>
<w:t xml:space="preserve">&quot;Party B&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>

<w:r>


<w:t xml:space="preserve">'s opinion, the </w:t>
<w:t xml:space="preserve">&apos;s opinion, the </w:t>

</w:r>
<w:sdt>
Expand All @@ -139,7 +139,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Widgets"</w:t>
<w:t xml:space="preserve">&quot;Widgets&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down Expand Up @@ -174,7 +174,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Party B"</w:t>
<w:t xml:space="preserve">&quot;Party B&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand All @@ -199,7 +199,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Party A"</w:t>
<w:t xml:space="preserve">&quot;Party A&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down Expand Up @@ -234,7 +234,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Widgets"</w:t>
<w:t xml:space="preserve">&quot;Widgets&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down Expand Up @@ -277,7 +277,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Party B"</w:t>
<w:t xml:space="preserve">&quot;Party B&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down Expand Up @@ -337,7 +337,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Widgets"</w:t>
<w:t xml:space="preserve">&quot;Widgets&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down Expand Up @@ -366,7 +366,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Party A"</w:t>
<w:t xml:space="preserve">&quot;Party A&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down Expand Up @@ -395,7 +395,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Widgets"</w:t>
<w:t xml:space="preserve">&quot;Widgets&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down Expand Up @@ -427,7 +427,7 @@
<w:r>


<w:t xml:space="preserve">The "Acceptance Criteria" are the specifications the </w:t>
<w:t xml:space="preserve">The &quot;Acceptance Criteria&quot; are the specifications the </w:t>

</w:r>
<w:sdt>
Expand All @@ -444,7 +444,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Widgets"</w:t>
<w:t xml:space="preserve">&quot;Widgets&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down Expand Up @@ -473,7 +473,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Party A"</w:t>
<w:t xml:space="preserve">&quot;Party A&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down Expand Up @@ -508,7 +508,7 @@
<w:sz w:val="24"/>

</w:rPr>
<w:t xml:space="preserve">"Attachment X"</w:t>
<w:t xml:space="preserve">&quot;Attachment X&quot;</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
Expand Down
27 changes: 27 additions & 0 deletions packages/markdown-docx/src/ToCiceroMarkVisitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ class ToCiceroMarkVisitor {
}
}

/**
* Gets the dependencies of a formula node
*
* @param {Array} variableProperties the variable elements
* @returns {string} the name of the variable
*/
getDependencies(variableProperties) {
for (const property of variableProperties) {
if (property.name === 'w:tag') {
return property.attributes['w:val'].split(SEPARATOR)[2];
}
}
}

/**
* Get the type of the element.
*
Expand Down Expand Up @@ -194,6 +208,14 @@ class ToCiceroMarkVisitor {
elementType: nodeInformation.elementType,
name: nodeInformation.name,
};
} else if (nodeInformation.nodeType === TRANSFORMED_NODES.formula) {
ciceroMarkNode = {
$class: TRANSFORMED_NODES.formula,
value: nodeInformation.value,
name: nodeInformation.name,
code: nodeInformation.code,
dependencies: nodeInformation.dependencies.split(','),
};
} else if (nodeInformation.nodeType === TRANSFORMED_NODES.code) {
ciceroMarkNode = {
$class: TRANSFORMED_NODES.code,
Expand Down Expand Up @@ -563,6 +585,11 @@ class ToCiceroMarkVisitor {
nodeInformation.name = this.getName(variableSubNodes.elements);
nodeInformation.elementType = this.getElementType(variableSubNodes.elements);
nodeInformation.nodeType = this.getNodeType(variableSubNodes.elements);
if (nodeInformation.nodeType === TRANSFORMED_NODES.formula) {
nodeInformation.code = nodeInformation.elementType;
nodeInformation.dependencies = this.getDependencies(variableSubNodes.elements);
delete nodeInformation.elementType;
}
}
if (variableSubNodes.name === 'w:sdtContent') {
if (nodeInformation.nodeType === TRANSFORMED_NODES.clause) {
Expand Down
11 changes: 8 additions & 3 deletions packages/markdown-docx/src/ToOOXMLVisitor/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@
'use strict';

/**
* Replaces the angular brackets with the respective codes.
* Escapes certain characters in OOXML with respective character encodings.
* (https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents)
*
* @param {string} node String to be replaced
* @returns {string} String with replaced angular brackets
*/
function sanitizeHtmlChars(node) {
return node.replace(/>/g, '&gt;').replace(/</g, '&lt;');
return node
.replace(/&/, '&amp;')
.replace(/>/g, '&gt;')
.replace(/</g, '&lt;')
.replace(/"/g, '&quot;')
.replace(/'/, '&apos;');
}

/**
Expand Down Expand Up @@ -63,7 +69,6 @@ function wrapAroundLockedContentControls(ooxml) {
* @returns {string} OOXML wraped in docx headers
*/
function wrapAroundDefaultDocxTags(ooxml, relationships) {

const LINK_STYLE_SPEC = `
<w:style w:type="character" w:styleId="Hyperlink">
<w:name w:val="Hyperlink"/>
Expand Down
33 changes: 32 additions & 1 deletion packages/markdown-docx/src/ToOOXMLVisitor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ const {
VANISH_PROPERTY_RULE,
CONDITIONAL_OR_OPTIONAL_FONT_FAMILY_RULE,
CONDITIONAL_RULE,
FORMULA_RULE,
} = require('./rules');
const { wrapAroundDefaultDocxTags, wrapAroundLockedContentControls } = require('./helpers');
const { wrapAroundDefaultDocxTags, wrapAroundLockedContentControls, sanitizeHtmlChars } = require('./helpers');
const { TRANSFORMED_NODES, RELATIONSHIP_OFFSET } = require('../constants');

/**
Expand Down Expand Up @@ -194,6 +195,36 @@ class ToOOXMLVisitor {
if (!(parent === TRANSFORMED_NODES.optional || parent === TRANSFORMED_NODES.conditional)) {
this.tags = [...this.tags, VARIABLE_RULE(title, tag, value, type)];
}
} else if (this.getClass(subNode) === TRANSFORMED_NODES.formula) {
// Dependencies are added for the reason to extract them
// when converting from ooxml -> ciceromark
const tag = subNode.name;
const type = sanitizeHtmlChars(subNode.code);
this.createOrUpdateCounter(tag, type);
const value = subNode.value;
const dependencies = subNode.dependencies.join(',');
const title = `${tag.toUpperCase()[0]}${tag.substring(1)}${this.counter[tag].count}`;
inlineOOXML += FORMULA_RULE(
title,
tag,
value,
type,
dependencies,
parentProperties.traversingNodeHiddenInConditional
);
if (!(parent === TRANSFORMED_NODES.optional || parent === TRANSFORMED_NODES.conditional)) {
this.tags = [
...this.tags,
FORMULA_RULE(
title,
tag,
value,
type,
dependencies,
parentProperties.traversingNodeHiddenInConditional
),
];
}
} else if (this.getClass(subNode) === TRANSFORMED_NODES.softbreak) {
inlineOOXML += SOFTBREAK_RULE();
if (!(parent === TRANSFORMED_NODES.optional || parent === TRANSFORMED_NODES.conditional)) {
Expand Down
34 changes: 34 additions & 0 deletions packages/markdown-docx/src/ToOOXMLVisitor/rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,39 @@ const CONDITIONAL_RULE = (title, tag, value) => {
</w:sdt>
`;
};
/**
* Inserts a formula.
*
* @param {string} title Title of the formula. Eg. receiver-1, shipper-1
* @param {string} tag Name of the formula. Eg. receiver, shipper
* @param {string} value Value of the formula
* @param {string} type Type of the formula - Long, Double, etc.
* @param {string} dependencies Dependencies of the formula
* @param {boolean} vanish Should vanish property be present
* @returns {string} OOXML string for the formula
*/
const FORMULA_RULE = (title, tag, value, type, dependencies, vanish = false) => {
return `
<w:sdt>
<w:sdtPr>
<w:rPr>
<w:sz w:val="24"/>
</w:rPr>
<w:alias w:val="${titleGenerator(title, type)}"/>
<w:tag w:val="${TRANSFORMED_NODES.formula}${SEPARATOR}${tag}${SEPARATOR}${dependencies}"/>
</w:sdtPr>
<w:sdtContent>
<w:r>
<w:rPr>
<w:sz w:val="24"/>
${vanish ? VANISH_PROPERTY_RULE() : ''}
</w:rPr>
<w:t xml:space="preserve">${sanitizeHtmlChars(value)}</w:t>
</w:r>
</w:sdtContent>
</w:sdt>
`;
};

module.exports = {
TEXT_RULE,
Expand All @@ -336,4 +369,5 @@ module.exports = {
VANISH_PROPERTY_RULE,
CONDITIONAL_OR_OPTIONAL_FONT_FAMILY_RULE,
CONDITIONAL_RULE,
FORMULA_RULE,
};
1 change: 1 addition & 0 deletions packages/markdown-docx/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const TRANSFORMED_NODES = {
optional: `${NS_PREFIX_CiceroMarkModel}Optional`,
document: `${NS_PREFIX_CommonMarkModel}Document`,
emphasize: `${NS_PREFIX_CommonMarkModel}Emph`,
formula: `${NS_PREFIX_CiceroMarkModel}Formula`,
heading: `${NS_PREFIX_CommonMarkModel}Heading`,
item: `${NS_PREFIX_CommonMarkModel}Item`,
link: `${NS_PREFIX_CommonMarkModel}Link`,
Expand Down
1 change: 1 addition & 0 deletions packages/markdown-docx/test/data/ciceroMark/formula.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.commonmark.Heading","level":"2","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"Fixed rate loan"}]},{"$class":"org.accordproject.commonmark.Paragraph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"This is a "},{"$class":"org.accordproject.commonmark.Emph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"fixed interest"}]},{"$class":"org.accordproject.commonmark.Text","text":" loan to the amount of "},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"at the yearly interest rate of "},{"$class":"org.accordproject.ciceromark.Variable","value":"2.5","name":"rate","elementType":"Double"},{"$class":"org.accordproject.commonmark.Text","text":"%"},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"with a loan term of "},{"$class":"org.accordproject.ciceromark.Variable","value":"15","name":"loanDuration","elementType":"Integer"},{"$class":"org.accordproject.commonmark.Text","text":","},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"and monthly payments of "},{"$class":"org.accordproject.ciceromark.Formula","value":"\"£667.00\"","dependencies":["loanAmount","rate","loanDuration"],"code":" monthlyPaymentFormula(loanAmount,rate,loanDuration) as \"K0,0.00\" ","name":"formula_d02c8642fa12d6ed08dea71f0af7a77b0c7893804d0b43b537eb18ea6f666463"}]}]}
Loading

0 comments on commit c659152

Please sign in to comment.