feat(docs): document CKEditor plugin migration

This commit is contained in:
Elian Doran 2025-05-10 02:00:49 +03:00
parent aab762911b
commit c3f9f3696e
No known key found for this signature in database
8 changed files with 294 additions and 154 deletions

View File

@ -1,4 +1,4 @@
<p>Bookmarks allows creating <a href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/_help_QEAPj01N5f7w">links</a> to
<p>Bookmarks allows creating <a href="#root/_help_QEAPj01N5f7w">links</a> to
a certain part of a note, such as referencing a particular heading.</p>
<p>Technically, bookmarks are HTML anchors.</p>
<p>This feature was introduced in TriliumNext 0.94.0.</p>
@ -8,7 +8,7 @@
<ul>
<li>Place the cursor at the desired position where to place the bookmark.</li>
<li>Look for the
<img src="Bookmarks_plus.png" width="15" height="16">button in the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/_help_nRhnJkTT8cPs">Formatting toolbar</a>,
<img src="Bookmarks_plus.png" width="15" height="16">button in the&nbsp;<a class="reference-link" href="#root/_help_nRhnJkTT8cPs">Formatting toolbar</a>,
and then press the
<img src="1_Bookmarks_plus.png" width="12" height="15">button.</li>
</ul>
@ -16,8 +16,8 @@
<li>To place a link to a bookmark:
<ul>
<li>Place the cursor at the desired position of the link.</li>
<li>From the <a href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/_help_QEAPj01N5f7w">link</a> pane,
select the <em>Bookmarks</em> section and select the desired bookmark.</li>
<li>From the <a href="#root/_help_QEAPj01N5f7w">link</a> pane, select the <em>Bookmarks</em> section
and select the desired bookmark.</li>
</ul>
</li>
</ul>

View File

