@contentrain/wp-import 0.7.0 → 0.9.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 CHANGED
@@ -120,6 +120,14 @@ block refers to it; an empty navigation block without a `ref` shows the most
120
120
  recent published one, as WordPress does. Block menu items have no WordPress id
121
121
  and get negative ids; the store claims no `wp_id` for them.
122
122
 
123
+ A navigation block in a template part that carries its own links (an inline
124
+ navigation, as in Twenty Twenty-Five's footer columns) is a menu of that part's
125
+ area: `Footer navigation 1`, `2`, … (its `ariaLabel` names it when set), links
126
+ in order and nested. Only template parts a template uses count — a theme ships
127
+ alternatives (`footer-columns`, `header-large-title`) that no page shows; without
128
+ the templates, the part named after its area (`header`, `footer`). A `#` link
129
+ stays `#`. Inline menus have no WordPress record: negative ids, no `wp_id`.
130
+
123
131
  A menu item that is itself a draft, or whose post target is not proven public
124
132
  — a draft, pending, private, scheduled or password-protected post, or one this
125
133
  import never read (a type outside REST, a listing past a page cap) — is left
@@ -132,6 +140,104 @@ contains `menus_require_auth` — an empty menu list is never presented as the
132
140
  site having none. The `menus` model gains a `locations` field only when the
133
141
  source named them.
134
142
 
143
+ A menu item that names a public post or term links to that post's or term's
144
+ public address (its REST `link`). The address the item stored is not used: a
145
+ block keeps the URL it had when it was saved, and a hand-typed `?page_id=` is a
146
+ form the migrated site cannot serve. A hand-typed `?page_id=` / `?p=` counts
147
+ as this site's with or without a leading `www.`.
148
+
149
+ ### Redirects over REST
150
+
151
+ REST reads one source of redirects: the Redirection plugin (`redirection/v1`).
152
+ This needs an application password of a user who may manage the plugin. Its
153
+ rules are shaped as the Bridge shapes them. Each rule lands in exactly one of
154
+ two places:
155
+
156
+ - `redirects`: the rules the site serves, with the plugin's query, case and
157
+ trailing-slash modes. A "gone" rule (410, 451) is served with an empty `to`.
158
+ - `redirects_excluded`: every other rule, with its reason (disabled,
159
+ conditional, a 404 or pass-through action).
160
+
161
+ Yoast Premium, Rank Math, Safe Redirect Manager and `.htaccess` keep their
162
+ rules where only the Bridge export reads them. So `gaps` always contains
163
+ `redirects_partial`. It also contains `redirects_require_auth` when the site
164
+ runs Redirection but its rules could not be read with the credential given.
165
+
166
+ A conditional rule (login, cookie, header, IP, role…) is excluded. Only a login
167
+ rule keeps its `condition`, which is its two addresses. Any other condition
168
+ holds the value a visitor must present, often a secret, so it is never
169
+ exported; the reason names its type.
170
+
171
+ Each attachment carries its attachment page as `link`, so the migrated site
172
+ can redirect it. The link is kept only when the attachment has no parent or
173
+ its parent is proven public, because the page sits under the parent's address
174
+ and would otherwise carry a draft's, a private post's or a scheduled post's
175
+ slug.
176
+
177
+ ### ACF fields, custom post types and taxonomies over REST
178
+
179
+ ACF / Secure Custom Fields values arrive on a post's `acf` key — only for field
180
+ groups set to "Show in REST API" (off by default). Each field is typed by one
181
+ versioned table (`ACF_MAPPING_VERSION`, exported with `ACF_SCALAR_TYPES` and
182
+ `ACF_REFERENCE_TYPES`): the ACF type is read from SCF's `<name>_source.type`
183
+ where the site states it, and inferred from the value's shape only when nothing
184
+ states it (the field description then says so).
185
+
186
+ | ACF | Contentrain |
187
+ | --- | --- |
188
+ | text, time picker | `string` |
189
+ | textarea | `text` |
190
+ | wysiwyg | `richtext` |
191
+ | email / url, oembed / number, range / true false | `email` / `url` / `number` / `boolean` |
192
+ | date picker / date time picker | `date` / `datetime` (ISO, with the site's offset) |
193
+ | color picker / icon picker | `color` / `icon` |
194
+ | select, radio, button group | `select` (its choices) |
195
+ | checkbox, multiple select | `array` of `select` |
196
+ | image / file | `image` / `file` (the URL) |
197
+ | link | `object { url, title, target }` |
198
+ | google map | `object { address, lat, lng, zoom }` |
199
+ | group | `object` of its fields |
200
+ | repeater | `array` of `object` (nested repeaters nest) |
201
+ | flexible content | `array` of `object`: a required `layout` select plus the union of the layouts' fields |
202
+ | post object, relationship | `relation` / `relations` to the entries' models |
203
+ | taxonomy / user / gallery | `relations` to the term model / `authors` / media |
204
+ | page link | `url`: the target's address, only when the target is published and unprotected |
205
+ | tab, accordion, message | nothing (layout only) |
206
+ | password | nothing, ever |
207
+
208
+ Sub-fields of a repeater, group or flexible layout are typed by the same table
209
+ when the site states their type (SCF's `_source` inside each row); a reference
210
+ inside a row, and a sub-field with no stated type, are typed from the value. A
211
+ select or checkbox value outside the field's stated choices is left out and
212
+ counted in the report's `acf_outside_choices`. A date time picker's value is written
213
+ with the site's UTC offset for that moment, DST included (the `/wp-json/`
214
+ index's `timezone_string`, else `gmt_offset`); with neither it stays local and
215
+ `acf_datetime_unzoned` counts it. `src/fixtures/acf-parity.json`
216
+ holds the cases the Contentrain Bridge must map the same way.
217
+
218
+ **A password field is never read** — at any depth: a password sub-field of a
219
+ repeater row, a group or a flexible layout is removed with its `_source` before
220
+ the value reaches `RawIR`. Where the source states the type, the type decides;
221
+ where it does not (plain ACF, no `<name>_source`), a field whose name has a
222
+ secret word in it (`password`, `user_pass`, `apiKey`, `access_token`, …; whole
223
+ words, so `passage` stays) is skipped instead. It never reaches `RawIR`, the
224
+ store, or a report.
225
+
226
+ ACF values follow their post: a draft's fields land in the store with the
227
+ draft (meta `status: draft`), like its body. A reference to an entry the import
228
+ did not read is dropped and counted in `dropped_relations`. The report's
229
+ `acf_fields` lists each field's type. When any post carries an `acf` key, the
230
+ result's `gaps` contains `acf_partial`: groups without REST exposure, options
231
+ pages and fields on post types outside REST are not visible to REST — the
232
+ Bridge reads those.
233
+
234
+ With an Application Password, post types are read with `context=edit` so their
235
+ `viewable` flag is known: a type that is in REST but not publicly queryable (a
236
+ testimonial post type, say) keeps its content but gets no address (`link` is
237
+ null), so no route or redirect claims a page that does not exist. Custom
238
+ taxonomies in REST are read with their terms, and a post's terms in them become
239
+ its relations.
240
+
135
241
 
136
242
  ### Publication and translation identity
137
243
 
package/dist/index.d.mts CHANGED
@@ -71,6 +71,13 @@ interface RestImportResult {
71
71
  * What this rung could not read, as codes a caller can act on (the text is in `warnings`).
72
72
  * `menus_require_auth`: menus and block navigation are only readable with an application password
73
73
  * of a user who may edit theme options — none was given, the site rejected it, or it lacks that right.
74
+ * `redirects_partial`: always, over REST — it reads only the Redirection plugin's rules; Yoast Premium, Rank Math,
75
+ * Safe Redirect Manager and `.htaccess` keep theirs where only the Bridge export reads them.
76
+ * `redirects_require_auth`: the site runs Redirection, and its rules need an application password of a user who
77
+ * may manage it — none was given, the site rejected it, or it lacks that right.
78
+ * `acf_partial`: the site runs ACF / Secure Custom Fields; REST shows only the field groups set to
79
+ * `show_in_rest` (off by default) and no options page — the Bridge export reads the rest. Where the site
80
+ * states no field types (plain ACF, no `<name>_source`), a secret field is recognised by its name only.
74
81
  */
75
82
  gaps: string[];
76
83
  }
@@ -83,6 +90,10 @@ interface ImportReport {
83
90
  title_fallback: number;
84
91
  meta_fields: Record<string, string>;
85
92
  acf_fields: Record<string, string>;
93
+ /** ACF select/checkbox values outside their field's stated choices, left out (`field: count`). */
94
+ acf_outside_choices: Record<string, number>;
95
+ /** ACF date-times written without a zone because the source named none (`timezone_string` / `gmt_offset`). */
96
+ acf_datetime_unzoned: number;
86
97
  skipped_types: string[];
87
98
  dropped_relations: number;
88
99
  models: Record<string, {
@@ -102,6 +113,11 @@ interface ImportReport {
102
113
  * put that text on a public site. Publish only after deciding what to show.
103
114
  */
104
115
  password_protected_drafts: number;
116
+ /**
117
+ * The source named no site title (no REST index name, no WXR channel title): the `site` entry has no
118
+ * `title`. The field stays required, so the store says what is missing rather than inventing a name.
119
+ */
120
+ site_title_missing: boolean;
105
121
  }
106
122
  interface ContentrainResult {
107
123
  files: Record<string, string>;
@@ -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;;;UCrC3E,iBAAA;EACf,MAAA;;EAEA,SAAA,UAAmB,KAAA;EDQI;;;;;;;;ECCvB,IAAA;IAAS,IAAA;IAAc,WAAA;EAAA;EACvB,OAAA;EDEc;AAGhB;;;;ECCE,WAAA;EDAK;;;;ECKL,QAAA;EACA,IAAA;AAAA;AAAA,UAGe,gBAAA;EACf,GAAA,EAAK,KAAA;EACL,QAAA;EDOkF;;;;;;;;ECElF,UAAA;IAAc,MAAA;IAA0C,SAAA;EAAA;;;AAvC1D;;;EA6CE,IAAA;AAAA;AAAA,iBAkDoB,cAAA,CAAe,OAAA,EAAS,iBAAA,GAAoB,OAAA,CAAQ,gBAAA;;;UCpFzD,YAAA;EACf,cAAA;EACA,aAAA;EACA,cAAA;EACA,WAAA,EAAa,MAAA;EACb,UAAA,EAAY,MAAA;EACZ,aAAA;EACA,iBAAA;EACA,MAAA,EAAQ,MAAA;IAAiB,IAAA;IAAc,MAAA;IAAgB,MAAA;IAAgB,OAAA;EAAA;EFJvE;EEMA,OAAA;EFNc;EEQd,kBAAA;EFLe;;;;;;EEYf,yBAAA;AAAA;AAAA,UAGe,iBAAA;EACf,KAAA,EAAO,MAAA;EACP,gBAAA,EAAkB,cAAA;EAClB,MAAA,EAAQ,YAAA;AAAA;AAAA,iBAoCM,gBAAA,CAAiB,GAAA,EAAK,KAAA,EAAO,IAAA;EAAS,SAAA;AAAA,IAAuB,iBAAA;;;;;;AF7D7E;;;iBGbgB,cAAA,CAAe,GAAA,EAAK,KAAA;EAAU,QAAA,EAAU,UAAA;EAAc,QAAA,EAAU,WAAA,CAAY,cAAA;AAAA;AAAA,iBAgB5E,mBAAA,CAAoB,GAAA,EAAK,KAAA,EAAO,OAAA,EAAS,cAAA,EAAgB,IAAA;EAAS,YAAA;AAAA,IAA0B,cAAA;;iBAiB5F,iBAAA,CAAkB,GAAA,EAAK,cAAA,GAAiB,eAAA;;;UC3CvC,iBAAA;EACf,EAAA;EACA,UAAA;EACA,KAAA;EACA,KAAA;AAAA;AAAA,iBAGc,eAAA,CAAgB,CAAA,YAAa,CAAA;AAAA,iBAI7B,cAAA,CAAe,GAAA;;iBAyFf,cAAA,CAAe,CAAA,WAAY,iBAAA;;;cC9F9B,KAAA,GAAS,CAAA;;cAST,KAAA,GAAS,CAAA;;cAcT,KAAA,GAAS,CAAA;;;;;;;;;ALCtB;cK8Ba,UAAA,EAAU,MAAA;;cAIV,WAAA,EAAW,MAAA;;cAOX,UAAA,GAAc,CAAA;AAAA,cAGd,OAAA,GAAW,CAAA;;;;UC3DP,UAAA;EACf,KAAA,EAAO,MAAA;EACP,gBAAA,EAAkB,cAAA;AAAA;AAAA,UAGH,oBAAA;ENOD;EMLd,KAAA,EAAO,eAAA;ENEO;EMAd,KAAA,EAAO,UAAA;ENA0C;EMEjD,QAAA,GAAW,UAAA;ENDX;;;;;EMOA,UAAA;ENFe;;;;EMOf,SAAA;AAAA;AAAA,cAGW,kBAAA;AAAA,cACA,iBAAA;;;ANQb;;;;;;;;;;iBM8NgB,eAAA,CAAgB,KAAA,EAAO,oBAAA,GAAuB,eAAA;;iBAkC9C,uBAAA,CAAwB,IAAA,EAAM,eAAA"}
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,iBA2EoB,cAAA,CAAe,OAAA,EAAS,iBAAA,GAAoB,OAAA,CAAQ,gBAAA;;;UCrHzD,YAAA;EACf,cAAA;EACA,aAAA;EACA,cAAA;EACA,WAAA,EAAa,MAAA;EACb,UAAA,EAAY,MAAA;EFFE;EEId,mBAAA,EAAqB,MAAA;EFPP;EESd,oBAAA;EACA,aAAA;EACA,iBAAA;EACA,MAAA,EAAQ,MAAA;IAAiB,IAAA;IAAc,MAAA;IAAgB,MAAA;IAAgB,OAAA;EAAA;EFNxD;EEQf,OAAA;;EAEA,kBAAA;EFTA;;;;;;EEgBA,yBAAA;EFE4B;;;;EEG5B,kBAAA;AAAA;AAAA,UAGe,iBAAA;EACf,KAAA,EAAO,MAAA;EACP,gBAAA,EAAkB,cAAA;EAClB,MAAA,EAAQ,YAAA;AAAA;AAAA,iBA0CM,gBAAA,CAAiB,GAAA,EAAK,KAAA,EAAO,IAAA;EAAS,SAAA;AAAA,IAAuB,iBAAA;;;;;;AF7E7E;;;iBGbgB,cAAA,CAAe,GAAA,EAAK,KAAA;EAAU,QAAA,EAAU,UAAA;EAAc,QAAA,EAAU,WAAA,CAAY,cAAA;AAAA;AAAA,iBAgB5E,mBAAA,CAAoB,GAAA,EAAK,KAAA,EAAO,OAAA,EAAS,cAAA,EAAgB,IAAA;EAAS,YAAA;AAAA,IAA0B,cAAA;;iBAiB5F,iBAAA,CAAkB,GAAA,EAAK,cAAA,GAAiB,eAAA;;;UC3CvC,iBAAA;EACf,EAAA;EACA,UAAA;EACA,KAAA;EACA,KAAA;AAAA;AAAA,iBAGc,eAAA,CAAgB,CAAA,YAAa,CAAA;AAAA,iBAI7B,cAAA,CAAe,GAAA;;iBAyFf,cAAA,CAAe,CAAA,WAAY,iBAAA;;;cC9F9B,KAAA,GAAS,CAAA;;cAST,KAAA,GAAS,CAAA;;cAcT,KAAA,GAAS,CAAA;;;;;;;;;ALCtB;cK8Ba,UAAA,EAAU,MAAA;;cAIV,WAAA,EAAW,MAAA;;cAOX,UAAA,GAAc,CAAA;AAAA,cAGd,OAAA,GAAW,CAAA;;;;UC3DP,UAAA;EACf,KAAA,EAAO,MAAA;EACP,gBAAA,EAAkB,cAAA;AAAA;AAAA,UAGH,oBAAA;ENOD;EMLd,KAAA,EAAO,eAAA;ENEO;EMAd,KAAA,EAAO,UAAA;ENA0C;EMEjD,QAAA,GAAW,UAAA;ENDX;;;;;EMOA,UAAA;ENFe;;;;EMOf,SAAA;AAAA;AAAA,cAGW,kBAAA;AAAA,cACA,iBAAA;;;ANQb;;;;;;;;;;iBM8NgB,eAAA,CAAgB,KAAA,EAAO,oBAAA,GAAuB,eAAA;;iBAkC9C,uBAAA,CAAwB,IAAA,EAAM,eAAA"}