How to Turn Word Docs into Vue Components with mammoth.js
This article explains how to use the open‑source mammoth.js library to convert Word (.docx) documents into clean HTML, customize the AST to fix layout issues, and automatically generate Vue component files, dramatically streamlining documentation integration in frontend projects.
When building backend management systems, developers often need to convert Word documents such as user agreements into HTML pages or Vue components. The open‑source library mammoth.js can unzip .docx files and parse their XML structure, turning Word into HTML. By customizing mammoth, we can automate the conversion into Vue components and improve efficiency.
mammoth.js Limitations
Although mammoth.js can generate HTML directly, several problems appear with typical Word files, such as misaligned titles, lost list numbering, mismatched styles, non‑interactive hyperlinks, and unexpected table rendering.
Transformation
To meet project requirements we customize mammoth by accessing its conversion AST. The workflow extracts the AST, transforms nodes, and finally emits a usable Vue file.
Parse AST
First we obtain the AST.
var options = {
transformDocument: transformElement,
};
mammoth.convertToHtml({ path }, options).done(async () => {
// Word processing completed
});AST Nodes
Each node indicates its type, alignment, font size, bold, italic, underline, etc. Types include:
Document (root)
Paragraph
Text
Run (a paragraph split into parts, requiring child text concatenation)
hyperlink
Table
tableRow
tableCell
Handle AST Nodes
Key considerations when processing nodes:
When type: 'paragraph', children: [] appears, a line break is needed.
Centered text with font size 16 is treated as a main title; centered text with font size 14 as a subtitle.
Paragraph indentation is added manually using four non‑breaking spaces: .
Bold and font size are expressed via common CSS classes, e.g., 'bold' 'font-size-14' 'font-size-16'. Spaces are replaced with . Hyperlinks become
<a target="_blank" class="blue" href="${txt.href}">${txt.children[0].value}</a>.
List numbering is derived from the node's numbering field; if present, convert Arabic numbers to Chinese numerals.
Table handling: the first child is a thead tag, followed by tbody. Table cells contain paragraph nodes processed recursively via handleParagraph.
Below is the core logic for processing paragraphs and tables.
function transformElement(element) {
// root node
const document = element.children;
if (Array.isArray(document)) {
document.forEach(ele => {
switch (ele.type) {
case 'paragraph':
str += handleParagraph(ele);
break;
case 'table':
handleTable(ele);
break;
default:
break;
}
});
}
return element;
}Code Formatting and Generation
We concatenate strings to form the Vue component source.
const originalStr = `<template>
...
</template>
<script>
// ...
</script>
<style lang="less" scoped>
// ...
</style>
`;Component names are generated automatically by translating the Chinese document title using translate-shell .
// Read the .docx path, translate the name, and generate template and file names
function getTranslatedNames(path) {
return new Promise(resolve => {
const chArr = path.replace('.docx', '').split('/');
exec(`trans -t english '${chArr[chArr.length - 1]}'`, (error, stdout, stderr) => {
const arr = stdout.split('
');
// ...
resolve(target.replace(/[^a-zA-Z-]/gi, ''));
});
});
}Finally, the generated code is formatted with prettier and written to a .vue file.
// Format
const finalStr = prettier.format(originalStr, config);
fs.writeFileSync(`${templateName}.vue`, finalStr, 'utf-8');Conclusion
In short, this tool builds on mammoth.js, leverages its AST, and applies project‑specific transformations to produce Vue components that match UI specifications. The approach simplifies Word‑to‑Vue conversion and is highly recommended.
References
[1]mammoth.js: https://github.com/mwilliamson/mammoth.js [2] translate-shell: https://www.soimort.org/translate-shell/
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
