Import de contenu

Sur cette page

Le système d’import d’EmDash utilise une architecture de sources extensible. Chaque source sait comment sonder, analyser et récupérer du contenu depuis une plateforme spécifique.

Sources d’import

ID de sourcePlateformeSondeOAuthImport complet
wxrFichier export WordPressNonNonOui
wordpress-comWordPress.comOuiOuiOui
wordpress-restWordPress auto-hébergéOuiNonSonde seulement

Téléversement de fichier WXR

La méthode d’import la plus complète. Téléversez un fichier d’export WordPress eXtended RSS (WXR) directement dans le tableau de bord d’administration.

Capacités :

  • Tous les types de publication (y compris personnalisés)
  • Tous les champs meta
  • Brouillons et publications privées
  • Hiérarchie complète des taxonomies
  • Métadonnées des pièces jointes média

Comment obtenir un fichier WXR :

  1. Dans l’admin WordPress, allez dans Outils → Exporter
  2. Sélectionnez Tout le contenu ou des types de publication spécifiques
  3. Cliquez sur Télécharger le fichier d’exportation
  4. Téléversez le fichier .xml dans EmDash

OAuth WordPress.com

Pour les sites hébergés sur WordPress.com, connectez-vous via OAuth pour importer sans export manuel de fichiers.

  1. Saisissez l’URL de votre site WordPress.com
  2. Cliquez sur Connect with WordPress.com
  3. Autorisez EmDash dans la fenêtre WordPress.com
  4. Sélectionnez le contenu à importer

Ce qui est inclus :

  • Contenu publié et brouillons
  • Publications privées (avec autorisation)
  • Fichiers média via l’API
  • Champs personnalisés exposés à l’API REST

Sonde API REST WordPress

Lorsque vous saisissez une URL, EmDash sonde le site pour détecter WordPress et afficher le contenu disponible :

Détecté : WordPress 6.4
├── Articles : 127 (publiés)
├── Pages : 12 (publiées)
└── Médias : 89 fichiers

Note : Les brouillons et le contenu privé nécessitent
une authentification ou un export WXR complet.

La sonde REST est informative. Pour les imports complets, elle suggère de téléverser un fichier WXR ou de se connecter via OAuth (pour WordPress.com).

Flux d’import

Toutes les sources suivent le même flux :

┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  Connexion  │────▶│   Analyse   │────▶│ Préparation │────▶│  Exécution  │
│  (sonde/    │     │  (vérif.    │     │  (création   │     │  (import    │
│  télévers.) │     │   schéma)   │     │   schéma)   │     │   contenu)  │
└─────────────┘     └─────────────┘     └─────────────┘     └─────────────┘

Étape 1 : Connexion

Saisissez une URL pour sonder ou téléversez un fichier directement.

Le sondage d’URL exécute toutes les sources enregistrées en parallèle. La correspondance avec la confiance la plus élevée détermine l’action suggérée :

  • Site WordPress.com → Proposer une connexion OAuth
  • WordPress auto-hébergé → Afficher les instructions d’export
  • Inconnu → Suggérer le téléversement de fichier

Étape 2 : Analyse

La source analyse le contenu et vérifie la compatibilité du schéma :

Types de publication :
├── post (127) → posts [Nouvelle collection]
├── page (12)  → pages [Existante, compatible]
├── product (45) → products [Ajout de 3 champs]
└── revision (234) → [Ignoré - type interne]

Modifications de schéma requises :
├── Créer la collection : posts
├── Ajouter des champs à pages : featured_image
└── Créer la collection : products

Chaque type de publication affiche son statut :

StatutSignification
PrêtLa collection existe avec des champs compatibles
Nouvelle collectionSera créée automatiquement
Ajout de champsLa collection existe, champs manquants ajoutés
IncompatibleConflits de types de champs (correction manuelle nécessaire)

Étape 3 : Préparer le schéma

Cliquez sur Create Schema & Import pour :

  1. Créer les nouvelles collections via SchemaRegistry
  2. Ajouter les champs manquants avec les types de colonnes corrects
  3. Configurer les tables de contenu avec les index

Étape 4 : Exécuter l’import

Le contenu est importé séquentiellement :

  • Gutenberg/HTML converti en Portable Text
  • Statuts WordPress mappés vers les statuts EmDash
  • Auteurs WordPress mappés vers la propriété (authorId) et les signatures de présentation
  • Taxonomies créées et liées
  • Blocs réutilisables (wp_block) importés comme Sections
  • Progression affichée en temps réel

Comportement d’import des auteurs :

  • Si un mapping d’auteur pointe vers un utilisateur EmDash, la propriété est attribuée à cet utilisateur et une signature liée est créée/réutilisée pour le même utilisateur.
  • S’il n’y a pas de mapping utilisateur, une signature invitée est créée/réutilisée à partir de l’identité de l’auteur WordPress.
  • Les entrées importées reçoivent des crédits de signature ordonnés, le premier crédit étant défini comme primaryBylineId.

Étape 5 : Import des médias (optionnel)

Après le contenu, importez optionnellement les médias :

  1. Analyse — Affiche le nombre de pièces jointes par type

    Médias trouvés :
    ├── Images : 75 fichiers
    ├── Vidéo : 10 fichiers
    └── Autres : 4 fichiers
  2. Téléchargement — Télécharge depuis les URL WordPress avec progression

    Import des médias...
    ├── 45 sur 89 (50%)
    ├── En cours : vacation-photo.jpg
    └── Statut : Téléversement
  3. Réécriture des URL — Le contenu est automatiquement mis à jour avec les nouvelles URL

