multi-publisher 1.1.1 → 1.1.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.
Files changed (42) hide show
  1. package/README.md +28 -22
  2. package/dist/adapters/csdn.d.ts +15 -0
  3. package/dist/adapters/csdn.js +136 -1
  4. package/dist/adapters/interface.d.ts +10 -0
  5. package/dist/adapters/qq.d.ts +19 -0
  6. package/dist/adapters/qq.js +185 -0
  7. package/dist/adapters/registry.js +2 -0
  8. package/dist/adapters/toutiao.d.ts +4 -0
  9. package/dist/adapters/toutiao.js +205 -40
  10. package/dist/adapters/wechat-publisher.d.ts +6 -1
  11. package/dist/adapters/wechat-publisher.js +58 -17
  12. package/dist/adapters/weixin.d.ts +5 -0
  13. package/dist/adapters/weixin.js +41 -5
  14. package/dist/cli/capture.d.ts +6 -0
  15. package/dist/cli/capture.js +49 -0
  16. package/dist/cli/index.js +8 -0
  17. package/dist/cli/login.js +3 -0
  18. package/dist/cli/platforms.js +2 -1
  19. package/dist/cli/publish-all.js +1 -1
  20. package/dist/cli/publish.d.ts +1 -0
  21. package/dist/cli/publish.js +29 -5
  22. package/dist/config.d.ts +8 -0
  23. package/dist/config.js +11 -0
  24. package/dist/core/parser.js +9 -1
  25. package/dist/core/renderer.d.ts +9 -1
  26. package/dist/core/renderer.js +86 -11
  27. package/dist/core/theme.d.ts +1 -1
  28. package/dist/core/theme.js +91 -336
  29. package/dist/runtime/browser-runtime.js +31 -2
  30. package/dist/tools/browser-upload.d.ts +13 -0
  31. package/dist/tools/browser-upload.js +349 -0
  32. package/dist/tools/capture.d.ts +26 -0
  33. package/dist/tools/capture.js +348 -0
  34. package/dist/tools/cover-fetcher.d.ts +10 -0
  35. package/dist/tools/cover-fetcher.js +100 -0
  36. package/dist/tools/imgbb-uploader.d.ts +18 -0
  37. package/dist/tools/imgbb-uploader.js +89 -0
  38. package/dist/tools/toutiao-upload.d.ts +10 -0
  39. package/dist/tools/toutiao-upload.js +166 -0
  40. package/package.json +1 -1
  41. package/themes/previews/cyberpunk.png +0 -0
  42. package/themes/previews/nord.png +0 -0
@@ -8,6 +8,8 @@ import { fileURLToPath } from 'node:url';
8
8
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
9
  const THEMES_DIR = path.resolve(__dirname, '../../themes');
10
10
  // 默认微信公众号主题 CSS(导出让 renderer.ts 也能用)
11
+ // 排版规范依据微信公众号编辑器:正文 15px / 行高 1.75、浅灰代码块、
12
+ // 浅色左边框引用、图片圆角居中、表格细边框、微信蓝链接。
11
13
  export const DEFAULT_CSS = `
12
14
  p {
13
15
  color: rgb(51, 51, 51);
@@ -15,27 +17,30 @@ p {
15
17
  line-height: 1.75em;
16
18
  margin: 0 0 1em 0;
17
19
  word-wrap: break-word;
20
+ letter-spacing: 0.5px;
18
21
  }
19
22
  h1, h2, h3, h4, h5, h6 {
20
23
  font-weight: bold;
21
- margin: 1em 0 0.5em 0;
24
+ color: #2c3e50;
25
+ margin: 1.2em 0 0.6em 0;
22
26
  }
23
- h1 { font-size: 1.25em; line-height: 1.4em; }
24
- h2 { font-size: 1.125em; }
27
+ h1 { font-size: 1.4em; line-height: 1.4em; border-bottom: 1px solid #e8e8e8; padding-bottom: 0.3em; }
28
+ h2 { font-size: 1.2em; border-left: 4px solid #07a35a; padding-left: 0.5em; }
25
29
  h3 { font-size: 1.05em; }
26
30
  h4, h5, h6 { font-size: 1em; }
31
+ ul, ol { margin: 0 0 1em 0; padding-left: 1.8em; }
32
+ li { margin: 0.3em 0; line-height: 1.7em; }
27
33
  li p { margin: 0; }
28
- ul, ol { margin: 0; padding-left: 2em; }
29
- li { margin: 0; padding: 0; line-height: normal; }
30
- li + li { margin-top: 0.3em; }
31
34
  pre {
32
35
  background-color: #f6f8fa;
36
+ border: 1px solid #eaecef;
33
37
  border-radius: 6px;
34
- padding: 16px;
38
+ padding: 14px 16px;
35
39
  overflow-x: auto;
36
- font-size: 14px;
40
+ font-size: 13.5px;
37
41
  line-height: 1.6;
38
42
  margin: 1em 0;
43
+ color: #24292e;
39
44
  }
40
45
  code {
41
46
  background-color: rgba(175, 184, 193, 0.2);
@@ -44,16 +49,24 @@ code {
44
49
  font-size: 0.9em;
45
50
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
46
51
  }
47
- pre code { background: none; padding: 0; font-size: 14px; }
48
- blockquote { border-left: 4px solid #ddd; padding-left: 1em; margin: 1em 0; color: #666; }
49
- hr { border: none; border-top: 1px solid #ddd; margin: 1.5em 0; }
52
+ pre code { background: none; padding: 0; border: none; font-size: 13.5px; }
53
+ blockquote {
54
+ border-left: 4px solid #07a35a;
55
+ background-color: #f6fbf8;
56
+ padding: 0.8em 1em;
57
+ margin: 1em 0;
58
+ color: #555;
59
+ border-radius: 0 4px 4px 0;
60
+ }
61
+ hr { border: none; border-top: 1px solid #e8e8e8; margin: 1.5em 0; }
50
62
  i, cite, em, var, address { font-style: italic; }
51
- b, strong { font-weight: bolder; }
52
- img { max-width: 100%; height: auto; display: block; margin: 1em auto; }
53
- table { border-collapse: collapse; width: 100%; margin: 1em 0; }
54
- table th, table td { border: 1px solid #ddd; padding: 8px 12px; }
55
- table th { background-color: #f6f8fa; font-weight: bold; }
56
- a { color: #0579b7; text-decoration: none; }
63
+ b, strong { font-weight: bold; color: #1a1a1a; }
64
+ img { max-width: 100%; height: auto; display: block; margin: 1em auto; border-radius: 4px; }
65
+ table { border-collapse: collapse; width: 100%; margin: 1em 0; font-size: 14px; }
66
+ table th, table td { border: 1px solid #e8e8e8; padding: 8px 12px; }
67
+ table th { background-color: #f6f8fa; font-weight: bold; color: #2c3e50; }
68
+ table tr:nth-child(even) { background-color: #fafafa; }
69
+ a { color: #576b95; text-decoration: none; border-bottom: 1px solid rgba(87, 107, 149, 0.3); }
57
70
  `;
