El sistema de importación de EmDash usa una arquitectura de fuentes pluggable. Cada fuente sabe cómo sondear, analizar y obtener contenido de una plataforma específica.
Fuentes de importación
| ID de fuente | Plataforma | Sondeo | OAuth | Importación completa |
|---|---|---|---|---|
wxr | Archivo de exportación WordPress | No | No | Sí |
wordpress-com | WordPress.com | Sí | Sí | Sí |
wordpress-rest | WordPress autoalojado | Sí | No | Solo sondeo |
Subida de archivo WXR
El método de importación más completo. Sube un archivo de exportación WordPress eXtended RSS (WXR) directamente al panel de administración.
Capacidades:
- Todos los tipos de entrada (incluidos los personalizados)
- Todos los campos meta
- Borradores y entradas privadas
- Jerarquía completa de taxonomías
- Metadatos de adjuntos de medios
Cómo obtener un archivo WXR:
- En el admin de WordPress, ve a Herramientas → Exportar
- Selecciona Todo el contenido o tipos de entrada específicos
- Haz clic en Descargar archivo de exportación
- Sube el archivo
.xmla EmDash
OAuth de WordPress.com
Para sitios alojados en WordPress.com, conéctate vía OAuth para importar sin exportaciones manuales de archivos.
- Introduce la URL de tu sitio WordPress.com
- Haz clic en Conectar con WordPress.com
- Autoriza EmDash en la ventana emergente de WordPress.com
- Selecciona el contenido a importar
Qué incluye:
- Contenido publicado y borradores
- Entradas privadas (con autorización)
- Archivos de medios vía API
- Campos personalizados expuestos a la REST API
Sondeo de la REST API de WordPress
Cuando introduces una URL, EmDash sondea el sitio para detectar WordPress y mostrar el contenido disponible:
Detected: WordPress 6.4
├── Posts: 127 (published)
├── Pages: 12 (published)
└── Media: 89 files
Note: Drafts and private content require authentication
or a full WXR export.
El sondeo REST es informativo. Para importaciones completas, sugiere subir un archivo WXR o conectarse vía OAuth (para WordPress.com).
Flujo de importación
Todas las fuentes siguen el mismo flujo:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Conectar │────▶│ Analizar │────▶│ Preparar │────▶│ Ejecutar │
│ (sondear/ │ │ (verificar │ │ (crear │ │ (importar │
│ subir) │ │ esquema) │ │ esquema) │ │ contenido)│
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
Paso 1: Conectar
Introduce una URL para sondear o sube un archivo directamente.
El sondeo de URL ejecuta todas las fuentes registradas en paralelo. La coincidencia con mayor confianza determina la acción sugerida:
- Sitio WordPress.com → Ofrecer conexión OAuth
- WordPress autoalojado → Mostrar instrucciones de exportación
- Desconocido → Sugerir subida de archivo
Paso 2: Analizar
La fuente analiza el contenido y verifica la compatibilidad del esquema:
Post Types:
├── post (127) → posts [Nueva colección]
├── page (12) → pages [Existente, compatible]
├── product (45) → products [Añadir 3 campos]
└── revision (234) → [Omitir - tipo interno]
Required Schema Changes:
├── Crear colección: posts
├── Añadir campos a pages: featured_image
└── Crear colección: products
Cada tipo de entrada muestra su estado:
| Estado | Significado |
|---|---|
| Ready | La colección existe con campos compatibles |
| New collection | Se creará automáticamente |
| Add fields | La colección existe, se añaden campos faltantes |
| Incompatible | Conflictos de tipo de campo (corrección manual necesaria) |
Paso 3: Preparar esquema
Haz clic en Crear esquema e importar para:
- Crear nuevas colecciones vía SchemaRegistry
- Añadir campos faltantes con los tipos de columna correctos
- Configurar tablas de contenido con índices
Paso 4: Ejecutar importación
El contenido se importa secuencialmente:
- Gutenberg/HTML convertido a Portable Text
- Estado de WordPress mapeado a estado de EmDash
- Autores de WordPress mapeados a propiedad (
authorId) y bylines de presentación - Taxonomías creadas y vinculadas
- Bloques reutilizables (
wp_block) importados como Secciones - Progreso mostrado en tiempo real
Comportamiento de importación de autores:
- Si un mapeo de autor apunta a un usuario de EmDash, la propiedad se establece a ese usuario y se crea/reutiliza un byline vinculado para el mismo usuario.
- Si no hay mapeo de usuario, se crea/reutiliza un byline de invitado a partir de la identidad del autor de WordPress.
- Las entradas importadas obtienen créditos de byline ordenados, con el primer crédito establecido como
primaryBylineId.
Paso 5: Importación de medios (Opcional)
Después del contenido, opcionalmente importa los medios:
-
Análisis — Muestra conteos de adjuntos por tipo
Media found: ├── Images: 75 files ├── Video: 10 files └── Other: 4 files -
Descarga — Transmite desde URLs de WordPress con progreso
Importing media... ├── 45 of 89 (50%) ├── Current: vacation-photo.jpg └── Status: Uploading -
Reescritura de URLs — El contenido se actualiza automáticamente con las nuevas URLs
La importación de medios usa hashing de contenido (xxHash64) para deduplicación. La misma imagen usada en múltiples posts se almacena una sola vez.
Interfaz de fuente
Las fuentes de importación implementan una interfaz estándar:
interface ImportSource {
/** Identificador único */
id: string;
/** Nombre para mostrar */
name: string;
/** Sondear una URL (opcional) */
probe?(url: string): Promise<SourceProbeResult | null>;
/** Analizar contenido de esta fuente */
analyze(input: SourceInput, context: ImportContext): Promise<ImportAnalysis>;
/** Transmitir elementos de contenido */
fetchContent(input: SourceInput, options: FetchOptions): AsyncGenerator<NormalizedItem>;
}
Tipos de entrada
Las fuentes aceptan diferentes tipos de entrada:
// Subida de archivo (WXR)
{ type: "file", file: File }
// URL con token opcional (REST API)
{ type: "url", url: string, token?: string }
// Conexión OAuth (WordPress.com)
{ type: "oauth", url: string, accessToken: string }
Salida normalizada
Todas las fuentes producen el mismo formato normalizado:
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;
}
Endpoints de API
El sistema de importación expone estos endpoints:
Sondear URL
POST /_emdash/api/import/probe
Content-Type: application/json
{ "url": "https://example.com" }
Devuelve la plataforma detectada y la acción sugerida.
Analizar WXR
POST /_emdash/api/import/wordpress/analyze
Content-Type: multipart/form-data
file: [Exportación WordPress .xml]
Devuelve el análisis de tipos de entrada con compatibilidad de esquema.
Preparar esquema
POST /_emdash/api/import/wordpress/prepare
Content-Type: application/json
{
"postTypes": [
{ "name": "post", "collection": "posts", "enabled": true }
]
}
Crea colecciones y campos.
Ejecutar importación
POST /_emdash/api/import/wordpress/execute
Content-Type: multipart/form-data
file: [Exportación WordPress .xml]
config: { "postTypeMappings": { "post": { "collection": "posts" } } }
Importa contenido a las colecciones especificadas.
Importar medios
POST /_emdash/api/import/wordpress/media
Content-Type: application/json
{
"attachments": [{ "id": 123, "url": "https://..." }],
"stream": true
}
Transmite actualizaciones de progreso NDJSON durante la descarga/subida.
Reescribir URLs
POST /_emdash/api/import/wordpress/rewrite-urls
Content-Type: application/json
{
"urlMap": { "https://old.com/image.jpg": "/_emdash/media/abc123" }
}
Actualiza el contenido Portable Text con las nuevas URLs de medios.
Manejo de errores
Errores recuperables
- Timeout de red — Reintento con backoff
- Fallo de análisis de un elemento — Registrado, omitido, la importación continúa
- Fallo de descarga de medios — Marcado para manejo manual
Errores fatales
- Formato de archivo inválido — La importación se detiene con mensaje de error
- Conexión a base de datos perdida — La importación se pausa, permite reanudar
- Cuota de almacenamiento excedida — La importación se detiene, muestra el uso
Informe de errores
Después de la importación:
Import Complete
✓ 125 posts imported
✓ 12 pages imported
✓ 85 media references recorded
⚠ 2 items had warnings:
- Post "Special Characters ñ" - title encoding fixed
- Page "About" - duplicate slug renamed to "about-1"
✗ 1 item failed:
- Post ID 456 - content parsing error (saved as draft)
Los elementos fallidos se guardan como borradores con el contenido original en _importError para revisión.
Crear fuentes personalizadas
Crea una fuente para otras plataformas:
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) {
// Analizar contenido
// Devolver ImportAnalysis
},
async *fetchContent(input, options) {
// Producir NormalizedItem para cada pieza de contenido
for (const item of items) {
yield {
sourceId: item.id,
postType: "post",
title: item.title,
content: convertToPortableText(item.body),
// ...
};
}
},
};
Registra la fuente en tu configuración de EmDash:
import { mySource } from "./src/import/custom-source";
export default defineConfig({
integrations: [
emdash({
import: {
sources: [mySource],
},
}),
],
});
Próximos pasos
- Migración de WordPress — Guía completa de migración de WordPress
- Portar plugins — Portar plugins de WordPress a EmDash