L’import des médias utilise le hachage de contenu (xxHash64) pour la déduplication. La même image utilisée dans plusieurs articles n’est stockée qu’une seule fois.

Interface des sources

Les sources d’import implémentent une interface standard :

interface ImportSource {
	/** Identifiant unique */
	id: string;

	/** Nom d'affichage */
	name: string;

	/** Sonder une URL (optionnel) */
	probe?(url: string): Promise<SourceProbeResult | null>;

	/** Analyser le contenu depuis cette source */
	analyze(input: SourceInput, context: ImportContext): Promise<ImportAnalysis>;

	/** Diffuser les éléments de contenu */
	fetchContent(input: SourceInput, options: FetchOptions): AsyncGenerator<NormalizedItem>;
}

Types d’entrée

Les sources acceptent différents types d’entrée :

// Téléversement de fichier (WXR)
{ type: "file", file: File }

// URL avec jeton optionnel (API REST)
{ type: "url", url: string, token?: string }

// Connexion OAuth (WordPress.com)
{ type: "oauth", url: string, accessToken: string }

Sortie normalisée

Toutes les sources produisent le même format normalisé :

interface NormalizedItem {
	sourceId: string | number;
	postType: string;
	status: "publish" | "draft" | "pending" | "private" | "future";
	slug: string;
	title: string;
	content: PortableTextBlock[];
	excerpt?: string;
	date: Date;
	author?: string;
	authors?: string[];
	categories?: string[];
	tags?: string[];
	meta?: Record<string, unknown>;
	featuredImage?: string;
}

Points de terminaison API

Le système d’import expose ces points de terminaison :

Sonder une URL

POST /_emdash/api/import/probe
Content-Type: application/json

{ "url": "https://example.com" }

Renvoie la plateforme détectée et l’action suggérée.

Analyser un WXR

POST /_emdash/api/import/wordpress/analyze
Content-Type: multipart/form-data

file: [fichier d'export WordPress .xml]

Renvoie l’analyse des types de publication avec la compatibilité du schéma.

Préparer le schéma

POST /_emdash/api/import/wordpress/prepare
Content-Type: application/json

{
  "postTypes": [
    { "name": "post", "collection": "posts", "enabled": true }
  ]
}

Crée les collections et les champs.

Exécuter l’import

POST /_emdash/api/import/wordpress/execute
Content-Type: multipart/form-data

file: [fichier d'export WordPress .xml]
config: { "postTypeMappings": { "post": { "collection": "posts" } } }

Importe le contenu dans les collections spécifiées.

Importer les médias

POST /_emdash/api/import/wordpress/media
Content-Type: application/json

{
  "attachments": [{ "id": 123, "url": "https://..." }],
  "stream": true
}

Diffuse les mises à jour de progression en NDJSON pendant le téléchargement/téléversement.

Réécrire les URL

POST /_emdash/api/import/wordpress/rewrite-urls
Content-Type: application/json

{
  "urlMap": { "https://old.com/image.jpg": "/_emdash/media/abc123" }
}

Met à jour le contenu Portable Text avec les nouvelles URL de médias.

Gestion des erreurs

Erreurs récupérables

  • Délai réseau dépassé — Réessai avec recul exponentiel
  • Échec d’analyse d’un élément — Journalisé, ignoré, l’import continue
  • Échec de téléchargement média — Marqué pour traitement manuel

Erreurs fatales

  • Format de fichier invalide — L’import s’arrête avec un message d’erreur
  • Connexion à la base perdue — L’import se met en pause, permet la reprise
  • Quota de stockage dépassé — L’import s’arrête, affiche l’utilisation

Rapport d’erreurs

Après l’import :

Import terminé

✓ 125 articles importés
✓ 12 pages importées
✓ 85 références média enregistrées

⚠ 2 éléments avec avertissements :
  - Article "Special Characters ñ" - encodage du titre corrigé
  - Page "About" - slug dupliqué renommé en "about-1"

✗ 1 élément échoué :
  - Article ID 456 - erreur d'analyse du contenu (sauvegardé comme brouillon)

Les éléments en échec sont sauvegardés comme brouillons avec le contenu original dans _importError pour révision.

Créer des sources personnalisées

Créez une source pour d’autres plateformes :

import type { ImportSource } from "emdash/import";

export const mySource: ImportSource = {
	id: "my-platform",
	name: "My Platform",
	description: "Import from My Platform",
	icon: "globe",
	canProbe: true,

	async probe(url) {
		const response = await fetch(`${url}/api/info`);
		if (!response.ok) return null;

		return {
			sourceId: "my-platform",
			confidence: "definite",
			detected: { platform: "my-platform" },
			// ...
		};
	},

	async analyze(input, context) {
		// Analyser le contenu
		// Renvoyer ImportAnalysis
	},

	async *fetchContent(input, options) {
		// Émettre un NormalizedItem pour chaque élément de contenu
		for (const item of items) {
			yield {
				sourceId: item.id,
				postType: "post",
				title: item.title,
				content: convertToPortableText(item.body),
				// ...
			};
		}
	},
};

Enregistrez la source dans votre configuration EmDash :

import { mySource } from "./src/import/custom-source";

export default defineConfig({
	integrations: [
		emdash({
			import: {
				sources: [mySource],
			},
		}),
	],
});

Prochaines étapes