@ -3,7 +3,7 @@
reveal special inserable items and blocks such as symbols, Math expressions
and separators.</p>
<h2>Bookmarks</h2>
<p>See the dedicated&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/_help_oSuaNgyyKnhu">Bookmarks</a>&nbsp;section.</p>
<p>See the dedicated&nbsp;<a class="reference-link" href="#root/_help_oSuaNgyyKnhu">Bookmarks</a>&nbsp;section.</p>
<h2>Emoji</h2>
<figure class="image image-style-align-right image_resized" style="width:42.4%;">
<img style="aspect-ratio:366/410;" src="Insert buttons_plus.png" width="366"
@ -15,66 +15,63 @@
be selected via a combo box to the right.</p>
<p>There is also the possibility of inserting emojis directly by typing <code>:</code> followed
by a name of an emoji, triggering the display of a list of emojis. Simply
use the arrow keys to select one and press <kbd>Enter</kbd> to insert it.
<a
id="emoji_keyboard"></a>
</p>
<p>
<img src="1_Insert buttons_plus.png" width="272" height="187">
</p>
use the arrow keys to select one and press <kbd>Enter</kbd> to insert it.</p>
<img
src="1_Insert buttons_plus.png" width="272" height="187">
<h2>Symbols</h2>
<figure class="image image-style-align-right">
<img style="aspect-ratio:346/322;" src="1_Insert buttons_image.png" width="346"
height="322">
</figure>
<p>Pressing the
<img src="7_Insert buttons_image.png" width="18" height="15">button will reveal a popup window displaying a list of characters that
are generally more difficult to insert directly from the keyboard, such
as a subset of emojis, quotation characters, etc.</p>
<p>Interaction:</p>
<ul>
<li>Click on a character to insert it at the current cursor position.</li>
<li>The window can be dragged around by the top bar where the title is, to
avoid it getting in the way of the text.</li>
<li>Click on the <em>Category</em> selector to filter the characters.</li>
</ul>
<h2>Math equations</h2>
<p>See the dedicated&nbsp;<a class="reference-link" href="#root/_help_YfYAtQBcfo5V">Math Equations</a>&nbsp;page.</p>
<h2>Mermaid diagram</h2>
<p>Press the
<img src="2_Insert buttons_image.png" width="16" height="17">button to create an inline Mermaid diagram.</p>
<p>This feature is quite similar to the&nbsp;<a class="reference-link" href="#root/_help_s1aBHPd79XYj">Mermaid Diagrams</a>&nbsp;note
types and is meant as an alternative to it for simple diagrams. For more
complex diagrams, use the&nbsp;<a class="reference-link" href="#root/_help_nBAXQFj20hS1">Include Note</a>&nbsp;feature
for a dedicated Mermaid note.</p>
<figure class="image">
<img style="aspect-ratio:1174/358;" src="6_Insert buttons_image.png" width="1174"
height="358">
</figure>
<figure class="image image-style-align-right">
<img style="aspect-ratio:346/322;" src="1_Insert buttons_image.png" width="346"
height="322">
</figure>
<p>Pressing the
<img src="7_Insert buttons_image.png" width="18" height="15">button will reveal a popup window displaying a list of characters that
are generally more difficult to insert directly from the keyboard, such
as a subset of emojis, quotation characters, etc.</p>
<p>Interaction:</p>
<ul>
<li>Click on a character to insert it at the current cursor position.</li>
<li>The window can be dragged around by the top bar where the title is, to
avoid it getting in the way of the text.</li>
<li>Click on the <em>Category</em> selector to filter the characters.</li>
</ul>
<h2>Math equations</h2>
<p>See the dedicated&nbsp;<a class="reference-link" href="#root/_help_YfYAtQBcfo5V">Math Equations</a>&nbsp;page.</p>
<h2>Mermaid diagram</h2>
<p>Press the
<img src="2_Insert buttons_image.png" width="16" height="17">button to create an inline Mermaid diagram.</p>
<p>This feature is quite similar to the&nbsp;<a class="reference-link" href="#root/_help_s1aBHPd79XYj">Mermaid Diagrams</a>&nbsp;note
types and is meant as an alternative to it for simple diagrams. For more
complex diagrams, use the&nbsp;<a class="reference-link" href="#root/_help_nBAXQFj20hS1">Include Note</a>&nbsp;feature
for a dedicated Mermaid note.</p>
<figure class="image">
<img style="aspect-ratio:1174/358;" src="6_Insert buttons_image.png" width="1174"
height="358">
</figure>
<h2>Horizontal ruler</h2>
<p>This feature will display a horizontal line, generally useful to separate
different sections of the text. To do so, press the
<img src="5_Insert buttons_image.png"
width="18" height="16">button in the&nbsp;<a class="reference-link" href="#root/_help_nRhnJkTT8cPs">Formatting toolbar</a>.</p>
<p>
<img src="3_Insert buttons_image.png" width="502" height="95">
</p>
<p>Alternatively, it's possible to insert a horizontal ruler by typing <code>---</code>.</p>
<h2>Page break</h2>
<figure class="image image-style-align-right">
<img style="aspect-ratio:371/79;" src="8_Insert buttons_image.png" width="371"
height="79">
</figure>
<p>Page breaks provide a way to force the next paragraph or block (table,
image, etc.) to be displayed onto the next page when printing (either to
a real printer to <a href="#root/_help_NRnIZmSMc5sj">when exporting to PDF</a>).</p>
<p>Page breaks are marked in the editor with the words <em>Page break</em>,
but they will not actually be shown when printed.</p>
<ul>
<li>To insert a page break, press the
<img src="Insert buttons_image.png" width="20"
height="19">in the formatting toolbar.</li>
<li>To insert many page breaks at once, insert a page break first, click on
it and press <kbd>Ctrl</kbd>+<kbd>C</kbd>. Then use <kbd>Ctrl</kbd>+<kbd>V</kbd>,
to paste as many times as needed.</li>
</ul>
<p>This feature will display a horizontal line, generally useful to separate
different sections of the text. To do so, press the
<img src="5_Insert buttons_image.png"
width="18" height="16">button in the&nbsp;<a class="reference-link" href="#root/_help_nRhnJkTT8cPs">Formatting toolbar</a>.</p>
<img
src="3_Insert buttons_image.png" width="502" height="95">
<p>Alternatively, it's possible to insert a horizontal ruler by typing <code>---</code>.</p>
<h2>Page break</h2>
<figure class="image image-style-align-right">
<img style="aspect-ratio:371/79;" src="8_Insert buttons_image.png" width="371"
height="79">
</figure>
<p>Page breaks provide a way to force the next paragraph or block (table,
image, etc.) to be displayed onto the next page when printing (either to
a real printer to <a href="#root/_help_NRnIZmSMc5sj">when exporting to PDF</a>).</p>
<p>Page breaks are marked in the editor with the words <em>Page break</em>,
but they will not actually be shown when printed.</p>
<ul>
<li>To insert a page break, press the
<img src="Insert buttons_image.png" width="20"
height="19">in the formatting toolbar.</li>
<li>To insert many page breaks at once, insert a page break first, click on
it and press <kbd>Ctrl</kbd>+<kbd>C</kbd>. Then use <kbd>Ctrl</kbd>+<kbd>V</kbd>,
to paste as many times as needed.</li>
</ul>

