@skrillex1224/chrome-article-publish-extension 1.0.1 → 1.0.2
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/README.md +40 -2
- package/dist/adapters/index.d.ts +42 -11
- package/dist/adapters/index.js +121 -7
- package/dist/adapters/index.js.map +1 -1
- package/dist/{chunk-UO6CDRC5.js → chunk-GPHPFYRZ.js} +1 -77
- package/dist/chunk-GPHPFYRZ.js.map +1 -0
- package/dist/{chunk-NKSXZF7J.js → chunk-LUN2JBGI.js} +1365 -288
- package/dist/chunk-LUN2JBGI.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.js +7 -5
- package/dist/index.js.map +1 -1
- package/dist/{interface-BlLeWXzS.d.ts → interface-DRp7JR58.d.ts} +10 -21
- package/dist/runtime/index.d.ts +3 -6
- package/dist/runtime/index.js +1 -1
- package/dist/{types-BAnNlLpy.d.ts → types-DllMbt54.d.ts} +1 -1
- package/package.json +12 -3
- package/dist/chunk-GATX26VC.js +0 -123
- package/dist/chunk-GATX26VC.js.map +0 -1
- package/dist/chunk-JFXS3MPU.js +0 -602
- package/dist/chunk-JFXS3MPU.js.map +0 -1
- package/dist/chunk-NKSXZF7J.js.map +0 -1
- package/dist/chunk-UO6CDRC5.js.map +0 -1
- package/dist/converter/index.d.ts +0 -2
- package/dist/converter/index.html +0 -10
- package/dist/converter/index.js +0 -432
- package/dist/converter/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -11,13 +11,39 @@ Direct article publishing adapters for Chrome extensions. The package runs in a
|
|
|
11
11
|
|
|
12
12
|
The host extension owns UI, local task state, retry buttons, storage, and polling cadence.
|
|
13
13
|
|
|
14
|
+
## Included Chrome Extension UI
|
|
15
|
+
|
|
16
|
+
This repository also includes a standalone host extension UI under `extension-app/`.
|
|
17
|
+
|
|
18
|
+
Boundary:
|
|
19
|
+
|
|
20
|
+
- `src/` is the reusable npm kernel.
|
|
21
|
+
- `extension-app/` is only a Chrome extension UI that imports the kernel package at build time.
|
|
22
|
+
- The extension app does not import adapter internals.
|
|
23
|
+
- The extension app never loads executable adapter code from a CDN.
|
|
24
|
+
|
|
25
|
+
Build the side panel extension:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm build:extension-app
|
|
29
|
+
pnpm zip:extension-app
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The zip is generated as:
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
chrome-article-publish-extension-ui-1.0.2.zip
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The UI uses Chrome Side Panel as the primary entry. Article creation happens in a full extension tab, while the side panel handles saved article selection, platform auth checks, publish tasks, retries, and status polling.
|
|
39
|
+
|
|
14
40
|
## Supported Platforms
|
|
15
41
|
|
|
16
42
|
| id | Platform | Notes |
|
|
17
43
|
|---|---|---|
|
|
18
44
|
| `bilibili` | Bilibili Opus | Supports cover and structured Opus payload. Tables degrade to readable text. |
|
|
19
45
|
| `weixin` | WeChat Official Account | Supports cover, body images, summary, and security QR events. |
|
|
20
|
-
| `douyin` | Douyin
|
|
46
|
+
| `douyin` | Douyin | Requires exactly one of `article.images` URL list for image-text notes or `article.video.url` for video posts. |
|
|
21
47
|
| `cnblogs` | Cnblogs | Supports article publish, tags, cover metadata. |
|
|
22
48
|
| `juejin` | Juejin | Supports cover and real tag ids when the account is eligible. |
|
|
23
49
|
| `baijiahao` | Baijiahao | Resolves public URLs from official page data after management status says published. |
|
|
@@ -148,10 +174,22 @@ type PublishArticleInput = {
|
|
|
148
174
|
cover?: string
|
|
149
175
|
tags?: string[]
|
|
150
176
|
category?: string
|
|
177
|
+
images?: Array<{ url: string }>
|
|
178
|
+
video?: {
|
|
179
|
+
url: string
|
|
180
|
+
filename?: string
|
|
181
|
+
mimeType?: string
|
|
182
|
+
}
|
|
151
183
|
source?: { url: string; platform: string }
|
|
152
184
|
}
|
|
153
185
|
```
|
|
154
186
|
|
|
187
|
+
For Douyin image-text, pass `platform: 'douyin'` and `article.images: [{ url }]`. The adapter uploads those image URLs through ImageX and publishes a note. Douyin image-text no longer converts Markdown into image cards.
|
|
188
|
+
|
|
189
|
+
For Douyin video, pass `platform: 'douyin'` and `article.video.url`. The adapter runs inside a logged-in Chrome extension context, uses the official Creator page uploader for the video asset, and then calls the Creator publish API. If `article.cover` is present, the adapter uploads it as the video cover; otherwise it uses the platform-generated poster from the uploaded video.
|
|
190
|
+
|
|
191
|
+
Douyin media inputs are URL-only and mutually exclusive: pass either `article.images[].url` or `article.video.url`, not both. `article.images[].url`, `article.video.url`, and `article.cover` must be `http://` or `https://` URLs.
|
|
192
|
+
|
|
155
193
|
`publish()` returns only:
|
|
156
194
|
|
|
157
195
|
```ts
|
|
@@ -202,7 +240,7 @@ const runtime = createExtensionRuntime({
|
|
|
202
240
|
})
|
|
203
241
|
```
|
|
204
242
|
|
|
205
|
-
`timeout` controls extension `fetch()` timeout in milliseconds. Keep it higher for platforms that upload images or
|
|
243
|
+
`timeout` controls extension `fetch()` timeout in milliseconds. Keep it higher for platforms that upload images or videos.
|
|
206
244
|
|
|
207
245
|
## Testing In A Host Extension
|
|
208
246
|
|
package/dist/adapters/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { P as PlatformAdapter, a as PublishOptions, A as AdapterRegistryEntry, b as PreprocessConfig } from '../types-
|
|
2
|
-
export { C as Category, D as DEFAULT_PREPROCESS_CONFIG, c as Draft, I as ImageProgressCallback, O as OutputFormat } from '../types-
|
|
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-
|
|
1
|
+
import { P as PlatformAdapter, a as PublishOptions, A as AdapterRegistryEntry, b as PreprocessConfig } from '../types-DllMbt54.js';
|
|
2
|
+
export { C as Category, D as DEFAULT_PREPROCESS_CONFIG, c as Draft, I as ImageProgressCallback, O as OutputFormat } from '../types-DllMbt54.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-DRp7JR58.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* 适配器基类
|
|
@@ -63,6 +63,11 @@ interface ImageUploadResult {
|
|
|
63
63
|
/** 额外的 img 属性 */
|
|
64
64
|
attrs?: Record<string, string | number>;
|
|
65
65
|
}
|
|
66
|
+
interface NormalizedImageFile {
|
|
67
|
+
file: File;
|
|
68
|
+
mimeType: string;
|
|
69
|
+
ext: string;
|
|
70
|
+
}
|
|
66
71
|
/**
|
|
67
72
|
* 图片处理选项
|
|
68
73
|
*/
|
|
@@ -154,6 +159,10 @@ declare abstract class CodeAdapter implements PlatformAdapter {
|
|
|
154
159
|
* data URI 转 Blob
|
|
155
160
|
*/
|
|
156
161
|
protected dataUriToBlob(dataUri: string): Promise<Blob>;
|
|
162
|
+
protected normalizeImageFile(blob: Blob, src: string, filenameBase?: string): Promise<NormalizedImageFile>;
|
|
163
|
+
private detectImageType;
|
|
164
|
+
private imageTypeFromUrl;
|
|
165
|
+
private imageTypeFromMime;
|
|
157
166
|
/**
|
|
158
167
|
* 延迟
|
|
159
168
|
*/
|
|
@@ -449,6 +458,7 @@ declare class CSDNAdapter extends CodeAdapter {
|
|
|
449
458
|
private signRequest;
|
|
450
459
|
private canonicalizeResource;
|
|
451
460
|
private resolveTags;
|
|
461
|
+
private preserveTaskListMarkers;
|
|
452
462
|
private postSaveArticle;
|
|
453
463
|
private postSaveArticleFromPage;
|
|
454
464
|
private getCsdnTabId;
|
|
@@ -506,9 +516,10 @@ declare class BilibiliAdapter extends CodeAdapter {
|
|
|
506
516
|
private markdownBlockTokenToInlineNodes;
|
|
507
517
|
private createCodeBlockParagraph;
|
|
508
518
|
private createTableParagraphs;
|
|
509
|
-
private
|
|
510
|
-
private
|
|
519
|
+
private tableToTextRows;
|
|
520
|
+
private tableCellsToText;
|
|
511
521
|
private inlineTokensToPlainText;
|
|
522
|
+
private linkTokenToText;
|
|
512
523
|
private createBlockquoteParagraphs;
|
|
513
524
|
private createTextParagraph;
|
|
514
525
|
private createHeadingParagraph;
|
|
@@ -546,12 +557,13 @@ declare class BilibiliAdapter extends CodeAdapter {
|
|
|
546
557
|
}
|
|
547
558
|
|
|
548
559
|
/**
|
|
549
|
-
*
|
|
560
|
+
* 抖音适配器
|
|
550
561
|
*
|
|
551
562
|
* 只复现创作者中心公开前端的 HTTP/API 行为:
|
|
552
563
|
* - 通过创作者中心接口检查登录态
|
|
553
564
|
* - 通过 ImageX 上传图片
|
|
554
|
-
* -
|
|
565
|
+
* - 图文:上传 caller 提供的 images URL 后通过 aweme/create_v2 直接发布
|
|
566
|
+
* - 视频:复用创作者中心官方 uploader 上传资产后通过 aweme/create 直接发布
|
|
555
567
|
*
|
|
556
568
|
* 不点击平台 UI,不逆向私有算法。若平台返回二次验证/风控,直接暴露给用户处理。
|
|
557
569
|
*/
|
|
@@ -572,6 +584,8 @@ declare class DouyinAdapter extends CodeAdapter {
|
|
|
572
584
|
checkAuth(): Promise<AuthResult>;
|
|
573
585
|
publish(article: Article, options?: PublishOptions): Promise<SyncResult>;
|
|
574
586
|
uploadImage(file: Blob, _filename?: string): Promise<string>;
|
|
587
|
+
private createPublishContext;
|
|
588
|
+
private publishVideo;
|
|
575
589
|
getStatus(statusRef: PublishStatusRef): Promise<PublishStatusResult>;
|
|
576
590
|
private resolveStatusId;
|
|
577
591
|
private getStatusUserId;
|
|
@@ -590,21 +604,27 @@ declare class DouyinAdapter extends CodeAdapter {
|
|
|
590
604
|
private isRejectedStatus;
|
|
591
605
|
private normalizeStatusValue;
|
|
592
606
|
private resolveDouyinPublicUrl;
|
|
607
|
+
private isVideoStatusRef;
|
|
608
|
+
private statusKindLabel;
|
|
593
609
|
private getStatusFields;
|
|
594
610
|
private formatStatusError;
|
|
595
611
|
protected uploadImageByUrl(src: string): Promise<ImageUploadResult>;
|
|
596
612
|
private postCreatorJson;
|
|
597
613
|
private postCreatorJsonFromPage;
|
|
614
|
+
private getCreatorJsonFromPage;
|
|
615
|
+
private postCreatorForm;
|
|
616
|
+
private postCreatorFormFromPage;
|
|
598
617
|
private getCreatorTabId;
|
|
599
618
|
private extractUserData;
|
|
600
619
|
private isSuccessResponse;
|
|
601
|
-
private renderMarkdownImageUrls;
|
|
602
620
|
private buildTextPayload;
|
|
603
621
|
private extractBodyText;
|
|
604
|
-
private extractCaptionText;
|
|
605
622
|
private normalizeText;
|
|
606
623
|
private limitText;
|
|
607
624
|
private buildPublishItem;
|
|
625
|
+
private uploadDouyinVideo;
|
|
626
|
+
private waitForVideoTransend;
|
|
627
|
+
private buildVideoPublishPayload;
|
|
608
628
|
private uploadDouyinImageByUrl;
|
|
609
629
|
private loadImageBlob;
|
|
610
630
|
private uploadDouyinImage;
|
|
@@ -613,10 +633,12 @@ declare class DouyinAdapter extends CodeAdapter {
|
|
|
613
633
|
private uploadToTOS;
|
|
614
634
|
private commitImageUpload;
|
|
615
635
|
private assertPublishSuccess;
|
|
636
|
+
private extractPublishPostId;
|
|
616
637
|
private looksLikeSecondVerify;
|
|
617
638
|
private detectImageSize;
|
|
618
639
|
private parseJsonText;
|
|
619
640
|
private pickString;
|
|
641
|
+
private createCreationId;
|
|
620
642
|
private stringifyId;
|
|
621
643
|
private decodeHtmlEntities;
|
|
622
644
|
}
|
|
@@ -653,6 +675,9 @@ declare class BaijiahaoAdapter extends CodeAdapter {
|
|
|
653
675
|
private prepareContent;
|
|
654
676
|
private replaceLinksWithUrls;
|
|
655
677
|
private replaceTablesWithText;
|
|
678
|
+
private replaceCodeBlocksWithText;
|
|
679
|
+
private replaceHorizontalRules;
|
|
680
|
+
private preserveTaskListMarkers;
|
|
656
681
|
private textFromHtml;
|
|
657
682
|
private decodeHtml;
|
|
658
683
|
private escapeHtml;
|
|
@@ -749,9 +774,10 @@ declare class WeixinAdapter extends CodeAdapter {
|
|
|
749
774
|
private escapeStyleAttribute;
|
|
750
775
|
/**
|
|
751
776
|
* 移除外部链接(微信不允许非 mp.weixin.qq.com 域名的链接)
|
|
752
|
-
* 将 <a href="外部链接">文字</a> 转换为
|
|
777
|
+
* 将 <a href="外部链接">文字</a> 转换为 文字(URL),避免公开页丢失链接信息
|
|
753
778
|
*/
|
|
754
779
|
private stripExternalLinks;
|
|
780
|
+
private stripHtml;
|
|
755
781
|
private formatError;
|
|
756
782
|
private formatStageError;
|
|
757
783
|
private wrapStageError;
|
|
@@ -788,7 +814,9 @@ declare class ToutiaoAdapter extends CodeAdapter {
|
|
|
788
814
|
private getVisitedUserId;
|
|
789
815
|
private buildManagedListUrl;
|
|
790
816
|
private resolvePostUrl;
|
|
817
|
+
private resolvePublicArticleUrl;
|
|
791
818
|
private prepareContent;
|
|
819
|
+
private textFromHtml;
|
|
792
820
|
private wrapImages;
|
|
793
821
|
private toCoverPayload;
|
|
794
822
|
private textLength;
|
|
@@ -818,6 +846,9 @@ declare class TencentAdapter extends CodeAdapter {
|
|
|
818
846
|
private prepareArticleContent;
|
|
819
847
|
private callPublishService;
|
|
820
848
|
private ensureTencentTab;
|
|
849
|
+
private buildArticleListUrl;
|
|
850
|
+
private hasListData;
|
|
851
|
+
private extractUserInfo;
|
|
821
852
|
private mapArticleStatus;
|
|
822
853
|
private isOk;
|
|
823
854
|
private errorMessage;
|
|
@@ -1122,4 +1153,4 @@ declare class NeteaseAdapter extends CodeAdapter {
|
|
|
1122
1153
|
private isPublicArticleAvailable;
|
|
1123
1154
|
}
|
|
1124
1155
|
|
|
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 };
|
|
1156
|
+
export { AdapterRegistryEntry, BaijiahaoAdapter, BaseAdapter, BilibiliAdapter, CSDNAdapter, CnblogsAdapter, CodeAdapter, Cto51Adapter, DoubanAdapter, DouyinAdapter, EastmoneyAdapter, type ImageProcessOptions, type ImageUploadResult, ImoocAdapter, JuejinAdapter, NeteaseAdapter, type NormalizedImageFile, OschinaAdapter, PlatformAdapter, PreprocessConfig, PublishOptions, SegmentfaultAdapter, SohuAdapter, TencentAdapter, ToutiaoAdapter, WeixinAdapter, WoshipmAdapter, XueqiuAdapter, YuqueAdapter, ZipDownloadAdapter, adapterRegistry, getAdapter, getPreprocessConfig, getPreprocessConfigs, registerAdapter };
|
package/dist/adapters/index.js
CHANGED
|
@@ -11,16 +11,11 @@ import {
|
|
|
11
11
|
SohuAdapter,
|
|
12
12
|
TencentAdapter,
|
|
13
13
|
ToutiaoAdapter,
|
|
14
|
-
WeixinAdapter
|
|
15
|
-
} from "../chunk-NKSXZF7J.js";
|
|
16
|
-
import {
|
|
17
|
-
markdownToDraft
|
|
18
|
-
} from "../chunk-GATX26VC.js";
|
|
19
|
-
import {
|
|
14
|
+
WeixinAdapter,
|
|
20
15
|
createLogger,
|
|
21
16
|
htmlToMarkdown,
|
|
22
17
|
parseMarkdownImages
|
|
23
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-LUN2JBGI.js";
|
|
24
19
|
|
|
25
20
|
// src/adapters/types.ts
|
|
26
21
|
var DEFAULT_PREPROCESS_CONFIG = {
|
|
@@ -203,6 +198,125 @@ function getPreprocessConfigs(platformIds) {
|
|
|
203
198
|
return adapterRegistry.getPreprocessConfigs(platformIds);
|
|
204
199
|
}
|
|
205
200
|
|
|
201
|
+
// src/lib/markdown-to-draft.ts
|
|
202
|
+
import { markdownToDraft as mdToDraft } from "markdown-draft-js";
|
|
203
|
+
var ImageRegexp = /^!\[([^\]]*)]\s*\(([^)"]+)( "([^)"]+)")?\)/;
|
|
204
|
+
var imageBlockPlugin = (remarkable) => {
|
|
205
|
+
remarkable.block.ruler.before("paragraph", "image", (state, startLine, endLine, silent) => {
|
|
206
|
+
const pos = state.bMarks[startLine] + state.tShift[startLine];
|
|
207
|
+
const max = state.eMarks[startLine];
|
|
208
|
+
if (pos >= max) return false;
|
|
209
|
+
if (!state.src) return false;
|
|
210
|
+
if (state.src[pos] !== "!") return false;
|
|
211
|
+
const match = ImageRegexp.exec(state.src.slice(pos));
|
|
212
|
+
if (!match) return false;
|
|
213
|
+
if (!silent) {
|
|
214
|
+
state.tokens.push({
|
|
215
|
+
type: "image_open",
|
|
216
|
+
src: match[2],
|
|
217
|
+
alt: match[1],
|
|
218
|
+
lines: [startLine, state.line],
|
|
219
|
+
level: state.level
|
|
220
|
+
});
|
|
221
|
+
state.tokens.push({
|
|
222
|
+
type: "image_close",
|
|
223
|
+
level: state.level
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
state.line = startLine + 1;
|
|
227
|
+
return true;
|
|
228
|
+
});
|
|
229
|
+
};
|
|
230
|
+
function markdownToDraft(markdown, imageDataMap = /* @__PURE__ */ new Map()) {
|
|
231
|
+
const processedMarkdown = markdown.split("\n").map((line) => {
|
|
232
|
+
const imageBlocks = line.split("![]");
|
|
233
|
+
return imageBlocks.length > 1 ? imageBlocks.join("\n![]") : line;
|
|
234
|
+
}).join("\n");
|
|
235
|
+
let keyCounter = 0;
|
|
236
|
+
const generateUniqueKey = () => keyCounter++;
|
|
237
|
+
const draftState = mdToDraft(processedMarkdown, {
|
|
238
|
+
remarkablePlugins: [imageBlockPlugin],
|
|
239
|
+
blockTypes: {
|
|
240
|
+
image_open: function(item) {
|
|
241
|
+
const key = generateUniqueKey();
|
|
242
|
+
const blockEntities = {};
|
|
243
|
+
const sourcePair = item.src ? item.src.split("?#") : ["", ""];
|
|
244
|
+
const rawSrc = sourcePair[0];
|
|
245
|
+
const sourceId = sourcePair[1] || "";
|
|
246
|
+
const imgData = imageDataMap.get(item.src) || imageDataMap.get(rawSrc);
|
|
247
|
+
const imageTemplate = imgData ? {
|
|
248
|
+
id: imgData.id,
|
|
249
|
+
src: imgData.url,
|
|
250
|
+
thumb: imgData.thumb,
|
|
251
|
+
url: imgData.url,
|
|
252
|
+
width: imgData.width,
|
|
253
|
+
height: imgData.height,
|
|
254
|
+
file_name: imgData.file_name,
|
|
255
|
+
file_size: imgData.file_size
|
|
256
|
+
} : {
|
|
257
|
+
id: sourceId,
|
|
258
|
+
src: rawSrc,
|
|
259
|
+
thumb: rawSrc,
|
|
260
|
+
url: rawSrc
|
|
261
|
+
};
|
|
262
|
+
blockEntities[key] = {
|
|
263
|
+
type: "IMAGE",
|
|
264
|
+
mutability: "IMMUTABLE",
|
|
265
|
+
data: imageTemplate
|
|
266
|
+
};
|
|
267
|
+
return {
|
|
268
|
+
type: "atomic",
|
|
269
|
+
blockEntities,
|
|
270
|
+
inlineStyleRanges: [],
|
|
271
|
+
entityRanges: [{ offset: 0, length: 1, key }],
|
|
272
|
+
text: " "
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
blockEntities: {
|
|
277
|
+
image: function(item) {
|
|
278
|
+
const sourcePair = item.src ? item.src.split("?#") : ["", ""];
|
|
279
|
+
const rawSrc = sourcePair[0];
|
|
280
|
+
const sourceId = sourcePair[1] || "";
|
|
281
|
+
const imgData = imageDataMap.get(item.src) || imageDataMap.get(rawSrc);
|
|
282
|
+
if (imgData) {
|
|
283
|
+
return {
|
|
284
|
+
type: "IMAGE",
|
|
285
|
+
mutability: "IMMUTABLE",
|
|
286
|
+
data: {
|
|
287
|
+
id: imgData.id,
|
|
288
|
+
src: imgData.url,
|
|
289
|
+
thumb: imgData.thumb,
|
|
290
|
+
url: imgData.url,
|
|
291
|
+
width: imgData.width,
|
|
292
|
+
height: imgData.height
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
type: "IMAGE",
|
|
298
|
+
mutability: "IMMUTABLE",
|
|
299
|
+
data: {
|
|
300
|
+
id: sourceId,
|
|
301
|
+
src: rawSrc,
|
|
302
|
+
thumb: rawSrc,
|
|
303
|
+
url: rawSrc
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
if (draftState.blocks) {
|
|
310
|
+
for (const block of draftState.blocks) {
|
|
311
|
+
if (block.blockEntities) {
|
|
312
|
+
Object.assign(draftState.entityMap, block.blockEntities);
|
|
313
|
+
delete block.blockEntities;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return JSON.stringify(draftState);
|
|
318
|
+
}
|
|
319
|
+
|
|
206
320
|
// src/adapters/platforms/douban.ts
|
|
207
321
|
var logger = createLogger("Douban");
|
|
208
322
|
var DoubanAdapter = class extends CodeAdapter {
|