Aller au contenu

Portage de thèmes WordPress

Les thèmes WordPress peuvent être systématiquement convertis vers EmDash. La conception visuelle, la structure du contenu et les fonctionnalités dynamiques sont toutes transférées en utilisant une approche en trois phases.

  1. Extraction de la Conception

    Extrayez les variables CSS, les polices, les couleurs et les modèles de mise en page du thème WordPress. Analysez le site en direct pour capturer les styles calculés et les points de rupture responsives.

  2. Conversion des Templates

    Convertissez les templates PHP en composants Astro. Mappez la hiérarchie des templates WordPress aux routes Astro et transformez les balises de template en appels d’API EmDash.

  3. Fonctionnalités Dynamiques

    Portez les menus de navigation, les zones de widgets, les taxonomies et les paramètres du site vers leurs équivalents EmDash. Créez un fichier de seed pour capturer le modèle de contenu complet.

FichierObjectif
style.cssFeuille de style principale avec l’en-tête du thème
assets/css/Feuilles de style supplémentaires
theme.jsonThèmes de blocs (WP 5.9+) - tokens structurés
Modèle WordPressVariable EmDash
Famille de police du corps--font-body
Police des titres--font-heading
Couleur primaire--color-primary
Arrière-plan--color-base
Couleur du texte--color-contrast
Largeur du contenu--content-width

Créez src/layouts/Base.astro avec les variables CSS extraites, la structure d’en-tête/pied de page, le chargement des polices et les points de rupture responsives :

src/layouts/Base.astro
---
import { getSiteSettings, getMenu } from "emdash";
import "../styles/global.css";
const { title, description } = Astro.props;
const settings = await getSiteSettings();
const primaryMenu = await getMenu("primary");
const pageTitle = title ? `${title} | ${settings.title}` : settings.title;
---
<!doctype html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{pageTitle}</title>
</head>
<body>
<header>
{settings.logo ? (
<img src={settings.logo.url} alt={settings.title} />
) : (
<span>{settings.title}</span>
)}
<nav>
{primaryMenu?.items.map((item) => (
<a href={item.url}>{item.label}</a>
))}
</nav>
</header>
<main><slot /></main>
</body>
</html>
Template WordPressRoute Astro
index.phpsrc/pages/index.astro
single.phpsrc/pages/posts/[slug].astro
single-{post_type}.phpsrc/pages/{type}/[slug].astro
page.phpsrc/pages/[...slug].astro
archive.phpsrc/pages/posts/index.astro
category.phpsrc/pages/categories/[slug].astro
tag.phpsrc/pages/tags/[slug].astro
search.phpsrc/pages/search.astro
404.phpsrc/pages/404.astro
header.php / footer.phpPartie de src/layouts/Base.astro
sidebar.phpsrc/components/Sidebar.astro
Fonction WordPressÉquivalent EmDash
have_posts() / the_post()getEmDashCollection()
get_post()getEmDashEntry()
the_title()post.data.title
the_content()<PortableText value={post.data.content} />
the_excerpt()post.data.excerpt
the_permalink()/posts/${post.slug}
the_post_thumbnail()post.data.featured_image
get_the_date()post.data.publishedAt
get_the_category()getEntryTerms(coll, id, "categories")
get_the_tags()getEntryTerms(coll, id, "tags")
php title="archive.php"
<?php while (have_posts()) : the_post(); ?>
<article>
<h2><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a>
</h2>
<?php the_excerpt(); ?>
</article>
<?php endwhile; ?>
php title="single.php"
<?php get_header(); ?>
<article>
<h1><?php the_title(); ?></h1>
<?php the_content(); ?>
<div class="post-meta">
Posted in: <?php the_category(', '); ?>
</div>
</article>
<?php get_footer(); ?>

Les appels get_template_part() de WordPress deviennent des imports de composants Astro. Le partial template-parts/content-post.php devient un composant PostCard.astro que vous importez et affichez dans une boucle.

Identifiez les menus dans functions.php et créez les menus EmDash correspondants :

astro title="src/components/PrimaryNav.astro"
---
import { getMenu } from "emdash";
const menu = await getMenu("primary");
---
{menu && (
<nav class="primary-nav">
<ul>
{menu.items.map((item) => (
<li>
<a href={item.url} aria-current={Astro.url.pathname === item.url ? "page" : undefined}>
{item.label}
</a>
{item.children.length > 0 && (
<ul class="submenu">
{item.children.map((child) => (
<li><a href={child.url}>{child.label}</a>
</li>
))}
</ul>
)}
</li>
))}
</ul>
</nav>
)}

Identifiez les zones de widgets dans le thème et affichez-les :

