wechat-md-publisher 0.2.7 → 0.2.8
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/dist/{Logger-DhicjDOJ.js → Logger-CU2JwTgd.js} +40 -37
- package/dist/Logger-CU2JwTgd.js.map +1 -0
- package/dist/cli.js +7 -4
- package/dist/cli.js.map +1 -1
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js.map +1 -1
- package/dist/core/renderer/ImageProcessor.d.ts.map +1 -1
- package/dist/core/renderer/ImageProcessor.js +3 -2
- package/dist/core/renderer/ImageProcessor.js.map +1 -1
- package/dist/core/renderer/MarkdownRenderer.d.ts +2 -0
- package/dist/core/renderer/MarkdownRenderer.d.ts.map +1 -1
- package/dist/core/renderer/MarkdownRenderer.js +9 -8
- package/dist/core/renderer/MarkdownRenderer.js.map +1 -1
- package/dist/core/theme/loaders/BuiltinLoader.d.ts.map +1 -1
- package/dist/core/theme/loaders/BuiltinLoader.js +1 -27
- package/dist/core/theme/loaders/BuiltinLoader.js.map +1 -1
- package/dist/core/wechat/WechatClient.d.ts +1 -0
- package/dist/core/wechat/WechatClient.d.ts.map +1 -1
- package/dist/core/wechat/WechatClient.js +2 -0
- package/dist/core/wechat/WechatClient.js.map +1 -1
- package/dist/infrastructure/config/ConfigStore.d.ts.map +1 -1
- package/dist/infrastructure/config/ConfigStore.js +28 -3
- package/dist/infrastructure/config/ConfigStore.js.map +1 -1
- package/dist/services/DraftService.d.ts.map +1 -1
- package/dist/services/DraftService.js +2 -0
- package/dist/services/DraftService.js.map +1 -1
- package/package.json +15 -19
- package/themes/builtin/sports.css +202 -141
- package/dist/Logger-DhicjDOJ.js.map +0 -1
- package/themes/builtin/orange-heart.css +0 -176
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { readFile } from "fs/promises";
|
|
2
2
|
import axios from "axios";
|
|
3
|
-
import {
|
|
4
|
-
import { fileURLToPath } from "url";
|
|
3
|
+
import { getTheme, createWenyanCore } from "@wenyan-md/core";
|
|
5
4
|
import { JSDOM } from "jsdom";
|
|
6
5
|
import Conf from "conf";
|
|
7
6
|
import { z } from "zod";
|
|
@@ -346,6 +345,7 @@ class MaterialAPI {
|
|
|
346
345
|
class WechatClient {
|
|
347
346
|
constructor(appId, appSecret, httpClient, tokenCache, logger) {
|
|
348
347
|
this.appId = appId;
|
|
348
|
+
this.appSecret = appSecret;
|
|
349
349
|
this.token = new TokenAPI(appId, appSecret, httpClient, tokenCache, logger);
|
|
350
350
|
const getAccessToken = () => this.token.getAccessToken();
|
|
351
351
|
this.draft = new DraftAPI(getAccessToken, httpClient, logger);
|
|
@@ -475,8 +475,6 @@ class RemoteLoader {
|
|
|
475
475
|
}
|
|
476
476
|
}
|
|
477
477
|
}
|
|
478
|
-
const __filename$1 = fileURLToPath(import.meta.url);
|
|
479
|
-
const __dirname$1 = dirname(__filename$1);
|
|
480
478
|
const WENYAN_THEMES = [
|
|
481
479
|
{ id: "default", name: "默认", description: "A clean, classic layout ideal for long-form reading." },
|
|
482
480
|
{ id: "orangeheart", name: "Orange Heart", description: "A vibrant and elegant theme in warm orange tones." },
|
|
@@ -487,14 +485,9 @@ const WENYAN_THEMES = [
|
|
|
487
485
|
{ id: "purple", name: "Purple", description: "Clean and minimalist, with a subtle purple accent." },
|
|
488
486
|
{ id: "phycat", name: "物理猫-薄荷", description: "A mint-green theme with clear structure and hierarchy." }
|
|
489
487
|
];
|
|
490
|
-
const LOCAL_THEMES = [
|
|
491
|
-
{ id: "sports", name: "运动风", description: "活力 · 动感 · 渐变色,适合体育和科技内容" },
|
|
492
|
-
{ id: "orange-heart", name: "Orange Heart", description: "橙红色系主题,优雅的标题和代码样式" }
|
|
493
|
-
];
|
|
494
488
|
class BuiltinLoader {
|
|
495
489
|
async loadAll() {
|
|
496
490
|
const themes = [];
|
|
497
|
-
const { getTheme } = await import("@wenyan-md/core");
|
|
498
491
|
for (const themeInfo of WENYAN_THEMES) {
|
|
499
492
|
try {
|
|
500
493
|
const wenyanTheme = getTheme(themeInfo.id);
|
|
@@ -513,21 +506,6 @@ class BuiltinLoader {
|
|
|
513
506
|
continue;
|
|
514
507
|
}
|
|
515
508
|
}
|
|
516
|
-
for (const themeInfo of LOCAL_THEMES) {
|
|
517
|
-
try {
|
|
518
|
-
const themePath = join(__dirname$1, "../../../..", "themes", "builtin", `${themeInfo.id}.css`);
|
|
519
|
-
const css = await readFile(themePath, "utf-8");
|
|
520
|
-
themes.push({
|
|
521
|
-
id: themeInfo.id,
|
|
522
|
-
name: themeInfo.name,
|
|
523
|
-
type: "builtin",
|
|
524
|
-
description: themeInfo.description,
|
|
525
|
-
getCss: async () => css
|
|
526
|
-
});
|
|
527
|
-
} catch (error) {
|
|
528
|
-
continue;
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
509
|
return themes;
|
|
532
510
|
}
|
|
533
511
|
}
|
|
@@ -614,7 +592,6 @@ class ThemeEngine {
|
|
|
614
592
|
class MarkdownRenderer {
|
|
615
593
|
wenyan;
|
|
616
594
|
async initialize() {
|
|
617
|
-
const { createWenyanCore } = await import("@wenyan-md/core");
|
|
618
595
|
this.wenyan = await createWenyanCore({
|
|
619
596
|
isConvertMathJax: true,
|
|
620
597
|
isWechat: true
|
|
@@ -624,8 +601,8 @@ class MarkdownRenderer {
|
|
|
624
601
|
if (!this.wenyan) {
|
|
625
602
|
await this.initialize();
|
|
626
603
|
}
|
|
627
|
-
const {
|
|
628
|
-
const html = await this.wenyan.renderMarkdown(body);
|
|
604
|
+
const { data } = await this.wenyan.handleFrontMatter(markdown);
|
|
605
|
+
const html = await this.wenyan.renderMarkdown(data.body);
|
|
629
606
|
const dom = new JSDOM(html);
|
|
630
607
|
const document = dom.window.document;
|
|
631
608
|
const wenyanElement = document.createElement("div");
|
|
@@ -634,14 +611,15 @@ class MarkdownRenderer {
|
|
|
634
611
|
const options = {
|
|
635
612
|
themeCss,
|
|
636
613
|
isMacStyle: true,
|
|
637
|
-
isAddFootnote:
|
|
614
|
+
isAddFootnote: true
|
|
638
615
|
};
|
|
639
|
-
await this.wenyan.applyStylesWithTheme(wenyanElement, options);
|
|
640
|
-
const styledHtml = wenyanElement.innerHTML;
|
|
616
|
+
const styledHtml = await this.wenyan.applyStylesWithTheme(wenyanElement, options);
|
|
641
617
|
return {
|
|
642
|
-
title: attributes.title || "",
|
|
618
|
+
title: data.attributes.title || "",
|
|
643
619
|
content: styledHtml,
|
|
644
|
-
cover: attributes.cover
|
|
620
|
+
cover: data.attributes.cover,
|
|
621
|
+
author: data.attributes.author,
|
|
622
|
+
sourceUrl: data.attributes.source_url || data.attributes.sourceUrl
|
|
645
623
|
};
|
|
646
624
|
}
|
|
647
625
|
}
|
|
@@ -654,20 +632,45 @@ const AccountSchema = z.object({
|
|
|
654
632
|
createdAt: z.date().optional(),
|
|
655
633
|
updatedAt: z.date().optional()
|
|
656
634
|
});
|
|
635
|
+
const ConfigSchema = z.object({
|
|
636
|
+
accounts: z.array(AccountSchema).default([]),
|
|
637
|
+
themes: z.object({
|
|
638
|
+
local: z.array(z.object({
|
|
639
|
+
name: z.string(),
|
|
640
|
+
path: z.string()
|
|
641
|
+
})).optional(),
|
|
642
|
+
remote: z.array(z.object({
|
|
643
|
+
name: z.string(),
|
|
644
|
+
apiUrl: z.string().url(),
|
|
645
|
+
apiKey: z.string(),
|
|
646
|
+
enabled: z.boolean().default(true)
|
|
647
|
+
})).optional()
|
|
648
|
+
}).optional(),
|
|
649
|
+
defaults: z.object({
|
|
650
|
+
theme: z.string().optional(),
|
|
651
|
+
account: z.string().optional(),
|
|
652
|
+
imageQuality: z.number().min(1).max(100).default(80),
|
|
653
|
+
cacheEnabled: z.boolean().default(true)
|
|
654
|
+
}).optional(),
|
|
655
|
+
cache: z.object({
|
|
656
|
+
tokenTTL: z.number().default(7200),
|
|
657
|
+
imageTTL: z.number().default(86400),
|
|
658
|
+
themeTTL: z.number().default(3600),
|
|
659
|
+
maxSize: z.number().default(100)
|
|
660
|
+
}).optional()
|
|
661
|
+
});
|
|
657
662
|
class ConfigStore {
|
|
658
663
|
store;
|
|
659
664
|
constructor() {
|
|
660
665
|
this.store = new Conf({
|
|
661
|
-
projectName: "wechat-md-publisher"
|
|
666
|
+
projectName: "wechat-md-publisher",
|
|
667
|
+
schema: ConfigSchema
|
|
662
668
|
});
|
|
663
669
|
}
|
|
664
670
|
get(key, defaultValue) {
|
|
665
671
|
return this.store.get(key, defaultValue);
|
|
666
672
|
}
|
|
667
673
|
set(key, value) {
|
|
668
|
-
if (key === "accounts") {
|
|
669
|
-
z.array(AccountSchema).parse(value);
|
|
670
|
-
}
|
|
671
674
|
this.store.set(key, value);
|
|
672
675
|
}
|
|
673
676
|
has(key) {
|
|
@@ -736,4 +739,4 @@ export {
|
|
|
736
739
|
WechatError as e,
|
|
737
740
|
WechatRateLimitError as f
|
|
738
741
|
};
|
|
739
|
-
//# sourceMappingURL=Logger-
|
|
742
|
+
//# sourceMappingURL=Logger-CU2JwTgd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Logger-CU2JwTgd.js","sources":["../src/errors/BaseError.ts","../src/errors/WechatError.ts","../src/core/wechat/constants.ts","../src/core/wechat/api/TokenAPI.ts","../src/core/wechat/api/DraftAPI.ts","../src/core/wechat/api/PublishAPI.ts","../src/core/wechat/api/MaterialAPI.ts","../src/core/wechat/WechatClient.ts","../src/errors/ThemeError.ts","../src/core/theme/loaders/LocalLoader.ts","../src/core/theme/loaders/RemoteLoader.ts","../src/core/theme/loaders/BuiltinLoader.ts","../src/core/theme/registry.ts","../src/core/theme/ThemeEngine.ts","../src/core/renderer/MarkdownRenderer.ts","../src/infrastructure/config/ConfigStore.ts","../src/infrastructure/logger/Logger.ts"],"sourcesContent":["export class BaseError extends Error {\n constructor(\n message: string,\n public code: string,\n public statusCode: number = 500,\n public details?: any\n ) {\n super(message);\n this.name = this.constructor.name;\n Error.captureStackTrace(this, this.constructor);\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n statusCode: this.statusCode,\n details: this.details,\n };\n }\n}\n","import { BaseError } from './BaseError';\n\nexport class WechatError extends BaseError {\n constructor(\n message: string,\n public errcode: number,\n public errmsg: string\n ) {\n super(message, 'WECHAT_API_ERROR', 500, { errcode, errmsg });\n }\n\n static fromResponse(data: { errcode: number; errmsg: string }): WechatError {\n return new WechatError(\n `微信 API 错误: ${data.errmsg} (${data.errcode})`,\n data.errcode,\n data.errmsg\n );\n }\n}\n\nexport class WechatAuthError extends BaseError {\n constructor(message: string) {\n super(message, 'WECHAT_AUTH_ERROR', 401);\n }\n}\n\nexport class WechatRateLimitError extends BaseError {\n constructor(message: string) {\n super(message, 'WECHAT_RATE_LIMIT_ERROR', 429);\n }\n}\n","export const WECHAT_API_BASE = 'https://api.weixin.qq.com';\n\nexport const WECHAT_API_ENDPOINTS = {\n TOKEN: '/cgi-bin/token',\n DRAFT_ADD: '/cgi-bin/draft/add',\n DRAFT_GET: '/cgi-bin/draft/get',\n DRAFT_DELETE: '/cgi-bin/draft/delete',\n DRAFT_UPDATE: '/cgi-bin/draft/update',\n DRAFT_BATCH_GET: '/cgi-bin/draft/batchget',\n DRAFT_COUNT: '/cgi-bin/draft/count',\n PUBLISH_SUBMIT: '/cgi-bin/freepublish/submit',\n PUBLISH_GET: '/cgi-bin/freepublish/get',\n PUBLISH_DELETE: '/cgi-bin/freepublish/delete',\n PUBLISH_BATCH_GET: '/cgi-bin/freepublish/batchget',\n PUBLISH_GET_STATUS: '/cgi-bin/freepublish/get',\n MATERIAL_ADD: '/cgi-bin/material/add_material',\n MATERIAL_GET: '/cgi-bin/material/get_material',\n MATERIAL_DELETE: '/cgi-bin/material/del_material',\n MATERIAL_BATCH_GET: '/cgi-bin/material/batchget_material',\n MATERIAL_COUNT: '/cgi-bin/material/get_materialcount',\n} as const;\n\nexport const WECHAT_ERROR_CODES = {\n SUCCESS: 0,\n INVALID_CREDENTIAL: 40001,\n ACCESS_TOKEN_EXPIRED: 42001,\n RATE_LIMIT_EXCEEDED: 45009,\n API_UNAUTHORIZED: 48001,\n} as const;\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { TokenCache } from '../../../infrastructure/cache/TokenCache';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\n\nexport class TokenAPI {\n constructor(\n private appId: string,\n private appSecret: string,\n private httpClient: HttpClient,\n private tokenCache: TokenCache,\n private logger: Logger\n ) {}\n\n async getAccessToken(): Promise<string> {\n const cached = await this.tokenCache.getToken(this.appId);\n if (cached) {\n this.logger.debug('使用缓存的 Access Token', { appId: this.appId });\n return cached;\n }\n\n return await this.refreshAccessToken();\n }\n\n async refreshAccessToken(): Promise<string> {\n this.logger.info('刷新 Access Token', { appId: this.appId });\n\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.TOKEN}`;\n const response = await this.httpClient.get(url, {\n params: {\n grant_type: 'client_credential',\n appid: this.appId,\n secret: this.appSecret,\n },\n });\n\n const data = response.data;\n\n if (data.errcode) {\n throw WechatError.fromResponse(data);\n }\n\n await this.tokenCache.setToken(\n this.appId,\n data.access_token,\n data.expires_in\n );\n\n this.logger.info('Access Token 刷新成功', {\n appId: this.appId,\n expiresIn: data.expires_in,\n });\n\n return data.access_token;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\nimport type { Draft, DraftList, DraftArticle } from '../../../types/draft';\n\nexport class DraftAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async create(article: DraftArticle): Promise<{ media_id: string }> {\n this.logger.info('创建草稿', { title: article.title });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_ADD}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n articles: [article],\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿创建成功', { media_id: data.media_id });\n return { media_id: data.media_id };\n }\n\n async get(mediaId: string): Promise<Draft> {\n this.logger.info('获取草稿详情', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async list(offset: number = 0, count: number = 20): Promise<DraftList> {\n this.logger.info('获取草稿列表', { offset, count });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_BATCH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n offset,\n count,\n no_content: 0,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async delete(mediaId: string): Promise<void> {\n this.logger.info('删除草稿', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_DELETE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿删除成功');\n }\n\n async update(mediaId: string, article: DraftArticle, index: number = 0): Promise<void> {\n this.logger.info('更新草稿', { media_id: mediaId, index });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_UPDATE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n index,\n articles: article,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('草稿更新成功');\n }\n\n async count(): Promise<number> {\n this.logger.info('获取草稿总数');\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.DRAFT_COUNT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.get(url);\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data.total_count || 0;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\nimport type { PublishResult, PublishedArticle, PublishList, PublishStatus } from '../../../types/publish';\n\nexport class PublishAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async submit(mediaId: string): Promise<PublishResult> {\n this.logger.info('发布草稿', { media_id: mediaId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_SUBMIT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n media_id: mediaId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('发布任务提交成功', { publish_id: data.publish_id });\n return {\n publish_id: data.publish_id,\n msg_data_id: data.msg_data_id,\n };\n }\n\n async get(articleId: string): Promise<PublishedArticle> {\n this.logger.info('获取已发布文章详情', { article_id: articleId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n article_id: articleId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async list(offset: number = 0, count: number = 20): Promise<PublishList> {\n this.logger.info('获取已发布文章列表', { offset, count });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_BATCH_GET}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n offset,\n count,\n no_content: 0,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n\n async delete(articleId: string, index: number = 0): Promise<void> {\n this.logger.info('删除已发布文章', { article_id: articleId, index });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_DELETE}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n article_id: articleId,\n index,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n this.logger.info('已发布文章删除成功');\n }\n\n async getStatus(publishId: string): Promise<PublishStatus> {\n this.logger.info('获取发布状态', { publish_id: publishId });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.PUBLISH_GET_STATUS}?access_token=${accessToken}`;\n\n const response = await this.httpClient.post(url, {\n publish_id: publishId,\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n}\n","import { HttpClient } from '../../../infrastructure/http/HttpClient';\nimport { Logger } from '../../../infrastructure/logger/Logger';\nimport { WechatError } from '../../../errors/WechatError';\nimport { WECHAT_API_BASE, WECHAT_API_ENDPOINTS } from '../constants';\n\nexport interface UploadResult {\n media_id: string;\n url: string;\n}\n\nexport class MaterialAPI {\n constructor(\n private getAccessToken: () => Promise<string>,\n private httpClient: HttpClient,\n private logger: Logger\n ) {}\n\n async uploadImage(file: Buffer, filename: string): Promise<UploadResult> {\n this.logger.info('上传图片', { filename });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_ADD}?access_token=${accessToken}&type=image`;\n\n const formData = new FormData();\n const blob = new Blob([file]);\n formData.append('media', blob, filename);\n\n const response = await this.httpClient.post(url, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n if (data.url && data.url.startsWith('http://')) {\n data.url = data.url.replace(/^http:\\/\\//i, 'https://');\n }\n\n this.logger.info('图片上传成功', { media_id: data.media_id });\n return {\n media_id: data.media_id,\n url: data.url,\n };\n }\n\n async uploadThumb(file: Buffer, filename: string): Promise<UploadResult> {\n this.logger.info('上传封面图', { filename });\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_ADD}?access_token=${accessToken}&type=thumb`;\n\n const formData = new FormData();\n const blob = new Blob([file]);\n formData.append('media', blob, filename);\n\n const response = await this.httpClient.post(url, formData, {\n headers: {\n 'Content-Type': 'multipart/form-data',\n },\n });\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n if (data.url && data.url.startsWith('http://')) {\n data.url = data.url.replace(/^http:\\/\\//i, 'https://');\n }\n\n this.logger.info('封面图上传成功', { media_id: data.media_id });\n return {\n media_id: data.media_id,\n url: data.url,\n };\n }\n\n async getMaterialCount(): Promise<{ voice_count: number; video_count: number; image_count: number; news_count: number }> {\n this.logger.info('获取素材总数');\n\n const accessToken = await this.getAccessToken();\n const url = `${WECHAT_API_BASE}${WECHAT_API_ENDPOINTS.MATERIAL_COUNT}?access_token=${accessToken}`;\n\n const response = await this.httpClient.get(url);\n\n const data = response.data;\n\n if (data.errcode && data.errcode !== 0) {\n throw WechatError.fromResponse(data);\n }\n\n return data;\n }\n}\n","import { TokenAPI } from './api/TokenAPI';\nimport { DraftAPI } from './api/DraftAPI';\nimport { PublishAPI } from './api/PublishAPI';\nimport { MaterialAPI } from './api/MaterialAPI';\nimport { HttpClient } from '../../infrastructure/http/HttpClient';\nimport { TokenCache } from '../../infrastructure/cache/TokenCache';\nimport { Logger } from '../../infrastructure/logger/Logger';\n\nexport class WechatClient {\n public readonly token: TokenAPI;\n public readonly draft: DraftAPI;\n public readonly publish: PublishAPI;\n public readonly material: MaterialAPI;\n\n constructor(\n private appId: string,\n private appSecret: string,\n httpClient: HttpClient,\n tokenCache: TokenCache,\n logger: Logger\n ) {\n this.token = new TokenAPI(appId, appSecret, httpClient, tokenCache, logger);\n \n const getAccessToken = () => this.token.getAccessToken();\n \n this.draft = new DraftAPI(getAccessToken, httpClient, logger);\n this.publish = new PublishAPI(getAccessToken, httpClient, logger);\n this.material = new MaterialAPI(getAccessToken, httpClient, logger);\n }\n\n async getAccessToken(): Promise<string> {\n return await this.token.getAccessToken();\n }\n\n async refreshAccessToken(): Promise<string> {\n return await this.token.refreshAccessToken();\n }\n\n getAppId(): string {\n return this.appId;\n }\n}\n","import { BaseError } from './BaseError';\n\nexport class ThemeError extends BaseError {\n constructor(message: string, details?: any) {\n super(message, 'THEME_ERROR', 500, details);\n }\n}\n\nexport class ThemeNotFoundError extends BaseError {\n constructor(themeId: string) {\n super(`主题不存在: ${themeId}`, 'THEME_NOT_FOUND', 404, { themeId });\n }\n}\n\nexport class ThemeLoadError extends BaseError {\n constructor(themeId: string, reason: string) {\n super(`主题加载失败: ${themeId} - ${reason}`, 'THEME_LOAD_ERROR', 500, { themeId, reason });\n }\n}\n","import { readFile } from 'fs/promises';\nimport type { Theme } from '../../../types/theme';\nimport { ThemeLoadError } from '../../../errors/ThemeError';\n\nexport class LocalLoader {\n async load(name: string, path: string): Promise<Theme> {\n try {\n const css = await readFile(path, 'utf-8');\n \n return {\n id: name,\n name,\n type: 'local',\n description: `本地主题: ${path}`,\n getCss: async () => css,\n };\n } catch (error) {\n throw new ThemeLoadError(name, `无法读取文件: ${path}`);\n }\n }\n}\n","import axios from 'axios';\nimport type { Theme, ThemeSource, RemoteThemeConfig } from '../../../types/theme';\nimport { ThemeLoadError } from '../../../errors/ThemeError';\n\nexport class RemoteLoader {\n private configs: Map<string, RemoteThemeConfig> = new Map();\n\n async addAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n this.configs.set(name, {\n name,\n apiUrl,\n apiKey,\n enabled: true,\n });\n }\n\n async load(themeId: string): Promise<Theme | null> {\n for (const [name, config] of this.configs) {\n if (!config.enabled) continue;\n\n try {\n const css = await this.fetchThemeCSS(config.apiUrl, config.apiKey, themeId);\n if (css) {\n return {\n id: themeId,\n name: `${name}:${themeId}`,\n type: 'remote',\n description: `远程主题来自 ${name}`,\n getCss: async () => css,\n };\n }\n } catch (error) {\n continue;\n }\n }\n\n return null;\n }\n\n async list(): Promise<ThemeSource[]> {\n const themes: ThemeSource[] = [];\n\n for (const [name, config] of this.configs) {\n if (!config.enabled) continue;\n\n try {\n const themeList = await this.fetchThemeList(config.apiUrl, config.apiKey);\n for (const themeId of themeList) {\n themes.push({\n type: 'remote',\n id: themeId,\n name: `${name}:${themeId}`,\n description: `远程主题来自 ${name}`,\n });\n }\n } catch (error) {\n continue;\n }\n }\n\n return themes;\n }\n\n getConfig(): RemoteThemeConfig[] {\n return Array.from(this.configs.values());\n }\n\n private async fetchThemeList(apiUrl: string, apiKey: string): Promise<string[]> {\n try {\n const response = await axios.get(`${apiUrl}/themes`, {\n headers: {\n 'X-API-Key': apiKey,\n },\n });\n return response.data.themes || [];\n } catch (error) {\n throw new ThemeLoadError('remote', '无法获取远程主题列表');\n }\n }\n\n private async fetchThemeCSS(apiUrl: string, apiKey: string, themeId: string): Promise<string | null> {\n try {\n const response = await axios.get(`${apiUrl}/themes/${themeId}`, {\n headers: {\n 'X-API-Key': apiKey,\n },\n });\n return response.data.css || null;\n } catch (error) {\n return null;\n }\n }\n}\n","import { getTheme } from '@wenyan-md/core';\nimport type { Theme } from '../../../types/theme';\n\nconst WENYAN_THEMES = [\n { id: 'default', name: '默认', description: 'A clean, classic layout ideal for long-form reading.' },\n { id: 'orangeheart', name: 'Orange Heart', description: 'A vibrant and elegant theme in warm orange tones.' },\n { id: 'rainbow', name: 'Rainbow', description: 'A colorful, lively theme with a clean layout.' },\n { id: 'lapis', name: 'Lapis', description: 'A minimal and refreshing theme in cool blue tones.' },\n { id: 'pie', name: 'Pie', description: 'Inspired by sspai.com and Misty — modern, sharp, and stylish.' },\n { id: 'maize', name: 'Maize', description: 'A crisp, light theme with a soft maize palette.' },\n { id: 'purple', name: 'Purple', description: 'Clean and minimalist, with a subtle purple accent.' },\n { id: 'phycat', name: '物理猫-薄荷', description: 'A mint-green theme with clear structure and hierarchy.' },\n];\n\nexport class BuiltinLoader {\n async loadAll(): Promise<Theme[]> {\n const themes: Theme[] = [];\n\n for (const themeInfo of WENYAN_THEMES) {\n try {\n const wenyanTheme = getTheme(themeInfo.id);\n if (!wenyanTheme) {\n continue;\n }\n\n const css = await wenyanTheme.getCss();\n\n themes.push({\n id: themeInfo.id,\n name: themeInfo.name,\n type: 'builtin',\n description: themeInfo.description,\n getCss: async () => css,\n });\n } catch (error) {\n continue;\n }\n }\n\n return themes;\n }\n}\n","import type { Theme, ThemeSource } from '../../types/theme';\n\nexport class ThemeRegistry {\n private themes: Map<string, Theme> = new Map();\n\n register(theme: Theme): void {\n this.themes.set(theme.id, theme);\n }\n\n get(id: string): Theme | undefined {\n return this.themes.get(id);\n }\n\n has(id: string): boolean {\n return this.themes.has(id);\n }\n\n remove(id: string): void {\n this.themes.delete(id);\n }\n\n list(): ThemeSource[] {\n return Array.from(this.themes.values()).map(theme => ({\n type: theme.type,\n id: theme.id,\n name: theme.name,\n description: theme.description,\n }));\n }\n\n getLocalThemes(): ThemeSource[] {\n return this.list().filter(t => t.type === 'local');\n }\n\n clear(): void {\n this.themes.clear();\n }\n}\n","import { LocalLoader } from './loaders/LocalLoader';\nimport { RemoteLoader } from './loaders/RemoteLoader';\nimport { BuiltinLoader } from './loaders/BuiltinLoader';\nimport { ThemeRegistry } from './registry';\nimport { ThemeNotFoundError } from '../../errors/ThemeError';\nimport type { ThemeSource } from '../../types/theme';\n\nexport class ThemeEngine {\n private registry: ThemeRegistry;\n private localLoader: LocalLoader;\n private remoteLoader: RemoteLoader;\n private builtinLoader: BuiltinLoader;\n\n constructor() {\n this.registry = new ThemeRegistry();\n this.localLoader = new LocalLoader();\n this.remoteLoader = new RemoteLoader();\n this.builtinLoader = new BuiltinLoader();\n }\n\n async loadBuiltinThemes(): Promise<void> {\n const themes = await this.builtinLoader.loadAll();\n for (const theme of themes) {\n this.registry.register(theme);\n }\n }\n\n async addLocalTheme(name: string, path: string): Promise<void> {\n const theme = await this.localLoader.load(name, path);\n this.registry.register(theme);\n }\n\n async addRemoteAPI(name: string, apiUrl: string, apiKey: string): Promise<void> {\n await this.remoteLoader.addAPI(name, apiUrl, apiKey);\n }\n\n async getThemeCSS(themeId: string): Promise<string> {\n const theme = this.registry.get(themeId);\n if (theme) {\n return await theme.getCss();\n }\n\n const remoteTheme = await this.remoteLoader.load(themeId);\n if (remoteTheme) {\n return await remoteTheme.getCss();\n }\n\n throw new ThemeNotFoundError(themeId);\n }\n\n async listThemes(): Promise<ThemeSource[]> {\n const themes: ThemeSource[] = [];\n \n themes.push(...this.registry.list());\n \n themes.push(...await this.remoteLoader.list());\n\n return themes;\n }\n\n async removeTheme(themeId: string): Promise<void> {\n this.registry.remove(themeId);\n }\n\n async getConfig(): Promise<any> {\n return {\n local: this.registry.getLocalThemes(),\n remote: this.remoteLoader.getConfig(),\n };\n }\n}\n","import { createWenyanCore } from '@wenyan-md/core';\nimport type { ApplyStylesOptions } from '@wenyan-md/core';\nimport { JSDOM } from 'jsdom';\n\nexport interface RenderResult {\n title: string;\n content: string;\n cover?: string;\n author?: string;\n sourceUrl?: string;\n}\n\nexport class MarkdownRenderer {\n private wenyan: any;\n\n async initialize(): Promise<void> {\n this.wenyan = await createWenyanCore({\n isConvertMathJax: true,\n isWechat: true,\n });\n }\n\n async render(markdown: string, themeCss?: string): Promise<RenderResult> {\n if (!this.wenyan) {\n await this.initialize();\n }\n\n const { data } = await this.wenyan.handleFrontMatter(markdown);\n const html = await this.wenyan.renderMarkdown(data.body);\n\n const dom = new JSDOM(html);\n const document = dom.window.document;\n const wenyanElement = document.createElement('div');\n wenyanElement.id = 'wenyan';\n wenyanElement.innerHTML = html;\n\n const options: ApplyStylesOptions = {\n themeCss,\n isMacStyle: true,\n isAddFootnote: true,\n };\n\n const styledHtml = await this.wenyan.applyStylesWithTheme(wenyanElement, options);\n\n return {\n title: data.attributes.title || '',\n content: styledHtml,\n cover: data.attributes.cover,\n author: data.attributes.author,\n sourceUrl: data.attributes.source_url || data.attributes.sourceUrl,\n };\n }\n}\n","import Conf from 'conf';\nimport { z } from 'zod';\nimport type { Config } from '../../types/config';\n\nconst AccountSchema = z.object({\n id: z.string(),\n name: z.string(),\n appId: z.string().regex(/^wx[a-zA-Z0-9]{16}$/, '无效的 AppID 格式'),\n appSecret: z.string().min(32, 'AppSecret 长度不足'),\n isDefault: z.boolean().optional(),\n createdAt: z.date().optional(),\n updatedAt: z.date().optional(),\n});\n\nconst ConfigSchema = z.object({\n accounts: z.array(AccountSchema).default([]),\n themes: z.object({\n local: z.array(z.object({\n name: z.string(),\n path: z.string(),\n })).optional(),\n remote: z.array(z.object({\n name: z.string(),\n apiUrl: z.string().url(),\n apiKey: z.string(),\n enabled: z.boolean().default(true),\n })).optional(),\n }).optional(),\n defaults: z.object({\n theme: z.string().optional(),\n account: z.string().optional(),\n imageQuality: z.number().min(1).max(100).default(80),\n cacheEnabled: z.boolean().default(true),\n }).optional(),\n cache: z.object({\n tokenTTL: z.number().default(7200),\n imageTTL: z.number().default(86400),\n themeTTL: z.number().default(3600),\n maxSize: z.number().default(100),\n }).optional(),\n});\n\nexport class ConfigStore {\n private store: Conf<Config>;\n\n constructor() {\n this.store = new Conf<Config>({\n projectName: 'wechat-md-publisher',\n schema: ConfigSchema as any,\n });\n }\n\n get<K extends keyof Config>(key: K): Config[K] | undefined;\n get<K extends keyof Config>(key: K, defaultValue: Config[K]): Config[K];\n get<K extends keyof Config>(key: K, defaultValue?: Config[K]): Config[K] | undefined {\n return this.store.get(key, defaultValue as any);\n }\n\n set<K extends keyof Config>(key: K, value: Config[K]): void {\n this.store.set(key, value);\n }\n\n has(key: keyof Config): boolean {\n return this.store.has(key);\n }\n\n delete(key: keyof Config): void {\n this.store.delete(key);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n getAll(): Config {\n return this.store.store;\n }\n\n getPath(): string {\n return this.store.path;\n }\n}\n","import winston from 'winston';\n\nexport class Logger {\n private logger: winston.Logger;\n\n constructor() {\n this.logger = winston.createLogger({\n level: process.env.LOG_LEVEL || 'info',\n format: winston.format.combine(\n winston.format.timestamp(),\n winston.format.errors({ stack: true }),\n winston.format.json()\n ),\n transports: [\n new winston.transports.Console({\n format: winston.format.combine(\n winston.format.colorize(),\n winston.format.printf(({ level, message, timestamp, ...meta }) => {\n const metaStr = Object.keys(meta).length ? JSON.stringify(meta) : '';\n return `${timestamp} [${level}]: ${message} ${metaStr}`;\n })\n ),\n }),\n ],\n });\n }\n\n debug(message: string, meta?: any): void {\n this.logger.debug(message, meta);\n }\n\n info(message: string, meta?: any): void {\n this.logger.info(message, meta);\n }\n\n warn(message: string, meta?: any): void {\n this.logger.warn(message, meta);\n }\n\n error(message: string, meta?: any): void {\n this.logger.error(message, meta);\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Command } from "commander";
|
|
|
3
3
|
import { readFileSync } from "fs";
|
|
4
4
|
import { isAbsolute, resolve, dirname, join } from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
|
-
import { C as ConfigStore, L as Logger, T as ThemeEngine, M as MarkdownRenderer, d as WechatClient } from "./Logger-
|
|
6
|
+
import { C as ConfigStore, L as Logger, T as ThemeEngine, M as MarkdownRenderer, d as WechatClient } from "./Logger-CU2JwTgd.js";
|
|
7
7
|
import axios from "axios";
|
|
8
8
|
import { JSDOM } from "jsdom";
|
|
9
9
|
import { readFile } from "fs/promises";
|
|
@@ -235,8 +235,9 @@ class ImageProcessor {
|
|
|
235
235
|
return { content, firstImageMediaId: "" };
|
|
236
236
|
}
|
|
237
237
|
const dom = new JSDOM(content);
|
|
238
|
-
const
|
|
239
|
-
const
|
|
238
|
+
const document = dom.window.document;
|
|
239
|
+
const images = Array.from(document.querySelectorAll("img"));
|
|
240
|
+
const uploadPromises = images.map(async (element) => {
|
|
240
241
|
const src = element.getAttribute("src");
|
|
241
242
|
if (!src) return null;
|
|
242
243
|
if (isWechatImageUrl(src)) {
|
|
@@ -538,7 +539,9 @@ class DraftService {
|
|
|
538
539
|
const result = await this.wechatClient.draft.create({
|
|
539
540
|
title: rendered.title,
|
|
540
541
|
content,
|
|
541
|
-
thumb_media_id: thumbMediaId
|
|
542
|
+
thumb_media_id: thumbMediaId,
|
|
543
|
+
author: rendered.author,
|
|
544
|
+
content_source_url: rendered.sourceUrl
|
|
542
545
|
});
|
|
543
546
|
this.logger.info("草稿创建成功", { media_id: result.media_id });
|
|
544
547
|
return result;
|