mirror of
https://github.com/zadam/trilium.git
synced 2026-03-01 18:13:39 +01:00
Merge branch 'main' into main
This commit is contained in:
commit
40be94804c
57
.vscode/launch.json
vendored
Normal file
57
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch client (Chrome)",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "chrome",
|
||||||
|
"url": "http://localhost:8080",
|
||||||
|
"webRoot": "${workspaceFolder}/apps/client"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Launch server",
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/apps/server/src/main.ts",
|
||||||
|
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
||||||
|
"env": {
|
||||||
|
"NODE_ENV": "development",
|
||||||
|
"TRILIUM_ENV": "dev",
|
||||||
|
"TRILIUM_DATA_DIR": "${input:trilium_data_dir}",
|
||||||
|
"TRILIUM_RESOURCE_DIR": "${workspaceFolder}/apps/server/src"
|
||||||
|
},
|
||||||
|
"autoAttachChildProcesses": true,
|
||||||
|
"cwd": "${workspaceFolder}",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"internalConsoleOptions": "neverOpen",
|
||||||
|
"skipFiles": ["<node_internals>/**", "${workspaceFolder}/node_modules/**"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Launch Vitest with current test file",
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"autoAttachChildProcesses": true,
|
||||||
|
"program": "${workspaceFolder}/node_modules/vitest/vitest.mjs",
|
||||||
|
"args": ["run", "${relativeFile}"],
|
||||||
|
"smartStep": true,
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"skipFiles": ["<node_internals>/**", "**/node_modules/**"],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compounds": [
|
||||||
|
{
|
||||||
|
"name": "Launch client (Chrome) and server",
|
||||||
|
"configurations": ["Launch server","Launch client (Chrome)"],
|
||||||
|
"stopAll": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"id": "trilium_data_dir",
|
||||||
|
"type": "promptString",
|
||||||
|
"description": "Select Trilum Notes data directory",
|
||||||
|
"default": "${workspaceFolder}/apps/server/data"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -14,9 +14,9 @@
|
|||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "Elian Doran <contact@eliandoran.me>",
|
"author": "Elian Doran <contact@eliandoran.me>",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"packageManager": "pnpm@10.30.1",
|
"packageManager": "pnpm@10.30.2",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@redocly/cli": "2.19.1",
|
"@redocly/cli": "2.19.2",
|
||||||
"archiver": "7.0.1",
|
"archiver": "7.0.1",
|
||||||
"fs-extra": "11.3.3",
|
"fs-extra": "11.3.3",
|
||||||
"js-yaml": "4.1.1",
|
"js-yaml": "4.1.1",
|
||||||
|
|||||||
@ -50,14 +50,14 @@
|
|||||||
"jquery": "4.0.0",
|
"jquery": "4.0.0",
|
||||||
"jquery.fancytree": "2.38.5",
|
"jquery.fancytree": "2.38.5",
|
||||||
"jsplumb": "2.15.6",
|
"jsplumb": "2.15.6",
|
||||||
"katex": "0.16.28",
|
"katex": "0.16.33",
|
||||||
"knockout": "3.5.1",
|
"knockout": "3.5.1",
|
||||||
"leaflet": "1.9.4",
|
"leaflet": "1.9.4",
|
||||||
"leaflet-gpx": "2.2.0",
|
"leaflet-gpx": "2.2.0",
|
||||||
"mark.js": "8.11.1",
|
"mark.js": "8.11.1",
|
||||||
"marked": "17.0.3",
|
"marked": "17.0.3",
|
||||||
"mermaid": "11.12.3",
|
"mermaid": "11.12.3",
|
||||||
"mind-elixir": "5.9.0",
|
"mind-elixir": "5.9.1",
|
||||||
"normalize.css": "8.0.1",
|
"normalize.css": "8.0.1",
|
||||||
"panzoom": "9.4.3",
|
"panzoom": "9.4.3",
|
||||||
"preact": "10.28.4",
|
"preact": "10.28.4",
|
||||||
@ -73,7 +73,7 @@
|
|||||||
"@ckeditor/ckeditor5-inspector": "5.0.0",
|
"@ckeditor/ckeditor5-inspector": "5.0.0",
|
||||||
"@prefresh/vite": "2.4.12",
|
"@prefresh/vite": "2.4.12",
|
||||||
"@types/bootstrap": "5.2.10",
|
"@types/bootstrap": "5.2.10",
|
||||||
"@types/jquery": "3.5.33",
|
"@types/jquery": "4.0.0",
|
||||||
"@types/leaflet": "1.9.21",
|
"@types/leaflet": "1.9.21",
|
||||||
"@types/leaflet-gpx": "1.3.8",
|
"@types/leaflet-gpx": "1.3.8",
|
||||||
"@types/mark.js": "8.11.12",
|
"@types/mark.js": "8.11.12",
|
||||||
|
|||||||
@ -192,7 +192,7 @@ function renderFile(entity: FNote | FAttachment, type: string, $renderedContent:
|
|||||||
throw new Error(`Can't recognize entity type of '${entity}'`);
|
throw new Error(`Can't recognize entity type of '${entity}'`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const $content = $('<div style="display: flex; flex-direction: column; height: 100%;">');
|
const $content = $('<div style="display: flex; flex-direction: column; height: 100%; justify-content: end;">');
|
||||||
|
|
||||||
if (type === "pdf") {
|
if (type === "pdf") {
|
||||||
const $pdfPreview = $('<iframe class="pdf-preview" style="width: 100%; flex-grow: 100;"></iframe>');
|
const $pdfPreview = $('<iframe class="pdf-preview" style="width: 100%; flex-grow: 100;"></iframe>');
|
||||||
|
|||||||
@ -120,7 +120,6 @@ async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: F
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$renderedContent.css("padding", "10px");
|
|
||||||
$renderedContent.addClass("text-with-ellipsis");
|
$renderedContent.addClass("text-with-ellipsis");
|
||||||
|
|
||||||
// just load the first 10 child notes
|
// just load the first 10 child notes
|
||||||
|
|||||||
@ -14,7 +14,9 @@ export function reloadFrontendApp(reason?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isElectron()) {
|
if (isElectron()) {
|
||||||
dynamicRequire("@electron/remote").BrowserWindow.getFocusedWindow()?.reload();
|
for (const window of dynamicRequire("@electron/remote").BrowserWindow.getAllWindows()) {
|
||||||
|
window.reload();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2630,7 +2630,7 @@ iframe.print-iframe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#root-widget.virtual-keyboard-opened .note-split:not(.active) {
|
body:not(.ios) #root-widget.virtual-keyboard-opened .note-split:not(.active) {
|
||||||
max-height: 80px;
|
max-height: 80px;
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -314,7 +314,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#left-pane .fancytree-node.tinted,
|
#left-pane .fancytree-node.tinted,
|
||||||
.nested-note-list-item.use-note-color {
|
.nested-note-list-item.use-note-color,
|
||||||
|
.note-book-card .note-book-header.use-note-color {
|
||||||
--custom-color: var(--dark-theme-custom-color);
|
--custom-color: var(--dark-theme-custom-color);
|
||||||
|
|
||||||
/* The background color of the active item in the note tree.
|
/* The background color of the active item in the note tree.
|
||||||
@ -365,7 +366,8 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
|
|||||||
|
|
||||||
.note-split.with-hue,
|
.note-split.with-hue,
|
||||||
.quick-edit-dialog-wrapper.with-hue,
|
.quick-edit-dialog-wrapper.with-hue,
|
||||||
.nested-note-list-item.with-hue {
|
.nested-note-list-item.with-hue,
|
||||||
|
.note-book-card.with-hue .note-book-header {
|
||||||
--note-icon-custom-background-color: hsl(var(--custom-color-hue), 15.8%, 30.9%);
|
--note-icon-custom-background-color: hsl(var(--custom-color-hue), 15.8%, 30.9%);
|
||||||
--note-icon-custom-color: hsl(var(--custom-color-hue), 100%, 76.5%);
|
--note-icon-custom-color: hsl(var(--custom-color-hue), 100%, 76.5%);
|
||||||
--note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 28.3%, 36.7%);
|
--note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 28.3%, 36.7%);
|
||||||
@ -375,3 +377,8 @@ body .todo-list input[type="checkbox"]:not(:checked):before {
|
|||||||
.quick-edit-dialog-wrapper.with-hue *::selection {
|
.quick-edit-dialog-wrapper.with-hue *::selection {
|
||||||
--selection-background-color: hsl(var(--custom-color-hue), 49.2%, 35%);
|
--selection-background-color: hsl(var(--custom-color-hue), 49.2%, 35%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.note-book-card.with-hue {
|
||||||
|
--card-background-color: hsl(var(--custom-color-hue), 6%, 21%);
|
||||||
|
--card-background-hover-color: hsl(var(--custom-color-hue), 8%, 25%);
|
||||||
|
}
|
||||||
@ -308,7 +308,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
#left-pane .fancytree-node.tinted,
|
#left-pane .fancytree-node.tinted,
|
||||||
.nested-note-list-item.use-note-color {
|
.nested-note-list-item.use-note-color,
|
||||||
|
.note-book-card .note-book-header.use-note-color {
|
||||||
--custom-color: var(--light-theme-custom-color);
|
--custom-color: var(--light-theme-custom-color);
|
||||||
|
|
||||||
/* The background color of the active item in the note tree.
|
/* The background color of the active item in the note tree.
|
||||||
@ -335,7 +336,8 @@
|
|||||||
|
|
||||||
.note-split.with-hue,
|
.note-split.with-hue,
|
||||||
.quick-edit-dialog-wrapper.with-hue,
|
.quick-edit-dialog-wrapper.with-hue,
|
||||||
.nested-note-list-item.with-hue {
|
.nested-note-list-item.with-hue,
|
||||||
|
.note-book-card.with-hue .note-book-header {
|
||||||
--note-icon-custom-background-color: hsl(var(--custom-color-hue), 44.5%, 43.1%);
|
--note-icon-custom-background-color: hsl(var(--custom-color-hue), 44.5%, 43.1%);
|
||||||
--note-icon-custom-color: hsl(var(--custom-color-hue), 91.3%, 91%);
|
--note-icon-custom-color: hsl(var(--custom-color-hue), 91.3%, 91%);
|
||||||
--note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 55.1%, 50.2%);
|
--note-icon-hover-custom-background-color: hsl(var(--custom-color-hue), 55.1%, 50.2%);
|
||||||
@ -345,3 +347,8 @@
|
|||||||
.quick-edit-dialog-wrapper.with-hue *::selection {
|
.quick-edit-dialog-wrapper.with-hue *::selection {
|
||||||
--selection-background-color: hsl(var(--custom-color-hue), 60%, 90%);
|
--selection-background-color: hsl(var(--custom-color-hue), 60%, 90%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.note-book-card.with-hue {
|
||||||
|
--card-background-color: hsl(var(--custom-color-hue), 21%, 94%);
|
||||||
|
--card-background-hover-color: hsl(var(--custom-color-hue), 21%, 87%);
|
||||||
|
}
|
||||||
@ -643,139 +643,6 @@ li.dropdown-item a.dropdown-item-button:focus-visible {
|
|||||||
transform: translateY(4%);
|
transform: translateY(4%);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE LIST
|
|
||||||
*/
|
|
||||||
|
|
||||||
.note-list .note-book-card {
|
|
||||||
--note-list-horizontal-padding: 22px;
|
|
||||||
--note-list-vertical-padding: 15px;
|
|
||||||
background-color: var(--card-background-color);
|
|
||||||
border: 1px solid var(--card-border-color) !important;
|
|
||||||
border-radius: 12px;
|
|
||||||
user-select: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 5px 10px 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root .note-list .note-book-card:hover {
|
|
||||||
background-color: var(--card-background-hover-color);
|
|
||||||
transition: background-color 200ms ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
:root .note-list.grid-view .note-book-card:active {
|
|
||||||
transform: scale(.98);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list.list-view .note-book-card {
|
|
||||||
box-shadow: 0 0 3px var(--card-shadow-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list.list-view .note-book-card .note-book-header .note-icon {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card a {
|
|
||||||
color: inherit !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-header {
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: bold;
|
|
||||||
padding: 0.5em 1rem;
|
|
||||||
border-bottom-color: var(--card-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-header .note-icon {
|
|
||||||
font-size: 17px;
|
|
||||||
vertical-align: text-bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-header .note-book-title {
|
|
||||||
font-size: 1em;
|
|
||||||
color: var(--active-item-text-color);
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-header .rendered-note-attributes {
|
|
||||||
font-size: 0.7em;
|
|
||||||
font-weight: normal;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-header:last-child {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content {
|
|
||||||
padding: 0 !important;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content .rendered-content {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content.type-image .rendered-content,
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content.type-pdf .rendered-content {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content .rendered-content.text-with-ellipsis {
|
|
||||||
padding: 1rem !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content h1,
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content h2,
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content h3,
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content h4,
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content h5,
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content h6 {
|
|
||||||
font-size: 1rem;
|
|
||||||
color: var(--active-item-text-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content p:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content.type-canvas .rendered-content,
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content.type-mindMap .rendered-content,
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content.type-code .rendered-content,
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content.type-video .rendered-content {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content.type-code {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .note-book-content.type-code pre {
|
|
||||||
height: 100%;
|
|
||||||
padding: 1em;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper .note-book-card .tn-icon {
|
|
||||||
color: var(--left-pane-icon-color) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list.grid-view .note-book-card:hover {
|
|
||||||
filter: contrast(105%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list.grid-view .ck-content {
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list.grid-view .ck-content p {
|
|
||||||
margin-bottom: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list.grid-view .ck-content figure.image {
|
|
||||||
width: 25%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE SEARCH SUGGESTIONS
|
* NOTE SEARCH SUGGESTIONS
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -647,10 +647,10 @@ html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ck-content hr {
|
:root .ck-content hr {
|
||||||
margin: 5px 0;
|
margin-block: 5px;
|
||||||
height: 1px;
|
height: 0;
|
||||||
background-color: var(--main-border-color);
|
border: thin solid var(--main-border-color);
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -372,10 +372,6 @@ body[dir=ltr] #launcher-container {
|
|||||||
.calendar-dropdown-widget .calendar-header [data-calendar-input="month"] {
|
.calendar-dropdown-widget .calendar-header [data-calendar-input="month"] {
|
||||||
--input-background-color: transparent;
|
--input-background-color: transparent;
|
||||||
--menu-background-color: transparent;
|
--menu-background-color: transparent;
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
font-size: 1.4em;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-dropdown-widget .calendar-header input:not(:focus) {
|
.calendar-dropdown-widget .calendar-header input:not(:focus) {
|
||||||
@ -425,8 +421,6 @@ body[dir=ltr] #launcher-container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.calendar-dropdown-widget .calendar-week span {
|
.calendar-dropdown-widget .calendar-week span {
|
||||||
font-size: 0.85em;
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--calendar-weekday-labels-color);
|
color: var(--calendar-weekday-labels-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,9 +683,10 @@ body.layout-vertical.background-effects div.quick-search .dropdown-menu {
|
|||||||
padding-inline-start: 12px;
|
padding-inline-start: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#left-pane span.fancytree-node.fancytree-active {
|
#left-pane span.fancytree-node.fancytree-active,
|
||||||
|
#left-pane span.fancytree-node.fancytree-active:hover {
|
||||||
position: relative;
|
position: relative;
|
||||||
background: transparent !important;
|
background: transparent;
|
||||||
color: var(--custom-color, var(--left-pane-item-selected-color));
|
color: var(--custom-color, var(--left-pane-item-selected-color));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -704,6 +699,14 @@ body.layout-vertical.background-effects div.quick-search .dropdown-menu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* .fancytree-node pseudo-elements:
|
||||||
|
*
|
||||||
|
* - ::before: the active tree item decorator.
|
||||||
|
* - ::after: the selected tree item background. A pseudo-element is used instead of the
|
||||||
|
* element's background color, to allow alpha compositing for the hover state.
|
||||||
|
*/
|
||||||
|
|
||||||
#left-pane span.fancytree-node.fancytree-active::before {
|
#left-pane span.fancytree-node.fancytree-active::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
content: "";
|
content: "";
|
||||||
@ -718,6 +721,24 @@ body.layout-vertical.background-effects div.quick-search .dropdown-menu {
|
|||||||
z-index: -1;
|
z-index: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#left-pane span.fancytree-node.fancytree-selected {
|
||||||
|
--left-pane-item-selected-shadow-size: 4px;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
background-color: transparent;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left-pane span.fancytree-node.fancytree-selected::after {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
z-index: -2;
|
||||||
|
content: "";
|
||||||
|
inset: 0;
|
||||||
|
background: var(--selection-background-color);
|
||||||
|
animation: left-pane-item-select 100ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
#left-pane span.fancytree-node.protected > span.fancytree-custom-icon {
|
#left-pane span.fancytree-node.protected > span.fancytree-custom-icon {
|
||||||
position: relative;
|
position: relative;
|
||||||
filter: unset !important;
|
filter: unset !important;
|
||||||
@ -780,7 +801,8 @@ body[dir=rtl] #left-pane span.fancytree-node.protected > span.fancytree-custom-i
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
#left-pane .tree-item-button {
|
#left-pane .tree-item-button,
|
||||||
|
#left-pane span.fancytree-node.fancytree-selected .fancytree-custom-icon {
|
||||||
margin-inline-end: 6px;
|
margin-inline-end: 6px;
|
||||||
border: unset;
|
border: unset;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
@ -791,7 +813,8 @@ body[dir=rtl] #left-pane span.fancytree-node.protected > span.fancytree-custom-i
|
|||||||
box-shadow 200ms ease-out;
|
box-shadow 200ms ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
#left-pane .tree-item-button:hover {
|
#left-pane .tree-item-button:hover,
|
||||||
|
#left-pane span.fancytree-node.fancytree-selected .fancytree-custom-icon:hover {
|
||||||
background: var(--left-pane-item-action-button-hover-background);
|
background: var(--left-pane-item-action-button-hover-background);
|
||||||
box-shadow: var(--left-pane-item-action-button-hover-shadow);
|
box-shadow: var(--left-pane-item-action-button-hover-shadow);
|
||||||
transition:
|
transition:
|
||||||
@ -799,10 +822,41 @@ body[dir=rtl] #left-pane span.fancytree-node.protected > span.fancytree-custom-i
|
|||||||
box-shadow 100ms ease-in;
|
box-shadow 100ms ease-in;
|
||||||
}
|
}
|
||||||
|
|
||||||
#left-pane span.fancytree-node.fancytree-active .tree-item-button:hover {
|
#left-pane span.fancytree-node.fancytree-active .tree-item-button:hover,
|
||||||
|
#left-pane span.fancytree-node.fancytree-active.fancytree-selected .fancytree-custom-icon:hover {
|
||||||
box-shadow: var(--left-pane-item-selected-action-button-hover-shadow);
|
box-shadow: var(--left-pane-item-selected-action-button-hover-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Selected item bulk action button */
|
||||||
|
|
||||||
|
@keyframes bulk-action-button-blink {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: .3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#left-pane span.fancytree-node.fancytree-selected .fancytree-custom-icon {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left-pane span.fancytree-node.fancytree-selected .fancytree-custom-icon::before {
|
||||||
|
border: 0;
|
||||||
|
font-size: .65em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left-pane span.fancytree-node.fancytree-selected:hover .fancytree-custom-icon:not(:hover)::before {
|
||||||
|
animation: bulk-action-button-blink 500ms linear infinite alternate;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left-pane span.fancytree-node.fancytree-selected.protected .fancytree-custom-icon::after {
|
||||||
|
/* Protected note indicator */
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#context-menu-container {
|
#context-menu-container {
|
||||||
/* The context menu of the tree */
|
/* The context menu of the tree */
|
||||||
--menu-item-icon-vert-offset: -1px;
|
--menu-item-icon-vert-offset: -1px;
|
||||||
|
|||||||
@ -140,10 +140,22 @@ ul.fancytree-container {
|
|||||||
background-color: inherit;
|
background-color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.fancytree-custom-icon {
|
.fancytree-custom-icon {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Fallback icon */
|
||||||
|
:where(.fancytree-custom-icon)::before {
|
||||||
|
content: "?";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Protected note icon badge */
|
||||||
span.fancytree-node.protected > span.fancytree-custom-icon {
|
span.fancytree-node.protected > span.fancytree-custom-icon {
|
||||||
filter: drop-shadow(2px 2px 2px var(--main-text-color));
|
filter: drop-shadow(2px 2px 2px var(--main-text-color));
|
||||||
}
|
}
|
||||||
@ -185,7 +197,7 @@ span.fancytree-node.fancytree-active-clone:not(.fancytree-active) .fancytree-tit
|
|||||||
|
|
||||||
span.fancytree-active {
|
span.fancytree-active {
|
||||||
color: var(--active-item-text-color);
|
color: var(--active-item-text-color);
|
||||||
background-color: var(--active-item-background-color) !important;
|
background-color: var(--active-item-background-color);
|
||||||
border-color: transparent; /* invisible border */
|
border-color: transparent; /* invisible border */
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
@ -195,20 +207,15 @@ span.fancytree-active .fancytree-title {
|
|||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
span.fancytree-selected {
|
span.fancytree-node.fancytree-selected {
|
||||||
border-color: var(--main-border-color) !important;
|
background-color: var(--selection-background-color);
|
||||||
border-radius: 5px;
|
border-radius: 0;
|
||||||
}
|
|
||||||
|
|
||||||
span.fancytree-selected .fancytree-title {
|
|
||||||
text-decoration: underline;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
span.fancytree-selected .fancytree-custom-icon::before {
|
span.fancytree-selected .fancytree-custom-icon::before {
|
||||||
font-family: "boxicons";
|
font-family: "boxicons";
|
||||||
content: "\eb43";
|
content: "\ef05";
|
||||||
border: 1px solid var(--main-border-color);
|
border: 1px solid var(--main-text-color);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1534,7 +1534,8 @@
|
|||||||
"task-list": "任务列表",
|
"task-list": "任务列表",
|
||||||
"new-feature": "新建",
|
"new-feature": "新建",
|
||||||
"collections": "集合",
|
"collections": "集合",
|
||||||
"book": "集合"
|
"book": "集合",
|
||||||
|
"ai-chat": "AI聊天"
|
||||||
},
|
},
|
||||||
"protect_note": {
|
"protect_note": {
|
||||||
"toggle-on": "保护笔记",
|
"toggle-on": "保护笔记",
|
||||||
@ -1630,7 +1631,8 @@
|
|||||||
},
|
},
|
||||||
"search_result": {
|
"search_result": {
|
||||||
"no_notes_found": "没有找到符合搜索条件的笔记。",
|
"no_notes_found": "没有找到符合搜索条件的笔记。",
|
||||||
"search_not_executed": "尚未执行搜索。请点击上方的\"搜索\"按钮查看结果。"
|
"search_not_executed": "尚未执行搜索。",
|
||||||
|
"search_now": "立即搜索"
|
||||||
},
|
},
|
||||||
"spacer": {
|
"spacer": {
|
||||||
"configure_launchbar": "配置启动栏"
|
"configure_launchbar": "配置启动栏"
|
||||||
@ -2005,7 +2007,9 @@
|
|||||||
"app-restart-required": "(需重启程序以应用更改)"
|
"app-restart-required": "(需重启程序以应用更改)"
|
||||||
},
|
},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"total_notes": "{{count}} 篇笔记"
|
"total_notes": "{{count}} 篇笔记",
|
||||||
|
"prev_page": "上一页",
|
||||||
|
"next_page": "下一页"
|
||||||
},
|
},
|
||||||
"collections": {
|
"collections": {
|
||||||
"rendering_error": "出现错误无法显示内容。"
|
"rendering_error": "出现错误无法显示内容。"
|
||||||
|
|||||||
@ -1679,7 +1679,8 @@
|
|||||||
},
|
},
|
||||||
"search_result": {
|
"search_result": {
|
||||||
"no_notes_found": "Ní bhfuarthas aon nótaí do na paraiméadair chuardaigh tugtha.",
|
"no_notes_found": "Ní bhfuarthas aon nótaí do na paraiméadair chuardaigh tugtha.",
|
||||||
"search_not_executed": "Níl an cuardach curtha i gcrích fós. Cliceáil ar an gcnaipe \"Cuardaigh\" thuas chun na torthaí a fheiceáil."
|
"search_not_executed": "Níl an cuardach curtha i gcrích fós.",
|
||||||
|
"search_now": "Cuardaigh anois"
|
||||||
},
|
},
|
||||||
"spacer": {
|
"spacer": {
|
||||||
"configure_launchbar": "Cumraigh an Barra Seoladh"
|
"configure_launchbar": "Cumraigh an Barra Seoladh"
|
||||||
|
|||||||
@ -83,7 +83,10 @@
|
|||||||
"erase_notes_warning": "Hapus catatan secara permanen (tidak bisa dikembalikan), termasuk semua duplikat. Aksi akan memaksa aplikasi untuk mengulang kembali.",
|
"erase_notes_warning": "Hapus catatan secara permanen (tidak bisa dikembalikan), termasuk semua duplikat. Aksi akan memaksa aplikasi untuk mengulang kembali.",
|
||||||
"notes_to_be_deleted": "Catatan-catatan berikut akan dihapuskan ({{notesCount}})",
|
"notes_to_be_deleted": "Catatan-catatan berikut akan dihapuskan ({{notesCount}})",
|
||||||
"no_note_to_delete": "Tidak ada Catatan yang akan dihapus (hanya duplikat).",
|
"no_note_to_delete": "Tidak ada Catatan yang akan dihapus (hanya duplikat).",
|
||||||
"broken_relations_to_be_deleted": "Hubungan berikut akan diputus dan dihapus ({{ relationCount}})"
|
"broken_relations_to_be_deleted": "Hubungan berikut akan diputus dan dihapus ({{ relationCount}})",
|
||||||
|
"cancel": "Batalkan",
|
||||||
|
"ok": "Setuju",
|
||||||
|
"deleted_relation_text": "Catatan {{- note}} (yang akan dihapus) dirujuk oleh relasi {{- relation}} yang berasal dari {{- source}}."
|
||||||
},
|
},
|
||||||
"clone_to": {
|
"clone_to": {
|
||||||
"clone_notes_to": "Duplikat catatan ke…",
|
"clone_notes_to": "Duplikat catatan ke…",
|
||||||
@ -96,5 +99,12 @@
|
|||||||
"clone_to_selected_note": "Salin ke catatan yang dipilih",
|
"clone_to_selected_note": "Salin ke catatan yang dipilih",
|
||||||
"no_path_to_clone_to": "Tidak ada jalur untuk digandakan.",
|
"no_path_to_clone_to": "Tidak ada jalur untuk digandakan.",
|
||||||
"note_cloned": "Catatan \"{{clonedTitle}}\" telah digandakan ke dalam \"{{targetTitle}}\""
|
"note_cloned": "Catatan \"{{clonedTitle}}\" telah digandakan ke dalam \"{{targetTitle}}\""
|
||||||
|
},
|
||||||
|
"search_result": {
|
||||||
|
"search_now": "Cari sekarang"
|
||||||
|
},
|
||||||
|
"export": {
|
||||||
|
"export_note_title": "Mengeluarkan catatan",
|
||||||
|
"close": "Tutup"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -118,7 +118,7 @@
|
|||||||
"export_type_subtree": "Questa nota e tutti i suoi discendenti",
|
"export_type_subtree": "Questa nota e tutti i suoi discendenti",
|
||||||
"format_html": "HTML - raccomandato in quanto mantiene tutti i formati",
|
"format_html": "HTML - raccomandato in quanto mantiene tutti i formati",
|
||||||
"format_html_zip": "HTML in archivio ZIP - questo è raccomandato in quanto conserva tutta la formattazione.",
|
"format_html_zip": "HTML in archivio ZIP - questo è raccomandato in quanto conserva tutta la formattazione.",
|
||||||
"format_markdown": "MArkdown - questo conserva la maggior parte della formattazione.",
|
"format_markdown": "Markdown: preserva la maggior parte della formattazione.",
|
||||||
"export_type_single": "Solo questa nota, senza le sottostanti",
|
"export_type_single": "Solo questa nota, senza le sottostanti",
|
||||||
"format_opml": "OPML - formato per scambio informazioni outline. Formattazione, immagini e files non sono inclusi.",
|
"format_opml": "OPML - formato per scambio informazioni outline. Formattazione, immagini e files non sono inclusi.",
|
||||||
"opml_version_1": "OPML v.1.0 - solo testo semplice",
|
"opml_version_1": "OPML v.1.0 - solo testo semplice",
|
||||||
@ -592,7 +592,7 @@
|
|||||||
"collapseExpand": "collassa/espande il nodo",
|
"collapseExpand": "collassa/espande il nodo",
|
||||||
"notSet": "non impostato",
|
"notSet": "non impostato",
|
||||||
"goBackForwards": "indietro/avanti nella cronologia",
|
"goBackForwards": "indietro/avanti nella cronologia",
|
||||||
"showJumpToNoteDialog": "mostra <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">finestra di dialogo “Vai a”</a>",
|
"showJumpToNoteDialog": "mostra <a class=\"external\" href=\"https://triliumnext.github.io/Docs/Wiki/note-navigation.html#jump-to-note\">\"Vai a\"</a>",
|
||||||
"title": "Scheda riassuntiva",
|
"title": "Scheda riassuntiva",
|
||||||
"noteNavigation": "Nota navigazione",
|
"noteNavigation": "Nota navigazione",
|
||||||
"scrollToActiveNote": "scorri fino alla nota attiva",
|
"scrollToActiveNote": "scorri fino alla nota attiva",
|
||||||
@ -1715,7 +1715,8 @@
|
|||||||
"beta-feature": "Beta",
|
"beta-feature": "Beta",
|
||||||
"task-list": "Elenco delle attività",
|
"task-list": "Elenco delle attività",
|
||||||
"new-feature": "Nuovo",
|
"new-feature": "Nuovo",
|
||||||
"collections": "Collezioni"
|
"collections": "Collezioni",
|
||||||
|
"ai-chat": "Chat con IA"
|
||||||
},
|
},
|
||||||
"protect_note": {
|
"protect_note": {
|
||||||
"toggle-on": "Proteggi la nota",
|
"toggle-on": "Proteggi la nota",
|
||||||
@ -1793,7 +1794,8 @@
|
|||||||
},
|
},
|
||||||
"search_result": {
|
"search_result": {
|
||||||
"no_notes_found": "Non sono state trovate note per i parametri di ricerca specificati.",
|
"no_notes_found": "Non sono state trovate note per i parametri di ricerca specificati.",
|
||||||
"search_not_executed": "La ricerca non è stata ancora eseguita. Clicca sul pulsante \"Cerca\" qui sopra per visualizzare i risultati."
|
"search_not_executed": "La ricerca non è stata ancora eseguita.",
|
||||||
|
"search_now": "Cerca ora"
|
||||||
},
|
},
|
||||||
"spacer": {
|
"spacer": {
|
||||||
"configure_launchbar": "Configura Launchbar"
|
"configure_launchbar": "Configura Launchbar"
|
||||||
@ -2020,7 +2022,9 @@
|
|||||||
"percentage": "%"
|
"percentage": "%"
|
||||||
},
|
},
|
||||||
"pagination": {
|
"pagination": {
|
||||||
"total_notes": "{{count}} note"
|
"total_notes": "{{count}} note",
|
||||||
|
"prev_page": "Pagina precedente",
|
||||||
|
"next_page": "Pagina successiva"
|
||||||
},
|
},
|
||||||
"collections": {
|
"collections": {
|
||||||
"rendering_error": "Impossibile mostrare il contenuto a causa di un errore."
|
"rendering_error": "Impossibile mostrare il contenuto a causa di un errore."
|
||||||
|
|||||||
@ -599,7 +599,8 @@
|
|||||||
"beta-feature": "Beta",
|
"beta-feature": "Beta",
|
||||||
"task-list": "タスクリスト",
|
"task-list": "タスクリスト",
|
||||||
"new-feature": "New",
|
"new-feature": "New",
|
||||||
"collections": "コレクション"
|
"collections": "コレクション",
|
||||||
|
"ai-chat": "AI チャット"
|
||||||
},
|
},
|
||||||
"edited_notes": {
|
"edited_notes": {
|
||||||
"no_edited_notes_found": "この日の編集されたノートはまだありません...",
|
"no_edited_notes_found": "この日の編集されたノートはまだありません...",
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import "./NoteDetail.css";
|
import "./NoteDetail.css";
|
||||||
|
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { note } from "mermaid/dist/rendering-util/rendering-elements/shapes/note.js";
|
|
||||||
import { isValidElement, VNode } from "preact";
|
import { isValidElement, VNode } from "preact";
|
||||||
import { useEffect, useRef, useState } from "preact/hooks";
|
import { useEffect, useRef, useState } from "preact/hooks";
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
top: 20px;
|
top: calc(env(safe-area-inset-top) + 20px);
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
contain: none;
|
contain: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,8 @@ import Button from "../react/Button";
|
|||||||
import "./Pagination.css";
|
import "./Pagination.css";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
interface PaginationContext {
|
export interface PaginationContext {
|
||||||
|
className?: string;
|
||||||
page: number;
|
page: number;
|
||||||
setPage: Dispatch<StateUpdater<number>>;
|
setPage: Dispatch<StateUpdater<number>>;
|
||||||
pageNotes?: FNote[];
|
pageNotes?: FNote[];
|
||||||
@ -18,11 +19,11 @@ interface PaginationContext {
|
|||||||
totalNotes: number;
|
totalNotes: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Pager({ page, pageSize, setPage, pageCount, totalNotes }: Omit<PaginationContext, "pageNotes">) {
|
export function Pager({ className, page, pageSize, setPage, pageCount, totalNotes }: Omit<PaginationContext, "pageNotes">) {
|
||||||
if (pageCount < 2) return;
|
if (pageCount < 2) return;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="note-list-pager-container">
|
<div className={clsx("note-list-pager-container", className)}>
|
||||||
<div className="note-list-pager">
|
<div className="note-list-pager">
|
||||||
<ActionButton
|
<ActionButton
|
||||||
icon="bx bx-chevron-left"
|
icon="bx bx-chevron-left"
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 1em;
|
gap: 1em;
|
||||||
padding-inline: 12px;
|
margin-inline: var(--content-margin-inline);
|
||||||
padding-block: 4px;
|
padding-block: 4px;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
|||||||
@ -52,7 +52,7 @@
|
|||||||
--fc-border-color: var(--main-border-color);
|
--fc-border-color: var(--main-border-color);
|
||||||
--fc-neutral-bg-color: var(--launcher-pane-background-color);
|
--fc-neutral-bg-color: var(--launcher-pane-background-color);
|
||||||
--fc-list-event-hover-bg-color: var(--left-pane-item-hover-background);
|
--fc-list-event-hover-bg-color: var(--left-pane-item-hover-background);
|
||||||
padding: 0 12px;
|
padding: 0 var(--content-margin-inline);
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-container .fc-list-sticky .fc-list-day > * {
|
.calendar-container .fc-list-sticky .fc-list-day > * {
|
||||||
|
|||||||
@ -2,142 +2,40 @@
|
|||||||
overflow: visible;
|
overflow: visible;
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
|
.note-list-wrapper {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.grid-view .note-list-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-list-bottom-pager {
|
||||||
|
margin-block: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:has(.note-list-bottom-pager)) {
|
||||||
|
margin-bottom: 48px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-book-card {
|
/* #region List view / Grid view common styles */
|
||||||
border-radius: 10px;
|
|
||||||
background-color: var(--accented-background-color);
|
|
||||||
padding: 10px 15px 15px 8px;
|
|
||||||
margin: 5px 5px 5px 5px;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex-shrink: 0;
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-card.archived {
|
.nested-note-list-item h5,
|
||||||
opacity: 0.5;
|
.note-book-card .note-book-header {
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-card:not(.expanded) .note-book-content {
|
|
||||||
padding: 10px
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-card.expanded .note-book-content {
|
|
||||||
display: block;
|
|
||||||
min-height: 0;
|
|
||||||
height: 100%;
|
|
||||||
padding-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-content .rendered-content {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-header {
|
|
||||||
border-bottom: 1px solid var(--main-border-color);
|
|
||||||
margin-bottom: 0;
|
|
||||||
padding-bottom: .5rem;
|
|
||||||
word-break: break-all;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* not-expanded title is limited to one line only */
|
|
||||||
.note-book-card:not(.expanded) .note-book-header {
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-header .rendered-note-attributes {
|
|
||||||
font-size: medium;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-header .rendered-note-attributes:before {
|
|
||||||
content: "\00a0\00a0";
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-header .note-icon {
|
|
||||||
font-size: 100%;
|
|
||||||
display: inline-block;
|
|
||||||
padding-inline-end: 7px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-card .note-book-card {
|
|
||||||
border: 1px solid var(--main-border-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-content.type-image, .note-book-content.type-file, .note-book-content.type-protectedSession {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
font-size: 1em;
|
||||||
text-align: center;
|
font-weight: normal;
|
||||||
padding: 10px;
|
margin: 0;
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-content.type-image img, .note-book-content.type-canvas svg {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-card.type-image .note-book-content img,
|
|
||||||
.note-book-card.type-text .note-book-content img,
|
|
||||||
.note-book-card.type-canvas .note-book-content img {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-book-header {
|
|
||||||
flex-grow: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-wrapper {
|
|
||||||
height: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #region List view */
|
|
||||||
|
|
||||||
@keyframes note-preview-show {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
} to {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.nested-note-list {
|
|
||||||
--card-nested-section-indent: 25px;
|
|
||||||
|
|
||||||
&.search-results {
|
|
||||||
--card-nested-section-indent: 32px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* List item */
|
|
||||||
.nested-note-list-item {
|
|
||||||
h5 {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 1em;
|
|
||||||
font-weight: normal;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-expander {
|
|
||||||
margin-inline-end: 4px;
|
|
||||||
font-size: x-large;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tn-icon {
|
.tn-icon {
|
||||||
margin-inline-end: 8px;
|
|
||||||
color: var(--note-list-view-icon-color);
|
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
|
margin-inline-end: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-book-title {
|
.note-book-title {
|
||||||
@ -147,52 +45,24 @@
|
|||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-path {
|
.note-book-item-menu {
|
||||||
margin-left: 0.5em;
|
|
||||||
vertical-align: middle;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list-attributes {
|
|
||||||
flex-grow: 1;
|
|
||||||
margin-inline-start: 1em;
|
|
||||||
text-align: right;
|
|
||||||
font-size: .75em;
|
|
||||||
opacity: .75;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nested-note-list-item-menu {
|
|
||||||
margin-inline-start: 8px;
|
margin-inline-start: 8px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.archived {
|
|
||||||
span.tn-icon + span,
|
|
||||||
.tn-icon {
|
|
||||||
opacity: .6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.use-note-color {
|
|
||||||
span.tn-icon + span,
|
|
||||||
.nested-note-list:not(.search-results) & .tn-icon,
|
|
||||||
.rendered-note-attributes {
|
|
||||||
color: var(--custom-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.nested-note-list:not(.search-results) h5 {
|
.nested-note-list-item.use-note-color,
|
||||||
|
.note-book-card.use-note-color .note-book-header {
|
||||||
span.tn-icon + span,
|
span.tn-icon + span,
|
||||||
.note-list-attributes {
|
.tn-icon,
|
||||||
white-space: nowrap;
|
.rendered-note-attributes {
|
||||||
overflow: hidden;
|
color: var(--custom-color);
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* List item (search results view) */
|
/* Search result view */
|
||||||
.nested-note-list.search-results .nested-note-list-item {
|
.nested-note-list.search-results .nested-note-list-item,
|
||||||
|
.note-list-container.search-results .note-book-card .note-book-header {
|
||||||
span.tn-icon + span > span {
|
span.tn-icon + span > span {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
@ -204,6 +74,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.note-path {
|
.note-path {
|
||||||
|
opacity: 0.5;
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
font-size: .85em;
|
font-size: .85em;
|
||||||
line-height: .85em;
|
line-height: .85em;
|
||||||
@ -225,7 +96,7 @@
|
|||||||
color: var(--note-icon-custom-color, var(--note-list-view-large-icon-color));
|
color: var(--note-icon-custom-color, var(--note-list-view-large-icon-color));
|
||||||
}
|
}
|
||||||
|
|
||||||
h5 .ck-find-result {
|
.ck-find-result {
|
||||||
background: var(--note-list-view-search-result-highlight-background);
|
background: var(--note-list-view-search-result-highlight-background);
|
||||||
color: var(--note-list-view-search-result-highlight-color);
|
color: var(--note-list-view-search-result-highlight-color);
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@ -233,21 +104,114 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes note-preview-show {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
} to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nested-note-list .note-book-content,
|
||||||
|
.note-list-container .note-book-content {
|
||||||
|
display: none;
|
||||||
|
animation: note-preview-show .35s ease-out;
|
||||||
|
will-change: opacity;
|
||||||
|
|
||||||
|
&.note-book-content-ready {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ck-find-result {
|
||||||
|
outline: 2px solid var(--note-list-view-content-search-result-highlight-background);
|
||||||
|
border-radius: 4px;
|
||||||
|
background: var(--note-list-view-content-search-result-highlight-background);
|
||||||
|
color: var(--note-list-view-content-search-result-highlight-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-book-content {
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
&.type-image, &.type-file, &.type-protectedSession {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.type-image img, &.type-canvas svg {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-content-preview:has(.note-book-content:empty) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endregion */
|
||||||
|
|
||||||
|
/* #region List view */
|
||||||
|
|
||||||
|
.nested-note-list {
|
||||||
|
--card-nested-section-indent: 25px;
|
||||||
|
|
||||||
|
&.search-results {
|
||||||
|
--card-nested-section-indent: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* List item */
|
||||||
|
.nested-note-list-item {
|
||||||
|
|
||||||
|
.note-expander {
|
||||||
|
margin-inline-end: 4px;
|
||||||
|
font-size: x-large;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tn-icon {
|
||||||
|
color: var(--note-list-view-icon-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-list-attributes {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-inline-start: 1em;
|
||||||
|
text-align: right;
|
||||||
|
font-size: .75em;
|
||||||
|
opacity: .75;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.archived {
|
||||||
|
span.tn-icon + span,
|
||||||
|
.tn-icon {
|
||||||
|
opacity: .6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nested-note-list:not(.search-results) h5,
|
||||||
|
.note-book-card:not(.search-results) h5 {
|
||||||
|
span.tn-icon + span,
|
||||||
|
.note-list-attributes {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Note content preview */
|
/* Note content preview */
|
||||||
.nested-note-list .note-book-content {
|
.nested-note-list .note-book-content {
|
||||||
display: none;
|
|
||||||
outline: 1px solid var(--note-list-view-content-background);
|
outline: 1px solid var(--note-list-view-content-background);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background-color: var(--note-list-view-content-background);
|
background-color: var(--note-list-view-content-background);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
user-select: text;
|
user-select: text;
|
||||||
font-size: .85rem;
|
font-size: .85rem;
|
||||||
animation: note-preview-show .25s ease-out;
|
|
||||||
will-change: opacity;
|
|
||||||
|
|
||||||
&.note-book-content-ready {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .rendered-content > *:last-child {
|
> .rendered-content > *:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
@ -285,54 +249,190 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-height: 50vh;
|
min-height: 50vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ck-find-result {
|
|
||||||
outline: 2px solid var(--note-list-view-content-search-result-highlight-background);
|
|
||||||
border-radius: 4px;
|
|
||||||
background: var(--note-list-view-content-search-result-highlight-background);
|
|
||||||
color: var(--note-list-view-content-search-result-highlight-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-content-preview:has(.note-book-content:empty) {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #endregion */
|
/* #endregion */
|
||||||
|
|
||||||
/* #region Grid view */
|
/* #region Grid view */
|
||||||
.note-list.grid-view .note-list-container {
|
|
||||||
|
.note-list .note-book-card {
|
||||||
|
--note-list-horizontal-padding: 22px;
|
||||||
|
--note-list-vertical-padding: 15px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-direction: column;
|
||||||
}
|
flex-shrink: 0;
|
||||||
|
flex-grow: 1;
|
||||||
.note-list.grid-view .note-book-card {
|
|
||||||
flex-basis: 300px;
|
flex-basis: 300px;
|
||||||
border: 1px solid transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
body.mobile .note-list.grid-view .note-book-card {
|
|
||||||
flex-basis: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list.grid-view .note-book-card {
|
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
|
padding: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
body.mobile & {
|
||||||
|
flex-basis: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--card-background-hover-color);
|
||||||
|
filter: contrast(105%);
|
||||||
|
transition: background-color 200ms ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(:has(:is(.note-book-item-menu:active, .btn-primary:active))):active {
|
||||||
|
transform: scale(.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.archived {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-book-header {
|
||||||
|
margin-bottom: 0;
|
||||||
|
border-bottom: 1px solid var(--card-border-color, var(--main-border-color));
|
||||||
|
padding-bottom: .5rem;
|
||||||
|
word-break: break-all;
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
padding-inline-end: 8px;
|
||||||
|
|
||||||
|
.tn-icon + span {
|
||||||
|
flex-grow: 1;
|
||||||
|
a {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& .note-book-content {
|
||||||
|
&.type-image .note-book-content img,
|
||||||
|
&.type-text .note-book-content img,
|
||||||
|
&.type-canvas .note-book-content img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rendered-content {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rendered-content:has(.file-footer) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-height: 220px;
|
||||||
|
object-fit: contain;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-footer {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
.btn.btn-primary {
|
||||||
|
flex: 1;
|
||||||
|
margin: 0;
|
||||||
|
box-shadow: unset;
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
padding: 8px;
|
||||||
|
color: var(--main-text-color);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--more-accented-background-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-list.grid-view .note-book-card img {
|
.note-book-card .note-book-content {
|
||||||
max-height: 220px;
|
padding: 0;
|
||||||
object-fit: contain;
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
|
||||||
|
&.note-book-content-overflowing {
|
||||||
|
mask-image: linear-gradient(to bottom, black calc(100% - 75px), transparent 100%);
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-size: 100% 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ck-content p {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ck-content figure.image {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ck-content .table {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
overflow-x: scroll;
|
||||||
|
--scrollbar-thickness: 0;
|
||||||
|
scrollbar-width: none;
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: max-content;
|
||||||
|
table-layout: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
figcaption {
|
||||||
|
display: block;
|
||||||
|
position: sticky;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.rendered-content,
|
||||||
|
.rendered-content.text-with-ellipsis {
|
||||||
|
padding: .5rem 1rem 1rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.type-image .rendered-content,
|
||||||
|
&.type-pdf .rendered-content {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.type-video video {
|
||||||
|
max-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-size: 1rem;
|
||||||
|
color: var(--active-item-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.type-canvas .rendered-content,
|
||||||
|
&.type-mindMap .rendered-content,
|
||||||
|
&.type-code .rendered-content,
|
||||||
|
&.type-video .rendered-content {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.type-code {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.type-code pre {
|
||||||
|
height: 100%;
|
||||||
|
padding: 1em;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-list.grid-view .note-book-card:hover {
|
/* #endregion */
|
||||||
cursor: pointer;
|
|
||||||
border: 1px solid var(--main-border-color);
|
|
||||||
background: var(--more-accented-background-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.note-list.grid-view .note-path {
|
|
||||||
margin-left: 0.5em;
|
|
||||||
vertical-align: middle;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
/* #endregion */
|
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import "./ListOrGridView.css";
|
import "./ListOrGridView.css";
|
||||||
import { Card, CardSection } from "../../react/Card";
|
import { Card, CardFrame, CardSection } from "../../react/Card";
|
||||||
|
|
||||||
import { useEffect, useRef, useState } from "preact/hooks";
|
import { useCallback, useEffect, useRef, useState } from "preact/hooks";
|
||||||
|
|
||||||
import FNote from "../../../entities/fnote";
|
import FNote from "../../../entities/fnote";
|
||||||
import attribute_renderer from "../../../services/attribute_renderer";
|
import attribute_renderer from "../../../services/attribute_renderer";
|
||||||
@ -13,13 +13,15 @@ import { useImperativeSearchHighlighlighting, useNoteLabel, useNoteLabelBoolean,
|
|||||||
import Icon from "../../react/Icon";
|
import Icon from "../../react/Icon";
|
||||||
import NoteLink from "../../react/NoteLink";
|
import NoteLink from "../../react/NoteLink";
|
||||||
import { ViewModeProps } from "../interface";
|
import { ViewModeProps } from "../interface";
|
||||||
import { Pager, usePagination } from "../Pagination";
|
import { Pager, usePagination, PaginationContext } from "../Pagination";
|
||||||
import { filterChildNotes, useFilteredNoteIds } from "./utils";
|
import { filterChildNotes, useFilteredNoteIds } from "./utils";
|
||||||
import { JSX } from "preact/jsx-runtime";
|
import { JSX } from "preact/jsx-runtime";
|
||||||
import { clsx } from "clsx";
|
import { clsx } from "clsx";
|
||||||
import ActionButton from "../../react/ActionButton";
|
import ActionButton from "../../react/ActionButton";
|
||||||
import linkContextMenuService from "../../../menus/link_context_menu";
|
import linkContextMenuService from "../../../menus/link_context_menu";
|
||||||
import { TargetedMouseEvent } from "preact";
|
import { ComponentChildren, TargetedMouseEvent } from "preact";
|
||||||
|
|
||||||
|
const contentSizeObserver = new ResizeObserver(onContentResized);
|
||||||
|
|
||||||
export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) {
|
export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) {
|
||||||
const expandDepth = useExpansionDepth(note);
|
const expandDepth = useExpansionDepth(note);
|
||||||
@ -27,32 +29,18 @@ export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
|||||||
const { pageNotes, ...pagination } = usePagination(note, noteIds);
|
const { pageNotes, ...pagination } = usePagination(note, noteIds);
|
||||||
const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived");
|
const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived");
|
||||||
const noteType = useNoteProperty(note, "type");
|
const noteType = useNoteProperty(note, "type");
|
||||||
const hasCollectionProperties = [ "book", "search" ].includes(noteType ?? "");
|
|
||||||
|
|
||||||
return (
|
return <NoteList note={note} viewMode="list-view" noteIds={noteIds} pagination={pagination}>
|
||||||
<div class="note-list list-view">
|
<Card className={clsx("nested-note-list", {"search-results": (noteType === "search")})}>
|
||||||
<CollectionProperties
|
{pageNotes?.map(childNote => (
|
||||||
note={note}
|
<ListNoteCard
|
||||||
centerChildren={<Pager {...pagination} />}
|
key={childNote.noteId}
|
||||||
/>
|
note={childNote} parentNote={note}
|
||||||
|
expandDepth={expandDepth} highlightedTokens={highlightedTokens}
|
||||||
{ noteIds.length > 0 && <div class="note-list-wrapper">
|
currentLevel={1} includeArchived={includeArchived} />
|
||||||
{!hasCollectionProperties && <Pager {...pagination} />}
|
))}
|
||||||
|
</Card>
|
||||||
<Card className={clsx("nested-note-list", {"search-results": (noteType === "search")})}>
|
</NoteList>;
|
||||||
{pageNotes?.map(childNote => (
|
|
||||||
<ListNoteCard
|
|
||||||
key={childNote.noteId}
|
|
||||||
note={childNote} parentNote={note}
|
|
||||||
expandDepth={expandDepth} highlightedTokens={highlightedTokens}
|
|
||||||
currentLevel={1} includeArchived={includeArchived} />
|
|
||||||
))}
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
<Pager {...pagination} />
|
|
||||||
</div>}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) {
|
export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) {
|
||||||
@ -60,28 +48,47 @@ export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
|
|||||||
const { pageNotes, ...pagination } = usePagination(note, noteIds);
|
const { pageNotes, ...pagination } = usePagination(note, noteIds);
|
||||||
const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived");
|
const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived");
|
||||||
const noteType = useNoteProperty(note, "type");
|
const noteType = useNoteProperty(note, "type");
|
||||||
const hasCollectionProperties = [ "book", "search" ].includes(noteType ?? "");
|
|
||||||
|
|
||||||
return (
|
return <NoteList note={note} viewMode="grid-view" noteIds={noteIds} pagination={pagination}>
|
||||||
<div class="note-list grid-view">
|
<div className={clsx("note-list-container use-tn-links", {"search-results": (noteType === "search")})}>
|
||||||
<CollectionProperties
|
{pageNotes?.map(childNote => (
|
||||||
note={note}
|
<GridNoteCard key={childNote.noteId}
|
||||||
centerChildren={<Pager {...pagination} />}
|
note={childNote}
|
||||||
/>
|
parentNote={note}
|
||||||
|
highlightedTokens={highlightedTokens}
|
||||||
<div class="note-list-wrapper">
|
includeArchived={includeArchived} />
|
||||||
{!hasCollectionProperties && <Pager {...pagination} />}
|
))}
|
||||||
|
|
||||||
<div class="note-list-container use-tn-links">
|
|
||||||
{pageNotes?.map(childNote => (
|
|
||||||
<GridNoteCard note={childNote} parentNote={note} highlightedTokens={highlightedTokens} includeArchived={includeArchived} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Pager {...pagination} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
</NoteList>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NoteListProps {
|
||||||
|
note: FNote,
|
||||||
|
viewMode: "list-view" | "grid-view",
|
||||||
|
noteIds: string[],
|
||||||
|
pagination: PaginationContext,
|
||||||
|
children: ComponentChildren
|
||||||
|
}
|
||||||
|
|
||||||
|
function NoteList(props: NoteListProps) {
|
||||||
|
const noteType = useNoteProperty(props.note, "type");
|
||||||
|
const hasCollectionProperties = ["book", "search"].includes(noteType ?? "");
|
||||||
|
|
||||||
|
return <div className={clsx("note-list", props.viewMode)}>
|
||||||
|
<CollectionProperties
|
||||||
|
note={props.note}
|
||||||
|
centerChildren={<Pager className="note-list-top-pager" {...props.pagination} />}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{props.noteIds.length > 0 && <div className="note-list-wrapper">
|
||||||
|
{!hasCollectionProperties && <Pager {...props.pagination} />}
|
||||||
|
|
||||||
|
{props.children}
|
||||||
|
|
||||||
|
<Pager className="note-list-bottom-pager" {...props.pagination} />
|
||||||
|
</div>}
|
||||||
|
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
function ListNoteCard({ note, parentNote, highlightedTokens, currentLevel, expandDepth, includeArchived }: {
|
function ListNoteCard({ note, parentNote, highlightedTokens, currentLevel, expandDepth, includeArchived }: {
|
||||||
@ -139,39 +146,47 @@ function ListNoteCard({ note, parentNote, highlightedTokens, currentLevel, expan
|
|||||||
showNotePath={parentNote.type === "search"}
|
showNotePath={parentNote.type === "search"}
|
||||||
highlightedTokens={highlightedTokens} />
|
highlightedTokens={highlightedTokens} />
|
||||||
<NoteAttributes note={note} />
|
<NoteAttributes note={note} />
|
||||||
<ActionButton className="nested-note-list-item-menu"
|
<NoteMenuButton notePath={notePath} />
|
||||||
icon="bx bx-dots-vertical-rounded" text=""
|
|
||||||
onClick={(e) => openNoteMenu(notePath, e)}
|
|
||||||
/>
|
|
||||||
</h5>
|
</h5>
|
||||||
</CardSection>
|
</CardSection>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function GridNoteCard({ note, parentNote, highlightedTokens, includeArchived }: { note: FNote, parentNote: FNote, highlightedTokens: string[] | null | undefined, includeArchived: boolean }) {
|
interface GridNoteCardProps {
|
||||||
const titleRef = useRef<HTMLSpanElement>(null);
|
note: FNote;
|
||||||
const [ noteTitle, setNoteTitle ] = useState<string>();
|
parentNote: FNote;
|
||||||
const notePath = getNotePath(parentNote, note);
|
highlightedTokens: string[] | null | undefined;
|
||||||
|
includeArchived: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GridNoteCard(props: GridNoteCardProps) {
|
||||||
|
const notePath = getNotePath(props.parentNote, props.note);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<CardFrame className={clsx("note-book-card", "no-tooltip-preview", "block-link", props.note.getColorClass(), {
|
||||||
className={`note-book-card no-tooltip-preview block-link ${note.isArchived ? "archived" : ""}`}
|
"archived": props.note.isArchived
|
||||||
data-href={`#${notePath}`}
|
})}
|
||||||
data-note-id={note.noteId}
|
data-href={`#${notePath}`}
|
||||||
onClick={(e) => link.goToLink(e)}
|
data-note-id={props.note.noteId}
|
||||||
|
onClick={(e) => link.goToLink(e)}
|
||||||
>
|
>
|
||||||
<h5 className="note-book-header">
|
<h5 className={clsx("note-book-header")}>
|
||||||
<Icon className="note-icon" icon={note.getIcon()} />
|
<Icon className="note-icon" icon={props.note.getIcon()} />
|
||||||
<NoteLink className="note-book-title" notePath={notePath} noPreview showNotePath={parentNote.type === "search"} highlightedTokens={highlightedTokens} />
|
<NoteLink className="note-book-title"
|
||||||
<NoteAttributes note={note} />
|
notePath={notePath}
|
||||||
|
noPreview
|
||||||
|
showNotePath={props.parentNote.type === "search"}
|
||||||
|
highlightedTokens={props.highlightedTokens}
|
||||||
|
/>
|
||||||
|
{!props.note.isOptions() && <NoteMenuButton notePath={notePath} />}
|
||||||
|
|
||||||
</h5>
|
</h5>
|
||||||
<NoteContent
|
<NoteContent note={props.note}
|
||||||
note={note}
|
trim
|
||||||
trim
|
highlightedTokens={props.highlightedTokens}
|
||||||
highlightedTokens={highlightedTokens}
|
includeArchivedNotes={props.includeArchived}
|
||||||
includeArchivedNotes={includeArchived}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</CardFrame>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +214,17 @@ export function NoteContent({ note, trim, noChildrenList, highlightedTokens, inc
|
|||||||
const [ready, setReady] = useState(false);
|
const [ready, setReady] = useState(false);
|
||||||
const [noteType, setNoteType] = useState<string>("none");
|
const [noteType, setNoteType] = useState<string>("none");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const contentElement = contentRef.current;
|
||||||
|
if (!contentElement) return;
|
||||||
|
|
||||||
|
contentSizeObserver.observe(contentElement);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
contentSizeObserver.unobserve(contentElement);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
content_renderer.getRenderedContent(note, {
|
content_renderer.getRenderedContent(note, {
|
||||||
trim,
|
trim,
|
||||||
@ -252,6 +278,18 @@ function NoteChildren({ note, parentNote, highlightedTokens, currentLevel, expan
|
|||||||
/>);
|
/>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function NoteMenuButton(props: {notePath: string}) {
|
||||||
|
const openMenu = useCallback((e: TargetedMouseEvent<HTMLElement>) => {
|
||||||
|
linkContextMenuService.openContextMenu(props.notePath, e);
|
||||||
|
e.stopPropagation()
|
||||||
|
}, [props.notePath]);
|
||||||
|
|
||||||
|
return <ActionButton className="note-book-item-menu"
|
||||||
|
icon="bx bx-dots-vertical-rounded" text=""
|
||||||
|
onClick={openMenu}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
function getNotePath(parentNote: FNote, childNote: FNote) {
|
function getNotePath(parentNote: FNote, childNote: FNote) {
|
||||||
if (parentNote.type === "search") {
|
if (parentNote.type === "search") {
|
||||||
// for search note parent, we want to display a non-search path
|
// for search note parent, we want to display a non-search path
|
||||||
@ -275,7 +313,9 @@ function useExpansionDepth(note: FNote) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function openNoteMenu(notePath, e: TargetedMouseEvent<HTMLElement>) {
|
function onContentResized(entries: ResizeObserverEntry[], observer: ResizeObserver): void {
|
||||||
linkContextMenuService.openContextMenu(notePath, e);
|
for (const contentElement of entries) {
|
||||||
e.stopPropagation()
|
const isOverflowing = ((contentElement.target.scrollHeight > contentElement.target.clientHeight))
|
||||||
}
|
contentElement.target.classList.toggle("note-book-content-overflowing", isOverflowing);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
.table-view-container {
|
.table-view-container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
margin-inline-start: var(--content-margin-inline);
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-widget-content .table-view {
|
.search-result-widget-content .table-view {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { LOCALES } from "@triliumnext/commons";
|
|||||||
import { EventData } from "../../components/app_context.js";
|
import { EventData } from "../../components/app_context.js";
|
||||||
import { getEnabledExperimentalFeatureIds } from "../../services/experimental_features.js";
|
import { getEnabledExperimentalFeatureIds } from "../../services/experimental_features.js";
|
||||||
import options from "../../services/options.js";
|
import options from "../../services/options.js";
|
||||||
import utils, { isMobile } from "../../services/utils.js";
|
import utils, { isIOS, isMobile } from "../../services/utils.js";
|
||||||
import { readCssVar } from "../../utils/css-var.js";
|
import { readCssVar } from "../../utils/css-var.js";
|
||||||
import type BasicWidget from "../basic_widget.js";
|
import type BasicWidget from "../basic_widget.js";
|
||||||
import FlexContainer from "./flex_container.js";
|
import FlexContainer from "./flex_container.js";
|
||||||
@ -13,15 +13,20 @@ import FlexContainer from "./flex_container.js";
|
|||||||
*
|
*
|
||||||
* For convenience, the root container has a few class selectors that can be used to target some global state:
|
* For convenience, the root container has a few class selectors that can be used to target some global state:
|
||||||
*
|
*
|
||||||
|
* - `#root-container.light-theme`, indicates whether the current color scheme is light.
|
||||||
|
* - `#root-container.dark-theme`, indicates whether the current color scheme is dark.
|
||||||
* - `#root-container.virtual-keyboard-opened`, on mobile devices if the virtual keyboard is open.
|
* - `#root-container.virtual-keyboard-opened`, on mobile devices if the virtual keyboard is open.
|
||||||
* - `#root-container.horizontal-layout`, if the current layout is horizontal.
|
* - `#root-container.horizontal-layout`, if the current layout is horizontal.
|
||||||
* - `#root-container.vertical-layout`, if the current layout is horizontal.
|
* - `#root-container.vertical-layout`, if the current layout is horizontal.
|
||||||
*/
|
*/
|
||||||
export default class RootContainer extends FlexContainer<BasicWidget> {
|
export default class RootContainer extends FlexContainer<BasicWidget> {
|
||||||
|
|
||||||
|
private originalWindowHeight: number;
|
||||||
|
|
||||||
constructor(isHorizontalLayout: boolean) {
|
constructor(isHorizontalLayout: boolean) {
|
||||||
super(isHorizontalLayout ? "column" : "row");
|
super(isHorizontalLayout ? "column" : "row");
|
||||||
|
|
||||||
|
this.originalWindowHeight = window.innerHeight ?? 0;
|
||||||
this.id("root-widget");
|
this.id("root-widget");
|
||||||
this.css("height", "100dvh");
|
this.css("height", "100dvh");
|
||||||
}
|
}
|
||||||
@ -31,6 +36,8 @@ export default class RootContainer extends FlexContainer<BasicWidget> {
|
|||||||
window.visualViewport?.addEventListener("resize", () => this.#onMobileResize());
|
window.visualViewport?.addEventListener("resize", () => this.#onMobileResize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.#initTheme();
|
||||||
|
this.#setDeviceSpecificClasses();
|
||||||
this.#setMaxContentWidth();
|
this.#setMaxContentWidth();
|
||||||
this.#setMotion();
|
this.#setMotion();
|
||||||
this.#setShadows();
|
this.#setShadows();
|
||||||
@ -63,9 +70,24 @@ export default class RootContainer extends FlexContainer<BasicWidget> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#initTheme() {
|
||||||
|
const colorSchemeChangeObserver = matchMedia("(prefers-color-scheme: dark)")
|
||||||
|
colorSchemeChangeObserver.addEventListener("change", () => this.#updateColorScheme());
|
||||||
|
this.#updateColorScheme();
|
||||||
|
|
||||||
|
document.body.setAttribute("data-theme-id", options.get("theme"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#updateColorScheme() {
|
||||||
|
const colorScheme = readCssVar(document.body, "theme-style").asString();
|
||||||
|
|
||||||
|
document.body.classList.toggle("light-theme", colorScheme === "light");
|
||||||
|
document.body.classList.toggle("dark-theme", colorScheme === "dark");
|
||||||
|
}
|
||||||
|
|
||||||
#onMobileResize() {
|
#onMobileResize() {
|
||||||
const viewportHeight = window.visualViewport?.height ?? window.innerHeight;
|
const viewportHeight = window.visualViewport?.height ?? window.innerHeight;
|
||||||
const windowHeight = window.innerHeight;
|
const windowHeight = Math.max(window.innerHeight, this.originalWindowHeight); // inner height changes when keyboard is opened, we need to compare with the original height to detect it.
|
||||||
|
|
||||||
// If viewport is significantly smaller, keyboard is likely open
|
// If viewport is significantly smaller, keyboard is likely open
|
||||||
const isKeyboardOpened = windowHeight - viewportHeight > 150;
|
const isKeyboardOpened = windowHeight - viewportHeight > 150;
|
||||||
@ -117,6 +139,12 @@ export default class RootContainer extends FlexContainer<BasicWidget> {
|
|||||||
document.body.dir = correspondingLocale?.rtl ? "rtl" : "ltr";
|
document.body.dir = correspondingLocale?.rtl ? "rtl" : "ltr";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#setDeviceSpecificClasses() {
|
||||||
|
if (isIOS()) {
|
||||||
|
document.body.classList.add("ios");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#initPWATopbarColor() {
|
#initPWATopbarColor() {
|
||||||
if (!utils.isPWA()) return;
|
if (!utils.isPWA()) return;
|
||||||
const tracker = $("#background-color-tracker");
|
const tracker = $("#background-color-tracker");
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
.calendar-dropdown-widget .calendar-header {
|
.calendar-dropdown-widget .calendar-header {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 0 0.5rem 0.5rem 0.5rem;
|
padding: 0 0.5rem 1rem 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-dropdown-widget .calendar-header>div {
|
.calendar-dropdown-widget .calendar-header>div {
|
||||||
@ -65,8 +65,13 @@
|
|||||||
border: 0;
|
border: 0;
|
||||||
border-inline-start: unset;
|
border-inline-start: unset;
|
||||||
background-color: var(--menu-background-color);
|
background-color: var(--menu-background-color);
|
||||||
font-weight: bold;
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-dropdown-widget .calendar-header .dropdown-toggle {
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-dropdown-widget .calendar-header .dropdown-toggle::after {
|
.calendar-dropdown-widget .calendar-header .dropdown-toggle::after {
|
||||||
@ -82,18 +87,20 @@
|
|||||||
.calendar-dropdown-widget .calendar-week span {
|
.calendar-dropdown-widget .calendar-week span {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 0 0 12.5%;
|
flex: 0 0 12.5%;
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: bold;
|
|
||||||
max-width: 12.5%;
|
max-width: 12.5%;
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
padding-bottom: 5px;
|
padding-bottom: 5px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
font-size: .85em;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-dropdown-widget .calendar-body {
|
.calendar-dropdown-widget .calendar-body {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
min-height: 250px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calendar-dropdown-widget .calendar-week-number {
|
.calendar-dropdown-widget .calendar-week-number {
|
||||||
|
|||||||
@ -4,10 +4,11 @@ body.experimental-feature-new-layout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.title-actions {
|
.title-actions {
|
||||||
--title-actions-padding-start: 12px;
|
--title-actions-padding-start: var(--content-margin-inline);
|
||||||
--title-actions-padding-end: 8px;
|
--title-actions-padding-end: var(--content-margin-inline);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
max-width: var(--max-content-width);
|
max-width: var(--max-content-width);
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.5em;
|
gap: 0.5em;
|
||||||
|
|||||||
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 5px;
|
top: 5px;
|
||||||
padding: .25em 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
.collection-properties {
|
.collection-properties {
|
||||||
padding: 0.55em 12px;
|
padding: 0.55em var(--content-margin-inline);
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.25em;
|
gap: 0.25em;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
@ -26,6 +26,7 @@ export default function NoteTitleWidget(props: {className?: string}) {
|
|||||||
|| note === undefined
|
|| note === undefined
|
||||||
|| (note.isProtected && !protected_session_holder.isProtectedSessionAvailable())
|
|| (note.isProtected && !protected_session_holder.isProtectedSessionAvailable())
|
||||||
|| isLaunchBarConfig(note.noteId)
|
|| isLaunchBarConfig(note.noteId)
|
||||||
|
|| note.noteId.startsWith("_help_")
|
||||||
|| viewScope?.viewMode !== "default";
|
|| viewScope?.viewMode !== "default";
|
||||||
setReadOnly(isReadOnly);
|
setReadOnly(isReadOnly);
|
||||||
}, [ note, note?.noteId, note?.isProtected, viewScope?.viewMode ]);
|
}, [ note, note?.noteId, note?.isProtected, viewScope?.viewMode ]);
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
import FlexContainer from "./containers/flex_container.js";
|
|
||||||
import utils from "../services/utils.js";
|
|
||||||
import attributeService from "../services/attributes.js";
|
|
||||||
import type BasicWidget from "./basic_widget.js";
|
|
||||||
import type { EventData } from "../components/app_context.js";
|
import type { EventData } from "../components/app_context.js";
|
||||||
import type NoteContext from "../components/note_context.js";
|
import type NoteContext from "../components/note_context.js";
|
||||||
import type FNote from "../entities/fnote.js";
|
import type FNote from "../entities/fnote.js";
|
||||||
|
import attributeService from "../services/attributes.js";
|
||||||
import { getLocaleById } from "../services/i18n.js";
|
import { getLocaleById } from "../services/i18n.js";
|
||||||
|
import utils from "../services/utils.js";
|
||||||
|
import type BasicWidget from "./basic_widget.js";
|
||||||
|
import FlexContainer from "./containers/flex_container.js";
|
||||||
|
|
||||||
export default class NoteWrapperWidget extends FlexContainer<BasicWidget> {
|
export default class NoteWrapperWidget extends FlexContainer<BasicWidget> {
|
||||||
|
|
||||||
@ -43,11 +43,16 @@ export default class NoteWrapperWidget extends FlexContainer<BasicWidget> {
|
|||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
const isHiddenExt = this.isHiddenExt(); // preserve through class reset
|
const isHiddenExt = this.isHiddenExt(); // preserve through class reset
|
||||||
|
const isActive = this.$widget.hasClass("active");
|
||||||
|
|
||||||
this.$widget.removeClass();
|
this.$widget.removeClass();
|
||||||
|
|
||||||
this.toggleExt(!isHiddenExt);
|
this.toggleExt(!isHiddenExt);
|
||||||
|
|
||||||
|
if (isActive) {
|
||||||
|
this.$widget.addClass("active");
|
||||||
|
}
|
||||||
|
|
||||||
this.$widget.addClass("component note-split");
|
this.$widget.addClass("component note-split");
|
||||||
|
|
||||||
const note = this.noteContext?.note;
|
const note = this.noteContext?.note;
|
||||||
@ -92,6 +97,11 @@ export default class NoteWrapperWidget extends FlexContainer<BasicWidget> {
|
|||||||
#hasBackgroundEffects(note: FNote): boolean {
|
#hasBackgroundEffects(note: FNote): boolean {
|
||||||
const MIME_TYPES_WITH_BACKGROUND_EFFECTS = [
|
const MIME_TYPES_WITH_BACKGROUND_EFFECTS = [
|
||||||
"application/pdf"
|
"application/pdf"
|
||||||
|
];
|
||||||
|
|
||||||
|
const COLLECTIONS_WITH_BACKGROUND_EFFECTS = [
|
||||||
|
"grid",
|
||||||
|
"list"
|
||||||
]
|
]
|
||||||
|
|
||||||
if (note.isOptions()) {
|
if (note.isOptions()) {
|
||||||
@ -102,6 +112,10 @@ export default class NoteWrapperWidget extends FlexContainer<BasicWidget> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (note.type === "book" && COLLECTIONS_WITH_BACKGROUND_EFFECTS.includes(note.getLabelValue("viewType") ?? "none")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
:where(.tn-card) {
|
:where(.tn-card, .tn-card-frame) {
|
||||||
--card-border-radius: 8px;
|
--card-border-radius: 8px;
|
||||||
--card-padding-block: 8px;
|
--card-padding-block: 8px;
|
||||||
--card-padding-inline: 16px;
|
--card-padding-inline: 16px;
|
||||||
@ -6,6 +6,22 @@
|
|||||||
--card-nested-section-indent: 30px;
|
--card-nested-section-indent: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tn-card-frame,
|
||||||
|
.tn-card-body .tn-card-section {
|
||||||
|
padding: var(--card-padding-block) var(--card-padding-inline);
|
||||||
|
border: 1px solid var(--card-border-color, var(--main-border-color));
|
||||||
|
background: var(--card-background-color);
|
||||||
|
|
||||||
|
&.tn-card-highlight-on-hover:hover {
|
||||||
|
background-color: var(--card-background-hover-color);
|
||||||
|
transition: background-color .2s ease-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tn-card-frame {
|
||||||
|
border-radius: var(--card-border-radius);
|
||||||
|
}
|
||||||
|
|
||||||
.tn-card-heading {
|
.tn-card-heading {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
font-size: .75rem;
|
font-size: .75rem;
|
||||||
@ -20,10 +36,6 @@
|
|||||||
gap: var(--card-section-gap);
|
gap: var(--card-section-gap);
|
||||||
|
|
||||||
.tn-card-section {
|
.tn-card-section {
|
||||||
padding: var(--card-padding-block) var(--card-padding-inline);
|
|
||||||
border: 1px solid var(--card-border-color, var(--main-border-color));
|
|
||||||
background: var(--card-background-color);
|
|
||||||
|
|
||||||
&:first-of-type {
|
&:first-of-type {
|
||||||
border-top-left-radius: var(--card-border-radius);
|
border-top-left-radius: var(--card-border-radius);
|
||||||
border-top-right-radius: var(--card-border-radius);
|
border-top-right-radius: var(--card-border-radius);
|
||||||
@ -38,10 +50,5 @@
|
|||||||
padding-left: calc(var(--card-padding-inline) + var(--card-nested-section-indent) * var(--tn-card-section-nesting-level));
|
padding-left: calc(var(--card-padding-inline) + var(--card-nested-section-indent) * var(--tn-card-section-nesting-level));
|
||||||
background-color: color-mix(in srgb, var(--card-background-color) calc(100% / (var(--tn-card-section-nesting-level) + 1)) , transparent);
|
background-color: color-mix(in srgb, var(--card-background-color) calc(100% / (var(--tn-card-section-nesting-level) + 1)) , transparent);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.tn-card-section-highlight-on-hover:hover {
|
|
||||||
background-color: var(--card-background-hover-color);
|
|
||||||
transition: background-color .2s ease-out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,9 +1,29 @@
|
|||||||
import "./Card.css";
|
import "./Card.css";
|
||||||
import { ComponentChildren, createContext } from "preact";
|
import { ComponentChildren, createContext } from "preact";
|
||||||
import { JSX } from "preact";
|
import { JSX, HTMLAttributes } from "preact";
|
||||||
import { useContext } from "preact/hooks";
|
import { useContext } from "preact/hooks";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
// #region Card Frame
|
||||||
|
|
||||||
|
export interface CardFrameProps extends HTMLAttributes<HTMLDivElement> {
|
||||||
|
className?: string;
|
||||||
|
highlightOnHover?: boolean;
|
||||||
|
children: ComponentChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CardFrame({className, highlightOnHover, children, ...rest}: CardFrameProps) {
|
||||||
|
return <div {...rest}
|
||||||
|
className={clsx("tn-card-frame", className, {
|
||||||
|
"tn-card-highlight-on-hover": highlightOnHover
|
||||||
|
})}>
|
||||||
|
|
||||||
|
{children}
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #endregion
|
||||||
|
|
||||||
// #region Card
|
// #region Card
|
||||||
|
|
||||||
export interface CardProps {
|
export interface CardProps {
|
||||||
@ -45,7 +65,7 @@ export function CardSection(props: {children: ComponentChildren} & CardSectionPr
|
|||||||
return <>
|
return <>
|
||||||
<section className={clsx("tn-card-section", props.className, {
|
<section className={clsx("tn-card-section", props.className, {
|
||||||
"tn-card-section-nested": nestingLevel > 0,
|
"tn-card-section-nested": nestingLevel > 0,
|
||||||
"tn-card-section-highlight-on-hover": props.highlightOnHover || props.onAction
|
"tn-card-highlight-on-hover": props.highlightOnHover || props.onAction
|
||||||
})}
|
})}
|
||||||
style={{"--tn-card-section-nesting-level": (nestingLevel) ? nestingLevel : null}}
|
style={{"--tn-card-section-nesting-level": (nestingLevel) ? nestingLevel : null}}
|
||||||
onClick={props.onAction}>
|
onClick={props.onAction}>
|
||||||
|
|||||||
@ -1383,3 +1383,28 @@ export function useGetContextDataFrom<K extends keyof NoteContextDataMap>(
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function useColorScheme() {
|
||||||
|
const themeStyle = getThemeStyle();
|
||||||
|
const defaultValue = themeStyle === "auto" ? (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) : themeStyle === "dark";
|
||||||
|
const [ prefersDark, setPrefersDark ] = useState(defaultValue);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (themeStyle !== "auto") return;
|
||||||
|
const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
|
||||||
|
const listener = (e: MediaQueryListEvent) => setPrefersDark(e.matches);
|
||||||
|
|
||||||
|
mediaQueryList.addEventListener("change", listener);
|
||||||
|
return () => mediaQueryList.removeEventListener("change", listener);
|
||||||
|
}, [ themeStyle ]);
|
||||||
|
|
||||||
|
return prefersDark ? "dark" : "light";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getThemeStyle() {
|
||||||
|
const style = window.getComputedStyle(document.body);
|
||||||
|
const themeStyle = style.getPropertyValue("--theme-style");
|
||||||
|
if (style.getPropertyValue("--theme-style-auto") !== "true" && (themeStyle === "light" || themeStyle === "dark")) {
|
||||||
|
return themeStyle as "light" | "dark";
|
||||||
|
}
|
||||||
|
return "auto";
|
||||||
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ export default function ScrollPadding() {
|
|||||||
const [height, setHeight] = useState<number>(10);
|
const [height, setHeight] = useState<number>(10);
|
||||||
const isEnabled = ["text", "code"].includes(note?.type ?? "")
|
const isEnabled = ["text", "code"].includes(note?.type ?? "")
|
||||||
&& viewScope?.viewMode === "default"
|
&& viewScope?.viewMode === "default"
|
||||||
|
&& note?.isContentAvailable()
|
||||||
&& !note?.isTriliumSqlite();
|
&& !note?.isTriliumSqlite();
|
||||||
|
|
||||||
const refreshHeight = () => {
|
const refreshHeight = () => {
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
contain: none !important;
|
contain: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-widget .note-list {
|
.search-result-widget .note-list-wrapper {
|
||||||
padding: 10px;
|
margin-inline: var(--content-margin-inline);
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-split.type-search .scrolling-container {
|
.note-split.type-search .scrolling-container {
|
||||||
|
|||||||
@ -4,4 +4,5 @@
|
|||||||
|
|
||||||
.note-detail.full-height .note-detail-content-widget-content {
|
.note-detail.full-height .note-detail-content-widget-content {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,12 +6,12 @@ import "./MindMap.css";
|
|||||||
import nodeMenu from "@mind-elixir/node-menu";
|
import nodeMenu from "@mind-elixir/node-menu";
|
||||||
import { DISPLAYABLE_LOCALE_IDS } from "@triliumnext/commons";
|
import { DISPLAYABLE_LOCALE_IDS } from "@triliumnext/commons";
|
||||||
import { snapdom } from "@zumer/snapdom";
|
import { snapdom } from "@zumer/snapdom";
|
||||||
import { default as VanillaMindElixir,MindElixirData, MindElixirInstance, Operation, Options } from "mind-elixir";
|
import { default as VanillaMindElixir,MindElixirData, MindElixirInstance, Operation, Options, THEME as LIGHT_THEME, DARK_THEME } from "mind-elixir";
|
||||||
import { HTMLAttributes, RefObject } from "preact";
|
import { HTMLAttributes, RefObject } from "preact";
|
||||||
import { useCallback, useEffect, useRef } from "preact/hooks";
|
import { useCallback, useEffect, useRef } from "preact/hooks";
|
||||||
|
|
||||||
import utils from "../../services/utils";
|
import utils from "../../services/utils";
|
||||||
import { useEditorSpacedUpdate, useNoteLabelBoolean, useSyncedRef, useTriliumEvent, useTriliumEvents, useTriliumOption } from "../react/hooks";
|
import { useColorScheme, useEditorSpacedUpdate, useNoteLabelBoolean, useSyncedRef, useTriliumEvent, useTriliumEvents, useTriliumOption } from "../react/hooks";
|
||||||
import { refToJQuerySelector } from "../react/react_utils";
|
import { refToJQuerySelector } from "../react/react_utils";
|
||||||
import { TypeWidgetProps } from "./type_widget";
|
import { TypeWidgetProps } from "./type_widget";
|
||||||
|
|
||||||
@ -85,9 +85,11 @@ export default function MindMap({ note, ntxId, noteContext }: TypeWidgetProps) {
|
|||||||
},
|
},
|
||||||
onContentChange: (content) => {
|
onContentChange: (content) => {
|
||||||
let newContent: MindElixirData;
|
let newContent: MindElixirData;
|
||||||
|
|
||||||
if (content) {
|
if (content) {
|
||||||
try {
|
try {
|
||||||
newContent = JSON.parse(content) as MindElixirData;
|
newContent = JSON.parse(content) as MindElixirData;
|
||||||
|
delete newContent.theme; // The theme is managed internally by the widget, so we remove it from the loaded content to avoid inconsistencies.
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(e);
|
console.warn(e);
|
||||||
console.debug("Wrong JSON content: ", content);
|
console.debug("Wrong JSON content: ", content);
|
||||||
@ -151,6 +153,7 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
|
|||||||
const containerRef = useSyncedRef<HTMLDivElement>(externalContainerRef, null);
|
const containerRef = useSyncedRef<HTMLDivElement>(externalContainerRef, null);
|
||||||
const apiRef = useRef<MindElixirInstance>(null);
|
const apiRef = useRef<MindElixirInstance>(null);
|
||||||
const [ locale ] = useTriliumOption("locale");
|
const [ locale ] = useTriliumOption("locale");
|
||||||
|
const colorScheme = useColorScheme();
|
||||||
|
|
||||||
function reinitialize() {
|
function reinitialize() {
|
||||||
if (!containerRef.current) return;
|
if (!containerRef.current) return;
|
||||||
@ -158,7 +161,8 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
|
|||||||
const mind = new VanillaMindElixir({
|
const mind = new VanillaMindElixir({
|
||||||
el: containerRef.current,
|
el: containerRef.current,
|
||||||
locale: LOCALE_MAPPINGS[locale as DISPLAYABLE_LOCALE_IDS] ?? undefined,
|
locale: LOCALE_MAPPINGS[locale as DISPLAYABLE_LOCALE_IDS] ?? undefined,
|
||||||
editable
|
editable,
|
||||||
|
theme: LIGHT_THEME
|
||||||
});
|
});
|
||||||
|
|
||||||
if (editable) {
|
if (editable) {
|
||||||
@ -179,6 +183,14 @@ function MindElixir({ containerRef: externalContainerRef, containerProps, apiRef
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// React to theme changes.
|
||||||
|
useEffect(() => {
|
||||||
|
if (!apiRef.current) return;
|
||||||
|
const newTheme = colorScheme === "dark" ? DARK_THEME : LIGHT_THEME;
|
||||||
|
if (apiRef.current.theme === newTheme) return; // Avoid unnecessary theme changes, which can be expensive to render.
|
||||||
|
apiRef.current.changeTheme(newTheme);
|
||||||
|
}, [ colorScheme ]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const data = apiRef.current?.getData();
|
const data = apiRef.current?.getData();
|
||||||
reinitialize();
|
reinitialize();
|
||||||
|
|||||||
@ -3,4 +3,8 @@
|
|||||||
margin-inline: 40px;
|
margin-inline: 40px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
|
label {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import { Excalidraw } from "@excalidraw/excalidraw";
|
import { Excalidraw } from "@excalidraw/excalidraw";
|
||||||
import { TypeWidgetProps } from "../type_widget";
|
import { TypeWidgetProps } from "../type_widget";
|
||||||
import "@excalidraw/excalidraw/index.css";
|
import "@excalidraw/excalidraw/index.css";
|
||||||
import { useNoteLabelBoolean, useTriliumOption } from "../../react/hooks";
|
import { useColorScheme, useNoteLabelBoolean, useTriliumOption } from "../../react/hooks";
|
||||||
import { useCallback, useMemo, useRef } from "preact/hooks";
|
import { useCallback, useMemo, useRef } from "preact/hooks";
|
||||||
import { type ExcalidrawImperativeAPI, type AppState } from "@excalidraw/excalidraw/types";
|
import { type ExcalidrawImperativeAPI, type AppState } from "@excalidraw/excalidraw/types";
|
||||||
import options from "../../../services/options";
|
import options from "../../../services/options";
|
||||||
@ -19,12 +19,9 @@ window.EXCALIDRAW_ASSET_PATH = `${window.location.pathname}/node_modules/@excali
|
|||||||
export default function Canvas({ note, noteContext }: TypeWidgetProps) {
|
export default function Canvas({ note, noteContext }: TypeWidgetProps) {
|
||||||
const apiRef = useRef<ExcalidrawImperativeAPI>(null);
|
const apiRef = useRef<ExcalidrawImperativeAPI>(null);
|
||||||
const [ isReadOnly ] = useNoteLabelBoolean(note, "readOnly");
|
const [ isReadOnly ] = useNoteLabelBoolean(note, "readOnly");
|
||||||
const themeStyle = useMemo(() => {
|
const colorScheme = useColorScheme();
|
||||||
const documentStyle = window.getComputedStyle(document.documentElement);
|
|
||||||
return documentStyle.getPropertyValue("--theme-style")?.trim() as AppState["theme"];
|
|
||||||
}, []);
|
|
||||||
const [ locale ] = useTriliumOption("locale");
|
const [ locale ] = useTriliumOption("locale");
|
||||||
const persistence = useCanvasPersistence(note, noteContext, apiRef, themeStyle, isReadOnly);
|
const persistence = useCanvasPersistence(note, noteContext, apiRef, colorScheme, isReadOnly);
|
||||||
|
|
||||||
/** Use excalidraw's native zoom instead of the global zoom. */
|
/** Use excalidraw's native zoom instead of the global zoom. */
|
||||||
const onWheel = useCallback((e: MouseEvent) => {
|
const onWheel = useCallback((e: MouseEvent) => {
|
||||||
@ -54,7 +51,7 @@ export default function Canvas({ note, noteContext }: TypeWidgetProps) {
|
|||||||
<div className="excalidraw-wrapper">
|
<div className="excalidraw-wrapper">
|
||||||
<Excalidraw
|
<Excalidraw
|
||||||
excalidrawAPI={api => apiRef.current = api}
|
excalidrawAPI={api => apiRef.current = api}
|
||||||
theme={themeStyle}
|
theme={colorScheme}
|
||||||
viewModeEnabled={isReadOnly || options.is("databaseReadonly")}
|
viewModeEnabled={isReadOnly || options.is("databaseReadonly")}
|
||||||
zenModeEnabled={false}
|
zenModeEnabled={false}
|
||||||
isCollaborating={false}
|
isCollaborating={false}
|
||||||
|
|||||||
@ -1,13 +1,36 @@
|
|||||||
import type { HTMLAttributes, RefObject } from "preact";
|
import type { HTMLAttributes, RefObject } from "preact";
|
||||||
import { useCallback, useEffect, useRef } from "preact/hooks";
|
import { useCallback, useEffect, useRef } from "preact/hooks";
|
||||||
|
import Inter from "./../../../fonts/Inter/Inter-VariableFont_opsz,wght.ttf";
|
||||||
import { useSyncedRef, useTriliumOption, useTriliumOptionBool } from "../../react/hooks";
|
import { useSyncedRef, useTriliumOption, useTriliumOptionBool } from "../../react/hooks";
|
||||||
|
|
||||||
|
interface FontDefinition {
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FONTS: FontDefinition[] = [
|
||||||
|
{name: "Inter", url: Inter},
|
||||||
|
]
|
||||||
|
|
||||||
const VARIABLE_WHITELIST = new Set([
|
const VARIABLE_WHITELIST = new Set([
|
||||||
"root-background",
|
"root-background",
|
||||||
"main-background-color",
|
"main-background-color",
|
||||||
"main-border-color",
|
"main-border-color",
|
||||||
"main-text-color"
|
"main-text-color",
|
||||||
|
"theme-style",
|
||||||
|
"menu-background-color",
|
||||||
|
"dropdown-backdrop-filter",
|
||||||
|
"dropdown-border-radius",
|
||||||
|
"dropdown-border-color",
|
||||||
|
"dropdown-shadow-opacity",
|
||||||
|
"menu-padding-size",
|
||||||
|
"menu-text-color",
|
||||||
|
"hover-item-background-color",
|
||||||
|
"hover-item-text-color",
|
||||||
|
"menu-item-icon-color",
|
||||||
|
"input-focus-outline-color",
|
||||||
|
"input-background-color",
|
||||||
|
"input-text-color"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
interface PdfViewerProps extends Pick<HTMLAttributes<HTMLIFrameElement>, "tabIndex"> {
|
interface PdfViewerProps extends Pick<HTMLAttributes<HTMLIFrameElement>, "tabIndex"> {
|
||||||
@ -55,8 +78,12 @@ function useStyleInjection(iframeRef: RefObject<HTMLIFrameElement>) {
|
|||||||
style.id = 'client-root-vars';
|
style.id = 'client-root-vars';
|
||||||
style.textContent = cssVarsToString(getRootCssVariables());
|
style.textContent = cssVarsToString(getRootCssVariables());
|
||||||
styleRef.current = style;
|
styleRef.current = style;
|
||||||
|
|
||||||
doc.head.appendChild(style);
|
doc.head.appendChild(style);
|
||||||
|
|
||||||
|
const fontStyles = doc.createElement("style");
|
||||||
|
fontStyles.textContent = FONTS.map(injectFont).join("\n");
|
||||||
|
doc.head.appendChild(fontStyles);
|
||||||
|
|
||||||
}, [ iframeRef ]);
|
}, [ iframeRef ]);
|
||||||
|
|
||||||
// React to changes.
|
// React to changes.
|
||||||
@ -92,3 +119,12 @@ function cssVarsToString(vars: Record<string, string>) {
|
|||||||
.map(([k, v]) => ` ${k}: ${v};`)
|
.map(([k, v]) => ` ${k}: ${v};`)
|
||||||
.join('\n')}\n}`;
|
.join('\n')}\n}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function injectFont(font: FontDefinition) {
|
||||||
|
return `
|
||||||
|
@font-face {
|
||||||
|
font-family: '${font.name}';
|
||||||
|
src: url('${font.url}');
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
@ -19,4 +19,12 @@
|
|||||||
.tn-link {
|
.tn-link {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-group {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,22 +2,14 @@ body.mobile {
|
|||||||
.classic-toolbar-outer-container {
|
.classic-toolbar-outer-container {
|
||||||
contain: none !important;
|
contain: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.classic-toolbar-outer-container.visible {
|
.classic-toolbar-outer-container.visible {
|
||||||
height: 38px;
|
height: 38px;
|
||||||
background-color: var(--main-background-color);
|
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#root-widget.virtual-keyboard-opened .classic-toolbar-outer-container.ios {
|
|
||||||
position: absolute;
|
|
||||||
inset-inline-start: 0;
|
|
||||||
inset-inline-end: 0;
|
|
||||||
bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.classic-toolbar-widget {
|
.classic-toolbar-widget {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@ -28,27 +20,27 @@ body.mobile {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
|
touch-action: pan-x;
|
||||||
scrollbar-width: 0 !important;
|
scrollbar-width: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.classic-toolbar-widget::-webkit-scrollbar:horizontal {
|
.classic-toolbar-widget::-webkit-scrollbar:horizontal {
|
||||||
height: 0 !important;
|
height: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.classic-toolbar-widget.dropdown-active {
|
.classic-toolbar-widget.dropdown-active {
|
||||||
height: 50vh;
|
height: 50vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.classic-toolbar-widget .ck.ck-toolbar {
|
.classic-toolbar-widget .ck.ck-toolbar {
|
||||||
--ck-color-toolbar-background: transparent;
|
--ck-color-toolbar-background: var(--main-background-color);
|
||||||
--ck-color-button-default-background: transparent;
|
--ck-color-button-default-background: transparent;
|
||||||
--ck-color-button-default-disabled-background: transparent;
|
--ck-color-button-default-disabled-background: transparent;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background-color: transparent;
|
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.classic-toolbar-widget .ck.ck-button.ck-disabled {
|
.classic-toolbar-widget .ck.ck-button.ck-disabled {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -66,11 +66,22 @@ export default function MobileEditorToolbar({ inPopupEditor }: MobileEditorToolb
|
|||||||
}
|
}
|
||||||
|
|
||||||
function usePositioningOniOS(enabled: boolean, wrapperRef: MutableRef<HTMLDivElement | null>) {
|
function usePositioningOniOS(enabled: boolean, wrapperRef: MutableRef<HTMLDivElement | null>) {
|
||||||
|
// Capture the baseline offset (Safari nav bar height) before the keyboard opens.
|
||||||
|
const baselineOffset = useRef(window.innerHeight - (window.visualViewport?.height ?? window.innerHeight));
|
||||||
|
|
||||||
const adjustPosition = useCallback(() => {
|
const adjustPosition = useCallback(() => {
|
||||||
if (!wrapperRef.current) return;
|
if (!wrapperRef.current) return;
|
||||||
const bottom = window.innerHeight - (window.visualViewport?.height || 0);
|
const viewport = window.visualViewport;
|
||||||
wrapperRef.current.style.bottom = `${bottom}px`;
|
if (!viewport) return;
|
||||||
}, []);
|
// Subtract the baseline so only the keyboard's contribution remains.
|
||||||
|
const bottom = window.innerHeight - viewport.height - viewport.offsetTop;
|
||||||
|
if (bottom - baselineOffset.current <= 0) {
|
||||||
|
// Keyboard is hidden — clear the inline style so CSS controls positioning.
|
||||||
|
wrapperRef.current.style.removeProperty("bottom");
|
||||||
|
} else {
|
||||||
|
wrapperRef.current.style.bottom = `${bottom}px`;
|
||||||
|
}
|
||||||
|
}, [ wrapperRef ]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isIOS() || !enabled) return;
|
if (!isIOS() || !enabled) return;
|
||||||
@ -82,7 +93,7 @@ function usePositioningOniOS(enabled: boolean, wrapperRef: MutableRef<HTMLDivEle
|
|||||||
window.visualViewport?.removeEventListener("resize", adjustPosition);
|
window.visualViewport?.removeEventListener("resize", adjustPosition);
|
||||||
window.removeEventListener("scroll", adjustPosition);
|
window.removeEventListener("scroll", adjustPosition);
|
||||||
};
|
};
|
||||||
}, [ enabled ]);
|
}, [ enabled, adjustPosition ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -3,5 +3,5 @@
|
|||||||
DIR=`dirname "$0"`
|
DIR=`dirname "$0"`
|
||||||
export NODE_TLS_REJECT_UNAUTHORIZED=0
|
export NODE_TLS_REJECT_UNAUTHORIZED=0
|
||||||
|
|
||||||
"$DIR/trilium"
|
exec "$DIR/trilium"
|
||||||
|
|
||||||
|
|||||||
@ -3,5 +3,5 @@
|
|||||||
DIR=`dirname "$0"`
|
DIR=`dirname "$0"`
|
||||||
export TRILIUM_DATA_DIR="$DIR/trilium-data"
|
export TRILIUM_DATA_DIR="$DIR/trilium-data"
|
||||||
|
|
||||||
"$DIR/trilium"
|
exec "$DIR/trilium"
|
||||||
|
|
||||||
|
|||||||
@ -3,5 +3,5 @@
|
|||||||
DIR=`dirname "$0"`
|
DIR=`dirname "$0"`
|
||||||
export TRILIUM_SAFE_MODE=1
|
export TRILIUM_SAFE_MODE=1
|
||||||
|
|
||||||
"$DIR/trilium" --disable-gpu
|
exec "$DIR/trilium" --disable-gpu
|
||||||
|
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
"@triliumnext/commons": "workspace:*",
|
"@triliumnext/commons": "workspace:*",
|
||||||
"@triliumnext/server": "workspace:*",
|
"@triliumnext/server": "workspace:*",
|
||||||
"copy-webpack-plugin": "13.0.1",
|
"copy-webpack-plugin": "13.0.1",
|
||||||
"electron": "40.6.0",
|
"electron": "40.6.1",
|
||||||
"@electron-forge/cli": "7.11.1",
|
"@electron-forge/cli": "7.11.1",
|
||||||
"@electron-forge/maker-deb": "7.11.1",
|
"@electron-forge/maker-deb": "7.11.1",
|
||||||
"@electron-forge/maker-dmg": "7.11.1",
|
"@electron-forge/maker-dmg": "7.11.1",
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
"@triliumnext/desktop": "workspace:*",
|
"@triliumnext/desktop": "workspace:*",
|
||||||
"@types/fs-extra": "11.0.4",
|
"@types/fs-extra": "11.0.4",
|
||||||
"copy-webpack-plugin": "13.0.1",
|
"copy-webpack-plugin": "13.0.1",
|
||||||
"electron": "40.6.0",
|
"electron": "40.6.1",
|
||||||
"fs-extra": "11.3.3"
|
"fs-extra": "11.3.3"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:24.13.1-bullseye-slim AS builder
|
FROM node:24.14.0-bullseye-slim AS builder
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
# Install native dependencies since we might be building cross-platform.
|
# Install native dependencies since we might be building cross-platform.
|
||||||
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
|||||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||||
|
|
||||||
FROM node:24.13.1-bullseye-slim
|
FROM node:24.14.0-bullseye-slim
|
||||||
# Install only runtime dependencies
|
# Install only runtime dependencies
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends \
|
apt-get install -y --no-install-recommends \
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:24.13.1-alpine AS builder
|
FROM node:24.14.0-alpine AS builder
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
# Install native dependencies since we might be building cross-platform.
|
# Install native dependencies since we might be building cross-platform.
|
||||||
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
|||||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||||
|
|
||||||
FROM node:24.13.1-alpine
|
FROM node:24.14.0-alpine
|
||||||
# Install runtime dependencies
|
# Install runtime dependencies
|
||||||
RUN apk add --no-cache su-exec shadow
|
RUN apk add --no-cache su-exec shadow
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:24.13.1-alpine AS builder
|
FROM node:24.14.0-alpine AS builder
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
# Install native dependencies since we might be building cross-platform.
|
# Install native dependencies since we might be building cross-platform.
|
||||||
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
|||||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||||
|
|
||||||
FROM node:24.13.1-alpine
|
FROM node:24.14.0-alpine
|
||||||
# Create a non-root user with configurable UID/GID
|
# Create a non-root user with configurable UID/GID
|
||||||
ARG USER=trilium
|
ARG USER=trilium
|
||||||
ARG UID=1001
|
ARG UID=1001
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM node:24.13.1-bullseye-slim AS builder
|
FROM node:24.14.0-bullseye-slim AS builder
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
# Install native dependencies since we might be building cross-platform.
|
# Install native dependencies since we might be building cross-platform.
|
||||||
@ -7,7 +7,7 @@ COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
|
|||||||
# We have to use --no-frozen-lockfile due to CKEditor patches
|
# We have to use --no-frozen-lockfile due to CKEditor patches
|
||||||
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
|
||||||
|
|
||||||
FROM node:24.13.1-bullseye-slim
|
FROM node:24.14.0-bullseye-slim
|
||||||
# Create a non-root user with configurable UID/GID
|
# Create a non-root user with configurable UID/GID
|
||||||
ARG USER=trilium
|
ARG USER=trilium
|
||||||
ARG UID=1001
|
ARG UID=1001
|
||||||
|
|||||||
@ -62,7 +62,7 @@
|
|||||||
"@types/serve-favicon": "2.5.7",
|
"@types/serve-favicon": "2.5.7",
|
||||||
"@types/serve-static": "2.2.0",
|
"@types/serve-static": "2.2.0",
|
||||||
"@types/stream-throttle": "0.1.4",
|
"@types/stream-throttle": "0.1.4",
|
||||||
"@types/supertest": "6.0.3",
|
"@types/supertest": "7.2.0",
|
||||||
"@types/tmp": "0.2.6",
|
"@types/tmp": "0.2.6",
|
||||||
"@types/turndown": "5.0.6",
|
"@types/turndown": "5.0.6",
|
||||||
"@types/ws": "8.18.1",
|
"@types/ws": "8.18.1",
|
||||||
@ -82,7 +82,7 @@
|
|||||||
"debounce": "3.0.0",
|
"debounce": "3.0.0",
|
||||||
"debug": "4.4.3",
|
"debug": "4.4.3",
|
||||||
"ejs": "4.0.1",
|
"ejs": "4.0.1",
|
||||||
"electron": "40.6.0",
|
"electron": "40.6.1",
|
||||||
"electron-debug": "4.1.0",
|
"electron-debug": "4.1.0",
|
||||||
"electron-window-state": "5.0.3",
|
"electron-window-state": "5.0.3",
|
||||||
"escape-html": "1.0.3",
|
"escape-html": "1.0.3",
|
||||||
|
|||||||
@ -43,7 +43,7 @@ rm -rf $BUILD_DIR/node/lib/node_modules/{npm,corepack} \
|
|||||||
$BUILD_DIR/node_modules/electron* \
|
$BUILD_DIR/node_modules/electron* \
|
||||||
$BUILD_DIR/electron*.{js,map}
|
$BUILD_DIR/electron*.{js,map}
|
||||||
|
|
||||||
printf "#!/bin/sh\n./node/bin/node main.cjs\n" > $BUILD_DIR/trilium.sh
|
printf "#!/bin/sh\nexec ./node/bin/node main.cjs\n" > $BUILD_DIR/trilium.sh
|
||||||
chmod 755 $BUILD_DIR/trilium.sh
|
chmod 755 $BUILD_DIR/trilium.sh
|
||||||
|
|
||||||
VERSION=`jq -r ".version" package.json`
|
VERSION=`jq -r ".version" package.json`
|
||||||
|
|||||||
@ -88,7 +88,7 @@ export default async function buildApp() {
|
|||||||
|
|
||||||
const sessionParser = (await import("./routes/session_parser.js")).default;
|
const sessionParser = (await import("./routes/session_parser.js")).default;
|
||||||
app.use(sessionParser);
|
app.use(sessionParser);
|
||||||
app.use(favicon(path.join(assetsDir, "icon.ico")));
|
app.use(favicon(path.join(assetsDir, isDev ? "icon-dev.ico" : "icon.ico")));
|
||||||
|
|
||||||
if (openID.isOpenIDEnabled())
|
if (openID.isOpenIDEnabled())
|
||||||
app.use(auth(openID.generateOAuthConfig()));
|
app.use(auth(openID.generateOAuthConfig()));
|
||||||
|
|||||||
@ -179,10 +179,10 @@ describe("Markdown export", () => {
|
|||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> This is a very important information.
|
> This is a very important information.
|
||||||
>${space}
|
>${space}
|
||||||
> | | |
|
> | | |
|
||||||
> | --- | --- |
|
> | --- | --- |
|
||||||
> | 1 | 2 |
|
> | 1 | 2 |
|
||||||
> | 3 | 4 |
|
> | 3 | 4 |
|
||||||
|
|
||||||
> [!CAUTION]
|
> [!CAUTION]
|
||||||
> This is a caution.
|
> This is a caution.
|
||||||
@ -374,10 +374,10 @@ describe("Markdown export", () => {
|
|||||||
</figure>
|
</figure>
|
||||||
`;
|
`;
|
||||||
const expected = trimIndentation`\
|
const expected = trimIndentation`\
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Hi | there |
|
| Hi | there |
|
||||||
| Hi | there |`;
|
| Hi | there |`;
|
||||||
expect(markdownExportService.toMarkdown(html)).toBe(expected);
|
expect(markdownExportService.toMarkdown(html)).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -192,5 +192,16 @@ describe("Hidden Subtree", () => {
|
|||||||
llmNote = becca.getNote(noteId);
|
llmNote = becca.getNote(noteId);
|
||||||
expect(llmNote).toBeFalsy();
|
expect(llmNote).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("fixes attribute of wrong type", () => {
|
||||||
|
const template = becca.getNoteOrThrow("_template_table");
|
||||||
|
cls.init(() => {
|
||||||
|
template.setAttribute("relation", "template", "root");
|
||||||
|
hiddenSubtreeService.checkHiddenSubtree();
|
||||||
|
});
|
||||||
|
const attr = template.getAttributes().find(a => a.name === "template");
|
||||||
|
expect(attr).toBeDefined();
|
||||||
|
expect(attr?.type).toBe("label");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -467,8 +467,10 @@ function checkHiddenSubtreeRecursively(parentNoteId: string, item: HiddenSubtree
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure value is consistent.
|
// Ensure value is consistent.
|
||||||
if (attribute.value !== attrDef.value) {
|
if (attribute.value !== attrDef.value || attribute.type !== attrDef.type) {
|
||||||
note.setAttributeValueById(attribute.attributeId, attrDef.value);
|
attribute.type = attrDef.type;
|
||||||
|
attribute.value = attrDef.value ?? "";
|
||||||
|
attribute.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,10 +13,10 @@
|
|||||||
"postinstall": "wxt prepare"
|
"postinstall": "wxt prepare"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"packageManager": "pnpm@10.30.1",
|
"packageManager": "pnpm@10.30.2",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@wxt-dev/auto-icons": "1.1.0",
|
"@wxt-dev/auto-icons": "1.1.1",
|
||||||
"wxt": "0.20.17"
|
"wxt": "0.20.18"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cash-dom": "8.1.5"
|
"cash-dom": "8.1.5"
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@preact/preset-vite": "2.10.3",
|
"@preact/preset-vite": "2.10.3",
|
||||||
"eslint": "10.0.1",
|
"eslint": "10.0.2",
|
||||||
"eslint-config-preact": "2.0.0",
|
"eslint-config-preact": "2.0.0",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
"user-agent-data-types": "0.4.2",
|
"user-agent-data-types": "0.4.2",
|
||||||
|
|||||||
10
package.json
10
package.json
@ -50,7 +50,7 @@
|
|||||||
"@triliumnext/server": "workspace:*",
|
"@triliumnext/server": "workspace:*",
|
||||||
"@types/express": "5.0.6",
|
"@types/express": "5.0.6",
|
||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "4.0.9",
|
||||||
"@types/node": "24.10.13",
|
"@types/node": "24.10.14",
|
||||||
"@vitest/browser-webdriverio": "4.0.18",
|
"@vitest/browser-webdriverio": "4.0.18",
|
||||||
"@vitest/coverage-v8": "4.0.18",
|
"@vitest/coverage-v8": "4.0.18",
|
||||||
"@vitest/ui": "4.0.18",
|
"@vitest/ui": "4.0.18",
|
||||||
@ -58,10 +58,10 @@
|
|||||||
"cross-env": "10.1.0",
|
"cross-env": "10.1.0",
|
||||||
"dpdm": "4.0.1",
|
"dpdm": "4.0.1",
|
||||||
"esbuild": "0.27.3",
|
"esbuild": "0.27.3",
|
||||||
"eslint": "10.0.1",
|
"eslint": "10.0.2",
|
||||||
"eslint-config-preact": "2.0.0",
|
"eslint-config-preact": "2.0.0",
|
||||||
"eslint-config-prettier": "10.1.8",
|
"eslint-config-prettier": "10.1.8",
|
||||||
"eslint-plugin-playwright": "2.7.0",
|
"eslint-plugin-playwright": "2.7.1",
|
||||||
"eslint-plugin-simple-import-sort": "12.1.1",
|
"eslint-plugin-simple-import-sort": "12.1.1",
|
||||||
"happy-dom": "20.7.0",
|
"happy-dom": "20.7.0",
|
||||||
"http-server": "14.1.1",
|
"http-server": "14.1.1",
|
||||||
@ -73,7 +73,7 @@
|
|||||||
"tslib": "2.8.1",
|
"tslib": "2.8.1",
|
||||||
"tsx": "4.21.0",
|
"tsx": "4.21.0",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
"typescript-eslint": "8.56.0",
|
"typescript-eslint": "8.56.1",
|
||||||
"upath": "2.0.1",
|
"upath": "2.0.1",
|
||||||
"vite": "7.3.1",
|
"vite": "7.3.1",
|
||||||
"vite-plugin-dts": "4.5.4",
|
"vite-plugin-dts": "4.5.4",
|
||||||
@ -93,7 +93,7 @@
|
|||||||
"url": "https://github.com/TriliumNext/Trilium/issues"
|
"url": "https://github.com/TriliumNext/Trilium/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://triliumnotes.org",
|
"homepage": "https://triliumnotes.org",
|
||||||
"packageManager": "pnpm@10.30.1",
|
"packageManager": "pnpm@10.30.2",
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"patchedDependencies": {
|
"patchedDependencies": {
|
||||||
"@ckeditor/ckeditor5-mention": "patches/@ckeditor__ckeditor5-mention.patch",
|
"@ckeditor/ckeditor5-mention": "patches/@ckeditor__ckeditor5-mention.patch",
|
||||||
|
|||||||
@ -24,16 +24,16 @@
|
|||||||
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
||||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||||
"@typescript-eslint/parser": "8.56.0",
|
"@typescript-eslint/parser": "8.56.1",
|
||||||
"@vitest/browser": "4.0.18",
|
"@vitest/browser": "4.0.18",
|
||||||
"@vitest/coverage-istanbul": "4.0.18",
|
"@vitest/coverage-istanbul": "4.0.18",
|
||||||
"ckeditor5": "47.4.0",
|
"ckeditor5": "47.4.0",
|
||||||
"eslint": "10.0.1",
|
"eslint": "10.0.2",
|
||||||
"eslint-config-ckeditor5": ">=9.1.0",
|
"eslint-config-ckeditor5": ">=9.1.0",
|
||||||
"http-server": "14.1.1",
|
"http-server": "14.1.1",
|
||||||
"lint-staged": "16.2.7",
|
"lint-staged": "16.2.7",
|
||||||
"stylelint": "17.3.0",
|
"stylelint": "17.4.0",
|
||||||
"stylelint-config-ckeditor5": ">=9.1.0",
|
"stylelint-config-ckeditor5": ">=9.1.0",
|
||||||
"ts-node": "10.9.2",
|
"ts-node": "10.9.2",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
|
|||||||
@ -25,16 +25,16 @@
|
|||||||
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
||||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||||
"@typescript-eslint/parser": "8.56.0",
|
"@typescript-eslint/parser": "8.56.1",
|
||||||
"@vitest/browser": "4.0.18",
|
"@vitest/browser": "4.0.18",
|
||||||
"@vitest/coverage-istanbul": "4.0.18",
|
"@vitest/coverage-istanbul": "4.0.18",
|
||||||
"ckeditor5": "47.4.0",
|
"ckeditor5": "47.4.0",
|
||||||
"eslint": "10.0.1",
|
"eslint": "10.0.2",
|
||||||
"eslint-config-ckeditor5": ">=9.1.0",
|
"eslint-config-ckeditor5": ">=9.1.0",
|
||||||
"http-server": "14.1.1",
|
"http-server": "14.1.1",
|
||||||
"lint-staged": "16.2.7",
|
"lint-staged": "16.2.7",
|
||||||
"stylelint": "17.3.0",
|
"stylelint": "17.4.0",
|
||||||
"stylelint-config-ckeditor5": ">=9.1.0",
|
"stylelint-config-ckeditor5": ">=9.1.0",
|
||||||
"ts-node": "10.9.2",
|
"ts-node": "10.9.2",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
|
|||||||
@ -27,16 +27,16 @@
|
|||||||
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
||||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||||
"@typescript-eslint/parser": "8.56.0",
|
"@typescript-eslint/parser": "8.56.1",
|
||||||
"@vitest/browser": "4.0.18",
|
"@vitest/browser": "4.0.18",
|
||||||
"@vitest/coverage-istanbul": "4.0.18",
|
"@vitest/coverage-istanbul": "4.0.18",
|
||||||
"ckeditor5": "47.4.0",
|
"ckeditor5": "47.4.0",
|
||||||
"eslint": "10.0.1",
|
"eslint": "10.0.2",
|
||||||
"eslint-config-ckeditor5": ">=9.1.0",
|
"eslint-config-ckeditor5": ">=9.1.0",
|
||||||
"http-server": "14.1.1",
|
"http-server": "14.1.1",
|
||||||
"lint-staged": "16.2.7",
|
"lint-staged": "16.2.7",
|
||||||
"stylelint": "17.3.0",
|
"stylelint": "17.4.0",
|
||||||
"stylelint-config-ckeditor5": ">=9.1.0",
|
"stylelint-config-ckeditor5": ">=9.1.0",
|
||||||
"ts-node": "10.9.2",
|
"ts-node": "10.9.2",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
|
|||||||
@ -27,16 +27,16 @@
|
|||||||
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
||||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||||
"@typescript-eslint/parser": "8.56.0",
|
"@typescript-eslint/parser": "8.56.1",
|
||||||
"@vitest/browser": "4.0.18",
|
"@vitest/browser": "4.0.18",
|
||||||
"@vitest/coverage-istanbul": "4.0.18",
|
"@vitest/coverage-istanbul": "4.0.18",
|
||||||
"ckeditor5": "47.4.0",
|
"ckeditor5": "47.4.0",
|
||||||
"eslint": "10.0.1",
|
"eslint": "10.0.2",
|
||||||
"eslint-config-ckeditor5": ">=9.1.0",
|
"eslint-config-ckeditor5": ">=9.1.0",
|
||||||
"http-server": "14.1.1",
|
"http-server": "14.1.1",
|
||||||
"lint-staged": "16.2.7",
|
"lint-staged": "16.2.7",
|
||||||
"stylelint": "17.3.0",
|
"stylelint": "17.4.0",
|
||||||
"stylelint-config-ckeditor5": ">=9.1.0",
|
"stylelint-config-ckeditor5": ">=9.1.0",
|
||||||
"ts-node": "10.9.2",
|
"ts-node": "10.9.2",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
|
|||||||
@ -27,16 +27,16 @@
|
|||||||
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
"@ckeditor/ckeditor5-dev-build-tools": "54.3.3",
|
||||||
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
"@ckeditor/ckeditor5-inspector": ">=4.1.0",
|
||||||
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
"@ckeditor/ckeditor5-package-tools": "5.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||||
"@typescript-eslint/parser": "8.56.0",
|
"@typescript-eslint/parser": "8.56.1",
|
||||||
"@vitest/browser": "4.0.18",
|
"@vitest/browser": "4.0.18",
|
||||||
"@vitest/coverage-istanbul": "4.0.18",
|
"@vitest/coverage-istanbul": "4.0.18",
|
||||||
"ckeditor5": "47.4.0",
|
"ckeditor5": "47.4.0",
|
||||||
"eslint": "10.0.1",
|
"eslint": "10.0.2",
|
||||||
"eslint-config-ckeditor5": ">=9.1.0",
|
"eslint-config-ckeditor5": ">=9.1.0",
|
||||||
"http-server": "14.1.1",
|
"http-server": "14.1.1",
|
||||||
"lint-staged": "16.2.7",
|
"lint-staged": "16.2.7",
|
||||||
"stylelint": "17.3.0",
|
"stylelint": "17.4.0",
|
||||||
"stylelint-config-ckeditor5": ">=9.1.0",
|
"stylelint-config-ckeditor5": ">=9.1.0",
|
||||||
"ts-node": "10.9.2",
|
"ts-node": "10.9.2",
|
||||||
"typescript": "5.9.3",
|
"typescript": "5.9.3",
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
"ckeditor5-premium-features": "47.4.0"
|
"ckeditor5-premium-features": "47.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@smithy/middleware-retry": "4.4.33",
|
"@smithy/middleware-retry": "4.4.37",
|
||||||
"@types/jquery": "3.5.33"
|
"@types/jquery": "4.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,6 @@ export default class IndentBlockShortcutPlugin extends Plugin {
|
|||||||
command.execute();
|
command.execute();
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
priority: "highest",
|
|
||||||
context: node => isWidget( node ) || node.is( 'editableElement' ),
|
context: node => isWidget( node ) || node.is( 'editableElement' ),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,6 @@
|
|||||||
"codemirror-lang-elixir": "4.0.0",
|
"codemirror-lang-elixir": "4.0.0",
|
||||||
"codemirror-lang-hcl": "0.1.0",
|
"codemirror-lang-hcl": "0.1.0",
|
||||||
"codemirror-lang-mermaid": "0.5.0",
|
"codemirror-lang-mermaid": "0.5.0",
|
||||||
"eslint-linter-browserify": "10.0.1"
|
"eslint-linter-browserify": "10.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,31 +1,181 @@
|
|||||||
:root {
|
/* #region General */
|
||||||
color-scheme: var(--tn-theme-style);
|
|
||||||
|
|
||||||
--body-bg-color: transparent;
|
:root {
|
||||||
--toolbar-bg-color: transparent;
|
|
||||||
--main-color: var(--tn-main-text-color);
|
--main-color: var(--tn-main-text-color);
|
||||||
|
--body-bg-color: transparent;
|
||||||
--toolbar-border-color: var(--tn-main-border-color);
|
--toolbar-border-color: var(--tn-main-border-color);
|
||||||
|
--toolbar-icon-bg-color: var(--tn-main-text-color);
|
||||||
|
--toolbar-bg-color: transparent;
|
||||||
--toolbar-icon-opacity: 1;
|
--toolbar-icon-opacity: 1;
|
||||||
|
--toggled-btn-bg-color: var(--tn-hover-item-background-color);
|
||||||
|
--doorhanger-bg-color: var(--tn-menu-background-color);
|
||||||
|
--doorhanger-separator-color: var(--tn-main-border-color);
|
||||||
|
|
||||||
--page-margin: 12px auto;
|
--page-margin: 12px auto;
|
||||||
--spreadHorizontalWrapped-margin-LR: 4px;
|
--spreadHorizontalWrapped-margin-LR: 4px;
|
||||||
|
|
||||||
|
color-scheme: var(--tn-theme-style);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pdfViewer {
|
:root button,
|
||||||
.page,
|
:root dialog,
|
||||||
.page > .canvasWrapper,
|
:root #toolbarContainer,
|
||||||
.page > .canvasWrapper > canvas {
|
:root .toolbarButton,
|
||||||
border-radius: 6px;
|
:root #scaleSelect,
|
||||||
}
|
:root .toolbarButtonWithContainer .editorParamsToolbar .editorParamsLabel,
|
||||||
|
:root #toolbarContainer #toolbarViewer input,
|
||||||
|
:root #editorUndoBar,
|
||||||
|
:root .dialogButton {
|
||||||
|
font-family: "Inter";
|
||||||
|
}
|
||||||
|
|
||||||
.page {
|
#secondaryToolbar,
|
||||||
border: 1px solid var(--tn-main-border-color);
|
#documentPropertiesDialog,
|
||||||
box-shadow: 7px 7px 15px #00000010;
|
#findbar.doorHanger,
|
||||||
|
.doorHangerRight,
|
||||||
|
#printServiceDialog {
|
||||||
|
border: 1px solid var(--tn-dropdown-border-color);
|
||||||
|
border-radius: var(--tn-dropdown-border-radius);
|
||||||
|
background-color: var(--tn-menu-background-color);
|
||||||
|
padding: var(--tn-menu-padding-size);
|
||||||
|
box-shadow: 0px 10px 20px rgba(0, 0, 0, var(--tn-dropdown-shadow-opacity));
|
||||||
|
backdrop-filter: var(--tn-dropdown-backdrop-filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
.doorHangerRight,
|
||||||
|
.doorHangerLeft,
|
||||||
|
.doorHanger {
|
||||||
|
&::after, &::before {
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:root .toggle-button {
|
||||||
|
--toggle-border-color: transparent;
|
||||||
|
--toggle-background-color: var(--tn-input-background-color);
|
||||||
|
--toggle-background-color-hover: var(--toggle-background-color);
|
||||||
|
--toggle-dot-background-color: var(--tn-input-text-color);
|
||||||
|
--toggle-background-color-pressed: var(--tn-input-text-color);
|
||||||
|
--toggle-background-color-pressed-hover: var(--toggle-background-color-pressed);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root .colorPicker {
|
||||||
|
--hover-outline-color: var(--tn-input-focus-outline-color);
|
||||||
|
--selected-outline-color: var(--tn-main-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endregion */
|
||||||
|
|
||||||
/* #region Toolbar */
|
/* #region Toolbar */
|
||||||
|
|
||||||
|
.toolbarButton {
|
||||||
|
&:not(.labeled):active::before {
|
||||||
|
transform: scale(.85) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--tn-hover-item-background-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
color: var(--tn-hover-item-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.toggled::before {
|
||||||
|
color: var(--tn-menu-item-icon-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#findbar {
|
||||||
|
}
|
||||||
|
|
||||||
|
#scaleSelectContainer {
|
||||||
|
--dropdown-btn-bg-color: transparent;
|
||||||
|
--button-hover-color: var(--tn-hover-item-background-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
select:focus {
|
||||||
|
background: var(--tn-main-background-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toolbar editor dropdowns */
|
||||||
|
:root .editorParamsToolbar:not(.menu),
|
||||||
|
:root #highlightParamsToolbarContainer {
|
||||||
|
padding: 10px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toolbar dropdowns */
|
||||||
|
:root .editorParamsToolbar {
|
||||||
|
.menu {
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editorParamsToolbarContainer {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Overflow menu */
|
||||||
|
:root #secondaryToolbar {
|
||||||
|
--toolbar-icon-bg-color: var(--tn-menu-item-icon-color);
|
||||||
|
--toolbar-icon-hover-bg-color: var(--tn-menu-item-icon-color);
|
||||||
|
--toggled-btn-bg-color: transparent;
|
||||||
|
--toggled-btn-color: currentColor;
|
||||||
|
--doorhanger-icon-opacity: 1;
|
||||||
|
padding: var(--tn-menu-padding-size);
|
||||||
|
|
||||||
|
.toolbarButton.labeled {
|
||||||
|
color: var(--tn-menu-text-color);
|
||||||
|
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Horizontal menu dividers */
|
||||||
|
:root #highlightParamsToolbarContainer #editorHighlightVisibility .divider,
|
||||||
|
:root .horizontalToolbarSeparator {
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
background: unset;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
border-top: 1px solid var(--tn-main-border-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Radio menu items */
|
||||||
|
#cursorToolButtons .toolbarButton,
|
||||||
|
#scrollModeButtons .toolbarButton,
|
||||||
|
#spreadModeButtons .toolbarButton {
|
||||||
|
--toggled-hover-active-btn-color: var(--tn-hover-item-background-color);
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
width: 2em;
|
||||||
|
height: 100%;
|
||||||
|
/* https://pictogrammers.com/library/mdi/icon/radiobox-blank/ */
|
||||||
|
mask-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3e%3ctitle%3eradiobox-blank%3c/title%3e%3cpath d='M12%2c20A8%2c8 0 0%2c1 4%2c12A8%2c8 0 0%2c1 12%2c4A8%2c8 0 0%2c1 20%2c12A8%2c8 0 0%2c1 12%2c20M12%2c2A10%2c10 0 0%2c0 2%2c12A10%2c10 0 0%2c0 12%2c22A10%2c10 0 0%2c0 22%2c12A10%2c10 0 0%2c0 12%2c2Z' /%3e%3c/svg%3e");
|
||||||
|
mask-size: 16px;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-position: center center;
|
||||||
|
background-color: var(--tn-main-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.toggled::after {
|
||||||
|
/* https://pictogrammers.com/library/mdi/icon/radiobox-marked/ */
|
||||||
|
mask-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3e%3ctitle%3eradiobox-marked%3c/title%3e%3cpath d='M12%2c20A8%2c8 0 0%2c1 4%2c12A8%2c8 0 0%2c1 12%2c4A8%2c8 0 0%2c1 20%2c12A8%2c8 0 0%2c1 12%2c20M12%2c2A10%2c10 0 0%2c0 2%2c12A10%2c10 0 0%2c0 12%2c22A10%2c10 0 0%2c0 22%2c12A10%2c10 0 0%2c0 12%2c2M12%2c7A5%2c5 0 0%2c0 7%2c12A5%2c5 0 0%2c0 12%2c17A5%2c5 0 0%2c0 17%2c12A5%2c5 0 0%2c0 12%2c7Z' /%3e%3c/svg%3e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Permanently removed buttons */
|
/* Permanently removed buttons */
|
||||||
#viewsManagerToggleButton,
|
#viewsManagerToggleButton,
|
||||||
#downloadButton,
|
#downloadButton,
|
||||||
@ -43,10 +193,51 @@
|
|||||||
|
|
||||||
/* #region Properties Dialog */
|
/* #region Properties Dialog */
|
||||||
|
|
||||||
/* Hide irrelevant properties */
|
#documentPropertiesDialog {
|
||||||
#documentPropertiesDialog > .row:has(#fileNameField),
|
--separator-color: transparent;
|
||||||
#documentPropertiesDialog > .row:has(#linearizedField) {
|
|
||||||
display: none;
|
user-select: none;
|
||||||
|
padding: 1em;
|
||||||
|
|
||||||
|
.row {
|
||||||
|
line-height: 1.5;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
font-weight: bold;
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
|
||||||
|
> p {
|
||||||
|
user-select: all;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Hide irrelevant properties */
|
||||||
|
> .row:has(#fileNameField),
|
||||||
|
> .row:has(#linearizedField) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #endregion */
|
/* #endregion */
|
||||||
|
|
||||||
|
/* #region Viewer Area */
|
||||||
|
|
||||||
|
.pdfViewer {
|
||||||
|
.page,
|
||||||
|
.page > .canvasWrapper,
|
||||||
|
.page > .canvasWrapper > canvas {
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
border: 1px solid var(--tn-main-border-color);
|
||||||
|
box-shadow: 7px 7px 15px #00000010;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#viewsManager {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endregion */
|
||||||
@ -25,17 +25,17 @@
|
|||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fuse.js": "7.1.0",
|
"fuse.js": "7.1.0",
|
||||||
"katex": "0.16.28",
|
"katex": "0.16.33",
|
||||||
"mermaid": "11.12.3"
|
"mermaid": "11.12.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@digitak/esrun": "3.2.26",
|
"@digitak/esrun": "3.2.26",
|
||||||
"@triliumnext/ckeditor5": "workspace:*",
|
"@triliumnext/ckeditor5": "workspace:*",
|
||||||
"@typescript-eslint/eslint-plugin": "8.56.0",
|
"@typescript-eslint/eslint-plugin": "8.56.1",
|
||||||
"@typescript-eslint/parser": "8.56.0",
|
"@typescript-eslint/parser": "8.56.1",
|
||||||
"dotenv": "17.3.1",
|
"dotenv": "17.3.1",
|
||||||
"esbuild": "0.27.3",
|
"esbuild": "0.27.3",
|
||||||
"eslint": "10.0.1",
|
"eslint": "10.0.2",
|
||||||
"highlight.js": "11.11.1",
|
"highlight.js": "11.11.1",
|
||||||
"typescript": "5.9.3"
|
"typescript": "5.9.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -96,7 +96,8 @@ rules.table = {
|
|||||||
var columnCount = tableColCount(node);
|
var columnCount = tableColCount(node);
|
||||||
var emptyHeader = ''
|
var emptyHeader = ''
|
||||||
if (columnCount && !secondLineIsDivider) {
|
if (columnCount && !secondLineIsDivider) {
|
||||||
emptyHeader = '|' + ' |'.repeat(columnCount) + '\n' + '|'
|
// MD060 compact style: 2 spaces between pipes for empty cells
|
||||||
|
emptyHeader = '|' + ' |'.repeat(columnCount) + '\n' + '|'
|
||||||
for (var columnIndex = 0; columnIndex < columnCount; ++columnIndex) {
|
for (var columnIndex = 0; columnIndex < columnCount; ++columnIndex) {
|
||||||
emptyHeader += ' ' + getBorder(getColumnAlignment(node, columnIndex)) + ' |';
|
emptyHeader += ' ' + getBorder(getColumnAlignment(node, columnIndex)) + ' |';
|
||||||
}
|
}
|
||||||
@ -157,13 +158,15 @@ function isFirstTbody (element) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Format table cells following MD060 compact style:
|
||||||
|
// Each cell has 1 space padding on left and right (prefix + content + ' |').
|
||||||
|
// Empty cells result in 2 spaces between pipes (1 left + 1 right padding).
|
||||||
function cell (content, node = null, index = null) {
|
function cell (content, node = null, index = null) {
|
||||||
if (index === null) index = indexOf.call(node.parentNode.childNodes, node)
|
if (index === null) index = indexOf.call(node.parentNode.childNodes, node)
|
||||||
var prefix = ' '
|
var prefix = ' '
|
||||||
if (index === 0) prefix = '| '
|
if (index === 0) prefix = '| '
|
||||||
let filteredContent = content.trim().replace(/\n\r/g, '<br>').replace(/\n/g, "<br>");
|
let filteredContent = content.trim().replace(/\n\r/g, '<br>').replace(/\n/g, "<br>");
|
||||||
filteredContent = filteredContent.replace(/\|+/g, '\\|')
|
filteredContent = filteredContent.replace(/\|+/g, '\\|')
|
||||||
while (filteredContent.length < 3) filteredContent += ' ';
|
|
||||||
if (node) filteredContent = handleColSpan(filteredContent, node, ' ');
|
if (node) filteredContent = handleColSpan(filteredContent, node, ' ');
|
||||||
return prefix + filteredContent + ' |'
|
return prefix + filteredContent + ' |'
|
||||||
}
|
}
|
||||||
@ -259,7 +262,7 @@ function nodeParentTable(node) {
|
|||||||
function handleColSpan(content, node, emptyChar) {
|
function handleColSpan(content, node, emptyChar) {
|
||||||
const colspan = node.getAttribute('colspan') || 1;
|
const colspan = node.getAttribute('colspan') || 1;
|
||||||
for (let i = 1; i < colspan; i++) {
|
for (let i = 1; i < colspan; i++) {
|
||||||
content += ' | ' + emptyChar.repeat(3);
|
content += ' |' + emptyChar;
|
||||||
}
|
}
|
||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
|
|||||||
@ -141,11 +141,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<pre class="expected">| Column 1 | Column 2 | Column 3 | Column 4 |
|
<pre class="expected">| Column 1 | Column 2 | Column 3 | Column 4 |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| | Row 1, Column 2 | Row 1, Column 3 | Row 1, Column 4 |
|
| | Row 1, Column 2 | Row 1, Column 3 | Row 1, Column 4 |
|
||||||
| Row 2, Column 1 | | Row 2, Column 3 | Row 2, Column 4 |
|
| Row 2, Column 1 | | Row 2, Column 3 | Row 2, Column 4 |
|
||||||
| Row 3, Column 1 | Row 3, Column 2 | | Row 3, Column 4 |
|
| Row 3, Column 1 | Row 3, Column 2 | | Row 3, Column 4 |
|
||||||
| Row 4, Column 1 | Row 4, Column 2 | Row 4, Column 3 | |
|
| Row 4, Column 1 | Row 4, Column 2 | Row 4, Column 3 | |
|
||||||
| | | | Row 5, Column 4 |</pre>
|
| | | | Row 5, Column 4 |</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="case" data-name="empty rows">
|
<div class="case" data-name="empty rows">
|
||||||
@ -174,7 +174,7 @@
|
|||||||
<pre class="expected">| Heading 1 | Heading 2 |
|
<pre class="expected">| Heading 1 | Heading 2 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Row 1 | Row 1 |
|
| Row 1 | Row 1 |
|
||||||
| | |
|
| | |
|
||||||
| Row 3 | Row 3 |</pre>
|
| Row 3 | Row 3 |</pre>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -259,7 +259,7 @@
|
|||||||
<tbody><tr><th>Heading</th></tr></tbody>
|
<tbody><tr><th>Heading</th></tr></tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<pre class="expected">| |
|
<pre class="expected">| |
|
||||||
| --- |
|
| --- |
|
||||||
| Heading |
|
| Heading |
|
||||||
| --- |</pre>
|
| --- |</pre>
|
||||||
@ -272,7 +272,7 @@
|
|||||||
<tr><td>Row 2 Cell 1</td><td>Row 2 Cell 2</td></tr>
|
<tr><td>Row 2 Cell 1</td><td>Row 2 Cell 2</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<pre class="expected">| | |
|
<pre class="expected">| | |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Row 1 Cell 1 | Row 1 Cell 2 |
|
| Row 1 Cell 1 | Row 1 Cell 2 |
|
||||||
| Row 2 Cell 1 | Row 2 Cell 2 |</pre>
|
| Row 2 Cell 1 | Row 2 Cell 2 |</pre>
|
||||||
@ -291,7 +291,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<pre class="expected">| | |
|
<pre class="expected">| | |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Heading | Not a heading |
|
| Heading | Not a heading |
|
||||||
| Heading | Not a heading |</pre>
|
| Heading | Not a heading |</pre>
|
||||||
|
|||||||
1965
pnpm-lock.yaml
generated
1965
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user