58
71
  // 内置主题
59
72
  const BUILTIN_THEMES = {
@@ -64,35 +77,38 @@ const BUILTIN_THEMES = {
64
77
  },
65
78
  wechat: {
66
79
  name: 'Wechat',
67
- description: '微信风格,仿微信官方文章样式',
80
+ description: '微信风格,仿微信官方文章排版(白底、微信蓝链接、浅灰代码块)',
68
81
  css: `
69
82
  p {
70
- color: rgb(51, 51, 51);
83
+ color: rgb(62, 62, 62);
71
84
  font-size: 15px;
72
85
  line-height: 1.75em;
73
86
  margin: 0 0 1em 0;
74
87
  word-wrap: break-word;
88
+ letter-spacing: 0.5px;
75
89
  }
76
90
  h1, h2, h3, h4, h5, h6 {
77
91
  font-weight: bold;
78
- margin: 1em 0 0.5em 0;
92
+ color: #3f3f3f;
93
+ margin: 1.4em 0 0.6em 0;
79
94
  }
80
- h1 { font-size: 1.35em; line-height: 1.4em; border-bottom: 1px solid #e8e8e8; padding-bottom: 0.3em; }
81
- h2 { font-size: 1.125em; }
95
+ h1 { font-size: 1.4em; line-height: 1.4em; border-bottom: 1px solid #e8e8e8; padding-bottom: 0.3em; text-align: center; }
96
+ h2 { font-size: 1.2em; border-left: 4px solid #07a35a; padding-left: 0.5em; }
82
97
  h3 { font-size: 1.05em; }
83
98
  h4, h5, h6 { font-size: 1em; }
99
+ ul, ol { margin: 0 0 1em 0; padding-left: 1.8em; }
100
+ li { margin: 0.35em 0; line-height: 1.7em; }
84
101
  li p { margin: 0; }
85
- ul, ol { margin: 0; padding-left: 2em; }
86
- li { margin: 0; padding: 0; line-height: normal; }
87
- li + li { margin-top: 0.3em; }
88
102
  pre {
89
103
  background-color: #f6f8fa;
104
+ border: 1px solid #eaecef;
90
105
  border-radius: 6px;
91
- padding: 16px;
106
+ padding: 14px 16px;
92
107
  overflow-x: auto;
93
- font-size: 14px;
108
+ font-size: 13.5px;
94
109
  line-height: 1.6;
95
110
  margin: 1em 0;
111
+ color: #24292e;
96
112
  }
97
113
  code {
98
114
  background-color: rgba(175, 184, 193, 0.2);
@@ -101,330 +117,69 @@ code {
101
117
  font-size: 0.9em;
102
118
  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
103
119
  }
104
- pre code { background: none; padding: 0; font-size: 14px; }
105
- blockquote { border-left: 3px solid #c8a96e; background: #faf9f7; padding-left: 1em; margin: 1em 0; color: #666; }
106
- hr { border: none; border-top: 1px solid #ddd; margin: 1.5em 0; }
120
+ pre code { background: none; padding: 0; border: none; font-size: 13.5px; }
121
+ blockquote {
122
+ border-left: 3px solid #c8a96e;
123
+ background-color: #faf9f7;
124
+ padding: 0.8em 1em;
125
+ margin: 1em 0;
126
+ color: #666;
127
+ border-radius: 0 4px 4px 0;
128
+ }
129
+ hr { border: none; border-top: 1px solid #e8e8e8; margin: 1.5em 0; }
107
130
  i, cite, em, var, address { font-style: italic; }
108
- b, strong { font-weight: bolder; }
131
+ b, strong { font-weight: bold; color: #1a1a1a; }
109
132
  img { max-width: 100%; height: auto; display: block; margin: 1em auto; border-radius: 4px; }
110
- table { border-collapse: collapse; width: 100%; margin: 1em 0; }
111
- table th, table td { border: 1px solid #ddd; padding: 8px 12px; }
112
- table th { background-color: #f8f8f8; font-weight: bold; }
133
+ table { border-collapse: collapse; width: 100%; margin: 1em 0; font-size: 14px; }
134
+ table th, table td { border: 1px solid #e8e8e8; padding: 8px 12px; }
135
+ table th { background-color: #f8f8f8; font-weight: bold; color: #3f3f3f; }
136
+ table tr:nth-child(even) { background-color: #fafafa; }
113
137
  a { color: #576b95; border-bottom: 1px solid rgba(87, 107, 149, 0.3); text-decoration: none; }
114
138
  `,
115
139
  },
116
140
  modern: {
117
141
  name: 'Modern',
118
- description: '现代风格,深色代码块,清晰的视觉层次',
142
+ description: '现代风格,深色代码块清晰层次,适合技术/编程类(知乎、网页友好)',
119
143
  css: `
120
144
  p { color: rgb(45, 45, 45); font-size: 15.5px; line-height: 1.85em; margin: 0 0 1.3em 0; }
121
- h1, h2, h3 { font-weight: 700; line-height: 1.35em; color: #111; }
122
- h1 { font-size: 1.4em; border-bottom: 2px solid #4a90d9; padding-bottom: 0.25em; }
123
- h2 { font-size: 1.2em; }
124
- pre { background-color: #1e1e1e; border-radius: 10px; padding: 18px 22px; font-size: 13.5px; margin: 1.3em 0; border: 1px solid #333; }
125
- code { background-color: rgba(74, 144, 217, 0.12); border-radius: 4px; padding: 0.15em 0.45em; font-size: 0.88em; color: #4a90d9; }
126
- pre code { background: none; padding: 0; color: #d4d4d4; }
127
- blockquote { border-left: 4px solid #4a90d9; background: linear-gradient(135deg, #f0f7ff 0%, #fff 100%); padding: 0.6em 1.2em; border-radius: 0 6px 6px 0; }
128
- img { border-radius: 8px; box-shadow: 0 2px 12px rgba(0,0,0,0.1); }
129
- table th { background-color: #4a90d9; color: #fff; }
130
- a { color: #4a90d9; }
145
+ h1, h2, h3, h4 { font-weight: 700; line-height: 1.35em; color: #1a1a1a; }
146
+ h1 { font-size: 1.45em; border-bottom: 2px solid #4a90d9; padding-bottom: 0.25em; }
147
+ h2 { font-size: 1.2em; border-left: 4px solid #4a90d9; padding-left: 0.5em; }
148
+ h3 { font-size: 1.05em; }
149
+ h4 { font-size: 1em; color: #555; }
150
+ ul, ol { margin: 0 0 1.2em 0; padding-left: 1.8em; }
151
+ li { margin: 0.35em 0; line-height: 1.7em; }
152
+ pre { background-color: #1e1e1e; border-radius: 8px; padding: 16px 18px; font-size: 13.5px; line-height: 1.6; margin: 1.3em 0; border: 1px solid #333; color: #d4d4d4; }
153
+ code { background-color: rgba(74, 144, 217, 0.12); border-radius: 4px; padding: 0.15em 0.45em; font-size: 0.88em; color: #2f6fb0; font-family: 'SFMono-Regular', Consolas, Menlo, monospace; }
154
+ pre code { background: none; padding: 0; border: none; color: #d4d4d4; }
155
+ blockquote { border-left: 4px solid #4a90d9; background-color: #f0f7ff; padding: 0.8em 1.2em; margin: 1.2em 0; color: #444; border-radius: 0 6px 6px 0; }
156
+ img { border-radius: 8px; box-shadow: 0 2px 12px rgba(0,0,0,0.1); margin: 1.2em 0; max-width: 100%; }
157
+ table { border-collapse: collapse; width: 100%; margin: 1.2em 0; font-size: 14px; }
158
+ table th, table td { border: 1px solid #e1e4e8; padding: 8px 12px; }
159
+ table th { background-color: #4a90d9; color: #fff; font-weight: 600; }
160
+ table tr:nth-child(even) { background-color: #f6f9fc; }
161
+ a { color: #4a90d9; text-decoration: none; border-bottom: 1px solid rgba(74, 144, 217, 0.3); }
131
162
  `,
132
163
  },
133
164
  minimal: {
134
165
  name: 'Minimal',
135
- description: '简约风格,干净留白,适合阅读',
166
+ description: '简约风格,干净留白,适合头条号等轻阅读平台',
136
167
  css: `
137
168
  p { color: rgb(60, 60, 60); font-size: 16px; line-height: 2em; margin: 0 0 1.5em 0; }
138
- h1 { font-size: 1.5em; text-align: center; letter-spacing: 0.05em; }
139
- h2 { font-size: 1.25em; border-bottom: 1px solid #eee; padding-bottom: 0.3em; }
140
- pre { background-color: #fafafa; border-radius: 6px; border: 1px solid #eee; }
141
- code { background-color: rgba(0,0,0,0.04); border-radius: 3px; color: #c7254e; }
142
- blockquote { border-left: none; background: #f9f9f9; font-style: italic; }
143
- img { border-radius: 4px; }
144
- a { color: #0969da; }
145
- `,
146
- },
147
- cyberpunk: {
148
- name: 'Cyberpunk',
149
- description: '赛博朋克风格,炫酷霓虹发光效果',
150
- css: `
151
- p { color: #c8c8ff; font-size: 15px; line-height: 1.8em; margin: 0 0 1em 0; }
152
- h1, h2, h3, h4, h5, h6 { font-weight: bold; margin: 1.2em 0 0.6em 0; line-height: 1.4em; }
153
- h1 { font-size: 1.6em; color: #00fff5; text-shadow: 0 0 20px #00fff5, 0 0 40px #00fff5; border-bottom: 2px solid #ff00ff; padding-bottom: 0.4em; }
154
- h2 { font-size: 1.3em; color: #ff00ff; text-shadow: 0 0 10px #ff00ff; }
155
- h3 { font-size: 1.15em; color: #00fff5; }
156
- li p { margin: 0; }
157
- ul, ol { margin: 0.8em 0; padding-left: 1.5em; }
158
- li { margin-bottom: 0.4em; color: #c8c8ff; }
159
- pre { background: linear-gradient(135deg, #0d022155, #0a0a1f); border: 1px solid #ff00ff33; border-radius: 8px; padding: 16px; overflow-x: auto; font-size: 13.5px; line-height: 1.7; margin: 1em 0; box-shadow: 0 0 20px #ff00ff22; }
160
- code { background: linear-gradient(90deg, #ff00ff22, #00fff522); border: 1px solid #ff00ff55; border-radius: 4px; padding: 0.2em 0.5em; color: #00fff5; font-size: 0.9em; font-family: 'SF Mono', Consolas, monospace; }
161
- pre code { background: none; border: none; padding: 0; color: #00fff5; }
162
- blockquote { border-left: 3px solid #ff00ff; background: linear-gradient(90deg, #ff00ff11, transparent); padding: 0.8rem 1rem; margin: 1em 0; color: #ff88ff; border-radius: 0 4px 4px 0; }
163
- hr { border: none; border-top: 1px solid #ff00ff44; margin: 2em 0; }
164
- i, cite, em, var, address { font-style: italic; color: #ff88ff; }
165
- b, strong { font-weight: bold; color: #fff; }
166
- img { max-width: 100%; height: auto; display: block; margin: 1em auto; border-radius: 8px; box-shadow: 0 0 20px #00fff544; }
167
- table { border-collapse: collapse; width: 100%; margin: 1em 0; }
168
- table th, table td { border: 1px solid #ff00ff44; padding: 8px 12px; }
169
- table th { background: linear-gradient(90deg, #ff00ff33, #00fff533); color: #00fff5; font-weight: bold; }
170
- table tr:nth-child(even) { background-color: #ff00ff11; }
171
- a { color: #00fff5; text-decoration: none; border-bottom: 1px solid #00fff5; }
172
- a:hover { text-shadow: 0 0 10px #00fff5; }
173
- `,
174
- },
175
- nord: {
176
- name: 'Nord',
177
- description: '北欧冷淡风格,蓝灰色调克制简洁',
178
- css: `
179
- p { color: #d8dee9; font-size: 15px; line-height: 1.8em; margin: 0 0 1em 0; }
180
- h1, h2, h3, h4, h5, h6 { font-weight: 600; margin: 1.2em 0 0.6em 0; line-height: 1.4em; }
181
- h1 { font-size: 1.6em; color: #88c0d0; border-bottom: 2px solid #4c566a; padding-bottom: 0.4em; }
182
- h2 { font-size: 1.3em; color: #81a1c1; }
183
- h3 { font-size: 1.15em; color: #88c0d0; }
184
- li p { margin: 0; }
185
- ul, ol { margin: 0.8em 0; padding-left: 1.5em; }
186
- li { margin-bottom: 0.4em; color: #d8dee9; }
187
- pre { background: #3b4252; border-radius: 8px; padding: 16px; overflow-x: auto; font-size: 13.5px; line-height: 1.7; margin: 1em 0; border-left: 3px solid #88c0d0; }
188
- code { background: #3b4252; border-radius: 4px; padding: 0.2em 0.5em; color: #a3be8c; font-size: 0.9em; font-family: 'SF Mono', Consolas, monospace; }
189
- pre code { background: none; padding: 0; color: #eceff4; }
190
- blockquote { border-left: 3px solid #5e81ac; background: #3b425255; padding: 0.8rem 1rem; margin: 1em 0; color: #d8dee9; font-style: italic; border-radius: 0 4px 4px 0; }
191
- hr { border: none; border-top: 1px solid #4c566a; margin: 2em 0; }
192
- i, cite, em, var, address { font-style: italic; }
193
- b, strong { font-weight: bold; color: #eceff4; }
194
- img { max-width: 100%; height: auto; display: block; margin: 1em auto; border-radius: 8px; }
195
- table { border-collapse: collapse; width: 100%; margin: 1em 0; }
196
- table th, table td { border: 1px solid #4c566a; padding: 8px 12px; }
197
- table th { background: #3b4252; color: #88c0d0; font-weight: bold; }
198
- table tr:nth-child(even) { background-color: #3b425255; }
199
- a { color: #88c0d0; text-decoration: none; }
200
- a:hover { color: #81a1c1; }
201
- `,
202
- },
203
- paper: {
204
- name: 'Paper',
205
- description: '笔记本风格,纸张纹理文艺复古',
206
- css: `
207
- body { background-image: linear-gradient(transparent 95%, #e8e4dc 95%); background-size: 100% 2em; }
208
- p { color: #444; font-size: 15px; line-height: 2em; margin: 0 0 1em 0; text-indent: 2em; }
209
- h1, h2, h3, h4, h5, h6 { font-weight: bold; margin: 1.5em 0 0.6em 0; line-height: 1.4em; color: #1a1a1a; font-family: Georgia, serif; }
210
- h1 { font-size: 1.8em; text-align: center; letter-spacing: 0.05em; text-indent: 0; }
211
- h2 { font-size: 1.4em; color: #2d2d2d; border-bottom: 1px solid #ccc; padding-bottom: 0.3em; text-indent: 0; }
212
- h3 { font-size: 1.1em; color: #3d3d3d; text-indent: 0; }
213
- li p { margin: 0; }
214
- ul, ol { margin: 0.8em 0; padding-left: 2em; }
215
- li { margin-bottom: 0.4em; color: #444; }
216
- pre { background: #f5f5f5; border: 1px solid #ddd; border-radius: 6px; padding: 16px; overflow-x: auto; font-size: 13.5px; line-height: 1.6; margin: 1em 0; font-family: 'Courier New', monospace; }
217
- code { background: #f5f5f5; border: 1px solid #ddd; border-radius: 3px; padding: 0.15em 0.4em; color: #c7254e; font-size: 0.9em; font-family: 'Courier New', monospace; }
218
- pre code { background: none; border: none; padding: 0; color: #333; }
219
- blockquote { border-left: 3px solid #c8a96e; background: #f9f7f3; padding: 0.8rem 1rem; margin: 1em 0; color: #666; font-style: italic; border-radius: 0 4px 4px 0; }
220
- hr { border: none; border-top: 1px solid #ccc; margin: 2em 0; }
221
- i, cite, em, var, address { font-style: italic; }
222
- b, strong { font-weight: bold; color: #111; }
223
- img { max-width: 100%; height: auto; display: block; margin: 1em auto; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
224
- table { border-collapse: collapse; width: 100%; margin: 1em 0; }
225
- table th, table td { border: 1px solid #ddd; padding: 8px 12px; }
226
- table th { background: #f5f5f5; color: #333; font-weight: bold; }
227
- a { color: #0969da; text-decoration: none; border-bottom: 1px dashed #0969da; }
228
- a:hover { border-bottom-style: solid; }
229
- `,
230
- },
231
- darkelite: {
232
- name: 'Dark Elite',
233
- description: '深色精英风格,GitHub 式专业硬核',
234
- css: `
235
- p { color: #c9d1d9; font-size: 15px; line-height: 1.8em; margin: 0 0 1em 0; }
236
- h1, h2, h3, h4, h5, h6 { font-weight: bold; margin: 1.2em 0 0.6em 0; line-height: 1.4em; }
237
- h1 { font-size: 1.6em; color: #fff; border-bottom: 1px solid #30363d; padding-bottom: 0.4em; }
238
- h2 { font-size: 1.3em; color: #58a6ff; }
239
- h3 { font-size: 1.15em; color: #8b949e; }
240
- li p { margin: 0; }
241
- ul, ol { margin: 0.8em 0; padding-left: 1.5em; }
242
- li { margin-bottom: 0.4em; color: #c9d1d9; }
243
- pre { background: #161b22; border: 1px solid #30363d; border-radius: 6px; padding: 16px; overflow-x: auto; font-size: 13.5px; line-height: 1.7; margin: 1em 0; }
244
- code { background: #21262d; border: 1px solid #30363d; border-radius: 4px; padding: 0.2em 0.5em; color: #f0883e; font-size: 0.9em; font-family: 'SF Mono', Consolas, monospace; }
245
- pre code { background: none; border: none; padding: 0; color: #c9d1d9; }
246
- blockquote { border-left: 3px solid #238636; background: #161b22; padding: 0.8rem 1rem; margin: 1em 0; color: #8b949e; border-radius: 0 4px 4px 0; }
247
- hr { border: none; border-top: 1px solid #30363d; margin: 2em 0; }
248
- i, cite, em, var, address { font-style: italic; }
249
- b, strong { font-weight: bold; color: #fff; }
250
- img { max-width: 100%; height: auto; display: block; margin: 1em auto; border-radius: 6px; }
251
- table { border-collapse: collapse; width: 100%; margin: 1em 0; border: 1px solid #30363d; }
252
- table th, table td { border: 1px solid #30363d; padding: 8px 12px; }
253
- table th { background: #161b22; color: #58a6ff; font-weight: bold; }
254
- a { color: #58a6ff; text-decoration: none; }
255
- a:hover { color: #79c0ff; }
256
- `,
257
- },
258
- sunset: {
259
- name: 'Sunset',
260
- description: '日落暖调风格,温暖治愈系',
261
- css: `
262
- body { background: linear-gradient(180deg, #1a1a2e 0%, #16213e 50%, #1a1a2e 100%); }
263
- p { color: #ddd; font-size: 15px; line-height: 1.8em; margin: 0 0 1em 0; }
264
- h1, h2, h3, h4, h5, h6 { font-weight: bold; margin: 1.2em 0 0.6em 0; line-height: 1.4em; color: #f5f5f5; }
265
- h1 { font-size: 1.6em; color: #ff6b6b; text-shadow: 0 0 30px #ff6b6b55; text-align: center; }
266
- h2 { font-size: 1.3em; color: #ffa07a; border-bottom: 1px solid #ffa07a44; padding-bottom: 0.3em; }
267
- h3 { font-size: 1.15em; color: #ffd93d; }
268
- li p { margin: 0; }
269
- ul, ol { margin: 0.8em 0; padding-left: 1.5em; }
270
- li { margin-bottom: 0.4em; color: #ddd; }
271
- pre { background: #2d2d44; border-radius: 8px; padding: 16px; overflow-x: auto; font-size: 13.5px; line-height: 1.7; margin: 1em 0; border-left: 3px solid #ff6b6b; }
272
- code { background: #2d2d44; border-radius: 4px; padding: 0.2em 0.5em; color: #ffd93d; font-size: 0.9em; font-family: 'SF Mono', Consolas, monospace; }
273
- pre code { background: none; padding: 0; color: #ffa07a; }
274
- blockquote { background: linear-gradient(90deg, #ff6b6b11, transparent); border-left: 3px solid #ff6b6b; padding: 0.8rem 1rem; margin: 1em 0; color: #bbb; border-radius: 0 4px 4px 0; }
275
- hr { border: none; border-top: 1px solid #444; margin: 2em 0; }
276
- i, cite, em, var, address { font-style: italic; color: #ffa07a; }
277
- b, strong { font-weight: bold; color: #fff; }
278
- img { max-width: 100%; height: auto; display: block; margin: 1em auto; border-radius: 8px; }
279
- table { border-collapse: collapse; width: 100%; margin: 1em 0; }
280
- table th, table td { border: 1px solid #444; padding: 8px 12px; }
281
- table th { background: #2d2d44; color: #ffd93d; font-weight: bold; }
282
- a { color: #ffa07a; text-decoration: none; }
283
- a:hover { color: #ff6b6b; }
284
- `,
285
- },
286
- zen: {
287
- name: 'Zen',
288
- description: '禅意风格,日式极简留白',
289
- css: `
290
- body { background: #f7f5f0; }
291
- p { color: #4a4a4a; font-size: 15px; line-height: 2em; margin: 0 0 1.5em 0; }
292
- h1, h2, h3, h4, h5, h6 { font-weight: normal; margin: 2em 0 0.8em 0; line-height: 1.6em; color: #2d2d2d; font-family: 'Noto Serif SC', 'Songti SC', serif; }
293
- h1 { font-size: 1.8em; text-align: center; letter-spacing: 0.15em; border-bottom: 1px solid #d4d4d4; padding-bottom: 0.5em; }
294
- h2 { font-size: 1.4em; letter-spacing: 0.1em; border-left: 3px solid #8b7355; padding-left: 0.8em; }
295
- h3 { font-size: 1.15em; color: #5a5a5a; }
296
- li p { margin: 0; }
297
- ul, ol { margin: 1em 0; padding-left: 1.5em; }
298
- li { margin-bottom: 0.6em; color: #4a4a4a; line-height: 1.9; }
299
- pre { background: #ebe8e0; border-radius: 4px; padding: 16px; overflow-x: auto; font-size: 13px; line-height: 1.7; margin: 1.5em 0; border-left: 2px solid #8b7355; }
300
- code { background: #ebe8e0; border-radius: 3px; padding: 0.15em 0.4em; color: #6b5b4f; font-size: 0.9em; font-family: 'SF Mono', monospace; }
301
- pre code { background: none; padding: 0; color: #4a4a4a; }
302
- blockquote { border-left: none; border-top: 1px solid #d4d4d4; border-bottom: 1px solid #d4d4d4; background: none; padding: 1em 1.5em; margin: 2em 0; color: #7a7a7a; font-style: normal; text-align: center; }
303
- hr { border: none; text-align: center; margin: 3em 0; }
304
- hr::after { content: '· · ·'; color: #8b7355; letter-spacing: 0.5em; font-size: 1.2em; }
305
- i, cite, em, var, address { font-style: italic; color: #7a7a7a; }
306
- b, strong { font-weight: normal; color: #3d3d3d; }
307
- img { max-width: 100%; height: auto; display: block; margin: 2em auto; border-radius: 2px; }
308
- table { border-collapse: collapse; width: 100%; margin: 1.5em 0; }
309
- table th, table td { border: none; border-top: 1px solid #d4d4d4; padding: 10px 12px; }
310
- table th { color: #8b7355; font-weight: normal; text-align: left; }
311
- a { color: #8b7355; text-decoration: none; border-bottom: 1px solid transparent; }
312
- a:hover { border-bottom-color: #8b7355; }
313
- `,
314
- },
315
- retro: {
316
- name: 'Retro Futurism',
317
- description: '80年代复古未来主义,霓虹几何',
318
- css: `
319
- body { background: #0d0d1a; background-image: repeating-linear-gradient(0deg, transparent, transparent 50px, #1a1a2e 50px, #1a1a2e 51px), repeating-linear-gradient(90deg, transparent, transparent 50px, #1a1a2e 50px, #1a1a2e 51px); }
320
- p { color: #e0e0e0; font-size: 15px; line-height: 1.8em; margin: 0 0 1em 0; }
321
- h1, h2, h3, h4, h5, h6 { font-weight: bold; margin: 1.5em 0 0.8em 0; line-height: 1.3em; color: #fff; text-transform: uppercase; letter-spacing: 0.1em; }
322
- h1 { font-size: 2em; color: #ff6ec7; text-shadow: 3px 3px 0 #00d4ff, -1px -1px 0 #ffff00; transform: skewX(-5deg); }
323
- h2 { font-size: 1.4em; color: #00d4ff; border-bottom: 2px solid #ff6ec7; padding-bottom: 0.3em; }
324
- h3 { font-size: 1.15em; color: #ffff00; }
325
- li p { margin: 0; }
326
- ul, ol { margin: 1em 0; padding-left: 1.5em; }
327
- li { margin-bottom: 0.5em; color: #e0e0e0; }
328
- pre { background: linear-gradient(135deg, #1a1a2e 0%, #0d0d1a 100%); border: 2px solid #ff6ec7; border-radius: 0; padding: 16px; overflow-x: auto; font-size: 13px; line-height: 1.7; margin: 1.5em 0; transform: perspective(500px) rotateX(2deg); box-shadow: 5px 5px 0 #00d4ff; }
329
- code { background: #ff6ec755; border: 1px solid #ff6ec7; border-radius: 0; padding: 0.2em 0.5em; color: #ff6ec7; font-size: 0.9em; font-family: 'Courier New', monospace; }
330
- pre code { background: none; border: none; padding: 0; color: #00d4ff; }
331
- blockquote { border-left: 4px solid #ffff00; background: #1a1a2e; padding: 1rem 1.5rem; margin: 1.5em 0; color: #e0e0e0; transform: skewX(-3deg); }
332
- hr { border: none; border-top: 2px dashed #ff6ec7; margin: 2.5em 0; }
333
- i, cite, em, var, address { font-style: italic; color: #ff6ec7; }
334
- b, strong { font-weight: bold; color: #ffff00; }
335
- img { max-width: 100%; height: auto; display: block; margin: 1.5em auto; border: 3px solid #00d4ff; filter: contrast(1.1) saturate(1.2); }
336
- table { border-collapse: separate; border-spacing: 2px; width: 100%; margin: 1.5em 0; }
337
- table th, table td { background: #1a1a2e; padding: 10px 14px; border: 1px solid #ff6ec7; }
338
- table th { color: #ffff00; text-align: center; }
339
- a { color: #00d4ff; text-decoration: none; text-transform: uppercase; }
340
- a:hover { color: #ff6ec7; text-shadow: 0 0 10px #ff6ec7; }
341
- `,
342
- },
343
- midnight: {
344
- name: 'Midnight Library',
345
- description: '深夜图书馆,暖黄灯光书香氛围',
346
- css: `
347
- body { background: #0f1a14; background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%231a2f23' fill-opacity='0.3'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E"); }
348
- p { color: #d4c5a9; font-size: 15.5px; line-height: 1.9em; margin: 0 0 1.2em 0; font-family: 'Lora', 'Noto Serif SC', Georgia, serif; }
349
- h1, h2, h3, h4, h5, h6 { font-weight: normal; margin: 1.8em 0 0.8em 0; line-height: 1.5em; color: #f5e6c8; font-family: 'Playfair Display', 'Noto Serif SC', serif; }
350
- h1 { font-size: 1.9em; text-align: center; letter-spacing: 0.08em; text-shadow: 0 0 40px #ffd70044; border-bottom: 1px solid #3d5a45; padding-bottom: 0.5em; }
351
- h2 { font-size: 1.4em; color: #c9a962; border-left: 3px solid #8b7355; padding-left: 0.8em; }
352
- h3 { font-size: 1.15em; color: #b8956e; }
353
- li p { margin: 0; }
354
- ul, ol { margin: 1em 0; padding-left: 1.5em; }
355
- li { margin-bottom: 0.5em; color: #d4c5a9; }
356
- pre { background: #1a2f23; border: 1px solid #3d5a45; border-radius: 4px; padding: 16px; overflow-x: auto; font-size: 13px; line-height: 1.7; margin: 1.5em 0; box-shadow: inset 0 0 20px #0d1a1444; }
357
- code { background: #2a3f33; border-radius: 3px; padding: 0.15em 0.4em; color: #ffd700; font-size: 0.9em; font-family: 'Courier New', monospace; }
358
- pre code { background: none; padding: 0; color: #d4c5a9; }
359
- blockquote { border-left: 3px solid #8b7355; background: linear-gradient(90deg, #1a2f2344, transparent); padding: 1rem 1.5rem; margin: 2em 0; color: #b8956e; font-style: italic; border-radius: 0 4px 4px 0; }
360
- hr { border: none; border-top: 1px solid #3d5a45; margin: 3em 0; }
361
- i, cite, em, var, address { font-style: italic; color: #c9a962; }
362
- b, strong { font-weight: normal; color: #f5e6c8; }
363
- img { max-width: 100%; height: auto; display: block; margin: 2em auto; border-radius: 2px; box-shadow: 0 4px 20px #00000055; }
364
- table { border-collapse: collapse; width: 100%; margin: 1.5em 0; }
365
- table th, table td { border: 1px solid #3d5a45; padding: 10px 14px; }
366
- table th { background: #1a2f23; color: #c9a962; text-align: left; }
367
- a { color: #c9a962; text-decoration: none; border-bottom: 1px dotted #8b7355; }
368
- a:hover { color: #ffd700; border-bottom-color: #ffd700; }
369
- `,
370
- },
371
- brutalism: {
372
- name: 'Brutalism',
373
- description: '粗野主义,大字体原始美学',
374
- css: `
375
- body { background: #fff; }
376
- p { color: #000; font-size: 16px; line-height: 1.6em; margin: 0 0 1em 0; font-weight: 500; }
377
- h1, h2, h3, h4, h5, h6 { font-weight: 900; margin: 1.5em 0 0.5em 0; line-height: 1.1em; color: #000; text-transform: uppercase; }
378
- h1 { font-size: 3em; border: 4px solid #000; padding: 0.2em 0.4em; transform: rotate(-1deg); display: inline-block; }
379
- h2 { font-size: 1.8em; border-bottom: 4px solid #000; padding-bottom: 0.2em; }
380
- h3 { font-size: 1.3em; }
381
- li p { margin: 0; }
382
- ul, ol { margin: 1em 0; padding-left: 1.5em; }
383
- li { margin-bottom: 0.5em; color: #000; font-weight: 600; }
384
- pre { background: #000; border-radius: 0; padding: 16px; overflow-x: auto; font-size: 13px; line-height: 1.6; margin: 1.5em 0; }
385
- code { background: #000; border-radius: 0; padding: 0.2em 0.4em; color: #fff; font-size: 1em; font-family: 'SF Mono', monospace; font-weight: bold; }
386
- pre code { background: none; padding: 0; color: #fff; }
387
- blockquote { border: 4px solid #000; background: #f0f0f0; padding: 1rem 1.5rem; margin: 2em 0; }
388
- blockquote p { font-size: 1.2em; font-weight: 900; margin: 0; }
389
- hr { border: none; border-top: 4px solid #000; margin: 3em 0; }
390
- i, cite, em, var, address { font-style: normal; text-decoration: underline; text-decoration-thickness: 3px; }
391
- b, strong { font-weight: 900; }
392
- img { max-width: 100%; height: auto; display: block; margin: 1.5em 0; border: 4px solid #000; }
393
- table { border-collapse: collapse; width: 100%; margin: 1.5em 0; border: 4px solid #000; }
394
- table th, table td { border: 2px solid #000; padding: 10px 14px; }
395
- table th { background: #000; color: #fff; font-weight: 900; text-transform: uppercase; }
396
- a { color: #000; text-decoration: none; background: #ffff00; padding: 0 0.2em; }
397
- a:hover { background: #000; color: #fff; }
398
- `,
399
- },
400
- neumorphism: {
401
- name: 'Neumorphism',
402
- description: '新拟态风格,柔和立体软UI',
403
- css: `
404
- body { background: #e0e5ec; }
405
- p { color: #4a5568; font-size: 15px; line-height: 1.8em; margin: 0 0 1em 0; }
406
- h1, h2, h3, h4, h5, h6 { font-weight: 600; margin: 1.2em 0 0.6em 0; line-height: 1.4em; color: #2d3748; }
407
- h1 { font-size: 1.7em; text-align: center; text-shadow: 6px 6px 12px #b8bcc2, -6px -6px 12px #ffffff; padding: 0.5em; }
408
- h2 { font-size: 1.3em; color: #4a5568; border-left: 4px solid #7c3aed; padding-left: 0.6em; }
409
- h3 { font-size: 1.1em; color: #5a6577; }
410
- li p { margin: 0; }
411
- ul, ol { margin: 0.8em 0; padding-left: 1.5em; }
412
- li { margin-bottom: 0.5em; color: #4a5568; }
413
- pre { background: #e0e5ec; border-radius: 16px; padding: 16px; overflow-x: auto; font-size: 13px; line-height: 1.7; margin: 1.2em 0; box-shadow: 8px 8px 16px #b8bcc2, -8px -8px 16px #ffffff; }
414
- code { background: #e0e5ec; border-radius: 8px; padding: 0.2em 0.5em; color: #7c3aed; font-size: 0.9em; font-family: 'SF Mono', monospace; box-shadow: inset 2px 2px 4px #b8bcc2, inset -2px -2px 4px #ffffff; }
415
- pre code { background: none; padding: 0; color: #4a5568; box-shadow: none; }
416
- blockquote { background: #e0e5ec; border-radius: 16px; padding: 1rem 1.5rem; margin: 1.2em 0; color: #5a6577; box-shadow: 8px 8px 16px #b8bcc2, -8px -8px 16px #ffffff; border-left: 4px solid #7c3aed; }
417
- hr { border: none; margin: 2em 0; }
418
- hr::after { content: '···'; color: #7c3aed; font-size: 1.5em; letter-spacing: 0.5em; }
419
- i, cite, em, var, address { font-style: italic; color: #7c3aed; }
420
- b, strong { font-weight: 600; color: #2d3748; }
421
- img { max-width: 100%; height: auto; display: block; margin: 1.2em auto; border-radius: 16px; box-shadow: 8px 8px 16px #b8bcc2, -8px -8px 16px #ffffff; }
422
- table { border-collapse: collapse; width: 100%; margin: 1.2em 0; background: #e0e5ec; border-radius: 16px; overflow: hidden; box-shadow: 8px 8px 16px #b8bcc2, -8px -8px 16px #ffffff; }
423
- table th, table td { padding: 12px 16px; }
424
- table th { background: linear-gradient(145deg, #e6ebf2, #d1d9e6); color: #7c3aed; font-weight: 600; }
425
- table tr:nth-child(even) { background: rgba(124, 58, 237, 0.05); }
426
- a { color: #7c3aed; text-decoration: none; font-weight: 600; }
427
- a:hover { color: #5b21b6; text-decoration: underline; }
169
+ h1 { font-size: 1.5em; text-align: center; letter-spacing: 0.05em; font-weight: 700; color: #222; }
170
+ h2 { font-size: 1.25em; border-bottom: 1px solid #eee; padding-bottom: 0.3em; color: #333; }
171
+ h3 { font-size: 1.1em; color: #444; }
172
+ ul, ol { margin: 0 0 1.4em 0; padding-left: 1.6em; }
173
+ li { margin: 0.4em 0; line-height: 1.9em; }
174
+ pre { background-color: #fafafa; border-radius: 6px; border: 1px solid #eee; padding: 14px 16px; overflow-x: auto; font-size: 13.5px; line-height: 1.6; margin: 1.2em 0; }
175
+ code { background-color: rgba(0,0,0,0.04); border-radius: 3px; color: #c7254e; padding: 0.15em 0.4em; font-family: 'SFMono-Regular', Consolas, monospace; }
176
+ pre code { background: none; padding: 0; border: none; }
177
+ blockquote { border-left: none; background: #f9f9f9; font-style: italic; padding: 0.8em 1.2em; margin: 1.4em 0; color: #666; border-radius: 4px; }
178
+ img { border-radius: 4px; margin: 1.2em auto; max-width: 100%; display: block; }
179
+ table { border-collapse: collapse; width: 100%; margin: 1.4em 0; font-size: 14px; }
180
+ table th, table td { border: 1px solid #eee; padding: 8px 12px; }
181
+ table th { background-color: #f5f5f5; font-weight: 600; color: #333; }
182
+ a { color: #0969da; text-decoration: none; }
428
183
  `,
429
184
  },
430
185
  };
