Skip to content

Commit

Permalink
feat(markdown-docx): add conditional transformer - #397
Browse files Browse the repository at this point in the history
transformation logic: OOXML<->CiceroMark
rules: OPTIONAL_RULE
tests

Signed-off-by: k-kumar-01 <[email protected]>
  • Loading branch information
K-Kumar-01 committed Aug 18, 2021
1 parent de694a2 commit f0f0af1
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 11 deletions.
59 changes: 55 additions & 4 deletions packages/markdown-docx/src/ToCiceroMarkVisitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,22 @@ class ToCiceroMarkVisitor {
ciceroMarkNode.whenSome = [];
}
}
if (nodeInformation.properties[nodePropertyIndex] === TRANSFORMED_NODES.conditional) {
let currentNodes = [...ciceroMarkNode.nodes];
ciceroMarkNode = {
$class: TRANSFORMED_NODES.conditional,
...nodeInformation.optionalProperties,
isTrue: nodeInformation.hasSome,
nodes: currentNodes,
};
if (nodeInformation.whenSomeType) {
ciceroMarkNode.whenTrue = currentNodes;
ciceroMarkNode.whenFalse = [];
} else {
ciceroMarkNode.whenFalse = currentNodes;
ciceroMarkNode.whenTrue = [];
}
}
if (nodeInformation.properties[nodePropertyIndex] === TRANSFORMED_NODES.link) {
ciceroMarkNode.title = '';
for (const relationshipElement of this.relationshipXML) {
Expand Down Expand Up @@ -312,6 +328,18 @@ class ToCiceroMarkVisitor {
} else {
eval(`${nestedExpression}nodes=${nestedExpression}whenNone`);
}
} else if (propertiesCurrent[commonPropertiesLength - 1] === TRANSFORMED_NODES.conditional) {
// equivalent to whenTrue
if (this.JSONXML[nodeIndex].whenSomeType) {
eval(`${nestedExpression}whenTrue=[...${nestedExpression}whenTrue, constructedNode]`);
} else {
eval(`${nestedExpression}whenFalse=[...${nestedExpression}whenFalse, constructedNode]`);
}
if (eval(`${nestedExpression}isTrue`)) {
eval(`${nestedExpression}nodes=${nestedExpression}whenTrue`);
} else {
eval(`${nestedExpression}nodes=${nestedExpression}whenFalse`);
}
} else {
eval(`${nestedExpression}nodes=[...${nestedExpression}nodes, constructedNode]`);
}
Expand Down Expand Up @@ -375,6 +403,15 @@ class ToCiceroMarkVisitor {
if (colorCodePresent && shadeCodePresent) {
nodeInformation.nodeType = TRANSFORMED_NODES.code;
}
/**
* for optional hasSome and whenSome stand for same as would be in the ciceromark.
* for conditional, the following relations with optional can be made
* optional | conditional
* hasSome | isTrue
* whenSome | whenTrue
* whenFalse | whenFalse
* The properties for conditional are not added therefore.
*/
if (vanishPropertyPresent) {
if (fontFamilyPresent) {
nodeInformation.whenSomeType = false;
Expand All @@ -395,7 +432,7 @@ class ToCiceroMarkVisitor {
} else if (runTimeNodes.name === 'w:t') {
if (calledBy === TRANSFORMED_NODES.codeBlock) {
ooxmlTagTextValue += runTimeNodes.elements ? runTimeNodes.elements[0].text : '';
} else if (calledBy === TRANSFORMED_NODES.optional) {
} else if (calledBy === TRANSFORMED_NODES.optional || calledBy === TRANSFORMED_NODES.conditional) {
ooxmlTagTextValue = runTimeNodes.elements && runTimeNodes.elements[0].text;
nodeInformation.value = ooxmlTagTextValue;
} else {
Expand All @@ -407,7 +444,7 @@ class ToCiceroMarkVisitor {
ooxmlTagTextValue += '\n';
} else if (runTimeNodes.name === 'w:sym') {
nodeInformation.nodeType = TRANSFORMED_NODES.softbreak;
if (calledBy !== TRANSFORMED_NODES.optional) {
if (!(calledBy === TRANSFORMED_NODES.optional || calledBy === TRANSFORMED_NODES.conditional)) {
this.JSONXML = [...this.JSONXML, nodeInformation];
}
}
Expand All @@ -419,7 +456,7 @@ class ToCiceroMarkVisitor {
nodeInformation.hasSome = true;
}

if (calledBy === TRANSFORMED_NODES.optional) {
if (calledBy === TRANSFORMED_NODES.optional || calledBy === TRANSFORMED_NODES.conditional) {
return nodeInformation;
}
return ooxmlTagTextValue;
Expand Down Expand Up @@ -555,6 +592,20 @@ class ToCiceroMarkVisitor {
this.JSONXML = [...this.JSONXML, { ...node }];
}
}
} else if (nodeInformation.nodeType === TRANSFORMED_NODES.conditional) {
if (variableSubNodes.elements) {
const optionalNodes = this.traverseElements(
variableSubNodes.elements,
TRANSFORMED_NODES.conditional
);
for (const node of optionalNodes) {
node.properties = [TRANSFORMED_NODES.conditional, ...node.properties];
node.optionalProperties = {
name: nodeInformation.name,
};
this.JSONXML = [...this.JSONXML, { ...node }];
}
}
} else {
for (const variableContentNodes of variableSubNodes.elements) {
if (variableContentNodes.name === 'w:r') {
Expand Down Expand Up @@ -582,7 +633,7 @@ class ToCiceroMarkVisitor {
inlineNodes = [...inlineNodes, this.fetchFormattingProperties(subNode, parent, nodeInformation)];
}
}
if (parent === TRANSFORMED_NODES.optional) {
if (parent === TRANSFORMED_NODES.optional || parent === TRANSFORMED_NODES.conditional) {
return inlineNodes;
}
return blockNodes;
Expand Down
36 changes: 31 additions & 5 deletions packages/markdown-docx/src/ToOOXMLVisitor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const {
OPTIONAL_RULE,
VANISH_PROPERTY_RULE,
CONDITIONAL_OR_OPTIONAL_FONT_FAMILY_RULE,
CONDITIONAL_RULE,
} = require('./rules');
const { wrapAroundDefaultDocxTags, wrapAroundLockedContentControls } = require('./helpers');
const { TRANSFORMED_NODES, RELATIONSHIP_OFFSET } = require('../constants');
Expand Down Expand Up @@ -153,13 +154,13 @@ class ToOOXMLVisitor {
if (this.getClass(subNode) === TRANSFORMED_NODES.text) {
const tag = this.generateTextOrCodeOOXML(subNode.text, properties, false, parentProperties);
inlineOOXML += tag;
if (parent !== TRANSFORMED_NODES.optional) {
if (!(parent === TRANSFORMED_NODES.optional || parent === TRANSFORMED_NODES.conditional)) {
this.tags = [...this.tags, tag];
}
} else if (this.getClass(subNode) === TRANSFORMED_NODES.code) {
const tag = this.generateTextOrCodeOOXML(subNode.text, properties, true, parentProperties);
inlineOOXML += tag;
if (parent !== TRANSFORMED_NODES.optional) {
if (!(parent === TRANSFORMED_NODES.optional || parent === TRANSFORMED_NODES.conditional)) {
this.tags = [...this.tags, tag];
}
} else if (this.getClass(subNode) === TRANSFORMED_NODES.codeBlock) {
Expand Down Expand Up @@ -190,12 +191,12 @@ class ToOOXMLVisitor {
type,
parentProperties.traversingNodeHiddenInConditional
);
if (parent !== TRANSFORMED_NODES.optional) {
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.softbreak) {
inlineOOXML += SOFTBREAK_RULE();
if (parent !== TRANSFORMED_NODES.optional) {
if (!(parent === TRANSFORMED_NODES.optional || parent === TRANSFORMED_NODES.conditional)) {
this.tags = [...this.tags, SOFTBREAK_RULE()];
}
} else if (this.getClass(subNode) === TRANSFORMED_NODES.thematicBreak) {
Expand Down Expand Up @@ -325,6 +326,31 @@ class ToOOXMLVisitor {
// make the parentProperties false as traversal is done
parentProperties.traversingNodeHiddenInConditional = false;
parentProperties.traversingNodePresentInWhenFalseOrWhenNoneCondtion = false;
} else if (this.getClass(subNode) === TRANSFORMED_NODES.conditional) {
parentProperties.traversingNodeHiddenInConditional = !subNode.isTrue;
// traverse true nodes
const whenTrueOOXML = this.traverseNodes(
subNode.whenTrue,
properties,
TRANSFORMED_NODES.conditional,
parentProperties
);
parentProperties.traversingNodePresentInWhenFalseOrWhenNoneCondtion = true;
// traverse false nodes
const whenFalseOOXML = this.traverseNodes(
subNode.whenFalse,
properties,
TRANSFORMED_NODES.conditional,
parentProperties
);
const ooxml = `${whenTrueOOXML} ${whenFalseOOXML}`;
const tag = subNode.name;
this.createOrUpdateCounter(tag);
const title = `${tag.toUpperCase()[0]}${tag.substring(1)}${this.counter[tag].count}`;
const conditionalTag = CONDITIONAL_RULE(title, tag, ooxml);
this.tags = [...this.tags, conditionalTag];
parentProperties.traversingNodeHiddenInConditional = false;
parentProperties.traversingNodePresentInWhenFalseOrWhenNoneCondtion = false;
} else {
if (this.getClass(subNode) === TRANSFORMED_NODES.link) {
this.relationships = [
Expand All @@ -336,7 +362,7 @@ class ToOOXMLVisitor {
];
}
let newProperties = [...properties, subNode.$class];
this.traverseNodes(subNode.nodes, newProperties, parent, parentProperties);
inlineOOXML += this.traverseNodes(subNode.nodes, newProperties, parent, parentProperties);
}
}
}
Expand Down
29 changes: 27 additions & 2 deletions packages/markdown-docx/src/ToOOXMLVisitor/rules.js
Original file line number Diff line number Diff line change
Expand Up @@ -283,14 +283,38 @@ const OPTIONAL_RULE = (title, tag, value, type) => {
const VANISH_PROPERTY_RULE = () => '<w:vanish/>';

/**
* Inserts a different font family so that the `whenNone` nodes for optional content can be distinguished from `whenSome` nodes.
*
* Inserts a different font family so that the conditional/optional content(else condition) can be distinguished. They can be of following types:-
* 1) `whenNone` nodes for optional(to be distinguished from `whenSome`)
* 2) `whenFalse` nodes for conditional(to be distinguished from `whenTrue`)
* @returns {string} OOXML tag for Baskerville Old Face font family
*/
const CONDITIONAL_OR_OPTIONAL_FONT_FAMILY_RULE = () => {
return '<w:rFonts w:ascii="Baskerville Old Face" w:hAnsi="Baskerville Old Face"/>';
};

/**
* Inserts optional node in OOXML form.
*
* @param {string} title Title of the optional node. Eg. receiver-1, shipper-1
* @param {string} tag Name of the optional node. Eg. receiver, shipper
* @param {string} value Value of the optional node
* @returns {string} OOXML string for the variable
*/
const CONDITIONAL_RULE = (title, tag, value) => {
return `
<w:sdt>
<w:sdtPr>
<w:alias w:val="${titleGenerator(title)}"/>
<w:tag w:val="${TRANSFORMED_NODES.conditional}${SEPARATOR}${tag}"/>
<w:lock w:val="contentLocked"/>
</w:sdtPr>
<w:sdtContent>
${value}
</w:sdtContent>
</w:sdt>
`;
};

module.exports = {
TEXT_RULE,
EMPHASIS_RULE,
Expand All @@ -311,4 +335,5 @@ module.exports = {
OPTIONAL_RULE,
VANISH_PROPERTY_RULE,
CONDITIONAL_OR_OPTIONAL_FONT_FAMILY_RULE,
CONDITIONAL_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 @@ -21,6 +21,7 @@ const TRANSFORMED_NODES = {
code: `${NS_PREFIX_CommonMarkModel}Code`,
codeBlock: `${NS_PREFIX_CommonMarkModel}CodeBlock`,
computedVariable: `${NS_PREFIX_CiceroMarkModel}ComputedVariable`,
conditional: `${NS_PREFIX_CiceroMarkModel}Conditional`,
optional: `${NS_PREFIX_CiceroMarkModel}Optional`,
document: `${NS_PREFIX_CommonMarkModel}Document`,
emphasize: `${NS_PREFIX_CommonMarkModel}Emph`,
Expand Down
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":"Late Delivery and Penalty."}]},{"$class":"org.accordproject.commonmark.Paragraph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"In case of delayed delivery"},{"$class":"org.accordproject.ciceromark.Conditional","isTrue":false,"whenTrue":[{"$class":"org.accordproject.commonmark.Text","text":" except for Force Majeure cases,"}],"whenFalse":[{"$class":"org.accordproject.commonmark.Text","text":" even when Force Majeure occurs,"}],"name":"forceMajeure","nodes":[{"$class":"org.accordproject.commonmark.Text","text":" even when Force Majeure occurs,"}]},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.ciceromark.Variable","value":"\"Dan\"","name":"seller","elementType":"org.accordproject.party.Party"},{"$class":"org.accordproject.commonmark.Text","text":" (the Seller) shall pay to "},{"$class":"org.accordproject.ciceromark.Variable","value":"\"Steve\"","name":"buyer","elementType":"org.accordproject.party.Party"},{"$class":"org.accordproject.commonmark.Text","text":" (the Buyer) for every "},{"$class":"org.accordproject.ciceromark.Variable","value":"2","name":"amount","elementType":"Long"},{"$class":"org.accordproject.commonmark.Text","text":" "},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"of delay penalty amounting to "},{"$class":"org.accordproject.ciceromark.Variable","value":"10.5","name":"penaltyPercentage","elementType":"Double"},{"$class":"org.accordproject.commonmark.Text","text":"% of the total value of the Equipment"},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"whose delivery has been delayed. Any fractional part of a "},{"$class":"org.accordproject.commonmark.Text","text":" is to be"},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"considered a full "},{"$class":"org.accordproject.commonmark.Text","text":". The total amount of penalty shall not however,"},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"exceed "},{"$class":"org.accordproject.ciceromark.Variable","value":"55.0","name":"capPercentage","elementType":"Double"},{"$class":"org.accordproject.commonmark.Text","text":"% of the total value of the Equipment involved in late delivery."},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"If the delay is more than "},{"$class":"org.accordproject.ciceromark.Variable","value":"15","name":"amount","elementType":"Long"},{"$class":"org.accordproject.commonmark.Text","text":" "},{"$class":"org.accordproject.commonmark.Text","text":", the Buyer is entitled to terminate this Contract."}]}]}
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":"Late Delivery and Penalty."}]},{"$class":"org.accordproject.commonmark.Paragraph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"In case of delayed delivery"},{"$class":"org.accordproject.ciceromark.Conditional","isTrue":true,"whenTrue":[{"$class":"org.accordproject.commonmark.Text","text":" except for Force Majeure cases,"},{"$class":"org.accordproject.commonmark.Emph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"not"}]}],"whenFalse":[{"$class":"org.accordproject.commonmark.Text","text":" even when Force Majeure occurs,"}],"name":"forceMajeure","nodes":[{"$class":"org.accordproject.commonmark.Text","text":" except for Force Majeure cases,"},{"$class":"org.accordproject.commonmark.Emph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"not"}]}]},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.ciceromark.Variable","value":"\"Dan\"","name":"seller","elementType":"org.accordproject.party.Party"},{"$class":"org.accordproject.commonmark.Text","text":" (the Seller) shall pay to "},{"$class":"org.accordproject.ciceromark.Variable","value":"\"Steve\"","name":"buyer","elementType":"org.accordproject.party.Party"},{"$class":"org.accordproject.commonmark.Text","text":" (the Buyer) for every "},{"$class":"org.accordproject.ciceromark.Variable","value":"2","name":"amount","elementType":"Long"},{"$class":"org.accordproject.commonmark.Text","text":" "},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"of delay penalty amounting to "},{"$class":"org.accordproject.ciceromark.Variable","value":"10.5","name":"penaltyPercentage","elementType":"Double"},{"$class":"org.accordproject.commonmark.Text","text":"% of the total value of the Equipment"},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"whose delivery has been delayed. Any fractional part of a "},{"$class":"org.accordproject.commonmark.Text","text":" is to be"},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"considered a full "},{"$class":"org.accordproject.commonmark.Text","text":". The total amount of penalty shall not however,"},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"exceed "},{"$class":"org.accordproject.ciceromark.Variable","value":"55.0","name":"capPercentage","elementType":"Double"},{"$class":"org.accordproject.commonmark.Text","text":"% of the total value of the Equipment involved in late delivery."},{"$class":"org.accordproject.commonmark.Softbreak"},{"$class":"org.accordproject.commonmark.Text","text":"If the delay is more than "},{"$class":"org.accordproject.ciceromark.Variable","value":"15","name":"amount","elementType":"Long"},{"$class":"org.accordproject.commonmark.Text","text":" "},{"$class":"org.accordproject.commonmark.Text","text":", the Buyer is entitled to terminate this Contract."}]}]}

0 comments on commit f0f0af1

Please sign in to comment.