From 9c00a23acabc739c034b76c0e683bccdd607cd46 Mon Sep 17 00:00:00 2001 From: k-kumar-01 Date: Tue, 10 Aug 2021 18:16:14 +0530 Subject: [PATCH] feat(markdown-docx): add optional transformer - #397 transformation logic:OOXML<->CiceroMark tests for optional update tests for other(xml changes in variable and clause) Signed-off-by: k-kumar-01 --- .../omitted-acceptance-of-delivery.xml | 28 +- .../markdown-docx/src/ToCiceroMarkVisitor.js | 70 +- .../markdown-docx/src/ToOOXMLVisitor/index.js | 104 ++- .../markdown-docx/src/ToOOXMLVisitor/rules.js | 30 +- packages/markdown-docx/src/constants.js | 1 + .../test/data/ciceroMark/optional.json | 1 + .../data/ooxml/acceptance-of-delivery.xml | 710 +++++++++++++++++- .../omitted-acceptance-of-delivery.xml | 28 +- 8 files changed, 895 insertions(+), 77 deletions(-) create mode 100644 packages/markdown-docx/test/data/ciceroMark/optional.json diff --git a/packages/markdown-cli/test/data/acceptance/omitted-acceptance-of-delivery.xml b/packages/markdown-cli/test/data/acceptance/omitted-acceptance-of-delivery.xml index 5c61ef8a..9e706dd5 100644 --- a/packages/markdown-cli/test/data/acceptance/omitted-acceptance-of-delivery.xml +++ b/packages/markdown-cli/test/data/acceptance/omitted-acceptance-of-delivery.xml @@ -71,7 +71,7 @@ - + @@ -105,7 +105,7 @@ - + @@ -129,7 +129,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -187,7 +187,7 @@ - + @@ -221,7 +221,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -287,7 +287,7 @@ - + @@ -321,7 +321,7 @@ - + @@ -349,7 +349,7 @@ - + @@ -377,7 +377,7 @@ - + @@ -425,7 +425,7 @@ - + @@ -453,7 +453,7 @@ - + @@ -487,7 +487,7 @@ - + diff --git a/packages/markdown-docx/src/ToCiceroMarkVisitor.js b/packages/markdown-docx/src/ToCiceroMarkVisitor.js index ac5fac88..e05f96b1 100644 --- a/packages/markdown-docx/src/ToCiceroMarkVisitor.js +++ b/packages/markdown-docx/src/ToCiceroMarkVisitor.js @@ -32,8 +32,11 @@ class ToCiceroMarkVisitor { // All the nodes generated from given OOXML this.nodes = []; - // contains the realtionship part of a given OOXML + // contains the relationship part of a given OOXML this.relationshipXML = []; + + // contains the nodes present in a conditional or optional OOXML + this.conditionalOrOptionalNodes = []; } /** @@ -64,7 +67,7 @@ class ToCiceroMarkVisitor { getName(variableProperties) { for (const property of variableProperties) { if (property.name === 'w:tag') { - return property.attributes['w:val']; + return property.attributes['w:val'].split('----')[1]; } } } @@ -87,7 +90,7 @@ class ToCiceroMarkVisitor { } /** - * Gets the node type based on the color property. + * Gets the node type based on the tag value. * * @param {Array} properties the variable elements * @returns {string} the type of the node @@ -95,11 +98,8 @@ class ToCiceroMarkVisitor { getNodeType(properties) { let nodeType = TRANSFORMED_NODES.variable; for (const property of properties) { - if (property.name === 'w15:color') { - // eg. "Shipper1 | org.accordproject.organization.Organization" - if (property.attributes['w:val'] === '99CCFF') { - nodeType = TRANSFORMED_NODES.clause; - } + if (property.name === 'w:tag') { + return property.attributes['w:val'].split('----')[0]; } } return nodeType; @@ -217,6 +217,17 @@ class ToCiceroMarkVisitor { $class: nodeInformation.properties[nodePropertyIndex], nodes: [ciceroMarkNode], }; + if (nodeInformation.properties[nodePropertyIndex] === TRANSFORMED_NODES.optional) { + let currentNodes = [...ciceroMarkNode.nodes]; + ciceroMarkNode = { + $class: TRANSFORMED_NODES.optional, + ...nodeInformation.optionalProperties, + whenSome: currentNodes, + whenNone: [], + hasSome: true, + nodes: currentNodes, + }; + } if (nodeInformation.properties[nodePropertyIndex] === TRANSFORMED_NODES.link) { ciceroMarkNode.title = ''; for (const relationshipElement of this.relationshipXML) { @@ -274,12 +285,19 @@ class ToCiceroMarkVisitor { ...rootNode.nodes[rootNodesLength - 1].nodes, constructedNode, ]; + if (propertiesCurrent[commonPropertiesLength - 1] === TRANSFORMED_NODES.optional) { + rootNode.nodes[rootNodesLength - 1].whenSome = rootNode.nodes[rootNodesLength - 1].nodes; + } } else if (commonPropertiesLength === 2) { const subNodeLength = rootNode.nodes[rootNodesLength - 1].nodes.length; rootNode.nodes[rootNodesLength - 1].nodes[subNodeLength - 1].nodes = [ ...rootNode.nodes[rootNodesLength - 1].nodes[subNodeLength - 1].nodes, constructedNode, ]; + if (propertiesCurrent[commonPropertiesLength - 1] === TRANSFORMED_NODES.optional) { + rootNode.nodes[rootNodesLength - 1].nodes[subNodeLength - 1].whenSome = + rootNode.nodes[rootNodesLength - 1].nodes[subNodeLength - 1].nodes; + } } else if (commonPropertiesLength === 3) { const subNodeLength = rootNode.nodes[rootNodesLength - 1].nodes.length; const deepSubNodeLength = rootNode.nodes[rootNodesLength - 1].nodes[subNodeLength - 1].nodes.length; @@ -288,6 +306,14 @@ class ToCiceroMarkVisitor { .nodes, constructedNode, ]; + if (propertiesCurrent[commonPropertiesLength - 1] === TRANSFORMED_NODES.optional) { + rootNode.nodes[rootNodesLength - 1].nodes[subNodeLength - 1].nodes[ + deepSubNodeLength - 1 + ].whenSome = + rootNode.nodes[rootNodesLength - 1].nodes[subNodeLength - 1].nodes[ + deepSubNodeLength - 1 + ].nodes; + } } } this.JSONXML = []; @@ -342,6 +368,10 @@ 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) { + ooxmlTagTextValue = runTimeNodes.elements ? runTimeNodes.elements[0].text : ' '; + nodeInformation.value = ooxmlTagTextValue; + this.conditionalOrOptionalNodes = [...this.conditionalOrOptionalNodes, nodeInformation]; } else { ooxmlTagTextValue = runTimeNodes.elements ? runTimeNodes.elements[0].text : ' '; nodeInformation.value = ooxmlTagTextValue; @@ -351,7 +381,11 @@ class ToCiceroMarkVisitor { ooxmlTagTextValue += '\n'; } else if (runTimeNodes.name === 'w:sym') { nodeInformation.nodeType = TRANSFORMED_NODES.softbreak; - this.JSONXML = [...this.JSONXML, nodeInformation]; + if (calledBy === TRANSFORMED_NODES.optional) { + this.conditionalOrOptionalNodes = [...this.conditionalOrOptionalNodes, nodeInformation]; + } else { + this.JSONXML = [...this.JSONXML, nodeInformation]; + } } } return ooxmlTagTextValue; @@ -469,14 +503,22 @@ class ToCiceroMarkVisitor { nodes, }; this.nodes = [...this.nodes, clauseNode]; + } else if (nodeInformation.nodeType === TRANSFORMED_NODES.optional) { + this.traverseElements(variableSubNodes.elements, TRANSFORMED_NODES.optional); + + for (let optionalNode of this.conditionalOrOptionalNodes) { + optionalNode.properties = [TRANSFORMED_NODES.optional, ...optionalNode.properties]; + optionalNode.optionalProperties = { + elementType: nodeInformation.elementType, + name: nodeInformation.name, + }; + this.JSONXML = [...this.JSONXML, { ...optionalNode }]; + } + this.conditionalOrOptionalNodes = []; } else { for (const variableContentNodes of variableSubNodes.elements) { if (variableContentNodes.name === 'w:r') { - this.fetchFormattingProperties( - variableContentNodes, - TRANSFORMED_NODES.paragraph, - nodeInformation - ); + this.fetchFormattingProperties(variableContentNodes, parent, nodeInformation); } } } diff --git a/packages/markdown-docx/src/ToOOXMLVisitor/index.js b/packages/markdown-docx/src/ToOOXMLVisitor/index.js index 28311bff..eb08bac1 100644 --- a/packages/markdown-docx/src/ToOOXMLVisitor/index.js +++ b/packages/markdown-docx/src/ToOOXMLVisitor/index.js @@ -31,6 +31,7 @@ const { CLAUSE_RULE, LINK_RULE, LINK_PROPERTY_RULE, + OPTIONAL_RULE, } = require('./rules'); const { wrapAroundDefaultDocxTags, wrapAroundLockedContentControls } = require('./helpers'); const { TRANSFORMED_NODES, RELATIONSHIP_OFFSET } = require('../constants'); @@ -51,6 +52,11 @@ class ToOOXMLVisitor { this.tags = []; // Relationship tags for links in a document this.relationships = []; + // Contains the tags for optional or conditional nodes. + // Optional/conditional themselves can act contain multiple inline nodes. + // However, they are not block elements and are present inside + // paragraph or clause nodes so an extra array is needed to store their info. + this.conditionalOrOptionalTags = []; } /** @@ -102,23 +108,55 @@ class ToOOXMLVisitor { return tag; } + /** + * Checks if an object contains the property and updates counter for it. + * + * @param {string} tag Tag of the property + * @param {string} type Type of the property + */ + generateCounter(tag, type) { + if (Object.prototype.hasOwnProperty.call(this.counter, tag)) { + this.counter = { + ...this.counter, + [tag]: { + ...this.counter[tag], + count: ++this.counter[tag].count, + }, + }; + } else { + this.counter[tag] = { + count: 1, + type, + }; + } + } + /** * Traverses CiceroMark nodes in a DFS approach * - * @param {object} node CiceroMark Node - * @param {array} properties Properties to be applied on current node + * @param {object} node CiceroMark Node + * @param {array} properties Properties to be applied on current node + * @param {boolean} isConditionalOrOptionalPresent True if the dfs traversal contains conditional or optional else false */ - traverseNodes(node, properties = []) { + traverseNodes(node, properties = [], isConditionalOrOptionalPresent = '') { if (this.getClass(node) === 'org.accordproject.commonmark.Document') { - this.traverseNodes(node.nodes, properties); + this.traverseNodes(node.nodes, properties, isConditionalOrOptionalPresent); } else { for (let subNode of node) { if (this.getClass(subNode) === TRANSFORMED_NODES.text) { const tag = this.generateTextOrCodeOOXML(subNode.text, properties); - this.tags = [...this.tags, tag]; + if (isConditionalOrOptionalPresent) { + this.conditionalOrOptionalTags = [...this.conditionalOrOptionalTags, tag]; + } else { + this.tags = [...this.tags, tag]; + } } else if (this.getClass(subNode) === TRANSFORMED_NODES.code) { const tag = this.generateTextOrCodeOOXML(subNode.text, properties, true); - this.tags = [...this.tags, tag]; + if (isConditionalOrOptionalPresent) { + this.conditionalOrOptionalTags = [...this.conditionalOrOptionalTags, tag]; + } else { + this.tags = [...this.tags, tag]; + } } else if (this.getClass(subNode) === TRANSFORMED_NODES.codeBlock) { let ooxml = CODEBLOCK_PROPERTIES_RULE(); let textValues = subNode.text.split('\n'); @@ -136,26 +174,24 @@ class ToOOXMLVisitor { } else if (this.getClass(subNode) === TRANSFORMED_NODES.variable) { const tag = subNode.name; const type = subNode.elementType; - if (Object.prototype.hasOwnProperty.call(this.counter, tag)) { - this.counter = { - ...this.counter, - [tag]: { - ...this.counter[tag], - count: ++this.counter[tag].count, - }, - }; - } else { - this.counter[tag] = { - count: 1, - type, - }; - } + this.generateCounter(tag, type); const value = subNode.value; const title = `${tag.toUpperCase()[0]}${tag.substring(1)}${this.counter[tag].count}`; - this.tags = [...this.tags, VARIABLE_RULE(title, tag, value, type)]; + if (isConditionalOrOptionalPresent) { + this.conditionalOrOptionalTags = [ + ...this.conditionalOrOptionalTags, + VARIABLE_RULE(title, tag, value, type), + ]; + } else { + this.tags = [...this.tags, VARIABLE_RULE(title, tag, value, type)]; + } } else if (this.getClass(subNode) === TRANSFORMED_NODES.softbreak) { - this.tags = [...this.tags, SOFTBREAK_RULE()]; + if (isConditionalOrOptionalPresent) { + this.conditionalOrOptionalTags = [...this.conditionalOrOptionalTags, SOFTBREAK_RULE()]; + } else { + this.tags = [...this.tags, SOFTBREAK_RULE()]; + } } else if (this.getClass(subNode) === TRANSFORMED_NODES.thematicBreak) { this.globalOOXML += THEMATICBREAK_RULE(); } else if (this.getClass(subNode) === TRANSFORMED_NODES.clause) { @@ -163,7 +199,7 @@ class ToOOXMLVisitor { if (subNode.nodes) { for (const deepNode of subNode.nodes) { if (this.getClass(deepNode) === TRANSFORMED_NODES.paragraph) { - this.traverseNodes(deepNode.nodes, properties); + this.traverseNodes(deepNode.nodes, properties, isConditionalOrOptionalPresent); let ooxml = ''; for (let xmlTag of this.tags) { ooxml += xmlTag; @@ -174,7 +210,7 @@ class ToOOXMLVisitor { // Clear all the tags as all nodes of paragraph have been traversed. this.tags = []; } else if (this.getClass(deepNode) === TRANSFORMED_NODES.heading) { - this.traverseNodes(deepNode.nodes, properties); + this.traverseNodes(deepNode.nodes, properties, isConditionalOrOptionalPresent); let ooxml = ''; for (let xmlTag of this.tags) { let headingPropertiesTag = ''; @@ -190,7 +226,7 @@ class ToOOXMLVisitor { this.tags = []; } else { let newProperties = [...properties, deepNode.$class]; - this.traverseNodes(deepNode.nodes, newProperties); + this.traverseNodes(deepNode.nodes, newProperties, isConditionalOrOptionalPresent); } } const tag = subNode.name; @@ -215,7 +251,7 @@ class ToOOXMLVisitor { } else { if (subNode.nodes) { if (this.getClass(subNode) === TRANSFORMED_NODES.paragraph) { - this.traverseNodes(subNode.nodes, properties); + this.traverseNodes(subNode.nodes, properties, isConditionalOrOptionalPresent); let ooxml = ''; for (let xmlTag of this.tags) { ooxml += xmlTag; @@ -226,7 +262,7 @@ class ToOOXMLVisitor { // Clear all the tags as all nodes of paragraph have been traversed. this.tags = []; } else if (this.getClass(subNode) === TRANSFORMED_NODES.heading) { - this.traverseNodes(subNode.nodes, properties); + this.traverseNodes(subNode.nodes, properties, isConditionalOrOptionalPresent); let ooxml = ''; for (let xmlTag of this.tags) { let headingPropertiesTag = ''; @@ -240,6 +276,18 @@ class ToOOXMLVisitor { this.globalOOXML += ooxml; this.tags = []; + } else if (this.getClass(subNode) === TRANSFORMED_NODES.optional) { + this.traverseNodes(subNode.nodes, properties, true); + const tag = subNode.name; + const type = subNode.elementType; + this.generateCounter(tag, type); + const title = `${tag.toUpperCase()[0]}${tag.substring(1)}${this.counter[tag].count}`; + let ooxml = ''; + for (let tag of this.conditionalOrOptionalTags) { + ooxml += tag; + } + let optionalTag = OPTIONAL_RULE(title, tag, ooxml, type); + this.tags = [...this.tags, optionalTag]; } else { if (this.getClass(subNode) === TRANSFORMED_NODES.link) { this.relationships = [ @@ -251,7 +299,7 @@ class ToOOXMLVisitor { ]; } let newProperties = [...properties, subNode.$class]; - this.traverseNodes(subNode.nodes, newProperties); + this.traverseNodes(subNode.nodes, newProperties, isConditionalOrOptionalPresent); } } } diff --git a/packages/markdown-docx/src/ToOOXMLVisitor/rules.js b/packages/markdown-docx/src/ToOOXMLVisitor/rules.js index 6620bb4a..b8d5a192 100644 --- a/packages/markdown-docx/src/ToOOXMLVisitor/rules.js +++ b/packages/markdown-docx/src/ToOOXMLVisitor/rules.js @@ -14,6 +14,7 @@ 'use strict'; +const { TRANSFORMED_NODES } = require('../constants'); const { sanitizeHtmlChars, titleGenerator } = require('./helpers'); /** @@ -135,7 +136,7 @@ const VARIABLE_RULE = (title, tag, value, type) => { - + @@ -220,7 +221,7 @@ const CLAUSE_RULE = (title, tag, type, content) => { - + ${content} @@ -248,6 +249,30 @@ const LINK_RULE = (value, relationshipId) => { `; }; +/** + * 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 + * @param {string} type Type of the optional node - Long, Double, etc. + * @returns {string} OOXML string for the variable + */ +const OPTIONAL_RULE = (title, tag, value, type) => { + return ` + + + + + + + + ${value} + + + `; +}; + module.exports = { TEXT_RULE, EMPHASIS_RULE, @@ -265,4 +290,5 @@ module.exports = { CLAUSE_RULE, LINK_PROPERTY_RULE, LINK_RULE, + OPTIONAL_RULE, }; diff --git a/packages/markdown-docx/src/constants.js b/packages/markdown-docx/src/constants.js index 844ee40a..88aeba7e 100644 --- a/packages/markdown-docx/src/constants.js +++ b/packages/markdown-docx/src/constants.js @@ -21,6 +21,7 @@ const TRANSFORMED_NODES = { code: `${NS_PREFIX_CommonMarkModel}Code`, codeBlock: `${NS_PREFIX_CommonMarkModel}CodeBlock`, computedVariable: `${NS_PREFIX_CiceroMarkModel}ComputedVariable`, + optional: `${NS_PREFIX_CiceroMarkModel}Optional`, document: `${NS_PREFIX_CommonMarkModel}Document`, emphasize: `${NS_PREFIX_CommonMarkModel}Emph`, heading: `${NS_PREFIX_CommonMarkModel}Heading`, diff --git a/packages/markdown-docx/test/data/ciceroMark/optional.json b/packages/markdown-docx/test/data/ciceroMark/optional.json new file mode 100644 index 00000000..cf023cec --- /dev/null +++ b/packages/markdown-docx/test/data/ciceroMark/optional.json @@ -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.Optional","hasSome":true,"whenSome":[{"$class":"org.accordproject.commonmark.Text","text":" except for Force Majeure cases in a "},{"$class":"org.accordproject.ciceromark.Variable","value":"100.0","name":"miles","elementType":"Double"},{"$class":"org.accordproject.commonmark.Text","text":" miles radius,"}],"whenNone":[],"name":"forceMajeure","elementType":"org.accordproject.latedeliveryandpenalty.Distance","nodes":[{"$class":"org.accordproject.commonmark.Text","text":" except for Force Majeure cases in a "},{"$class":"org.accordproject.ciceromark.Variable","value":"100.0","name":"miles","elementType":"Double"},{"$class":"org.accordproject.commonmark.Text","text":" miles radius,"}]},{"$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."}]}]} \ No newline at end of file diff --git a/packages/markdown-docx/test/data/ooxml/acceptance-of-delivery.xml b/packages/markdown-docx/test/data/ooxml/acceptance-of-delivery.xml index 4af6e2fb..9e706dd5 100644 --- a/packages/markdown-docx/test/data/ooxml/acceptance-of-delivery.xml +++ b/packages/markdown-docx/test/data/ooxml/acceptance-of-delivery.xml @@ -1,5 +1,705 @@ - - - - -Acceptance of Delivery."Party A" will be deemed to have completed its delivery obligationsif in "Party B"'s opinion, the "Widgets" satisfies theAcceptance Criteria, and "Party B" notifies "Party A" in writingthat it is accepting the "Widgets".Inspection and Notice."Party B" will have 10 Business Days to inspect andevaluate the "Widgets" on the delivery date before notifying"Party A" that it is either accepting or rejecting the"Widgets".Acceptance Criteria.The "Acceptance Criteria" are the specifications the "Widgets"must meet for the "Party A" to comply with its requirements andobligations under this agreement, detailed in "Attachment X", attachedto this agreement. \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Acceptance of Delivery. + + + + + + + + + + + + + + + + + + + + "Party A" + + + + + + + + will be deemed to have completed its delivery obligations + + + + + + + + + + if in + + + + + + + + + + + + + + + + "Party B" + + + + + + + + 's opinion, the + + + + + + + + + + + + + + + + "Widgets" + + + + + + + + satisfies the + + + + + + + + + + Acceptance Criteria, and + + + + + + + + + + + + + + + + "Party B" + + + + + + + + notifies + + + + + + + + + + + + + + + + "Party A" + + + + + + + + in writing + + + + + + + + + + that it is accepting the + + + + + + + + + + + + + + + + "Widgets" + + + + + + + + . + + + + + + + + + + + + + + Inspection and Notice. + + + + + + + + + + + + + + + + + + + + "Party B" + + + + + + + + will have + + + + + + + + + + + + + + + + 10 + + + + + + + + Business Days to inspect and + + + + + + + + + + evaluate the + + + + + + + + + + + + + + + + "Widgets" + + + + + + + + on the delivery date before notifying + + + + + + + + + + + + + + + + + + + + "Party A" + + + + + + + + that it is either accepting or rejecting the + + + + + + + + + + + + + + + + + + + + "Widgets" + + + + + + + + . + + + + + + + + + + + + + + Acceptance Criteria. + + + + + + + + + + The "Acceptance Criteria" are the specifications the + + + + + + + + + + + + + + + + "Widgets" + + + + + + + + + + + + must meet for the + + + + + + + + + + + + + + + + "Party A" + + + + + + + + to comply with its requirements and + + + + + + + + + + obligations under this agreement, detailed in + + + + + + + + + + + + + + + + "Attachment X" + + + + + + + + , attached + + + + + + + + + + to this agreement. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/markdown-transform/test/data/acceptance/omitted-acceptance-of-delivery.xml b/packages/markdown-transform/test/data/acceptance/omitted-acceptance-of-delivery.xml index 5c61ef8a..9e706dd5 100644 --- a/packages/markdown-transform/test/data/acceptance/omitted-acceptance-of-delivery.xml +++ b/packages/markdown-transform/test/data/acceptance/omitted-acceptance-of-delivery.xml @@ -71,7 +71,7 @@ - + @@ -105,7 +105,7 @@ - + @@ -129,7 +129,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -187,7 +187,7 @@ - + @@ -221,7 +221,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -287,7 +287,7 @@ - + @@ -321,7 +321,7 @@ - + @@ -349,7 +349,7 @@ - + @@ -377,7 +377,7 @@ - + @@ -425,7 +425,7 @@ - + @@ -453,7 +453,7 @@ - + @@ -487,7 +487,7 @@ - +