更新采购订单、发货、合同查询、盘点、入库和配置文件,新增零改单和文档
This commit is contained in:
237
scripts/markdown-to-pdf.js
Normal file
237
scripts/markdown-to-pdf.js
Normal file
@@ -0,0 +1,237 @@
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
|
||||
const input = process.argv[2]
|
||||
const output = process.argv[3]
|
||||
|
||||
if (!input || !output) {
|
||||
console.error('Usage: node scripts/markdown-to-pdf.js <input.md> <output.html>')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const markdown = fs.readFileSync(input, 'utf8')
|
||||
|
||||
function escapeHtml(value) {
|
||||
return value
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
}
|
||||
|
||||
function inlineFormat(value) {
|
||||
return escapeHtml(value)
|
||||
.replace(/`([^`]+)`/g, '<code>$1</code>')
|
||||
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
|
||||
}
|
||||
|
||||
function renderTable(lines) {
|
||||
const rows = lines
|
||||
.filter(line => line.trim())
|
||||
.map(line => line.trim().replace(/^\|/, '').replace(/\|$/, '').split('|').map(cell => inlineFormat(cell.trim())))
|
||||
|
||||
if (rows.length < 2) return ''
|
||||
|
||||
const head = rows[0]
|
||||
const body = rows.slice(2)
|
||||
return [
|
||||
'<table>',
|
||||
'<thead><tr>' + head.map(cell => '<th>' + cell + '</th>').join('') + '</tr></thead>',
|
||||
'<tbody>',
|
||||
body.map(row => '<tr>' + row.map(cell => '<td>' + cell + '</td>').join('') + '</tr>').join('\n'),
|
||||
'</tbody>',
|
||||
'</table>'
|
||||
].join('\n')
|
||||
}
|
||||
|
||||
function renderMarkdown(text) {
|
||||
const lines = text.replace(/\r\n/g, '\n').split('\n')
|
||||
const html = []
|
||||
let paragraph = []
|
||||
let list = []
|
||||
let code = []
|
||||
let inCode = false
|
||||
let table = []
|
||||
|
||||
function flushParagraph() {
|
||||
if (paragraph.length) {
|
||||
html.push('<p>' + inlineFormat(paragraph.join(' ')) + '</p>')
|
||||
paragraph = []
|
||||
}
|
||||
}
|
||||
|
||||
function flushList() {
|
||||
if (list.length) {
|
||||
html.push('<ul>' + list.map(item => '<li>' + inlineFormat(item) + '</li>').join('') + '</ul>')
|
||||
list = []
|
||||
}
|
||||
}
|
||||
|
||||
function flushTable() {
|
||||
if (table.length) {
|
||||
html.push(renderTable(table))
|
||||
table = []
|
||||
}
|
||||
}
|
||||
|
||||
lines.forEach(line => {
|
||||
if (/^```/.test(line.trim())) {
|
||||
if (inCode) {
|
||||
html.push('<pre><code>' + escapeHtml(code.join('\n')) + '</code></pre>')
|
||||
code = []
|
||||
inCode = false
|
||||
} else {
|
||||
flushParagraph()
|
||||
flushList()
|
||||
flushTable()
|
||||
inCode = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (inCode) {
|
||||
code.push(line)
|
||||
return
|
||||
}
|
||||
|
||||
if (/^\|.*\|$/.test(line.trim())) {
|
||||
flushParagraph()
|
||||
flushList()
|
||||
table.push(line)
|
||||
return
|
||||
}
|
||||
|
||||
flushTable()
|
||||
|
||||
if (!line.trim()) {
|
||||
flushParagraph()
|
||||
flushList()
|
||||
return
|
||||
}
|
||||
|
||||
const heading = line.match(/^(#{1,6})\s+(.+)$/)
|
||||
if (heading) {
|
||||
flushParagraph()
|
||||
flushList()
|
||||
const level = heading[1].length
|
||||
html.push('<h' + level + '>' + inlineFormat(heading[2]) + '</h' + level + '>')
|
||||
return
|
||||
}
|
||||
|
||||
const image = line.match(/^!\[([^\]]*)\]\(([^)]+)\)$/)
|
||||
if (image) {
|
||||
flushParagraph()
|
||||
flushList()
|
||||
html.push('<figure><img src="' + escapeHtml(image[2]) + '" alt="' + escapeHtml(image[1]) + '"><figcaption>' + inlineFormat(image[1]) + '</figcaption></figure>')
|
||||
return
|
||||
}
|
||||
|
||||
const listItem = line.match(/^- (.+)$/)
|
||||
if (listItem) {
|
||||
flushParagraph()
|
||||
list.push(listItem[1])
|
||||
return
|
||||
}
|
||||
|
||||
paragraph.push(line.trim())
|
||||
})
|
||||
|
||||
flushParagraph()
|
||||
flushList()
|
||||
flushTable()
|
||||
|
||||
return html.join('\n')
|
||||
}
|
||||
|
||||
const body = renderMarkdown(markdown)
|
||||
const html = `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>零件改制功能设计方案</title>
|
||||
<style>
|
||||
@page { size: A4; margin: 18mm 16mm; }
|
||||
body {
|
||||
font-family: "Microsoft YaHei", "SimSun", Arial, sans-serif;
|
||||
color: #1f2933;
|
||||
font-size: 13px;
|
||||
line-height: 1.65;
|
||||
}
|
||||
h1 {
|
||||
font-size: 26px;
|
||||
text-align: center;
|
||||
margin: 0 0 24px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 2px solid #2f80ed;
|
||||
}
|
||||
h2 {
|
||||
font-size: 19px;
|
||||
margin: 24px 0 10px;
|
||||
padding-left: 8px;
|
||||
border-left: 4px solid #2f80ed;
|
||||
page-break-after: avoid;
|
||||
}
|
||||
h3 {
|
||||
font-size: 16px;
|
||||
margin: 18px 0 8px;
|
||||
page-break-after: avoid;
|
||||
}
|
||||
p { margin: 7px 0; }
|
||||
ul { margin: 6px 0 10px 22px; padding: 0; }
|
||||
li { margin: 3px 0; }
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 10px 0 16px;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #cbd5e1;
|
||||
padding: 6px 8px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
word-break: break-word;
|
||||
}
|
||||
th {
|
||||
background: #eef4ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
code {
|
||||
font-family: Consolas, "Microsoft YaHei", monospace;
|
||||
background: #f3f4f6;
|
||||
padding: 1px 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
pre {
|
||||
background: #f8fafc;
|
||||
border: 1px solid #d8dee9;
|
||||
padding: 10px;
|
||||
overflow-wrap: break-word;
|
||||
white-space: pre-wrap;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
figure {
|
||||
margin: 14px 0 20px;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
figure img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border: 1px solid #d8dee9;
|
||||
}
|
||||
figcaption {
|
||||
margin-top: 6px;
|
||||
color: #64748b;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
${body}
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
fs.writeFileSync(output, html, 'utf8')
|
||||
Reference in New Issue
Block a user