@@ -18,9 +18,28 @@ export class BrowserRuntime {
18
18
  this.browser = await chromium.launch({
19
19
  headless: false, // 需要可见浏览器让用户登录
20
20
  channel: 'chromium', // 使用用户的默认 Chrome 配置
21
+ args: [
22
+ '--disable-blink-features=AutomationControlled',
23
+ '--disable-devtools-shm-usage',
24
+ '--no-sandbox',
25
+ ],
26
+ });
27
+ // 创建新 context,带真实浏览器配置
28
+ const context = await this.browser.newContext({
29
+ viewport: { width: 1280, height: 900 },
30
+ userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
31
+ });
32
+ this.page = await context.newPage();
33
+ // 使用 CDP 隐藏自动化特征
34
+ const cdp = await this.page.context().newCDPSession(this.page);
35
+ await cdp.send('Page.addScriptToEvaluateOnNewDocument', {
36
+ source: `
37
+ Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
38
+ Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
39
+ Object.defineProperty(navigator, 'languages', { get: () => ['zh-CN', 'zh', 'en'] });
40
+ window.chrome = { runtime: {}, loadTimes: () => {}, csi: () => {} };
41
+ `
21
42
  });
22
- // 不创建新context,让Playwright使用默认context,保持已登录状态
23
- this.page = await this.browser.newPage();
24
43
  // 注意:不清理 cookies,使用用户已有的登录状态
25
44
  console.log(`打开登录页面: ${loginConfig.loginUrl}`);
26
45
  await this.page.goto(loginConfig.loginUrl, { waitUntil: 'domcontentloaded', timeout: 60000 });
@@ -397,6 +416,16 @@ export const PLATFORM_LOGIN_CONFIGS = {
397
416
  },
398
417
  extraCookieDomains: ['.51cto.com', '.cto51.com'],
399
418
  },
419
+ qq: {
420
+ id: 'qq',
421
+ name: '企鹅号',
422
+ loginUrl: 'https://om.qq.com/',
423
+ successCondition: {
424
+ cookieName: 'userid',
425
+ waitMs: 60000,
426
+ },
427
+ extraCookieDomains: ['.qq.com', '.om.qq.com'],
428
+ },
400
429
  };
401
430
  /**
402
431
  * 执行平台登录
@@ -0,0 +1,13 @@
1
+ export interface BrowserUploadResult {
2
+ success: boolean;
3
+ coverUrl?: string;
4
+ error?: string;
5
+ }
6
+ /**
7
+ * 通过浏览器自动化上传封面图片
8
+ * 流程:打开文章编辑页 -> 在右侧设置面板上传封面
9
+ * @param articleId 文章ID(发布后返回的)
10
+ * @param imagePath 本地图片路径
11
+ * @returns 上传后的封面 URL
12
+ */
13
+ export declare function uploadCoverViaBrowser(articleId: string, imagePath: string): Promise<BrowserUploadResult>;