astro title="src/components/Sidebar.astro"
---
import { getWidgetArea, getMenu } from "emdash";
import { PortableText } from "emdash/ui";
import RecentPosts from "../../themes/widgets/RecentPosts.astro";
const sidebar = await getWidgetArea("sidebar");
const widgetComponents = { "core:recent-posts": RecentPosts };
---
{sidebar && sidebar.widgets.length > 0 && (
<aside class="sidebar">
{sidebar.widgets.map(async (widget) => (
<div class="widget">
{widget.title && <h3>{widget.title}</h3>
}
{widget.type === "content" && <PortableText value={widget.content} />}
{widget.type === "menu" && (
<nav>
{await getMenu(widget.menuName).then((m) =>
m?.items.map((item) => <a href={item.url}>{item.label}</a>
)
)}
</nav>
)}
{widget.type === "component" && widgetComponents[widget.componentId] && (
<Fragment>
{(() => {
const Component = widgetComponents[widget.componentId];
return <Component {...widget.componentProps} />;
})()}
</Fragment>
)}
</div>
))}
</aside>
)}
Widget WordPressType de Widget EmDash
Texte/HTML Personnalisétype: "content"
Menu Personnalisétype: "menu"
Articles Récentscomponent: "core:recent-posts"
Catégoriescomponent: "core:categories"
Nuage de Mots-cléscomponent: "core:tag-cloud"
Recherchecomponent: "core:search"

Interrogez les taxonomies enregistrées dans le thème :

astro title="src/pages/genres/[slug].astro"
---
import { getTaxonomyTerms, getEntriesByTerm } from "emdash";
import Base from "../../../layouts/Base.astro";
export async function getStaticPaths() {
const genres = await getTaxonomyTerms("genre");
return genres.map((genre) => ({
params: { slug: genre.slug },
props: { genre },
}));
}
const { genre } = Astro.props;
const books = await getEntriesByTerm("books", "genre", genre.slug);
---
<Base title={genre.label}>
<h1>{genre.label}</h1>
{books.map((book) => (
<article>
<h2><a href={`/books/${book.slug}`}>{book.data.title}</a>
</h2>
</article>
))}
</Base>
Personnalisateur WordPressParamètre EmDash
Titre du Sitetitle
Slogantagline
Icône du Sitefavicon
Logo Personnalisélogo
Articles par pagepostsPerPage

Les shortcodes WordPress deviennent des blocs personnalisés Portable Text :

php title="functions.php"
add_shortcode('gallery', function($atts) {
$ids = explode(',', $atts['ids']);
return '<div class="gallery">...</div>
';
});

Capturez le modèle de contenu complet dans un fichier de graine. Incluez les paramètres, taxonomies, menus et zones de widgets :

json title=".emdash/seed.json"
{
"$schema": "https://emdashcms.com/seed.schema.json",
"version": "1",
"meta": { "name": "Ported Theme" },
"settings": { "title": "Mon site", "tagline": "Bienvenue", "postsPerPage": 10 },
"taxonomies": [
{
"name": "category",
"label": "Catégories",
"hierarchical": true,
"collections": ["posts"]
}
],
"menus": [
{
"name": "primary",
"label": "Navigation principale",
"items": [
{ "type": "custom", "label": "Accueil", "url": "/" },
{ "type": "custom", "label": "Blog", "url": "/posts" }
]
}
],
"widgetAreas": [
{
"name": "sidebar",
"label": "Barre latérale principale",
"widgets": [
{
"type": "component",
"componentId": "core:recent-posts",
"props": { "count": 5 }
}
]
}
]
}

Voir Format du Fichier de Graine pour la spécification complète.

Phase 1 (Design) : Variables CSS extraites, chargement des polices, schéma de couleurs correspondant, points de rupture responsifs fonctionnels.

Phase 2 (Modèles) : Page d’accueil, articles individuels, archives et page 404 tous rendus correctement.

Phase 3 (Dynamique) : Paramètres du site configurés, menus fonctionnels, taxonomies interrogeables, zones de widgets affichées, fichier de graine complet.

Si le thème a un parent (vérifiez style.css pour Template:), analysez d’abord le thème parent, puis appliquez les surcharges du thème enfant.

Les thèmes par blocs WordPress 5.9+ utilisent theme.json pour les jetons de design et templates/*.html pour le balisage des blocs. Convertissez le balisage des blocs en composants Astro et extrayez les jetons de theme.json.

Le contenu construit avec Elementor, Divi ou similaire est stocké dans les métadonnées des publications, pas dans les fichiers du thème. Ce contenu est importé via WXR, pas via le portage du thème. Concentrez le portage du thème sur l’enveloppe—le contenu du constructeur de pages est rendu via Portable Text après l’importation.