You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
9.7 KiB
9.7 KiB
Words Soma
Soma sera el propietario del motor headless de Words.
Este directorio esta creado como staging documental. La implementacion no debe empezar hasta cerrar contrato Morfo y alcance V1.
Estado
2026-05-24:
- Alcance V1 firmado.
- Slice 4 de motor puro implementado en
engine/. - Slice 5 implementa el primer Provider Soma real y el puente
contenteditable. - Slice 6 cierra wrapper Eidos, receta visual, pack Sema y demo UIX de 6 tabs.
- Tests focalizados en
engine/engine.test.ts,words-provider.svelte.test.tsywords-content.svelte.test.tscon 36 casos.
Responsabilidad
- Documento canonico JSON.
- Estado editable/readonly/disabled/focused/empty/invalid.
- Seleccion DOM <-> seleccion de documento.
- Pipeline de input:
beforeinput,input, composition/IME, paste, drop. - Comandos.
- History.
- Normalizacion de documento.
- Plugins internos.
- Serializacion JSON/HTML/Markdown.
- Integracion con logger, clipboard, format y events de ActiveUIX.
Submodulos propuestos
words/
README.md
types.ts
index.ts
exports.ts
words-provider.svelte.ts
words-provider.svelte.test.ts
engine/
document.ts
dom.ts
dom-selection.ts
selection.ts
commands.ts
history.ts
input.ts
normalize.ts
operations.ts
render.ts
clipboard.ts
serialize-json.ts
serialize-html.ts
serialize-markdown.ts
logger.ts
plugins/
basic.ts
marks.ts
blocks.ts
lists.ts
links.ts
history.ts
markdown.ts
components/
words.svelte
words-content.svelte
words-placeholder.svelte
words-toolbar.svelte
words-toolbar-group.svelte
words-command-button.svelte
words-bubble-menu.svelte
words-link-popover.svelte
words-hidden-input.svelte
words-status.svelte
Modelo minimo V1
type WordsDocument = {
version: 1;
children: WordsBlock[];
};
type WordsBlock =
| { type: 'paragraph'; children: WordsInline[] }
| { type: 'heading'; level: 1 | 2 | 3; children: WordsInline[] }
| { type: 'quote'; children: WordsInline[] }
| { type: 'list'; kind: 'ordered' | 'unordered' | 'check'; children: WordsListItem[] };
type WordsInline =
| { type: 'text'; text: string; marks?: WordsMark[] }
| { type: 'link'; href: string; title?: string; children: WordsInline[] };
type WordsMark = 'bold' | 'italic' | 'underline' | 'strike' | 'code';
Comandos V1
focusblurundoredotoggleMarksetBlocktoggleListinsertTextinsertLineBreakinsertLinkunlinkclearFormattingreplaceDocumentimportContentexportContent
Slice implementado
| Archivo | Estado |
|---|---|
engine/document.ts |
Modelo JSON V1, factories y helpers de marcas/texto. |
engine/dom.ts |
Contrato data-words-*, path encode/decode y selection targets. |
engine/dom-selection.ts |
Adaptador Selection API para leer/restaurar seleccion real del DOM. |
engine/normalize.ts |
Normaliza documentos, bloques, inline nodes, marks y links inseguros. |
engine/selection.ts |
Modelo de seleccion path + offset, rangos y text leaves. |
engine/path.ts |
Navegacion de arbol, paths profundos, replace/set helpers. |
engine/operations.ts |
Rangos, insert, marks, blocks, listas, links, Enter, Backspace. |
engine/commands.ts |
Dispatcher tipado de comandos V1 parciales. |
engine/history.ts |
Undo/redo por snapshots con batching y limite de stack. |
engine/input.ts |
Traduccion de beforeinput a comandos o accion de history. |
engine/render.ts |
Descriptor de render headless con tags y attrs para contenteditable. |
engine/serialize-json.ts |
Parse normalizado y serialize sin mutacion implicita. |
engine/serialize-html.ts |
Export HTML limpio sin data-words-* ni zero-width placeholders. |
engine/serialize-text.ts |
Import seguro de texto plano a parrafos canonicos. |
engine/engine.test.ts |
Cobertura de normalizacion, listas, rangos, links, history y teclado. |
Correcciones cerradas en slice 5
src/uix/morfo/components/words.tsdeclara contrato V1: Provider, Content, Placeholder, Toolbar, ToolbarGroup, CommandButton, HiddenInput y Status.- Morfo incluye
data-focused,data-empty,data-dirty,data-disabled,data-readonly,data-required,data-invalid,data-composing,data-selection,data-block,data-command,data-stateydata-status. - Eventos declarados con familias Sema validas:
contact-focus,commit-content,commit-format,commit-history,commit-clearysignal-invalid-input. - Provider Soma mantiene documento, seleccion, history, active marks,
focused,dirty,disabled,readonly,required,invalide integracion conFieldProvider. Contentrenderiza HTML seguro desde descriptores propios del motor, escuchabeforeinput,paste, shortcuts de teclado y composition events.HiddenInputserializa JSON canonico para formularios.CommandButtonejecuta comandos de formato, listas, bloques, undo, redo, clear y commit; expone estado activo/deshabilitado por Morfo.- Paste HTML sin texto plano se rechaza y se reporta por el logger UIX como
soma.words. - IME/composition queda conectado al Provider:
compositionendaplica el comando final. deleteWord*ydeleteLine*tienen comandos propios; losbeforeinputno soportados no se cancelan cuando el motor no los posee.- Las listas tienen salida por Enter en item vacio y Backspace al inicio del
primer item;
setBlocksobre listas produce un bloque por item. - Los botones de lista se activan por
listKind, no por cualquier bloquelist. - Los links anidados se aplanan en normalizacion y
insertLinkno anida dentro de un link existente. exportContentexpone JSON, texto plano y HTML limpio;importContentacepta JSON y texto plano.Words.Contentya no usa{@html ...}como bloque reactivo; gestionainnerHTMLde forma controlada y restaura la seleccion cuando el editor mantenia foco interno. Tiene cobertura montando el componente Svelte real.WordsProvidersincroniza cambios externos devalueyselectionsin remount, normaliza el documento entrante y no emite callbacks de edicion de usuario para cambios controlados desde fuera.- El Provider usa
batch: 'typing'debeforeinputpara agrupar escritura, borrado e IME contiguos en una sola entrada de undo; seleccion externa, blur, commit, undo/redo o comandos de formato cierran el batch. - La seleccion de rango se sincroniza desde
selectionchange, teclado, puntero yselect;CommandButtonpreserva la seleccion del editor antes de aplicar comandos de toolbar sobre el rango seleccionado.
Correcciones cerradas en slice 2
- Paths de profundidad variable para parrafos, listas y texto dentro de links.
getNodeAtPath,resolveTextAtPath,replaceInlineAtPathy helpers de hijos inline.- Operaciones de rango multi-inline y multi-bloque para reemplazo de texto.
- Edicion real dentro de list items.
insertParagraph,insertLineBreak,deleteBackward,deleteForwardydeleteRange.unlinkdesde el texto interior de un link.- Links relativos internos (
/ruta,?query,#anchor) permitidos. - History con
batchHistoryCommandsy limite por defecto de 200 snapshots. serializeWordsJsonya no normaliza ni muta silenciosamente.
Correcciones cerradas en slice 3
- Contrato DOM estable basado en
data-words-nodeydata-words-path. - Encode/decode de paths para no depender de indices inventados por el DOM.
- Mapping
WordsSelection<-> targets DOM serializables y clampados. - Render headless de bloques, listas, items, links y text leaves.
- Texto vacio renderizable mediante placeholder zero-width y
data-words-empty-text. - Traduccion de
beforeinputpara texto, Enter, line break, delete, formato, history undo/redo y composition guard.
Correcciones cerradas en slice 4
- Lectura de
Selection APIdesde DOM real mediantedata-words-path. - Soporte de rangos que cruzan texto normal y texto dentro de link.
- Restauracion de
Selection APIdesde targets DOM codificados. - Clamp de offsets DOM contra texto renderizado y placeholders vacios.
- Primitivas de paste seguro: texto plano con normalizacion de saltos de linea, HTML ignorado hasta tener importador seguro.
- Primitivas IME/composition: begin, update y commit final como comando explicito.
Pendiente despues de Provider
- Importador HTML seguro y Markdown import/export controlado.
- Drop/clipboard avanzado a traves de servicios ActiveUIX.
- Bubble toolbar y popover de links como partes Soma reales si entran en V1.
- Cobertura de componentes Svelte renderizados para el resto de partes compuestas.
- Eidos recipe y demo bajo
web/routes/uix/components/wordsya existen; queda auditoria visual iterativa conforme crezcan BubbleMenu/import/export.
Reglas de seguridad
- HTML importado debe validarse y normalizarse antes de entrar al documento.
- Links solo con protocolos permitidos.
javascript:,data:y protocolos desconocidos deben rechazarse o convertirse en error logueado.- No aceptar nodos desconocidos silenciosamente.
- Paste desde HTML debe tener fallback a texto plano si la importacion falla.
Eventos
Soma dispara runtime.trigger(...) solo para eventos declarados en Morfo.
Cambios internos frecuentes deben agruparse y convertirse en commit-content
cuando proceda.