@wenyan-md/core 3.0.7 → 3.0.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/core.js CHANGED
@@ -446,12 +446,24 @@ function createMarkedClient() {
446
446
  const match = rule.exec(src);
447
447
  if (!match) return;
448
448
  const isImage = !!match[1];
449
+ const text = match[2];
450
+ const inner = match[3].trim();
451
+ let href = "";
452
+ let title = "";
453
+ const titleMatch = inner.match(/(.*?)\s+["']([^"']*)["']$/);
454
+ if (titleMatch) {
455
+ href = titleMatch[1].trim();
456
+ title = titleMatch[2];
457
+ } else {
458
+ href = inner;
459
+ }
449
460
  return {
450
461
  type: isImage ? "image" : "link",
451
462
  raw: match[0],
452
- text: match[2],
453
- href: match[3],
454
- tokens: this.lexer.inlineTokens(match[2])
463
+ text,
464
+ href,
465
+ title,
466
+ tokens: this.lexer.inlineTokens(text)
455
467
  };
456
468
  }
457
469
  },
@@ -1519,7 +1531,7 @@ async function replaceMermaidCodeBlocks(root, renderDiagram) {
1519
1531
  return false;
1520
1532
  }
1521
1533
  const ownerDocument = getOwnerDocument(root);
1522
- for (const [index, codeBlock] of codeBlocks.entries()) {
1534
+ for (const [_, codeBlock] of codeBlocks.entries()) {
1523
1535
  const pre = codeBlock.parentElement;
1524
1536
  const parent = pre?.parentElement;
1525
1537
  if (!pre || !parent) {
@@ -1527,7 +1539,7 @@ async function replaceMermaidCodeBlocks(root, renderDiagram) {
1527
1539
  }
1528
1540
  const code = codeBlock.textContent ?? "";
1529
1541
  const svg = await renderDiagram({
1530
- id: `wenyan-mermaid-${index + 1}`,
1542
+ id: `wenyan-mermaid-${crypto.randomUUID()}`,
1531
1543
  code
1532
1544
  });
1533
1545
  const figure = ownerDocument.createElement("figure");
@@ -1548,7 +1560,6 @@ function createBrowserMermaidRenderer(options = {}) {
1548
1560
  const document = parser.parseFromString(`<body>${html}</body>`, "text/html");
1549
1561
  const root = document.body;
1550
1562
  const mermaid = await getMermaidModule();
1551
- mermaid.initialize(createMermaidConfig(options.mermaidConfig));
1552
1563
  try {
1553
1564
  await replaceMermaidCodeBlocks(root, async ({ id, code }) => {
1554
1565
  const { svg } = await mermaid.render(id, code);
@@ -1565,7 +1576,9 @@ function createBrowserMermaidRenderer(options = {}) {
1565
1576
  mermaidModulePromise = import("mermaid");
1566
1577
  }
1567
1578
  const module = await mermaidModulePromise;
1568
- return module.default;
1579
+ const mermaid = module.default;
1580
+ mermaid.initialize(createMermaidConfig(options.mermaidConfig));
1581
+ return mermaid;
1569
1582
  }
1570
1583
  }
1571
1584
  function createMermaidRenderError(error) {
package/dist/publish.js CHANGED
@@ -16,7 +16,7 @@ class TokenStore {
16
16
  try {
17
17
  const loadedData = await this.adapter.loadToken();
18
18
  if (loadedData) {
19
- this.cache = loadedData;
19
+ this.cache = { ...defaultTokenCache, ...loadedData };
20
20
  }
21
21
  } catch (error) {
22
22
  throw new Error(`无法加载 token: ${error instanceof Error ? error.message : String(error)}`);
@@ -32,15 +32,16 @@ class TokenStore {
32
32
  async waitForInit() {
33
33
  await this.initPromise;
34
34
  }
35
- isValid(appid) {
35
+ async isValid(appid) {
36
+ await this.initPromise;
36
37
  const currentTime = Math.floor(Date.now() / 1e3);
37
38
  const bufferTime = 600;
38
39
  const isAppidMatch = this.cache.appid === appid;
39
- const isNotExpired = this.cache.expireAt > currentTime + bufferTime;
40
+ const isNotExpired = this.cache.expireAt < 0 ? true : this.cache.expireAt > currentTime + bufferTime;
40
41
  return isAppidMatch && isNotExpired;
41
42
  }
42
- getToken(appid) {
43
- return this.isValid(appid) ? this.cache.accessToken : null;
43
+ async getToken(appid) {
44
+ return await this.isValid(appid) ? this.cache.accessToken : null;
44
45
  }
45
46
  async setToken(appid, accessToken, expiresIn) {
46
47
  await this.initPromise;
@@ -52,6 +53,16 @@ class TokenStore {
52
53
  };
53
54
  await this.save();
54
55
  }
56
+ async setExternalToken(appid, accessToken) {
57
+ await this.initPromise;
58
+ this.cache = {
59
+ appid,
60
+ accessToken,
61
+ expireAt: -1
62
+ // 标记为外部托管,永不校验过期
63
+ };
64
+ await this.save();
65
+ }
55
66
  async clear() {
56
67
  await this.initPromise;
57
68
  this.cache = { ...defaultTokenCache };
@@ -115,12 +126,14 @@ class CredentialStore {
115
126
  constructor(adapter) {
116
127
  this.adapter = adapter;
117
128
  this.initPromise = this.load();
129
+ this.initPromise.catch(() => {
130
+ });
118
131
  }
119
132
  async load() {
120
133
  try {
121
134
  const loadedData = await this.adapter.loadCredential();
122
135
  if (loadedData) {
123
- this.credential = loadedData;
136
+ this.credential = { ...defaultCredential, ...loadedData };
124
137
  }
125
138
  } catch (error) {
126
139
  throw new Error(`无法加载凭据: ${error instanceof Error ? error.message : String(error)}`);
@@ -133,27 +146,47 @@ class CredentialStore {
133
146
  throw new Error(`无法保存凭据: ${error instanceof Error ? error.message : String(error)}`);
134
147
  }
135
148
  }
136
- async _getWechatCredential() {
149
+ /**
150
+ * 获取微信凭据 (通过 appId 或 alias)
151
+ */
152
+ async getWechatCredential(appIdOrAlias) {
137
153
  await this.initPromise;
138
- return this.credential.wechat ?? {};
139
- }
140
- async getWechatCredential(appId) {
141
- const wechat = await this._getWechatCredential();
142
- if (!wechat) return null;
143
- const appSecret = wechat[appId];
144
- if (!appSecret) return null;
145
- return { appId, appSecret };
154
+ const wechat = this.credential.wechat ?? {};
155
+ if (wechat[appIdOrAlias]) {
156
+ return {
157
+ appId: appIdOrAlias,
158
+ ...wechat[appIdOrAlias]
159
+ };
160
+ }
161
+ const entry = Object.entries(wechat).find(([_, item]) => item.alias === appIdOrAlias);
162
+ if (entry) {
163
+ return {
164
+ appId: entry[0],
165
+ ...entry[1]
166
+ };
167
+ }
168
+ return null;
146
169
  }
147
- async saveWechatCredential(appId, appSecret) {
170
+ /**
171
+ * 保存或更新微信凭据
172
+ */
173
+ async saveWechatCredential(appId, appSecret, alias) {
148
174
  await this.initPromise;
149
175
  this.credential.wechat ??= {};
150
- this.credential.wechat[appId] = appSecret;
176
+ const item = { appSecret };
177
+ if (alias) {
178
+ item.alias = alias;
179
+ }
180
+ this.credential.wechat[appId] = item;
151
181
  await this.save();
152
182
  }
153
- async deleteWechatCredential(appId) {
154
- await this.initPromise;
155
- if (this.credential.wechat) {
156
- delete this.credential.wechat[appId];
183
+ /**
184
+ * 删除微信凭据 (通过 appId 或 alias)
185
+ */
186
+ async deleteWechatCredential(appIdOrAlias) {
187
+ const target = await this.getWechatCredential(appIdOrAlias);
188
+ if (target && this.credential.wechat) {
189
+ delete this.credential.wechat[target.appId];
157
190
  await this.save();
158
191
  }
159
192
  }
@@ -177,7 +210,7 @@ class WechatPublisher {
177
210
  const result2 = await this.fetchAccessToken(appId, appSecret);
178
211
  return result2.access_token;
179
212
  }
180
- const cached = this.tokenStore.getToken(appId);
213
+ const cached = await this.tokenStore.getToken(appId);
181
214
  if (cached) {
182
215
  return cached;
183
216
  }
@@ -217,6 +250,11 @@ class WechatPublisher {
217
250
  await this.uploadCacheStore.clear();
218
251
  }
219
252
  }
253
+ async setExternalToken(appid, accessToken) {
254
+ if (this.tokenStore) {
255
+ await this.tokenStore.setExternalToken(appid, accessToken);
256
+ }
257
+ }
220
258
  }
221
259
  export {
222
260
  CredentialStore,
@@ -1,5 +1,9 @@
1
+ export interface WechatCredentialItem {
2
+ appSecret: string;
3
+ alias?: string;
4
+ }
1
5
  export interface WenyanCredential {
2
- wechat?: Record<string, string>;
6
+ wechat?: Record<string, WechatCredentialItem>;
3
7
  }
4
8
  export declare const defaultCredential: WenyanCredential;
5
9
  export interface CredentialStorageAdapter {
@@ -14,11 +18,20 @@ export declare class CredentialStore {
14
18
  constructor(adapter: CredentialStorageAdapter);
15
19
  private load;
16
20
  private save;
17
- private _getWechatCredential;
18
- getWechatCredential(appId: string): Promise<{
21
+ /**
22
+ * 获取微信凭据 (通过 appId 或 alias)
23
+ */
24
+ getWechatCredential(appIdOrAlias: string): Promise<{
19
25
  appId: string;
20
26
  appSecret: string;
27
+ alias?: string;
21
28
  } | null>;
22
- saveWechatCredential(appId: string, appSecret: string): Promise<void>;
23
- deleteWechatCredential(appId: string): Promise<void>;
29
+ /**
30
+ * 保存或更新微信凭据
31
+ */
32
+ saveWechatCredential(appId: string, appSecret: string, alias?: string | null): Promise<void>;
33
+ /**
34
+ * 删除微信凭据 (通过 appId 或 alias)
35
+ */
36
+ deleteWechatCredential(appIdOrAlias: string): Promise<void>;
24
37
  }
@@ -25,6 +25,7 @@ export declare class WechatPublisher {
25
25
  uploadImage(file: Blob, filename: string, accessToken: string, appId?: string): Promise<WechatUploadResponse>;
26
26
  publishToDraft(accessToken: string, options: WechatPublishOptions): Promise<WechatPublishResponse>;
27
27
  clearCache(): Promise<void>;
28
+ setExternalToken(appid: string, accessToken: string): Promise<void>;
28
29
  }
29
30
  export * from "./tokenStore.js";
30
31
  export * from "./uploadCacheStore.js";
@@ -17,8 +17,9 @@ export declare class TokenStore {
17
17
  private load;
18
18
  private save;
19
19
  waitForInit(): Promise<void>;
20
- isValid(appid: string): boolean;
21
- getToken(appid: string): string | null;
20
+ isValid(appid: string): Promise<boolean>;
21
+ getToken(appid: string): Promise<string | null>;
22
22
  setToken(appid: string, accessToken: string, expiresIn: number): Promise<void>;
23
+ setExternalToken(appid: string, accessToken: string): Promise<void>;
23
24
  clear(): Promise<void>;
24
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wenyan-md/core",
3
- "version": "3.0.7",
3
+ "version": "3.0.8",
4
4
  "description": "Core library for Wenyan markdown rendering & publishing",
5
5
  "author": "Lei <caol64@gmail.com> (https://github.com/caol64)",
6
6
  "license": "Apache-2.0",