From 3ecb7d45530193106df3097a2cedea485c376669 Mon Sep 17 00:00:00 2001 From: Vishal Date: Sat, 5 Oct 2024 11:17:10 +0530 Subject: [PATCH 1/6] Added
tag functionlity Signed-off-by: Vishal --- .eslintrc.json | 16 +++++++- example/example-node.js | 4 ++ example/example.js | 3 ++ example/react-example/src/App.js | 4 ++ src/helpers/render-document-file.js | 5 +++ src/helpers/xml-builder.js | 62 ++++++++++++++++++++--------- 6 files changed, 73 insertions(+), 21 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index e7e4700..45cfedc 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,7 +6,19 @@ "plugins": ["prettier"], "rules": { "prettier/prettier": ["error"], - "default-case": "off" + "default-case": "off", + "import/extensions": ["error", "ignorePackages", { + "js": "always", + "jsx": "always" + }], + "import/no-unresolved": "off", + "settings": { + "import/resolver": { + "node": { + "extensions": [".js", ".jsx"] + } + } + } }, "ignorePatterns": "dist/**/*.js" -} +} \ No newline at end of file diff --git a/example/example-node.js b/example/example-node.js index c61b756..a648fee 100644 --- a/example/example-node.js +++ b/example/example-node.js @@ -15,6 +15,10 @@ const htmlString = `

Taken from wikipedia

+

Taken from wikipedia

+
+

This is a test for hr tag

+
Red dot

Taken from wikipedia

+
+

This is a test for hr tag

+
Red dot

Taken from wikipedia

+

Taken from wikipedia

+
+

This is a test for hr tag

+
Red dot .att('@w', 'hRule', 'atLeast') .up(); +const buildHorizontalRule = () => { + const hrFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'p'); + const pPr = hrFragment.ele('@w', 'pPr'); + const pBdr = pPr.ele('@w', 'pBdr'); + pBdr.ele('@w', 'bottom', { + 'w:val': 'single', + 'w:sz': '24', + 'w:space': '1', + 'w:color': '000000' + }); + pBdr.up(); + pPr.up(); + hrFragment.up(); + return hrFragment; +}; + const buildVerticalAlignment = (verticalAlignment) => { if (verticalAlignment.toLowerCase() === 'middle') { verticalAlignment = 'center'; @@ -854,7 +870,6 @@ const buildRun = async (vNode, attributes, docxDocumentInstance) => { case 'b': tempAttributes.strong = true; break; - case 'em': case 'i': tempAttributes.i = true; break; @@ -1450,25 +1465,30 @@ const buildParagraph = async (vNode, attributes, docxDocumentInstance) => { computeImageDimensions(childVNode, modifiedAttributes); } - const runOrHyperlinkFragments = await buildRunOrHyperLink( - childVNode, - isVNode(childVNode) && childVNode.tagName === 'img' - ? { ...modifiedAttributes, type: 'picture', description: childVNode.properties.alt } - : modifiedAttributes, - docxDocumentInstance - ); - if (Array.isArray(runOrHyperlinkFragments)) { - for ( - let iteratorIndex = 0; - iteratorIndex < runOrHyperlinkFragments.length; - iteratorIndex++ - ) { - const runOrHyperlinkFragment = runOrHyperlinkFragments[iteratorIndex]; - - paragraphFragment.import(runOrHyperlinkFragment); - } + if (childVNode.tagName === 'hr') { + const hrFragment = buildHorizontalRule(); + paragraphFragment.import(hrFragment); } else { - paragraphFragment.import(runOrHyperlinkFragments); + const runOrHyperlinkFragments = await buildRunOrHyperLink( + childVNode, + isVNode(childVNode) && childVNode.tagName === 'img' + ? { ...modifiedAttributes, type: 'picture', description: childVNode.properties.alt } + : modifiedAttributes, + docxDocumentInstance + ); + if (Array.isArray(runOrHyperlinkFragments)) { + for ( + let iteratorIndex = 0; + iteratorIndex < runOrHyperlinkFragments.length; + iteratorIndex++ + ) { + const runOrHyperlinkFragment = runOrHyperlinkFragments[iteratorIndex]; + + paragraphFragment.import(runOrHyperlinkFragment); + } + } else { + paragraphFragment.import(runOrHyperlinkFragments); + } } } } @@ -2513,6 +2533,9 @@ const buildTableCell = async (vNode, attributes, rowSpanMap, columnIndex, docxDo } } } + } else if (isVNode(childVNode) && childVNode.tagName === 'hr') { + const hrFragment = buildHorizontalRule(docxDocumentInstance); + tableCellFragment.import(hrFragment); } else if (isVNode(childVNode) && ['ul', 'ol'].includes(childVNode.tagName)) { // render list in table if (vNodeHasChildren(childVNode)) { @@ -3603,4 +3626,5 @@ export { buildUnderline, buildDrawing, fixupLineHeight, + buildHorizontalRule }; From 8a868ff3b8ed5274821703bcc0f3637575269950 Mon Sep 17 00:00:00 2001 From: Vishal Date: Sun, 6 Oct 2024 19:17:08 +0530 Subject: [PATCH 2/6] Added parameter and constants for hr styles Signed-off-by: Vishal --- README.md | 5 +++++ src/constants.js | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/README.md b/README.md index e46fb73..3838326 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,11 @@ full fledged examples can be found under `example/` - `lang` language localization code for spell checker to work properly. Defaults to `en-US`. - `preProcessing` - `skipHTMLMinify` flag to skip minification of HTML. Defaults to `false`. + - `hrStyles` + - `val` The border style (e.g., `single`, `dashed`). Defaults to `single`. + - `sz` The size of the border. Defaults to `24`. + - `space` The space around border. Defaults to `1`. + - `color` The color of the border. Defaults to `000000`. - `footerHTMLString` <[String]> clean html string equivalent of footer. Defaults to `

