Skip to content

Commit a23129f

Browse files
authored
feat: add text and emphasis transformers - #397 (#401)
1 parent 4233d14 commit a23129f

File tree

9 files changed

+324
-50
lines changed

9 files changed

+324
-50
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
'use strict';
16+
17+
/**
18+
* Replaces the angular brackets with the respective codes.
19+
*
20+
* @param {string} node String to be replaced
21+
* @returns {string} String with replaced angular brackets
22+
*/
23+
function sanitizeHtmlChars(node) {
24+
return node.replace(/>/g, '&gt;').replace(/</g, '&lt;');
25+
}
26+
27+
/**
28+
* Wraps OOXML in docx headers.
29+
*
30+
* @param {string} ooxml OOXML to be wrapped
31+
* @returns {string} OOXML wraped in docx headers
32+
*/
33+
function wrapAroundDefaultDocxTags(ooxml) {
34+
ooxml = `<pkg:package
35+
xmlns:pkg="http://schemas.microsoft.com/office/2006/xmlPackage">
36+
<pkg:part pkg:name="/_rels/.rels" pkg:contentType="application/vnd.openxmlformats-package.relationships+xml" pkg:padding="512">
37+
<pkg:xmlData>
38+
<Relationships
39+
xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
40+
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
41+
</Relationships>
42+
</pkg:xmlData>
43+
</pkg:part>
44+
<pkg:part pkg:name="/word/document.xml" pkg:contentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml">
45+
<pkg:xmlData>
46+
<w:document
47+
xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas"
48+
xmlns:cx="http://schemas.microsoft.com/office/drawing/2014/chartex"
49+
xmlns:cx1="http://schemas.microsoft.com/office/drawing/2015/9/8/chartex"
50+
xmlns:cx2="http://schemas.microsoft.com/office/drawing/2015/10/21/chartex"
51+
xmlns:cx3="http://schemas.microsoft.com/office/drawing/2016/5/9/chartex"
52+
xmlns:cx4="http://schemas.microsoft.com/office/drawing/2016/5/10/chartex"
53+
xmlns:cx5="http://schemas.microsoft.com/office/drawing/2016/5/11/chartex"
54+
xmlns:cx6="http://schemas.microsoft.com/office/drawing/2016/5/12/chartex"
55+
xmlns:cx7="http://schemas.microsoft.com/office/drawing/2016/5/13/chartex"
56+
xmlns:cx8="http://schemas.microsoft.com/office/drawing/2016/5/14/chartex"
57+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
58+
xmlns:aink="http://schemas.microsoft.com/office/drawing/2016/ink"
59+
xmlns:am3d="http://schemas.microsoft.com/office/drawing/2017/model3d"
60+
xmlns:o="urn:schemas-microsoft-com:office:office"
61+
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
62+
xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"
63+
xmlns:v="urn:schemas-microsoft-com:vml"
64+
xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing"
65+
xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing"
66+
xmlns:w10="urn:schemas-microsoft-com:office:word"
67+
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
68+
xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml"
69+
xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml"
70+
xmlns:w16cid="http://schemas.microsoft.com/office/word/2016/wordml/cid"
71+
xmlns:w16se="http://schemas.microsoft.com/office/word/2015/wordml/symex"
72+
xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup"
73+
xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk"
74+
xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml"
75+
xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" mc:Ignorable="w14 w15 w16se w16cid wp14">
76+
<w:body>
77+
${ooxml}
78+
<w:p/>
79+
</w:body>
80+
</w:document>
81+
</pkg:xmlData>
82+
</pkg:part>
83+
</pkg:package>`;
84+
85+
return ooxml;
86+
}
87+
88+
module.exports = { sanitizeHtmlChars, wrapAroundDefaultDocxTags };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
'use strict';
16+
17+
const { TEXT_RULE, EMPHASIS_RULE } = require('./rules');
18+
const { wrapAroundDefaultDocxTags } = require('./helpers');
19+
20+
const definedNodes = {
21+
computedVariable: 'org.accordproject.ciceromark.ComputedVariable',
22+
heading: 'org.accordproject.commonmark.Heading',
23+
item: 'org.accordproject.commonmark.Item',
24+
list: 'org.accordproject.commonmark.List',
25+
listBlock: 'org.accordproject.ciceromark.ListBlock',
26+
paragraph: 'org.accordproject.commonmark.Paragraph',
27+
softbreak: 'org.accordproject.commonmark.Softbreak',
28+
text: 'org.accordproject.commonmark.Text',
29+
variable: 'org.accordproject.ciceromark.Variable',
30+
emphasize: 'org.accordproject.commonmark.Emph',
31+
};
32+
33+
/**
34+
* Transforms the ciceromark to OOXML
35+
*/
36+
class CiceroMarkToOOXMLTransfomer {
37+
38+
39+
/**
40+
* Declares the OOXML variable
41+
*/
42+
constructor() {
43+
this.globalOOXML = '';
44+
}
45+
46+
/**
47+
* Gets the class of a given CiceroMark node.
48+
*
49+
* @param {object} node CiceroMark node entity
50+
* @returns {string} Class of given node
51+
*/
52+
getClass(node) {
53+
return node.$class;
54+
}
55+
56+
/**
57+
* Gets the OOXML for the given node.
58+
*
59+
* @param {object} node Description of node type
60+
* @param {object} counter Counter for different variables based on node name
61+
* @param {object} parent Parent object for a node
62+
* @returns {string} OOXML for the given node
63+
*/
64+
getNodes(node, counter, parent = null) {
65+
if (this.getClass(node) === definedNodes.text) {
66+
if (parent !== null && parent.class === definedNodes.emphasize) {
67+
return EMPHASIS_RULE(node.text, true);
68+
} else {
69+
return TEXT_RULE(node.text);
70+
}
71+
}
72+
73+
if (this.getClass(node) === definedNodes.emphasize) {
74+
let ooxml = '';
75+
node.nodes.forEach(subNode => {
76+
ooxml += this.getNodes(subNode, counter, { class: node.$class });
77+
});
78+
return ooxml;
79+
}
80+
81+
if (this.getClass(node) === definedNodes.paragraph) {
82+
let ooxml = '';
83+
node.nodes.forEach(subNode => {
84+
ooxml += this.getNodes(subNode, counter,);
85+
});
86+
this.globalOOXML = `${this.globalOOXML}<w:p>${ooxml}</w:p>`;
87+
}
88+
return '';
89+
}
90+
91+
/**
92+
* Transforms the given CiceroMark JSON to OOXML
93+
*
94+
* @param {Object} ciceromark CiceroMark JSON to be converted
95+
* @param {Object} counter Counter for different variables based on node name
96+
* @param {string} ooxml Initial OOXML string
97+
* @returns {string} Converted OOXML string i.e. CicecoMark->OOXML
98+
*/
99+
toOOXML(ciceromark, counter, ooxml = '') {
100+
this.globalOOXML = ooxml;
101+
ciceromark.nodes.forEach(node => {
102+
this.getNodes(node, counter);
103+
});
104+
this.globalOOXML = wrapAroundDefaultDocxTags(this.globalOOXML);
105+
return this.globalOOXML;
106+
}
107+
}
108+
109+
module.exports = CiceroMarkToOOXMLTransfomer;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
// @ts-nocheck
16+
/* eslint-disable no-undef */
17+
'use strict';
18+
19+
const fs = require('fs');
20+
const chai = require('chai');
21+
22+
const expect = chai.expect;
23+
24+
const OoxmlTransformer = require('../OOXMLTransformer');
25+
const CiceroMarkToOOXMLTransfomer = require('.');
26+
27+
describe('Perform roundtripping between CiceroMark and OOXML', () => {
28+
it('should parse textgraphs and emphasis nodes.', async () => {
29+
let textAndEmphasisCiceroMark = await fs.readFileSync(
30+
'test/data/ciceroMark/text-and-emphasis.json',
31+
'utf-8'
32+
);
33+
// converts from string to JSON object
34+
textAndEmphasisCiceroMark = JSON.parse(textAndEmphasisCiceroMark);
35+
36+
const ciceroMarkTransformer = new CiceroMarkToOOXMLTransfomer();
37+
const ooxml = ciceroMarkTransformer.toOOXML(textAndEmphasisCiceroMark);
38+
39+
const ooxmlTransformer = new OoxmlTransformer();
40+
const convertedObject = ooxmlTransformer.toCiceroMark(ooxml);
41+
expect(convertedObject).to.deep.equal(textAndEmphasisCiceroMark);
42+
});
43+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
'use strict';
16+
17+
const { sanitizeHtmlChars } = require('./helpers');
18+
19+
/**
20+
* Inserts text.
21+
*
22+
* @param {string} value Enclosing value of the OOXML tag
23+
* @returns {string} OOXML tag for the text
24+
*/
25+
const TEXT_RULE = (value) => {
26+
return `
27+
<w:r>
28+
<w:t xml:space="preserve">${sanitizeHtmlChars(value)}</w:t>
29+
</w:r>
30+
`;
31+
};
32+
33+
/**
34+
* Inserts emphasised text.
35+
*
36+
* @param {string} value Enclosing value of the OOXML tag
37+
* @returns {string} OOXML tag for the emphasised text
38+
*/
39+
const EMPHASIS_RULE = (value) => {
40+
return `
41+
<w:r>
42+
<w:rPr>
43+
<w:i />
44+
</w:rPr>
45+
<w:t>${sanitizeHtmlChars(value)}</w:t>
46+
</w:r>
47+
`;
48+
};
49+
50+
module.exports = { TEXT_RULE, EMPHASIS_RULE };

packages/markdown-docx/src/CiceroMarkToOOXMLTransformer.js

-49
This file was deleted.

packages/markdown-docx/src/OoxmlTransformer.js packages/markdown-docx/src/OOXMLTransformer/index.js

+15
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,21 @@ class OoxmlTransformer {
151151
$class: `${NS_PREFIX_CommonMarkModel}Softbreak`,
152152
};
153153
case 'w:r':
154+
if (element.elements[0].name === 'w:rPr') {
155+
let emphasisedTextFound = element.elements[0].elements.some(
156+
subElement => {
157+
return subElement.name === 'w:i';
158+
}
159+
);
160+
if (emphasisedTextFound) {
161+
return {
162+
$class: `${NS_PREFIX_CommonMarkModel}Emph`,
163+
nodes: [
164+
...this.deserializeElements(element.elements),
165+
],
166+
};
167+
}
168+
}
154169
return [...this.deserializeElements(element.elements)];
155170
case 'w:color':
156171
return element.attributes['w:color'];

packages/markdown-docx/src/OoxmlTransformer.test.js packages/markdown-docx/src/OOXMLTransformer/index.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const chai = require('chai');
1919

2020
const expect = chai.expect;
2121

22-
const OoxmlTransformer = require('./OoxmlTransformer');
22+
const OoxmlTransformer = require('.');
2323

2424
describe('OOXML -> CiceroMark', () => {
2525

packages/markdown-docx/src/index.js

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
'use strict';
16+
17+
module.exports.CiceroMarkToOOXMLTransfomer= require('./CiceroMarkToOOXML');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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."}]}]}

0 commit comments

Comments
 (0)