@skrillex1224/chrome-article-publish-extension 1.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.
@@ -0,0 +1,1125 @@
1
+ import { P as PlatformAdapter, a as PublishOptions, A as AdapterRegistryEntry, b as PreprocessConfig } from '../types-BAnNlLpy.js';
2
+ export { C as Category, D as DEFAULT_PREPROCESS_CONFIG, c as Draft, I as ImageProgressCallback, O as OutputFormat } from '../types-BAnNlLpy.js';
3
+ import { P as PlatformMeta, R as RuntimeInterface, A as AuthResult, a as Article, S as SyncResult, c as PublishStatusRef, d as PublishStatusResult, H as HeaderRule } from '../interface-BlLeWXzS.js';
4
+
5
+ /**
6
+ * 适配器基类
7
+ * 提供通用的请求处理和模板解析
8
+ */
9
+ declare abstract class BaseAdapter implements PlatformAdapter {
10
+ abstract readonly meta: PlatformMeta;
11
+ protected runtime: RuntimeInterface;
12
+ protected context: Record<string, unknown>;
13
+ init(runtime: RuntimeInterface): Promise<void>;
14
+ abstract checkAuth(): Promise<AuthResult>;
15
+ abstract publish(article: Article): Promise<SyncResult>;
16
+ /**
17
+ * 发送请求
18
+ */
19
+ protected request<T = unknown>(url: string, options?: RequestInit): Promise<T>;
20
+ /**
21
+ * 带重试的请求
22
+ */
23
+ protected requestWithRetry<T = unknown>(url: string, options?: RequestInit, maxRetries?: number): Promise<T>;
24
+ /**
25
+ * 延迟
26
+ */
27
+ protected delay(ms: number): Promise<void>;
28
+ /**
29
+ * 创建同步结果
30
+ */
31
+ protected createResult(success: boolean, data?: Partial<SyncResult>): SyncResult;
32
+ }
33
+
34
+ /**
35
+ * 代码适配器基类
36
+ *
37
+ * 架构说明:
38
+ * - Content Script (有 DOM): 负责所有 HTML/DOM 处理
39
+ * - 代码块处理 (使用 innerText)
40
+ * - 懒加载图片处理
41
+ * - HTML 转 Markdown
42
+ * - Service Worker (无 DOM): 只负责 API 调用
43
+ * - 接收已处理好的 html 和 markdown
44
+ * - 图片上传 (URL 替换,不需要 DOM)
45
+ * - 调用平台 API
46
+ *
47
+ * 适配器接收的 Article 对象:
48
+ * - article.html: 已预处理的 HTML (代码块已简化,图片已处理)
49
+ * - article.markdown: 已转换的 Markdown
50
+ *
51
+ * 适配器只需:
52
+ * 1. 选择使用 html 还是 markdown
53
+ * 2. 处理图片上传 (如果平台需要)
54
+ * 3. 调用平台 API
55
+ */
56
+
57
+ /**
58
+ * 图片上传结果
59
+ */
60
+ interface ImageUploadResult {
61
+ /** 新的图片 URL */
62
+ url: string;
63
+ /** 额外的 img 属性 */
64
+ attrs?: Record<string, string | number>;
65
+ }
66
+ /**
67
+ * 图片处理选项
68
+ */
69
+ interface ImageProcessOptions {
70
+ /** 跳过匹配这些模式的图片 */
71
+ skipPatterns?: string[];
72
+ /** 进度回调 */
73
+ onProgress?: (current: number, total: number) => void;
74
+ }
75
+ /**
76
+ * 代码适配器基类
77
+ */
78
+ declare abstract class CodeAdapter implements PlatformAdapter {
79
+ abstract readonly meta: PlatformMeta;
80
+ protected runtime: RuntimeInterface;
81
+ /** Header 规则 ID 列表(用于请求拦截) */
82
+ protected headerRuleIds: string[];
83
+ init(runtime: RuntimeInterface): Promise<void>;
84
+ abstract checkAuth(): Promise<AuthResult>;
85
+ abstract publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
86
+ protected getStatusFromUrl(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
87
+ /**
88
+ * 添加 Header 规则
89
+ * @param rule 规则配置
90
+ * @returns 规则 ID
91
+ */
92
+ protected addHeaderRule(rule: Omit<HeaderRule, 'id'>): Promise<string | null>;
93
+ /**
94
+ * 批量添加 Header 规则
95
+ * @param rules 规则配置列表
96
+ */
97
+ protected addHeaderRules(rules: Array<Omit<HeaderRule, 'id'>>): Promise<void>;
98
+ /**
99
+ * 清除所有已添加的 Header 规则
100
+ */
101
+ protected clearHeaderRules(): Promise<void>;
102
+ /**
103
+ * 在 Header 规则保护下执行操作
104
+ * 自动设置规则,执行完成后自动清除
105
+ * @param rules 规则配置列表
106
+ * @param fn 要执行的操作
107
+ */
108
+ protected withHeaderRules<T>(rules: Array<Omit<HeaderRule, 'id'>>, fn: () => Promise<T>): Promise<T>;
109
+ /**
110
+ * GET 请求
111
+ */
112
+ protected get<T = unknown>(url: string, headers?: Record<string, string>): Promise<T>;
113
+ /**
114
+ * POST 请求 (JSON)
115
+ */
116
+ protected postJson<T = unknown>(url: string, data: Record<string, unknown>, headers?: Record<string, string>): Promise<T>;
117
+ /**
118
+ * POST 请求 (Form)
119
+ */
120
+ protected postForm<T = unknown>(url: string, data: Record<string, string>, headers?: Record<string, string>): Promise<T>;
121
+ /**
122
+ * POST 请求 (Multipart)
123
+ */
124
+ protected postMultipart<T = unknown>(url: string, formData: FormData, headers?: Record<string, string>): Promise<T>;
125
+ /**
126
+ * 解析响应
127
+ */
128
+ private parseResponse;
129
+ /**
130
+ * 处理文章图片 (使用正则提取 URL,兼容 Service Worker)
131
+ * 同时支持 HTML 和 Markdown 格式
132
+ * - HTML: <img src="url" alt="text">
133
+ * - Markdown: ![text](url)
134
+ *
135
+ * 注意: 这个方法只做 URL 提取和替换,不涉及 DOM 解析
136
+ */
137
+ protected processImages(content: string, uploadFn: (src: string) => Promise<ImageUploadResult>, options?: ImageProcessOptions): Promise<string>;
138
+ /**
139
+ * 上传图片(子类实现)
140
+ * 默认实现抛出错误
141
+ */
142
+ protected uploadImageByUrl(_src: string): Promise<ImageUploadResult>;
143
+ /**
144
+ * 通过 Blob 上传图片(公开方法,实现 PlatformAdapter 接口)
145
+ * 默认实现:转为 data URI,调用 uploadImageByUrl
146
+ * 子类可以覆盖以提供更优的实现
147
+ */
148
+ uploadImage(file: Blob, _filename?: string): Promise<string>;
149
+ /**
150
+ * Blob 转 data URI
151
+ */
152
+ protected blobToDataUri(blob: Blob): Promise<string>;
153
+ /**
154
+ * data URI 转 Blob
155
+ */
156
+ protected dataUriToBlob(dataUri: string): Promise<Blob>;
157
+ /**
158
+ * 延迟
159
+ */
160
+ protected delay(ms: number): Promise<void>;
161
+ /**
162
+ * 创建同步结果
163
+ */
164
+ protected createResult(success: boolean, data?: Partial<SyncResult>): SyncResult;
165
+ }
166
+
167
+ /**
168
+ * 适配器注册中心
169
+ * 管理所有平台适配器的注册和获取
170
+ */
171
+ declare class AdapterRegistry {
172
+ private adapters;
173
+ private instances;
174
+ private runtime?;
175
+ /**
176
+ * 设置运行时
177
+ */
178
+ setRuntime(runtime: RuntimeInterface): void;
179
+ /**
180
+ * 注册适配器
181
+ */
182
+ register(entry: AdapterRegistryEntry): void;
183
+ /**
184
+ * 批量注册
185
+ */
186
+ registerAll(entries: AdapterRegistryEntry[]): void;
187
+ /**
188
+ * 获取适配器实例
189
+ */
190
+ get(platformId: string): Promise<PlatformAdapter | null>;
191
+ /**
192
+ * 获取所有平台元信息
193
+ */
194
+ getAllMeta(): PlatformMeta[];
195
+ /**
196
+ * 检查平台是否已注册
197
+ */
198
+ has(platformId: string): boolean;
199
+ /**
200
+ * 获取已注册的平台 ID 列表
201
+ */
202
+ getRegisteredIds(): string[];
203
+ /**
204
+ * 清空注册
205
+ */
206
+ clear(): void;
207
+ /**
208
+ * 获取平台的预处理配置
209
+ */
210
+ getPreprocessConfig(platformId: string): PreprocessConfig;
211
+ /**
212
+ * 获取多个平台的预处理配置
213
+ */
214
+ getPreprocessConfigs(platformIds: string[]): Record<string, PreprocessConfig>;
215
+ }
216
+ /**
217
+ * 全局适配器注册中心实例
218
+ */
219
+ declare const adapterRegistry: AdapterRegistry;
220
+ /**
221
+ * 注册适配器的便捷函数
222
+ */
223
+ declare function registerAdapter(entry: AdapterRegistryEntry): void;
224
+ /**
225
+ * 获取适配器的便捷函数
226
+ */
227
+ declare function getAdapter(platformId: string): Promise<PlatformAdapter | null>;
228
+ /**
229
+ * 获取平台的预处理配置
230
+ */
231
+ declare function getPreprocessConfig(platformId: string): PreprocessConfig;
232
+ /**
233
+ * 获取多个平台的预处理配置
234
+ */
235
+ declare function getPreprocessConfigs(platformIds: string[]): Record<string, PreprocessConfig>;
236
+
237
+ /**
238
+ * 豆瓣适配器
239
+ */
240
+
241
+ declare class DoubanAdapter extends CodeAdapter {
242
+ readonly meta: PlatformMeta;
243
+ /** 预处理配置: 豆瓣使用 Markdown 格式 (转换为 Draft.js) */
244
+ readonly preprocessConfig: {
245
+ outputFormat: "markdown";
246
+ };
247
+ private username;
248
+ private avatar;
249
+ private formData;
250
+ private postParams;
251
+ /** 豆瓣 API 需要的 Header 规则 */
252
+ private readonly HEADER_RULES;
253
+ checkAuth(): Promise<AuthResult>;
254
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
255
+ /**
256
+ * 上传图片并返回完整数据
257
+ */
258
+ private uploadImageWithFullData;
259
+ }
260
+
261
+ /**
262
+ * 雪球适配器
263
+ */
264
+
265
+ declare class XueqiuAdapter extends CodeAdapter {
266
+ readonly meta: PlatformMeta;
267
+ /** 预处理配置: 雪球使用 Markdown 格式 */
268
+ readonly preprocessConfig: {
269
+ outputFormat: "markdown";
270
+ removeSpecialTags: boolean;
271
+ removeSpecialTagsWithParent: boolean;
272
+ processCodeBlocks: boolean;
273
+ };
274
+ private currentUser;
275
+ /** 雪球 API 需要的 Header 规则 */
276
+ private readonly HEADER_RULES;
277
+ checkAuth(): Promise<AuthResult>;
278
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
279
+ /**
280
+ * 通过 URL 上传图片
281
+ */
282
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
283
+ }
284
+
285
+ /**
286
+ * 搜狐号适配器
287
+ */
288
+
289
+ declare class SohuAdapter extends CodeAdapter {
290
+ readonly meta: PlatformMeta;
291
+ /** 预处理配置: 搜狐号使用 HTML 格式 */
292
+ readonly preprocessConfig: {
293
+ outputFormat: "html";
294
+ };
295
+ private accountInfo;
296
+ private deviceId;
297
+ private spCm;
298
+ /** 搜狐号 API 需要的 Header 规则 */
299
+ private readonly HEADER_RULES;
300
+ checkAuth(): Promise<AuthResult>;
301
+ /**
302
+ * 获取 sp-cm 值 (从 cookie 或生成)
303
+ */
304
+ private fetchSpCm;
305
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
306
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
307
+ /**
308
+ * 通过 URL 上传图片
309
+ */
310
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
311
+ private findNewsItem;
312
+ private mapNewsStatus;
313
+ private getPublicUrl;
314
+ private resolveTags;
315
+ }
316
+
317
+ /**
318
+ * 人人都是产品经理 (woshipm.com) 适配器
319
+ */
320
+
321
+ declare class WoshipmAdapter extends CodeAdapter {
322
+ readonly meta: PlatformMeta;
323
+ /** 预处理配置: 人人都是产品经理使用 HTML 格式 */
324
+ readonly preprocessConfig: {
325
+ outputFormat: "html";
326
+ removeEmptyLines: boolean;
327
+ };
328
+ private jltoken;
329
+ /** 人人都是产品经理 API 需要的 Header 规则 */
330
+ private readonly HEADER_RULES;
331
+ checkAuth(): Promise<AuthResult>;
332
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
333
+ /**
334
+ * 通过 Blob 上传图片(覆盖基类方法)
335
+ */
336
+ uploadImage(file: Blob, filename?: string): Promise<string>;
337
+ /**
338
+ * 通过 URL 上传图片
339
+ */
340
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
341
+ /**
342
+ * 上传图片 (二进制方式) - 内部使用
343
+ */
344
+ private uploadImageBinaryInternal;
345
+ /**
346
+ * 从 URL 提取文件名
347
+ */
348
+ private getFilenameFromUrl;
349
+ }
350
+
351
+ /**
352
+ * 掘金适配器
353
+ */
354
+
355
+ declare class JuejinAdapter extends CodeAdapter {
356
+ readonly meta: PlatformMeta;
357
+ /** 预处理配置: 掘金使用 Markdown 格式 */
358
+ readonly preprocessConfig: {
359
+ outputFormat: "markdown";
360
+ };
361
+ private cachedCsrfToken;
362
+ private cachedImageXToken;
363
+ private imageXTokenExpiry;
364
+ private uuid;
365
+ /** 掘金 API 需要的 Header 规则 */
366
+ private readonly HEADER_RULES;
367
+ checkAuth(): Promise<AuthResult>;
368
+ /**
369
+ * 获取 CSRF Token (参考 DSL juejin.transform.ts)
370
+ */
371
+ private getCsrfToken;
372
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
373
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
374
+ private resolveCategoryId;
375
+ private fetchCategories;
376
+ private resolveTagIds;
377
+ private fetchTags;
378
+ /**
379
+ * 通过 Blob 上传图片(覆盖基类方法)
380
+ * 需要设置动态请求头规则以支持 MCP 调用
381
+ */
382
+ uploadImage(file: Blob, _filename?: string): Promise<string>;
383
+ /**
384
+ * 通过 URL 上传图片
385
+ * 支持远程 URL 和 data URI,都使用 ImageX 流程
386
+ */
387
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
388
+ /**
389
+ * 获取 ImageX 上传凭证
390
+ */
391
+ private getImageXToken;
392
+ /**
393
+ * 申请图片上传
394
+ */
395
+ private applyImageUpload;
396
+ /**
397
+ * 上传文件到 TOS
398
+ */
399
+ private uploadToTOS;
400
+ /**
401
+ * 提交图片上传
402
+ */
403
+ private commitImageUpload;
404
+ /**
405
+ * 获取图片 URL
406
+ */
407
+ private getImageUrl;
408
+ /**
409
+ * 上传图片 (ImageX 方式) - 内部使用
410
+ */
411
+ private uploadImageBinaryInternal;
412
+ /**
413
+ * 获取分类列表
414
+ */
415
+ getCategories(): Promise<{
416
+ id: string;
417
+ name: string;
418
+ }[]>;
419
+ }
420
+
421
+ /**
422
+ * CSDN 适配器
423
+ */
424
+
425
+ declare class CSDNAdapter extends CodeAdapter {
426
+ readonly meta: PlatformMeta;
427
+ /** 预处理配置: CSDN 使用 Markdown 格式 */
428
+ readonly preprocessConfig: {
429
+ outputFormat: "markdown";
430
+ };
431
+ private userInfo;
432
+ private readonly API_KEY;
433
+ private readonly API_SECRET;
434
+ /** CSDN API 需要的 Header 规则 */
435
+ private readonly HEADER_RULES;
436
+ checkAuth(): Promise<AuthResult>;
437
+ /**
438
+ * 生成 UUID
439
+ */
440
+ private createUuid;
441
+ /**
442
+ * HMAC-SHA256 签名 (使用 Web Crypto API)
443
+ */
444
+ private hmacSha256;
445
+ /**
446
+ * 生成 CSDN API 签名
447
+ * 签名格式: METHOD\nAccept\nContent-MD5\nContent-Type\n\nHeaders\nPath
448
+ */
449
+ private signRequest;
450
+ private canonicalizeResource;
451
+ private resolveTags;
452
+ private postSaveArticle;
453
+ private postSaveArticleFromPage;
454
+ private getCsdnTabId;
455
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
456
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
457
+ private findManagedArticle;
458
+ private mapManagedStatus;
459
+ private getArticleId;
460
+ private extractPostIdFromUrl;
461
+ private resolvePublicUrl;
462
+ /**
463
+ * 通过 Blob 上传图片(覆盖基类方法)
464
+ * 需要设置动态请求头规则以支持 MCP 调用
465
+ */
466
+ uploadImage(file: Blob, _filename?: string): Promise<string>;
467
+ /**
468
+ * 通过 URL 上传图片
469
+ */
470
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
471
+ private resolveCover;
472
+ }
473
+
474
+ /**
475
+ * B站适配器
476
+ */
477
+
478
+ declare class BilibiliAdapter extends CodeAdapter {
479
+ readonly meta: PlatformMeta;
480
+ /** 预处理配置: B站使用 HTML,移除外链 */
481
+ readonly preprocessConfig: {
482
+ outputFormat: "html";
483
+ removeLinks: boolean;
484
+ };
485
+ private userInfo;
486
+ private csrf;
487
+ private wbiKeys;
488
+ /** B站 API 需要的 Header 规则 */
489
+ private readonly HEADER_RULES;
490
+ checkAuth(): Promise<AuthResult>;
491
+ private fetchCsrf;
492
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
493
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
494
+ private readStatusHostMid;
495
+ private findDynamicInSpaceFeed;
496
+ private mapDynamicStatus;
497
+ private createOpusPayload;
498
+ private contentToOpusContent;
499
+ private markdownToOpusContent;
500
+ private markdownTokenToParagraphs;
501
+ private inlineParagraphs;
502
+ private inlineTokensToNodes;
503
+ private htmlInlineToNodes;
504
+ private createListParagraphs;
505
+ private createListItemParagraphs;
506
+ private markdownBlockTokenToInlineNodes;
507
+ private createCodeBlockParagraph;
508
+ private createTableParagraphs;
509
+ private tableToMarkdown;
510
+ private tableCellsToMarkdownRow;
511
+ private inlineTokensToPlainText;
512
+ private createBlockquoteParagraphs;
513
+ private createTextParagraph;
514
+ private createHeadingParagraph;
515
+ private createReferenceParagraph;
516
+ private createLineParagraph;
517
+ private createListParagraph;
518
+ private createImageParagraph;
519
+ private createWordNode;
520
+ private applyWordTypography;
521
+ private getListTheme;
522
+ private createCombineHash;
523
+ private mergeAdjacentNodes;
524
+ private getNodeWords;
525
+ private haveSameWordStyle;
526
+ private htmlToOpusContent;
527
+ private htmlToReadableText;
528
+ private htmlTableToText;
529
+ private htmlInlineToText;
530
+ private stripHtml;
531
+ private createUploadId;
532
+ private ensureWbiKeys;
533
+ private extractWbiKeys;
534
+ private signWbiParams;
535
+ private resolvePostId;
536
+ private resolvePostUrl;
537
+ private extractFilename;
538
+ private extractHtmlAttr;
539
+ private normalizeImageUrl;
540
+ private normalizePublicUrl;
541
+ private createCoverInfo;
542
+ private toOfficialCoverUrl;
543
+ private toNumber;
544
+ private decodeHtmlEntities;
545
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
546
+ }
547
+
548
+ /**
549
+ * 抖音图文适配器
550
+ *
551
+ * 只复现创作者中心公开前端的 HTTP/API 行为:
552
+ * - 通过创作者中心接口检查登录态
553
+ * - 通过 ImageX 上传图片
554
+ * - 通过 aweme/create_v2 直接发布图文
555
+ *
556
+ * 不点击平台 UI,不逆向私有算法。若平台返回二次验证/风控,直接暴露给用户处理。
557
+ */
558
+
559
+ declare class DouyinAdapter extends CodeAdapter {
560
+ readonly meta: PlatformMeta;
561
+ readonly preprocessConfig: {
562
+ outputFormat: "html";
563
+ removeLinks: boolean;
564
+ removeIframes: boolean;
565
+ removeComments: boolean;
566
+ processLazyImages: boolean;
567
+ convertTablesToText: boolean;
568
+ };
569
+ private userInfo;
570
+ private cachedImageXToken;
571
+ private readonly HEADER_RULES;
572
+ checkAuth(): Promise<AuthResult>;
573
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
574
+ uploadImage(file: Blob, _filename?: string): Promise<string>;
575
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
576
+ private resolveStatusId;
577
+ private getStatusUserId;
578
+ private resolveCurrentUserId;
579
+ private fetchItemDetail;
580
+ private fetchItemMget;
581
+ private extractDetailStatusItem;
582
+ private extractMgetStatusItem;
583
+ private toStatusItem;
584
+ private readApiError;
585
+ private mapDouyinItemStatus;
586
+ private readStatusValue;
587
+ private readStatusReason;
588
+ private isPublishedStatus;
589
+ private isReviewingStatus;
590
+ private isRejectedStatus;
591
+ private normalizeStatusValue;
592
+ private resolveDouyinPublicUrl;
593
+ private getStatusFields;
594
+ private formatStatusError;
595
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
596
+ private postCreatorJson;
597
+ private postCreatorJsonFromPage;
598
+ private getCreatorTabId;
599
+ private extractUserData;
600
+ private isSuccessResponse;
601
+ private renderMarkdownImageUrls;
602
+ private buildTextPayload;
603
+ private extractBodyText;
604
+ private extractCaptionText;
605
+ private normalizeText;
606
+ private limitText;
607
+ private buildPublishItem;
608
+ private uploadDouyinImageByUrl;
609
+ private loadImageBlob;
610
+ private uploadDouyinImage;
611
+ private getImageXToken;
612
+ private applyImageUpload;
613
+ private uploadToTOS;
614
+ private commitImageUpload;
615
+ private assertPublishSuccess;
616
+ private looksLikeSecondVerify;
617
+ private detectImageSize;
618
+ private parseJsonText;
619
+ private pickString;
620
+ private stringifyId;
621
+ private decodeHtmlEntities;
622
+ }
623
+
624
+ /**
625
+ * 百家号适配器
626
+ */
627
+
628
+ declare class BaijiahaoAdapter extends CodeAdapter {
629
+ readonly meta: PlatformMeta;
630
+ /** 预处理配置: 百家号使用 HTML 格式 */
631
+ readonly preprocessConfig: {
632
+ outputFormat: "html";
633
+ };
634
+ private userInfo;
635
+ private authToken;
636
+ /** 百家号 API 需要的 Header 规则 */
637
+ private readonly HEADER_RULES;
638
+ checkAuth(): Promise<AuthResult>;
639
+ private fetchAuthToken;
640
+ private parseArticleResponse;
641
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
642
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
643
+ private findArticle;
644
+ private mapArticleStatus;
645
+ private isPublishedItem;
646
+ private resolvePublishedPublicUrl;
647
+ private getPublishedPageTabId;
648
+ private readPublishedPageSnapshot;
649
+ private urlMatchesArticleId;
650
+ private sleep;
651
+ private toPublicUrl;
652
+ private appendCoverParams;
653
+ private prepareContent;
654
+ private replaceLinksWithUrls;
655
+ private replaceTablesWithText;
656
+ private textFromHtml;
657
+ private decodeHtml;
658
+ private escapeHtml;
659
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
660
+ }
661
+
662
+ /**
663
+ * 语雀适配器
664
+ */
665
+
666
+ declare class YuqueAdapter extends CodeAdapter {
667
+ readonly meta: PlatformMeta;
668
+ /** 预处理配置: 语雀使用 Markdown 格式 (转换为 lake) */
669
+ readonly preprocessConfig: {
670
+ outputFormat: "markdown";
671
+ removeSpecialTags: boolean;
672
+ removeSpecialTagsWithParent: boolean;
673
+ processCodeBlocks: boolean;
674
+ };
675
+ private userInfo;
676
+ private bookId;
677
+ private csrfToken;
678
+ private currentPostId;
679
+ /** 语雀 API 需要的 Header 规则 */
680
+ private readonly HEADER_RULES;
681
+ private getCsrfToken;
682
+ checkAuth(): Promise<AuthResult>;
683
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
684
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
685
+ }
686
+
687
+ /**
688
+ * 微信公众号适配器
689
+ */
690
+
691
+ interface WeixinImageUploadResult extends ImageUploadResult {
692
+ fileId?: string;
693
+ width?: number;
694
+ height?: number;
695
+ }
696
+ declare class WeixinAdapter extends CodeAdapter {
697
+ readonly meta: PlatformMeta;
698
+ /** 预处理配置: 微信公众号使用 HTML 格式,移除非微信域名链接,压缩标签间空白避免 ProseMirror 产生空节点 */
699
+ readonly preprocessConfig: {
700
+ outputFormat: "html";
701
+ removeLinks: boolean;
702
+ keepLinkDomains: string[];
703
+ compactHtml: boolean;
704
+ };
705
+ private weixinMeta;
706
+ private authUrl;
707
+ /** 微信公众号 API 需要的 Header 规则 */
708
+ private readonly HEADER_RULES;
709
+ checkAuth(): Promise<AuthResult>;
710
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
711
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
712
+ private createAndPublish;
713
+ private resolveCoverImage;
714
+ private extractFirstImageInfo;
715
+ private getAttr;
716
+ private decodeHtmlAttr;
717
+ private publishDraft;
718
+ private runPublishPreflight;
719
+ private checkSameMaterial;
720
+ private checkCopyright;
721
+ private checkSponsorAd;
722
+ private checkMusic;
723
+ private ensureNotInPublishQueue;
724
+ private loadSafePublishCode;
725
+ private pollSafeUuid;
726
+ private emitPublishEvent;
727
+ private needsSafeScan;
728
+ private parseStrategyInfo;
729
+ private parseJson;
730
+ private masssendActionUrl;
731
+ private getRet;
732
+ private loadPublishData;
733
+ private getPublishReqTime;
734
+ private loadAuthFromUrl;
735
+ private extractWxCommonData;
736
+ private extractCommonDataField;
737
+ private extractTokenFromUrl;
738
+ private loadTokenFromSourceUrl;
739
+ protected uploadImageByUrl(src: string): Promise<WeixinImageUploadResult>;
740
+ private buildCoverCropList;
741
+ private centerCrop;
742
+ private getImageSize;
743
+ private isLatexFormula;
744
+ private processLatex;
745
+ private processContent;
746
+ private inlineSelectorStyle;
747
+ private inlineTagStyle;
748
+ private mergeInlineStyle;
749
+ private escapeStyleAttribute;
750
+ /**
751
+ * 移除外部链接(微信不允许非 mp.weixin.qq.com 域名的链接)
752
+ * 将 <a href="外部链接">文字</a> 转换为 文字
753
+ */
754
+ private stripExternalLinks;
755
+ private formatError;
756
+ private formatStageError;
757
+ private wrapStageError;
758
+ private formatUnexpectedError;
759
+ private randomId;
760
+ }
761
+
762
+ /**
763
+ * 今日头条适配器
764
+ */
765
+
766
+ declare class ToutiaoAdapter extends CodeAdapter {
767
+ readonly meta: PlatformMeta;
768
+ readonly preprocessConfig: {
769
+ outputFormat: "html";
770
+ removeLinks: boolean;
771
+ removeIframes: boolean;
772
+ removeSvgImages: boolean;
773
+ };
774
+ private readonly HEADER_RULES;
775
+ checkAuth(): Promise<AuthResult>;
776
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
777
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
778
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
779
+ private getCsrfToken;
780
+ private publishInPage;
781
+ private ensureToutiaoTab;
782
+ private findManagedArticle;
783
+ private extractList;
784
+ private parseManagedRow;
785
+ private itemMatches;
786
+ private mapManagedStatus;
787
+ private ensureToutiaoManageTab;
788
+ private getVisitedUserId;
789
+ private buildManagedListUrl;
790
+ private resolvePostUrl;
791
+ private prepareContent;
792
+ private wrapImages;
793
+ private toCoverPayload;
794
+ private textLength;
795
+ private getTitle;
796
+ }
797
+
798
+ /**
799
+ * 腾讯号/腾讯内容开放平台适配器
800
+ */
801
+
802
+ interface TencentImageUploadResult extends ImageUploadResult {
803
+ variants?: Record<string, string>;
804
+ }
805
+ declare class TencentAdapter extends CodeAdapter {
806
+ readonly meta: PlatformMeta;
807
+ readonly preprocessConfig: {
808
+ outputFormat: "html";
809
+ };
810
+ private userInfo;
811
+ private readonly HEADER_RULES;
812
+ checkAuth(): Promise<AuthResult>;
813
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
814
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
815
+ protected uploadImageByUrl(src: string): Promise<TencentImageUploadResult>;
816
+ private uploadCoverByUrl;
817
+ private uploadImageFileByUrl;
818
+ private prepareArticleContent;
819
+ private callPublishService;
820
+ private ensureTencentTab;
821
+ private mapArticleStatus;
822
+ private isOk;
823
+ private errorMessage;
824
+ private pickImageUrl;
825
+ private toStringRecord;
826
+ private stringifyId;
827
+ private userId;
828
+ private textFromHtml;
829
+ }
830
+
831
+ /**
832
+ * 51CTO 适配器
833
+ * https://blog.51cto.com
834
+ *
835
+ * 新版图片上传流程:
836
+ * 1. getUploadSign - 获取上传签名
837
+ * 2. getUploadConfig - 获取腾讯云 COS 上传凭证
838
+ * 3. 上传到腾讯云 COS
839
+ */
840
+
841
+ declare class Cto51Adapter extends CodeAdapter {
842
+ meta: PlatformMeta;
843
+ /** 预处理配置: 51CTO 使用 Markdown 格式 */
844
+ readonly preprocessConfig: {
845
+ outputFormat: "markdown";
846
+ };
847
+ private csrf;
848
+ private userPath;
849
+ private category;
850
+ /** 51CTO API 需要的 Header 规则 */
851
+ private readonly HEADER_RULES;
852
+ private readonly STATUS_HEADER_RULES;
853
+ /**
854
+ * 检查登录状态
855
+ */
856
+ checkAuth(): Promise<AuthResult>;
857
+ /**
858
+ * 获取上传签名
859
+ */
860
+ private getUploadSign;
861
+ /**
862
+ * 获取上传配置 (腾讯云 COS 凭证)
863
+ */
864
+ private getUploadConfig;
865
+ /**
866
+ * 上传图片到腾讯云 COS
867
+ */
868
+ private uploadToCOS;
869
+ /**
870
+ * 上传图片
871
+ */
872
+ uploadImageByUrl(url: string): Promise<ImageUploadResult>;
873
+ /**
874
+ * 发布文章
875
+ */
876
+ publish(article: Article): Promise<SyncResult>;
877
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
878
+ private extractPostId;
879
+ private extractPostUrl;
880
+ private resolveTags;
881
+ private resolveCategory;
882
+ private findManagedArticle;
883
+ private listManagedArticles;
884
+ private mapManagedStatus;
885
+ private extractPostIdFromUrl;
886
+ }
887
+
888
+ /**
889
+ * 慕课网手记适配器
890
+ * https://www.imooc.com
891
+ */
892
+
893
+ declare class ImoocAdapter extends CodeAdapter {
894
+ meta: PlatformMeta;
895
+ /** 预处理配置: 慕课网使用 Markdown 格式 */
896
+ readonly preprocessConfig: {
897
+ outputFormat: "markdown";
898
+ };
899
+ /** 慕课网 API 需要的 Header 规则 */
900
+ private readonly HEADER_RULES;
901
+ /**
902
+ * 检查登录状态
903
+ */
904
+ checkAuth(): Promise<AuthResult>;
905
+ /**
906
+ * 上传图片
907
+ */
908
+ uploadImageByUrl(url: string): Promise<ImageUploadResult>;
909
+ /**
910
+ * 发布文章
911
+ */
912
+ publish(article: Article): Promise<SyncResult>;
913
+ }
914
+
915
+ /**
916
+ * 开源中国适配器
917
+ * https://my.oschina.net
918
+ */
919
+
920
+ declare class OschinaAdapter extends CodeAdapter {
921
+ meta: PlatformMeta;
922
+ /** 预处理配置: 开源中国使用 Markdown 格式 */
923
+ readonly preprocessConfig: {
924
+ outputFormat: "markdown";
925
+ };
926
+ private userId;
927
+ /** 开源中国 API 需要的 Header 规则 */
928
+ private readonly HEADER_RULES;
929
+ /**
930
+ * 检查登录状态
931
+ */
932
+ checkAuth(): Promise<AuthResult>;
933
+ /**
934
+ * 上传图片
935
+ */
936
+ uploadImageByUrl(url: string): Promise<ImageUploadResult>;
937
+ private getFilenameFromUrl;
938
+ /**
939
+ * 发布文章
940
+ */
941
+ publish(article: Article): Promise<SyncResult>;
942
+ }
943
+
944
+ /**
945
+ * 思否 (Segmentfault) 适配器
946
+ * https://segmentfault.com
947
+ */
948
+
949
+ declare class SegmentfaultAdapter extends CodeAdapter {
950
+ meta: PlatformMeta;
951
+ /** 预处理配置: 思否使用 Markdown 格式 */
952
+ readonly preprocessConfig: {
953
+ outputFormat: "markdown";
954
+ };
955
+ private sessionToken;
956
+ /** 思否 API 需要的 Header 规则 */
957
+ private readonly HEADER_RULES;
958
+ /**
959
+ * 检查登录状态
960
+ */
961
+ checkAuth(): Promise<AuthResult>;
962
+ /**
963
+ * 获取 session token
964
+ */
965
+ private getSessionToken;
966
+ /**
967
+ * 上传图片
968
+ */
969
+ uploadImageByUrl(url: string): Promise<ImageUploadResult>;
970
+ /**
971
+ * 发布文章
972
+ */
973
+ publish(article: Article): Promise<SyncResult>;
974
+ }
975
+
976
+ /**
977
+ * 博客园 (cnblogs.com) 适配器
978
+ */
979
+
980
+ declare class CnblogsAdapter extends CodeAdapter {
981
+ readonly meta: PlatformMeta;
982
+ /** 预处理配置: 博客园使用 Markdown 格式 */
983
+ readonly preprocessConfig: {
984
+ outputFormat: "markdown";
985
+ };
986
+ private xsrfToken;
987
+ /** 博客园 API 需要的 Header 规则 */
988
+ private readonly HEADER_RULES;
989
+ /**
990
+ * 从 cookie 中获取 XSRF-TOKEN
991
+ */
992
+ private getXsrfToken;
993
+ checkAuth(): Promise<AuthResult>;
994
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
995
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
996
+ private findManagedPost;
997
+ private mapManagedPostStatus;
998
+ private extractPostIdFromUrl;
999
+ private resolvePublicUrl;
1000
+ private resolveTags;
1001
+ /**
1002
+ * 上传图片到博客园
1003
+ * 使用新版 CORS 上传接口
1004
+ */
1005
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
1006
+ }
1007
+
1008
+ /**
1009
+ * Markdown 压缩包下载适配器
1010
+ *
1011
+ * 将文章导出为 Markdown + 图片的 ZIP 压缩包:
1012
+ * - article.md: Markdown 文件
1013
+ * - images/: 图片目录,所有图片使用相对路径引用
1014
+ *
1015
+ * 使用 chrome.downloads API 直接触发下载,避免大文件传递问题
1016
+ */
1017
+
1018
+ declare class ZipDownloadAdapter extends CodeAdapter {
1019
+ readonly meta: PlatformMeta;
1020
+ /**
1021
+ * 本地导出不需要认证
1022
+ */
1023
+ checkAuth(): Promise<AuthResult>;
1024
+ /**
1025
+ * 导出为 ZIP 压缩包
1026
+ */
1027
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
1028
+ /**
1029
+ * 处理 Markdown 中的图片:下载并添加到 ZIP
1030
+ */
1031
+ private processImagesForZip;
1032
+ /**
1033
+ * 获取图片扩展名
1034
+ */
1035
+ private getImageExtension;
1036
+ /**
1037
+ * 清理文件名,移除非法字符
1038
+ */
1039
+ private sanitizeFilename;
1040
+ }
1041
+
1042
+ /**
1043
+ * 东方财富适配器
1044
+ */
1045
+
1046
+ declare class EastmoneyAdapter extends CodeAdapter {
1047
+ readonly meta: PlatformMeta;
1048
+ /** 预处理配置 */
1049
+ readonly preprocessConfig: {
1050
+ outputFormat: "html";
1051
+ removeComments: boolean;
1052
+ removeSpecialTags: boolean;
1053
+ processCodeBlocks: boolean;
1054
+ convertSectionToDiv: boolean;
1055
+ removeEmptyLines: boolean;
1056
+ removeEmptyDivs: boolean;
1057
+ removeNestedEmptyContainers: boolean;
1058
+ unwrapSingleChildContainers: boolean;
1059
+ unwrapNestedFigures: boolean;
1060
+ removeTrailingBr: boolean;
1061
+ removeDataAttributes: boolean;
1062
+ removeSrcset: boolean;
1063
+ removeSizes: boolean;
1064
+ compactHtml: boolean;
1065
+ };
1066
+ private ctoken;
1067
+ private utoken;
1068
+ private deviceId;
1069
+ /** 获取或生成持久化 deviceId(32位大写 hex) */
1070
+ private getDeviceId;
1071
+ /** API Header 规则 */
1072
+ private readonly HEADER_RULES;
1073
+ checkAuth(): Promise<AuthResult>;
1074
+ /** 从 cookie 读取 token */
1075
+ private fetchToken;
1076
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
1077
+ /** 构造 API 参数 */
1078
+ private buildParm;
1079
+ /** 调用草稿 API */
1080
+ private callDraftApi;
1081
+ private createDraft;
1082
+ private updateDraft;
1083
+ /** URL 上传图片 */
1084
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
1085
+ /** 上传图片 Blob */
1086
+ private uploadImageBlob;
1087
+ }
1088
+
1089
+ /**
1090
+ * 网易号适配器
1091
+ */
1092
+
1093
+ declare class NeteaseAdapter extends CodeAdapter {
1094
+ readonly meta: PlatformMeta;
1095
+ readonly preprocessConfig: {
1096
+ outputFormat: "html";
1097
+ convertTablesToText: boolean;
1098
+ };
1099
+ private accountInfo;
1100
+ private readonly HEADER_RULES;
1101
+ checkAuth(): Promise<AuthResult>;
1102
+ publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
1103
+ getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
1104
+ protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
1105
+ private fetchPostPageInfo;
1106
+ private assertPublishAllowed;
1107
+ private formatApiError;
1108
+ private prepareContent;
1109
+ private replaceLinksWithUrls;
1110
+ private replaceTablesWithText;
1111
+ private replaceCodeBlocksWithText;
1112
+ private textFromHtml;
1113
+ private decodeHtml;
1114
+ private escapeHtml;
1115
+ private extractPostId;
1116
+ private stringifyId;
1117
+ private extractPostIdFromUrl;
1118
+ private findManagedArticle;
1119
+ private findManagedArticleByTitle;
1120
+ private listManagedArticles;
1121
+ private mapManagedStatus;
1122
+ private isPublicArticleAvailable;
1123
+ }
1124
+
1125
+ export { AdapterRegistryEntry, BaijiahaoAdapter, BaseAdapter, BilibiliAdapter, CSDNAdapter, CnblogsAdapter, CodeAdapter, Cto51Adapter, DoubanAdapter, DouyinAdapter, EastmoneyAdapter, type ImageProcessOptions, type ImageUploadResult, ImoocAdapter, JuejinAdapter, NeteaseAdapter, OschinaAdapter, PlatformAdapter, PreprocessConfig, PublishOptions, SegmentfaultAdapter, SohuAdapter, TencentAdapter, ToutiaoAdapter, WeixinAdapter, WoshipmAdapter, XueqiuAdapter, YuqueAdapter, ZipDownloadAdapter, adapterRegistry, getAdapter, getPreprocessConfig, getPreprocessConfigs, registerAdapter };