@cogenta/import 0.1.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.
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/wordpress/collections.d.ts +232 -0
- package/dist/wordpress/collections.d.ts.map +1 -0
- package/dist/wordpress/collections.js +133 -0
- package/dist/wordpress/collections.js.map +1 -0
- package/dist/wordpress/content-convert.d.ts +50 -0
- package/dist/wordpress/content-convert.d.ts.map +1 -0
- package/dist/wordpress/content-convert.js +222 -0
- package/dist/wordpress/content-convert.js.map +1 -0
- package/dist/wordpress/gutenberg.d.ts +27 -0
- package/dist/wordpress/gutenberg.d.ts.map +1 -0
- package/dist/wordpress/gutenberg.js +83 -0
- package/dist/wordpress/gutenberg.js.map +1 -0
- package/dist/wordpress/html-to-richtext.d.ts +23 -0
- package/dist/wordpress/html-to-richtext.d.ts.map +1 -0
- package/dist/wordpress/html-to-richtext.js +209 -0
- package/dist/wordpress/html-to-richtext.js.map +1 -0
- package/dist/wordpress/import.d.ts +19 -0
- package/dist/wordpress/import.d.ts.map +1 -0
- package/dist/wordpress/import.js +241 -0
- package/dist/wordpress/import.js.map +1 -0
- package/dist/wordpress/media.d.ts +27 -0
- package/dist/wordpress/media.d.ts.map +1 -0
- package/dist/wordpress/media.js +68 -0
- package/dist/wordpress/media.js.map +1 -0
- package/dist/wordpress/parse.d.ts +12 -0
- package/dist/wordpress/parse.d.ts.map +1 -0
- package/dist/wordpress/parse.js +95 -0
- package/dist/wordpress/parse.js.map +1 -0
- package/dist/wordpress/report.d.ts +45 -0
- package/dist/wordpress/report.d.ts.map +1 -0
- package/dist/wordpress/report.js +41 -0
- package/dist/wordpress/report.js.map +1 -0
- package/dist/wordpress/types.d.ts +66 -0
- package/dist/wordpress/types.d.ts.map +1 -0
- package/dist/wordpress/types.js +10 -0
- package/dist/wordpress/types.js.map +1 -0
- package/dist/wordpress/xml.d.ts +33 -0
- package/dist/wordpress/xml.d.ts.map +1 -0
- package/dist/wordpress/xml.js +262 -0
- package/dist/wordpress/xml.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { createUserStore, ensureAuthTables } from '@cogenta/auth';
|
|
2
|
+
import { createDatabaseMediaStore } from '@cogenta/core';
|
|
3
|
+
import { buildPath, createContentStore, createRedirectStore, createSchemaTables, } from '@cogenta/schema';
|
|
4
|
+
import { WORDPRESS_IMPORT_COLLECTIONS, wpCategory, wpComment, wpPage, wpPost, wpTag, } from './collections.js';
|
|
5
|
+
import { convertContent, mediaUrlsOf, resolveMediaReferences, } from './content-convert.js';
|
|
6
|
+
import { downloadAndStoreMedia } from './media.js';
|
|
7
|
+
import { parseWxr } from './parse.js';
|
|
8
|
+
import { emptyReport } from './report.js';
|
|
9
|
+
const APPROVED = '1';
|
|
10
|
+
const IMPORTABLE_STATUSES = new Set(['publish', 'draft', 'pending', 'private', 'future']);
|
|
11
|
+
function wpDateToIso(wpDate) {
|
|
12
|
+
if (wpDate.length === 0 || wpDate === '0000-00-00 00:00:00')
|
|
13
|
+
return null;
|
|
14
|
+
const iso = wpDate.includes('T') ? wpDate : `${wpDate.replace(' ', 'T')}Z`;
|
|
15
|
+
const date = new Date(iso);
|
|
16
|
+
return Number.isNaN(date.getTime()) ? null : date.toISOString();
|
|
17
|
+
}
|
|
18
|
+
function toContentBlocks(blocks) {
|
|
19
|
+
return blocks.map((block) => {
|
|
20
|
+
const { _key, _type, ...data } = block;
|
|
21
|
+
return { key: _key, type: _type, data: data };
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
function relativePathOf(link, baseUrl) {
|
|
25
|
+
try {
|
|
26
|
+
const url = new URL(link, baseUrl || link);
|
|
27
|
+
return url.pathname;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Imports a WordPress "Export All Content" WXR file into Cogenta.
|
|
35
|
+
*
|
|
36
|
+
* Every step degrades to a report entry rather than aborting the import: a
|
|
37
|
+
* dead media URL, an unmappable Gutenberg block, an author with no email, a
|
|
38
|
+
* redirect that would loop — none of them stop the run, because the lot's own
|
|
39
|
+
* framing is explicit that a reported partial loss beats a silent one. The
|
|
40
|
+
* only thing that stops the run is a document `parseWxr` cannot read at all.
|
|
41
|
+
*/
|
|
42
|
+
export async function importWordPress(xml, options) {
|
|
43
|
+
const { db, storage } = options;
|
|
44
|
+
const parsed = parseWxr(xml);
|
|
45
|
+
const acc = emptyReport();
|
|
46
|
+
await createSchemaTables(db, WORDPRESS_IMPORT_COLLECTIONS);
|
|
47
|
+
await ensureAuthTables(db);
|
|
48
|
+
const users = createUserStore(db);
|
|
49
|
+
const redirects = createRedirectStore({ db });
|
|
50
|
+
await redirects.ensureTable();
|
|
51
|
+
const mediaStore = createDatabaseMediaStore({ db });
|
|
52
|
+
const categoryStore = createContentStore({ db, collection: wpCategory });
|
|
53
|
+
const tagStore = createContentStore({ db, collection: wpTag });
|
|
54
|
+
const postStore = createContentStore({ db, collection: wpPost });
|
|
55
|
+
const pageStore = createContentStore({ db, collection: wpPage });
|
|
56
|
+
const commentStore = createContentStore({ db, collection: wpComment });
|
|
57
|
+
// ---- Authors -------------------------------------------------------
|
|
58
|
+
const loginToUserId = new Map();
|
|
59
|
+
for (const author of parsed.authors) {
|
|
60
|
+
const email = author.email.trim().length > 0
|
|
61
|
+
? author.email.trim()
|
|
62
|
+
: `${author.login || 'author'}@imported.invalid`;
|
|
63
|
+
if (author.email.trim().length === 0) {
|
|
64
|
+
acc.warnings.push(`Author "${author.login}" had no email in the export; used a placeholder (${email}).`);
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
const user = await users.create({ email, roles: ['author'] });
|
|
68
|
+
loginToUserId.set(author.login, user.id);
|
|
69
|
+
acc.imported.authors += 1;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// AUTH_USER_EXISTS: a previous import (or the site itself) already has
|
|
73
|
+
// this email — reuse that account rather than failing the whole run.
|
|
74
|
+
const existing = await users.byEmail(email);
|
|
75
|
+
if (existing !== null)
|
|
76
|
+
loginToUserId.set(author.login, existing.id);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// ---- Categories & tags ----------------------------------------------
|
|
80
|
+
const categoryByNiceName = new Map();
|
|
81
|
+
for (const category of parsed.categories) {
|
|
82
|
+
const entry = await categoryStore.create({
|
|
83
|
+
values: { name: category.name || category.niceName, slug: category.niceName },
|
|
84
|
+
status: 'published',
|
|
85
|
+
});
|
|
86
|
+
categoryByNiceName.set(category.niceName, entry.id);
|
|
87
|
+
acc.imported.categories += 1;
|
|
88
|
+
}
|
|
89
|
+
const tagByNiceName = new Map();
|
|
90
|
+
for (const tag of parsed.tags) {
|
|
91
|
+
const entry = await tagStore.create({
|
|
92
|
+
values: { name: tag.name || tag.slug, slug: tag.slug },
|
|
93
|
+
status: 'published',
|
|
94
|
+
});
|
|
95
|
+
tagByNiceName.set(tag.slug, entry.id);
|
|
96
|
+
acc.imported.tags += 1;
|
|
97
|
+
}
|
|
98
|
+
// ---- Media --------------------------------------------------------
|
|
99
|
+
const posts = parsed.items.filter((item) => item.postType === 'post');
|
|
100
|
+
const pages = parsed.items.filter((item) => item.postType === 'page');
|
|
101
|
+
const attachments = parsed.items.filter((item) => item.postType === 'attachment');
|
|
102
|
+
const attachmentUrlById = new Map(attachments
|
|
103
|
+
.filter((item) => item.attachmentUrl !== null)
|
|
104
|
+
.map((item) => [item.postId, item.attachmentUrl]));
|
|
105
|
+
const converted = new Map();
|
|
106
|
+
const allMediaUrls = new Set();
|
|
107
|
+
for (const item of [...posts, ...pages]) {
|
|
108
|
+
const { blocks, notes } = convertContent(item.contentEncoded);
|
|
109
|
+
converted.set(item.postId, { blocks, notes: [...notes] });
|
|
110
|
+
for (const url of mediaUrlsOf(blocks))
|
|
111
|
+
allMediaUrls.add(url);
|
|
112
|
+
const thumbnail = item.thumbnailId === null ? undefined : attachmentUrlById.get(item.thumbnailId);
|
|
113
|
+
if (thumbnail !== undefined)
|
|
114
|
+
allMediaUrls.add(thumbnail);
|
|
115
|
+
}
|
|
116
|
+
for (const url of attachmentUrlById.values())
|
|
117
|
+
allMediaUrls.add(url);
|
|
118
|
+
const mediaResult = await downloadAndStoreMedia([...allMediaUrls], {
|
|
119
|
+
mediaStore,
|
|
120
|
+
storage,
|
|
121
|
+
createdBy: null,
|
|
122
|
+
...(options.fetchImpl === undefined ? {} : { fetchImpl: options.fetchImpl }),
|
|
123
|
+
});
|
|
124
|
+
acc.imported.media = mediaResult.imported.length;
|
|
125
|
+
for (const failure of mediaResult.failed) {
|
|
126
|
+
acc.warnings.push(`Media "${failure.url}" could not be downloaded: ${failure.reason}`);
|
|
127
|
+
}
|
|
128
|
+
for (const asset of mediaResult.imported) {
|
|
129
|
+
acc.warnings.push(`Media "${asset.filename}" was imported with a synthesised alt text; review it.`);
|
|
130
|
+
}
|
|
131
|
+
// ---- Posts & pages --------------------------------------------------
|
|
132
|
+
async function writeEntry(item, store, kind) {
|
|
133
|
+
if (item.status === 'trash') {
|
|
134
|
+
acc.skipped.push({
|
|
135
|
+
type: kind,
|
|
136
|
+
wpId: item.postId,
|
|
137
|
+
title: item.title,
|
|
138
|
+
reason: 'Trashed in WordPress; not imported.',
|
|
139
|
+
});
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
if (!IMPORTABLE_STATUSES.has(item.status)) {
|
|
143
|
+
acc.skipped.push({
|
|
144
|
+
type: kind,
|
|
145
|
+
wpId: item.postId,
|
|
146
|
+
title: item.title,
|
|
147
|
+
reason: `Unrecognised WordPress status "${item.status}".`,
|
|
148
|
+
});
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
const draft = converted.get(item.postId);
|
|
152
|
+
const notes = draft?.notes ?? [];
|
|
153
|
+
const resolvedBlocks = resolveMediaReferences(draft?.blocks ?? [], mediaResult.urlToMediaId, notes);
|
|
154
|
+
for (const note of notes) {
|
|
155
|
+
acc.unconvertedBlocks.push({
|
|
156
|
+
...note,
|
|
157
|
+
postTitle: item.title || `(untitled ${kind} ${item.postId})`,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
const status = item.status === 'publish' ? 'published' : 'draft';
|
|
161
|
+
const createdBy = loginToUserId.get(item.creator) ?? null;
|
|
162
|
+
if (createdBy === null && item.creator.length > 0) {
|
|
163
|
+
acc.warnings.push(`Author "${item.creator}" of "${item.title}" was not found among the export's authors.`);
|
|
164
|
+
}
|
|
165
|
+
const customFields = Object.fromEntries(item.postMeta
|
|
166
|
+
.filter((meta) => !meta.key.startsWith('_'))
|
|
167
|
+
.map((meta) => [meta.key, meta.value]));
|
|
168
|
+
const values = {
|
|
169
|
+
title: item.title || `(untitled ${item.postId})`,
|
|
170
|
+
slug: item.postName || item.postId,
|
|
171
|
+
publishedAt: wpDateToIso(item.postDate),
|
|
172
|
+
customFields,
|
|
173
|
+
};
|
|
174
|
+
if (kind === 'post') {
|
|
175
|
+
values['excerpt'] = item.excerptEncoded;
|
|
176
|
+
const categoryRef = item.categories.find((ref) => ref.domain === 'category');
|
|
177
|
+
const category = categoryRef === undefined ? null : (categoryByNiceName.get(categoryRef.niceName) ?? null);
|
|
178
|
+
if (category !== null)
|
|
179
|
+
values['category'] = category;
|
|
180
|
+
values['tags'] = item.categories
|
|
181
|
+
.filter((ref) => ref.domain === 'post_tag')
|
|
182
|
+
.map((ref) => tagByNiceName.get(ref.niceName))
|
|
183
|
+
.filter((id) => id !== undefined);
|
|
184
|
+
}
|
|
185
|
+
const entry = await store.create({
|
|
186
|
+
id: item.postId,
|
|
187
|
+
status,
|
|
188
|
+
createdBy,
|
|
189
|
+
values,
|
|
190
|
+
blocks: { body: toContentBlocks(resolvedBlocks) },
|
|
191
|
+
});
|
|
192
|
+
const collection = kind === 'post' ? wpPost : wpPage;
|
|
193
|
+
const to = buildPath(collection, { slug: values['slug'] });
|
|
194
|
+
const from = relativePathOf(item.link, parsed.baseUrl);
|
|
195
|
+
if (from !== null && from !== to) {
|
|
196
|
+
try {
|
|
197
|
+
await redirects.add({ from, to, reason: 'import', collection: kind, entryId: entry.id });
|
|
198
|
+
acc.redirectsCreated += 1;
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
acc.warnings.push(`Redirect ${from} → ${to} was not created: ${error instanceof Error ? error.message : String(error)}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return entry.id;
|
|
205
|
+
}
|
|
206
|
+
for (const item of posts) {
|
|
207
|
+
const id = await writeEntry(item, postStore, 'post');
|
|
208
|
+
if (id !== null) {
|
|
209
|
+
acc.imported.posts += 1;
|
|
210
|
+
for (const comment of item.comments) {
|
|
211
|
+
if (comment.approved !== APPROVED)
|
|
212
|
+
continue;
|
|
213
|
+
await commentStore.create({
|
|
214
|
+
status: 'published',
|
|
215
|
+
values: {
|
|
216
|
+
post: id,
|
|
217
|
+
author: comment.author || 'Anonymous',
|
|
218
|
+
authorEmail: comment.authorEmail,
|
|
219
|
+
body: comment.content,
|
|
220
|
+
publishedAt: wpDateToIso(comment.date),
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
acc.imported.comments += 1;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
for (const item of pages) {
|
|
228
|
+
const id = await writeEntry(item, pageStore, 'page');
|
|
229
|
+
if (id !== null)
|
|
230
|
+
acc.imported.pages += 1;
|
|
231
|
+
}
|
|
232
|
+
const skipped = acc.skipped;
|
|
233
|
+
return {
|
|
234
|
+
imported: acc.imported,
|
|
235
|
+
redirectsCreated: acc.redirectsCreated,
|
|
236
|
+
skipped,
|
|
237
|
+
unconvertedBlocks: acc.unconvertedBlocks,
|
|
238
|
+
warnings: acc.warnings,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/wordpress/import.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { MediaAsset, MediaStore, StorageDriver } from '@cogenta/core';
|
|
2
|
+
export interface MediaDownloadFailure {
|
|
3
|
+
readonly url: string;
|
|
4
|
+
readonly reason: string;
|
|
5
|
+
}
|
|
6
|
+
export interface MediaImportResult {
|
|
7
|
+
readonly urlToMediaId: ReadonlyMap<string, string>;
|
|
8
|
+
readonly imported: readonly MediaAsset[];
|
|
9
|
+
readonly failed: readonly MediaDownloadFailure[];
|
|
10
|
+
}
|
|
11
|
+
export interface DownloadAndStoreMediaOptions {
|
|
12
|
+
readonly mediaStore: MediaStore;
|
|
13
|
+
readonly storage: StorageDriver;
|
|
14
|
+
readonly createdBy: string | null;
|
|
15
|
+
/** Injected for tests — real `fetch` by default. */
|
|
16
|
+
readonly fetchImpl?: typeof fetch;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Downloads every distinct media URL a WXR import references and stores it
|
|
20
|
+
* for real (rule: no mocking the storage layer — the fetch boundary is the
|
|
21
|
+
* only thing tests stand in for). A URL that fails to fetch is named in
|
|
22
|
+
* `failed`, never thrown: one dead upstream image, common in a real-world
|
|
23
|
+
* export, must not abort the whole import (the lot's own framing: a reported
|
|
24
|
+
* partial loss is the acceptable outcome, a silent one is not).
|
|
25
|
+
*/
|
|
26
|
+
export declare function downloadAndStoreMedia(urls: readonly string[], options: DownloadAndStoreMediaOptions): Promise<MediaImportResult>;
|
|
27
|
+
//# sourceMappingURL=media.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/wordpress/media.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAE5F,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClD,QAAQ,CAAC,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAA;IACxC,QAAQ,CAAC,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAA;CACjD;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,oDAAoD;IACpD,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;CAClC;AAmBD;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,iBAAiB,CAAC,CA2C5B"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { basename } from 'node:path';
|
|
2
|
+
function filenameFrom(url) {
|
|
3
|
+
try {
|
|
4
|
+
const path = new URL(url).pathname;
|
|
5
|
+
const name = basename(path);
|
|
6
|
+
return name.length > 0 ? name : 'file';
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return 'file';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
function kindFor(mimeType) {
|
|
13
|
+
if (mimeType.startsWith('image/'))
|
|
14
|
+
return 'image';
|
|
15
|
+
if (mimeType.startsWith('video/'))
|
|
16
|
+
return 'video';
|
|
17
|
+
if (mimeType.startsWith('audio/'))
|
|
18
|
+
return 'audio';
|
|
19
|
+
return 'file';
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Downloads every distinct media URL a WXR import references and stores it
|
|
23
|
+
* for real (rule: no mocking the storage layer — the fetch boundary is the
|
|
24
|
+
* only thing tests stand in for). A URL that fails to fetch is named in
|
|
25
|
+
* `failed`, never thrown: one dead upstream image, common in a real-world
|
|
26
|
+
* export, must not abort the whole import (the lot's own framing: a reported
|
|
27
|
+
* partial loss is the acceptable outcome, a silent one is not).
|
|
28
|
+
*/
|
|
29
|
+
export async function downloadAndStoreMedia(urls, options) {
|
|
30
|
+
const doFetch = options.fetchImpl ?? fetch;
|
|
31
|
+
const urlToMediaId = new Map();
|
|
32
|
+
const imported = [];
|
|
33
|
+
const failed = [];
|
|
34
|
+
for (const url of new Set(urls)) {
|
|
35
|
+
try {
|
|
36
|
+
const response = await doFetch(url);
|
|
37
|
+
if (!response.ok) {
|
|
38
|
+
failed.push({ url, reason: `HTTP ${response.status}` });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const mimeType = response.headers.get('content-type')?.split(';')[0]?.trim() ?? 'application/octet-stream';
|
|
42
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
43
|
+
const filename = filenameFrom(url);
|
|
44
|
+
const storageKey = `imports/wordpress/${Date.now()}-${Math.random().toString(36).slice(2)}-${filename}`;
|
|
45
|
+
await options.storage.put(storageKey, buffer, { contentType: mimeType });
|
|
46
|
+
const asset = await options.mediaStore.create({
|
|
47
|
+
kind: kindFor(mimeType),
|
|
48
|
+
filename,
|
|
49
|
+
mimeType,
|
|
50
|
+
size: buffer.byteLength,
|
|
51
|
+
// WXR carries no alt text for attachments; a synthesised value keeps
|
|
52
|
+
// the media library's own alt-text requirement honest rather than
|
|
53
|
+
// inventing a description of an image nobody described, and the gap
|
|
54
|
+
// is named in the conversion report so an editor knows to revisit it.
|
|
55
|
+
alt: `Imported from WordPress: ${filename}`,
|
|
56
|
+
storageKey,
|
|
57
|
+
createdBy: options.createdBy,
|
|
58
|
+
});
|
|
59
|
+
urlToMediaId.set(url, asset.id);
|
|
60
|
+
imported.push(asset);
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
failed.push({ url, reason: error instanceof Error ? error.message : String(error) });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { urlToMediaId, imported, failed };
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=media.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../src/wordpress/media.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ParsedWxr } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Reads a WordPress "Export All Content" WXR file into plain data.
|
|
4
|
+
*
|
|
5
|
+
* No conversion decisions happen here — this module only decodes the XML into
|
|
6
|
+
* the shape `content-convert.ts` and `import.ts` work from. `WXR_POST_STATUSES`
|
|
7
|
+
* is not enforced here either: an export from a fork or a very old WordPress
|
|
8
|
+
* version may carry a status this list does not name, and refusing to parse it
|
|
9
|
+
* would lose everything else in the file over one field.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseWxr(source: string): ParsedWxr;
|
|
12
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/wordpress/parse.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,SAAS,EAQV,MAAM,YAAY,CAAA;AAiFnB;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAqBlD"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { CogentaError } from '@cogenta/core';
|
|
2
|
+
import { children, firstChild, parseXmlDocument, textOf, textOfChild, } from './xml.js';
|
|
3
|
+
function parseAuthor(el) {
|
|
4
|
+
return {
|
|
5
|
+
login: textOfChild(el, 'wp:author_login'),
|
|
6
|
+
email: textOfChild(el, 'wp:author_email'),
|
|
7
|
+
displayName: textOfChild(el, 'wp:author_display_name'),
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
function parseCategoryTerm(el) {
|
|
11
|
+
return {
|
|
12
|
+
termId: textOfChild(el, 'wp:term_id'),
|
|
13
|
+
niceName: textOfChild(el, 'wp:category_nicename'),
|
|
14
|
+
name: textOfChild(el, 'wp:cat_name'),
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function parseTagTerm(el) {
|
|
18
|
+
return {
|
|
19
|
+
termId: textOfChild(el, 'wp:term_id'),
|
|
20
|
+
slug: textOfChild(el, 'wp:tag_slug'),
|
|
21
|
+
name: textOfChild(el, 'wp:tag_name'),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function parseTermRef(el) {
|
|
25
|
+
return {
|
|
26
|
+
domain: el.attrs['domain'] ?? '',
|
|
27
|
+
niceName: el.attrs['nicename'] ?? '',
|
|
28
|
+
name: textOf(el),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function parsePostMeta(el) {
|
|
32
|
+
return { key: textOfChild(el, 'wp:meta_key'), value: textOfChild(el, 'wp:meta_value') };
|
|
33
|
+
}
|
|
34
|
+
function parseComment(el) {
|
|
35
|
+
return {
|
|
36
|
+
id: textOfChild(el, 'wp:comment_id'),
|
|
37
|
+
author: textOfChild(el, 'wp:comment_author'),
|
|
38
|
+
authorEmail: textOfChild(el, 'wp:comment_author_email'),
|
|
39
|
+
date: textOfChild(el, 'wp:comment_date_gmt') || textOfChild(el, 'wp:comment_date'),
|
|
40
|
+
content: textOfChild(el, 'wp:comment_content'),
|
|
41
|
+
approved: textOfChild(el, 'wp:comment_approved'),
|
|
42
|
+
parentId: textOfChild(el, 'wp:comment_parent'),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function parseItem(el) {
|
|
46
|
+
const postMeta = children(el, 'wp:postmeta').map(parsePostMeta);
|
|
47
|
+
const thumbnailId = postMeta.find((meta) => meta.key === '_thumbnail_id')?.value ?? null;
|
|
48
|
+
return {
|
|
49
|
+
postId: textOfChild(el, 'wp:post_id'),
|
|
50
|
+
postType: textOfChild(el, 'wp:post_type'),
|
|
51
|
+
title: textOfChild(el, 'title'),
|
|
52
|
+
link: textOfChild(el, 'link'),
|
|
53
|
+
postName: textOfChild(el, 'wp:post_name'),
|
|
54
|
+
status: textOfChild(el, 'wp:status'),
|
|
55
|
+
postDate: textOfChild(el, 'wp:post_date_gmt') || textOfChild(el, 'wp:post_date'),
|
|
56
|
+
creator: textOfChild(el, 'dc:creator'),
|
|
57
|
+
contentEncoded: textOfChild(el, 'content:encoded'),
|
|
58
|
+
excerptEncoded: textOfChild(el, 'excerpt:encoded'),
|
|
59
|
+
categories: children(el, 'category').map(parseTermRef),
|
|
60
|
+
postMeta,
|
|
61
|
+
comments: children(el, 'wp:comment').map(parseComment),
|
|
62
|
+
attachmentUrl: textOfChild(el, 'wp:attachment_url') || null,
|
|
63
|
+
thumbnailId,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Reads a WordPress "Export All Content" WXR file into plain data.
|
|
68
|
+
*
|
|
69
|
+
* No conversion decisions happen here — this module only decodes the XML into
|
|
70
|
+
* the shape `content-convert.ts` and `import.ts` work from. `WXR_POST_STATUSES`
|
|
71
|
+
* is not enforced here either: an export from a fork or a very old WordPress
|
|
72
|
+
* version may carry a status this list does not name, and refusing to parse it
|
|
73
|
+
* would lose everything else in the file over one field.
|
|
74
|
+
*/
|
|
75
|
+
export function parseWxr(source) {
|
|
76
|
+
const root = parseXmlDocument(source);
|
|
77
|
+
const channel = firstChild(root, 'channel');
|
|
78
|
+
if (channel === null) {
|
|
79
|
+
throw new CogentaError({
|
|
80
|
+
code: 'IMPORT_WXR_PARSE_FAILED',
|
|
81
|
+
message: 'The document has no <channel> element.',
|
|
82
|
+
hint: 'This does not look like a WordPress WXR export — check the file was produced by Tools → Export.',
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const items = children(channel, 'item').map(parseItem);
|
|
86
|
+
return {
|
|
87
|
+
siteTitle: textOfChild(channel, 'title'),
|
|
88
|
+
baseUrl: textOfChild(channel, 'wp:base_site_url') || textOfChild(channel, 'wp:base_blog_url'),
|
|
89
|
+
authors: children(channel, 'wp:author').map(parseAuthor),
|
|
90
|
+
categories: children(channel, 'wp:category').map(parseCategoryTerm),
|
|
91
|
+
tags: children(channel, 'wp:tag').map(parseTagTerm),
|
|
92
|
+
items,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../../src/wordpress/parse.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ContentConversionNote } from './content-convert.js';
|
|
2
|
+
export interface UnconvertedItem {
|
|
3
|
+
readonly type: string;
|
|
4
|
+
readonly wpId: string;
|
|
5
|
+
readonly title: string;
|
|
6
|
+
readonly reason: string;
|
|
7
|
+
}
|
|
8
|
+
export interface ConversionReport {
|
|
9
|
+
readonly imported: {
|
|
10
|
+
readonly posts: number;
|
|
11
|
+
readonly pages: number;
|
|
12
|
+
readonly categories: number;
|
|
13
|
+
readonly tags: number;
|
|
14
|
+
readonly media: number;
|
|
15
|
+
readonly authors: number;
|
|
16
|
+
readonly comments: number;
|
|
17
|
+
};
|
|
18
|
+
readonly redirectsCreated: number;
|
|
19
|
+
readonly skipped: readonly UnconvertedItem[];
|
|
20
|
+
readonly unconvertedBlocks: readonly (ContentConversionNote & {
|
|
21
|
+
readonly postTitle: string;
|
|
22
|
+
})[];
|
|
23
|
+
readonly warnings: readonly string[];
|
|
24
|
+
}
|
|
25
|
+
export interface MutableConversionAccumulator {
|
|
26
|
+
imported: {
|
|
27
|
+
posts: number;
|
|
28
|
+
pages: number;
|
|
29
|
+
categories: number;
|
|
30
|
+
tags: number;
|
|
31
|
+
media: number;
|
|
32
|
+
authors: number;
|
|
33
|
+
comments: number;
|
|
34
|
+
};
|
|
35
|
+
redirectsCreated: number;
|
|
36
|
+
skipped: UnconvertedItem[];
|
|
37
|
+
unconvertedBlocks: (ContentConversionNote & {
|
|
38
|
+
postTitle: string;
|
|
39
|
+
})[];
|
|
40
|
+
warnings: string[];
|
|
41
|
+
}
|
|
42
|
+
export declare function emptyReport(): MutableConversionAccumulator;
|
|
43
|
+
/** A human-readable summary — what `cogenta import wordpress` prints. */
|
|
44
|
+
export declare function formatConversionReport(report: ConversionReport): string;
|
|
45
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../src/wordpress/report.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAEjE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,QAAQ,EAAE;QACjB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;QAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;QACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAC1B,CAAA;IACD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAA;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,SAAS,CAAC,qBAAqB,GAAG;QAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAA;IAC/F,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CACrC;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE;QACR,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,MAAM,CAAA;QACb,UAAU,EAAE,MAAM,CAAA;QAClB,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;KACjB,CAAA;IACD,gBAAgB,EAAE,MAAM,CAAA;IACxB,OAAO,EAAE,eAAe,EAAE,CAAA;IAC1B,iBAAiB,EAAE,CAAC,qBAAqB,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAA;IACpE,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,wBAAgB,WAAW,IAAI,4BAA4B,CAQ1D;AAED,yEAAyE;AACzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAqCvE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export function emptyReport() {
|
|
2
|
+
return {
|
|
3
|
+
imported: { posts: 0, pages: 0, categories: 0, tags: 0, media: 0, authors: 0, comments: 0 },
|
|
4
|
+
redirectsCreated: 0,
|
|
5
|
+
skipped: [],
|
|
6
|
+
unconvertedBlocks: [],
|
|
7
|
+
warnings: [],
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** A human-readable summary — what `cogenta import wordpress` prints. */
|
|
11
|
+
export function formatConversionReport(report) {
|
|
12
|
+
const lines = [];
|
|
13
|
+
const { imported } = report;
|
|
14
|
+
lines.push('Imported:');
|
|
15
|
+
lines.push(` ${imported.posts} posts, ${imported.pages} pages`);
|
|
16
|
+
lines.push(` ${imported.categories} categories, ${imported.tags} tags`);
|
|
17
|
+
lines.push(` ${imported.media} media files, ${imported.authors} authors, ${imported.comments} comments`);
|
|
18
|
+
lines.push(` ${report.redirectsCreated} redirects`);
|
|
19
|
+
if (report.skipped.length > 0) {
|
|
20
|
+
lines.push('');
|
|
21
|
+
lines.push(`Not imported (${report.skipped.length}):`);
|
|
22
|
+
for (const item of report.skipped) {
|
|
23
|
+
lines.push(` [${item.type} ${item.wpId}] "${item.title}" — ${item.reason}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (report.unconvertedBlocks.length > 0) {
|
|
27
|
+
lines.push('');
|
|
28
|
+
lines.push(`Content that could not be converted to a block or a rich-text node (${report.unconvertedBlocks.length}):`);
|
|
29
|
+
for (const note of report.unconvertedBlocks) {
|
|
30
|
+
lines.push(` "${note.postTitle}" — ${note.source}: ${note.reason}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (report.warnings.length > 0) {
|
|
34
|
+
lines.push('');
|
|
35
|
+
lines.push('Warnings:');
|
|
36
|
+
for (const warning of report.warnings)
|
|
37
|
+
lines.push(` ${warning}`);
|
|
38
|
+
}
|
|
39
|
+
return lines.join('\n');
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/wordpress/report.ts"],"names":[],"mappings":"AAyCA,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE;QAC3F,gBAAgB,EAAE,CAAC;QACnB,OAAO,EAAE,EAAE;QACX,iBAAiB,EAAE,EAAE;QACrB,QAAQ,EAAE,EAAE;KACb,CAAA;AACH,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,sBAAsB,CAAC,MAAwB;IAC7D,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAA;IAE3B,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;IACvB,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,WAAW,QAAQ,CAAC,KAAK,QAAQ,CAAC,CAAA;IAChE,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,UAAU,gBAAgB,QAAQ,CAAC,IAAI,OAAO,CAAC,CAAA;IACxE,KAAK,CAAC,IAAI,CACR,KAAK,QAAQ,CAAC,KAAK,iBAAiB,QAAQ,CAAC,OAAO,aAAa,QAAQ,CAAC,QAAQ,WAAW,CAC9F,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,gBAAgB,YAAY,CAAC,CAAA;IAEpD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACd,KAAK,CAAC,IAAI,CAAC,iBAAiB,MAAM,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAA;QACtD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YAClC,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,KAAK,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;QAC9E,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACd,KAAK,CAAC,IAAI,CACR,uEAAuE,MAAM,CAAC,iBAAiB,CAAC,MAAM,IAAI,CAC3G,CAAA;QACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,SAAS,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAA;QACtE,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACd,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QACvB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC,CAAA;IACnE,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** The WXR document, decoded into plain data — no XML concepts leak past this module. */
|
|
2
|
+
export interface WxrAuthor {
|
|
3
|
+
readonly login: string;
|
|
4
|
+
readonly email: string;
|
|
5
|
+
readonly displayName: string;
|
|
6
|
+
}
|
|
7
|
+
export interface WxrCategory {
|
|
8
|
+
readonly termId: string;
|
|
9
|
+
readonly niceName: string;
|
|
10
|
+
readonly name: string;
|
|
11
|
+
}
|
|
12
|
+
export interface WxrTag {
|
|
13
|
+
readonly termId: string;
|
|
14
|
+
readonly slug: string;
|
|
15
|
+
readonly name: string;
|
|
16
|
+
}
|
|
17
|
+
/** A `<category>` element on an `<item>` — the term it actually applies. */
|
|
18
|
+
export interface WxrTermRef {
|
|
19
|
+
readonly domain: 'category' | 'post_tag' | string;
|
|
20
|
+
readonly niceName: string;
|
|
21
|
+
readonly name: string;
|
|
22
|
+
}
|
|
23
|
+
export interface WxrPostMeta {
|
|
24
|
+
readonly key: string;
|
|
25
|
+
readonly value: string;
|
|
26
|
+
}
|
|
27
|
+
export interface WxrComment {
|
|
28
|
+
readonly id: string;
|
|
29
|
+
readonly author: string;
|
|
30
|
+
readonly authorEmail: string;
|
|
31
|
+
readonly date: string;
|
|
32
|
+
readonly content: string;
|
|
33
|
+
/** `'1'` approved, `'0'` pending, `'spam'` — only `'1'` is imported. */
|
|
34
|
+
readonly approved: string;
|
|
35
|
+
readonly parentId: string;
|
|
36
|
+
}
|
|
37
|
+
export declare const WXR_POST_STATUSES: readonly ['publish', 'draft', 'pending', 'private', 'future', 'trash'];
|
|
38
|
+
export type WxrPostStatus = (typeof WXR_POST_STATUSES)[number];
|
|
39
|
+
export interface WxrItem {
|
|
40
|
+
readonly postId: string;
|
|
41
|
+
readonly postType: string;
|
|
42
|
+
readonly title: string;
|
|
43
|
+
readonly link: string;
|
|
44
|
+
readonly postName: string;
|
|
45
|
+
readonly status: string;
|
|
46
|
+
readonly postDate: string;
|
|
47
|
+
readonly creator: string;
|
|
48
|
+
readonly contentEncoded: string;
|
|
49
|
+
readonly excerptEncoded: string;
|
|
50
|
+
readonly categories: readonly WxrTermRef[];
|
|
51
|
+
readonly postMeta: readonly WxrPostMeta[];
|
|
52
|
+
readonly comments: readonly WxrComment[];
|
|
53
|
+
/** Set only when `postType === 'attachment'`. */
|
|
54
|
+
readonly attachmentUrl: string | null;
|
|
55
|
+
/** The thumbnail's `wp:post_id`, from `_thumbnail_id` postmeta, resolved later against attachments. */
|
|
56
|
+
readonly thumbnailId: string | null;
|
|
57
|
+
}
|
|
58
|
+
export interface ParsedWxr {
|
|
59
|
+
readonly siteTitle: string;
|
|
60
|
+
readonly baseUrl: string;
|
|
61
|
+
readonly authors: readonly WxrAuthor[];
|
|
62
|
+
readonly categories: readonly WxrCategory[];
|
|
63
|
+
readonly tags: readonly WxrTag[];
|
|
64
|
+
readonly items: readonly WxrItem[];
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=types.d.ts.map
|