View File

@ -59,8 +59,8 @@
with the text inside of it.</li>
</ul>
</li>
<li>For <a href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/_help_CohkqWQC1iBv">emojis</a>,
type <code>:</code> followed by an emoji name to trigger an auto-completion.</li>
<li>For <a href="#root/_help_CohkqWQC1iBv">emojis</a>, type <code>:</code> followed
by an emoji name to trigger an auto-completion.</li>
</ul>
<p>If auto-formatting is not desirable, press <kbd>Ctrl</kbd> + <kbd>Z</kbd> to
revert the text to its original form.</p>

View File

@ -7,7 +7,8 @@
<img src="1_Math Equations_image.png" width="20" height="15">button from the&nbsp;<a class="reference-link" href="#root/_help_nRhnJkTT8cPs">Formatting toolbar</a>&nbsp;(generally
found under the&nbsp;<a class="reference-link" href="#root/_help_CohkqWQC1iBv">Insert buttons</a>).</p>
<p>If inserting equations frequently, using the <kbd>Ctrl</kbd>+<kbd>M</kbd> keyboard
shortcut can be more comfortable.</p>
shortcut can be more comfortable. Alternatively, type <code>$$</code> or <code>\[</code> to
trigger the popup directly.</p>
<p>There is currently no quick way to insert an equation, such as surrounding
it with <code>$</code> or pressing <kbd>Ctrl</kbd>+<kbd>M</kbd> on an already
typed-out equation.</p>

View File

@ -69,7 +69,67 @@
],
"format": "markdown",
"dataFileName": "Project Structure.md",
"attachments": []
"attachments": [],
"dirFileName": "Project Structure",
"children": [
{
"isClone": false,
"noteId": "Jg7clqogFOyD",
"notePath": [
"jdjRLhLV3TtI",
"cxfTSHIUQtt2",
"Jg7clqogFOyD"
],
"title": "CKEditor",
"notePosition": 10,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "label",
"name": "iconClass",
"value": "bx bx-package",
"isInheritable": false,
"position": 10
},
{
"type": "relation",
"name": "internalLink",
"value": "BRhQZHgwaGyw",
"isInheritable": false,
"position": 20
}
],
"format": "markdown",
"dataFileName": "CKEditor.md",
"attachments": [],
"dirFileName": "CKEditor",
"children": [
{
"isClone": false,
"noteId": "BRhQZHgwaGyw",
"notePath": [
"jdjRLhLV3TtI",
"cxfTSHIUQtt2",
"Jg7clqogFOyD",
"BRhQZHgwaGyw"
],
"title": "Plugin migration guide",
"notePosition": 10,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [],
"format": "markdown",
"dataFileName": "Plugin migration guide.md",
"attachments": []
}
]
}
]
},
{
"isClone": false,
@ -169,15 +229,7 @@
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "relation",
"name": "internalLink",
"value": "IxkDdjTogO18",
"isInheritable": false,
"position": 10
}
],
"attributes": [],
"format": "markdown",
"dataFileName": "Releasing a version.md",
"attachments": []
@ -220,6 +272,22 @@
"attachments": [],
"dirFileName": "Building and deployment",
"children": [
{
"isClone": true,
"noteId": "PXzm2t3sCdsP",
"notePath": [
"jdjRLhLV3TtI",
"ibAPHul7Efvr",
"sUqOpnrQyEC7",
"PXzm2t3sCdsP"
],
"title": "Build deliveries locally",
"prefix": null,
"dataFileName": "Build deliveries locally.clone.md",
"type": "text",
"format": "markdown",
"isExpanded": false
},
{
"isClone": false,
"noteId": "zdQzavvHDl1k",
@ -240,54 +308,6 @@
"dataFileName": "Documentation.md",
"attachments": []
},
{
"isClone": true,
"noteId": "czgXkoEYwclZ",
"notePath": [
"jdjRLhLV3TtI",
"ibAPHul7Efvr",
"sUqOpnrQyEC7",
"czgXkoEYwclZ"
],
"title": "Running a development build",
"prefix": null,
"dataFileName": "Running a development build.clone.md",
"type": "text",
"format": "markdown",
"isExpanded": false
},
{
"isClone": true,
"noteId": "PXzm2t3sCdsP",
"notePath": [
"jdjRLhLV3TtI",
"ibAPHul7Efvr",
"sUqOpnrQyEC7",
"PXzm2t3sCdsP"
],
"title": "Build deliveries locally",
"prefix": null,
"dataFileName": "Build deliveries locally.clone.md",
"type": "text",
"format": "markdown",
"isExpanded": false
},
{
"isClone": true,
"noteId": "rLWcPPQi7Eso",
"notePath": [
"jdjRLhLV3TtI",
"ibAPHul7Efvr",
"sUqOpnrQyEC7",
"rLWcPPQi7Eso"
],
"title": "Releasing a version",
"prefix": null,
"dataFileName": "Releasing a version.clone.md",
"type": "text",
"format": "markdown",
"isExpanded": false
},
{
"isClone": false,
"noteId": "oqg9OpK8xfcm",
@ -355,6 +375,38 @@
]
}
]
},
{
"isClone": true,
"noteId": "rLWcPPQi7Eso",
"notePath": [
"jdjRLhLV3TtI",
"ibAPHul7Efvr",
"sUqOpnrQyEC7",
"rLWcPPQi7Eso"
],
"title": "Releasing a version",
"prefix": null,
"dataFileName": "Releasing a version.clone.md",
"type": "text",
"format": "markdown",
"isExpanded": false
},
{
"isClone": true,
"noteId": "czgXkoEYwclZ",
"notePath": [
"jdjRLhLV3TtI",
"ibAPHul7Efvr",
"sUqOpnrQyEC7",
"czgXkoEYwclZ"
],
"title": "Running a development build",
"prefix": null,
"dataFileName": "Running a development build.clone.md",
"type": "text",
"format": "markdown",
"isExpanded": false
}
]
},

