@contentrain/wp-import 0.16.4 → 0.17.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 +10 -4
- package/dist/index.d.mts +3 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +39 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -77,10 +77,16 @@ models get `i18n: true`, content and meta are written per locale
|
|
|
77
77
|
(`content/{domain}/{model}/{locale}.json`), and every translation in a group
|
|
78
78
|
shares one entry id — the canonical member is the default-locale post (else
|
|
79
79
|
the lowest id), so `entry_source_map[wp_id]` addresses each post by that id
|
|
80
|
-
and its own locale. Locales are primary subtags (`tr_TR` → `tr`).
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
and its own locale. Locales are primary subtags (`tr_TR` → `tr`). A taxonomy
|
|
81
|
+
stays one store-wide model unless its terms carry a language (`RawTerm.lang`,
|
|
82
|
+
from the Bridge): then it is i18n too, and the Bridge's `term_pairs` fold each
|
|
83
|
+
term translation group into one entry id the same way (default-locale term,
|
|
84
|
+
else the lowest id). Every reference to a term — a post's taxonomy field, its
|
|
85
|
+
primary category, an ACF term field, a menu target, a parent — resolves to its
|
|
86
|
+
group's id. The `language` / `post_translations` bookkeeping taxonomies never
|
|
87
|
+
become models. `report.locales`, `report.translation_groups` and
|
|
88
|
+
`report.term_translation_groups` say what happened. A monolingual site is
|
|
89
|
+
unchanged (`i18n: false`, `data.json`).
|
|
84
90
|
|
|
85
91
|
Few sites are translated evenly. A post type whose content exists in some of the
|
|
86
92
|
site's languages gets `model.locales` — the locales it actually has posts in,
|
package/dist/index.d.mts
CHANGED
|
@@ -126,10 +126,12 @@ interface ImportReport {
|
|
|
126
126
|
fields: number;
|
|
127
127
|
entries: number;
|
|
128
128
|
}>;
|
|
129
|
-
/** Default first, then every other language seen on a post. One entry on a monolingual site. */
|
|
129
|
+
/** Default first, then every other language seen on a post or a translated term. One entry on a monolingual site. */
|
|
130
130
|
locales: string[];
|
|
131
131
|
/** Translation groups that were folded into one entry id across locales. */
|
|
132
132
|
translation_groups: number;
|
|
133
|
+
/** Term translation groups (`term_pairs`) folded into one entry id across locales. */
|
|
134
|
+
term_translation_groups: number;
|
|
133
135
|
/**
|
|
134
136
|
* Password-protected posts imported as `draft`, whatever their WordPress
|
|
135
137
|
* status. Their body is the protected text, and nothing downstream (query
|
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;;;;UClHzD,QAAA;EACf,KAAA;EACA,IAAA;EFPuB;EESvB,IAAA;EFLc;EEOd,IAAA;EFVc;;;;EEed,MAAA;AAAA;AAAA,UAkBe,YAAA;EACf,cAAA;EACA,aAAA;EFhCc;EEkCd,UAAA,EAAY,QAAA;EACZ,cAAA;EACA,WAAA,EAAa,MAAA;EACb,UAAA,EAAY,MAAA;EFjCZ;EEmCA,WAAA,EAAa,MAAA;EFlCb;EEoCA,mBAAA,EAAqB,MAAA;EFpCN;EEsCf,mBAAA,EAAqB,MAAA;EFrBD;EEuBpB,oBAAA;;EAEA,iBAAA,EAAmB,MAAA;EFzBuE;EE2B1F,sBAAA,EAAwB,MAAA;EACxB,aAAA;EACA,iBAAA;EACA,MAAA,EAAQ,MAAA;IAAiB,IAAA;IAAc,MAAA;IAAgB,MAAA;IAAgB,OAAA;EAAA;EF9BiC;EEgCxG,OAAA;;EAEA,kBAAA;;
|
|
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
|
@@ -2233,7 +2233,9 @@ function rawToContentrain(input, opts) {
|
|
|
2233
2233
|
const localeContents = {};
|
|
2234
2234
|
const localeMetas = {};
|
|
2235
2235
|
const postLocale = (p) => normLocale(p.lang ?? p.terms.find((t) => t.taxonomy === "language")?.slug) || locale;
|
|
2236
|
-
const
|
|
2236
|
+
const termLocale = (t) => normLocale(t.lang) || locale;
|
|
2237
|
+
const termLocales = raw.terms.filter((t) => t.lang && !LANGUAGE_TAXONOMIES.has(t.taxonomy)).map(termLocale);
|
|
2238
|
+
const locales = [locale, ...[...new Set([...raw.posts.filter((p) => !SKIP_TYPES.test(p.type)).map(postLocale), ...termLocales])].filter((l) => l !== locale).toSorted()];
|
|
2237
2239
|
const multilingual = locales.length > 1;
|
|
2238
2240
|
const postById = new Map(raw.posts.map((p) => [p.id, p]));
|
|
2239
2241
|
const canonicalOf = /* @__PURE__ */ new Map();
|
|
@@ -2267,6 +2269,7 @@ function rawToContentrain(input, opts) {
|
|
|
2267
2269
|
models: {},
|
|
2268
2270
|
locales,
|
|
2269
2271
|
translation_groups: translationGroups,
|
|
2272
|
+
term_translation_groups: 0,
|
|
2270
2273
|
password_protected_drafts: 0,
|
|
2271
2274
|
site_title_missing: false
|
|
2272
2275
|
};
|
|
@@ -2291,6 +2294,19 @@ function rawToContentrain(input, opts) {
|
|
|
2291
2294
|
};
|
|
2292
2295
|
const authorId = (login) => hexId(`authors:${login}`);
|
|
2293
2296
|
const termId = (tax, slug) => hexId(`${tax}:${slug}`);
|
|
2297
|
+
const termByWpId = new Map(raw.terms.filter((t) => t.id !== null).map((t) => [t.id, t]));
|
|
2298
|
+
const canonicalTermSlug = /* @__PURE__ */ new Map();
|
|
2299
|
+
for (const pair of raw.term_pairs ?? []) {
|
|
2300
|
+
const members = [...new Set(Object.values(pair.translations))].map((id) => termByWpId.get(id)).filter((t) => t !== void 0 && t.taxonomy === pair.taxonomy);
|
|
2301
|
+
if (members.length < 2 || new Set(members.map(termLocale)).size !== members.length) continue;
|
|
2302
|
+
const canonical = members.find((t) => termLocale(t) === locale) ?? members.reduce((a, b) => a.id <= b.id ? a : b);
|
|
2303
|
+
for (const t of members) canonicalTermSlug.set(`${t.taxonomy}:${t.slug}`, canonical.slug);
|
|
2304
|
+
report.term_translation_groups++;
|
|
2305
|
+
}
|
|
2306
|
+
/** The entry id a reference to a term resolves to: its group's canonical member's. */
|
|
2307
|
+
const termRef = (tax, slug) => termId(tax, canonicalTermSlug.get(`${tax}:${slug}`) ?? slug);
|
|
2308
|
+
const i18nTaxonomies = new Set(multilingual ? raw.terms.filter((t) => t.lang).map((t) => t.taxonomy) : []);
|
|
2309
|
+
const termExists = (mid, id) => contents[mid]?.[id] !== void 0 || Object.values(localeContents[mid] ?? {}).some((bucket) => bucket[id] !== void 0);
|
|
2294
2310
|
const usedSlugs = /* @__PURE__ */ new Map();
|
|
2295
2311
|
const postSlug = (p) => {
|
|
2296
2312
|
let s = addressSlug(p.slug);
|
|
@@ -2378,7 +2394,7 @@ function rawToContentrain(input, opts) {
|
|
|
2378
2394
|
const t = termById.get(id);
|
|
2379
2395
|
return t && models[taxModelId(t.taxonomy)] ? {
|
|
2380
2396
|
model: taxModelId(t.taxonomy),
|
|
2381
|
-
ref:
|
|
2397
|
+
ref: termRef(t.taxonomy, t.slug)
|
|
2382
2398
|
} : null;
|
|
2383
2399
|
}
|
|
2384
2400
|
return null;
|
|
@@ -2548,12 +2564,15 @@ function rawToContentrain(input, opts) {
|
|
|
2548
2564
|
const taxonomies = [...new Set(raw.terms.map((t) => t.taxonomy))].filter((t) => t !== "nav_menu" && t !== "post_format" && !LANGUAGE_TAXONOMIES.has(t));
|
|
2549
2565
|
for (const tax of taxonomies) {
|
|
2550
2566
|
const mid = taxModelId(tax);
|
|
2567
|
+
const i18n = i18nTaxonomies.has(tax);
|
|
2568
|
+
const covered = locales.filter((l) => l === locale || raw.terms.some((t) => t.taxonomy === tax && termLocale(t) === l));
|
|
2551
2569
|
addModel({
|
|
2552
2570
|
id: mid,
|
|
2553
2571
|
name: mid,
|
|
2554
2572
|
kind: "collection",
|
|
2555
2573
|
domain: "blog",
|
|
2556
|
-
i18n
|
|
2574
|
+
i18n,
|
|
2575
|
+
...i18n && covered.length < locales.length ? { locales: covered } : {},
|
|
2557
2576
|
title_field: "name",
|
|
2558
2577
|
fields: {
|
|
2559
2578
|
name: {
|
|
@@ -2588,12 +2607,15 @@ function rawToContentrain(input, opts) {
|
|
|
2588
2607
|
}
|
|
2589
2608
|
});
|
|
2590
2609
|
for (const t of raw.terms.filter((x) => x.taxonomy === tax)) {
|
|
2591
|
-
const id =
|
|
2592
|
-
|
|
2610
|
+
const id = termRef(tax, t.slug);
|
|
2611
|
+
const loc = termLocale(t);
|
|
2612
|
+
const content = i18n ? (localeContents[mid] ??= {})[loc] ??= {} : contents[mid];
|
|
2613
|
+
const meta = i18n ? (localeMetas[mid] ??= {})[loc] ??= {} : metas[mid];
|
|
2614
|
+
content[id] = pick({
|
|
2593
2615
|
name: strip(t.name),
|
|
2594
2616
|
slug: addressSlug(t.slug) || `term-${t.id}`,
|
|
2595
2617
|
description: strip(t.description),
|
|
2596
|
-
parent: t.parent && t.parent_resolved ?
|
|
2618
|
+
parent: t.parent && t.parent_resolved ? termRef(tax, t.parent) : null,
|
|
2597
2619
|
wp_id: t.id
|
|
2598
2620
|
}, new Set([
|
|
2599
2621
|
"name",
|
|
@@ -2602,19 +2624,22 @@ function rawToContentrain(input, opts) {
|
|
|
2602
2624
|
"parent",
|
|
2603
2625
|
"wp_id"
|
|
2604
2626
|
]));
|
|
2605
|
-
|
|
2627
|
+
meta[id] = importMeta("published");
|
|
2606
2628
|
}
|
|
2607
2629
|
}
|
|
2608
2630
|
for (const p of raw.posts) for (const t of p.terms) {
|
|
2609
2631
|
if (t.taxonomy === "nav_menu" || t.taxonomy === "post_format" || t.resolved) continue;
|
|
2610
2632
|
const mid = taxModelId(t.taxonomy);
|
|
2611
2633
|
if (!models[mid]) continue;
|
|
2612
|
-
const id =
|
|
2613
|
-
|
|
2634
|
+
const id = termRef(t.taxonomy, t.slug);
|
|
2635
|
+
if (termExists(mid, id)) continue;
|
|
2636
|
+
const content = models[mid].i18n ? (localeContents[mid] ??= {})[locale] ??= {} : contents[mid];
|
|
2637
|
+
const meta = models[mid].i18n ? (localeMetas[mid] ??= {})[locale] ??= {} : metas[mid];
|
|
2638
|
+
content[id] = {
|
|
2614
2639
|
name: strip(t.name),
|
|
2615
2640
|
slug: addressSlug(t.slug) || `term-${hexId(`${t.taxonomy}:${t.slug}`).slice(0, 8)}`
|
|
2616
2641
|
};
|
|
2617
|
-
|
|
2642
|
+
meta[id] = importMeta("published");
|
|
2618
2643
|
}
|
|
2619
2644
|
const postTypes = [...new Set(raw.posts.map((p) => p.type))].filter((t) => {
|
|
2620
2645
|
if (SKIP_TYPES.test(t)) {
|
|
@@ -2886,7 +2911,7 @@ function rawToContentrain(input, opts) {
|
|
|
2886
2911
|
if (p.modified) e.modified_at = p.modified;
|
|
2887
2912
|
if (p.link) e.link = p.link;
|
|
2888
2913
|
if (fields.author && p.author) e.author = authorId(slugify(p.author));
|
|
2889
|
-
for (const t of taxes) e[taxModelId(t)] = p.terms.filter((x) => x.taxonomy === t &&
|
|
2914
|
+
for (const t of taxes) e[taxModelId(t)] = p.terms.filter((x) => x.taxonomy === t && termExists(taxModelId(t), termRef(t, x.slug))).map((x) => termRef(t, x.slug));
|
|
2890
2915
|
if (fields.cover && p.meta._thumbnail_id) {
|
|
2891
2916
|
const m = mediaRef(Number(p.meta._thumbnail_id));
|
|
2892
2917
|
if (m) e.cover = m;
|
|
@@ -2902,9 +2927,9 @@ function rawToContentrain(input, opts) {
|
|
|
2902
2927
|
if (fields.primary_category) {
|
|
2903
2928
|
const termWpId = primaryCategoryId(p);
|
|
2904
2929
|
const term = termWpId === void 0 ? void 0 : termById.get(termWpId);
|
|
2905
|
-
const ref = term && term.taxonomy === "category" ?
|
|
2930
|
+
const ref = term && term.taxonomy === "category" ? termRef("category", term.slug) : void 0;
|
|
2906
2931
|
const assigned = ref !== void 0 && Array.isArray(e[taxModelId("category")]) && e[taxModelId("category")].includes(ref);
|
|
2907
|
-
if (ref && assigned &&
|
|
2932
|
+
if (ref && assigned && termExists(taxModelId("category"), ref)) e.primary_category = ref;
|
|
2908
2933
|
else if (termWpId !== void 0) report.dropped_relations++;
|
|
2909
2934
|
}
|
|
2910
2935
|
if (fields.template && typeof p.meta._wp_page_template === "string" && p.meta._wp_page_template !== "default") e.template = p.meta._wp_page_template;
|
|
@@ -3087,7 +3112,7 @@ function rawToContentrain(input, opts) {
|
|
|
3087
3112
|
}
|
|
3088
3113
|
if (i.target.kind === "term" && i.target.resolved && i.target.slug && models[taxModelId(i.target.taxonomy)]) e.target = toTarget.ref({
|
|
3089
3114
|
model: taxModelId(i.target.taxonomy),
|
|
3090
|
-
ref:
|
|
3115
|
+
ref: termRef(i.target.taxonomy, i.target.slug)
|
|
3091
3116
|
});
|
|
3092
3117
|
if (i.classes?.length) e.classes = i.classes;
|
|
3093
3118
|
if (i.description) e.description = strip(i.description);
|