From 7651099cfb5b25e142ce63c4a2e40f0256dc0404 Mon Sep 17 00:00:00 2001 From: Kushal Kumar <59891164+K-Kumar-01@users.noreply.github.com> Date: Fri, 11 Jun 2021 17:20:20 +0530 Subject: [PATCH] feat: add text and emphasis transformers - #397 (#401) --- .../src/CiceroMarkToOOXML/helpers.js | 88 ++++++++++++++ .../src/CiceroMarkToOOXML/index.js | 109 ++++++++++++++++++ .../src/CiceroMarkToOOXML/index.test.js | 43 +++++++ .../src/CiceroMarkToOOXML/rules.js | 50 ++++++++ .../src/CiceroMarkToOOXMLTransformer.js | 49 -------- .../index.js} | 15 +++ .../index.test.js} | 2 +- packages/markdown-docx/src/index.js | 17 +++ .../data/ciceroMark/text-and-emphasis.json | 1 + 9 files changed, 324 insertions(+), 50 deletions(-) create mode 100644 packages/markdown-docx/src/CiceroMarkToOOXML/helpers.js create mode 100644 packages/markdown-docx/src/CiceroMarkToOOXML/index.js create mode 100644 packages/markdown-docx/src/CiceroMarkToOOXML/index.test.js create mode 100644 packages/markdown-docx/src/CiceroMarkToOOXML/rules.js delete mode 100644 packages/markdown-docx/src/CiceroMarkToOOXMLTransformer.js rename packages/markdown-docx/src/{OoxmlTransformer.js => OOXMLTransformer/index.js} (92%) rename packages/markdown-docx/src/{OoxmlTransformer.test.js => OOXMLTransformer/index.test.js} (95%) create mode 100644 packages/markdown-docx/src/index.js create mode 100644 packages/markdown-docx/test/data/ciceroMark/text-and-emphasis.json diff --git a/packages/markdown-docx/src/CiceroMarkToOOXML/helpers.js b/packages/markdown-docx/src/CiceroMarkToOOXML/helpers.js new file mode 100644 index 00000000..a7f1ae06 --- /dev/null +++ b/packages/markdown-docx/src/CiceroMarkToOOXML/helpers.js @@ -0,0 +1,88 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +/** + * Replaces the angular brackets with the respective codes. + * + * @param {string} node String to be replaced + * @returns {string} String with replaced angular brackets + */ +function sanitizeHtmlChars(node) { + return node.replace(/>/g, '>').replace(/ + + + + + + + + + + + + ${ooxml} + + + + + + `; + + return ooxml; +} + +module.exports = { sanitizeHtmlChars, wrapAroundDefaultDocxTags }; diff --git a/packages/markdown-docx/src/CiceroMarkToOOXML/index.js b/packages/markdown-docx/src/CiceroMarkToOOXML/index.js new file mode 100644 index 00000000..86629091 --- /dev/null +++ b/packages/markdown-docx/src/CiceroMarkToOOXML/index.js @@ -0,0 +1,109 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const { TEXT_RULE, EMPHASIS_RULE } = require('./rules'); +const { wrapAroundDefaultDocxTags } = require('./helpers'); + +const definedNodes = { + computedVariable: 'org.accordproject.ciceromark.ComputedVariable', + heading: 'org.accordproject.commonmark.Heading', + item: 'org.accordproject.commonmark.Item', + list: 'org.accordproject.commonmark.List', + listBlock: 'org.accordproject.ciceromark.ListBlock', + paragraph: 'org.accordproject.commonmark.Paragraph', + softbreak: 'org.accordproject.commonmark.Softbreak', + text: 'org.accordproject.commonmark.Text', + variable: 'org.accordproject.ciceromark.Variable', + emphasize: 'org.accordproject.commonmark.Emph', +}; + +/** + * Transforms the ciceromark to OOXML + */ +class CiceroMarkToOOXMLTransfomer { + + + /** + * Declares the OOXML variable + */ + constructor() { + this.globalOOXML = ''; + } + + /** + * Gets the class of a given CiceroMark node. + * + * @param {object} node CiceroMark node entity + * @returns {string} Class of given node + */ + getClass(node) { + return node.$class; + } + + /** + * Gets the OOXML for the given node. + * + * @param {object} node Description of node type + * @param {object} counter Counter for different variables based on node name + * @param {object} parent Parent object for a node + * @returns {string} OOXML for the given node + */ + getNodes(node, counter, parent = null) { + if (this.getClass(node) === definedNodes.text) { + if (parent !== null && parent.class === definedNodes.emphasize) { + return EMPHASIS_RULE(node.text, true); + } else { + return TEXT_RULE(node.text); + } + } + + if (this.getClass(node) === definedNodes.emphasize) { + let ooxml = ''; + node.nodes.forEach(subNode => { + ooxml += this.getNodes(subNode, counter, { class: node.$class }); + }); + return ooxml; + } + + if (this.getClass(node) === definedNodes.paragraph) { + let ooxml = ''; + node.nodes.forEach(subNode => { + ooxml += this.getNodes(subNode, counter,); + }); + this.globalOOXML = `${this.globalOOXML}${ooxml}`; + } + return ''; + } + + /** + * Transforms the given CiceroMark JSON to OOXML + * + * @param {Object} ciceromark CiceroMark JSON to be converted + * @param {Object} counter Counter for different variables based on node name + * @param {string} ooxml Initial OOXML string + * @returns {string} Converted OOXML string i.e. CicecoMark->OOXML + */ + toOOXML(ciceromark, counter, ooxml = '') { + this.globalOOXML = ooxml; + ciceromark.nodes.forEach(node => { + this.getNodes(node, counter); + }); + this.globalOOXML = wrapAroundDefaultDocxTags(this.globalOOXML); + return this.globalOOXML; + } +} + +module.exports = CiceroMarkToOOXMLTransfomer; diff --git a/packages/markdown-docx/src/CiceroMarkToOOXML/index.test.js b/packages/markdown-docx/src/CiceroMarkToOOXML/index.test.js new file mode 100644 index 00000000..233f5cf5 --- /dev/null +++ b/packages/markdown-docx/src/CiceroMarkToOOXML/index.test.js @@ -0,0 +1,43 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-nocheck +/* eslint-disable no-undef */ +'use strict'; + +const fs = require('fs'); +const chai = require('chai'); + +const expect = chai.expect; + +const OoxmlTransformer = require('../OOXMLTransformer'); +const CiceroMarkToOOXMLTransfomer = require('.'); + +describe('Perform roundtripping between CiceroMark and OOXML', () => { + it('should parse textgraphs and emphasis nodes.', async () => { + let textAndEmphasisCiceroMark = await fs.readFileSync( + 'test/data/ciceroMark/text-and-emphasis.json', + 'utf-8' + ); + // converts from string to JSON object + textAndEmphasisCiceroMark = JSON.parse(textAndEmphasisCiceroMark); + + const ciceroMarkTransformer = new CiceroMarkToOOXMLTransfomer(); + const ooxml = ciceroMarkTransformer.toOOXML(textAndEmphasisCiceroMark); + + const ooxmlTransformer = new OoxmlTransformer(); + const convertedObject = ooxmlTransformer.toCiceroMark(ooxml); + expect(convertedObject).to.deep.equal(textAndEmphasisCiceroMark); + }); +}); diff --git a/packages/markdown-docx/src/CiceroMarkToOOXML/rules.js b/packages/markdown-docx/src/CiceroMarkToOOXML/rules.js new file mode 100644 index 00000000..d9ff161f --- /dev/null +++ b/packages/markdown-docx/src/CiceroMarkToOOXML/rules.js @@ -0,0 +1,50 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const { sanitizeHtmlChars } = require('./helpers'); + +/** + * Inserts text. + * + * @param {string} value Enclosing value of the OOXML tag + * @returns {string} OOXML tag for the text + */ +const TEXT_RULE = (value) => { + return ` + + ${sanitizeHtmlChars(value)} + + `; +}; + +/** + * Inserts emphasised text. + * + * @param {string} value Enclosing value of the OOXML tag + * @returns {string} OOXML tag for the emphasised text + */ +const EMPHASIS_RULE = (value) => { + return ` + + + + + ${sanitizeHtmlChars(value)} + + `; +}; + +module.exports = { TEXT_RULE, EMPHASIS_RULE }; diff --git a/packages/markdown-docx/src/CiceroMarkToOOXMLTransformer.js b/packages/markdown-docx/src/CiceroMarkToOOXMLTransformer.js deleted file mode 100644 index c6335689..00000000 --- a/packages/markdown-docx/src/CiceroMarkToOOXMLTransformer.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -/** - * Transforms the ciceromark to OOXML - */ -class CiceroMarkToOOXMLTransfomer { - - definedNodes = { - computedVariable: 'org.accordproject.ciceromark.ComputedVariable', - heading: 'org.accordproject.commonmark.Heading', - item: 'org.accordproject.commonmark.Item', - list: 'org.accordproject.commonmark.List', - listBlock: 'org.accordproject.ciceromark.ListBlock', - paragraph: 'org.accordproject.commonmark.Paragraph', - softbreak: 'org.accordproject.commonmark.Softbreak', - text: 'org.accordproject.commonmark.Text', - variable: 'org.accordproject.ciceromark.Variable', - emphasize: 'org.accordproject.commonmark.Emph', - }; - - /** - * Transforms the given CiceroMark JSON to OOXML - * - * @param {Object} ciceromark CiceroMark JSON to be converted - * @param {Object} counter Counter for different variables based on node name - * @param {string} ooxml Initial OOXML string - * @returns {string} Converted OOXML string i.e. CicecoMark->OOXML - */ - toOOXML(ciceromark, counter, ooxml) { - let globalOOXML = ooxml; - return globalOOXML; - } -} - -module.exports = CiceroMarkToOOXMLTransfomer; \ No newline at end of file diff --git a/packages/markdown-docx/src/OoxmlTransformer.js b/packages/markdown-docx/src/OOXMLTransformer/index.js similarity index 92% rename from packages/markdown-docx/src/OoxmlTransformer.js rename to packages/markdown-docx/src/OOXMLTransformer/index.js index 2fcde302..b6af73d2 100644 --- a/packages/markdown-docx/src/OoxmlTransformer.js +++ b/packages/markdown-docx/src/OOXMLTransformer/index.js @@ -151,6 +151,21 @@ class OoxmlTransformer { $class: `${NS_PREFIX_CommonMarkModel}Softbreak`, }; case 'w:r': + if (element.elements[0].name === 'w:rPr') { + let emphasisedTextFound = element.elements[0].elements.some( + subElement => { + return subElement.name === 'w:i'; + } + ); + if (emphasisedTextFound) { + return { + $class: `${NS_PREFIX_CommonMarkModel}Emph`, + nodes: [ + ...this.deserializeElements(element.elements), + ], + }; + } + } return [...this.deserializeElements(element.elements)]; case 'w:color': return element.attributes['w:color']; diff --git a/packages/markdown-docx/src/OoxmlTransformer.test.js b/packages/markdown-docx/src/OOXMLTransformer/index.test.js similarity index 95% rename from packages/markdown-docx/src/OoxmlTransformer.test.js rename to packages/markdown-docx/src/OOXMLTransformer/index.test.js index 5fe7c24c..f0740bb7 100644 --- a/packages/markdown-docx/src/OoxmlTransformer.test.js +++ b/packages/markdown-docx/src/OOXMLTransformer/index.test.js @@ -19,7 +19,7 @@ const chai = require('chai'); const expect = chai.expect; -const OoxmlTransformer = require('./OoxmlTransformer'); +const OoxmlTransformer = require('.'); describe('OOXML -> CiceroMark', () => { diff --git a/packages/markdown-docx/src/index.js b/packages/markdown-docx/src/index.js new file mode 100644 index 00000000..ed611a3f --- /dev/null +++ b/packages/markdown-docx/src/index.js @@ -0,0 +1,17 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +module.exports.CiceroMarkToOOXMLTransfomer= require('./CiceroMarkToOOXML'); diff --git a/packages/markdown-docx/test/data/ciceroMark/text-and-emphasis.json b/packages/markdown-docx/test/data/ciceroMark/text-and-emphasis.json new file mode 100644 index 00000000..b1198879 --- /dev/null +++ b/packages/markdown-docx/test/data/ciceroMark/text-and-emphasis.json @@ -0,0 +1 @@ +{"$class":"org.accordproject.commonmark.Document","xmlns":"http://commonmark.org/xml/1.0","nodes":[{"$class":"org.accordproject.commonmark.Paragraph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"Hello and Welcome to the testing round. Today we try "},{"$class":"org.accordproject.commonmark.Emph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"testing"}]},{"$class":"org.accordproject.commonmark.Text","text":" of the converters."}]},{"$class":"org.accordproject.commonmark.Paragraph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"Let\"s start with the basic testing of the converters."}]},{"$class":"org.accordproject.commonmark.Paragraph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"The Accord Project is a non-profit, collaborative, initiative developing an ecosystem and open source tools specifically for smart legal contracts. Open source means that anyone can freely use and contribute to development."}]},{"$class":"org.accordproject.commonmark.Paragraph","nodes":[{"$class":"org.accordproject.commonmark.Text","text":"We hope to see many more successful tests."}]}]} \ No newline at end of file