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.
|
|
5 months ago | |
|---|---|---|
| .. | ||
| components | 5 months ago | |
| engine | 5 months ago | |
| test | 5 months ago | |
| README.md | 5 months ago | |
| exports.ts | 5 months ago | |
| index.ts | 5 months ago | |
| types.ts | 5 months ago | |
| words-content.svelte.test.ts | 5 months ago | |
| words-provider.svelte.test.ts | 5 months ago | |
| words-provider.svelte.ts | 5 months ago | |
README.md
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.ts.
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-editor.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, LinkEditor, 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-link,commit-unlink,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.LinkEditoraplicainsertLinkyunlinksobre la seleccion estable del documento, exponeselectedLink,canUnlink,captureSelectiony feedback de URL invalida.- 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, texto plano y HTML seguro conservador.exportContenttambien expone Markdown V1 sin dependencia externa;importContentacepta Markdown conservador para headings, quote, listas, links y marcas inline basicas.Words.Contentrenderiza el HTML seguro del motor como contenido inicial de Svelte y usa un efecto posterior solo para restaurar la seleccion cuando el editor mantenia foco interno. La rama gestionada no monta snippets internos, de modo que wrappers Eidos/demos no apagan accidentalmente el render del documento. 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. Ctrl+AusaselectAll()dentro del Provider para seleccionar todo el documento en el modelo Soma y restaurar la Selection API condata-selection="range".BubbleMenucalcula su posicion desde el rectangulo deSelection API, exponedata-open,data-positioned,data-sideydata-selection, y evita que elpointerdowndel toolbar contextual colapse la seleccion antes de ejecutar comandos.
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 avanzado con tablas, imagenes y HTML arbitrario completo.
- Drop/clipboard avanzado a traves de servicios ActiveUIX.
- Popover flotante de links anclado directamente al rango seleccionado. V1 usa
LinkEditordentro de toolbar/bubble menu con el popover reutilizable de Eidos. - 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.