` if footer flag is `true`. ### Returns diff --git a/src/constants.js b/src/constants.js index 6284f42..c8af868 100644 --- a/src/constants.js +++ b/src/constants.js @@ -34,6 +34,12 @@ const defaultTableBorderAttributeOptions = { size: 1, stroke: 'single', }; +const defaultHorizontalRuleOptions = { + val: 'single', + sz: '24', + space: '1', + color: '000000', +}; const defaultDocumentOptions = { orientation: defaultOrientation, margins: cloneDeep(portraitMargins), @@ -124,6 +130,7 @@ export { defaultDocumentOptions, defaultTableBorderOptions, defaultHTMLString, + defaultHorizontalRuleOptions, relsFolderName, headerFileName, footerFileName, From 874210f7e864d230be883c00812dcdda44dbc831 Mon Sep 17 00:00:00 2001 From: Vishal Date: Mon, 7 Oct 2024 15:34:49 +0530 Subject: [PATCH 3/6] Added style properties of hr rule Signed-off-by: Vishal --- example/example-node.js | 2 +- index.js | 8 ++++- src/constants.js | 2 +- src/helpers/render-document-file.js | 5 +-- src/helpers/xml-builder.js | 48 +++++++++++++++++++++-------- src/html-to-docx.js | 4 ++- 6 files changed, 50 insertions(+), 19 deletions(-) diff --git a/example/example-node.js b/example/example-node.js index a648fee..85cf90f 100644 --- a/example/example-node.js +++ b/example/example-node.js @@ -16,7 +16,7 @@ const htmlString = `

Taken from wikipedia

Taken from wikipedia

-
+

This is a test for hr tag


