markdown-paper 2.0.0

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/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "markdown-paper",
3
+ "type": "module",
4
+ "version": "2.0.0",
5
+ "author": {
6
+ "name": "LeafYeeXYZ",
7
+ "email": "xiaoyezi@leafyee.xyz"
8
+ },
9
+ "license": "GPL-3.0-only",
10
+ "scripts": {
11
+ "mdp": "bun ./bin/mdp.ts",
12
+ "pub": "npm publish",
13
+ "try": "bun mdp ../../GoogleDrive/Curriculum/论文写作/论文.md --out=./demo/论文 --outputHTML"
14
+ },
15
+ "bin": {
16
+ "mdp": "./bin/mdp.ts"
17
+ },
18
+ "devDependencies": {
19
+ "@types/bun": "latest"
20
+ },
21
+ "peerDependencies": {
22
+ "typescript": "^5.0.0"
23
+ },
24
+ "dependencies": {
25
+ "marked": "^12.0.2",
26
+ "puppeteer-core": "^22.9.0"
27
+ }
28
+ }
@@ -0,0 +1,134 @@
1
+ * {
2
+ font-family: 'Times New Roman', '宋体'; /* 所有数字和英文字体都用 Times New Roman */
3
+ line-height: 1.55em; /* 1.5倍行距 */
4
+ margin: 0;
5
+ }
6
+
7
+ h1 { /* 中文题目: 二号黑体 */
8
+ font-size: 29px;
9
+ font-weight: normal;
10
+ font-family: '黑体';
11
+ text-align: center;
12
+ margin-bottom: 9px;
13
+ }
14
+ .author { /* 作者姓名: 四号仿宋 */
15
+ font-size: 18px;
16
+ font-family: '仿宋';
17
+ text-align: center;
18
+ margin-bottom: 3px;
19
+ }
20
+ .school { /* 作者单位: 小五宋体 */
21
+ font-size: 12px;
22
+ text-align: center;
23
+ margin-bottom: 38px;
24
+ }
25
+ .abstract { /* 摘要和关键词: 五号宋体 */
26
+ font-size: 14px;
27
+ text-align: justify;
28
+ padding: 0 28px;
29
+ &::before {
30
+ content: '摘 要';
31
+ font-family: '黑体';
32
+ display: inline-block;
33
+ margin-right: 14px;
34
+ }
35
+ }
36
+ .keywords {
37
+ font-size: 14px;
38
+ margin-bottom: 31px;
39
+ padding: 0 28px;
40
+ &::before {
41
+ content: '关键词';
42
+ font-family: '黑体';
43
+ display: inline-block;
44
+ margin-right: 14px;
45
+ }
46
+ }
47
+
48
+ h2 { /* 一级标题: 四号宋体 */
49
+ font-size: 18px;
50
+ font-weight: normal;
51
+ margin: 7px 0;
52
+ }
53
+ h3 { /* 二级标题: 五号黑体 */
54
+ font-size: 14px;
55
+ font-weight: normal;
56
+ font-family: '黑体';
57
+ margin: 5px 0;
58
+ }
59
+ h4 { /* 三级标题: 五号黑体 */
60
+ font-size: 14px;
61
+ font-weight: normal;
62
+ font-family: '黑体';
63
+ margin: 3px 0;
64
+ }
65
+
66
+ p { /* 正文: 五号宋体 */
67
+ font-size: 14px;
68
+ text-indent: 24px;
69
+ text-align: justify;
70
+ }
71
+
72
+ h5 { /* "参考文献": 五号黑体 */
73
+ font-size: 14px;
74
+ font-weight: normal;
75
+ font-family: '黑体';
76
+ text-align: center;
77
+ margin-bottom: 7px;
78
+ margin-top: 20px;
79
+ }
80
+ ul, ol { /* 参考文献的项目: 小五号宋体 */
81
+ list-style-type: none;
82
+ padding: 0;
83
+ & > li {
84
+ font-size: 12px;
85
+ margin: 6px 0;
86
+ text-align: justify;
87
+ text-indent: -24px;
88
+ padding-left: 24px;
89
+ }
90
+ & a {
91
+ text-decoration: none;
92
+ color: black;
93
+ }
94
+ }
95
+
96
+ img {
97
+ display: block;
98
+ max-width: 100%;
99
+ margin: 0 auto;
100
+ margin-top: 10px;
101
+ }
102
+
103
+ blockquote, blockquote > p { /* 图片和表格的标题: 小五号宋体 */
104
+ font-size: 12px;
105
+ font-weight: normal;
106
+ text-align: center;
107
+ margin: 0;
108
+ }
109
+ blockquote > p { margin: 6px 0; }
110
+ table { /* 表格: 小五号宋体 */
111
+ font-size: 12px;
112
+ position: relative;
113
+ border-top: 1px solid black;
114
+ border-bottom: 1px solid black;
115
+ width: 100%;
116
+ max-width: 100%;
117
+ margin: 0 auto;
118
+ margin-bottom: 10px;
119
+ & th, & td {
120
+ font-weight: normal;
121
+ }
122
+ & thead::after { /* 用来做三线表中间的横线 */
123
+ content: '';
124
+ display: block;
125
+ position: absolute;
126
+ border-top: 1px solid #00000060;
127
+ width: 100%;
128
+ }
129
+ }
130
+
131
+ b, strong { /* 加粗按黑体处理 */
132
+ font-family: '黑体';
133
+ font-weight: normal;
134
+ }
@@ -0,0 +1,41 @@
1
+ # APS 模板
2
+ `Acta Psychologica Sinica`, 心理学报
3
+
4
+ ## 额外命令行参数
5
+ | 参数 | 说明 |
6
+ | :---: | :---: |
7
+ | `--showTitle` | 在页眉显示文件名, 默认不显示 |
8
+ | `--hideFooter` | 隐藏页码, 默认显示 |
9
+ | `--zhPunctuation` | 将正文中的英文标点符号替换为中文标点符号, 默认不替换<br>仅替换 `PDF` 和 `DOCX` 文件 |
10
+ | `--enPunctuation` | 将正文中的中文标点符号替换为英文标点符号, 默认不替换<br>仅替换 `PDF` 和 `DOCX` 文件 |
11
+
12
+ ## 编写格式
13
+ ```markdown
14
+ # 中文标题
15
+ #author# 作者信息
16
+ #school# 单位信息
17
+ #abstract# 摘要内容
18
+ #keywords# 关键词内容
19
+
20
+ ## 1 一级标题
21
+ ### 1.1 二级标题
22
+ #### 1.1.1 三级标题
23
+ 正文
24
+
25
+ ![](图片路径)
26
+
27
+ > 图片标题
28
+
29
+ > 表格标题
30
+
31
+ | 表头1 | 表头2 |
32
+ | :---: | :---: |
33
+ | 内容1 | 内容2 |
34
+
35
+ ##### 参考文献
36
+ - 文献1
37
+ - 文献2
38
+ - 文献3
39
+
40
+ ##### 附录
41
+ ```
@@ -0,0 +1,122 @@
1
+ import { Theme } from '../theme'
2
+ import { readFileSync } from 'node:fs'
3
+ import { resolve } from 'node:path'
4
+ import type { PDFOptions } from 'puppeteer-core'
5
+
6
+ export class APS extends Theme {
7
+
8
+ css: string
9
+ preParseMarkdown: (md: string) => string
10
+ preParseHTML: (html: string) => string
11
+ script: () => void
12
+ pdfOptions: PDFOptions
13
+
14
+ constructor(args: string[], cwd: string) {
15
+
16
+ super(args, cwd)
17
+
18
+ // 默认自定义参数
19
+ let showTitle: boolean = false
20
+ let hideFooter: boolean = false
21
+ let zhPunctuation: boolean = false
22
+ let enPunctuation: boolean = false
23
+ // 解析参数
24
+ args.forEach(arg => {
25
+ switch (arg.split('=')[0]) {
26
+ case '--showTitle': showTitle = true; break
27
+ case '--hideFooter': hideFooter = true; break
28
+ case '--zhPunctuation': zhPunctuation = true; break
29
+ case '--enPunctuation': enPunctuation = true; break
30
+ }
31
+ })
32
+
33
+ // css
34
+ this.css = readFileSync(resolve(import.meta.dir, 'aps.css'), 'utf-8')
35
+
36
+ // preParseMarkdown
37
+ this.preParseMarkdown = (md: string): string => {
38
+ // 作者
39
+ md = md.replace(/#author# (.*)/mg, '<div class="author">$1</div>')
40
+ // 单位
41
+ md = md.replace(/#school# (.*)/mg, '<div class="school">$1</div>')
42
+ // 关键词
43
+ md = md.replace(/#keywords# (.*)/mg, '<div class="keywords">$1</div>')
44
+ // 摘要
45
+ md = md.replace(/#abstract# (.*)/mg, '<div class="abstract">$1</div>')
46
+ // 返回处理后的字符串
47
+ return md
48
+ }
49
+
50
+ // preParseHTML
51
+ // 把包裹图片的 p 标签去掉
52
+ this.preParseHTML = (html: string): string => {
53
+ html = html.replace(/<p><img (.*?)><\/p>/g, '<img $1>')
54
+ return html
55
+ }
56
+
57
+ // script
58
+ // 替换标点
59
+ if (zhPunctuation && !enPunctuation) {
60
+ this.script = () => {
61
+ const nodes = document.querySelectorAll('body > p, .abstract, .keywords, .author, .school')
62
+ nodes.forEach(node => {
63
+ let text = node.textContent ?? ''
64
+ // 替换中英文逗号和句号
65
+ text = text.replace(/, /g, ',').replace(/\. /g, '。').replace(/\.$/, '。')
66
+ // 替换中英文冒号
67
+ text = text.replace(/: /g, ':')
68
+ // 替换中英文分号
69
+ text = text.replace(/; /g, ';')
70
+ // 替换中英文感叹号
71
+ text = text.replace(/! /g, '!').replace(/!$/, '!')
72
+ // 替换中英文问号
73
+ text = text.replace(/\? /g, '?').replace(/\?$/, '?')
74
+ // 替换中英文括号
75
+ text = text.replace(/ \(/g, '(').replace(/\) /g, ')')
76
+ // 恢复et al.,
77
+ text = text.replace(/et al\.,/g, 'et al., ').replace(/et al。/g, 'et al. ')
78
+ // 设置新文本
79
+ node.textContent = text
80
+ })
81
+ }
82
+ } else if (!zhPunctuation && enPunctuation) {
83
+ this.script = () => {
84
+ const nodes = document.querySelectorAll('body > p, .abstract, .keywords, .author, .school')
85
+ nodes.forEach(node => {
86
+ let text = node.textContent ?? ''
87
+ // 替换中英文逗号和句号
88
+ text = text.replace(/,/g, ', ').replace(/。 /g, '. ')
89
+ // 替换中英文冒号
90
+ text = text.replace(/:/g, ': ')
91
+ // 替换中英文分号
92
+ text = text.replace(/;/g, '; ')
93
+ // 替换中英文感叹号
94
+ text = text.replace(/!/g, '! ')
95
+ // 替换中英文问号
96
+ text = text.replace(/?/g, '? ')
97
+ // 替换中英文括号
98
+ text = text.replace(/(/g, ' (').replace(/)/g, ') ')
99
+ // 设置新文本
100
+ node.textContent = text
101
+ })
102
+ }
103
+ } else {
104
+ this.script = () => {}
105
+ }
106
+
107
+ // pdfOptions
108
+ this.pdfOptions = {
109
+ format: 'A4',
110
+ margin: {
111
+ top: '2cm',
112
+ right: '2.5cm',
113
+ bottom: '2cm',
114
+ left: '2.5cm'
115
+ },
116
+ displayHeaderFooter: showTitle || !hideFooter,
117
+ headerTemplate: showTitle ? `<div style="font-size: 9px; font-family: '宋体'; color: #333; padding: 5px; margin-left: 0.6cm;"> <span class="title"></span> </div>` : `<div></div>`,
118
+ footerTemplate: hideFooter ? `<div></div>` : `<div style="font-size: 9px; font-family: '宋体'; color: #333; padding: 5px; margin: 0 auto;">第 <span class="pageNumber"></span> 页 / 共 <span class="totalPages"></span> 页</div>`,
119
+ }
120
+
121
+ }
122
+ }
File without changes
File without changes
File without changes
package/theme/theme.ts ADDED
@@ -0,0 +1,45 @@
1
+ import type { PDFOptions } from 'puppeteer-core'
2
+
3
+ export abstract class Theme {
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
16
+ /**
17
+ * css 样式
18
+ * 不含 \<style>\</style>
19
+ */
20
+ abstract css: string
21
+ /**
22
+ * 预处理 markdown 字符串
23
+ * 用于转换自定义标签等
24
+ * @param md markdown 字符串
25
+ * @returns 转换后的 markdown 字符串
26
+ */
27
+ abstract preParseMarkdown(md: string): string
28
+ /**
29
+ * 预处理 html 字符串
30
+ * 将在保存 html 文件前调用
31
+ * @param html html 字符串
32
+ * @returns 转换后的 html 字符串
33
+ */
34
+ abstract preParseHTML(html: string): string
35
+ /**
36
+ * 在网页中要执行的函数
37
+ * 将在保存 html 文件后调用
38
+ */
39
+ abstract script(): void
40
+ /**
41
+ * PDF 参数
42
+ * 无需设置路径
43
+ */
44
+ abstract pdfOptions: PDFOptions
45
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "compilerOptions": {
3
+ // Enable latest features
4
+ "lib": ["ESNext", "DOM"],
5
+ "target": "ESNext",
6
+ "module": "ESNext",
7
+ "moduleDetection": "force",
8
+ "jsx": "react-jsx",
9
+ "allowJs": true,
10
+
11
+ // Bundler mode
12
+ "moduleResolution": "bundler",
13
+ "allowImportingTsExtensions": true,
14
+ "verbatimModuleSyntax": true,
15
+ "noEmit": true,
16
+
17
+ // Best practices
18
+ "strict": true,
19
+ "skipLibCheck": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+
22
+ // Some stricter flags (disabled by default)
23
+ "noUnusedLocals": true,
24
+ "noUnusedParameters": true,
25
+ "noPropertyAccessFromIndexSignature": true
26
+ }
27
+ }