View File

@ -0,0 +1,6 @@
# CKEditor
* We migrated away from the legacy CKEditor builds using Webpack and instead use the prebuilt npm binaries.
* The role of the `packages/ckeditor5` is to gather the CKEditor for consumption by the client, which includes plugin definitions.
* The internal Trilium plugins (e.g. cut to note, include note) are present in `packages/ckeditor5/src/plugins`.
* External CKEditor plugins that needed adjustments are present in `packages/ckeditor5-*`.
* To integrate a new plugin, see <a class="reference-link" href="CKEditor/Plugin%20migration%20guide.md">Plugin migration guide</a>.

View File

@ -0,0 +1,84 @@
# Plugin migration guide
This guide walks through the basic steps to take to integrate a CKEditor 5 plugin for use inside the Trilium monorepo, which allows:
* Making modifications to the implementation without having to maintain a new repo.
* Integrating an older plugin based on the legacy installation method so that it works well with the new one.
> [!IMPORTANT]
> This guide assumes that the CKEditor plugin is written in TypeScript. If it isn't, then you will have to port it to TypeScript to match the rest of the monorepo.
## Step 1. Creating the project skeleton
First, we are going to generate a project from scratch so that it picks up the latest template for building CKEditor plugins, whereas the plugin which is being integrated might be based on the legacy method.
Outside the `Notes` repository, we are going to use the CKEditor generator to generate the new project structure for us. We are not doing it directly inside `Notes` repository since it's going to use a different package manager (Yarn/NPM vs `pnpm`) and it also creates its own Git repository.
```
npx ckeditor5-package-generator @triliumnext/ckeditor5-foo --use-npm --lang ts --installation-methods current
```
Of course, replace `foo` with the name of the plugin. Generally it's better to stick with the original name of the plugin which can be determined by looking at the prefix of file names (e.g. `mermaid` from `mermaidui` or `mermaidediting`).
## Step 2. Copy the new project
1. Go to the newly created `ckeditor5-foo` directory.
2. Remove `node_modules` since we are going to use `pnpm` to handle it.
3. Remove `.git` from it.
4. Copy the folder into the `Notes` repo, as a subdirectory of `packages`.
## Step 3. Updating dependencies
In the newly copied package, go to `package.json` and edit:
1. In `devDependencies`, change `ckeditor5` from `latest` to the same version as the one described in `packages/ckeditor5/package.json` (fixed version, e.g. `43.2.0`).
2. In `peerDependencies`, change `ckeditor5` to the same version as from the previous step.
3. Similarly, update `vitest` dependencies to match the monorepo one.
4. Remove the `prepare` entry from the `scripts` section.
5. Change `build:dist` to simply `build` in order to integrate it with NX.
## Step 4. Install missing dependencies and build errors
Run `pnpm build-dist` on the `Notes` root, and:
1. If there is an error about `Invalid module name in augmentation, module '@ckeditor/ckeditor5-core' cannot be found.`, simply replace `@ckeditor/ckeditor5-core` with `ckeditor5`.
2. Run the build command again and ensure there are no build errors.
3. Commit the changes.
## Step 5. Using `git subtree` to pull in the original repo
Instead of copying the files from the existing plugin we are actually going to carry over the history for traceability. To do so, we will use a temporary directory inside the repo:
```
git subtree add --prefix=_regroup/<name> https://[...]/repo.git <main_branch>
```
This will bring in all the commits of the upstream repo from the provided branch and rewrite them to be placed under the desired directory.
## Step 6. Integrate the plugin
1. Start by copying each sub-plugin (except the main one such as `FooEditing` and `FooUI`).
1. If they are written in JavaScript, port them to TypeScript.
1. Remove any non-TypeScript type documentation.
2. If they have non-standard imports to CKEditor, such as `'ckeditor5/src/core.js'`, rewrite them to simply `ckeditor`.
2. Install any necessary dependencies used by the source code (try going based on compilation errors rather than simply copying over all dependencies from `package.json`).
3. Keep the existing TypeScript files that were generated automatically and integrate the changes into them.
4. In `tsconfig.json` of the plugin, set `compilerOptions.composite` to `true`.
5. Add a workspace dependency to the new plugin in `packages/ckeditor5/package.json`.
6. In `packages/ckeditor5` look for `plugins.ts` and import the top-level plugin in `EXTERNAL_PLUGINS`.
## Handling CSS
Some plugins have custom CSS whereas some don't.
1. `import` the CSS in the `index.ts` of the plugin.
2. When building the plugin, `dist/index.css` will be updated.
3. In `plugins.ts` from `packages/ckeditor5`, add an import to the CSS.
## Integrating from another monorepo
This is a more complicated use-case if the upstream plugin belongs to a monorepo of another project (similar to how `trilium-ckeditor5` used to be).
1. Create a fresh Git clone of the upstream monorepo to obtain the plugin from.
2. Run `git filter-repo --path packages/ckeditor5-foo/` (the trailing slash is very important!).
3. Run `git subtree add` just like in the previous steps but point to the local Git directory instead (by appending `/.git` to the absolute path of the repository).
4. Follow same integration steps as normal.

