mirror of
https://github.com/zadam/trilium.git
synced 2025-12-06 07:24:25 +01:00
Compare commits
29 Commits
873aa47433
...
96154b385f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96154b385f | ||
|
|
22c4fba665 | ||
|
|
f8d84814e0 | ||
|
|
c46cf41842 | ||
|
|
64ab1c4116 | ||
|
|
a6de1041c7 | ||
|
|
c8d34e65ea | ||
|
|
51db729546 | ||
|
|
d2052ad236 | ||
|
|
9c4301467f | ||
|
|
e7355dc0e4 | ||
|
|
4110fec94f | ||
|
|
d5e601eae9 | ||
|
|
4f044c4a57 | ||
|
|
5821c350e1 | ||
|
|
edba8188fe | ||
|
|
1471a72633 | ||
|
|
56834cb88a | ||
|
|
a0f16f9184 | ||
|
|
de80eb4806 | ||
|
|
48a4b81fbe | ||
|
|
e225794f72 | ||
|
|
4eef30f8b5 | ||
|
|
569b09609d | ||
|
|
39838c25c2 | ||
|
|
49e90c08a9 | ||
|
|
e777b06fb8 | ||
|
|
497ec2ac74 | ||
|
|
c5d282d203 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -48,4 +48,4 @@ upload
|
|||||||
.svelte-kit
|
.svelte-kit
|
||||||
|
|
||||||
# docs
|
# docs
|
||||||
site/
|
site/
|
||||||
@ -5,69 +5,50 @@
|
|||||||
Keyboard shortcuts. Using <code>global:</code> prefix, you can assign a shortcut
|
Keyboard shortcuts. Using <code>global:</code> prefix, you can assign a shortcut
|
||||||
which will work even without Trilium being in focus (requires app restart
|
which will work even without Trilium being in focus (requires app restart
|
||||||
to take effect).</p>
|
to take effect).</p>
|
||||||
|
<h2>Tree</h2>
|
||||||
|
<p>See the corresponding section: <a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/oPVyFC7WL2Lp/_help_DvdZhoQZY9Yd">Keyboard shortcuts</a>
|
||||||
|
</p>
|
||||||
<h2>Note navigation</h2>
|
<h2>Note navigation</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><kbd><span>↑</span></kbd>, <kbd><span>↓</span></kbd> - go up/down in the
|
<li data-list-item-id="ed8fd9c2ab08ae80ea76c1ae5dc943e90"><kbd>Alt</kbd> + <kbd><span>←</span></kbd>, <kbd>Alt</kbd> + <kbd><span>→</span></kbd> –
|
||||||
list of notes, <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd><span>↑</span></kbd> and <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd><span>↓</span></kbd> work
|
|
||||||
also from editor</li>
|
|
||||||
<li><kbd><span>←</span></kbd>, <kbd><span>→</span></kbd> - collapse/expand node</li>
|
|
||||||
<li><kbd>Alt</kbd> + <kbd><span>←</span></kbd>, <kbd>Alt</kbd> + <kbd><span>→</span></kbd> -
|
|
||||||
go back / forwards in the history</li>
|
go back / forwards in the history</li>
|
||||||
<li><kbd>Ctrl</kbd> + <kbd>J</kbd> - show <a href="#root/_help_MMiBEQljMQh2">"Jump to" dialog</a>
|
<li data-list-item-id="eff3c5760b3d985e7808f1524982fcb9b"><kbd>Ctrl</kbd> + <kbd>J</kbd> – show <a href="#root/_help_MMiBEQljMQh2">"Jump to" dialog</a>
|
||||||
</li>
|
</li>
|
||||||
<li><kbd>Ctrl</kbd> + <kbd>.</kbd> - scroll to current note (useful when you
|
<li data-list-item-id="e1fdee08a424868922b0579e78584279c"><kbd>Ctrl</kbd> + <kbd>.</kbd> – scroll to current note (useful when you
|
||||||
scroll away from your note or your focus is currently in the editor)</li>
|
scroll away from your note or your focus is currently in the editor)</li>
|
||||||
<li><kbd><span>Backspace</span></kbd> - jumps to parent note</li>
|
<li
|
||||||
<li><kbd>Alt</kbd> + <kbd>C</kbd> - collapse whole note tree</li>
|
data-list-item-id="e9bbc51f19a729c10997010a915779d07"><kbd><span>Backspace</span></kbd> – jumps to parent note</li>
|
||||||
<li><kbd>Alt</kbd> + <kbd>-</kbd> (alt with minus sign) - collapse subtree (if
|
<li data-list-item-id="eaaa0f36b2e561d4a24358552e633d924"><kbd>Alt</kbd> + <kbd>C</kbd> – collapse whole note tree</li>
|
||||||
some subtree takes too much space on tree pane you can collapse it)</li>
|
<li data-list-item-id="ee625a141f5298dbd52ecb6e56693e647"><kbd>Alt</kbd> + <kbd>-</kbd> (alt with minus sign) – collapse subtree (if
|
||||||
<li>you can define a <a href="#root/_help_zEY4DaJG4YT5">label</a> <code>#keyboardShortcut</code> with
|
some subtree takes too much space on tree pane you can collapse it)</li>
|
||||||
e.g. value <kbd>Ctrl</kbd> + <kbd>I</kbd> . Pressing this keyboard combination
|
<li
|
||||||
will then bring you to the note on which it is defined. Note that Trilium
|
data-list-item-id="ec1bf00840a017ea798880470e419f3d9">you can define a <a href="#root/_help_zEY4DaJG4YT5">label</a> <code>#keyboardShortcut</code> with
|
||||||
must be reloaded/restarted (<kbd>Ctrl</kbd> + <kbd>R</kbd> ) for changes to
|
e.g. value <kbd>Ctrl</kbd> + <kbd>I</kbd> . Pressing this keyboard combination
|
||||||
be in effect.</li>
|
will then bring you to the note on which it is defined. Note that Trilium
|
||||||
|
must be reloaded/restarted (<kbd>Ctrl</kbd> + <kbd>R</kbd> ) for changes to
|
||||||
|
be in effect.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>See demo of some of these features in <a href="#root/_help_MMiBEQljMQh2">note navigation</a>.</p>
|
<p>See demo of some of these features in <a href="#root/_help_MMiBEQljMQh2">note navigation</a>.</p>
|
||||||
<h2>Tabs</h2>
|
<h2>Tabs</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><kbd>Ctrl</kbd> + <kbd>🖱 Left click</kbd> - (or middle mouse click) on note
|
<li data-list-item-id="e6a9d460427c0394177000c8a0eecfca4"><kbd>Ctrl</kbd> + <kbd>🖱 Left click</kbd> – (or middle mouse click) on note
|
||||||
link opens note in a new tab</li>
|
link opens note in a new tab</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>Only in desktop (electron build):</p>
|
<p>Only in desktop (electron build):</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><kbd>Ctrl</kbd> + <kbd>T</kbd> - opens empty tab</li>
|
<li data-list-item-id="e745e6690db1a4bee718faa94b272013e"><kbd>Ctrl</kbd> + <kbd>T</kbd> – opens empty tab</li>
|
||||||
<li><kbd>Ctrl</kbd> + <kbd>W</kbd> - closes active tab</li>
|
<li data-list-item-id="ec34c224c2c0dd74367753a6aff4f9721"><kbd>Ctrl</kbd> + <kbd>W</kbd> – closes active tab</li>
|
||||||
<li><kbd>Ctrl</kbd> + <kbd>Tab</kbd> - activates next tab</li>
|
<li data-list-item-id="e4b9a2163cccc3ab7dbdcf6fb7f149315"><kbd>Ctrl</kbd> + <kbd>Tab</kbd> – activates next tab</li>
|
||||||
<li><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>Tab</kbd> - activates previous tab</li>
|
<li data-list-item-id="eeeabd750227ec42c30b282b9b8ab5c8d"><kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>Tab</kbd> – activates previous tab</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Creating notes</h2>
|
<h2>Creating notes</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>CTRL+O</code> - creates new note after the current note</li>
|
<li data-list-item-id="e90a7441e67297c921f8bb2145829dd55"><kbd>CTRL</kbd>+<kbd>O</kbd> – creates new note after the current note</li>
|
||||||
<li><code>CTRL+P</code> - creates new sub-note into current note</li>
|
<li
|
||||||
<li><code>F2</code> - edit <a href="#root/_help_MMiBEQljMQh2">prefix</a> of current
|
data-list-item-id="e6064f6dd7b09083448cfb52247c94baa"><kbd>CTRL</kbd>+<kbd>P</kbd> – creates new sub-note into current note</li>
|
||||||
note clone</li>
|
<li
|
||||||
</ul>
|
data-list-item-id="e191cb0e7231c4439632d70da65dcf800"><kbd>F2</kbd> – edit <a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/BFs8mudNFgCS/IakOLONlIfGI/_help_TBwsyfadTA18">Branch prefix</a> of
|
||||||
<h2>Moving / cloning notes</h2>
|
current note clone</li>
|
||||||
<ul>
|
|
||||||
<li><kbd>Ctrl</kbd> + <kbd><span>↑</span></kbd> , Ctrl + <kbd><span>↓</span></kbd> -
|
|
||||||
move note up/down in the note list</li>
|
|
||||||
<li><kbd>Ctrl</kbd> + <kbd><span>←</span></kbd> - move note up in the note tree</li>
|
|
||||||
<li><kbd>Ctrl</kbd>+<kbd><span>→</span></kbd> - move note down in the note
|
|
||||||
tree</li>
|
|
||||||
<li><kbd>Shift</kbd>+<kbd><span>↑</span></kbd>, <kbd>Shift</kbd><code>+</code><kbd><span>↓</span></kbd> -
|
|
||||||
multi-select note above/below</li>
|
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>A</kbd> - select all notes in the current level</li>
|
|
||||||
<li><kbd>Shift</kbd>+<kbd>🖱 Left click</kbd> - multi select note which you
|
|
||||||
clicked on</li>
|
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>C</kbd> - copies current note (or current selection)
|
|
||||||
into clipboard (used for <a href="#root/_help_IakOLONlIfGI">cloning</a>
|
|
||||||
</li>
|
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>X</kbd> - cuts current (or current selection) note
|
|
||||||
into clipboard (used for moving notes)</li>
|
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>V</kbd> - pastes note(s) as sub-note into current
|
|
||||||
note (which is either move or clone depending on whether it was copied
|
|
||||||
or cut into clipboard)</li>
|
|
||||||
<li><kbd>Del</kbd> - delete note / sub-tree</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Editing notes</h2>
|
<h2>Editing notes</h2>
|
||||||
<aside class="admonition note">
|
<aside class="admonition note">
|
||||||
@ -77,30 +58,32 @@
|
|||||||
class="reference-link" href="#root/_help_QrtTYPmdd1qq">Markdown-like formatting</a>.</p>
|
class="reference-link" href="#root/_help_QrtTYPmdd1qq">Markdown-like formatting</a>.</p>
|
||||||
</aside>
|
</aside>
|
||||||
<ul>
|
<ul>
|
||||||
<li><kbd>Enter</kbd> in tree pane switches from tree pane into note title.
|
<li data-list-item-id="eea3611b470b2482ccf07e8844e4f66b9"><kbd>Enter</kbd> in tree pane switches from tree pane into note title.
|
||||||
Enter from note title switches focus to text editor. <kbd>Ctrl</kbd>+<kbd>.</kbd> switches
|
Enter from note title switches focus to text editor. <kbd>Ctrl</kbd>+<kbd>.</kbd> switches
|
||||||
back from editor to tree pane.</li>
|
back from editor to tree pane.</li>
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>.</kbd> - jump away from the editor to tree pane and
|
<li data-list-item-id="e5dab831910ac694ccef7bc474b2e67fc"><kbd>Ctrl</kbd>+<kbd>.</kbd> – jump away from the editor to tree pane and
|
||||||
scroll to current note</li>
|
scroll to current note</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Runtime shortcuts</h2>
|
<h2>Runtime shortcuts</h2>
|
||||||
<p>These are hooked in Electron to be similar to native browser keyboard
|
<p>These are hooked in Electron to be similar to native browser keyboard
|
||||||
shortcuts.</p>
|
shortcuts.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><kbd>F5</kbd>, <kbd>Ctrl</kbd>-<kbd>R</kbd> - reloads Trilium front-end</li>
|
<li data-list-item-id="e1a17ce297e78109362180536b7eabd68"><kbd>F5</kbd>, <kbd>Ctrl</kbd>+<kbd>R</kbd> – reloads Trilium front-end</li>
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd> - show developer tools</li>
|
<li
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>F</kbd> - show search dialog</li>
|
data-list-item-id="e07d1b25dc46ce0b0bd76a8db13373198"><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd> – show developer tools</li>
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>-</kbd> - zoom out</li>
|
<li
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>=</kbd> - zoom in</li>
|
data-list-item-id="e7dc66078ba520c48364952f2ac48aa79"><kbd>Ctrl</kbd>+<kbd>F</kbd> – show search dialog</li>
|
||||||
|
<li data-list-item-id="e63161bd165a51e19fd04dd1223173e68"><kbd>Ctrl</kbd>+<kbd>-</kbd> – zoom out</li>
|
||||||
|
<li data-list-item-id="e961144d0a57b51792830a2182459c8cf"><kbd>Ctrl</kbd>+<kbd>=</kbd> – zoom in</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Other</h2>
|
<h2>Other</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><kbd>Alt</kbd>+<kbd>O</kbd> - show SQL console (use only if you know what
|
<li data-list-item-id="eb007c4ea2f2cd6eefbc8972d538c724c"><kbd>Alt</kbd> + <kbd>O</kbd> – show SQL console (use only if you know what
|
||||||
you're doing)</li>
|
you're doing)</li>
|
||||||
<li><kbd>Alt</kbd>+<kbd>M</kbd> - distraction-free mode - display only note
|
<li data-list-item-id="e9caedb43e6c66fc7c57b4899bd6d5d76"><kbd>Alt</kbd> + <kbd>M</kbd> – distraction-free mode - display only note
|
||||||
editor, everything else is hidden</li>
|
editor, everything else is hidden</li>
|
||||||
<li><kbd>F11</kbd> - toggle full screen</li>
|
<li data-list-item-id="ec55bd0e5ff7da0c488a5378c0bdabed5"><kbd>F11</kbd> – toggle full screen</li>
|
||||||
<li><kbd>Ctrl</kbd> + <kbd>S</kbd> - toggle <a href="#root/_help_eIg8jdvaoNNd">search</a> form
|
<li data-list-item-id="e8d4ec0d76155371de5d060ad661cb19e"><kbd>Ctrl</kbd> + <kbd>S</kbd> – toggle <a href="#root/_help_eIg8jdvaoNNd">search</a> form
|
||||||
in tree pane</li>
|
in tree pane</li>
|
||||||
<li><kbd>Alt</kbd> +<kbd>A</kbd> - show note <a href="#root/_help_zEY4DaJG4YT5">attributes</a> dialog</li>
|
<li data-list-item-id="eb938081f527f44b158be7c3ed4af4925"><kbd>Alt</kbd> +<kbd>A</kbd> – show note <a href="#root/_help_zEY4DaJG4YT5">attributes</a> dialog</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -1,33 +1,53 @@
|
|||||||
<p>The <a class="reference-link" href="#root/_help_oPVyFC7WL2Lp">Note Tree</a> comes
|
<p>The <a class="reference-link" href="#root/_help_oPVyFC7WL2Lp">Note Tree</a> comes
|
||||||
with multiple keyboard shortcuts to make editing faster:</p>
|
with multiple keyboard shortcuts to make editing faster:</p>
|
||||||
|
<h2>Navigation within the tree</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Opening notes:
|
<li data-list-item-id="eede1a5721dab5213153c6bb25bad38c9"><kbd><span>↑</span></kbd> and <kbd><span>↑</span></kbd> to navigate between
|
||||||
<ul>
|
notes.</li>
|
||||||
<li><kbd>Click</kbd> to open the note in the current tab.</li>
|
<li data-list-item-id="ec4c4ab60720b34a95f73e93223ed3628"><kbd><span>←</span></kbd> to collapse a note with children, or <kbd><span>→</span></kbd> to
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>Click</kbd> or <kbd>Middle click</kbd> to open the note
|
expand it.</li>
|
||||||
in a new tab.</li>
|
<li data-list-item-id="eb5ad59d78e70611d0233ffbb5ede3b96"><kbd><span>←</span></kbd> on a note with no children to navigate to its
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>Right click</kbd> to open the note in <a class="reference-link"
|
parent.</li>
|
||||||
href="#root/_help_ZjLYv08Rp3qC">Quick edit</a>.</li>
|
</ul>
|
||||||
</ul>
|
<h2>Opening notes</h2>
|
||||||
</li>
|
<ul>
|
||||||
<li>Navigation within the tree:
|
<li data-list-item-id="e3d92e8c3a1e5b9d6f2efe5067004ef5c"><kbd>Click</kbd> to open the note in the current tab.</li>
|
||||||
<ul>
|
<li data-list-item-id="e8ae44ff429a0da1d529c627874f54908"><kbd>Ctrl</kbd>+<kbd>Click</kbd> or <kbd>Middle click</kbd> to open the note
|
||||||
<li><kbd>Up</kbd> and <kbd>Down</kbd> to navigate between notes.</li>
|
in a new tab.</li>
|
||||||
<li><kbd>Left</kbd> to collapse a note, or <kbd>Right</kbd> to expand it.</li>
|
<li data-list-item-id="e183b1a014e2bd563450dac0c8913c6f0"><kbd>Ctrl</kbd>+<kbd>Right click</kbd> to open the note in <a class="reference-link"
|
||||||
</ul>
|
href="#root/_help_ZjLYv08Rp3qC">Quick edit</a>.</li>
|
||||||
</li>
|
</ul>
|
||||||
<li>Clipboard management:
|
<h2>Clipboard management</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>C</kbd> to copy a note.</li>
|
<li data-list-item-id="e28fb424bcc0d06b97ddcbcbc5145c350"><kbd>Ctrl</kbd>+<kbd>C</kbd> to copy one or more notes based on selection
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>X</kbd> to cut a note.</li>
|
(see <a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/BFs8mudNFgCS/_help_IakOLONlIfGI">Cloning Notes</a>).</li>
|
||||||
<li><kbd>Ctrl</kbd>+<kbd>V</kbd> to paste it somewhere.</li>
|
<li
|
||||||
</ul>
|
data-list-item-id="e11c4c9fcdfeb566a58d9319a340ff893"><kbd>Ctrl</kbd>+<kbd>X</kbd> to cut one or more notes (for moving them).</li>
|
||||||
</li>
|
<li
|
||||||
<li>For <a class="reference-link" href="#root/_help_yTjUdsOi4CIE">Multiple selection</a>:
|
data-list-item-id="e242519cf16b3414242c4d11f20688b5b"><kbd>Ctrl</kbd>+<kbd>V</kbd> to paste them somewhere (which results in
|
||||||
<ul>
|
a copy or move based on the shortcut used).</li>
|
||||||
<li><kbd>Alt</kbd>+<kbd>Click</kbd>to add a single note to the current selection.</li>
|
</ul>
|
||||||
<li><kbd>Shift</kbd>+<kbd>Click</kbd>to select a range of notes, starting
|
<h2>Moving notes</h2>
|
||||||
from the current note (the highlighted one) to the one that is being clicked.</li>
|
<ul>
|
||||||
</ul>
|
<li data-list-item-id="ee2d0e5633e0ab23d0fcde7b968731794"><kbd>Ctrl</kbd> + <kbd><span>↑</span></kbd> , <kbd>Ctrl</kbd> + <kbd><span>↓</span></kbd> -
|
||||||
</li>
|
move note up/down in the note list.</li>
|
||||||
|
<li data-list-item-id="e14146e7aacfc92aa7daf8215ce4b379c"><kbd>Ctrl</kbd> + <kbd><span>←</span></kbd> - move note up in the note tree.</li>
|
||||||
|
<li
|
||||||
|
data-list-item-id="e21a7f5ab9d62af04b6ab81b0cc4cf8c7"><kbd>Ctrl</kbd>+<kbd><span>→</span></kbd> - move note down in the note
|
||||||
|
tree.</li>
|
||||||
|
<li data-list-item-id="e99f4b0aef9693ad25ca0ce62c5b67418"><kbd>Del</kbd> - deletes note and optionally its subtree (asked in the
|
||||||
|
dialog).</li>
|
||||||
|
</ul>
|
||||||
|
<h2>Multiple selection</h2>
|
||||||
|
<p>See <a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/oPVyFC7WL2Lp/_help_yTjUdsOi4CIE">Multiple selection</a> for
|
||||||
|
more information about how selection works.</p>
|
||||||
|
<ul>
|
||||||
|
<li data-list-item-id="ebe4907d702229ab599e50f753d23cfb6"><kbd>Alt</kbd>+<kbd>Click</kbd> – add a single note to the current selection.</li>
|
||||||
|
<li
|
||||||
|
data-list-item-id="ecf6bb49f8d993d376382dcab4e4a7ee8"><kbd>Shift</kbd>+<kbd>Click</kbd> – select a range of notes, starting from
|
||||||
|
the current note (the highlighted one) to the one that is being clicked.</li>
|
||||||
|
<li
|
||||||
|
data-list-item-id="eb1398c2cf85b53eafc3b7ab7a0974668"><kbd>Shift</kbd>+<kbd><span>↑</span></kbd>, <kbd>Shift</kbd>+<kbd><span>↓</span></kbd> –
|
||||||
|
multi-select not above/below.</li>
|
||||||
|
<li data-list-item-id="ebc1274f576f67d08a6d665a7318d80a8"><kbd>Ctrl</kbd>+<kbd>A</kbd> – select all notes in the current level</li>
|
||||||
</ul>
|
</ul>
|
||||||
13
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Collections/List View.html
generated
vendored
13
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Collections/List View.html
generated
vendored
@ -12,9 +12,9 @@
|
|||||||
as a single continuous document.</p>
|
as a single continuous document.</p>
|
||||||
<h2>Interaction</h2>
|
<h2>Interaction</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li data-list-item-id="e8a9709d9f325dab560cb24289d5ab231">Each note can be expanded or collapsed by clicking on the arrow to the
|
<li>Each note can be expanded or collapsed by clicking on the arrow to the
|
||||||
left of the title.</li>
|
left of the title.</li>
|
||||||
<li data-list-item-id="e38647a2388fb38e1c6de17b617db9e76">In the <a class="reference-link" href="#root/_help_BlN9DFI679QC">Ribbon</a>,
|
<li>In the <a class="reference-link" href="#root/_help_BlN9DFI679QC">Ribbon</a>,
|
||||||
in the <em>Collection</em> tab there are options to expand and to collapse
|
in the <em>Collection</em> tab there are options to expand and to collapse
|
||||||
all notes easily.</li>
|
all notes easily.</li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -25,16 +25,15 @@
|
|||||||
<p>If exported to PDF within the desktop application, there is additional
|
<p>If exported to PDF within the desktop application, there is additional
|
||||||
functionality:</p>
|
functionality:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li data-list-item-id="e06095ff0a3876a29bdc11f1a2f18dfdc">The table of contents of the PDF will reflect the structure of the notes.</li>
|
<li>The table of contents of the PDF will reflect the structure of the notes.</li>
|
||||||
<li
|
<li>Reference and inline links to other notes within the same hierarchy will
|
||||||
data-list-item-id="e656526a5aa019d58af324ae5c3d39216">Reference and inline links to other notes within the same hierarchy will
|
|
||||||
be functional (will jump to the corresponding page). If a link refers to
|
be functional (will jump to the corresponding page). If a link refers to
|
||||||
a note that is not in the printed hierarchy, it will be unlinked.</li>
|
a note that is not in the printed hierarchy, it will be unlinked.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Expanding and collapsing multiple notes at once</h2>
|
<h2>Expanding and collapsing multiple notes at once</h2>
|
||||||
<p>Apart from individually expanding or collapsing notes, it's also possible
|
<p>Apart from individually expanding or collapsing notes, it's also possible
|
||||||
to expand or collapse them all at once. To do so, go to the <em>Collection Properties</em> tab
|
to expand or collapse them all at once. To do so, go to the <em>Collection Properties</em> tab
|
||||||
in the <a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_BlN9DFI679QC">Ribbon</a> and
|
in the <a class="reference-link" href="#root/_help_BlN9DFI679QC">Ribbon</a> and
|
||||||
look for the corresponding button.</p>
|
look for the corresponding button.</p>
|
||||||
<p>By default, the <em>Expand</em> button will only expand the direct children
|
<p>By default, the <em>Expand</em> button will only expand the direct children
|
||||||
(first level) of the collection. Starting with v0.100.0, it's possible
|
(first level) of the collection. Starting with v0.100.0, it's possible
|
||||||
@ -45,7 +44,7 @@
|
|||||||
<aside class="admonition tip">
|
<aside class="admonition tip">
|
||||||
<p>By design, the UI provides only a handful of levels of depth for expanding
|
<p>By design, the UI provides only a handful of levels of depth for expanding
|
||||||
notes (direct children, 2-5, all levels). It's also possible to specify
|
notes (direct children, 2-5, all levels). It's also possible to specify
|
||||||
any desired depth by manually setting the <a href="#root/pOsGYCXsbNQG/tC7s2alapj8V/zEY4DaJG4YT5/_help_HI6GBBIduIgv">corresponding label</a>.
|
any desired depth by manually setting the <a href="#root/_help_HI6GBBIduIgv">corresponding label</a>.
|
||||||
For example: <code>#expanded=100</code> to expand up to 100 levels of depth.</p>
|
For example: <code>#expanded=100</code> to expand up to 100 levels of depth.</p>
|
||||||
</aside>
|
</aside>
|
||||||
<aside class="admonition note">
|
<aside class="admonition note">
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
# Documentation
|
# Documentation
|
||||||
There are multiple types of documentation for Trilium:<img class="image-style-align-right" src="api/images/VUKpkCok5Zh4/Documentation_image.png" width="205" height="162">
|
There are multiple types of documentation for Trilium:<img class="image-style-align-right" src="api/images/Xtlv3JlumknM/Documentation_image.png" width="205" height="162">
|
||||||
|
|
||||||
* The _User Guide_ represents the user-facing documentation. This documentation can be browsed by users directly from within Trilium, by pressing <kbd>F1</kbd>.
|
* The _User Guide_ represents the user-facing documentation. This documentation can be browsed by users directly from within Trilium, by pressing <kbd>F1</kbd>.
|
||||||
* The _Developer's Guide_ represents a set of Markdown documents that present the internals of Trilium, for developers.
|
* The _Developer's Guide_ represents a set of Markdown documents that present the internals of Trilium, for developers.
|
||||||
|
|||||||
56
docs/User Guide/!!!meta.json
vendored
56
docs/User Guide/!!!meta.json
vendored
@ -2380,13 +2380,6 @@
|
|||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 20
|
"position": 20
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "relation",
|
|
||||||
"name": "internalLink",
|
|
||||||
"value": "yTjUdsOi4CIE",
|
|
||||||
"isInheritable": false,
|
|
||||||
"position": 30
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "label",
|
"type": "label",
|
||||||
"name": "iconClass",
|
"name": "iconClass",
|
||||||
@ -2400,6 +2393,20 @@
|
|||||||
"value": "keyboard-shortcuts",
|
"value": "keyboard-shortcuts",
|
||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 40
|
"position": 40
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation",
|
||||||
|
"name": "internalLink",
|
||||||
|
"value": "IakOLONlIfGI",
|
||||||
|
"isInheritable": false,
|
||||||
|
"position": 50
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation",
|
||||||
|
"name": "internalLink",
|
||||||
|
"value": "yTjUdsOi4CIE",
|
||||||
|
"isInheritable": false,
|
||||||
|
"position": 60
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"format": "markdown",
|
"format": "markdown",
|
||||||
@ -5211,13 +5218,6 @@
|
|||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 20
|
"position": 20
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"type": "relation",
|
|
||||||
"name": "internalLink",
|
|
||||||
"value": "IakOLONlIfGI",
|
|
||||||
"isInheritable": false,
|
|
||||||
"position": 30
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"type": "relation",
|
"type": "relation",
|
||||||
"name": "internalLink",
|
"name": "internalLink",
|
||||||
@ -5259,6 +5259,20 @@
|
|||||||
"value": "bx bxs-keyboard",
|
"value": "bx bxs-keyboard",
|
||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 80
|
"position": 80
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation",
|
||||||
|
"name": "internalLink",
|
||||||
|
"value": "DvdZhoQZY9Yd",
|
||||||
|
"isInheritable": false,
|
||||||
|
"position": 90
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "relation",
|
||||||
|
"name": "internalLink",
|
||||||
|
"value": "TBwsyfadTA18",
|
||||||
|
"isInheritable": false,
|
||||||
|
"position": 100
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"format": "markdown",
|
"format": "markdown",
|
||||||
@ -10576,6 +10590,13 @@
|
|||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 30
|
"position": 30
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "relation",
|
||||||
|
"name": "internalLink",
|
||||||
|
"value": "HI6GBBIduIgv",
|
||||||
|
"isInheritable": false,
|
||||||
|
"position": 40
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "label",
|
"type": "label",
|
||||||
"name": "iconClass",
|
"name": "iconClass",
|
||||||
@ -10589,13 +10610,6 @@
|
|||||||
"value": "list",
|
"value": "list",
|
||||||
"isInheritable": false,
|
"isInheritable": false,
|
||||||
"position": 30
|
"position": 30
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "relation",
|
|
||||||
"name": "internalLink",
|
|
||||||
"value": "HI6GBBIduIgv",
|
|
||||||
"isInheritable": false,
|
|
||||||
"position": 40
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"format": "markdown",
|
"format": "markdown",
|
||||||
|
|||||||
@ -3,49 +3,38 @@ This is supposed to be a complete list of keyboard shortcuts. Note that some of
|
|||||||
|
|
||||||
It is also possible to configure most keyboard shortcuts in Options -> Keyboard shortcuts. Using `global:` prefix, you can assign a shortcut which will work even without Trilium being in focus (requires app restart to take effect).
|
It is also possible to configure most keyboard shortcuts in Options -> Keyboard shortcuts. Using `global:` prefix, you can assign a shortcut which will work even without Trilium being in focus (requires app restart to take effect).
|
||||||
|
|
||||||
|
## Tree
|
||||||
|
|
||||||
|
See the corresponding section: <a class="reference-link" href="UI%20Elements/Note%20Tree/Keyboard%20shortcuts.md">Keyboard shortcuts</a>
|
||||||
|
|
||||||
## Note navigation
|
## Note navigation
|
||||||
|
|
||||||
* <kbd><span>↑</span></kbd>, <kbd><span>↓</span></kbd> - go up/down in the list of notes, <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd><span>↑</span></kbd> and <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd><span>↓</span></kbd> work also from editor
|
* <kbd>Alt</kbd> + <kbd><span>←</span></kbd>, <kbd>Alt</kbd> + <kbd><span>→</span></kbd> – go back / forwards in the history
|
||||||
* <kbd><span>←</span></kbd>, <kbd><span>→</span></kbd> - collapse/expand node
|
* <kbd>Ctrl</kbd> + <kbd>J</kbd> – show ["Jump to" dialog](Navigation/Note%20Navigation.md)
|
||||||
* <kbd>Alt</kbd> + <kbd><span>←</span></kbd>, <kbd>Alt</kbd> + <kbd><span>→</span></kbd> - go back / forwards in the history
|
* <kbd>Ctrl</kbd> + <kbd>.</kbd> – scroll to current note (useful when you scroll away from your note or your focus is currently in the editor)
|
||||||
* <kbd>Ctrl</kbd> + <kbd>J</kbd> - show ["Jump to" dialog](Navigation/Note%20Navigation.md)
|
* <kbd><span>Backspace</span></kbd> – jumps to parent note
|
||||||
* <kbd>Ctrl</kbd> + <kbd>.</kbd> - scroll to current note (useful when you scroll away from your note or your focus is currently in the editor)
|
* <kbd>Alt</kbd> + <kbd>C</kbd> – collapse whole note tree
|
||||||
* <kbd><span>Backspace</span></kbd> - jumps to parent note
|
* <kbd>Alt</kbd> + <kbd>-</kbd> (alt with minus sign) – collapse subtree (if some subtree takes too much space on tree pane you can collapse it)
|
||||||
* <kbd>Alt</kbd> + <kbd>C</kbd> - collapse whole note tree
|
|
||||||
* <kbd>Alt</kbd> + <kbd>-</kbd> (alt with minus sign) - collapse subtree (if some subtree takes too much space on tree pane you can collapse it)
|
|
||||||
* you can define a [label](../Advanced%20Usage/Attributes.md) `#keyboardShortcut` with e.g. value <kbd>Ctrl</kbd> + <kbd>I</kbd> . Pressing this keyboard combination will then bring you to the note on which it is defined. Note that Trilium must be reloaded/restarted (<kbd>Ctrl</kbd> + <kbd>R</kbd> ) for changes to be in effect.
|
* you can define a [label](../Advanced%20Usage/Attributes.md) `#keyboardShortcut` with e.g. value <kbd>Ctrl</kbd> + <kbd>I</kbd> . Pressing this keyboard combination will then bring you to the note on which it is defined. Note that Trilium must be reloaded/restarted (<kbd>Ctrl</kbd> + <kbd>R</kbd> ) for changes to be in effect.
|
||||||
|
|
||||||
See demo of some of these features in [note navigation](Navigation/Note%20Navigation.md).
|
See demo of some of these features in [note navigation](Navigation/Note%20Navigation.md).
|
||||||
|
|
||||||
## Tabs
|
## Tabs
|
||||||
|
|
||||||
* <kbd>Ctrl</kbd> + <kbd>🖱 Left click</kbd> - (or middle mouse click) on note link opens note in a new tab
|
* <kbd>Ctrl</kbd> + <kbd>🖱 Left click</kbd> – (or middle mouse click) on note link opens note in a new tab
|
||||||
|
|
||||||
Only in desktop (electron build):
|
Only in desktop (electron build):
|
||||||
|
|
||||||
* <kbd>Ctrl</kbd> + <kbd>T</kbd> - opens empty tab
|
* <kbd>Ctrl</kbd> + <kbd>T</kbd> – opens empty tab
|
||||||
* <kbd>Ctrl</kbd> + <kbd>W</kbd> - closes active tab
|
* <kbd>Ctrl</kbd> + <kbd>W</kbd> – closes active tab
|
||||||
* <kbd>Ctrl</kbd> + <kbd>Tab</kbd> - activates next tab
|
* <kbd>Ctrl</kbd> + <kbd>Tab</kbd> – activates next tab
|
||||||
* <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>Tab</kbd> - activates previous tab
|
* <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>Tab</kbd> – activates previous tab
|
||||||
|
|
||||||
## Creating notes
|
## Creating notes
|
||||||
|
|
||||||
* `CTRL+O` - creates new note after the current note
|
* <kbd>CTRL</kbd>+<kbd>O</kbd> – creates new note after the current note
|
||||||
* `CTRL+P` - creates new sub-note into current note
|
* <kbd>CTRL</kbd>+<kbd>P</kbd> – creates new sub-note into current note
|
||||||
* `F2` - edit [prefix](Navigation/Note%20Navigation.md) of current note clone
|
* <kbd>F2</kbd> – edit <a class="reference-link" href="Notes/Cloning%20Notes/Branch%20prefix.md">Branch prefix</a> of current note clone
|
||||||
|
|
||||||
## Moving / cloning notes
|
|
||||||
|
|
||||||
* <kbd>Ctrl</kbd> + <kbd><span>↑</span></kbd> , Ctrl + <kbd><span>↓</span></kbd> - move note up/down in the note list
|
|
||||||
* <kbd>Ctrl</kbd> + <kbd><span>←</span></kbd> - move note up in the note tree
|
|
||||||
* <kbd>Ctrl</kbd>+<kbd><span>→</span></kbd> - move note down in the note tree
|
|
||||||
* <kbd>Shift</kbd>+<kbd><span>↑</span></kbd>, <kbd>Shift</kbd>`+`<kbd><span>↓</span></kbd> - multi-select note above/below
|
|
||||||
* <kbd>Ctrl</kbd>+<kbd>A</kbd> - select all notes in the current level
|
|
||||||
* <kbd>Shift</kbd>+<kbd>🖱 Left click</kbd> - multi select note which you clicked on
|
|
||||||
* <kbd>Ctrl</kbd>+<kbd>C</kbd> - copies current note (or current selection) into clipboard (used for [cloning](Notes/Cloning%20Notes.md)
|
|
||||||
* <kbd>Ctrl</kbd>+<kbd>X</kbd> - cuts current (or current selection) note into clipboard (used for moving notes)
|
|
||||||
* <kbd>Ctrl</kbd>+<kbd>V</kbd> - pastes note(s) as sub-note into current note (which is either move or clone depending on whether it was copied or cut into clipboard)
|
|
||||||
* <kbd>Del</kbd> - delete note / sub-tree
|
|
||||||
|
|
||||||
## Editing notes
|
## Editing notes
|
||||||
|
|
||||||
@ -53,22 +42,22 @@ Only in desktop (electron build):
|
|||||||
> For keyboard shortcuts specific to <a class="reference-link" href="../Note%20Types/Text.md">Text</a> notes, refer to <a class="reference-link" href="../Note%20Types/Text/Keyboard%20shortcuts.md">Keyboard shortcuts</a> and <a class="reference-link" href="../Note%20Types/Text/Markdown-like%20formatting.md">Markdown-like formatting</a>.
|
> For keyboard shortcuts specific to <a class="reference-link" href="../Note%20Types/Text.md">Text</a> notes, refer to <a class="reference-link" href="../Note%20Types/Text/Keyboard%20shortcuts.md">Keyboard shortcuts</a> and <a class="reference-link" href="../Note%20Types/Text/Markdown-like%20formatting.md">Markdown-like formatting</a>.
|
||||||
|
|
||||||
* <kbd>Enter</kbd> in tree pane switches from tree pane into note title. Enter from note title switches focus to text editor. <kbd>Ctrl</kbd>+<kbd>.</kbd> switches back from editor to tree pane.
|
* <kbd>Enter</kbd> in tree pane switches from tree pane into note title. Enter from note title switches focus to text editor. <kbd>Ctrl</kbd>+<kbd>.</kbd> switches back from editor to tree pane.
|
||||||
* <kbd>Ctrl</kbd>+<kbd>.</kbd> - jump away from the editor to tree pane and scroll to current note
|
* <kbd>Ctrl</kbd>+<kbd>.</kbd> – jump away from the editor to tree pane and scroll to current note
|
||||||
|
|
||||||
## Runtime shortcuts
|
## Runtime shortcuts
|
||||||
|
|
||||||
These are hooked in Electron to be similar to native browser keyboard shortcuts.
|
These are hooked in Electron to be similar to native browser keyboard shortcuts.
|
||||||
|
|
||||||
* <kbd>F5</kbd>, <kbd>Ctrl</kbd>\-<kbd>R</kbd> - reloads Trilium front-end
|
* <kbd>F5</kbd>, <kbd>Ctrl</kbd>+<kbd>R</kbd> – reloads Trilium front-end
|
||||||
* <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd> - show developer tools
|
* <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>I</kbd> – show developer tools
|
||||||
* <kbd>Ctrl</kbd>+<kbd>F</kbd> - show search dialog
|
* <kbd>Ctrl</kbd>+<kbd>F</kbd> – show search dialog
|
||||||
* <kbd>Ctrl</kbd>+<kbd>-</kbd> - zoom out
|
* <kbd>Ctrl</kbd>+<kbd>-</kbd> – zoom out
|
||||||
* <kbd>Ctrl</kbd>+<kbd>=</kbd> - zoom in
|
* <kbd>Ctrl</kbd>+<kbd>=</kbd> – zoom in
|
||||||
|
|
||||||
## Other
|
## Other
|
||||||
|
|
||||||
* <kbd>Alt</kbd>+<kbd>O</kbd> - show SQL console (use only if you know what you're doing)
|
* <kbd>Alt</kbd> + <kbd>O</kbd> – show SQL console (use only if you know what you're doing)
|
||||||
* <kbd>Alt</kbd>+<kbd>M</kbd> - distraction-free mode - display only note editor, everything else is hidden
|
* <kbd>Alt</kbd> + <kbd>M</kbd> – distraction-free mode - display only note editor, everything else is hidden
|
||||||
* <kbd>F11</kbd> - toggle full screen
|
* <kbd>F11</kbd> – toggle full screen
|
||||||
* <kbd>Ctrl</kbd> + <kbd>S</kbd> - toggle [search](Navigation/Search.md) form in tree pane
|
* <kbd>Ctrl</kbd> + <kbd>S</kbd> – toggle [search](Navigation/Search.md) form in tree pane
|
||||||
* <kbd>Alt</kbd> +<kbd>A</kbd> - show note [attributes](../Advanced%20Usage/Attributes.md) dialog
|
* <kbd>Alt</kbd> +<kbd>A</kbd> – show note [attributes](../Advanced%20Usage/Attributes.md) dialog
|
||||||
@ -1,17 +1,36 @@
|
|||||||
# Keyboard shortcuts
|
# Keyboard shortcuts
|
||||||
The <a class="reference-link" href="../Note%20Tree.md">Note Tree</a> comes with multiple keyboard shortcuts to make editing faster:
|
The <a class="reference-link" href="../Note%20Tree.md">Note Tree</a> comes with multiple keyboard shortcuts to make editing faster:
|
||||||
|
|
||||||
* Opening notes:
|
## Navigation within the tree
|
||||||
* <kbd>Click</kbd> to open the note in the current tab.
|
|
||||||
* <kbd>Ctrl</kbd>+<kbd>Click</kbd> or <kbd>Middle click</kbd> to open the note in a new tab.
|
* <kbd><span>↑</span></kbd> and <kbd><span>↑</span></kbd> to navigate between notes.
|
||||||
* <kbd>Ctrl</kbd>+<kbd>Right click</kbd> to open the note in <a class="reference-link" href="../../Navigation/Quick%20edit.md">Quick edit</a>.
|
* <kbd><span>←</span></kbd> to collapse a note with children, or <kbd><span>→</span></kbd> to expand it.
|
||||||
* Navigation within the tree:
|
* <kbd><span>←</span></kbd> on a note with no children to navigate to its parent.
|
||||||
* <kbd>Up</kbd> and <kbd>Down</kbd> to navigate between notes.
|
|
||||||
* <kbd>Left</kbd> to collapse a note, or <kbd>Right</kbd> to expand it.
|
## Opening notes
|
||||||
* Clipboard management:
|
|
||||||
* <kbd>Ctrl</kbd>+<kbd>C</kbd> to copy a note.
|
* <kbd>Click</kbd> to open the note in the current tab.
|
||||||
* <kbd>Ctrl</kbd>+<kbd>X</kbd> to cut a note.
|
* <kbd>Ctrl</kbd>+<kbd>Click</kbd> or <kbd>Middle click</kbd> to open the note in a new tab.
|
||||||
* <kbd>Ctrl</kbd>+<kbd>V</kbd> to paste it somewhere.
|
* <kbd>Ctrl</kbd>+<kbd>Right click</kbd> to open the note in <a class="reference-link" href="../../Navigation/Quick%20edit.md">Quick edit</a>.
|
||||||
* For <a class="reference-link" href="Multiple%20selection.md">Multiple selection</a>:
|
|
||||||
* <kbd>Alt</kbd>+<kbd>Click</kbd>to add a single note to the current selection.
|
## Clipboard management
|
||||||
* <kbd>Shift</kbd>+<kbd>Click</kbd>to select a range of notes, starting from the current note (the highlighted one) to the one that is being clicked.
|
|
||||||
|
* <kbd>Ctrl</kbd>+<kbd>C</kbd> to copy one or more notes based on selection (see <a class="reference-link" href="../../Notes/Cloning%20Notes.md">Cloning Notes</a>).
|
||||||
|
* <kbd>Ctrl</kbd>+<kbd>X</kbd> to cut one or more notes (for moving them).
|
||||||
|
* <kbd>Ctrl</kbd>+<kbd>V</kbd> to paste them somewhere (which results in a copy or move based on the shortcut used).
|
||||||
|
|
||||||
|
## Moving notes
|
||||||
|
|
||||||
|
* <kbd>Ctrl</kbd> + <kbd><span>↑</span></kbd> , <kbd>Ctrl</kbd> + <kbd><span>↓</span></kbd> - move note up/down in the note list.
|
||||||
|
* <kbd>Ctrl</kbd> + <kbd><span>←</span></kbd> - move note up in the note tree.
|
||||||
|
* <kbd>Ctrl</kbd>+<kbd><span>→</span></kbd> - move note down in the note tree.
|
||||||
|
* <kbd>Del</kbd> - deletes note and optionally its subtree (asked in the dialog).
|
||||||
|
|
||||||
|
## Multiple selection
|
||||||
|
|
||||||
|
See <a class="reference-link" href="Multiple%20selection.md">Multiple selection</a> for more information about how selection works.
|
||||||
|
|
||||||
|
* <kbd>Alt</kbd>+<kbd>Click</kbd> – add a single note to the current selection.
|
||||||
|
* <kbd>Shift</kbd>+<kbd>Click</kbd> – select a range of notes, starting from the current note (the highlighted one) to the one that is being clicked.
|
||||||
|
* <kbd>Shift</kbd>+<kbd><span>↑</span></kbd>, <kbd>Shift</kbd>+<kbd><span>↓</span></kbd> – multi-select not above/below.
|
||||||
|
* <kbd>Ctrl</kbd>+<kbd>A</kbd> – select all notes in the current level
|
||||||
@ -71,6 +71,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ckeditor/ckeditor5-icons": "47.2.0"
|
"@ckeditor/ckeditor5-icons": "47.2.0",
|
||||||
|
"mathlive": "0.108.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
import ckeditor from './../theme/icons/math.svg?raw';
|
import ckeditor from './../theme/icons/math.svg?raw';
|
||||||
import './augmentation.js';
|
import './augmentation.js';
|
||||||
import "../theme/mathform.css";
|
import "../theme/mathform.css";
|
||||||
|
import 'mathlive';
|
||||||
|
import 'mathlive/fonts.css';
|
||||||
|
import 'mathlive/static.css';
|
||||||
|
|
||||||
export { default as Math } from './math.js';
|
export { default as Math } from './math.js';
|
||||||
export { default as MathUI } from './mathui.js';
|
export { default as MathUI } from './mathui.js';
|
||||||
|
|||||||
@ -56,7 +56,7 @@ export default class MathUI extends Plugin {
|
|||||||
this._balloon.showStack( 'main' );
|
this._balloon.showStack( 'main' );
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
this.formView?.mathInputView.fieldView.element?.focus();
|
this.formView?.mathLiveInputView.focus();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,31 +71,38 @@ export default class MathUI extends Plugin {
|
|||||||
throw new CKEditorError( 'math-command' );
|
throw new CKEditorError( 'math-command' );
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
const mathConfig = editor.config.get( 'math' )!;
|
const mathConfig = editor.config.get( 'math' )!;
|
||||||
|
|
||||||
const formView = new MainFormView(
|
const formView = new MainFormView(
|
||||||
editor.locale,
|
editor.locale,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
{
|
||||||
mathConfig.engine!,
|
engine: mathConfig.engine!,
|
||||||
mathConfig.lazyLoad,
|
lazyLoad: mathConfig.lazyLoad,
|
||||||
|
previewUid: this._previewUid,
|
||||||
|
previewClassName: mathConfig.previewClassName!,
|
||||||
|
katexRenderOptions: mathConfig.katexRenderOptions!
|
||||||
|
},
|
||||||
mathConfig.enablePreview,
|
mathConfig.enablePreview,
|
||||||
this._previewUid,
|
mathConfig.popupClassName!
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
mathConfig.previewClassName!,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
mathConfig.popupClassName!,
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
mathConfig.katexRenderOptions!
|
|
||||||
);
|
);
|
||||||
|
|
||||||
formView.mathInputView.bind( 'value' ).to( mathCommand, 'value' );
|
formView.mathLiveInputView.bind( 'value' ).to( mathCommand, 'value' );
|
||||||
formView.displayButtonView.bind( 'isOn' ).to( mathCommand, 'display' );
|
formView.displayButtonView.bind( 'isOn' ).to( mathCommand, 'display' );
|
||||||
|
|
||||||
// Form elements should be read-only when corresponding commands are disabled.
|
// Form elements should be read-only when corresponding commands are disabled.
|
||||||
formView.mathInputView.bind( 'isReadOnly' ).to( mathCommand, 'isEnabled', value => !value );
|
formView.mathLiveInputView.bind( 'isReadOnly' ).to( mathCommand, 'isEnabled', value => !value );
|
||||||
formView.saveButtonView.bind( 'isEnabled' ).to( mathCommand );
|
formView.saveButtonView.bind( 'isEnabled' ).to(
|
||||||
formView.displayButtonView.bind( 'isEnabled' ).to( mathCommand );
|
mathCommand,
|
||||||
|
'isEnabled',
|
||||||
|
formView.mathLiveInputView,
|
||||||
|
'value',
|
||||||
|
( commandEnabled, equation ) => {
|
||||||
|
const normalizedEquation = ( equation ?? '' ).trim();
|
||||||
|
return commandEnabled && normalizedEquation.length > 0;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
formView.displayButtonView.bind( 'isEnabled' ).to( mathCommand, 'isEnabled' );
|
||||||
|
|
||||||
// Listen to submit button click
|
// Listen to submit button click
|
||||||
this.listenTo( formView, 'submit', () => {
|
this.listenTo( formView, 'submit', () => {
|
||||||
@ -122,18 +129,6 @@ export default class MathUI extends Plugin {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Allow the textarea to be resizable
|
|
||||||
formView.mathInputView.fieldView.once('render', () => {
|
|
||||||
const textarea = formView.mathInputView.fieldView.element;
|
|
||||||
if (!textarea) return;
|
|
||||||
Object.assign(textarea.style, {
|
|
||||||
resize: 'both',
|
|
||||||
height: '100px',
|
|
||||||
width: '400px',
|
|
||||||
minWidth: '100%',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return formView;
|
return formView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,14 +157,14 @@ export default class MathUI extends Plugin {
|
|||||||
} );
|
} );
|
||||||
|
|
||||||
if ( this._balloon.visibleView === this.formView ) {
|
if ( this._balloon.visibleView === this.formView ) {
|
||||||
this.formView.mathInputView.fieldView.element?.select();
|
this.formView.mathLiveInputView.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show preview element
|
// Show preview element
|
||||||
const previewEl = document.getElementById( this._previewUid );
|
const previewEl = document.getElementById( this._previewUid );
|
||||||
if ( previewEl && this.formView.previewEnabled ) {
|
if ( previewEl && this.formView.mathView ) {
|
||||||
// Force refresh preview
|
// Force refresh preview
|
||||||
this.formView.mathView?.updateMath();
|
this.formView.mathView.updateMath();
|
||||||
}
|
}
|
||||||
|
|
||||||
this.formView.equation = mathCommand.value ?? '';
|
this.formView.equation = mathCommand.value ?? '';
|
||||||
|
|||||||
@ -1,270 +1,219 @@
|
|||||||
import { ButtonView, createLabeledTextarea, FocusCycler, LabelView, LabeledFieldView, submitHandler, SwitchButtonView, View, ViewCollection, type TextareaView, type FocusableView, Locale, FocusTracker, KeystrokeHandler } from 'ckeditor5';
|
import {
|
||||||
import IconCheck from "@ckeditor/ckeditor5-icons/theme/icons/check.svg?raw";
|
ButtonView,
|
||||||
import IconCancel from "@ckeditor/ckeditor5-icons/theme/icons/cancel.svg?raw";
|
FocusCycler,
|
||||||
|
LabelView,
|
||||||
|
submitHandler,
|
||||||
|
SwitchButtonView,
|
||||||
|
View,
|
||||||
|
ViewCollection,
|
||||||
|
type FocusableView,
|
||||||
|
Locale,
|
||||||
|
FocusTracker,
|
||||||
|
KeystrokeHandler
|
||||||
|
} from 'ckeditor5';
|
||||||
|
import IconCheck from '@ckeditor/ckeditor5-icons/theme/icons/check.svg?raw';
|
||||||
|
import IconCancel from '@ckeditor/ckeditor5-icons/theme/icons/cancel.svg?raw';
|
||||||
import { extractDelimiters, hasDelimiters } from '../utils.js';
|
import { extractDelimiters, hasDelimiters } from '../utils.js';
|
||||||
import MathView from './mathview.js';
|
import MathView, { type MathViewOptions } from './mathview.js';
|
||||||
|
import MathLiveInputView from './mathliveinputview.js';
|
||||||
|
import RawLatexInputView from './rawlatexinputview.js';
|
||||||
import '../../theme/mathform.css';
|
import '../../theme/mathform.css';
|
||||||
import type { KatexOptions } from '../typings-external.js';
|
|
||||||
|
|
||||||
class MathInputView extends LabeledFieldView<TextareaView> {
|
|
||||||
public value: null | string = null;
|
|
||||||
public isReadOnly = false;
|
|
||||||
|
|
||||||
constructor( locale: Locale ) {
|
|
||||||
super( locale, createLabeledTextarea );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class MainFormView extends View {
|
export default class MainFormView extends View {
|
||||||
public saveButtonView: ButtonView;
|
public saveButtonView: ButtonView;
|
||||||
public mathInputView: MathInputView;
|
|
||||||
public displayButtonView: SwitchButtonView;
|
|
||||||
public cancelButtonView: ButtonView;
|
public cancelButtonView: ButtonView;
|
||||||
public previewEnabled: boolean;
|
public displayButtonView: SwitchButtonView;
|
||||||
public previewLabel?: LabelView;
|
|
||||||
|
public mathLiveInputView: MathLiveInputView;
|
||||||
|
public rawLatexInputView: RawLatexInputView;
|
||||||
public mathView?: MathView;
|
public mathView?: MathView;
|
||||||
public override locale: Locale = new Locale();
|
|
||||||
public lazyLoad: undefined | ( () => Promise<void> );
|
public focusTracker = new FocusTracker();
|
||||||
|
public keystrokes = new KeystrokeHandler();
|
||||||
|
private _focusables = new ViewCollection<FocusableView>();
|
||||||
|
private _focusCycler: FocusCycler;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
locale: Locale,
|
locale: Locale,
|
||||||
engine:
|
mathViewOptions: MathViewOptions,
|
||||||
| 'mathjax'
|
|
||||||
| 'katex'
|
|
||||||
| ( (
|
|
||||||
equation: string,
|
|
||||||
element: HTMLElement,
|
|
||||||
display: boolean,
|
|
||||||
) => void ),
|
|
||||||
lazyLoad: undefined | ( () => Promise<void> ),
|
|
||||||
previewEnabled = false,
|
previewEnabled = false,
|
||||||
previewUid: string,
|
popupClassName: string[] = []
|
||||||
previewClassName: Array<string>,
|
|
||||||
popupClassName: Array<string>,
|
|
||||||
katexRenderOptions: KatexOptions
|
|
||||||
) {
|
) {
|
||||||
super( locale );
|
super( locale );
|
||||||
|
|
||||||
const t = locale.t;
|
const t = locale.t;
|
||||||
|
|
||||||
// Submit button
|
// --- 1. View Initialization ---
|
||||||
this.saveButtonView = this._createButton( t( 'Save' ), IconCheck, 'ck-button-save', null );
|
|
||||||
|
this.mathLiveInputView = new MathLiveInputView( locale );
|
||||||
|
this.rawLatexInputView = new RawLatexInputView( locale );
|
||||||
|
this.rawLatexInputView.label = t( 'LaTeX' );
|
||||||
|
|
||||||
|
this.saveButtonView = this._createButton( t( 'Save' ), IconCheck, 'ck-button-save' );
|
||||||
this.saveButtonView.type = 'submit';
|
this.saveButtonView.type = 'submit';
|
||||||
|
|
||||||
// Equation input
|
this.cancelButtonView = this._createButton( t( 'Cancel' ), IconCancel, 'ck-button-cancel' );
|
||||||
this.mathInputView = this._createMathInput();
|
this.cancelButtonView.delegate( 'execute' ).to( this, 'cancel' );
|
||||||
|
|
||||||
// Display button
|
this.displayButtonView = this._createDisplayButton( t );
|
||||||
this.displayButtonView = this._createDisplayButton();
|
|
||||||
|
|
||||||
// Cancel button
|
// --- 2. Construct Children & Preview ---
|
||||||
this.cancelButtonView = this._createButton( t( 'Cancel' ), IconCancel, 'ck-button-cancel', 'cancel' );
|
|
||||||
|
|
||||||
this.previewEnabled = previewEnabled;
|
const children: View[] = [
|
||||||
|
this.mathLiveInputView,
|
||||||
|
this.rawLatexInputView,
|
||||||
|
this.displayButtonView
|
||||||
|
];
|
||||||
|
|
||||||
let children = [];
|
if ( previewEnabled ) {
|
||||||
if ( this.previewEnabled ) {
|
const previewLabel = new LabelView( locale );
|
||||||
// Preview label
|
previewLabel.text = t( 'Equation preview' );
|
||||||
this.previewLabel = new LabelView( locale );
|
|
||||||
this.previewLabel.text = t( 'Equation preview' );
|
|
||||||
|
|
||||||
// Math element
|
// Clean instantiation using the options object
|
||||||
this.mathView = new MathView( engine, lazyLoad, locale, previewUid, previewClassName, katexRenderOptions );
|
this.mathView = new MathView( locale, mathViewOptions );
|
||||||
|
|
||||||
|
// Bind display mode: When button flips, preview updates automatically
|
||||||
this.mathView.bind( 'display' ).to( this.displayButtonView, 'isOn' );
|
this.mathView.bind( 'display' ).to( this.displayButtonView, 'isOn' );
|
||||||
|
|
||||||
children = [
|
children.push( previewLabel, this.mathView );
|
||||||
this.mathInputView,
|
|
||||||
this.displayButtonView,
|
|
||||||
this.previewLabel,
|
|
||||||
this.mathView
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
children = [
|
|
||||||
this.mathInputView,
|
|
||||||
this.displayButtonView
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add UI elements to template
|
// --- 3. Sync Logic ---
|
||||||
|
this._setupInputSync( previewEnabled );
|
||||||
|
|
||||||
|
// --- 4. Template Setup ---
|
||||||
this.setTemplate( {
|
this.setTemplate( {
|
||||||
tag: 'form',
|
tag: 'form',
|
||||||
attributes: {
|
attributes: {
|
||||||
class: [
|
class: [ 'ck', 'ck-math-form', ...popupClassName ],
|
||||||
'ck',
|
|
||||||
'ck-math-form',
|
|
||||||
...popupClassName
|
|
||||||
],
|
|
||||||
tabindex: '-1',
|
tabindex: '-1',
|
||||||
spellcheck: 'false'
|
spellcheck: 'false'
|
||||||
},
|
},
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
tag: 'div',
|
tag: 'div',
|
||||||
attributes: {
|
attributes: { class: [ 'ck-math-scroll' ] },
|
||||||
class: [
|
children: [ { tag: 'div', attributes: { class: [ 'ck-math-view' ] }, children } ]
|
||||||
'ck-math-view'
|
|
||||||
]
|
|
||||||
},
|
|
||||||
children
|
|
||||||
},
|
},
|
||||||
this.saveButtonView,
|
{
|
||||||
this.cancelButtonView
|
tag: 'div',
|
||||||
|
attributes: { class: [ 'ck-math-button-row' ] },
|
||||||
|
children: [ this.saveButtonView, this.cancelButtonView ]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
// --- 5. Accessibility ---
|
||||||
|
this._focusCycler = new FocusCycler( {
|
||||||
|
focusables: this._focusables,
|
||||||
|
focusTracker: this.focusTracker,
|
||||||
|
keystrokeHandler: this.keystrokes,
|
||||||
|
actions: { focusPrevious: 'shift + tab', focusNext: 'tab' }
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
public override render(): void {
|
public override render(): void {
|
||||||
super.render();
|
super.render();
|
||||||
|
|
||||||
// Prevent default form submit event & trigger custom 'submit'
|
submitHandler( { view: this } );
|
||||||
submitHandler( {
|
|
||||||
view: this
|
|
||||||
} );
|
|
||||||
|
|
||||||
// Register form elements to focusable elements
|
// Register focusables
|
||||||
const childViews = [
|
[
|
||||||
this.mathInputView,
|
this.mathLiveInputView,
|
||||||
|
this.rawLatexInputView,
|
||||||
this.displayButtonView,
|
this.displayButtonView,
|
||||||
this.saveButtonView,
|
this.saveButtonView,
|
||||||
this.cancelButtonView
|
this.cancelButtonView
|
||||||
];
|
].forEach( v => {
|
||||||
|
|
||||||
childViews.forEach( v => {
|
|
||||||
if ( v.element ) {
|
if ( v.element ) {
|
||||||
this._focusables.add( v );
|
this._focusables.add( v );
|
||||||
this.focusTracker.add( v.element );
|
this.focusTracker.add( v.element );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// Listen to keypresses inside form element
|
if ( this.element ) this.keystrokes.listenTo( this.element );
|
||||||
if ( this.element ) {
|
}
|
||||||
this.keystrokes.listenTo( this.element );
|
|
||||||
}
|
public get equation(): string {
|
||||||
|
return this.mathLiveInputView.value ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public set equation( equation: string ) {
|
||||||
|
const norm = equation.trim();
|
||||||
|
// Direct updates to the "source of truth"
|
||||||
|
this.mathLiveInputView.value = norm.length ? norm : null;
|
||||||
|
this.rawLatexInputView.value = norm;
|
||||||
|
if ( this.mathView ) this.mathView.value = norm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public focus(): void {
|
public focus(): void {
|
||||||
this._focusCycler.focusFirst();
|
this._focusCycler.focusFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
public get equation(): string {
|
/**
|
||||||
return this.mathInputView.fieldView.element?.value ?? '';
|
* Sets up split handlers for synchronization.
|
||||||
}
|
*/
|
||||||
|
private _setupInputSync( previewEnabled: boolean ): void {
|
||||||
|
// Handler 1: MathLive -> Raw LaTeX
|
||||||
|
this.mathLiveInputView.on( 'change:value', () => {
|
||||||
|
let eq = ( this.mathLiveInputView.value ?? '' ).trim();
|
||||||
|
|
||||||
public set equation( equation: string ) {
|
// Delimiter Normalization
|
||||||
if ( this.mathInputView.fieldView.element ) {
|
if ( hasDelimiters( eq ) ) {
|
||||||
this.mathInputView.fieldView.element.value = equation;
|
const params = extractDelimiters( eq );
|
||||||
}
|
eq = params.equation;
|
||||||
if ( this.previewEnabled && this.mathView ) {
|
this.displayButtonView.isOn = params.display;
|
||||||
this.mathView.value = equation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public focusTracker: FocusTracker = new FocusTracker();
|
// UX Fix: If we stripped delimiters, update the source
|
||||||
public keystrokes: KeystrokeHandler = new KeystrokeHandler();
|
// so the visual editor doesn't show them.
|
||||||
private _focusables = new ViewCollection<FocusableView>();
|
if ( this.mathLiveInputView.value !== eq ) {
|
||||||
private _focusCycler: FocusCycler = new FocusCycler( {
|
this.mathLiveInputView.value = eq;
|
||||||
focusables: this._focusables,
|
|
||||||
focusTracker: this.focusTracker,
|
|
||||||
keystrokeHandler: this.keystrokes,
|
|
||||||
actions: {
|
|
||||||
focusPrevious: 'shift + tab',
|
|
||||||
focusNext: 'tab'
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
private _createMathInput() {
|
|
||||||
const t = this.locale.t;
|
|
||||||
|
|
||||||
// Create equation input
|
|
||||||
const mathInput = new MathInputView( this.locale );
|
|
||||||
const fieldView = mathInput.fieldView;
|
|
||||||
mathInput.infoText = t( 'Insert equation in TeX format.' );
|
|
||||||
|
|
||||||
const onInput = () => {
|
|
||||||
if ( fieldView.element != null ) {
|
|
||||||
let equationInput = fieldView.element.value.trim();
|
|
||||||
|
|
||||||
// If input has delimiters
|
|
||||||
if ( hasDelimiters( equationInput ) ) {
|
|
||||||
// Get equation without delimiters
|
|
||||||
const params = extractDelimiters( equationInput );
|
|
||||||
|
|
||||||
// Remove delimiters from input field
|
|
||||||
fieldView.element.value = params.equation;
|
|
||||||
|
|
||||||
equationInput = params.equation;
|
|
||||||
|
|
||||||
// update display button and preview
|
|
||||||
this.displayButtonView.isOn = params.display;
|
|
||||||
}
|
}
|
||||||
if ( this.previewEnabled && this.mathView ) {
|
|
||||||
// Update preview view
|
|
||||||
this.mathView.value = equationInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.saveButtonView.isEnabled = !!equationInput;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
fieldView.on( 'render', onInput );
|
// Sync to Raw LaTeX
|
||||||
fieldView.on( 'input', onInput );
|
if ( this.rawLatexInputView.value !== eq ) {
|
||||||
|
this.rawLatexInputView.value = eq;
|
||||||
|
}
|
||||||
|
|
||||||
return mathInput;
|
// Sync to Preview
|
||||||
|
if ( previewEnabled && this.mathView && this.mathView.value !== eq ) {
|
||||||
|
this.mathView.value = eq;
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Handler 2: Raw LaTeX -> MathLive
|
||||||
|
this.rawLatexInputView.on( 'change:value', () => {
|
||||||
|
const eq = ( this.rawLatexInputView.value ?? '' ).trim();
|
||||||
|
const normalized = eq.length ? eq : null;
|
||||||
|
|
||||||
|
// Sync to MathLive
|
||||||
|
if ( this.mathLiveInputView.value !== normalized ) {
|
||||||
|
this.mathLiveInputView.value = normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync to Preview
|
||||||
|
if ( previewEnabled && this.mathView && this.mathView.value !== eq ) {
|
||||||
|
this.mathView.value = eq;
|
||||||
|
}
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createButton(
|
private _createButton( label: string, icon: string, className: string ): ButtonView {
|
||||||
label: string,
|
const btn = new ButtonView( this.locale );
|
||||||
icon: string,
|
btn.set( { label, icon, tooltip: true } );
|
||||||
className: string,
|
btn.extendTemplate( { attributes: { class: className } } );
|
||||||
eventName: string | null
|
return btn;
|
||||||
) {
|
|
||||||
const button = new ButtonView( this.locale );
|
|
||||||
|
|
||||||
button.set( {
|
|
||||||
label,
|
|
||||||
icon,
|
|
||||||
tooltip: true
|
|
||||||
} );
|
|
||||||
|
|
||||||
button.extendTemplate( {
|
|
||||||
attributes: {
|
|
||||||
class: className
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
if ( eventName ) {
|
|
||||||
button.delegate( 'execute' ).to( this, eventName );
|
|
||||||
}
|
|
||||||
|
|
||||||
return button;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createDisplayButton() {
|
private _createDisplayButton( t: ( str: string ) => string ): SwitchButtonView {
|
||||||
const t = this.locale.t;
|
const btn = new SwitchButtonView( this.locale );
|
||||||
|
btn.set( { label: t( 'Display mode' ), withText: true } );
|
||||||
|
btn.extendTemplate( { attributes: { class: 'ck-button-display-toggle' } } );
|
||||||
|
|
||||||
const switchButton = new SwitchButtonView( this.locale );
|
btn.on( 'execute', () => {
|
||||||
|
btn.isOn = !btn.isOn;
|
||||||
switchButton.set( {
|
// mathView updates automatically via bind()
|
||||||
label: t( 'Display mode' ),
|
|
||||||
withText: true
|
|
||||||
} );
|
} );
|
||||||
|
return btn;
|
||||||
switchButton.extendTemplate( {
|
|
||||||
attributes: {
|
|
||||||
class: 'ck-button-display-toggle'
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
switchButton.on( 'execute', () => {
|
|
||||||
// Toggle state
|
|
||||||
switchButton.isOn = !switchButton.isOn;
|
|
||||||
|
|
||||||
if ( this.previewEnabled && this.mathView ) {
|
|
||||||
// Update preview view
|
|
||||||
this.mathView.display = switchButton.isOn;
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
return switchButton;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
116
packages/ckeditor5-math/src/ui/mathliveinputview.ts
Normal file
116
packages/ckeditor5-math/src/ui/mathliveinputview.ts
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
import { View, type Locale } from 'ckeditor5';
|
||||||
|
import 'mathlive'; // Import side-effects only (registers the <math-field> tag)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface describing the custom <math-field> element.
|
||||||
|
*/
|
||||||
|
interface MathFieldElement extends HTMLElement {
|
||||||
|
value: string;
|
||||||
|
readOnly: boolean;
|
||||||
|
mathVirtualKeyboardPolicy: string;
|
||||||
|
// Interface includes the shortcuts property
|
||||||
|
inlineShortcuts: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A wrapper for the MathLive <math-field> component.
|
||||||
|
*/
|
||||||
|
export default class MathLiveInputView extends View {
|
||||||
|
/**
|
||||||
|
* The current LaTeX value.
|
||||||
|
* @observable
|
||||||
|
*/
|
||||||
|
public declare value: string | null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read-only state.
|
||||||
|
* @observable
|
||||||
|
*/
|
||||||
|
public declare isReadOnly: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reference to the DOM element.
|
||||||
|
* Typed as MathFieldElement | null for proper TS support.
|
||||||
|
*/
|
||||||
|
public mathfield: MathFieldElement | null = null;
|
||||||
|
|
||||||
|
constructor( locale: Locale ) {
|
||||||
|
super( locale );
|
||||||
|
|
||||||
|
this.set( 'value', null );
|
||||||
|
this.set( 'isReadOnly', false );
|
||||||
|
|
||||||
|
this.setTemplate( {
|
||||||
|
tag: 'div',
|
||||||
|
attributes: {
|
||||||
|
class: [ 'ck', 'ck-mathlive-input' ]
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
public override render(): void {
|
||||||
|
super.render();
|
||||||
|
|
||||||
|
// 1. Create element with the specific type
|
||||||
|
const mathfield = document.createElement( 'math-field' ) as MathFieldElement;
|
||||||
|
|
||||||
|
// 2. Configure Options
|
||||||
|
mathfield.mathVirtualKeyboardPolicy = 'manual';
|
||||||
|
|
||||||
|
//Disable differential D
|
||||||
|
mathfield.addEventListener( 'mount', () => {
|
||||||
|
mathfield.inlineShortcuts = {
|
||||||
|
...mathfield.inlineShortcuts, // Safe to read now
|
||||||
|
dx: 'dx',
|
||||||
|
dy: 'dy',
|
||||||
|
dt: 'dt'
|
||||||
|
};
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
||||||
|
// Disable sounds safely
|
||||||
|
const MathfieldConstructor = customElements.get( 'math-field' );
|
||||||
|
if ( MathfieldConstructor ) {
|
||||||
|
const proto = MathfieldConstructor as any;
|
||||||
|
if ( proto.soundsDirectory !== null ) proto.soundsDirectory = null;
|
||||||
|
if ( proto.plonkSound !== null ) proto.plonkSound = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Set Initial State
|
||||||
|
mathfield.value = this.value ?? '';
|
||||||
|
mathfield.readOnly = this.isReadOnly;
|
||||||
|
|
||||||
|
// 4. Bind Events (DOM -> Observable)
|
||||||
|
mathfield.addEventListener( 'input', () => {
|
||||||
|
const val = mathfield.value;
|
||||||
|
this.value = val.length ? val : null;
|
||||||
|
} );
|
||||||
|
|
||||||
|
// 5. Bind Events (Observable -> DOM)
|
||||||
|
this.on( 'change:value', ( _evt, _name, nextValue ) => {
|
||||||
|
if ( mathfield.value !== nextValue ) {
|
||||||
|
mathfield.value = nextValue ?? '';
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
this.on( 'change:isReadOnly', ( _evt, _name, nextValue ) => {
|
||||||
|
mathfield.readOnly = nextValue;
|
||||||
|
} );
|
||||||
|
|
||||||
|
// 6. Mount to the wrapper view
|
||||||
|
this.element?.appendChild( mathfield );
|
||||||
|
this.mathfield = mathfield;
|
||||||
|
}
|
||||||
|
|
||||||
|
public focus(): void {
|
||||||
|
this.mathfield?.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override destroy(): void {
|
||||||
|
if ( this.mathfield ) {
|
||||||
|
this.mathfield.remove();
|
||||||
|
this.mathfield = null;
|
||||||
|
}
|
||||||
|
super.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,44 +2,44 @@ import { View, type Locale } from 'ckeditor5';
|
|||||||
import type { KatexOptions } from '../typings-external.js';
|
import type { KatexOptions } from '../typings-external.js';
|
||||||
import { renderEquation } from '../utils.js';
|
import { renderEquation } from '../utils.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configuration options for the MathView.
|
||||||
|
*/
|
||||||
|
export interface MathViewOptions {
|
||||||
|
engine: 'mathjax' | 'katex' | ( ( equation: string, element: HTMLElement, display: boolean ) => void );
|
||||||
|
lazyLoad: undefined | ( () => Promise<void> );
|
||||||
|
previewUid: string;
|
||||||
|
previewClassName: Array<string>;
|
||||||
|
katexRenderOptions: KatexOptions;
|
||||||
|
}
|
||||||
|
|
||||||
export default class MathView extends View {
|
export default class MathView extends View {
|
||||||
|
/**
|
||||||
|
* The LaTeX equation value to render.
|
||||||
|
* @observable
|
||||||
|
*/
|
||||||
public declare value: string;
|
public declare value: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to render in display mode (centered) or inline.
|
||||||
|
* @observable
|
||||||
|
*/
|
||||||
public declare display: boolean;
|
public declare display: boolean;
|
||||||
public previewUid: string;
|
|
||||||
public previewClassName: Array<string>;
|
|
||||||
public katexRenderOptions: KatexOptions;
|
|
||||||
public engine:
|
|
||||||
| 'mathjax'
|
|
||||||
| 'katex'
|
|
||||||
| ( ( equation: string, element: HTMLElement, display: boolean ) => void );
|
|
||||||
public lazyLoad: undefined | ( () => Promise<void> );
|
|
||||||
|
|
||||||
constructor(
|
/**
|
||||||
engine:
|
* Configuration options passed during initialization.
|
||||||
| 'mathjax'
|
*/
|
||||||
| 'katex'
|
private options: MathViewOptions;
|
||||||
| ( (
|
|
||||||
equation: string,
|
constructor( locale: Locale, options: MathViewOptions ) {
|
||||||
element: HTMLElement,
|
|
||||||
display: boolean,
|
|
||||||
) => void ),
|
|
||||||
lazyLoad: undefined | ( () => Promise<void> ),
|
|
||||||
locale: Locale,
|
|
||||||
previewUid: string,
|
|
||||||
previewClassName: Array<string>,
|
|
||||||
katexRenderOptions: KatexOptions
|
|
||||||
) {
|
|
||||||
super( locale );
|
super( locale );
|
||||||
|
this.options = options;
|
||||||
this.engine = engine;
|
|
||||||
this.lazyLoad = lazyLoad;
|
|
||||||
this.previewUid = previewUid;
|
|
||||||
this.katexRenderOptions = katexRenderOptions;
|
|
||||||
this.previewClassName = previewClassName;
|
|
||||||
|
|
||||||
this.set( 'value', '' );
|
this.set( 'value', '' );
|
||||||
this.set( 'display', false );
|
this.set( 'display', false );
|
||||||
|
|
||||||
|
// Update rendering when state changes.
|
||||||
|
// Checking isRendered prevents errors during initialization.
|
||||||
this.on( 'change', () => {
|
this.on( 'change', () => {
|
||||||
if ( this.isRendered ) {
|
if ( this.isRendered ) {
|
||||||
this.updateMath();
|
this.updateMath();
|
||||||
@ -56,16 +56,20 @@ export default class MathView extends View {
|
|||||||
|
|
||||||
public updateMath(): void {
|
public updateMath(): void {
|
||||||
if ( this.element ) {
|
if ( this.element ) {
|
||||||
|
|
||||||
|
// This prevents the new render from appending to the old one.
|
||||||
|
this.element.textContent = '';
|
||||||
|
|
||||||
void renderEquation(
|
void renderEquation(
|
||||||
this.value,
|
this.value,
|
||||||
this.element,
|
this.element,
|
||||||
this.engine,
|
this.options.engine,
|
||||||
this.lazyLoad,
|
this.options.lazyLoad,
|
||||||
this.display,
|
this.display,
|
||||||
true,
|
true, // isPreview
|
||||||
this.previewUid,
|
this.options.previewUid,
|
||||||
this.previewClassName,
|
this.options.previewClassName,
|
||||||
this.katexRenderOptions
|
this.options.katexRenderOptions
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
54
packages/ckeditor5-math/src/ui/rawlatexinputview.ts
Normal file
54
packages/ckeditor5-math/src/ui/rawlatexinputview.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { LabeledFieldView, createLabeledTextarea, type Locale, type TextareaView } from 'ckeditor5';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A labeled textarea view for direct LaTeX code editing.
|
||||||
|
*/
|
||||||
|
export default class RawLatexInputView extends LabeledFieldView<TextareaView> {
|
||||||
|
/**
|
||||||
|
* The current LaTeX value.
|
||||||
|
* @observable
|
||||||
|
*/
|
||||||
|
public declare value: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the input is in read-only mode.
|
||||||
|
* @observable
|
||||||
|
*/
|
||||||
|
public declare isReadOnly: boolean;
|
||||||
|
|
||||||
|
constructor( locale: Locale ) {
|
||||||
|
super( locale, createLabeledTextarea );
|
||||||
|
|
||||||
|
this.set( 'value', '' );
|
||||||
|
this.set( 'isReadOnly', false );
|
||||||
|
|
||||||
|
const fieldView = this.fieldView;
|
||||||
|
|
||||||
|
// 1. Sync: DOM (Textarea) -> Observable
|
||||||
|
fieldView.on( 'input', () => {
|
||||||
|
// We cast strictly to HTMLTextAreaElement to access '.value' safely
|
||||||
|
const textarea = fieldView.element as HTMLTextAreaElement;
|
||||||
|
if ( textarea ) {
|
||||||
|
this.value = textarea.value;
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
// 2. Sync: Observable -> DOM (Textarea)
|
||||||
|
this.on( 'change:value', () => {
|
||||||
|
const textarea = fieldView.element as HTMLTextAreaElement;
|
||||||
|
// Check for difference to avoid cursor jumping
|
||||||
|
if ( textarea && textarea.value !== this.value ) {
|
||||||
|
textarea.value = this.value;
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
// 3. Sync: ReadOnly State
|
||||||
|
this.on( 'change:isReadOnly', ( _evt, _name, nextValue ) => {
|
||||||
|
fieldView.isReadOnly = nextValue;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
public override render(): void {
|
||||||
|
super.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -168,13 +168,13 @@ describe( 'MathUI', () => {
|
|||||||
|
|
||||||
command.isEnabled = true;
|
command.isEnabled = true;
|
||||||
|
|
||||||
expect( formView!.mathInputView.isReadOnly ).to.be.false;
|
expect( formView!.mathLiveInputView.isReadOnly ).to.be.false;
|
||||||
expect( formView!.saveButtonView.isEnabled ).to.be.false;
|
expect( formView!.saveButtonView.isEnabled ).to.be.false;
|
||||||
expect( formView!.cancelButtonView.isEnabled ).to.be.true;
|
expect( formView!.cancelButtonView.isEnabled ).to.be.true;
|
||||||
|
|
||||||
command.isEnabled = false;
|
command.isEnabled = false;
|
||||||
|
|
||||||
expect( formView!.mathInputView.isReadOnly ).to.be.true;
|
expect( formView!.mathLiveInputView.isReadOnly ).to.be.true;
|
||||||
expect( formView!.saveButtonView.isEnabled ).to.be.false;
|
expect( formView!.saveButtonView.isEnabled ).to.be.false;
|
||||||
expect( formView!.cancelButtonView.isEnabled ).to.be.true;
|
expect( formView!.cancelButtonView.isEnabled ).to.be.true;
|
||||||
} );
|
} );
|
||||||
@ -407,22 +407,30 @@ describe( 'MathUI', () => {
|
|||||||
setModelData( editor.model, '<paragraph>f[o]o</paragraph>' );
|
setModelData( editor.model, '<paragraph>f[o]o</paragraph>' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
it( 'should bind mainFormView.mathInputView#value to math command value', () => {
|
it( 'should bind mainFormView.mathLiveInputView#value to math command value', () => {
|
||||||
const command = editor.commands.get( 'math' );
|
const command = editor.commands.get( 'math' );
|
||||||
|
|
||||||
expect( formView!.mathInputView.value ).to.null;
|
expect( formView!.mathLiveInputView.value ).to.be.null;
|
||||||
|
|
||||||
command!.value = 'x^2';
|
command!.value = 'x^2';
|
||||||
expect( formView!.mathInputView.value ).to.equal( 'x^2' );
|
expect( formView!.mathLiveInputView.value ).to.equal( 'x^2' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
it( 'should execute math command on mainFormView#submit event', () => {
|
it( 'should execute math command on mainFormView#submit event', () => {
|
||||||
const executeSpy = vi.spyOn( editor, 'execute' );
|
const executeSpy = vi.spyOn( editor, 'execute' );
|
||||||
|
|
||||||
formView!.mathInputView.fieldView.element!.value = 'x^2';
|
formView!.mathLiveInputView.value = 'x^2';
|
||||||
formView!.fire( 'submit' );
|
formView!.fire( 'submit' );
|
||||||
|
|
||||||
expect(executeSpy.mock.lastCall?.slice(0, 2)).toMatchObject(['math', 'x^2']);
|
expect( executeSpy.mock.lastCall?.slice( 0, 2 ) ).toMatchObject( [ 'math', 'x^2' ] );
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'should sync mathLiveInputView and rawLatexInputView', () => {
|
||||||
|
formView!.mathLiveInputView.value = 'x^2';
|
||||||
|
expect( formView!.rawLatexInputView.value ).to.equal( 'x^2' );
|
||||||
|
|
||||||
|
formView!.rawLatexInputView.value = '\\frac{1}{2}';
|
||||||
|
expect( formView!.mathLiveInputView.value ).to.equal( '\\frac{1}{2}' );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
it( 'should hide the balloon on mainFormView#cancel if math command does not have a value', () => {
|
it( 'should hide the balloon on mainFormView#cancel if math command does not have a value', () => {
|
||||||
|
|||||||
@ -1,35 +1,214 @@
|
|||||||
|
/**
|
||||||
|
* Math equation editor dialog styles
|
||||||
|
* Supports MathLive input, raw LaTeX textarea, and equation preview
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
Main Dialog Container
|
||||||
|
========================================================================= */
|
||||||
|
|
||||||
.ck.ck-math-form {
|
.ck.ck-math-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
flex-direction: column;
|
||||||
flex-direction: row;
|
padding: var(--ck-spacing-standard);
|
||||||
flex-wrap: nowrap;
|
box-sizing: border-box;
|
||||||
padding: var(--ck-spacing-standard);
|
max-width: 80vw;
|
||||||
|
max-height: 80vh;
|
||||||
@media screen and (max-width: 600px) {
|
height: 100%;
|
||||||
flex-wrap: wrap;
|
overflow-x: hidden;
|
||||||
|
|
||||||
& .ck-math-view {
|
|
||||||
flex-basis: 100%;
|
|
||||||
|
|
||||||
& .ck-labeled-view {
|
|
||||||
flex-basis: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .ck-label {
|
|
||||||
flex-basis: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
& .ck-button {
|
|
||||||
flex-basis: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.ck-math-tex.ck-placeholder::before {
|
/* Mobile responsiveness */
|
||||||
display: none !important;
|
@media screen and (max-width: 600px) {
|
||||||
|
.ck.ck-math-form {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ck.ck-toolbar-container {
|
/* ============================================================================
|
||||||
z-index: calc(var(--ck-z-panel) + 2);
|
Content Layout
|
||||||
|
========================================================================= */
|
||||||
|
|
||||||
|
.ck-math-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
gap: var(--ck-spacing-standard);
|
||||||
|
min-height: fit-content;
|
||||||
|
min-width: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LaTeX section heading */
|
||||||
|
.ck-math-view > .ck-labeled-field-view::before {
|
||||||
|
content: "LaTeX";
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--ck-color-text, #333);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
padding-left: 2px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Equation preview section heading */
|
||||||
|
.ck-math-view > math-field::before {
|
||||||
|
content: "Equation preview";
|
||||||
|
display: block;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--ck-color-text, #333);
|
||||||
|
margin-bottom: 4px;
|
||||||
|
padding-left: 2px;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add spacing between preview and action buttons */
|
||||||
|
.ck-math-view > math-field {
|
||||||
|
margin-bottom: var(--ck-spacing-large, 16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Action buttons row (Save/Cancel) */
|
||||||
|
.ck-math-button-row {
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
gap: var(--ck-spacing-standard);
|
||||||
|
margin-top: var(--ck-spacing-standard);
|
||||||
|
width: fit-content;
|
||||||
|
max-width: 100%;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
Shared Styles for Input Fields
|
||||||
|
========================================================================= */
|
||||||
|
|
||||||
|
/* Base styling for both MathLive fields and textareas */
|
||||||
|
.ck.ck-math-form math-field,
|
||||||
|
.ck.ck-math-form textarea {
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: var(--ck-spacing-small);
|
||||||
|
background: var(--ck-color-input-background) !important;
|
||||||
|
color: var(--ck-color-input-text, inherit);
|
||||||
|
font-size: var(--ck-font-size-base);
|
||||||
|
border: none !important;
|
||||||
|
border-radius: var(--ck-border-radius, 6px);
|
||||||
|
outline: 3px solid transparent;
|
||||||
|
outline-offset: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* MathLive-specific configuration */
|
||||||
|
.ck.ck-math-form math-field {
|
||||||
|
display: block !important;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
overflow-x: auto !important;
|
||||||
|
|
||||||
|
/* MathLive theme customization */
|
||||||
|
--selection-background-color: rgba(33, 150, 243, 0.2);
|
||||||
|
--selection-color: inherit;
|
||||||
|
--contains-highlight-background-color: rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
MathLive Visual Editor (Top Input)
|
||||||
|
========================================================================= */
|
||||||
|
|
||||||
|
.ck.ck-mathlive-input {
|
||||||
|
display: inline-block;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
min-height: fit-content;
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow: auto;
|
||||||
|
padding-bottom: var(--ck-spacing-small);
|
||||||
|
resize: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Configure MathLive shadow DOM layout */
|
||||||
|
.ck.ck-math-form math-field::part(container),
|
||||||
|
.ck.ck-math-form math-field::part(content),
|
||||||
|
.ck.ck-math-form math-field::part(field) {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: 100%;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Position MathLive UI controls */
|
||||||
|
.ck.ck-math-form math-field::part(virtual-keyboard-toggle),
|
||||||
|
.ck.ck-math-form math-field::part(menu-toggle) {
|
||||||
|
position: absolute;
|
||||||
|
top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ck.ck-math-form math-field::part(virtual-keyboard-toggle) {
|
||||||
|
right: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ck.ck-math-form math-field::part(menu-toggle) {
|
||||||
|
right: 8px;
|
||||||
|
display: flex !important;
|
||||||
|
visibility: visible !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ============================================================================
|
||||||
|
Raw LaTeX Textarea (Middle Input)
|
||||||
|
========================================================================= */
|
||||||
|
|
||||||
|
.ck-math-view .ck-labeled-field-view {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
min-width: 100%;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
min-height: 60px;
|
||||||
|
max-height: 65vh;
|
||||||
|
resize: both;
|
||||||
|
overflow: auto;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide the default label (we use ::before for custom heading) */
|
||||||
|
.ck-math-view .ck-labeled-field-view .ck-label {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Textarea wrapper */
|
||||||
|
.ck-math-view .ck-labeled-field-view .ck-labeled-field-view__input-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100px;
|
||||||
|
height: auto;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Raw LaTeX textarea styling */
|
||||||
|
.ck-math-view .ck-labeled-field-view textarea {
|
||||||
|
display: block;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100%;
|
||||||
|
min-height: 140px;
|
||||||
|
resize: none !important;
|
||||||
|
border-radius: 0 !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Textarea hover and focus states */
|
||||||
|
.ck-math-view .ck-labeled-field-view textarea:hover,
|
||||||
|
.ck-math-view .ck-labeled-field-view textarea:focus {
|
||||||
|
background: var(--ck-color-input-background) !important;
|
||||||
|
outline: none !important;
|
||||||
|
box-shadow: none !important;
|
||||||
}
|
}
|
||||||
|
|||||||
36
pnpm-lock.yaml
generated
36
pnpm-lock.yaml
generated
@ -1061,6 +1061,9 @@ importers:
|
|||||||
'@ckeditor/ckeditor5-icons':
|
'@ckeditor/ckeditor5-icons':
|
||||||
specifier: 47.2.0
|
specifier: 47.2.0
|
||||||
version: 47.2.0
|
version: 47.2.0
|
||||||
|
mathlive:
|
||||||
|
specifier: 0.108.2
|
||||||
|
version: 0.108.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@ckeditor/ckeditor5-dev-build-tools':
|
'@ckeditor/ckeditor5-dev-build-tools':
|
||||||
specifier: 43.1.0
|
specifier: 43.1.0
|
||||||
@ -2123,6 +2126,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
|
resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
|
||||||
engines: {node: '>=0.1.90'}
|
engines: {node: '>=0.1.90'}
|
||||||
|
|
||||||
|
'@cortex-js/compute-engine@0.30.2':
|
||||||
|
resolution: {integrity: sha512-Zx+iisk9WWdbxjm8EYsneIBszvjfUs7BHNwf1jBtSINIgfWGpHrTTq9vW0J59iGCFt6bOFxbmWyxNMRSmksHMA==}
|
||||||
|
engines: {node: '>=21.7.3', npm: '>=10.5.0'}
|
||||||
|
|
||||||
'@cspotcode/source-map-support@0.8.1':
|
'@cspotcode/source-map-support@0.8.1':
|
||||||
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@ -6879,6 +6886,10 @@ packages:
|
|||||||
compare-versions@6.1.1:
|
compare-versions@6.1.1:
|
||||||
resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==}
|
resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==}
|
||||||
|
|
||||||
|
complex-esm@2.1.1-esm1:
|
||||||
|
resolution: {integrity: sha512-IShBEWHILB9s7MnfyevqNGxV0A1cfcSnewL/4uPFiSxkcQL4Mm3FxJ0pXMtCXuWLjYz3lRRyk6OfkeDZcjD6nw==}
|
||||||
|
engines: {node: '>=16.14.2', npm: '>=8.5.0'}
|
||||||
|
|
||||||
component-emitter@1.3.1:
|
component-emitter@1.3.1:
|
||||||
resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==}
|
resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==}
|
||||||
|
|
||||||
@ -10192,6 +10203,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
mathlive@0.108.2:
|
||||||
|
resolution: {integrity: sha512-GIZkfprGTxrbHckOvwo92ZmOOxdD018BHDzlrEwYUU+pzR5KabhqI1s43lxe/vqXdF5RLiQKgDcuk5jxEjhkYg==}
|
||||||
|
|
||||||
mathml-tag-names@2.1.3:
|
mathml-tag-names@2.1.3:
|
||||||
resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==}
|
resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==}
|
||||||
|
|
||||||
@ -15623,6 +15637,8 @@ snapshots:
|
|||||||
'@ckeditor/ckeditor5-core': 47.2.0
|
'@ckeditor/ckeditor5-core': 47.2.0
|
||||||
'@ckeditor/ckeditor5-upload': 47.2.0
|
'@ckeditor/ckeditor5-upload': 47.2.0
|
||||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@ckeditor/ckeditor5-ai@47.2.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)':
|
'@ckeditor/ckeditor5-ai@47.2.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -15769,6 +15785,8 @@ snapshots:
|
|||||||
'@ckeditor/ckeditor5-core': 47.2.0
|
'@ckeditor/ckeditor5-core': 47.2.0
|
||||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@ckeditor/ckeditor5-code-block@47.2.0(patch_hash=2361d8caad7d6b5bddacc3a3b4aa37dbfba260b1c1b22a450413a79c1bb1ce95)':
|
'@ckeditor/ckeditor5-code-block@47.2.0(patch_hash=2361d8caad7d6b5bddacc3a3b4aa37dbfba260b1c1b22a450413a79c1bb1ce95)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -15833,8 +15851,6 @@ snapshots:
|
|||||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||||
'@ckeditor/ckeditor5-watchdog': 47.2.0
|
'@ckeditor/ckeditor5-watchdog': 47.2.0
|
||||||
es-toolkit: 1.39.5
|
es-toolkit: 1.39.5
|
||||||
transitivePeerDependencies:
|
|
||||||
- supports-color
|
|
||||||
|
|
||||||
'@ckeditor/ckeditor5-dev-build-tools@43.1.0(@swc/helpers@0.5.17)(tslib@2.8.1)(typescript@5.9.3)':
|
'@ckeditor/ckeditor5-dev-build-tools@43.1.0(@swc/helpers@0.5.17)(tslib@2.8.1)(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -16029,6 +16045,8 @@ snapshots:
|
|||||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||||
es-toolkit: 1.39.5
|
es-toolkit: 1.39.5
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@ckeditor/ckeditor5-editor-multi-root@47.2.0':
|
'@ckeditor/ckeditor5-editor-multi-root@47.2.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -16941,6 +16959,11 @@ snapshots:
|
|||||||
|
|
||||||
'@colors/colors@1.5.0': {}
|
'@colors/colors@1.5.0': {}
|
||||||
|
|
||||||
|
'@cortex-js/compute-engine@0.30.2':
|
||||||
|
dependencies:
|
||||||
|
complex-esm: 2.1.1-esm1
|
||||||
|
decimal.js: 10.6.0
|
||||||
|
|
||||||
'@cspotcode/source-map-support@0.8.1':
|
'@cspotcode/source-map-support@0.8.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/trace-mapping': 0.3.9
|
'@jridgewell/trace-mapping': 0.3.9
|
||||||
@ -22577,6 +22600,8 @@ snapshots:
|
|||||||
|
|
||||||
compare-versions@6.1.1: {}
|
compare-versions@6.1.1: {}
|
||||||
|
|
||||||
|
complex-esm@2.1.1-esm1: {}
|
||||||
|
|
||||||
component-emitter@1.3.1: {}
|
component-emitter@1.3.1: {}
|
||||||
|
|
||||||
compress-commons@6.0.2:
|
compress-commons@6.0.2:
|
||||||
@ -23360,8 +23385,7 @@ snapshots:
|
|||||||
|
|
||||||
decimal.js@10.5.0: {}
|
decimal.js@10.5.0: {}
|
||||||
|
|
||||||
decimal.js@10.6.0:
|
decimal.js@10.6.0: {}
|
||||||
optional: true
|
|
||||||
|
|
||||||
decko@1.2.0: {}
|
decko@1.2.0: {}
|
||||||
|
|
||||||
@ -26780,6 +26804,10 @@ snapshots:
|
|||||||
|
|
||||||
math-intrinsics@1.1.0: {}
|
math-intrinsics@1.1.0: {}
|
||||||
|
|
||||||
|
mathlive@0.108.2:
|
||||||
|
dependencies:
|
||||||
|
'@cortex-js/compute-engine': 0.30.2
|
||||||
|
|
||||||
mathml-tag-names@2.1.3: {}
|
mathml-tag-names@2.1.3: {}
|
||||||
|
|
||||||
mdast-util-find-and-replace@3.0.2:
|
mdast-util-find-and-replace@3.0.2:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user