@contentrain/wp-import 0.12.2 → 0.13.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/README.md +1 -0
- package/dist/index.d.mts +32 -5
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +38 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -37,6 +37,7 @@ const commentsExport = buildCommentsExport(raw, entry_source_map)
|
|
|
37
37
|
- **UTC dates** — GMT columns preferred, stamped ISO 8601 `Z`.
|
|
38
38
|
- **Pure conversion** — `rawToContentrain` returns a canonical-serialized file map (sorted keys, 2-space indent, trailing newline); writing to disk is the caller's one line.
|
|
39
39
|
- **EntrySourceMap produced at the only place that can know it** — the WP-id → entry-address mapping the comments intake requires.
|
|
40
|
+
- **No e-mail addresses by default** — a WXR export carries author and commenter e-mails; `rawToContentrain` leaves them out of the store unless called with `{ includeEmails: true }` (the store usually ends up in git), and `buildCommentsExport` sets `email: null` unless given the same option. Comment meta under a personal-data key (IP, user agent, e-mail, avatar URLs, every `akismet_*`; `COMMENT_PII_META_KEY`) never travels, with or without it. The REST path never has them. Names, logins, commenter website URLs and comment text are written.
|
|
40
41
|
- **Only public discussion leaves the site** — `buildCommentsExport` carries comments on published, unprotected entries that are approved or pending (pending lands in the receiver's moderation queue). Comments on drafts, private, scheduled or password-protected entries, any other status (spam, trash, `post-trashed`, a plugin's) and entries the import does not hold, stay behind; `excluded` counts them.
|
|
41
42
|
|
|
42
43
|
Streaming WXR parse (sax): a 100 MB export holds only its records in memory.
|
package/dist/index.d.mts
CHANGED
|
@@ -148,9 +148,19 @@ interface ContentrainResult {
|
|
|
148
148
|
entry_source_map: EntrySourceMap;
|
|
149
149
|
report: ImportReport;
|
|
150
150
|
}
|
|
151
|
-
|
|
151
|
+
interface RawToContentrainOptions {
|
|
152
|
+
/** `updated_by` stamped on every meta entry. Default `@contentrain/wp-import`. */
|
|
152
153
|
updatedBy?: string;
|
|
153
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Write author and commenter e-mail addresses into the `authors` and
|
|
156
|
+
* `comments` entries. Default `false`: a WXR export carries them, but they
|
|
157
|
+
* are third parties' personal data and a store usually ends up in git
|
|
158
|
+
* (sometimes a public repo), so they stay out unless asked for. The REST
|
|
159
|
+
* path never has them.
|
|
160
|
+
*/
|
|
161
|
+
includeEmails?: boolean;
|
|
162
|
+
}
|
|
163
|
+
declare function rawToContentrain(raw: RawIR, opts?: RawToContentrainOptions): ContentrainResult;
|
|
154
164
|
//#endregion
|
|
155
165
|
//#region src/comments.d.ts
|
|
156
166
|
/**
|
|
@@ -163,9 +173,26 @@ declare function selectComments(raw: RawIR): {
|
|
|
163
173
|
comments: RawComment[];
|
|
164
174
|
excluded: NonNullable<CommentsExport['excluded']>;
|
|
165
175
|
};
|
|
166
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Comment meta keys that hold a commenter's personal data: IP, browser user
|
|
178
|
+
* agent, e-mail, avatar URLs (a Gravatar URL carries the e-mail's hash). Same
|
|
179
|
+
* list as Migrate's intake (`PII_META_KEY`), plus every `akismet_*` key:
|
|
180
|
+
* `akismet_as_submitted` stores the whole submission (IP, user agent, e-mail,
|
|
181
|
+
* referrer) and the rest is spam-check bookkeeping. Matched by key, so a
|
|
182
|
+
* comment with no e-mail still loses its IP and user agent.
|
|
183
|
+
*/
|
|
184
|
+
declare const COMMENT_PII_META_KEY: RegExp;
|
|
185
|
+
interface CommentsExportOptions {
|
|
167
186
|
generated_at?: string;
|
|
168
|
-
|
|
187
|
+
/**
|
|
188
|
+
* Carry commenter e-mail addresses. Default `false`: the export is written
|
|
189
|
+
* next to the store and is personal data of third parties; a receiving
|
|
190
|
+
* service that needs addresses asks for them. IPs, user agents and avatar
|
|
191
|
+
* URLs are never carried, with or without this option.
|
|
192
|
+
*/
|
|
193
|
+
includeEmails?: boolean;
|
|
194
|
+
}
|
|
195
|
+
declare function buildCommentsExport(raw: RawIR, entries: EntrySourceMap, opts?: CommentsExportOptions): CommentsExport;
|
|
169
196
|
/** Handoff summary for the export: counts + closed threads + what could not be addressed. */
|
|
170
197
|
declare function summarizeComments(exp: CommentsExport): HandoffComments;
|
|
171
198
|
//#endregion
|
|
@@ -266,5 +293,5 @@ declare function planSourceDelta(input: PlanSourceDeltaInput): SourceDeltaPlan;
|
|
|
266
293
|
/** The plan as text, for a dry run: one line per record, then conflicts, unmapped records, redirects and warnings. */
|
|
267
294
|
declare function formatSourceDeltaReport(plan: SourceDeltaPlan): string;
|
|
268
295
|
//#endregion
|
|
269
|
-
export { type ContentrainResult, DEFAULT_IMPORTERS, DEFAULT_TAXONOMIES, type DeltaStore, type ImportReport, LANDING_PAGE_TYPE, PLUGIN_META, type PlanSourceDeltaInput, type RestImportOptions, type RestImportResult, SKIP_TYPES, type UnserializeResult, type WxrParseResult, type WxrStats, addressSlug, buildCommentsExport, canon, fetchRestRawIR, formatSourceDeltaReport, hexId, looksSerialized, pageTypeOf, parseWxr, phpUnserialize, planSourceDelta, rawToContentrain, selectComments, slugify, strip, summarizeComments, taxModelId, tryUnserialize };
|
|
296
|
+
export { COMMENT_PII_META_KEY, type CommentsExportOptions, type ContentrainResult, DEFAULT_IMPORTERS, DEFAULT_TAXONOMIES, type DeltaStore, type ImportReport, LANDING_PAGE_TYPE, PLUGIN_META, type PlanSourceDeltaInput, type RawToContentrainOptions, type RestImportOptions, type RestImportResult, SKIP_TYPES, type UnserializeResult, type WxrParseResult, type WxrStats, addressSlug, buildCommentsExport, canon, fetchRestRawIR, formatSourceDeltaReport, hexId, looksSerialized, pageTypeOf, parseWxr, phpUnserialize, planSourceDelta, rawToContentrain, selectComments, slugify, strip, summarizeComments, taxModelId, tryUnserialize };
|
|
270
297
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/wxr.ts","../src/rest.ts","../src/contentrain.ts","../src/comments.ts","../src/php-unserialize.ts","../src/core.ts","../src/delta.ts"],"mappings":";;;;UA2BiB,QAAA;EACf,UAAA;IAAc,QAAA;IAAkB,OAAA;IAAiB,MAAA;IAAgB,IAAA;EAAA;EACjE,UAAA;EACA,gBAAA;EACA,MAAA,EAAQ,MAAA;AAAA;AAAA,UAGO,cAAA;EACf,GAAA,EAAK,KAAA;EACL,KAAA,EAAO,QAAA;AAAA;AAAA,iBAiBa,QAAA,CAAS,KAAA,WAAgB,QAAA,EAAU,IAAA;EAAS,IAAA;AAAA,IAAkB,OAAA,CAAQ,cAAA;;;UCnC3E,iBAAA;EACf,MAAA;;EAEA,SAAA,UAAmB,KAAA;EDMI;;;;;;;;ECGvB,IAAA;IAAS,IAAA;IAAc,WAAA;EAAA;EACvB,OAAA;EDAc;AAGhB;;;;ECGE,WAAA;EDFK;;;;ECOL,QAAA;EACA,IAAA;AAAA;AAAA,UAGe,gBAAA;EACf,GAAA,EAAK,KAAA;EACL,QAAA;EDKkF;;;;;;;;ECIlF,UAAA;IAAc,MAAA;IAA0C,SAAA;EAAA;;;AAvC1D;;;;;;;;;;EAoDE,IAAA;AAAA;AAAA,iBA4EoB,cAAA,CAAe,OAAA,EAAS,iBAAA,GAAoB,OAAA,CAAQ,gBAAA;;;;UCnHzD,QAAA;EACf,KAAA;EACA,IAAA;EFNuB;EEQvB,IAAA;EFJc;EEMd,IAAA;EFTc;;;;EEcd,MAAA;AAAA;AAAA,UAkBe,YAAA;EACf,cAAA;EACA,aAAA;EF/Bc;EEiCd,UAAA,EAAY,QAAA;EACZ,cAAA;EACA,WAAA,EAAa,MAAA;EACb,UAAA,EAAY,MAAA;EFhCZ;EEkCA,WAAA,EAAa,MAAA;EFjCb;EEmCA,mBAAA,EAAqB,MAAA;EFnCN;EEqCf,mBAAA,EAAqB,MAAA;EFpBD;EEsBpB,oBAAA;;EAEA,iBAAA,EAAmB,MAAA;EFxBuE;EE0B1F,sBAAA,EAAwB,MAAA;EACxB,aAAA;EACA,iBAAA;EACA,MAAA,EAAQ,MAAA;IAAiB,IAAA;IAAc,MAAA;IAAgB,MAAA;IAAgB,OAAA;EAAA;EF7BiC;EE+BxG,OAAA;;EAEA,kBAAA;;ADpEF;;;;;EC2EE,yBAAA;EDxEmB;;;;EC6EnB,kBAAA;AAAA;AAAA,UAGe,iBAAA;EACf,KAAA,EAAO,MAAA;EACP,gBAAA,EAAkB,cAAA;EAClB,MAAA,EAAQ,YAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/wxr.ts","../src/rest.ts","../src/contentrain.ts","../src/comments.ts","../src/php-unserialize.ts","../src/core.ts","../src/delta.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -2200,6 +2200,7 @@ function relationOver(targets) {
|
|
|
2200
2200
|
const idsOf = (v) => (Array.isArray(v) ? v : [v]).map((x) => typeof x === "number" ? x : typeof x === "string" && /^\d+$/.test(x) ? Number(x) : x && typeof x === "object" ? Number(x.ID ?? x.id ?? x.term_id) : NaN).filter((n) => Number.isSafeInteger(n) && n > 0);
|
|
2201
2201
|
function rawToContentrain(raw, opts) {
|
|
2202
2202
|
const updatedBy = opts?.updatedBy ?? "@contentrain/wp-import";
|
|
2203
|
+
const includeEmails = opts?.includeEmails === true;
|
|
2203
2204
|
const locale = normLocale(raw.site.language) || "en";
|
|
2204
2205
|
const models = {};
|
|
2205
2206
|
const contents = {};
|
|
@@ -2502,7 +2503,7 @@ function rawToContentrain(raw, opts) {
|
|
|
2502
2503
|
contents.authors[id] = pick({
|
|
2503
2504
|
name: strip(a.display_name),
|
|
2504
2505
|
slug: slugify(a.login),
|
|
2505
|
-
email: a.email,
|
|
2506
|
+
email: includeEmails ? a.email : null,
|
|
2506
2507
|
wp_id: a.id
|
|
2507
2508
|
}, new Set([
|
|
2508
2509
|
"name",
|
|
@@ -3118,7 +3119,7 @@ function rawToContentrain(raw, opts) {
|
|
|
3118
3119
|
}
|
|
3119
3120
|
contents.comments[cRef(c.id)] = pick({
|
|
3120
3121
|
author: strip(c.author) || "anonymous",
|
|
3121
|
-
email: c.email,
|
|
3122
|
+
email: includeEmails ? c.email : null,
|
|
3122
3123
|
url: c.url,
|
|
3123
3124
|
body: c.content,
|
|
3124
3125
|
published_at: c.date,
|
|
@@ -3321,9 +3322,42 @@ function selectComments(raw) {
|
|
|
3321
3322
|
excluded
|
|
3322
3323
|
};
|
|
3323
3324
|
}
|
|
3325
|
+
/**
|
|
3326
|
+
* Comment meta keys that hold a commenter's personal data: IP, browser user
|
|
3327
|
+
* agent, e-mail, avatar URLs (a Gravatar URL carries the e-mail's hash). Same
|
|
3328
|
+
* list as Migrate's intake (`PII_META_KEY`), plus every `akismet_*` key:
|
|
3329
|
+
* `akismet_as_submitted` stores the whole submission (IP, user agent, e-mail,
|
|
3330
|
+
* referrer) and the rest is spam-check bookkeeping. Matched by key, so a
|
|
3331
|
+
* comment with no e-mail still loses its IP and user agent.
|
|
3332
|
+
*/
|
|
3333
|
+
const COMMENT_PII_META_KEY = /(?:^|[_-])(?:ip|ip_address|author_ip|user_ip|agent|user_agent|author_agent|email|author_email|mail|avatar|avatar_url|avatar_urls|author_avatar_urls)$|^_?akismet_/i;
|
|
3334
|
+
/** Anything shaped like an e-mail address, anywhere in a serialized value. */
|
|
3335
|
+
const EMAIL_RE = /[^\s@"'<>;:]+@[^\s@"'<>;:]+\.[a-z]{2,}/i;
|
|
3336
|
+
const serialized = (v) => typeof v === "string" ? v : JSON.stringify(v) ?? "";
|
|
3337
|
+
/**
|
|
3338
|
+
* A comment as it may leave the site. Meta under a personal-data key is always
|
|
3339
|
+
* dropped: IPs and user agents are never exported. Without `includeEmails`,
|
|
3340
|
+
* `email` becomes null and any remaining meta whose value holds an address is
|
|
3341
|
+
* dropped too (an unknown plugin's own key).
|
|
3342
|
+
*/
|
|
3343
|
+
function exportableComment(c, includeEmails) {
|
|
3344
|
+
const out = includeEmails ? { ...c } : {
|
|
3345
|
+
...c,
|
|
3346
|
+
email: null
|
|
3347
|
+
};
|
|
3348
|
+
if (c.meta) {
|
|
3349
|
+
const kept = Object.entries(c.meta).filter(([k, v]) => !COMMENT_PII_META_KEY.test(k) && (includeEmails || !EMAIL_RE.test(serialized(v))));
|
|
3350
|
+
if (kept.length) out.meta = Object.fromEntries(kept);
|
|
3351
|
+
else delete out.meta;
|
|
3352
|
+
}
|
|
3353
|
+
return out;
|
|
3354
|
+
}
|
|
3324
3355
|
function buildCommentsExport(raw, entries, opts) {
|
|
3325
3356
|
const threadsClosed = raw.posts.filter((p) => p.comment_status && p.comment_status !== "open").map((p) => p.id);
|
|
3326
|
-
const
|
|
3357
|
+
const selected = selectComments(raw);
|
|
3358
|
+
const excluded = selected.excluded;
|
|
3359
|
+
const includeEmails = opts?.includeEmails === true;
|
|
3360
|
+
const comments = selected.comments.map((c) => exportableComment(c, includeEmails));
|
|
3327
3361
|
return {
|
|
3328
3362
|
version: MIGRATION_CONTRACT_VERSION,
|
|
3329
3363
|
format: COMMENTS_EXPORT_FORMAT,
|
|
@@ -3611,6 +3645,6 @@ function formatSourceDeltaReport(plan) {
|
|
|
3611
3645
|
return `${lines.join("\n")}\n`;
|
|
3612
3646
|
}
|
|
3613
3647
|
//#endregion
|
|
3614
|
-
export { DEFAULT_IMPORTERS, DEFAULT_TAXONOMIES, LANDING_PAGE_TYPE, PLUGIN_META, SKIP_TYPES, addressSlug, buildCommentsExport, canon, fetchRestRawIR, formatSourceDeltaReport, hexId, looksSerialized, pageTypeOf, parseWxr, phpUnserialize, planSourceDelta, rawToContentrain, selectComments, slugify, strip, summarizeComments, taxModelId, tryUnserialize };
|
|
3648
|
+
export { COMMENT_PII_META_KEY, DEFAULT_IMPORTERS, DEFAULT_TAXONOMIES, LANDING_PAGE_TYPE, PLUGIN_META, SKIP_TYPES, addressSlug, buildCommentsExport, canon, fetchRestRawIR, formatSourceDeltaReport, hexId, looksSerialized, pageTypeOf, parseWxr, phpUnserialize, planSourceDelta, rawToContentrain, selectComments, slugify, strip, summarizeComments, taxModelId, tryUnserialize };
|
|
3615
3649
|
|
|
3616
3650
|
//# sourceMappingURL=index.mjs.map
|