@geekity/plugin-wordpress 0.5.0 → 0.6.1

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 CHANGED
@@ -26,7 +26,7 @@ pnpm add @geekity/plugin-wordpress
26
26
  ```
27
27
 
28
28
  ```ts
29
- import { defineConfig } from '@geekity/cms';
29
+ import { defineConfig } from '@geekity/cms/config';
30
30
  import wordpress from '@geekity/plugin-wordpress';
31
31
 
32
32
  export default defineConfig({
@@ -105,6 +105,7 @@ reason.
105
105
  | ----------- | -------------------------------------------------------------------------------------------------------- |
106
106
  | `written` | The file is new, was changed on WordPress since the last run, or was removed here and is written again. |
107
107
  | `unchanged` | The file already holds what WordPress has. |
108
+ | `removed` | A comment the import wrote is no longer on WordPress, or is spam or trash there. It is removed here. |
108
109
  | `kept` | The file was edited on this site and WordPress has not changed it since. The edit stays. |
109
110
  | `conflict` | The file was edited on this site and changed on WordPress too. The edit stays. The row gives both dates. |
110
111
  | `clash` | A file the import never wrote is at the path. It is left alone. |
@@ -115,7 +116,8 @@ reason.
115
116
  content directory byte for byte the same as one run. A run over a newer export
116
117
  picks up what was added or edited on WordPress since. The import never
117
118
  overwrites a file it did not write, and never deletes a file, so you can edit
118
- imported files and keep the edits. To take WordPress's side of a conflict,
119
+ imported files and keep the edits. The one thing a rerun removes is an imported
120
+ comment that WordPress no longer has, as described under comments below. To take WordPress's side of a conflict,
119
121
  remove the file and run the import again.
120
122
 
121
123
  ### Posts and pages
@@ -269,6 +271,17 @@ imported comment that a moderator approved, filed as spam, edited or deleted.
269
271
  It still marks such a comment migrated and gives it its origin, its user and
270
272
  its actor.
271
273
 
274
+ A rerun also removes an imported comment that has left WordPress since the
275
+ last run: one that was deleted there, or moved to spam or the trash. The
276
+ WordPress ActivityPub plugin deletes a like or boost when its sender undoes
277
+ it, so this keeps reaction counts the same on both sites. The import removes a
278
+ comment only when it is still exactly as the import wrote it, compared with
279
+ the hash in `import.json`. Each removal is a `removed` row naming the post and
280
+ the WordPress comment id. A comment that was edited or moderated on this site
281
+ stays and is reported as `kept`. A comment this site received itself is never
282
+ removed. Comments recorded by an earlier version of the import have no
283
+ WordPress id in `import.json`, so their rows name the comment's key instead.
284
+
272
285
  **Upgrading from 0.2.0.** Version 0.2.0 used each comment's WordPress URL as
273
286
  its id. The site replaces every such id with the key of that URL when it next
274
287
  boots, or when it next runs a plugin command. A rerun of the import then moves
@@ -337,7 +350,11 @@ The command:
337
350
  plugin's `actors.json`
338
351
  3. fetches the WordPress plugin's public followers collection into
339
352
  `content/_data/federation/ada/followers.json`. It dereferences each follower
340
- for its inbox, shared inbox, handle, name, avatar and profile URL.
353
+ for its inbox, shared inbox, handle, name, avatar and profile URL. Each of
354
+ those requests is signed with the imported RSA key under
355
+ `<actor id>#main-key`, so servers that run Mastodon's authorized fetch
356
+ answer it. The report lists a follower whose server refuses the signed
357
+ request, and running the command again does not change that.
341
358
 
342
359
  | Option | What it is |
343
360
  | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -34662,45 +34662,45 @@ var require_jsonld_esm = __commonJS({
34662
34662
  if (isCallable(C2) && (!setPrototypeOf || isPrototypeOf(TypedArray, C2))) return C2;
34663
34663
  throw new TypeError2(tryToString(C2) + " is not a typed array constructor");
34664
34664
  };
34665
- var exportTypedArrayMethod = function(KEY, property, forced, options) {
34665
+ var exportTypedArrayMethod = function(KEY2, property, forced, options) {
34666
34666
  if (!DESCRIPTORS) return;
34667
34667
  if (forced) for (var ARRAY in TypedArrayConstructorsList) {
34668
34668
  var TypedArrayConstructor = globalThis2[ARRAY];
34669
- if (TypedArrayConstructor && hasOwn(TypedArrayConstructor.prototype, KEY)) try {
34670
- delete TypedArrayConstructor.prototype[KEY];
34669
+ if (TypedArrayConstructor && hasOwn(TypedArrayConstructor.prototype, KEY2)) try {
34670
+ delete TypedArrayConstructor.prototype[KEY2];
34671
34671
  } catch (error) {
34672
34672
  try {
34673
- TypedArrayConstructor.prototype[KEY] = property;
34673
+ TypedArrayConstructor.prototype[KEY2] = property;
34674
34674
  } catch (error2) {
34675
34675
  }
34676
34676
  }
34677
34677
  }
34678
- if (!TypedArrayPrototype[KEY] || forced) {
34679
- defineBuiltIn(TypedArrayPrototype, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype[KEY] || property, options);
34678
+ if (!TypedArrayPrototype[KEY2] || forced) {
34679
+ defineBuiltIn(TypedArrayPrototype, KEY2, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && Int8ArrayPrototype[KEY2] || property, options);
34680
34680
  }
34681
34681
  };
34682
- var exportTypedArrayStaticMethod = function(KEY, property, forced) {
34682
+ var exportTypedArrayStaticMethod = function(KEY2, property, forced) {
34683
34683
  var ARRAY, TypedArrayConstructor;
34684
34684
  if (!DESCRIPTORS) return;
34685
34685
  if (setPrototypeOf) {
34686
34686
  if (forced) for (ARRAY in TypedArrayConstructorsList) {
34687
34687
  TypedArrayConstructor = globalThis2[ARRAY];
34688
- if (TypedArrayConstructor && hasOwn(TypedArrayConstructor, KEY)) try {
34689
- delete TypedArrayConstructor[KEY];
34688
+ if (TypedArrayConstructor && hasOwn(TypedArrayConstructor, KEY2)) try {
34689
+ delete TypedArrayConstructor[KEY2];
34690
34690
  } catch (error) {
34691
34691
  }
34692
34692
  }
34693
- if (!TypedArray[KEY] || forced) {
34693
+ if (!TypedArray[KEY2] || forced) {
34694
34694
  try {
34695
- return defineBuiltIn(TypedArray, KEY, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && TypedArray[KEY] || property);
34695
+ return defineBuiltIn(TypedArray, KEY2, forced ? property : NATIVE_ARRAY_BUFFER_VIEWS && TypedArray[KEY2] || property);
34696
34696
  } catch (error) {
34697
34697
  }
34698
34698
  } else return;
34699
34699
  }
34700
34700
  for (ARRAY in TypedArrayConstructorsList) {
34701
34701
  TypedArrayConstructor = globalThis2[ARRAY];
34702
- if (TypedArrayConstructor && (!TypedArrayConstructor[KEY] || forced)) {
34703
- defineBuiltIn(TypedArrayConstructor, KEY, property);
34702
+ if (TypedArrayConstructor && (!TypedArrayConstructor[KEY2] || forced)) {
34703
+ defineBuiltIn(TypedArrayConstructor, KEY2, property);
34704
34704
  }
34705
34705
  }
34706
34706
  };
@@ -70064,9 +70064,13 @@ function withTrailingSlash(value) {
70064
70064
  function repliesKey(guid) {
70065
70065
  return createHash("sha256").update(guid).digest("hex").slice(0, 16);
70066
70066
  }
70067
+ var KEY = /^[0-9a-f]{16}$/;
70067
70068
  function webmentionKey(source, permalink) {
70068
70069
  return source === null || source === "" ? void 0 : repliesKey(`${source} ${permalink}`);
70069
70070
  }
70071
+ function isKey(value) {
70072
+ return KEY.test(value);
70073
+ }
70070
70074
 
70071
70075
  // ../cms/dist/content/slug.js
70072
70076
  var TRANSLITERATIONS = [
@@ -71665,12 +71669,12 @@ function generateNextLine(state, level) {
71665
71669
  return `
71666
71670
  ${" ".repeat(state.indent * level)}`;
71667
71671
  }
71668
- function scalarLayout(state, node, parent, level, isKey, flowOnly) {
71672
+ function scalarLayout(state, node, parent, level, isKey2, flowOnly) {
71669
71673
  return {
71670
71674
  node,
71671
71675
  parent,
71672
71676
  level,
71673
- isKey,
71677
+ isKey: isKey2,
71674
71678
  flowOnly,
71675
71679
  shiftOfParent: level === 0 ? -1 : state.indent * (level - 1),
71676
71680
  shiftOfContent: state.indent * Math.max(1, level),
@@ -181950,10 +181954,14 @@ async function importFollowers(options) {
181950
181954
  const unchanged = [];
181951
181955
  const refreshed = [];
181952
181956
  const failed = [];
181957
+ const signer = {
181958
+ privateKey: await signingKeyOf(privateKeyFrom(options.privateKeyPem)),
181959
+ keyId: new URL(`${options.actorId}#main-key`)
181960
+ };
181953
181961
  for (const item of await collectionItems(source)) {
181954
181962
  const actor = uriOf(item) ?? String(item);
181955
181963
  try {
181956
- const document2 = isRecord(item) && uriOf(item["inbox"]) !== null ? item : await fetchAs(actor);
181964
+ const document2 = isRecord(item) && uriOf(item["inbox"]) !== null ? item : await fetchAs(actor, signer);
181957
181965
  const follower = followerFrom(document2);
181958
181966
  const held = site.followers(username).find((entry) => entry.actorId === follower.actorId);
181959
181967
  await site.addFollower(username, follower);
@@ -181961,7 +181969,11 @@ async function importFollowers(options) {
181961
181969
  else if (sameFollower(held, follower)) unchanged.push(follower.actorId);
181962
181970
  else refreshed.push(follower.actorId);
181963
181971
  } catch (error) {
181964
- failed.push({ actor, reason: messageOf(error) });
181972
+ failed.push({
181973
+ actor,
181974
+ reason: messageOf(error),
181975
+ refused: error instanceof RefusedSignedFetchError
181976
+ });
181965
181977
  }
181966
181978
  }
181967
181979
  return { source, added, unchanged, refreshed, failed };
@@ -182010,15 +182022,25 @@ function isUrl(source) {
182010
182022
  return protocol === "http:" || protocol === "https:";
182011
182023
  }
182012
182024
  var ACTIVITY_STREAMS_ACCEPT = 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"';
182013
- async function fetchAs(url) {
182025
+ var RefusedSignedFetchError = class extends Error {
182026
+ name = "RefusedSignedFetchError";
182027
+ };
182028
+ async function fetchAs(url, signer) {
182014
182029
  let response;
182015
182030
  try {
182016
- response = await fetch(url, { headers: { accept: ACTIVITY_STREAMS_ACCEPT } });
182031
+ const request = new Request(url, { headers: { accept: ACTIVITY_STREAMS_ACCEPT } });
182032
+ response = await fetch(
182033
+ signer === void 0 ? request : await signRequest(request, signer.privateKey, signer.keyId)
182034
+ );
182017
182035
  } catch (error) {
182018
182036
  throw new Error(`${url} could not be fetched: ${messageOf(error)}`, { cause: error });
182019
182037
  }
182038
+ const status = `${String(response.status)} ${response.statusText}`.trim();
182039
+ if (signer !== void 0 && (response.status === 401 || response.status === 403)) {
182040
+ throw new RefusedSignedFetchError(`${url} refused a signed fetch: ${status}`);
182041
+ }
182020
182042
  if (!response.ok) {
182021
- throw new Error(`${url} answered ${String(response.status)} ${response.statusText}`.trim());
182043
+ throw new Error(`${url} answered ${status}`);
182022
182044
  }
182023
182045
  try {
182024
182046
  return await response.json();
@@ -182138,11 +182160,13 @@ function assertPairMatches(privateKey, publicKeyPem) {
182138
182160
  }
182139
182161
  }
182140
182162
  async function privateJwkOf(privateKey) {
182163
+ return await exportJwk(await signingKeyOf(privateKey));
182164
+ }
182165
+ async function signingKeyOf(privateKey) {
182141
182166
  const pkcs8 = privateKey.export({ type: "pkcs8", format: "der" });
182142
- const key = await crypto.subtle.importKey("pkcs8", pkcs8, { name: RSA, hash: "SHA-256" }, true, [
182167
+ return await crypto.subtle.importKey("pkcs8", pkcs8, { name: RSA, hash: "SHA-256" }, true, [
182143
182168
  "sign"
182144
182169
  ]);
182145
- return await exportJwk(key);
182146
182170
  }
182147
182171
  function sameKeyFile(held, incoming) {
182148
182172
  try {
@@ -182297,9 +182321,14 @@ function importSummary(report) {
182297
182321
  for (const failure of followers.failed) {
182298
182322
  lines.push(` skipped ${failure.actor}: ${failure.reason}`);
182299
182323
  }
182300
- if (followers.failed.length > 0) {
182324
+ if (followers.failed.some((failure) => !failure.refused)) {
182325
+ lines.push(
182326
+ " Followers whose servers did not answer were left out. Run this again once their servers answer; nothing already imported is touched twice."
182327
+ );
182328
+ }
182329
+ if (followers.failed.some((failure) => failure.refused)) {
182301
182330
  lines.push(
182302
- " Those followers were left out. Run this again once their servers answer; nothing already imported is touched twice."
182331
+ " Followers whose servers refused a fetch signed with the imported key were left out, and running this again will not bring them across. A --followers file that holds their actor documents will."
182303
182332
  );
182304
182333
  }
182305
182334
  }
@@ -182359,12 +182388,14 @@ async function importWordPressContent(options) {
182359
182388
  const files = [];
182360
182389
  const entries = [];
182361
182390
  const comments = [];
182391
+ const posts = [];
182362
182392
  for (const importer of importers) {
182363
182393
  const output = await importer.import(exported, context2);
182364
182394
  files.push(...output.files);
182365
182395
  rows.push(...output.notes);
182366
182396
  entries.push(...output.entries ?? []);
182367
182397
  comments.push(...output.comments ?? []);
182398
+ posts.push(...output.posts ?? []);
182368
182399
  }
182369
182400
  const record = readRecord(data);
182370
182401
  const seen = /* @__PURE__ */ new Set();
@@ -182391,8 +182422,10 @@ async function importWordPressContent(options) {
182391
182422
  for (const [permalink, onPost] of byPost) {
182392
182423
  rows.push(...await writeComments(context2.site, permalink, onPost, record, data));
182393
182424
  }
182425
+ rows.push(...await pruneComments(context2.site, byPost, posts, record, data));
182394
182426
  const order = new Map(exported.items.map((item, index) => [item, index]));
182395
- rows.sort((a4, b2) => (order.get(a4.item) ?? 0) - (order.get(b2.item) ?? 0));
182427
+ const at = (row) => row.item === void 0 ? exported.items.length : order.get(row.item) ?? 0;
182428
+ rows.sort((a4, b2) => at(a4) - at(b2));
182396
182429
  return { rows };
182397
182430
  }
182398
182431
  function readRecord(data) {
@@ -182404,7 +182437,9 @@ function readRecord(data) {
182404
182437
  return {
182405
182438
  files: new Map(Object.entries(parsed.files ?? {})),
182406
182439
  entries: nested(parsed.entries),
182407
- comments: nested(parsed.comments)
182440
+ comments: nested(parsed.comments),
182441
+ commentPosts: new Map(Object.entries(parsed.commentPosts ?? {})),
182442
+ commentWordPressIds: nested(parsed.commentWordPressIds)
182408
182443
  };
182409
182444
  }
182410
182445
  async function saveRecord(data, record) {
@@ -182415,6 +182450,10 @@ async function saveRecord(data, record) {
182415
182450
  const saved = { files: sorted(record.files) };
182416
182451
  if (record.entries.size > 0) saved.entries = nested(record.entries);
182417
182452
  if (record.comments.size > 0) saved.comments = nested(record.comments);
182453
+ if (record.commentPosts.size > 0) saved.commentPosts = sorted(record.commentPosts);
182454
+ if (record.commentWordPressIds.size > 0) {
182455
+ saved.commentWordPressIds = nested(record.commentWordPressIds);
182456
+ }
182418
182457
  await data.update(IMPORT_RECORD_FILE, () => `${JSON.stringify(saved, null, 2)}
182419
182458
  `);
182420
182459
  }
@@ -182512,7 +182551,8 @@ async function writeComments(site, permalink, comments, record, data) {
182512
182551
  const { recorded, carried } = carryOver(record.comments.get(held.file), comments, byId);
182513
182552
  const rows = [];
182514
182553
  const writes = [];
182515
- for (const { item, comment, label } of comments) {
182554
+ const wordPressIds = record.commentWordPressIds.get(held.file) ?? /* @__PURE__ */ new Map();
182555
+ for (const { item, comment, wordPressId, label } of comments) {
182516
182556
  const here = byId.get(comment.id);
182517
182557
  const now = here === void 0 ? void 0 : sha256(canonical(here));
182518
182558
  const before = recorded.get(comment.id);
@@ -182534,13 +182574,91 @@ async function writeComments(site, permalink, comments, record, data) {
182534
182574
  why = `${why}; marked migrated, with its origin${comment.user === void 0 ? "" : " and its user"}${comment.actor === void 0 ? "" : " and its actor"}`;
182535
182575
  }
182536
182576
  if (decision.action !== "leave") recorded.set(comment.id, next);
182577
+ if (recorded.has(comment.id)) wordPressIds.set(comment.id, wordPressId);
182537
182578
  rows.push({ outcome: decision.outcome, item, path: held.file, why: `${label}: ${why}` });
182538
182579
  }
182539
182580
  await site.putComments(permalink, writes);
182540
- if (recorded.size > 0) record.comments.set(held.file, recorded);
182581
+ if (recorded.size > 0) {
182582
+ record.comments.set(held.file, recorded);
182583
+ record.commentPosts.set(held.file, permalink);
182584
+ record.commentWordPressIds.set(held.file, wordPressIds);
182585
+ }
182541
182586
  await saveRecord(data, record);
182542
182587
  return rows;
182543
182588
  }
182589
+ async function pruneComments(site, imported, posts, record, data) {
182590
+ const items = new Map(posts.map(({ item, permalink }) => [permalink, item]));
182591
+ const formerIds = new Map(
182592
+ [...imported.values()].flat().map(({ comment, formerId }) => [comment.id, formerId])
182593
+ );
182594
+ let legacyPostsByFile;
182595
+ const rows = [];
182596
+ let changed = false;
182597
+ for (const [file, recorded] of [...record.comments]) {
182598
+ let permalink = record.commentPosts.get(file);
182599
+ if (permalink === void 0) {
182600
+ legacyPostsByFile ??= new Map(
182601
+ posts.map((post) => [site.comments(post.permalink).file, post.permalink])
182602
+ );
182603
+ permalink = legacyPostsByFile.get(file);
182604
+ }
182605
+ if (permalink === void 0) continue;
182606
+ const item = items.get(permalink);
182607
+ const kept = new Set((imported.get(permalink) ?? []).map(({ comment }) => comment.id));
182608
+ const held = new Map(site.comments(permalink).comments.map((comment) => [comment.id, comment]));
182609
+ const wordPressIds = record.commentWordPressIds.get(file);
182610
+ const former = new Map(
182611
+ [...recorded.keys()].filter((entry) => !isKey(entry)).map((entry) => [repliesKey(entry), entry])
182612
+ );
182613
+ for (const [entry, before] of [...recorded]) {
182614
+ const id = keyOfRecorded(entry);
182615
+ if (kept.has(id)) continue;
182616
+ const forget = () => {
182617
+ recorded.delete(entry);
182618
+ wordPressIds?.delete(entry);
182619
+ changed = true;
182620
+ };
182621
+ const here = held.get(id);
182622
+ if (here === void 0) {
182623
+ forget();
182624
+ continue;
182625
+ }
182626
+ const asWritten = isKey(entry) ? here : {
182627
+ ...here,
182628
+ id: entry,
182629
+ inReplyTo: here.inReplyTo === null ? null : former.get(here.inReplyTo) ?? formerIds.get(here.inReplyTo) ?? here.inReplyTo
182630
+ };
182631
+ const wordPressId = wordPressIds?.get(entry) ?? /#comment-(\d+)$/.exec(entry)?.[1];
182632
+ const label = `${wordPressId === void 0 ? `comment with key ${id}` : `comment ${String(wordPressId)}`}, a ${here.kind} by ${here.author.name}`;
182633
+ const where = item === void 0 ? `on ${permalink}, which this export no longer imports; ` : "";
182634
+ const gone = "no longer on WordPress, or spam or trash there";
182635
+ if (sha256(canonical(asWritten)) === before) {
182636
+ await site.removeComment(id);
182637
+ forget();
182638
+ rows.push({
182639
+ outcome: "removed",
182640
+ item,
182641
+ path: file,
182642
+ why: `${label}: ${where}${gone}; removed`
182643
+ });
182644
+ } else {
182645
+ rows.push({
182646
+ outcome: "kept",
182647
+ item,
182648
+ path: file,
182649
+ why: `${label}: ${where}${gone}, but edited on this site; left alone`
182650
+ });
182651
+ }
182652
+ }
182653
+ if (recorded.size === 0) {
182654
+ record.comments.delete(file);
182655
+ record.commentPosts.delete(file);
182656
+ record.commentWordPressIds.delete(file);
182657
+ }
182658
+ }
182659
+ if (changed) await saveRecord(data, record);
182660
+ return rows;
182661
+ }
182544
182662
  function carryOver(saved, comments, held) {
182545
182663
  const recorded = new Map(saved);
182546
182664
  const carried = /* @__PURE__ */ new Set();
@@ -182587,6 +182705,9 @@ async function readIfPresent(file) {
182587
182705
  function sha256(contents) {
182588
182706
  return createHash2("sha256").update(contents).digest("hex");
182589
182707
  }
182708
+ function keyOfRecorded(entry) {
182709
+ return isKey(entry) ? entry : repliesKey(entry);
182710
+ }
182590
182711
 
182591
182712
  // src/media.ts
182592
182713
  var WORDPRESS_UPLOADS = "/wp-content/uploads/";
@@ -182681,6 +182802,11 @@ function decoded(text3) {
182681
182802
  var import_turndown = __toESM(require_turndown_cjs(), 1);
182682
182803
  function convertBody(content) {
182683
182804
  let html = content.replace(/\r\n?/g, "\n");
182805
+ let contact = false;
182806
+ html = html.replace(JETPACK_CONTACT_FORM, () => {
182807
+ contact = true;
182808
+ return "";
182809
+ });
182684
182810
  let inReplyTo;
182685
182811
  html = html.replace(
182686
182812
  /<!--\s+wp:activitypub\/reply\s+(\{[\s\S]*?\})\s+\/-->/g,
@@ -182705,8 +182831,9 @@ function convertBody(content) {
182705
182831
  `);
182706
182832
  if (!blocks) html = wpautop(html);
182707
182833
  const markdown = tidy(turndown.turndown(html));
182708
- return { markdown, ...inReplyTo === void 0 ? {} : { inReplyTo } };
182834
+ return { markdown, contact, ...inReplyTo === void 0 ? {} : { inReplyTo } };
182709
182835
  }
182836
+ var JETPACK_CONTACT_FORM = /\[contact-form(?=[\s/\]])[^\]]*?(?:\/\]|\][\s\S]*?\[\/contact-form\])/g;
182710
182837
  function tidy(markdown) {
182711
182838
  const lines = [];
182712
182839
  let fence;
@@ -183075,11 +183202,19 @@ function importPostsAndPages(exported, context2) {
183075
183202
  });
183076
183203
  }
183077
183204
  const body = convertBody(item.content);
183205
+ if (body.contact && item.type !== "page") {
183206
+ notes.push({
183207
+ item,
183208
+ outcome: "warned",
183209
+ why: "had a Jetpack contact form, which was dropped, since only pages offer the contact form"
183210
+ });
183211
+ }
183078
183212
  const document2 = documentOf(item, disposition, {
183079
183213
  permalink,
183080
183214
  formerly: formerPermalinks(item, permalink),
183081
183215
  author,
183082
183216
  inReplyTo: body.inReplyTo,
183217
+ contact: body.contact,
183083
183218
  home,
183084
183219
  body: media.rewrite(body.markdown)
183085
183220
  });
@@ -183238,6 +183373,7 @@ function documentOf(item, disposition, derived) {
183238
183373
  const extra = {};
183239
183374
  if (guid !== void 0) extra["guid"] = guid;
183240
183375
  if (disposition.migrated) extra["migrated"] = true;
183376
+ if (derived.contact && item.type === "page") extra["contact"] = true;
183241
183377
  return {
183242
183378
  title,
183243
183379
  ...date === void 0 ? {} : { date },
@@ -183290,6 +183426,7 @@ function importComments(exported, context2) {
183290
183426
  for (const placement of placements(exported)) {
183291
183427
  if ("permalink" in placement) permalinks.set(placement.item, placement.permalink);
183292
183428
  }
183429
+ const posts = [...permalinks].map(([item, permalink]) => ({ item, permalink }));
183293
183430
  const usernames = new Set(context2.site.users().map((user) => user.username));
183294
183431
  const users = new Map(
183295
183432
  exported.authors.filter((author) => usernames.has(author.login)).map((author) => [author.id, author.login])
@@ -183311,7 +183448,7 @@ function importComments(exported, context2) {
183311
183448
  notes.push(...mapped.notes);
183312
183449
  comments.push(...mapped.comments);
183313
183450
  }
183314
- return { files: [], notes, comments };
183451
+ return { files: [], notes, comments, posts };
183315
183452
  }
183316
183453
  function mapComments(item, permalink, markdownOf, users, actors) {
183317
183454
  const notes = [];
@@ -183364,7 +183501,7 @@ function mapComments(item, permalink, markdownOf, users, actors) {
183364
183501
  kept.filter(({ comment }) => comment.kind === "reply").map(({ wordPress, comment }) => [wordPress.id, comment.id])
183365
183502
  );
183366
183503
  const comments = kept.map(({ wordPress, comment, formerId, label }) => {
183367
- const imported = { item, permalink, formerId, label };
183504
+ const imported = { item, permalink, formerId, wordPressId: wordPress.id, label };
183368
183505
  const { parent } = wordPress;
183369
183506
  if (parent === 0) return { ...imported, comment };
183370
183507
  const inReplyTo = replies.get(parent);
@@ -184273,6 +184410,7 @@ async function readExport(given, file) {
184273
184410
  var OUTCOMES = [
184274
184411
  "written",
184275
184412
  "unchanged",
184413
+ "removed",
184276
184414
  "kept",
184277
184415
  "conflict",
184278
184416
  "clash",
@@ -184287,7 +184425,7 @@ function formatReport(given, contentDir, report) {
184287
184425
  };
184288
184426
  const outcomes = count(report.rows.map((row) => row.outcome));
184289
184427
  const skippedTypes = count(
184290
- report.rows.filter((row) => row.outcome === "skipped").map((row) => row.item.type)
184428
+ report.rows.filter((row) => row.outcome === "skipped").map((row) => row.item?.type ?? "")
184291
184429
  );
184292
184430
  const lines = [
184293
184431
  `Imported ${given} into ${contentDir}`,
@@ -184308,9 +184446,9 @@ function formatReport(given, contentDir, report) {
184308
184446
  lines.push(
184309
184447
  [
184310
184448
  row.outcome,
184311
- row.item.type,
184312
- String(row.item.id),
184313
- row.item.title.replace(/\s+/g, " "),
184449
+ row.item?.type ?? "",
184450
+ row.item === void 0 ? "" : String(row.item.id),
184451
+ row.item?.title.replace(/\s+/g, " ") ?? "",
184314
184452
  row.path ?? "",
184315
184453
  row.why
184316
184454
  ].join(" ")
@@ -184519,7 +184657,7 @@ function wordPressScreen(records) {
184519
184657
  }
184520
184658
 
184521
184659
  // src/version.ts
184522
- var VERSION2 = "0.5.0";
184660
+ var VERSION2 = "0.6.1";
184523
184661
 
184524
184662
  // src/index.ts
184525
184663
  var index_default = definePlugin({
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@geekity/plugin-wordpress",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "hostApi": 2,
5
5
  "peerDependencies": {
6
- "@geekity/cms": ">=0.32.0 <1.0.0"
6
+ "@geekity/cms": ">=0.34.0 <1.0.0"
7
7
  }
8
8
  }
package/dist/command.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { PluginCommand } from '@geekity/cms/plugin';
2
+ import type { ImportWordPressActorReport } from './import.ts';
2
3
  import type { WordPressRecords } from './records.ts';
3
4
  /**
4
5
  * `geekity import wordpress-actor <username>`: the cutover, for one person.
@@ -14,4 +15,6 @@ import type { WordPressRecords } from './records.ts';
14
15
  * comes first.
15
16
  */
16
17
  export declare function importCommand(records: WordPressRecords): PluginCommand;
18
+ /** What the run did, as the operator reads it. */
19
+ export declare function importSummary(report: ImportWordPressActorReport): string;
17
20
  //# sourceMappingURL=command.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAwB,MAAM,qBAAqB,CAAC;AAK/E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,CAkDtE"}
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAwB,MAAM,qBAAqB,CAAC;AAG/E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa,CAkDtE;AAqHD,kDAAkD;AAClD,wBAAgB,aAAa,CAAC,MAAM,EAAE,0BAA0B,GAAG,MAAM,CA4CxE"}
package/dist/command.js CHANGED
@@ -152,7 +152,7 @@ function followersSource(context) {
152
152
  return isAbsoluteHttpUrl(given) ? given : path.resolve(context.cwd, given);
153
153
  }
154
154
  /** What the run did, as the operator reads it. */
155
- function importSummary(report) {
155
+ export function importSummary(report) {
156
156
  const lines = [];
157
157
  const { followers } = report;
158
158
  lines.push(report.changed
@@ -174,9 +174,14 @@ function importSummary(report) {
174
174
  for (const failure of followers.failed) {
175
175
  lines.push(` skipped ${failure.actor}: ${failure.reason}`);
176
176
  }
177
- if (followers.failed.length > 0) {
178
- lines.push(' Those followers were left out. Run this again once their servers answer; ' +
179
- 'nothing already imported is touched twice.');
177
+ if (followers.failed.some((failure) => !failure.refused)) {
178
+ lines.push(' Followers whose servers did not answer were left out. Run this again once their ' +
179
+ 'servers answer; nothing already imported is touched twice.');
180
+ }
181
+ if (followers.failed.some((failure) => failure.refused)) {
182
+ lines.push(' Followers whose servers refused a fetch signed with the imported key were left out, ' +
183
+ 'and running this again will not bring them across. A --followers file that holds ' +
184
+ 'their actor documents will.');
180
185
  }
181
186
  }
182
187
  return `${lines.join('\n')}\n`;
@@ -1 +1 @@
1
- {"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../src/command.ts"],"names":[],"mappings":"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"}
@@ -35,6 +35,7 @@ function importComments(exported, context) {
35
35
  if ('permalink' in placement)
36
36
  permalinks.set(placement.item, placement.permalink);
37
37
  }
38
+ const posts = [...permalinks].map(([item, permalink]) => ({ item, permalink }));
38
39
  // Who wrote it signed in: the WordPress user's login, when this site has a
39
40
  // user by that name, the rule a post's author is mapped by.
40
41
  const usernames = new Set(context.site.users().map((user) => user.username));
@@ -61,7 +62,7 @@ function importComments(exported, context) {
61
62
  notes.push(...mapped.notes);
62
63
  comments.push(...mapped.comments);
63
64
  }
64
- return { files: [], notes, comments };
65
+ return { files: [], notes, comments, posts };
65
66
  }
66
67
  function mapComments(item, permalink, markdownOf, users, actors) {
67
68
  const notes = [];
@@ -118,7 +119,7 @@ function mapComments(item, permalink, markdownOf, users, actors) {
118
119
  .filter(({ comment }) => comment.kind === 'reply')
119
120
  .map(({ wordPress, comment }) => [wordPress.id, comment.id]));
120
121
  const comments = kept.map(({ wordPress, comment, formerId, label }) => {
121
- const imported = { item, permalink, formerId, label };
122
+ const imported = { item, permalink, formerId, wordPressId: wordPress.id, label };
122
123
  const { parent } = wordPress;
123
124
  if (parent === 0)
124
125
  return { ...imported, comment };