markdown-paper 2.2.1 → 2.2.3
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 +2 -2
- package/lib/main.ts +45 -24
- package/package.json +1 -1
- package/theme/aps/aps.ts +146 -10
- package/theme/theme.ts +6 -18
package/README.md
CHANGED
|
@@ -84,9 +84,9 @@ mdp example.md --outputDOCX
|
|
|
84
84
|
| `--outputDOCX` | 输出 `DOCX` 文件, 默认不输出<br>**须先通过 `python` 安装依赖 `pdf2docx`**<br>使用时推荐开启 `--hideFooter` 参数 |
|
|
85
85
|
|
|
86
86
|
# 模板说明
|
|
87
|
-
`/theme/theme.ts` 中的 `
|
|
87
|
+
`/theme/theme.ts` 中的 `MarkdownnPaperTheme` 接口定义了模板的样式, 按照类似于 `aps` 文件夹的结构可自定义模板; 模板可以提供自定义功能
|
|
88
88
|
|
|
89
|
-
模板制作完成后, 在 `/lib/main.ts` 中导入并添加到 `class
|
|
89
|
+
模板制作完成后, 在 `/lib/main.ts` 中导入并添加到 `class MarkdownPaperOptions -> constructor -> case '--theme':` 中, 并在下方添加使用文档即可
|
|
90
90
|
|
|
91
91
|
推荐所有主题的文档和编写格式都尽量与 `aps` 主题保持一致
|
|
92
92
|
|
package/lib/main.ts
CHANGED
|
@@ -4,7 +4,7 @@ import fs from 'node:fs/promises'
|
|
|
4
4
|
import path from 'node:path'
|
|
5
5
|
import { readFileSync } from 'node:fs'
|
|
6
6
|
import { APS } from '../theme/aps/aps'
|
|
7
|
-
import { MarkdownPaperTheme } from '../theme/theme'
|
|
7
|
+
import type { MarkdownPaperTheme } from '../theme/theme'
|
|
8
8
|
import type { PDFOptions } from 'puppeteer'
|
|
9
9
|
|
|
10
10
|
/** 应用参数 */
|
|
@@ -40,7 +40,7 @@ class MarkdownPaperOptions {
|
|
|
40
40
|
this.out = ''
|
|
41
41
|
this.outputHTML = false
|
|
42
42
|
this.outputDOCX = false
|
|
43
|
-
this.theme = new APS(args
|
|
43
|
+
this.theme = new APS(args)
|
|
44
44
|
// 解析路径参数
|
|
45
45
|
if (args.length === 0) throw SyntaxError()
|
|
46
46
|
else args[0] = `--src=${args[0]}`
|
|
@@ -90,32 +90,14 @@ class MarkdownPaperOptions {
|
|
|
90
90
|
/**
|
|
91
91
|
* 渲染 markdown
|
|
92
92
|
* @param options 参数
|
|
93
|
-
* @param rawMarkdown 如果传入此参数, 则不再读取文件
|
|
94
93
|
*/
|
|
95
94
|
async function renderMarkdown(
|
|
96
95
|
options: MarkdownPaperOptions,
|
|
97
|
-
rawMarkdown?: string,
|
|
98
96
|
): Promise<void> {
|
|
99
97
|
// 读取 markdown 文件
|
|
100
|
-
const raw =
|
|
101
|
-
//
|
|
102
|
-
const
|
|
103
|
-
// 转换 markdown 为 html
|
|
104
|
-
let html = `
|
|
105
|
-
<!DOCTYPE html>
|
|
106
|
-
<html lang="zh-CN">
|
|
107
|
-
<head>
|
|
108
|
-
<meta charset="UTF-8">
|
|
109
|
-
<title>${path.basename(options.src).replace('.md', '')}</title>
|
|
110
|
-
<style>${options.theme.css}</style>
|
|
111
|
-
</head>
|
|
112
|
-
<body>
|
|
113
|
-
${await marked(md)}
|
|
114
|
-
</body>
|
|
115
|
-
</html>
|
|
116
|
-
`
|
|
117
|
-
// 预处理 html
|
|
118
|
-
html = await options.theme.preParseHTML(html)
|
|
98
|
+
const raw = await fs.readFile(options.src, { encoding: 'utf-8' })
|
|
99
|
+
// 生成 html 文件
|
|
100
|
+
const html = await mdToHtml(raw, options.theme, path.basename(options.src).replace('.md', ''))
|
|
119
101
|
// 保存 html 文件
|
|
120
102
|
options.outputHTML && await fs.writeFile(options.out.replace('.pdf', '.html'), html)
|
|
121
103
|
// 保存 pdf 文件
|
|
@@ -180,10 +162,49 @@ function pdfToDocx(pdfPath: string): Promise<void> {
|
|
|
180
162
|
})
|
|
181
163
|
}
|
|
182
164
|
|
|
165
|
+
/**
|
|
166
|
+
* 把 markdown 转换为 html
|
|
167
|
+
* @important 浏览器环境中可用
|
|
168
|
+
* @param md markdown 字符串
|
|
169
|
+
* @param theme 论文模板
|
|
170
|
+
* @param pageTitle 页面标题
|
|
171
|
+
* @returns html 字符串
|
|
172
|
+
*/
|
|
173
|
+
async function mdToHtml(
|
|
174
|
+
md: string,
|
|
175
|
+
theme: MarkdownPaperTheme,
|
|
176
|
+
pageTitle: string = 'MarkdownPaper'
|
|
177
|
+
): Promise<string> {
|
|
178
|
+
// 预处理 markdown
|
|
179
|
+
let html = await theme.preParseMarkdown(md)
|
|
180
|
+
// 转换 markdown 为 html
|
|
181
|
+
html = `
|
|
182
|
+
<!DOCTYPE html>
|
|
183
|
+
<html lang="zh-CN">
|
|
184
|
+
<head>
|
|
185
|
+
<meta charset="UTF-8">
|
|
186
|
+
<title>${pageTitle}</title>
|
|
187
|
+
<style>${theme.css}</style>
|
|
188
|
+
</head>
|
|
189
|
+
<body>
|
|
190
|
+
${await marked(html)}
|
|
191
|
+
</body>
|
|
192
|
+
</html>
|
|
193
|
+
`
|
|
194
|
+
// 预处理 html
|
|
195
|
+
html = await theme.preParseHTML(html)
|
|
196
|
+
return html
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
|
|
183
200
|
export {
|
|
184
|
-
MarkdownPaperTheme,
|
|
185
201
|
MarkdownPaperOptions,
|
|
186
202
|
renderMarkdown,
|
|
187
203
|
htmlToPdf,
|
|
188
204
|
pdfToDocx,
|
|
205
|
+
mdToHtml,
|
|
206
|
+
APS
|
|
207
|
+
}
|
|
208
|
+
export type {
|
|
209
|
+
MarkdownPaperTheme
|
|
189
210
|
}
|
package/package.json
CHANGED
package/theme/aps/aps.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { MarkdownPaperTheme } from '../theme'
|
|
2
|
-
import {
|
|
3
|
-
import { resolve } from 'node:path'
|
|
4
|
-
import type { PDFOptions } from 'puppeteer-core'
|
|
1
|
+
import type { MarkdownPaperTheme } from '../theme'
|
|
2
|
+
import type { PDFOptions } from 'puppeteer'
|
|
5
3
|
|
|
6
|
-
export class APS
|
|
4
|
+
export class APS implements MarkdownPaperTheme {
|
|
7
5
|
|
|
8
6
|
css: string
|
|
9
7
|
preParseMarkdown: (md: string) => Promise<string>
|
|
@@ -11,10 +9,10 @@ export class APS extends MarkdownPaperTheme {
|
|
|
11
9
|
script: () => void
|
|
12
10
|
pdfOptions: PDFOptions
|
|
13
11
|
|
|
14
|
-
constructor(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
constructor(
|
|
13
|
+
args: string[] = [],
|
|
14
|
+
) {
|
|
15
|
+
|
|
18
16
|
// 默认自定义参数
|
|
19
17
|
let showTitle: boolean = false
|
|
20
18
|
let hideFooter: boolean = false
|
|
@@ -31,7 +29,145 @@ export class APS extends MarkdownPaperTheme {
|
|
|
31
29
|
})
|
|
32
30
|
|
|
33
31
|
// css
|
|
34
|
-
this.css =
|
|
32
|
+
this.css = `
|
|
33
|
+
* {
|
|
34
|
+
font-family: 'Times', 'Times New Roman', '宋体', 'SimSun', '华文宋体', 'STSong'; /* 所有数字和英文字体都用 Times New Roman */
|
|
35
|
+
line-height: 1.55em; /* 1.5倍行距 */
|
|
36
|
+
margin: 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
h1 { /* 中文题目: 二号黑体 */
|
|
40
|
+
font-size: 29px;
|
|
41
|
+
font-weight: normal;
|
|
42
|
+
font-family: '黑体', 'SimHei', '华文黑体', 'STHeiti';
|
|
43
|
+
text-align: center;
|
|
44
|
+
margin-bottom: 9px;
|
|
45
|
+
}
|
|
46
|
+
.author { /* 作者姓名: 四号仿宋 */
|
|
47
|
+
font-size: 18px;
|
|
48
|
+
font-weight: normal;
|
|
49
|
+
font-family: '仿宋', 'Fangsong', '华文仿宋', 'STFangsong';
|
|
50
|
+
text-align: center;
|
|
51
|
+
margin-bottom: 3px;
|
|
52
|
+
}
|
|
53
|
+
.school { /* 作者单位: 小五宋体 */
|
|
54
|
+
font-size: 12px;
|
|
55
|
+
text-align: center;
|
|
56
|
+
margin-bottom: 38px;
|
|
57
|
+
}
|
|
58
|
+
.abstract { /* 摘要和关键词: 五号宋体 */
|
|
59
|
+
font-size: 14px;
|
|
60
|
+
text-align: justify;
|
|
61
|
+
padding: 0 28px;
|
|
62
|
+
&::before {
|
|
63
|
+
content: '摘 要';
|
|
64
|
+
font-weight: normal;
|
|
65
|
+
font-family: '黑体', 'SimHei', '华文黑体', 'STHeiti';
|
|
66
|
+
display: inline-block;
|
|
67
|
+
margin-right: 14px;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
.keywords {
|
|
71
|
+
font-size: 14px;
|
|
72
|
+
margin-bottom: 31px;
|
|
73
|
+
padding: 0 28px;
|
|
74
|
+
&::before {
|
|
75
|
+
content: '关键词';
|
|
76
|
+
font-weight: normal;
|
|
77
|
+
font-family: '黑体', 'SimHei', '华文黑体', 'STHeiti';
|
|
78
|
+
display: inline-block;
|
|
79
|
+
margin-right: 14px;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
h2 { /* 一级标题: 四号宋体 */
|
|
84
|
+
font-size: 18px;
|
|
85
|
+
font-weight: normal;
|
|
86
|
+
margin: 7px 0;
|
|
87
|
+
}
|
|
88
|
+
h3 { /* 二级标题: 五号黑体 */
|
|
89
|
+
font-size: 14px;
|
|
90
|
+
font-weight: normal;
|
|
91
|
+
font-family: '黑体', 'SimHei', '华文黑体', 'STHeiti';
|
|
92
|
+
margin: 5px 0;
|
|
93
|
+
}
|
|
94
|
+
h4 { /* 三级标题: 五号黑体 */
|
|
95
|
+
font-size: 14px;
|
|
96
|
+
font-weight: normal;
|
|
97
|
+
font-family: '黑体', 'SimHei', '华文黑体', 'STHeiti';
|
|
98
|
+
margin: 3px 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
p { /* 正文: 五号宋体 */
|
|
102
|
+
font-size: 14px;
|
|
103
|
+
text-indent: 24px;
|
|
104
|
+
text-align: justify;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
h5 { /* "参考文献": 五号黑体 */
|
|
108
|
+
font-size: 14px;
|
|
109
|
+
font-weight: normal;
|
|
110
|
+
font-family: '黑体', 'SimHei', '华文黑体', 'STHeiti';
|
|
111
|
+
text-align: center;
|
|
112
|
+
margin-bottom: 7px;
|
|
113
|
+
margin-top: 20px;
|
|
114
|
+
}
|
|
115
|
+
ul, ol { /* 参考文献的项目: 小五号宋体 */
|
|
116
|
+
list-style-type: none;
|
|
117
|
+
padding: 0;
|
|
118
|
+
& > li {
|
|
119
|
+
font-size: 12px;
|
|
120
|
+
margin: 6px 0;
|
|
121
|
+
text-align: justify;
|
|
122
|
+
text-indent: -24px;
|
|
123
|
+
padding-left: 24px;
|
|
124
|
+
}
|
|
125
|
+
& a {
|
|
126
|
+
text-decoration: none;
|
|
127
|
+
color: black;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
img {
|
|
132
|
+
display: block;
|
|
133
|
+
max-width: 100%;
|
|
134
|
+
margin: 0 auto;
|
|
135
|
+
margin-top: 10px;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
blockquote, blockquote > p { /* 图片和表格的标题: 小五号宋体 */
|
|
139
|
+
font-size: 12px;
|
|
140
|
+
font-weight: normal;
|
|
141
|
+
text-align: center;
|
|
142
|
+
margin: 0;
|
|
143
|
+
}
|
|
144
|
+
blockquote > p { margin: 6px 0; }
|
|
145
|
+
table { /* 表格: 小五号宋体 */
|
|
146
|
+
font-size: 12px;
|
|
147
|
+
position: relative;
|
|
148
|
+
border-top: 1px solid black;
|
|
149
|
+
border-bottom: 1px solid black;
|
|
150
|
+
width: 100%;
|
|
151
|
+
max-width: 100%;
|
|
152
|
+
margin: 0 auto;
|
|
153
|
+
margin-bottom: 10px;
|
|
154
|
+
& th, & td {
|
|
155
|
+
font-weight: normal;
|
|
156
|
+
}
|
|
157
|
+
& thead::after { /* 用来做三线表中间的横线 */
|
|
158
|
+
content: '';
|
|
159
|
+
display: block;
|
|
160
|
+
position: absolute;
|
|
161
|
+
border-top: 1px solid #00000060;
|
|
162
|
+
width: 100%;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
b, strong { /* 加粗按黑体处理 */
|
|
167
|
+
font-weight: normal;
|
|
168
|
+
font-family: '黑体', 'SimHei', '华文黑体', 'STHeiti';
|
|
169
|
+
}
|
|
170
|
+
`
|
|
35
171
|
|
|
36
172
|
// preParseMarkdown
|
|
37
173
|
this.preParseMarkdown = async (md: string): Promise<string> => {
|
package/theme/theme.ts
CHANGED
|
@@ -1,45 +1,33 @@
|
|
|
1
1
|
import type { PDFOptions } from 'puppeteer-core'
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
/**
|
|
5
|
-
* @param args 命令行参数
|
|
6
|
-
* @param cwd 当前工作目录
|
|
7
|
-
*/
|
|
8
|
-
constructor(args?: string[], cwd?: string) {
|
|
9
|
-
this.args = args ?? []
|
|
10
|
-
this.cwd = cwd ?? process.cwd()
|
|
11
|
-
}
|
|
12
|
-
/** 命令行参数 */
|
|
13
|
-
args: string[]
|
|
14
|
-
/** 当前工作目录 */
|
|
15
|
-
cwd: string
|
|
3
|
+
export interface MarkdownPaperTheme {
|
|
16
4
|
/**
|
|
17
5
|
* css 样式
|
|
18
6
|
* 不含 \<style>\</style>
|
|
19
7
|
*/
|
|
20
|
-
|
|
8
|
+
css: string
|
|
21
9
|
/**
|
|
22
10
|
* 预处理 markdown 字符串
|
|
23
11
|
* 用于转换自定义标签等
|
|
24
12
|
* @param md markdown 字符串
|
|
25
13
|
* @returns 转换后的 markdown 字符串
|
|
26
14
|
*/
|
|
27
|
-
|
|
15
|
+
preParseMarkdown(md: string): Promise<string>
|
|
28
16
|
/**
|
|
29
17
|
* 预处理 html 字符串
|
|
30
18
|
* 将在保存 html 文件前调用
|
|
31
19
|
* @param html html 字符串
|
|
32
20
|
* @returns 转换后的 html 字符串
|
|
33
21
|
*/
|
|
34
|
-
|
|
22
|
+
preParseHTML(html: string): Promise<string>
|
|
35
23
|
/**
|
|
36
24
|
* 在网页中要执行的函数
|
|
37
25
|
* 将在保存 html 文件后调用
|
|
38
26
|
*/
|
|
39
|
-
|
|
27
|
+
script(): void
|
|
40
28
|
/**
|
|
41
29
|
* PDF 参数
|
|
42
30
|
* 无需设置路径
|
|
43
31
|
*/
|
|
44
|
-
|
|
32
|
+
pdfOptions: PDFOptions
|
|
45
33
|
}
|