Skip to content

Algoo ooxml #400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 130 additions & 15 deletions packages/markdown-docx/src/CiceroMarkToOOXMLTransformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,134 @@

'use strict';

const { TEXT_RULE } = require('./rules');

/**
* 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',
};
/**
* Declares the nodes and global OOXML.
*/
constructor(){
this.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',
};
Comment on lines +28 to +39
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this out of the class if eslint cannot parse this as a class variable.

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) === this.definedNodes.text) {
if (parent !== null && parent.class === this.definedNodes.emphasize) {
return TEXT_RULE(node.text, true);
} else {
return TEXT_RULE(node.text);
}
}

if (this.getClass(node) === this.definedNodes.emphasize) {
let ooxml = '';
node.nodes.forEach(subNode => {
ooxml += this.getNodes(subNode, counter, { class: node.$class });
});
return ooxml;
}

if (this.getClass(node) === this.definedNodes.paragraph) {
let ooxml = '';
node.nodes.forEach(subNode => {
ooxml += this.getNodes(subNode, counter, );
});
this.globalOOXML = `${this.globalOOXML}<w:p>${ooxml}</w:p>`;
}
return '';
}

/**
* Wraps OOXML in docx headers.
*
* @param {string} ooxml OOXML to be wrapped
*/
wrapOOXML(ooxml){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are exactly the kind of methods that should be in helpers./utils.

this.globalOOXML = `<pkg:package
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">
<pkg:part pkg:name="/_rels/.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="512">
<pkg:xmlData>
<Relationships
xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
</Relationships>
</pkg:xmlData>
</pkg:part>
<pkg:part pkg:name="/word/document.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml">
<pkg:xmlData>
<w:document
xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex"
xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex"
xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex"
xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex"
xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex"
xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex"
xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex"
xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex"
xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink"
xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
xmlns:w10="urn:schemas-microsoft-com:office:word"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"
xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid wp14">
<w:body>
${ooxml}
<w:p/>
</w:body>
</w:document>
</pkg:xmlData>
</pkg:part>
</pkg:package>`;
}

/**
* Transforms the given CiceroMark JSON to OOXML
Expand All @@ -40,9 +151,13 @@ class CiceroMarkToOOXMLTransfomer {
* @param {string} ooxml Initial OOXML string
* @returns {string} Converted OOXML string i.e. CicecoMark->OOXML
*/
toOOXML(ciceromark, counter, ooxml) {
let globalOOXML = ooxml;
return globalOOXML;
toOOXML(ciceromark, counter, ooxml = '') {
this.globalOOXML = ooxml;
ciceromark.nodes.forEach(node => {
this.getNodes(node, counter);
});
this.wrapOOXML(this.globalOOXML);
return this.globalOOXML;
}
}

Expand Down
91 changes: 91 additions & 0 deletions packages/markdown-docx/src/CiceroMarkToOOXMLTransformer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* 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 chai = require('chai');

const expect = chai.expect;

const OoxmlTransformer = require('./OoxmlTransformer');
const CiceroMarkToOOXMLTransfomer = require('./CiceroMarkToOOXMLTransformer');

describe('Round Tripping', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should be descriptive here. Maybe something like "perform roundtripping between CiceroMark and OOXML ". I can give you a reason for this as well. When you run the entire test suite, and suppose this fails, you will have this name handy to know where it failed.


it('Pargaphs and emphasis', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reword this to should parse paragraphs and emphasis nodes.

Also, there is a typographical error in "paragraphs". If you are prone to them, I suggest you to install a VSCode extension, or if your computer specification allows, switch to an IDE like WebStorm.

const ciceroMarkJSON = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can put this entire JSON object in the test resources directory.

'$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.'
}
]
}
]
};
const ciceroMarkTransformer = new CiceroMarkToOOXMLTransfomer();
const ooxml = ciceroMarkTransformer.toOOXML(ciceroMarkJSON);

const ooxmlTransformer = new OoxmlTransformer();
const convertedObject = ooxmlTransformer.toCiceroMark(ooxml);
expect(convertedObject).to.deep.equal(ciceroMarkJSON);
});
});
11 changes: 11 additions & 0 deletions packages/markdown-docx/src/OoxmlTransformer.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,17 @@ class OoxmlTransformer {
$class: `${NS_PREFIX_CommonMarkModel}Softbreak`,
};
case 'w:r':
if(element.elements[0].name==='w:rPr'){
let emphFound = element.elements[0].elements.some(subElement=>{
return subElement.name==='w:i' && subElement.attributes['w:val'] === 'true';
});
if(emphFound){
return {
$class: `${NS_PREFIX_CommonMarkModel}Emph`,
nodes:[...this.deserializeElements(element.elements)]
};
}
}
return [...this.deserializeElements(element.elements)];
case 'w:color':
return element.attributes['w:color'];
Expand Down
27 changes: 27 additions & 0 deletions packages/markdown-docx/src/helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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, '&gt;').replace(/</g, '&lt;');
}

module.exports = { sanitizeHtmlChars };
33 changes: 33 additions & 0 deletions packages/markdown-docx/src/rules.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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 Text to be rendered
* @param {boolean} emphasize true=emphasized text, false=normal text
* @returns {string} OOXML for the text
*/
const TEXT_RULE = (value, emphasize = false) => {
if (emphasize) {
return `<w:r><w:rPr><w:i w:val="true" /></w:rPr><w:t>${sanitizeHtmlChars(value)}</w:t></w:r>`;
}
return `<w:r><w:t xml:space="preserve">${sanitizeHtmlChars(value)}</w:t></w:r>`;
};

module.exports = { TEXT_RULE };