Skip to content

Commit 1c569bf

Browse files
authored
feat(markdown-docx): add codeblock transformer - #397 (#430)
Signed-off-by: k-kumar-01 <[email protected]>
1 parent 2b617d1 commit 1c569bf

File tree

5 files changed

+116
-6
lines changed

5 files changed

+116
-6
lines changed

packages/markdown-docx/src/ToCiceroMarkVisitor.js

+77-5
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,50 @@ class ToCiceroMarkVisitor {
112112
return isBorderPresent;
113113
}
114114

115+
/**
116+
* Checks if the node is a codeblock or not
117+
*
118+
* @param {Array} paragraphProperties paragraph styling properties
119+
* @returns {boolean} true if the node is of type codeblock or else, false
120+
*/
121+
checkCodeBlockProperties(paragraphProperties) {
122+
let isDesiredTopBorderPresent = false;
123+
let isDesiredBottomBorderPresent = false;
124+
let isDesiredLeftBorderPresent = false;
125+
let isDesiredRightBorderPresent = false;
126+
let isDesiredShadePresent = false;
127+
128+
for (const property of paragraphProperties) {
129+
if (property.name === 'w:pBdr') {
130+
// do something
131+
for (const borderProperty of property.elements) {
132+
if (borderProperty.attributes['w:color'] === 'CCCCCC') {
133+
if (borderProperty.name === 'w:top') {
134+
isDesiredTopBorderPresent = true;
135+
} else if (borderProperty.name === 'w:bottom') {
136+
isDesiredBottomBorderPresent = true;
137+
} else if (borderProperty.name === 'w:left') {
138+
isDesiredLeftBorderPresent = true;
139+
} else if (borderProperty.name === 'w:right') {
140+
isDesiredRightBorderPresent = true;
141+
}
142+
}
143+
}
144+
} else if (property.name === 'w:shd') {
145+
if (property.attributes['w:fill'] === 'F8F8F8') {
146+
isDesiredShadePresent = true;
147+
}
148+
}
149+
}
150+
return (
151+
isDesiredTopBorderPresent &&
152+
isDesiredBottomBorderPresent &&
153+
isDesiredLeftBorderPresent &&
154+
isDesiredRightBorderPresent &&
155+
isDesiredShadePresent
156+
);
157+
}
158+
115159
/**
116160
* Constructs a ciceroMark Node for inline element from the information.
117161
*
@@ -213,10 +257,13 @@ class ToCiceroMarkVisitor {
213257
/**
214258
* Traverses for properties and value.
215259
*
216-
* @param {Array} node Node to be traversed
217-
* @param {object} nodeInformation Information for the current node
260+
* @param {Array} node Node to be traversed
261+
* @param {object} nodeInformation Information for the current node
262+
* @param {Boolean} calledByCodeBlock Is function called by codeblock checker
263+
* @returns {string} Value in <w:t> tags
218264
*/
219-
fetchFormattingProperties(node, nodeInformation) {
265+
fetchFormattingProperties(node, nodeInformation, calledByCodeBlock = false) {
266+
let ooxmlTagTextValue = '';
220267
for (const runTimeNodes of node.elements) {
221268
if (runTimeNodes.name === 'w:rPr') {
222269
let colorCodePresent = false;
@@ -245,13 +292,21 @@ class ToCiceroMarkVisitor {
245292
nodeInformation.nodeType = TRANSFORMED_NODES.code;
246293
}
247294
} else if (runTimeNodes.name === 'w:t') {
248-
nodeInformation.value = runTimeNodes.elements ? runTimeNodes.elements[0].text : ' ';
249-
this.JSONXML = [...this.JSONXML, nodeInformation];
295+
if (calledByCodeBlock) {
296+
ooxmlTagTextValue += runTimeNodes.elements ? runTimeNodes.elements[0].text : '';
297+
} else {
298+
ooxmlTagTextValue = runTimeNodes.elements ? runTimeNodes.elements[0].text : ' ';
299+
nodeInformation.value = ooxmlTagTextValue;
300+
this.JSONXML = [...this.JSONXML, nodeInformation];
301+
}
302+
} else if (runTimeNodes.name === 'w:br') {
303+
ooxmlTagTextValue += '\n';
250304
} else if (runTimeNodes.name === 'w:sym') {
251305
nodeInformation.nodeType = TRANSFORMED_NODES.softbreak;
252306
this.JSONXML = [...this.JSONXML, nodeInformation];
253307
}
254308
}
309+
return ooxmlTagTextValue;
255310
}
256311

257312
/**
@@ -273,6 +328,23 @@ class ToCiceroMarkVisitor {
273328

274329
const isThematicBreak = this.checkThematicBreakProperties(subNode.elements[0].elements);
275330

331+
const isCodeBlock = this.checkCodeBlockProperties(subNode.elements[0].elements);
332+
333+
if (isCodeBlock) {
334+
let text = '';
335+
for (const codeBlockSubNode of subNode.elements) {
336+
if (codeBlockSubNode.name === 'w:r') {
337+
text = this.fetchFormattingProperties(codeBlockSubNode, undefined, true);
338+
}
339+
}
340+
const codeBlockNode = {
341+
$class: TRANSFORMED_NODES.codeBlock,
342+
text,
343+
};
344+
this.nodes = [...this.nodes, codeBlockNode];
345+
continue;
346+
}
347+
276348
if (isThematicBreak) {
277349
const thematicBreakNode = {
278350
$class: TRANSFORMED_NODES.thematicBreak,

packages/markdown-docx/src/ToOOXMLVisitor/index.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ const {
2626
STRONG_RULE,
2727
CODE_PROPERTIES_RULE,
2828
THEMATICBREAK_RULE,
29+
CODEBLOCK_PROPERTIES_RULE,
30+
CODEBLOCK_FONTPROPERTIES_RULE,
2931
} = require('./rules');
3032
const { wrapAroundDefaultDocxTags } = require('./helpers');
3133
const { TRANSFORMED_NODES } = require('../constants');
@@ -99,6 +101,20 @@ class ToOOXMLVisitor {
99101

100102
let tag = TEXT_WRAPPER_RULE(propertyTag, textValueTag);
101103
this.tags = [...this.tags, tag];
104+
} else if (this.getClass(subNode) === TRANSFORMED_NODES.codeBlock) {
105+
let ooxml = CODEBLOCK_PROPERTIES_RULE();
106+
let textValues = subNode.text.split('\n');
107+
let textValueTag = '';
108+
for (let textValueIndex = 0; textValueIndex < textValues.length; textValueIndex++) {
109+
textValueTag += TEXT_RULE(textValues[textValueIndex]);
110+
if (textValueIndex !== textValues.length - 1) {
111+
textValueTag += '<w:br />';
112+
}
113+
}
114+
let textPropertyTag = TEXT_STYLES_RULE(CODEBLOCK_FONTPROPERTIES_RULE());
115+
ooxml += TEXT_WRAPPER_RULE(textPropertyTag, textValueTag);
116+
117+
this.globalOOXML += PARAGRAPH_RULE(ooxml);
102118
} else if (this.getClass(subNode) === TRANSFORMED_NODES.variable) {
103119
const tag = subNode.name;
104120
const type = subNode.elementType;
@@ -122,7 +138,7 @@ class ToOOXMLVisitor {
122138
this.tags = [...this.tags, VARIABLE_RULE(title, tag, value, type)];
123139
} else if (this.getClass(subNode) === TRANSFORMED_NODES.softbreak) {
124140
this.tags = [...this.tags, SOFTBREAK_RULE()];
125-
} else if(this.getClass(subNode) === TRANSFORMED_NODES.thematicBreak){
141+
} else if (this.getClass(subNode) === TRANSFORMED_NODES.thematicBreak) {
126142
this.globalOOXML += THEMATICBREAK_RULE();
127143
} else {
128144
if (subNode.nodes) {

packages/markdown-docx/src/ToOOXMLVisitor/rules.js

+20
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,24 @@ const CODE_PROPERTIES_RULE = () => {
169169
`;
170170
};
171171

172+
const CODEBLOCK_FONTPROPERTIES_RULE = () => {
173+
return '<w:rFonts w:ascii="Courier New" w:h-ansi="Courier New" w:cs="Courier New"/>';
174+
};
175+
176+
const CODEBLOCK_PROPERTIES_RULE = () => {
177+
return `
178+
<w:pPr>
179+
<w:pBdr>
180+
<w:top w:val="single" w:sz="4" w:space="1" w:color="CCCCCC" />
181+
<w:left w:val="single" w:sz="4" w:space="4" w:color="CCCCCC" />
182+
<w:bottom w:val="single" w:sz="4" w:space="1" w:color="CCCCCC" />
183+
<w:right w:val="single" w:sz="4" w:space="4" w:color="CCCCCC" />
184+
</w:pBdr>
185+
<w:shd w:val="clear" w:color="auto" w:fill="F8F8F8"/>
186+
</w:pPr>
187+
`;
188+
};
189+
172190
const LINEBREAK_RULE = () => {
173191
return '<w:p/>';
174192
};
@@ -197,5 +215,7 @@ module.exports = {
197215
SOFTBREAK_RULE,
198216
STRONG_RULE,
199217
CODE_PROPERTIES_RULE,
218+
CODEBLOCK_PROPERTIES_RULE,
219+
CODEBLOCK_FONTPROPERTIES_RULE,
200220
THEMATICBREAK_RULE,
201221
};

packages/markdown-docx/src/constants.js

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const { NS_PREFIX_CiceroMarkModel } = require('@accordproject/markdown-cicero').
1919

2020
const TRANSFORMED_NODES = {
2121
code: `${NS_PREFIX_CommonMarkModel}Code`,
22+
codeBlock: `${NS_PREFIX_CommonMarkModel}CodeBlock`,
2223
computedVariable: `${NS_PREFIX_CiceroMarkModel}ComputedVariable`,
2324
document: `${NS_PREFIX_CommonMarkModel}Document`,
2425
emphasize: `${NS_PREFIX_CommonMarkModel}Emph`,
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":"just testing some"}]},{"$class":"org.accordproject.commonmark.CodeBlock","text":"Let us try some sentences to see whether we are able to convert the above\ninto an ooxml document **using some** of the techniques we have already encountered.\nlets hope for the best\n"}]}

0 commit comments

Comments
 (0)