Both plugins win by listening at a higher priority than ImageUploadEditing, so
the code they pre-empt stays in place and reads correctly on its own — each is
easy to mistake for redundant. Write down what they displace and what breaks if
the narrowness goes: widening the bare-image rule brings back the Word paste
that loses its text, and dropping the restore priority makes every internal
paste duplicate its images.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
WebdriverIO downloads a Chrome for Testing build and a chromedriver of
its own, both linked against libraries no NixOS store path provides, so
they abort on a missing libxcb.so.1 and the suite cannot start. Working
around it by hand — a driver started on a fixed port, a local config
connecting to it — is a recipe everyone has to rediscover.
Two variables replace it. CHROMEDRIVER_PATH is webdriverio's own, and
makes it spawn that driver on a free port; CHROME_BIN is read here and
handed over as a capability, which also stops the browser download,
since a string binary short-circuits the puppeteer setup. Neither is set
on a normal machine, so nothing about CI changes.
The dev shell exports both from pkgs.chromium and pkgs.chromedriver —
one nixpkgs revision, so their versions agree.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The last of the ckeditor5-* packages. `packages/ckeditor5-math` had no
consumers outside `@triliumnext/ckeditor5`, was never published, and
carried a ckeditor5-package-generator scaffold that nothing invoked —
including a tsconfig.test.json referencing an uninstalled @types/mocha,
so its tests were never typechecked at all.
Move it to src/plugins/math/, flattening src/ui/ and renaming to the
repo's snake_case convention, with the tests co-located as *.spec.ts.
The `mathlive` and `@ckeditor/ckeditor5-icons` dependencies move onto
this package, which is now the only thing that needs them.
Three things the move surfaced:
- math_input_view.ts re-declared `window.mathVirtualKeyboard`, which
MathLive declares itself. Harmless in a separate package, a hard
TS2717/TS2687 here — and it was cascading into a dozen unrelated
typecheck errors across apps/client and apps/build-docs.
- MathUI binds `mathInputView#value` to the command, but MathInputView
assigns its own `value` on every MathLive/textarea change, which
severs the binding. A legacy test asserted the live binding and had
been passing only by accident of timing. It now asserts the contract
that holds, and _addFormView()'s seemingly redundant manual push is
documented as load-bearing.
- The preview element is never actually hidden or removed by hand:
both call sites look it up after the view containing it has already
gone. Marked as dead rather than left looking functional.
Coverage: lines and functions 100%, statements 99.91%, branches 98.91%.
The residue is branch permutations in the MathLive sync logic
(main_form_view, math_input_view, math_ui) and still needs tests before
the aggregate's 100% gate passes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`packages/ckeditor5-mermaid` had no consumers outside
`@triliumnext/ckeditor5`, declared no dependencies of its own — the
mermaid library is supplied by the host through `config.mermaid.lazyLoad`
— was never published, and carried a ckeditor5-package-generator scaffold
(sample pages, manual test fixtures, its own ESLint / Stylelint / vitest
configs, typings) that no root script or CI job ever invoked.
Move it to src/plugins/mermaid/, renamed to the repo's snake_case
convention with the commands/ subdirectory flattened, matching how the
admonition, collapsible and footnotes plugins are laid out. The icons
gain a `mermaid-` prefix because `info.svg` and `insert.svg` are too
generic for the shared src/icons/ folder.
`augmentation.ts` folds into mermaid.ts alongside the glue plugin — the
PluginsMap entries, the `EditorConfig.mermaid` shape and the global
MermaidInstance/MermaidConfig types — and the barrel is dropped, so
consumers import INSERT_MERMAID_COMMAND and MermaidSample directly. The
`icons` export the barrel provided had no consumers and goes with it,
along with the DLL test that asserted it.
src/index.ts keeps a side-effect import of the plugin: it is what forces
the module augmentation into the aggregate's emitted declarations, and
without it the client fails to typecheck `config.mermaid`.
The package arrived at 100% coverage (4a32394001) and holds it here under
the aggregate's gate: 107 tests, no uncovered lines in the moved code.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`packages/ckeditor5-footnotes` had no consumers outside
`@triliumnext/ckeditor5`, was never published, and shipped a
ckeditor5-package-generator scaffold (sample pages, its own ESLint /
Stylelint / vitest configs, typings) that no root script or CI job ever
invoked. Its vitest config declared a 100% coverage gate while the
package contained no tests at all, and CI never ran it with
`--coverage`, so ~1300 lines went entirely unexercised.
Move it to src/plugins/footnotes/, flattening the footnote-editing/
subdirectory and renaming to the repo's snake_case convention, and adapt
it to the destination: repo code style, the augmentation folded into a
`declare module` block, and the theme CSS moved to src/theme/. The ISC
license and its Forum Magnum / Bohan Niu attribution move with the code.
Add the missing tests — 77 across the command, editing, UI, converters,
schema, autoformat and utils — bringing the plugin to 100% statements,
functions and lines inside the aggregate's gate. Fixtures build the
document with a model writer rather than `_setModelData()`, which
coerces numeric-looking attribute values to numbers and reads `[^1]` as
selection markers; both silently made earlier fixtures test nothing.
Fix a renumbering bug found while writing those tests: `_removeFootnote`
used `${ index ?? 0 + i + 1 }`, which parses as `index ?? (0 + i + 1)`.
Since `index` is non-null there, every trailing footnote was assigned
the same number rather than being renumbered in sequence.
Also drop code that had no reachable path: the `modelQueryText` and
`modelQueryTextAll` helpers and the `DATA_FOOTNOTE_ID` constant (no
callers), the schema's `listItem` child check (the list feature has
modelled entries as attributed blocks since v41, so no `listItem`
element exists), an `editor.plugins.has("Autoformat")` guard inside a
plugin that `requires` Autoformat, and a handful of duplicated or
impossible null checks. The remaining defensive guards are marked with
`/* v8 ignore next -- defensive: ... */`, matching the convention
already used elsewhere in the repo, rather than deleted from ported
third-party code.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`packages/ckeditor5-admonition` had no consumers outside
`@triliumnext/ckeditor5`, was never published, and shipped a
ckeditor5-package-generator scaffold (sample pages, its own ESLint /
Stylelint / vitest configs, typings) that no root script or CI job ever
invoked. Half the feature already lived in the aggregate:
admonition_toolbar.ts and admonition_type_dropdown.ts were here while
the plugin they drive was in the package.
Move it to src/plugins/admonition/ alongside those two, renamed to match
the repo's snake_case convention, and adapt it to the destination: repo
code style, the augmentation folded into a `declare module` block, the
`(this as any)` cast in the autoformat replaced by the real Autoformat
instance, and three non-null assertions removed.
Two latent problems are straightened out on the way:
- The package exported two different `ADMONITION_TYPES` — a tuple of
names from the command module and a Record<type, {title}> from the UI
module — and the barrel re-exported the UI one, shadowing the other.
The tuple is now ADMONITION_TYPE_NAMES.
- theme/blockquote.css is not admonition styling at all; it is the
baseline `blockquote` CSS inherited from the block-quote fork. It
moves to src/theme/blockquote.css and is imported from src/index.ts
with the other global stylesheets.
The feature arrived with zero tests, so add specs for the command,
editing, UI and autoformat parts (47 tests). Reaching the aggregate's
100% coverage gate required removing three genuinely unreachable
fragments rather than faking coverage for them:
- the post-fixer branch unwrapping an `<aside>` inserted at an illegal
position — writer.insert()/move() both normalise it out of such a
parent first, so the differ never reports one there;
- two `match.length` guards in the autoformat, on a regex with exactly
one capture group;
- two `is("element")` re-checks on findQuote(), which can only ever
return an element.
Suite: 891 tests, 100% statements/branches/functions/lines.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`packages/ckeditor5-keyboard-marker` had no consumers outside
`@triliumnext/ckeditor5`, was never published, and carried a full
ckeditor5-package-generator scaffold (sample pages, its own ESLint /
Stylelint / vitest configs, typings) that no root script or CI job ever
invoked. Its GPL-3.0 license combines with this repository's
AGPL-3.0-only, so the split bought no license isolation either, and
upstream (mlewand/ckeditor5-keyboard-marker) targets a long-obsolete
CKEditor 5 version and is not tracked — the source was ported and has
since diverged.
Move the plugin to src/plugins/keyboard_marker/, renamed to match the
todo_list_multistate convention, and adapt it to the destination
package: repo code style, the augmentation folded into a `declare
module` block, and the spec moved onto the shared createTestEditor()
kit. The unused `icons` barrel export is dropped.
Attribution is preserved: the upstream LICENSE moves next to the code,
alongside a README recording the provenance and the divergence.
The plugin's tests land inside the aggregate's 100% coverage gate
without a carve-out; the suite stays at 100% (848 tests).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Registers ko in UNSORTED_LOCALES and maps it through every locale
registry keyed by DISPLAYABLE_LOCALE_IDS: dayjs, FullCalendar,
Excalidraw (ko-KR), Univer (KO_KR, all nine preset bundles) and
CKEditor. PDF.js needs no mapping — ko resolves through electronLocale
and the viewer already ships ko/viewer.ftl.
The CKEditor test pins every locale by hand rather than iterating them,
so it takes an entry of its own to stay complete.
The developer guide was missing the Univer step altogether, so record
that, along with the CKEditor test caveat, the condition under which
PDF.js needs nothing, and the fact that typecheck enumerates the rest
once the locale is registered.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`edit-integration-db` wrote to `apps/server/spec/db/document.db`, which is
git-ignored, while the DB the tests actually load is the tracked fixture at
`packages/trilium-core/src/test/fixtures/document.db`. Editing the DB therefore
required a manual copy dance in and out of the fixture.
Point the tool at the tracked fixture via `TRILIUM_DOCUMENT_PATH` (keeping
`TRILIUM_DATA_DIR=spec/db` so logs/tmp/config stay git-ignored), and open the
DB in the rollback (DELETE) journal mode under `TRILIUM_INTEGRATION_TEST` so the
fixture stays a single committable file with no WAL sidecars. Update the (stale)
Test database developer doc to match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The `docs/Script API/` directory was an orphaned TypeDoc snapshot from an
older docs pipeline. The current generator (apps/build-docs) builds the
Script API into the gitignored `site/script-api/{backend,frontend,electron}`
and publishes it to docs.triliumnotes.org, so the committed copy was no
longer regenerated and had gone stale (its media/README*.md landing pages
still referenced trilium.cc and the old wiki URLs).
Delete the folder and update the docs references that still pointed at it
(CLAUDE.md, copilot-instructions.md, Developer Guide/Documentation.md).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>