The inlineToHtml comment falsely claimed import ALWAYS yields the code mark
last; import yields code last for bold/italic/strike but code FIRST for the
==-highlight extension. Reworded to state the real invariant (wrap <code>
innermost regardless of imported order) and de-universalized the parallel
phrase in text-arbitraries.ts. Comment-only, no behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Теперь узел может нести [code, bold], и сериализатор PM→Markdown должен это
корректно выгружать в обе стороны (git-sync — data-loss-critical, требуется
байт-стабильность md2===md1).
case "text": убран ранний return для code-рана. Backtick-спан оборачивается
ПЕРВЫМ (самая внутренняя марка), затем прочие марки в том же порядке массива —
`**`code`**`. Для НЕ-code ранов вывод байт-идентичен прежнему (вынесены хелперы
escapeInlineText и applyInlineMark, поведение сохранено).
renderInlineChildren: собирает максимальный пробег подряд идущих text-узлов с
голой-делимитерной эмфазис-маркой (bold/italic/strike/uncolored-highlight),
содержащий хотя бы один code-узел. ОДНОРОДНЫЙ пробег (у всех идентичное
множество не-code марок) и безопасные границы → общие марки выносятся наружу
ОДИН раз: `**`aaa` + `bbb`**`, `**`code4` tail**`. НЕОДНОРОДНЫЙ (`[code,bold]`
рядом с `[italic]`) ИЛИ граница упирается в словесный символ (делимитер `**`
перед backtick не был бы flanking → эмфаза потерялась бы) → весь пробег через
lossless inlineToHtml (схема-HTML). НЕ-code вывод байт-идентичен, кроме
редкого случая голой-делимитерной эмфазы вплотную к code+эмфазе. Узлы, где
code раньше вообще не мог нести эмфазу, — новая территория, существующие
страницы не затрагиваются.
inlineToHtml: `<code>` тоже оборачивается ВНУТРЕННИМ (импорт отдаёт code
последним в массиве — `[emphasis, code]`; порядок-зависимый цикл переворачивал
бы `<strong><code>` в `<code><strong>` на реэкспорте и ломал байт-фикспойнт).
Тесты: перевёрнуты ассерты, фиксировавшие старое (по CommonMark неверное)
поведение (code+bold/strike/link → теперь `**`x`**`/`~~`x`~~`/`[`x`](…)`);
генераторы расширены на code+{bold,italic,strike,highlight} в каноническом
порядке импорта; добавлены явные round-trip пины 5 кейсов репорта (импорт→марки
и md→pm→md идемпотентность) + усиление code-combo свойства (обе марки выживают).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
По CommonMark `**` рядом с инлайн-кодом дают `<strong><code>` — узел с
составом марок [code, bold]. Марка `code` из tiptap несёт `excludes: "_"`
(исключает все прочие инлайн-марки), и ProseMirror на HTML→PM импорте
(`generateJSON`) выкидывает сосуществующую bold — так `**`--flag`**` терял
жирный. Ставим `excludes: ""` (не исключает ничего) во всех четырёх местах,
где марка конфигурируется независимо:
- Единый источник: новая каноническая марка `Code = TiptapCode.extend({
excludes: "" })` в @docmost/editor-ext, экспортируется из barrel.
- Живой редактор (extensions.ts): базовая `Code` теперь из editor-ext,
поверх сохранены client-only addInputRules/addKeyboardShortcuts.
- Collab-сервер + серверный HTML-парс/экспорт (collaboration.util.ts):
StarterKit code:false + общая `Code`; @docmost/editor-ext объявлен в
apps/server/package.json (использовался, но не был задекларирован).
- Редактор комментариев (comment-editor.tsx): StarterKit code:false + `Code`.
- Вендор-зеркало docmostExtensions (docmost-schema.ts) — сознательно отдельная
копия, не тянущая editor-ext в node-рантайм: `excludes:""` объявлен локально
(StarterKit code:false + `Code.extend({ excludes:"" })`), держится в
синхроне с editor-ext паритет-тестом.
Паритет-гард: тест в пакете сверяет excludes марки code вендор-зеркала с
канонической editor-ext Code (обе ""); vitest резолвит @docmost/editor-ext на
sibling-исходник, чтобы гард был герметичным.
`excludes:""` делает code «перекрывающейся» маркой в y-prosemirror (как comment):
она пишется в Yjs под хешированным ключом `code--<hash>` и распаковывается
обратно в `code` штатным декодером — правим mcp-тест-хелпер fragmentToJson,
чтобы он снимал хеш ровно как yattr2markname (иначе overlapping-code утёк бы
в сравнение как `code--<hash>`).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>