@lkaopremier/html-to-docx 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/bin/cli.js +461 -0
- package/package.json +26 -0
- package/src/helper.js +544 -0
- package/src/index.d.ts +39 -0
- package/src/index.js +172 -0
- package/src/tree.js +643 -0
package/package.json
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
{
|
2
|
+
"name": "@lkaopremier/html-to-docx",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"main": "src/index.js",
|
5
|
+
"type": "module",
|
6
|
+
"keywords": [],
|
7
|
+
"author": "lkapremier",
|
8
|
+
"license": "ISC",
|
9
|
+
"description": "",
|
10
|
+
"dependencies": {
|
11
|
+
"docx": "^9.0.3",
|
12
|
+
"html-entities": "^2.5.2",
|
13
|
+
"html-minifier": "^4.0.0",
|
14
|
+
"lodash": "^4.17.21",
|
15
|
+
"node-html-parser": "^6.1.13",
|
16
|
+
"sharp": "^0.33.5"
|
17
|
+
},
|
18
|
+
"bin": {
|
19
|
+
"html-to-docx": "bin/cli.js"
|
20
|
+
},
|
21
|
+
"devDependencies": {},
|
22
|
+
"scripts": {
|
23
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
24
|
+
},
|
25
|
+
"types": "./src/index.d.ts"
|
26
|
+
}
|
package/src/helper.js
ADDED
@@ -0,0 +1,544 @@
|
|
1
|
+
import { parse as htmlParser } from 'node-html-parser'
|
2
|
+
import { minify } from 'html-minifier'
|
3
|
+
import sharp from 'sharp'
|
4
|
+
|
5
|
+
export function normalizeHtml(content) {
|
6
|
+
const elm = htmlParser(content)
|
7
|
+
|
8
|
+
const head =
|
9
|
+
elm.querySelector('head')?.outerHTML ??
|
10
|
+
`<head><meta charset="UTF-8"><title>Document</title></head>`
|
11
|
+
|
12
|
+
const body = cleanHtmlContent(
|
13
|
+
elm.querySelector('body')?.outerHTML?.trim() ??
|
14
|
+
`<body>${cleanHtmlContent(elm.outerHTML).trim()}</body>`,
|
15
|
+
)
|
16
|
+
|
17
|
+
const doc = minify(`<!DOCTYPE html><html>${head}${body}</html>`, {
|
18
|
+
removeAttributeQuotes: true,
|
19
|
+
removeEmptyAttributes: true,
|
20
|
+
removeComments: true,
|
21
|
+
})
|
22
|
+
|
23
|
+
return cleanHtmlContent(doc)
|
24
|
+
}
|
25
|
+
|
26
|
+
export function cleanHtmlContent(content) {
|
27
|
+
return content.replace(/(\s{2,}|\n)/g, match => {
|
28
|
+
if (/<(pre|code)>/.test(match)) {
|
29
|
+
return match
|
30
|
+
}
|
31
|
+
|
32
|
+
return ' '
|
33
|
+
})
|
34
|
+
}
|
35
|
+
|
36
|
+
export function pageNodes(bodyElm) {
|
37
|
+
const pages = {}
|
38
|
+
let children = []
|
39
|
+
bodyElm.childNodes.forEach(child => {
|
40
|
+
if (child && child.classList?.contains('page-break')) {
|
41
|
+
pages[Object.keys(pages).length + 1] = arrayToNodeHTMLElement(children)
|
42
|
+
children = []
|
43
|
+
} else {
|
44
|
+
children.push(child)
|
45
|
+
}
|
46
|
+
})
|
47
|
+
|
48
|
+
if (children.length > 0) {
|
49
|
+
pages[Object.keys(pages).length + 1] = arrayToNodeHTMLElement(children)
|
50
|
+
}
|
51
|
+
|
52
|
+
return Object.values(pages)
|
53
|
+
}
|
54
|
+
|
55
|
+
export function arrayToNodeHTMLElement(array) {
|
56
|
+
const fragment = htmlParser('')
|
57
|
+
array.forEach(item => fragment.appendChild(item))
|
58
|
+
return fragment
|
59
|
+
}
|
60
|
+
|
61
|
+
export function trim(str, ch) {
|
62
|
+
var start = 0,
|
63
|
+
end = str.length
|
64
|
+
|
65
|
+
while (start < end && str[start] === ch) ++start
|
66
|
+
|
67
|
+
while (end > start && str[end - 1] === ch) --end
|
68
|
+
|
69
|
+
return start > 0 || end < str.length ? str.substring(start, end) : str
|
70
|
+
}
|
71
|
+
|
72
|
+
export function splitMeasure(value) {
|
73
|
+
const match = value?.toString().match(/^(\d+(\.\d+)?)(px|pt|cm|in|mm|pc|pi)$/)
|
74
|
+
|
75
|
+
if (!match) {
|
76
|
+
return []
|
77
|
+
}
|
78
|
+
|
79
|
+
return [parseFloat(match[1]), match[3]]
|
80
|
+
}
|
81
|
+
|
82
|
+
export function normalizeMeasure(value) {
|
83
|
+
const [numericValue, unit] = splitMeasure(value)
|
84
|
+
|
85
|
+
if (!numericValue || !unit) {
|
86
|
+
return ''
|
87
|
+
}
|
88
|
+
|
89
|
+
if (unit === 'px') {
|
90
|
+
return `${numericValue * 0.75}pt`
|
91
|
+
} else if (['pt', 'in', 'cm', 'mm', 'pc', 'pi'].includes(unit)) {
|
92
|
+
return `${numericValue}${unit}`
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
/**
|
97
|
+
* Capitalizes first letters of words in string.
|
98
|
+
* @param {string} str String to be modified
|
99
|
+
* @param {boolean=false} lower Whether all other letters should be lowercased
|
100
|
+
* @return {string}
|
101
|
+
* @usage
|
102
|
+
* capitalize('fix this string'); // -> 'Fix This String'
|
103
|
+
* capitalize('javaSCrIPT'); // -> 'JavaSCrIPT'
|
104
|
+
* capitalize('javaSCrIPT', true); // -> 'Javascript'
|
105
|
+
*/
|
106
|
+
export const capitalize = (str, lower = false) => {
|
107
|
+
return (lower ? str.toLowerCase() : str).replace(
|
108
|
+
/(?:^|\s|["'([{])+\S/g,
|
109
|
+
match => match.toUpperCase(),
|
110
|
+
)
|
111
|
+
}
|
112
|
+
|
113
|
+
export function colorToHex(color) {
|
114
|
+
const namedColors = {
|
115
|
+
red: '#FF0000',
|
116
|
+
blue: '#0000FF',
|
117
|
+
green: '#008000',
|
118
|
+
black: '#000000',
|
119
|
+
white: '#FFFFFF',
|
120
|
+
yellow: '#FFFF00',
|
121
|
+
orange: '#FFA500',
|
122
|
+
purple: '#800080',
|
123
|
+
pink: '#FFC0CB',
|
124
|
+
gray: '#808080',
|
125
|
+
silver: '#C0C0C0',
|
126
|
+
maroon: '#800000',
|
127
|
+
olive: '#808000',
|
128
|
+
lime: '#00FF00',
|
129
|
+
teal: '#008080',
|
130
|
+
navy: '#000080',
|
131
|
+
aqua: '#00FFFF',
|
132
|
+
fuchsia: '#FF00FF',
|
133
|
+
cyan: '#00FFFF',
|
134
|
+
brown: '#A52A2A',
|
135
|
+
gold: '#FFD700',
|
136
|
+
coral: '#FF7F50',
|
137
|
+
violet: '#EE82EE',
|
138
|
+
indigo: '#4B0082',
|
139
|
+
khaki: '#F0E68C',
|
140
|
+
salmon: '#FA8072',
|
141
|
+
chocolate: '#D2691E',
|
142
|
+
tan: '#D2B48C',
|
143
|
+
azure: '#F0FFFF',
|
144
|
+
beige: '#F5F5DC',
|
145
|
+
lavender: '#E6E6FA',
|
146
|
+
crimson: '#DC143C',
|
147
|
+
turquoise: '#40E0D0',
|
148
|
+
ivory: '#FFFFF0',
|
149
|
+
orchid: '#DA70D6',
|
150
|
+
plum: '#DDA0DD',
|
151
|
+
sienna: '#A0522D',
|
152
|
+
midnightblue: '#191970',
|
153
|
+
seashell: '#FFF5EE',
|
154
|
+
tomato: '#FF6347',
|
155
|
+
snow: '#FFFAFA',
|
156
|
+
mintcream: '#F5FFFA',
|
157
|
+
wheat: '#F5DEB3',
|
158
|
+
moccasin: '#FFE4B5',
|
159
|
+
hotpink: '#FF69B4',
|
160
|
+
skyblue: '#87CEEB',
|
161
|
+
slategray: '#708090',
|
162
|
+
darkblue: '#00008B',
|
163
|
+
darkgreen: '#006400',
|
164
|
+
darkred: '#8B0000',
|
165
|
+
lightblue: '#ADD8E6',
|
166
|
+
lightgreen: '#90EE90',
|
167
|
+
lightpink: '#FFB6C1',
|
168
|
+
lightgray: '#D3D3D3',
|
169
|
+
}
|
170
|
+
|
171
|
+
if (namedColors[color.toLowerCase()]) {
|
172
|
+
return namedColors[color.toLowerCase()]
|
173
|
+
}
|
174
|
+
|
175
|
+
const hexRegex = /^#([0-9A-F]{3}|[0-9A-F]{4}|[0-9A-F]{6}|[0-9A-F]{8})$/i
|
176
|
+
if (hexRegex.test(color)) {
|
177
|
+
return color.toUpperCase()
|
178
|
+
}
|
179
|
+
|
180
|
+
const rgbRegex =
|
181
|
+
/^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})(?:,\s*(\d?\.?\d+))?\)$/i
|
182
|
+
const rgbMatch = color.match(rgbRegex)
|
183
|
+
if (rgbMatch) {
|
184
|
+
const r = parseInt(rgbMatch[1]).toString(16).padStart(2, '0')
|
185
|
+
const g = parseInt(rgbMatch[2]).toString(16).padStart(2, '0')
|
186
|
+
const b = parseInt(rgbMatch[3]).toString(16).padStart(2, '0')
|
187
|
+
const a =
|
188
|
+
rgbMatch[4] !== undefined
|
189
|
+
? Math.round(parseFloat(rgbMatch[4]) * 255)
|
190
|
+
.toString(16)
|
191
|
+
.padStart(2, '0')
|
192
|
+
: null
|
193
|
+
|
194
|
+
return `#${r}${g}${b}${a || ''}`.toUpperCase()
|
195
|
+
}
|
196
|
+
|
197
|
+
const hslRegex =
|
198
|
+
/^hsla?\((\d{1,3}),\s*([\d.]+%)?,\s*([\d.]+%)?(?:,\s*(\d?\.?\d+))?\)$/i
|
199
|
+
const hslMatch = color.match(hslRegex)
|
200
|
+
if (hslMatch) {
|
201
|
+
const h = parseInt(hslMatch[1]) % 360
|
202
|
+
const s = parseFloat(hslMatch[2]) / 100
|
203
|
+
const l = parseFloat(hslMatch[3]) / 100
|
204
|
+
const a = hslMatch[4] !== undefined ? parseFloat(hslMatch[4]) : 1
|
205
|
+
|
206
|
+
const rgb = hslToRgb(h, s, l)
|
207
|
+
const r = rgb.r.toString(16).padStart(2, '0')
|
208
|
+
const g = rgb.g.toString(16).padStart(2, '0')
|
209
|
+
const b = rgb.b.toString(16).padStart(2, '0')
|
210
|
+
const alpha =
|
211
|
+
a < 1
|
212
|
+
? Math.round(a * 255)
|
213
|
+
.toString(16)
|
214
|
+
.padStart(2, '0')
|
215
|
+
: null
|
216
|
+
|
217
|
+
return `#${r}${g}${b}${alpha || ''}`.toUpperCase()
|
218
|
+
}
|
219
|
+
|
220
|
+
return '#00000'
|
221
|
+
}
|
222
|
+
|
223
|
+
export function hslToRgb(h, s, l) {
|
224
|
+
const c = (1 - Math.abs(2 * l - 1)) * s
|
225
|
+
const x = c * (1 - Math.abs(((h / 60) % 2) - 1))
|
226
|
+
const m = l - c / 2
|
227
|
+
|
228
|
+
let r = 0,
|
229
|
+
g = 0,
|
230
|
+
b = 0
|
231
|
+
if (h < 60) {
|
232
|
+
r = c
|
233
|
+
g = x
|
234
|
+
b = 0
|
235
|
+
} else if (h < 120) {
|
236
|
+
r = x
|
237
|
+
g = c
|
238
|
+
b = 0
|
239
|
+
} else if (h < 180) {
|
240
|
+
r = 0
|
241
|
+
g = c
|
242
|
+
b = x
|
243
|
+
} else if (h < 240) {
|
244
|
+
r = 0
|
245
|
+
g = x
|
246
|
+
b = c
|
247
|
+
} else if (h < 300) {
|
248
|
+
r = x
|
249
|
+
g = 0
|
250
|
+
b = c
|
251
|
+
} else {
|
252
|
+
r = c
|
253
|
+
g = 0
|
254
|
+
b = x
|
255
|
+
}
|
256
|
+
|
257
|
+
return {
|
258
|
+
r: Math.round((r + m) * 255),
|
259
|
+
g: Math.round((g + m) * 255),
|
260
|
+
b: Math.round((b + m) * 255),
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
export function calculateRatio(w, h) {
|
265
|
+
if (typeof w !== 'number' || typeof h !== 'number' || h === 0) {
|
266
|
+
throw new Error(
|
267
|
+
'Les paramètres doivent être des nombres, et h ne doit pas être 0',
|
268
|
+
)
|
269
|
+
}
|
270
|
+
|
271
|
+
return (w / h).toFixed(2)
|
272
|
+
}
|
273
|
+
|
274
|
+
export async function imageBase64ToBuffer(base64Content) {
|
275
|
+
if (!base64Content.startsWith('data:')) {
|
276
|
+
return undefined
|
277
|
+
}
|
278
|
+
|
279
|
+
const mimeTypeMatch = base64Content.match(/^data:(.+);base64,/)
|
280
|
+
if (!mimeTypeMatch) {
|
281
|
+
return undefined
|
282
|
+
}
|
283
|
+
|
284
|
+
const mimeType = mimeTypeMatch[1]
|
285
|
+
|
286
|
+
const base64Data = base64Content.replace(/^data:.+;base64,/, '')
|
287
|
+
|
288
|
+
const buffer = Buffer.from(base64Data, 'base64')
|
289
|
+
|
290
|
+
const mimeToExtension = {
|
291
|
+
'image/png': 'png',
|
292
|
+
'image/jpeg': 'jpg',
|
293
|
+
'image/jpg': 'jpg',
|
294
|
+
'image/gif': 'gif',
|
295
|
+
'image/webp': 'webp',
|
296
|
+
'image/svg+xml': 'svg',
|
297
|
+
}
|
298
|
+
|
299
|
+
const extension = mimeToExtension[mimeType]
|
300
|
+
if (!extension) {
|
301
|
+
return undefined
|
302
|
+
}
|
303
|
+
|
304
|
+
const metadata = await sharp(buffer).metadata()
|
305
|
+
const { width, height } = metadata
|
306
|
+
|
307
|
+
if (!width || !height) {
|
308
|
+
return undefined
|
309
|
+
}
|
310
|
+
|
311
|
+
const ratio = calculateRatio(width, height)
|
312
|
+
|
313
|
+
return { mimeType, extension, buffer, width, height, ratio }
|
314
|
+
}
|
315
|
+
|
316
|
+
export function random(length) {
|
317
|
+
return Math.random().toString(36).substring(length)
|
318
|
+
}
|
319
|
+
|
320
|
+
export function convertCssToDocxMeasurement(cssValue) {
|
321
|
+
const auto = { size: 0, type: 'nil' }
|
322
|
+
|
323
|
+
if (typeof cssValue !== 'string') {
|
324
|
+
return auto
|
325
|
+
}
|
326
|
+
|
327
|
+
if (cssValue.endsWith('%')) {
|
328
|
+
const percentage = parseFloat(cssValue)
|
329
|
+
|
330
|
+
if (isNaN(percentage)) {
|
331
|
+
return auto
|
332
|
+
}
|
333
|
+
|
334
|
+
return { size: percentage, type: 'pct' }
|
335
|
+
}
|
336
|
+
|
337
|
+
if (cssValue === 'auto' || cssValue === '0' || cssValue === 'none') {
|
338
|
+
return auto
|
339
|
+
}
|
340
|
+
|
341
|
+
if (cssValue.endsWith('px')) {
|
342
|
+
const pixels = parseFloat(cssValue)
|
343
|
+
if (isNaN(pixels)) {
|
344
|
+
return auto
|
345
|
+
}
|
346
|
+
|
347
|
+
return { size: Math.round(pixels * 15), type: 'dxa' }
|
348
|
+
}
|
349
|
+
|
350
|
+
if (cssValue.endsWith('pt')) {
|
351
|
+
const points = parseFloat(cssValue)
|
352
|
+
if (isNaN(points)) {
|
353
|
+
return auto
|
354
|
+
}
|
355
|
+
|
356
|
+
return { size: Math.round(points * 20), type: 'dxa' }
|
357
|
+
}
|
358
|
+
|
359
|
+
return auto
|
360
|
+
}
|
361
|
+
|
362
|
+
/**
|
363
|
+
* Convertit une valeur CSS de marge (ex: "15px", "10px 20px", "5px 10px 15px 20px")
|
364
|
+
* en un objet avec `top`, `left`, `bottom`, et `right` (espacement en twips).
|
365
|
+
*
|
366
|
+
* @param cssMargin - Une chaîne représentant les marges CSS.
|
367
|
+
* @returns Un objet contenant les marges `top`, `left`, `bottom`, et `right` en twips.
|
368
|
+
*/
|
369
|
+
export function parseCssMargin(cssMargin) {
|
370
|
+
const toTwips = value => {
|
371
|
+
if (value.endsWith('px')) {
|
372
|
+
return Math.round(parseFloat(value) * 15)
|
373
|
+
}
|
374
|
+
if (value.endsWith('pt')) {
|
375
|
+
return Math.round(parseFloat(value) * 20)
|
376
|
+
}
|
377
|
+
return 0
|
378
|
+
}
|
379
|
+
|
380
|
+
const parts = cssMargin.split(' ').map(part => part.trim())
|
381
|
+
|
382
|
+
let top, right, bottom, left
|
383
|
+
|
384
|
+
if (parts.length === 1) {
|
385
|
+
top = right = bottom = left = toTwips(parts[0])
|
386
|
+
} else if (parts.length === 2) {
|
387
|
+
top = bottom = toTwips(parts[0])
|
388
|
+
right = left = toTwips(parts[1])
|
389
|
+
} else if (parts.length === 3) {
|
390
|
+
top = toTwips(parts[0])
|
391
|
+
right = left = toTwips(parts[1])
|
392
|
+
bottom = toTwips(parts[2])
|
393
|
+
} else if (parts.length === 4) {
|
394
|
+
top = toTwips(parts[0])
|
395
|
+
right = toTwips(parts[1])
|
396
|
+
bottom = toTwips(parts[2])
|
397
|
+
left = toTwips(parts[3])
|
398
|
+
} else {
|
399
|
+
top = right = bottom = left = 0
|
400
|
+
}
|
401
|
+
|
402
|
+
return { top, right, bottom, left }
|
403
|
+
}
|
404
|
+
|
405
|
+
export function getListItemNumber(styleType, start) {
|
406
|
+
function toRoman(num, isUpper = false) {
|
407
|
+
const romanNumerals = [
|
408
|
+
{ value: 1000, numeral: 'M' },
|
409
|
+
{ value: 900, numeral: 'CM' },
|
410
|
+
{ value: 500, numeral: 'D' },
|
411
|
+
{ value: 400, numeral: 'CD' },
|
412
|
+
{ value: 100, numeral: 'C' },
|
413
|
+
{ value: 90, numeral: 'XC' },
|
414
|
+
{ value: 50, numeral: 'L' },
|
415
|
+
{ value: 40, numeral: 'XL' },
|
416
|
+
{ value: 10, numeral: 'X' },
|
417
|
+
{ value: 9, numeral: 'IX' },
|
418
|
+
{ value: 5, numeral: 'V' },
|
419
|
+
{ value: 4, numeral: 'IV' },
|
420
|
+
{ value: 1, numeral: 'I' },
|
421
|
+
]
|
422
|
+
|
423
|
+
let result = ''
|
424
|
+
let tempNum = num
|
425
|
+
|
426
|
+
for (let i = 0; i < romanNumerals.length; i++) {
|
427
|
+
while (tempNum >= romanNumerals[i].value) {
|
428
|
+
result += romanNumerals[i].numeral
|
429
|
+
tempNum -= romanNumerals[i].value
|
430
|
+
}
|
431
|
+
}
|
432
|
+
|
433
|
+
return isUpper ? result.toUpperCase() : result.toLowerCase()
|
434
|
+
}
|
435
|
+
|
436
|
+
function toAlpha(num, isUpper = false) {
|
437
|
+
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
|
438
|
+
let result = ''
|
439
|
+
while (num > 0) {
|
440
|
+
num--
|
441
|
+
result = alphabet[num % 26] + result
|
442
|
+
num = Math.floor(num / 26)
|
443
|
+
}
|
444
|
+
return isUpper ? result.toUpperCase() : result.toLowerCase()
|
445
|
+
}
|
446
|
+
|
447
|
+
function toGreek(num, isUpper = false) {
|
448
|
+
const greekAlphabet = [
|
449
|
+
'α',
|
450
|
+
'β',
|
451
|
+
'γ',
|
452
|
+
'δ',
|
453
|
+
'ε',
|
454
|
+
'ζ',
|
455
|
+
'η',
|
456
|
+
'θ',
|
457
|
+
'ι',
|
458
|
+
'κ',
|
459
|
+
'λ',
|
460
|
+
'μ',
|
461
|
+
'ν',
|
462
|
+
'ξ',
|
463
|
+
'ο',
|
464
|
+
'π',
|
465
|
+
'ρ',
|
466
|
+
'σ',
|
467
|
+
'τ',
|
468
|
+
'υ',
|
469
|
+
'φ',
|
470
|
+
'χ',
|
471
|
+
'ψ',
|
472
|
+
'ω',
|
473
|
+
]
|
474
|
+
let result = greekAlphabet[(num - 1) % 24]
|
475
|
+
return isUpper ? result.toUpperCase() : result.toLowerCase()
|
476
|
+
}
|
477
|
+
|
478
|
+
function toLetter(num, isUpper = false) {
|
479
|
+
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
|
480
|
+
let letter = alphabet[(num - 1) % 26]
|
481
|
+
return isUpper ? letter.toUpperCase() : letter.toLowerCase()
|
482
|
+
}
|
483
|
+
|
484
|
+
switch (styleType) {
|
485
|
+
case 'decimal':
|
486
|
+
return start
|
487
|
+
case 'upper-roman':
|
488
|
+
return toRoman(start, true)
|
489
|
+
case 'lower-roman':
|
490
|
+
return toRoman(start, false)
|
491
|
+
case 'upper-alpha':
|
492
|
+
return toAlpha(start, true)
|
493
|
+
case 'lower-alpha':
|
494
|
+
return toAlpha(start, false)
|
495
|
+
case 'upper-letter':
|
496
|
+
return toLetter(start, true)
|
497
|
+
case 'lower-letter':
|
498
|
+
return toLetter(start, false)
|
499
|
+
case 'upper-greek':
|
500
|
+
return toGreek(start, true)
|
501
|
+
case 'lower-greek':
|
502
|
+
return toGreek(start, false)
|
503
|
+
case 'circle':
|
504
|
+
return '○'
|
505
|
+
case 'disc':
|
506
|
+
return '•'
|
507
|
+
case 'square':
|
508
|
+
return '▪'
|
509
|
+
case 'none':
|
510
|
+
return ''
|
511
|
+
default:
|
512
|
+
return start
|
513
|
+
}
|
514
|
+
}
|
515
|
+
|
516
|
+
export function getWordIndent(level) {
|
517
|
+
const baseIndent = 720 // 720 TWIP = 0.5 pouce
|
518
|
+
const hangingIndent = 360 // 360 TWIP = 0.25 pouce
|
519
|
+
|
520
|
+
const left = level * baseIndent
|
521
|
+
|
522
|
+
return {
|
523
|
+
left: left,
|
524
|
+
hanging: hangingIndent,
|
525
|
+
}
|
526
|
+
}
|
527
|
+
|
528
|
+
export default {
|
529
|
+
normalizeHtml,
|
530
|
+
pageNodes,
|
531
|
+
trim,
|
532
|
+
colorToHex,
|
533
|
+
hslToRgb,
|
534
|
+
normalizeMeasure,
|
535
|
+
splitMeasure,
|
536
|
+
capitalize,
|
537
|
+
calculateRatio,
|
538
|
+
arrayToNodeHTMLElement,
|
539
|
+
imageBase64ToBuffer,
|
540
|
+
convertCssToDocxMeasurement,
|
541
|
+
random,
|
542
|
+
parseCssMargin,
|
543
|
+
getListItemNumber,
|
544
|
+
}
|
package/src/index.d.ts
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
// index.d.ts
|
2
|
+
|
3
|
+
declare module "html-to-docx" {
|
4
|
+
/**
|
5
|
+
* Options pour la conversion HTML en DOCX.
|
6
|
+
*/
|
7
|
+
interface HtmlToDocxOptions {
|
8
|
+
/**
|
9
|
+
* Définit le nom du fichier DOCX généré.
|
10
|
+
*/
|
11
|
+
fileName?: string;
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Définit les marges du document.
|
15
|
+
* Exemple : { top: 1, bottom: 1, left: 1, right: 1 }
|
16
|
+
*/
|
17
|
+
margins?: {
|
18
|
+
top?: string;
|
19
|
+
bottom?: string;
|
20
|
+
left?: string;
|
21
|
+
right?: string;
|
22
|
+
};
|
23
|
+
}
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Convertit un contenu HTML en un fichier DOCX.
|
27
|
+
*
|
28
|
+
* @param html - Le contenu HTML à convertir.
|
29
|
+
* @param options - Les options de configuration pour la conversion.
|
30
|
+
* @returns Une promesse qui se résout en un `ArrayBuffer` contenant les données du fichier DOCX.
|
31
|
+
*/
|
32
|
+
function htmlToDocx(
|
33
|
+
html: string,
|
34
|
+
options?: HtmlToDocxOptions
|
35
|
+
): Promise<ArrayBuffer>;
|
36
|
+
|
37
|
+
export default htmlToDocx;
|
38
|
+
}
|
39
|
+
|