View File

@ -5090,25 +5090,25 @@
"mime": "text/html",
"attributes": [
{
"type": "label",
"name": "iconClass",
"value": "bx bx-bookmark",
"type": "relation",
"name": "internalLink",
"value": "QEAPj01N5f7w",
"isInheritable": false,
"position": 10
},
{
"type": "relation",
"name": "internalLink",
"value": "QEAPj01N5f7w",
"value": "nRhnJkTT8cPs",
"isInheritable": false,
"position": 20
},
{
"type": "relation",
"name": "internalLink",
"value": "nRhnJkTT8cPs",
"type": "label",
"name": "iconClass",
"value": "bx bx-bookmark",
"isInheritable": false,
"position": 30
"position": 10
}
],
"format": "markdown",
@ -6013,44 +6013,44 @@
{
"type": "relation",
"name": "internalLink",
"value": "s1aBHPd79XYj",
"value": "oSuaNgyyKnhu",
"isInheritable": false,
"position": 20
},
{
"type": "relation",
"name": "internalLink",
"value": "nBAXQFj20hS1",
"value": "s1aBHPd79XYj",
"isInheritable": false,
"position": 30
},
{
"type": "relation",
"name": "internalLink",
"value": "NRnIZmSMc5sj",
"value": "nBAXQFj20hS1",
"isInheritable": false,
"position": 40
},
{
"type": "relation",
"name": "internalLink",
"value": "YfYAtQBcfo5V",
"value": "NRnIZmSMc5sj",
"isInheritable": false,
"position": 50
},
{
"type": "relation",
"name": "internalLink",
"value": "YfYAtQBcfo5V",
"isInheritable": false,
"position": 60
},
{
"type": "label",
"name": "iconClass",
"value": "bx bx-plus",
"isInheritable": false,
"position": 60
},
{
"type": "relation",
"name": "internalLink",
"value": "oSuaNgyyKnhu",
"isInheritable": false,
"position": 70
}
],
"format": "markdown",
@ -6455,23 +6455,23 @@
{
"type": "relation",
"name": "internalLink",
"value": "dEHYtoWWi8ct",
"value": "CohkqWQC1iBv",
"isInheritable": false,
"position": 70
},
{
"type": "relation",
"name": "internalLink",
"value": "dEHYtoWWi8ct",
"isInheritable": false,
"position": 80
},
{
"type": "label",
"name": "iconClass",
"value": "bx bxl-markdown",
"isInheritable": false,
"position": 70
},
{
"type": "relation",
"name": "internalLink",
"value": "CohkqWQC1iBv",
"isInheritable": false,
"position": 80
}
],
"format": "markdown",