Перейти к содержимому
FastOffice

Структура документа: как её получить

Архитектура и границы ответственности, путь одного пользовательского действия, семантическая модель и текущий Rust Session API для чтения.

Базовый поток данных неизменен для desktop, системного WebView и headless-интеграции:

Слой Что делает Чего не делает
Partner Host Окно, бренд, вход, хранилище, бизнес-процессы, lifecycle Не владеет моделью документа и layout
Web Surface Canvas, ribbon/UI, ввод, показ меню, доставка событий Не правит DOCX напрямую
Host Adapter Запуск процесса, bootstrap URL, JSONL/WS, WebView events Не интерпретирует OOXML
Document Session Команды, selection, history, model/layout projections, save Не отдаёт произвольный DOM-контроль
Rust Core OOXML package, семантическая истина, layout, writeback Не зависит от конкретного бренда оболочки
DOCX Сохраняемая и повторно открываемая истина Не подменяется HTML-снимком
  • Pointer event. Web Surface получает координаты click/right-click/double-click.

  • Canonical hit-test. D6 связывает координату с page/line/caret и далее с семантическим target.

  • Interaction context. Формируются target, selection, ancestors, revision и разрешённые команды.

  • UI decision. A4 и внешний provider составляют контекстное меню без изменения документа.

  • Typed command. Выбранный пункт превращается в версионированную команду Rust-сессии.

  • Truth update. Rust проверяет revision/capability, меняет модель и возвращает receipt.

  • Repaint + persistence. Проекции обновляются; save пишет DOCX, который повторно открывается той же моделью.

Главное правило расширения внешнее приложение может добавлять поведение вокруг процессора, но не создавать вторую истину документа в DOM, JavaScript-состоянии или вручную изменённом OOXML.

Термин «структура документа» неоднозначен. A4 разделяет четыре представления, чтобы интегратор запрашивал только то, что ему действительно нужно.

Представление Команда Назначение Пример данных
Semantic model model / model-docx Абзацы, runs, таблицы, ссылки на стили/нумерацию, support markers body.blocks[], paragraph_index, text, runs[]
Layout compose / paginate Секции, страницы, линии, переносы, геометрия page_index, line boxes, page stack
Scene print / print-window / print-delta Материализованные страницы и paint primitives page scenes, fingerprints
Review & styles review / style Комментарии, изменения, style resolution review/style projections
Editing state status / set-selection Revision, dirty, undo/redo, selection/view state accepted_revision, selection_revision

STANDALONE ЧТЕНИЕ БЕЗ ДОЛГОЖИВУЩЕЙ СЕССИИ

Окно терминала
target/debug/A4-cli model-docx /data/contract.docx --format json

ФАКТИЧЕСКАЯ ФОРМА ОТВЕТА MODEL-DOCX

{
"model_version": "A4-d1-document-model-v1",
"block_count": 1,
"paragraph_count": 1,
"body": {"blocks": [{
"kind": "paragraph",
"block_index": 0,
"text": "A4 basic paragraph.",
"style_ref": null,
"numbering_ref": null,
"runs": [{
"run_index": 0,
"text": "A4 basic paragraph.",
"direct_format": {"bold": null, "italic": null}
}]
}]}
}
Что считать стабильной ссылкой Индекс абзаца удобен для bounded-команд, но для -расширений нужен стабильный nodeId + revision. Поэтому публичный target DTO следует заморозить отдельно и не выдавать внутренние CSS-селекторы или DOM-узлы.

ЗАПУСК ЛОКАЛЬНОГО ПРОЦЕССОРА

Процесс печатает первую строку ready со схемой A4.session-serve.v1. После этого каждая строка stdin — JSON-запрос, каждая строка stdout — коррелированный JSON-ответ.

ЗАПРОСЫ В ОДНУ ДОЛГОЖИВУЩУЮ СЕССИЮ

{"id":"open-1","cmd":"open",
"path":"/data/contract.docx","document_id":"contract-42"}
{"id":"model-1","cmd":"model"}
{"id":"pages-1","cmd":"paginate"}
{"id":"review-1","cmd":"review"}
{"id":"state-1","cmd":"status"}

ОБЩИЙ ENVELOPE ОТВЕТА

{
"id": "model-1",
"ok": true,
"cmd": "model",
"elapsed_ms": 2,
"result": { "model_version": "...", "body": { "blocks": [] } }
}

ЯЗЫКОНЕЗАВИСИМЫЙ ЛОКАЛЬНЫЙ ТРАНСПОРТ

Окно терминала
target/debug/A4-cli serve --ws 0
# stdout: {"schema":"A4.session-ws-bootstrap.v1",
# "host":"127.0.0.1","port":49172,"token":"..."}
  • Привязка — только 127.0.0.1. Порт 0 выбирается автоматически.

  • Token — 256-bit secret. Его нельзя писать в логи и аналитику.

  • Команды одинаковы. JSONL и WS используют один SessionHost и одну схему запросов.

Рекомендация для первого пилота Начать с отдельного Rust-процесса и JSONL/loopback WS: это уже проверяемая языконезависимая граница. In-process Rust crate/C ABI можно заморозить позже, не смешивая внутренние Rust-типы с публичным SDK.

Ассистент документации

Ответ собран из документации и может быть неточным — сверяйтесь с источниками.