{ try { @@ -25,10 +26,15 @@ async function generateContainer( htmlString, headerHTMLString, documentOptions = {}, - footerHTMLString + footerHTMLString, + customDefaults = {} ) { const zip = new JSZip(); + if (customDefaults.hrStyles) { + Object.assign(defaultHorizontalRuleOptions, customDefaults.hrStyles); + } + const normalizedDocumentOptions = createDocumentOptionsAndMergeWithDefaults(documentOptions); let contentHTML = htmlString; diff --git a/src/constants.js b/src/constants.js index c8af868..53135c3 100644 --- a/src/constants.js +++ b/src/constants.js @@ -38,7 +38,7 @@ const defaultHorizontalRuleOptions = { val: 'single', sz: '24', space: '1', - color: '000000', + color: 'FF0000', }; const defaultDocumentOptions = { orientation: defaultOrientation, diff --git a/src/helpers/render-document-file.js b/src/helpers/render-document-file.js index d27807f..284864b 100644 --- a/src/helpers/render-document-file.js +++ b/src/helpers/render-document-file.js @@ -1,3 +1,4 @@ +// render-document-file.js /* eslint-disable no-await-in-loop */ /* eslint-disable no-case-declarations */ import { fragment } from 'xmlbuilder2'; @@ -311,7 +312,7 @@ async function findXMLEquivalent(docxDocumentInstance, vNode, xmlFragment) { xmlFragment.import(linebreakFragment); return; case 'hr': - const hrFragment = buildHorizontalRule(); + const hrFragment = buildHorizontalRule(vNode, vNode.properties.style); xmlFragment.import(hrFragment); return; case 'head': @@ -358,4 +359,4 @@ async function renderDocumentFile(docxDocumentInstance) { return populatedXmlFragment; } -export default renderDocumentFile; +export default renderDocumentFile; \ No newline at end of file diff --git a/src/helpers/xml-builder.js b/src/helpers/xml-builder.js index 0d38aa5..f4e5786 100644 --- a/src/helpers/xml-builder.js +++ b/src/helpers/xml-builder.js @@ -12,7 +12,6 @@ import { cloneDeep } from 'lodash'; import imageToBase64 from 'image-to-base64'; import sizeOf from 'image-size'; import { getMimeType } from '../utils/image' - import namespaces from '../namespaces'; import { rgbToHex, @@ -55,7 +54,8 @@ import { imageType, internalRelationship, defaultTableBorderOptions, - defaultTableBorderAttributeOptions + defaultTableBorderAttributeOptions, + defaultHorizontalRuleOptions, } from '../constants'; import { vNodeHasChildren } from '../utils/vnode'; import { isValidUrl } from '../utils/url'; @@ -179,22 +179,44 @@ const buildTableRowHeight = (tableRowHeight) => .att('@w', 'hRule', 'atLeast') .up(); -const buildHorizontalRule = () => { - const hrFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'p'); - const pPr = hrFragment.ele('@w', 'pPr'); - const pBdr = pPr.ele('@w', 'pBdr'); - pBdr.ele('@w', 'bottom', { - 'w:val': 'single', - 'w:sz': '24', - 'w:space': '1', - 'w:color': '000000' +const buildHorizontalRule = (element, styles = {}) => { + // Parse inline styles from the element + const inlineStyles = (styleString => { + const styles = {}; + if (styleString) { + styleString.split(";").forEach(style => { + const [key, value] = style.split(":").map(s => s.trim()); + if (key && value) { + styles[key] = value; + } + }); + } + return styles; + })(element && typeof element.getAttribute === 'function' ? element.getAttribute("style") : ""); + + // Merge inline styles with default styles and additional styles + const mergedStyles = { ...defaultHorizontalRuleOptions, ...styles, ...inlineStyles }; + + // Use the imported fragment directly + const hrFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele("@w", "p"); + const pPr = hrFragment.ele("@w", "pPr"); + const pBdr = pPr.ele("@w", "pBdr"); + + // Define the bottom border properties + pBdr.ele("@w", "bottom", { + "w:val": mergedStyles.val || 'single', + "w:sz": mergedStyles.sz || '4', + "w:space": mergedStyles.space || '1', + "w:color": mergedStyles.color || 'auto' }); + pBdr.up(); pPr.up(); hrFragment.up(); - return hrFragment; -}; + return hrFragment; +}; + const buildVerticalAlignment = (verticalAlignment) => { if (verticalAlignment.toLowerCase() === 'middle') { verticalAlignment = 'center'; diff --git a/src/html-to-docx.js b/src/html-to-docx.js index 5ae2408..899d515 100644 --- a/src/html-to-docx.js +++ b/src/html-to-docx.js @@ -1,3 +1,4 @@ +// html-to-docx.js import { create } from 'xmlbuilder2'; import VNode from 'virtual-dom/vnode/vnode'; import VText from 'virtual-dom/vnode/vtext'; @@ -22,6 +23,7 @@ import { themeFolder, themeType, } from './constants'; +import { buildHorizontalRule } from './helpers/xml-builder'; const convertHTML = HTMLToVDOM({ VNode, @@ -146,4 +148,4 @@ async function addFilesToContainer( return zip; } -export default addFilesToContainer; +export default addFilesToContainer; \ No newline at end of file From 812e1ac39588cf6c38bf90c041f908b3d8957b4f Mon Sep 17 00:00:00 2001 From: Vishal Date: Wed, 9 Oct 2024 23:22:51 +0530 Subject: [PATCH 4/6] Added Parameters and style attributes Signed-off-by: Vishal --- README.md | 16 ++++-- example/example-node.js | 2 +- example/example.js | 2 +- src/constants.js | 19 +++++-- src/docx-document.js | 1 + src/helpers/xml-builder.js | 103 +++++++++++++++++++++---------------- 6 files changed, 88 insertions(+), 55 deletions(-) diff --git a/README.md b/README.md index 3838326..79542da 100644 --- a/README.md +++ b/README.md @@ -84,10 +84,18 @@ full fledged examples can be found under `example/` - `preProcessing` - `skipHTMLMinify` flag to skip minification of HTML. Defaults to `false`. - `hrStyles` - - `val` The border style (e.g., `single`, `dashed`). Defaults to `single`. - - `sz` The size of the border. Defaults to `24`. - - `space` The space around border. Defaults to `1`. - - `color` The color of the border. Defaults to `000000`. + - `height` The size of the border. Defaults to `24`. + - `width` The space around border. Defaults to `1`. + - `backgroundColor` The color of the border. Defaults to `000000`. + - `borderOptions` + - `size` denotes the border size. Defaults to `0`. + - `val` denotes the style of the borderStyle. Defaults to `solid`. + - `color` determines the border color. Defaults to `000000`. + - `margins` + - `top` <[Number]> distance between the top of the text margins for the main document and the top of the page for all pages in this section in [TWIP]. Defaults to 1440. Supports equivalent measurement in [pixel], [cm] or [inch]. + - `right` <[Number]> distance between the right edge of the page and the right edge of the text extents for this document in [TWIP]. Defaults to 1800. Supports equivalent measurement in [pixel], [cm] or [inch]. + - `bottom` <[Number]> distance between the bottom of text margins for the document and the bottom of the page in [TWIP]. Defaults to 1440. Supports equivalent measurement in [pixel], [cm] or [inch]. + - `left` <[Number]> distance between the left edge of the page and the left edge of the text extents for this document in [TWIP]. Defaults to 1800. Supports equivalent measurement in [pixel], [cm] or [inch]. - `footerHTMLString` <[String]> clean html string equivalent of footer. Defaults to `

` if footer flag is `true`. ### Returns diff --git a/example/example-node.js b/example/example-node.js index 85cf90f..3e226e2 100644 --- a/example/example-node.js +++ b/example/example-node.js @@ -16,7 +16,7 @@ const htmlString = `

Taken from wikipedia

Taken from wikipedia

-
+

This is a test for hr tag


Taken from wikipedia

-
+

This is a test for hr tag


.att('@w', 'hRule', 'atLeast') .up(); -const buildHorizontalRule = (element, styles = {}) => { - // Parse inline styles from the element - const inlineStyles = (styleString => { - const styles = {}; - if (styleString) { - styleString.split(";").forEach(style => { - const [key, value] = style.split(":").map(s => s.trim()); - if (key && value) { - styles[key] = value; - } - }); - } - return styles; - })(element && typeof element.getAttribute === 'function' ? element.getAttribute("style") : ""); - - // Merge inline styles with default styles and additional styles - const mergedStyles = { ...defaultHorizontalRuleOptions, ...styles, ...inlineStyles }; - - // Use the imported fragment directly - const hrFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele("@w", "p"); - const pPr = hrFragment.ele("@w", "pPr"); - const pBdr = pPr.ele("@w", "pBdr"); - - // Define the bottom border properties - pBdr.ele("@w", "bottom", { - "w:val": mergedStyles.val || 'single', - "w:sz": mergedStyles.sz || '4', - "w:space": mergedStyles.space || '1', - "w:color": mergedStyles.color || 'auto' - }); - - pBdr.up(); - pPr.up(); - hrFragment.up(); - - return hrFragment; -}; + const buildHorizontalRuleProperties = (attributes) => { + const horizontalRulePropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'pPr'); + + if (attributes && typeof attributes === 'object') { + const spacingFragment = buildSpacing( + attributes.lineHeight, + attributes.beforeSpacing, + attributes.afterSpacing + ); + horizontalRulePropertiesFragment.import(spacingFragment); + + const borderFragment = buildBorder( + 'bottom', + attributes.borderOptions.size, + attributes.borderOptions.val, + attributes.borderOptions.color + ); + horizontalRulePropertiesFragment.import(borderFragment); + + const shadingFragment = buildShading(attributes.backgroundColor); + horizontalRulePropertiesFragment.import(shadingFragment); + + horizontalRulePropertiesFragment.up(); + } + + return horizontalRulePropertiesFragment; + }; + + const buildHorizontalRule = (vNode, attributes, docxDocumentInstance) => { + const options = { + isParagraph: false, + }; + + const modifiedAttributes = modifiedStyleAttributesBuilder(docxDocumentInstance, vNode, attributes, options); + + if (!modifiedAttributes.borderOptions) { + modifiedAttributes.borderOptions = defaultHorizontalRuleOptions.borderOptions; + } + + const horizontalRuleFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'hr'); + const horizontalRulePropertiesFragment = buildHorizontalRuleProperties(modifiedAttributes); + horizontalRuleFragment.import(horizontalRulePropertiesFragment); + + horizontalRuleFragment.ele('w:r') + .ele('@w','rPr') + .ele('@w','shd', { 'w:fill': modifiedAttributes.backgroundColor }).up() + .ele('@w','bdr', { 'w:val': modifiedAttributes.borderOptions.val, 'w:sz': modifiedAttributes.borderOptions.size, 'w:color': modifiedAttributes.borderOptions.color }).up() + .up() + .ele('@w', 't', { 'xml:space': 'preserve' }, ' '.repeat(modifiedAttributes.width)) + .up() + .up() + .up(); + + return horizontalRuleFragment; + }; const buildVerticalAlignment = (verticalAlignment) => { if (verticalAlignment.toLowerCase() === 'middle') { @@ -470,11 +488,9 @@ const fixupColumnWidth = (columnWidthString, parentWidth = 0) => { const fixupMargin = (marginString) => { if (pointRegex.test(marginString)) { const matchedParts = marginString.match(pointRegex); - // convert point to half point return pointToTWIP(matchedParts[1]); } else if (pixelRegex.test(marginString)) { const matchedParts = marginString.match(pixelRegex); - // convert pixels to half point return pixelToTWIP(matchedParts[1]); } else if (cmRegex.test(marginString)) { const matchedParts = marginString.match(cmRegex); @@ -483,22 +499,19 @@ const fixupMargin = (marginString) => { const matchedParts = marginString.match(inchRegex); return inchToTWIP(matchedParts[1]); } else if (percentageRegex.test(marginString)) { - // This requires changes in lot of functions. So, for now, we are returning the percentage value as it is. - // TODO: Revisit this and see how margins in percentages are handled and change in respective functions. const matchedParts = marginString.match(percentageRegex); - return matchedParts[1] + return matchedParts[1]; } }; const borderStyleParser = (style) => { - // Accepted OOXML Values for border style: http://officeopenxml.com/WPtableBorders.php if (['dashed', 'dotted', 'double', 'inset', 'outset', 'none'].includes(style)) { return style; } else if (style === 'hidden') { return 'nil'; } - return 'single' -} + return 'single'; +}; const borderSizeParser = (borderSize) => { if (pointRegex.test(borderSize)) { From b33bd800d2e8f13f1812b43d3efbb115e7e8f997 Mon Sep 17 00:00:00 2001 From: Vishal Date: Thu, 10 Oct 2024 14:25:54 +0530 Subject: [PATCH 5/6] Fixed breaking changes of docx, making changes to buildhorizontalRule Signed-off-by: Vishal --- example/example-node.js | 4 +- src/constants.js | 4 +- src/helpers/xml-builder.js | 109 +++++++++++++++++-------------------- 3 files changed, 55 insertions(+), 62 deletions(-) diff --git a/example/example-node.js b/example/example-node.js index 3e226e2..0f02f52 100644 --- a/example/example-node.js +++ b/example/example-node.js @@ -16,9 +16,9 @@ const htmlString = `

Taken from wikipedia

Taken from wikipedia

-
+

This is a test for hr tag

-
+
Red dot .att('@w', 'val', tableRowHeight) .att('@w', 'hRule', 'atLeast') .up(); - - const buildHorizontalRuleProperties = (attributes) => { - const horizontalRulePropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'pPr'); - - if (attributes && typeof attributes === 'object') { - const spacingFragment = buildSpacing( - attributes.lineHeight, - attributes.beforeSpacing, - attributes.afterSpacing - ); - horizontalRulePropertiesFragment.import(spacingFragment); - - const borderFragment = buildBorder( - 'bottom', - attributes.borderOptions.size, - attributes.borderOptions.val, - attributes.borderOptions.color - ); - horizontalRulePropertiesFragment.import(borderFragment); - - const shadingFragment = buildShading(attributes.backgroundColor); - horizontalRulePropertiesFragment.import(shadingFragment); - - horizontalRulePropertiesFragment.up(); - } - - return horizontalRulePropertiesFragment; - }; - - const buildHorizontalRule = (vNode, attributes, docxDocumentInstance) => { - const options = { - isParagraph: false, - }; - - const modifiedAttributes = modifiedStyleAttributesBuilder(docxDocumentInstance, vNode, attributes, options); - - if (!modifiedAttributes.borderOptions) { - modifiedAttributes.borderOptions = defaultHorizontalRuleOptions.borderOptions; - } - - const horizontalRuleFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'hr'); - const horizontalRulePropertiesFragment = buildHorizontalRuleProperties(modifiedAttributes); - horizontalRuleFragment.import(horizontalRulePropertiesFragment); - - horizontalRuleFragment.ele('w:r') - .ele('@w','rPr') - .ele('@w','shd', { 'w:fill': modifiedAttributes.backgroundColor }).up() - .ele('@w','bdr', { 'w:val': modifiedAttributes.borderOptions.val, 'w:sz': modifiedAttributes.borderOptions.size, 'w:color': modifiedAttributes.borderOptions.color }).up() - .up() - .ele('@w', 't', { 'xml:space': 'preserve' }, ' '.repeat(modifiedAttributes.width)) - .up() - .up() - .up(); - - return horizontalRuleFragment; - }; +const buildHorizontalRuleProperties = (vNode) => { + const horizontalRulePropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('w:pPr'); + + const modifiedAttributes = modifiedStyleAttributesBuilder(null, vNode, {}, { isParagraph: false }); + console.log(modifiedAttributes); + if (modifiedAttributes.lineHeight || modifiedAttributes.beforeSpacing || modifiedAttributes.afterSpacing) { + const spacingFragment = buildSpacing( + modifiedAttributes.lineHeight, + modifiedAttributes.beforeSpacing, + modifiedAttributes.afterSpacing + ); + horizontalRulePropertiesFragment.import(spacingFragment); + } + + if (modifiedAttributes.backgroundColor) { + const shadingFragment = buildShading(modifiedAttributes.backgroundColor); + horizontalRulePropertiesFragment.import(shadingFragment); + } + + const { border = '' } = vNode.properties.style || {}; + let [borderSize, borderVal, borderColor] = cssBorderParser(border, defaultHorizontalRuleOptions.borderOptions); + if (modifiedAttributes.height) { + const heightValue = parseInt(modifiedAttributes.height, 10); + console.log(heightValue); + borderSize = heightValue; + } + const borderFragment = buildBorder('bottom', borderSize, borderVal, borderColor); + horizontalRulePropertiesFragment.import(borderFragment); + + horizontalRulePropertiesFragment.up(); + console.log(horizontalRulePropertiesFragment); + return horizontalRulePropertiesFragment; +}; + +const buildHorizontalRule = (vNode) => { + const horizontalRuleFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('w:p'); + console.log(vNode); + const propertiesFragment = buildHorizontalRuleProperties(vNode); + horizontalRuleFragment.import(propertiesFragment); + + const runFragment = horizontalRuleFragment.ele('w:r'); + runFragment.ele('w:rPr'); + runFragment.up(); + horizontalRuleFragment.up(); + + return horizontalRuleFragment; +}; + const buildVerticalAlignment = (verticalAlignment) => { if (verticalAlignment.toLowerCase() === 'middle') { verticalAlignment = 'center'; @@ -526,7 +518,7 @@ const borderSizeParser = (borderSize) => { return borderSize } -const cssBorderParser = (borderString, defaultBorderOptions = { ...defaultTableBorderOptions, stroke: 'single' }) => { +const cssBorderParser = (borderString, defaultBorderOptions = { ...defaultHorizontalRuleOptions.borderOptions, stroke: 'single' }) => { const tokens = borderString.split(' '); let { size, stroke, color } = defaultBorderOptions @@ -575,7 +567,6 @@ const cssBorderParser = (borderString, defaultBorderOptions = { ...defaultTableB const modifiedStyleAttributesBuilder = (docxDocumentInstance, vNode, attributes, options) => { const modifiedAttributes = { ...attributes }; - // styles if (isVNode(vNode) && vNode.properties && vNode.properties.style) { const vNodeStyle = vNode.properties.style; @@ -610,6 +601,8 @@ const modifiedStyleAttributesBuilder = (docxDocumentInstance, vNode, attributes, } } else if (vNodeStyleKey === 'font-family') { modifiedAttributes.font = docxDocumentInstance.createFont(vNodeStyleValue); + } else if (vNodeStyleKey === 'height') { + modifiedAttributes.height = vNodeStyleValue; } else if (vNodeStyleKey === 'font-size') { modifiedAttributes.fontSize = fixupFontSize(vNodeStyleValue, docxDocumentInstance); } else if (vNodeStyleKey === 'line-height') { From 29606e072ce3577aa632cf2f4dfd36d735934bb6 Mon Sep 17 00:00:00 2001 From: Vishal Date: Sat, 12 Oct 2024 09:04:21 +0530 Subject: [PATCH 6/6] Added fragments to fix height and border Signed-off-by: Vishal --- src/helpers/xml-builder.js | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/helpers/xml-builder.js b/src/helpers/xml-builder.js index b5f30b0..f7cd22a 100644 --- a/src/helpers/xml-builder.js +++ b/src/helpers/xml-builder.js @@ -183,7 +183,6 @@ const buildHorizontalRuleProperties = (vNode) => { const horizontalRulePropertiesFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('w:pPr'); const modifiedAttributes = modifiedStyleAttributesBuilder(null, vNode, {}, { isParagraph: false }); - console.log(modifiedAttributes); if (modifiedAttributes.lineHeight || modifiedAttributes.beforeSpacing || modifiedAttributes.afterSpacing) { const spacingFragment = buildSpacing( modifiedAttributes.lineHeight, @@ -202,30 +201,41 @@ const buildHorizontalRuleProperties = (vNode) => { let [borderSize, borderVal, borderColor] = cssBorderParser(border, defaultHorizontalRuleOptions.borderOptions); if (modifiedAttributes.height) { const heightValue = parseInt(modifiedAttributes.height, 10); - console.log(heightValue); borderSize = heightValue; } const borderFragment = buildBorder('bottom', borderSize, borderVal, borderColor); horizontalRulePropertiesFragment.import(borderFragment); horizontalRulePropertiesFragment.up(); - console.log(horizontalRulePropertiesFragment); return horizontalRulePropertiesFragment; }; const buildHorizontalRule = (vNode) => { const horizontalRuleFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('w:p'); - console.log(vNode); const propertiesFragment = buildHorizontalRuleProperties(vNode); horizontalRuleFragment.import(propertiesFragment); const runFragment = horizontalRuleFragment.ele('w:r'); - runFragment.ele('w:rPr'); + const runPropertiesFragment = runFragment.ele('w:rPr'); + + const { + height = defaultHorizontalRuleOptions.height, + width = defaultHorizontalRuleOptions.width, + backgroundColor = defaultHorizontalRuleOptions.backgroundColor, + border = `${defaultHorizontalRuleOptions.borderOptions.size}px ${defaultHorizontalRuleOptions.borderOptions.val} ${defaultHorizontalRuleOptions.borderOptions.color}` + } = vNode.properties.style || {}; + + const [borderSize, borderVal, borderColor] = cssBorderParser(border, defaultHorizontalRuleOptions.borderOptions); + + runPropertiesFragment.ele('w:shd', { 'w:fill': backgroundColor }).up(); + runPropertiesFragment.ele('w:bdr', { 'w:val': borderVal, 'w:sz': borderSize, 'w:color': borderColor }).up(); + + runFragment.ele('w:t', { 'xml:space': 'preserve' }, ' '.repeat(parseInt(width, 10) || 1)).up(); runFragment.up(); horizontalRuleFragment.up(); return horizontalRuleFragment; -}; +}; const buildVerticalAlignment = (verticalAlignment) => { if (verticalAlignment.toLowerCase() === 'middle') { @@ -781,6 +791,8 @@ const buildFormatting = (htmlTag, options) => { return buildTextDecoration(options && options.textDecoration ? options.textDecoration : {}); case 'textShadow': return buildTextShadow(); + case 'hr': + return buildHorizontalRule(); } return null;