close
Skip to content

fix(import): bring WordPress menus, settings, and custom-block images through#607

Open
mohamedmostafa58 wants to merge 2 commits intoemdash-cms:mainfrom
mohamedmostafa58:fix/wordpress-import-menus-settings-v2
Open

fix(import): bring WordPress menus, settings, and custom-block images through#607
mohamedmostafa58 wants to merge 2 commits intoemdash-cms:mainfrom
mohamedmostafa58:fix/wordpress-import-menus-settings-v2

Conversation

@mohamedmostafa58
Copy link
Copy Markdown
Contributor

What does this PR do?

Fixes several silent-drop paths in the WordPress (WXR) import so exports land with their menus, site identity, button links, and custom-theme imagery intact.

  • Navigation menus are never imported. nav_menu_item and wp_navigation are filtered out as internal post types in the analyzer, so the admin UI's "Import navigation menus" toggle has no server-side effect. Any site being imported loses its Primary/Footer/etc. menus.
  • Site identity is never imported. <channel><title>, <description>, and the base URL are parsed but never written to site settings. The admin's importSiteTitle toggle is tracked in component state but dropped in executeImport().
  • Button hrefs are dropped. core/buttons only reads attrs.url. Any content authored in the classic editor or older Gutenberg keeps the URL inside the inner <a href> and the container transformer doesn't fall back to it, so buttons come through with labels but no links.
  • Custom theme block imagery is dropped. Themes ship custom blocks that wrap content around their own image attributes — hero sections holding an imageUrl, logo marquees / sliders / carousels holding an items[] array of image URLs, and similar patterns. The unknown-block fallback only recurses into innerBlocks, so any imagery declared on the wrapper's attrs silently disappears.
  • Internal links still point at the source WordPress host after import. Navigation buttons and inline link marks that referenced other pages on the source site keep their absolute URLs, so clicking them bounces back to the WordPress origin instead of navigating within the imported site.

What changed

  • packages/core/src/astro/routes/api/import/wordpress/analyze.ts
    • Surface navMenus, tagline, and a detected homePageSlug on the analysis response (the admin UI's existing check against data.navMenus now actually hits).
  • packages/core/src/astro/routes/api/import/wordpress/execute.ts
    • New importNavMenus helper — writes into _emdash_menus / _emdash_menu_items, resolves post_type menu items that reference imported pages to their emdash IDs, falls back to a custom URL when the target wasn't imported, and replaces same-name menus on re-import.
    • New importSiteSettings helper — writes title / tagline / url via setSiteSettings.
    • ImportConfig gains importMenus and importSiteSettings flags (default true); ImportResult reports menus and siteSettings summaries.
    • Menu items whose WordPress title is empty (the case where WordPress renders the linked page's current title at runtime) fall back to the imported page's title instead of the raw slug.
    • New rewriteInternalLinks post-pass — button URLs and inline link-mark hrefs that point at the source WordPress host are rewritten to site-relative paths. Scoped narrowly: image asset URLs, linked-image hrefs, and gallery items stay absolute and continue to flow through the existing media-URL rewrite step.
  • packages/gutenberg-to-portable-text/src/transformers/core.ts
    • core/buttons falls back to the inner <a href> when attrs.url is missing, mirroring the fallback already in core/file.
  • packages/gutenberg-to-portable-text/src/transformers/index.ts
    • Unknown-block fallback walks block.attrs and emits standard image blocks for any image-shaped URLs it finds (single-image attrs and items[].url array shapes), in addition to recursing into inner blocks. Emits standard image blocks so the existing media-import + URL-rewrite steps pick them up normally.
  • Admin UI (packages/admin) sends the importMenus / importSiteTitle toggle state in the import config, and types are extended to match the new response fields.

… through

WXR imports were silently dropping content:

- `nav_menu_item` and `wp_navigation` post types were marked internal and
  filtered out of the analyzer, so the admin UI's menu-import toggle had
  no server-side effect. The XML's menus are now written into
  `_emdash_menus` / `_emdash_menu_items`, linking items that reference
  imported pages by ULID and falling back to a custom URL otherwise. When
  a WP menu item's <title> is empty (WP uses the linked page's current
  title at render time), the imported label falls back to the page title
  rather than the raw slug.

- Channel-level <title>, <description>, and base URL were parsed but
  never written to site settings. The admin's "Import site title" toggle
  is now honored; analyzer also surfaces a detected homePageSlug for
  themes that want to key off it.

- The `core/buttons` transformer only read `attrs.url`, so classic-editor
  content (href lives inside the inner <a>) lost all button links. It now
  mirrors the `core/file` transformer's HTML href fallback.

- Unknown-block fallback now extracts image URLs from `attrs.imageUrl`,
  `attrs.items[].url`, etc., so custom theme wrappers (hero sections,
  logo marquees, sliders) keep their imagery instead of silently dropping
  it. Images remain in standard image blocks so the media-import + URL
  rewrite steps handle them normally.

- Execute step rewrites button URLs and inline link-mark hrefs that point
  back to the source WordPress host into site-relative paths, so
  navigation stays inside the imported site. Scoped narrowly — image
  asset URLs stay absolute and flow through the existing media URL
  rewrite.
@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 16, 2026

🦋 Changeset detected

Latest commit: e2a9d1e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
emdash Patch
@emdash-cms/admin Patch
@emdash-cms/cloudflare Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
create-emdash Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

Scope check

This PR changes 863 lines across 9 files. Large PRs are harder to review and more likely to be closed without review.

If this scope is intentional, no action needed. A maintainer will review it. If not, please consider splitting this into smaller PRs.

See CONTRIBUTING.md for contribution guidelines.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 16, 2026

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@607

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@607

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@607

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@607

emdash

npm i https://pkg.pr.new/emdash@607

create-emdash

npm i https://pkg.pr.new/create-emdash@607

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@607

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@607

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@607

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@607

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@607

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@607

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@607

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@607

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@607

commit: 30174d7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant