fix(word): strip HTML style blocks and alignment divs from DOCX input

Pre-process markdown before Word/DOCX export to remove raw HTML artifacts

(<style> blocks, HTML comments, and <div align=...> tags) that were

visible in the generated document. Applies to single and batch DOCX exports

via both Pandoc and WordTemplateExporter paths.
This commit is contained in:
2026-06-30 13:57:29 +05:30
parent d705cfc30b
commit e72b863362
3 changed files with 139 additions and 5 deletions
+56 -4
View File
@@ -2562,7 +2562,23 @@ function performExportWithOptions(format, options) {
// Use pandoc for export with advanced options
let pandocCmd = `${getPandocPath()} "${currentFile}" -o "${outputFile}"`;
let inputFile = currentFile;
let tempInputFile = null;
// Pre-process markdown for Word output so that <style> blocks, HTML
// comments, and alignment <div> tags do not appear as visible text.
if (format === 'docx') {
const content = fs.readFileSync(currentFile, 'utf-8');
const cleanedContent = WordTemplateExporter.preprocessMarkdownForWordExport(content);
tempInputFile = path.join(
require('os').tmpdir(),
`mc_export_${Date.now()}_${path.basename(currentFile)}`
);
fs.writeFileSync(tempInputFile, cleanedContent, 'utf-8');
inputFile = tempInputFile;
}
let pandocCmd = `${getPandocPath()} "${inputFile}" -o "${outputFile}"`;
// Add template if specified
if (options.template && options.template !== 'default') {
@@ -2657,7 +2673,15 @@ function performExportWithOptions(format, options) {
});
} else if (format === 'docx') {
pandocCmd += ' -t docx';
exportWithPandoc(pandocCmd, outputFile, format);
exportWithPandoc(pandocCmd, outputFile, format, () => {
if (tempInputFile) {
try {
fs.unlinkSync(tempInputFile);
} catch {
// Ignore cleanup errors
}
}
});
} else if (format === 'pptx') {
// Add PowerPoint footer if enabled
if (headerFooterSettings.enabled && headerFooterSettings.footer.center) {
@@ -2859,7 +2883,7 @@ function showExportSuccess(outputFile) {
}
// Helper function to export with pandoc (general) - uses runPandocCmd for safety
function exportWithPandoc(pandocCmd, outputFile, format) {
function exportWithPandoc(pandocCmd, outputFile, format, onComplete) {
runPandocCmd(pandocCmd, async (error, stdout, stderr) => {
if (error) {
console.error(`Pandoc error for ${format}:`, error);
@@ -2924,6 +2948,9 @@ function exportWithPandoc(pandocCmd, outputFile, format) {
}
showExportSuccess(outputFile);
}
if (typeof onComplete === 'function') {
onComplete(error);
}
});
}
@@ -3749,7 +3776,23 @@ async function performBatchConversion(inputFolder, outputFolder, format, options
}
// Build pandoc command for other formats
let pandocCmd = `${getPandocPath()} "${inputFile}" -o "${outputFile}"`;
let pandocInputFile = inputFile;
let batchTempInputFile = null;
// Pre-process markdown for Word output so that <style> blocks, HTML
// comments, and alignment <div> tags do not appear as visible text.
if (format === 'docx') {
const content = fs.readFileSync(inputFile, 'utf-8');
const cleanedContent = WordTemplateExporter.preprocessMarkdownForWordExport(content);
batchTempInputFile = path.join(
require('os').tmpdir(),
`mc_batch_export_${Date.now()}_${path.basename(inputFile)}`
);
fs.writeFileSync(batchTempInputFile, cleanedContent, 'utf-8');
pandocInputFile = batchTempInputFile;
}
let pandocCmd = `${getPandocPath()} "${pandocInputFile}" -o "${outputFile}"`;
// Add template if specified
if (options.template && options.template !== 'default') {
@@ -3850,6 +3893,15 @@ async function performBatchConversion(inputFolder, outputFolder, format, options
// Execute conversion (using runPandocCmd for safety)
runPandocCmd(pandocCmd, async (error, _stdout, stderr) => {
// Clean up temporary pre-processed input file
if (batchTempInputFile) {
try {
fs.unlinkSync(batchTempInputFile);
} catch {
// Ignore cleanup errors
}
}
if (error) {
console.error(`Batch: Failed to convert ${path.basename(inputFile)}:`, error.message, stderr);
} else {
+22 -1
View File
@@ -15,6 +15,26 @@ class WordTemplateExporter {
this.pageSettings = pageSettings; // Page size and orientation settings
}
/**
* Strip HTML artifacts that Pandoc / Word cannot render and that would
* otherwise appear as visible text in DOCX output.
* Removes HTML comments, <style> blocks, and alignment <div> tags.
*/
static preprocessMarkdownForWordExport(markdown) {
if (typeof markdown !== 'string') return markdown;
return (
markdown
// HTML comments (multi-line)
.replace(/<!--[\s\S]*?-->/g, '')
// <style> blocks (case-insensitive, multi-line)
.replace(/<style\b[\s\S]*?<\/style>/gi, '')
// Opening <div align="..."> tags
.replace(/<div\b[^>]*?\balign\s*=\s*["'][^"']*["'][^>]*>/gi, '')
// Closing </div> tags
.replace(/<\/div\s*>/gi, '')
);
}
/**
* Convert markdown to Word document using template
*/
@@ -33,7 +53,8 @@ class WordTemplateExporter {
}
// Parse markdown and generate Word XML
const newContentXml = this.markdownToWordXml(markdownContent);
const cleanedContent = WordTemplateExporter.preprocessMarkdownForWordExport(markdownContent);
const newContentXml = this.markdownToWordXml(cleanedContent);
// Insert new content after the specified start page
const modifiedXml = this.insertContentAfterPage(documentXml, newContentXml, this.startPage);