Skip to content

Commit db8ea9f

Browse files
committed
Added style properties of hr rule
1 parent 8a868ff commit db8ea9f

File tree

6 files changed

+50
-19
lines changed

6 files changed

+50
-19
lines changed

example/example-node.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const htmlString = `<!DOCTYPE html>
1616
<div>
1717
<p>Taken from wikipedia</p>
1818
<p>Taken from wikipedia</p>
19-
<hr>
19+
<hr style="border: 10px dotted red;" />
2020
<p>This is a test for hr tag</p>
2121
<hr>
2222
<img

index.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { minify } from 'html-minifier-terser';
44

55
import createDocumentOptionsAndMergeWithDefaults from './src/utils/options-utils';
66
import addFilesToContainer from './src/html-to-docx';
7+
import { defaultHorizontalRuleOptions } from './src/constants';
78

89
const minifyHTMLString = async (htmlString) => {
910
try {
@@ -25,10 +26,15 @@ async function generateContainer(
2526
htmlString,
2627
headerHTMLString,
2728
documentOptions = {},
28-
footerHTMLString
29+
footerHTMLString,
30+
customDefaults = {}
2931
) {
3032
const zip = new JSZip();
3133

34+
if (customDefaults.hrStyles) {
35+
Object.assign(defaultHorizontalRuleOptions, customDefaults.hrStyles);
36+
}
37+
3238
const normalizedDocumentOptions = createDocumentOptionsAndMergeWithDefaults(documentOptions);
3339

3440
let contentHTML = htmlString;

src/constants.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const defaultHorizontalRuleOptions = {
3838
val: 'single',
3939
sz: '24',
4040
space: '1',
41-
color: '000000',
41+
color: 'FF0000',
4242
};
4343
const defaultDocumentOptions = {
4444
orientation: defaultOrientation,

src/helpers/render-document-file.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// render-document-file.js
12
/* eslint-disable no-await-in-loop */
23
/* eslint-disable no-case-declarations */
34
import { fragment } from 'xmlbuilder2';
@@ -311,7 +312,7 @@ async function findXMLEquivalent(docxDocumentInstance, vNode, xmlFragment) {
311312
xmlFragment.import(linebreakFragment);
312313
return;
313314
case 'hr':
314-
const hrFragment = buildHorizontalRule();
315+
const hrFragment = buildHorizontalRule(vNode, vNode.properties.style);
315316
xmlFragment.import(hrFragment);
316317
return;
317318
case 'head':
@@ -358,4 +359,4 @@ async function renderDocumentFile(docxDocumentInstance) {
358359
return populatedXmlFragment;
359360
}
360361

361-
export default renderDocumentFile;
362+
export default renderDocumentFile;

src/helpers/xml-builder.js

+35-13
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import { cloneDeep } from 'lodash';
1212
import imageToBase64 from 'image-to-base64';
1313
import sizeOf from 'image-size';
1414
import { getMimeType } from '../utils/image'
15-
1615
import namespaces from '../namespaces';
1716
import {
1817
rgbToHex,
@@ -55,7 +54,8 @@ import {
5554
imageType,
5655
internalRelationship,
5756
defaultTableBorderOptions,
58-
defaultTableBorderAttributeOptions
57+
defaultTableBorderAttributeOptions,
58+
defaultHorizontalRuleOptions,
5959
} from '../constants';
6060
import { vNodeHasChildren } from '../utils/vnode';
6161
import { isValidUrl } from '../utils/url';
@@ -179,22 +179,44 @@ const buildTableRowHeight = (tableRowHeight) =>
179179
.att('@w', 'hRule', 'atLeast')
180180
.up();
181181

182-
const buildHorizontalRule = () => {
183-
const hrFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele('@w', 'p');
184-
const pPr = hrFragment.ele('@w', 'pPr');
185-
const pBdr = pPr.ele('@w', 'pBdr');
186-
pBdr.ele('@w', 'bottom', {
187-
'w:val': 'single',
188-
'w:sz': '24',
189-
'w:space': '1',
190-
'w:color': '000000'
182+
const buildHorizontalRule = (element, styles = {}) => {
183+
// Parse inline styles from the element
184+
const inlineStyles = (styleString => {
185+
const styles = {};
186+
if (styleString) {
187+
styleString.split(";").forEach(style => {
188+
const [key, value] = style.split(":").map(s => s.trim());
189+
if (key && value) {
190+
styles[key] = value;
191+
}
192+
});
193+
}
194+
return styles;
195+
})(element && typeof element.getAttribute === 'function' ? element.getAttribute("style") : "");
196+
197+
// Merge inline styles with default styles and additional styles
198+
const mergedStyles = { ...defaultHorizontalRuleOptions, ...styles, ...inlineStyles };
199+
200+
// Use the imported fragment directly
201+
const hrFragment = fragment({ namespaceAlias: { w: namespaces.w } }).ele("@w", "p");
202+
const pPr = hrFragment.ele("@w", "pPr");
203+
const pBdr = pPr.ele("@w", "pBdr");
204+
205+
// Define the bottom border properties
206+
pBdr.ele("@w", "bottom", {
207+
"w:val": mergedStyles.val || 'single',
208+
"w:sz": mergedStyles.sz || '4',
209+
"w:space": mergedStyles.space || '1',
210+
"w:color": mergedStyles.color || 'auto'
191211
});
212+
192213
pBdr.up();
193214
pPr.up();
194215
hrFragment.up();
195-
return hrFragment;
196-
};
197216

217+
return hrFragment;
218+
};
219+
198220
const buildVerticalAlignment = (verticalAlignment) => {
199221
if (verticalAlignment.toLowerCase() === 'middle') {
200222
verticalAlignment = 'center';

src/html-to-docx.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// html-to-docx.js
12
import { create } from 'xmlbuilder2';
23
import VNode from 'virtual-dom/vnode/vnode';
34
import VText from 'virtual-dom/vnode/vtext';
@@ -22,6 +23,7 @@ import {
2223
themeFolder,
2324
themeType,
2425
} from './constants';
26+
import { buildHorizontalRule } from './helpers/xml-builder';
2527

2628
const convertHTML = HTMLToVDOM({
2729
VNode,
@@ -146,4 +148,4 @@ async function addFilesToContainer(
146148
return zip;
147149
}
148150

149-
export default addFilesToContainer;
151+
export default addFilesToContainer;

0 commit comments

Comments
 (0)