Compare commits

..

1 Commits

Author SHA1 Message Date
renovate[bot]
a8680a7121 fix(deps): update dependency react-window to v2.2.4 2026-01-08 16:22:10 +00:00
64 changed files with 587 additions and 1658 deletions

View File

@@ -11,14 +11,6 @@ concurrency:
cancel-in-progress: true
jobs:
sanity-check:
name: Sanity Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Check version consistency
run: pnpm tsx ${{ github.workspace }}/scripts/check-version-consistency.ts ${{ github.ref_name }}
make-electron:
name: Make Electron
strategy:

View File

@@ -9,7 +9,7 @@
"keywords": [],
"author": "Elian Doran <contact@eliandoran.me>",
"license": "AGPL-3.0-only",
"packageManager": "pnpm@10.28.0",
"packageManager": "pnpm@10.27.0",
"devDependencies": {
"@redocly/cli": "2.14.3",
"archiver": "7.0.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@triliumnext/client",
"version": "0.101.3",
"version": "0.101.1",
"description": "JQuery-based client for TriliumNext, used for both web and desktop (via Electron)",
"private": true,
"license": "AGPL-3.0-only",
@@ -61,7 +61,7 @@
"panzoom": "9.4.3",
"preact": "10.28.1",
"react-i18next": "16.5.1",
"react-window": "2.2.3",
"react-window": "2.2.4",
"reveal.js": "5.2.1",
"svg-pan-zoom": "3.6.2",
"tabulator-tables": "6.3.1",
@@ -69,6 +69,7 @@
},
"devDependencies": {
"@ckeditor/ckeditor5-inspector": "5.0.0",
"@preact/preset-vite": "2.10.2",
"@types/bootstrap": "5.2.10",
"@types/jquery": "3.5.33",
"@types/leaflet": "1.9.21",
@@ -78,7 +79,6 @@
"@types/tabulator-tables": "6.3.1",
"copy-webpack-plugin": "13.0.1",
"happy-dom": "20.0.11",
"lightningcss": "1.30.2",
"script-loader": "0.7.2",
"vite-plugin-static-copy": "3.1.4"
}

View File

@@ -154,7 +154,6 @@ export type CommandMappings = {
};
openInTab: ContextMenuCommandData;
openNoteInSplit: ContextMenuCommandData;
openNoteInWindow: ContextMenuCommandData;
openNoteInPopup: ContextMenuCommandData;
toggleNoteHoisting: ContextMenuCommandData;
insertNoteAfter: ContextMenuCommandData;

View File

@@ -616,9 +616,7 @@ export default class FNote {
}
isFolder() {
if (this.isLabelTruthy("subtreeHidden")) return false;
if (this.type === "search") return true;
return this.getFilteredChildBranches().length > 0;
return this.type === "search" || this.getFilteredChildBranches().length > 0;
}
getFilteredChildBranches() {

View File

@@ -1,21 +1,21 @@
import appContext, { type ContextMenuCommandData, type FilteredCommandNames } from "../components/app_context.js";
import type { SelectMenuItemEventListener } from "../components/events.js";
import type FAttachment from "../entities/fattachment.js";
import attributes from "../services/attributes.js";
import { executeBulkActions } from "../services/bulk_action.js";
import clipboard from "../services/clipboard.js";
import dialogService from "../services/dialog.js";
import NoteColorPicker from "./custom-items/NoteColorPicker.jsx";
import treeService from "../services/tree.js";
import froca from "../services/froca.js";
import { t } from "../services/i18n.js";
import clipboard from "../services/clipboard.js";
import noteCreateService from "../services/note_create.js";
import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js";
import appContext, { type ContextMenuCommandData, type FilteredCommandNames } from "../components/app_context.js";
import noteTypesService from "../services/note_types.js";
import server from "../services/server.js";
import toastService from "../services/toast.js";
import treeService from "../services/tree.js";
import utils from "../services/utils.js";
import dialogService from "../services/dialog.js";
import { t } from "../services/i18n.js";
import type NoteTreeWidget from "../widgets/note_tree.js";
import contextMenu, { type MenuCommandItem, type MenuItem } from "./context_menu.js";
import NoteColorPicker from "./custom-items/NoteColorPicker.jsx";
import type FAttachment from "../entities/fattachment.js";
import type { SelectMenuItemEventListener } from "../components/events.js";
import utils from "../services/utils.js";
import attributes from "../services/attributes.js";
import { executeBulkActions } from "../services/bulk_action.js";
// TODO: Deduplicate once client/server is well split.
interface ConvertToAttachmentResponse {
@@ -72,8 +72,6 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
const noSelectedNotes = selNodes.length === 0 || (selNodes.length === 1 && selNodes[0] === this.node);
const notSearch = note?.type !== "search";
const hasSubtreeHidden = note?.isLabelTruthy("subtreeHidden") ?? false;
const isSpotlighted = this.node.extraClasses.includes("spotlighted-node");
const notOptionsOrHelp = !note?.noteId.startsWith("_options") && !note?.noteId.startsWith("_help");
const parentNotSearch = !parentNote || parentNote.type !== "search";
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
@@ -81,18 +79,17 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
const items: (MenuItem<TreeCommandNames> | null)[] = [
{ title: t("tree-context-menu.open-in-a-new-tab"), command: "openInTab", shortcut: "Ctrl+Click", uiIcon: "bx bx-link-external", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-a-new-split"), command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-a-new-window"), command: "openNoteInWindow", uiIcon: "bx bx-window-open", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-popup"), command: "openNoteInPopup", uiIcon: "bx bx-edit", enabled: noSelectedNotes },
isHoisted
? null
: {
title: `${t("tree-context-menu.hoist-note")}`,
command: "toggleNoteHoisting",
keyboardShortcut: "toggleNoteHoisting",
uiIcon: "bx bxs-chevrons-up",
enabled: noSelectedNotes && notSearch
},
title: `${t("tree-context-menu.hoist-note")}`,
command: "toggleNoteHoisting",
keyboardShortcut: "toggleNoteHoisting",
uiIcon: "bx bxs-chevrons-up",
enabled: noSelectedNotes && notSearch
},
!isHoisted || !isNotRoot
? null
: { title: t("tree-context-menu.unhoist-note"), command: "toggleNoteHoisting", keyboardShortcut: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
@@ -115,7 +112,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
keyboardShortcut: "createNoteInto",
uiIcon: "bx bx-plus",
items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
enabled: notSearch && noSelectedNotes && notOptionsOrHelp && !hasSubtreeHidden && !isSpotlighted,
enabled: notSearch && noSelectedNotes && notOptionsOrHelp,
columns: 2
},
@@ -153,17 +150,8 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
{ kind: "separator" },
!hasSubtreeHidden && { title: t("tree-context-menu.expand-subtree"), command: "expandSubtree", keyboardShortcut: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
!hasSubtreeHidden && { title: t("tree-context-menu.collapse-subtree"), command: "collapseSubtree", keyboardShortcut: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{
title: hasSubtreeHidden ? t("tree-context-menu.show-subtree") : t("tree-context-menu.hide-subtree"),
uiIcon: "bx bx-show",
handler: async () => {
const note = await froca.getNote(this.node.data.noteId);
if (!note) return;
attributes.setBooleanWithInheritance(note, "subtreeHidden", !hasSubtreeHidden);
}
},
{ title: t("tree-context-menu.expand-subtree"), command: "expandSubtree", keyboardShortcut: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: t("tree-context-menu.collapse-subtree"), command: "collapseSubtree", keyboardShortcut: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{
title: t("tree-context-menu.sort-by"),
command: "sortChildNotes",
@@ -176,7 +164,7 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
{ title: t("tree-context-menu.copy-note-path-to-clipboard"), command: "copyNotePathToClipboard", uiIcon: "bx bx-directions", enabled: true },
{ title: t("tree-context-menu.recent-changes-in-subtree"), command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes && notOptionsOrHelp }
].filter(Boolean) as MenuItem<TreeCommandNames>[]
]
},
{ kind: "separator" },
@@ -304,30 +292,25 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
noteCreateService.createNote(parentNotePath, {
target: "after",
targetBranchId: this.node.data.branchId,
type,
isProtected,
templateNoteId
type: type,
isProtected: isProtected,
templateNoteId: templateNoteId
});
} else if (command === "insertChildNote") {
const parentNotePath = treeService.getNotePath(this.node);
noteCreateService.createNote(parentNotePath, {
type,
type: type,
isProtected: this.node.data.isProtected,
templateNoteId
templateNoteId: templateNoteId
});
} else if (command === "openNoteInSplit") {
const subContexts = appContext.tabManager.getActiveContext()?.getSubContexts();
const { ntxId } = subContexts?.[subContexts.length - 1] ?? {};
this.treeWidget.triggerCommand("openNewNoteSplit", { ntxId, notePath });
} else if (command === "openNoteInWindow") {
appContext.triggerCommand("openInWindow", {
notePath,
hoistedNoteId: appContext.tabManager.getActiveContext()?.hoistedNoteId
});
} else if (command === "openNoteInPopup") {
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath });
appContext.triggerCommand("openInPopup", { noteIdOrPath: notePath })
} else if (command === "convertNoteToAttachment") {
if (!(await dialogService.confirm(t("tree-context-menu.convert-to-attachment-confirm")))) {
return;
@@ -349,11 +332,11 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
toastService.showMessage(t("tree-context-menu.converted-to-attachments", { count: converted }));
} else if (command === "copyNotePathToClipboard") {
navigator.clipboard.writeText(`#${ notePath}`);
navigator.clipboard.writeText("#" + notePath);
} else if (command) {
this.treeWidget.triggerCommand<TreeCommandNames>(command, {
node: this.node,
notePath,
notePath: notePath,
noteId: this.node.data.noteId,
selectedOrActiveBranchIds: this.treeWidget.getSelectedOrActiveBranchIds(this.node),
selectedOrActiveNoteIds: this.treeWidget.getSelectedOrActiveNoteIds(this.node)

View File

@@ -1,139 +0,0 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { buildNote } from "../test/easy-froca";
import { setBooleanWithInheritance } from "./attributes";
import froca from "./froca";
import server from "./server.js";
// Spy on server methods to track calls
// @ts-expect-error the generic typing is causing issues here
server.put = vi.fn(async <T> (url: string, data?: T) => ({} as T));
// @ts-expect-error the generic typing is causing issues here
server.remove = vi.fn(async <T> (url: string) => ({} as T));
describe("Set boolean with inheritance", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("doesn't call server if value matches directly", async () => {
const noteWithLabel = buildNote({
title: "New note",
"#foo": ""
});
const noteWithoutLabel = buildNote({
title: "New note"
});
await setBooleanWithInheritance(noteWithLabel, "foo", true);
await setBooleanWithInheritance(noteWithoutLabel, "foo", false);
expect(server.put).not.toHaveBeenCalled();
expect(server.remove).not.toHaveBeenCalled();
});
it("sets boolean normally without inheritance", async () => {
const standaloneNote = buildNote({
title: "New note"
});
await setBooleanWithInheritance(standaloneNote, "foo", true);
expect(server.put).toHaveBeenCalledWith(`notes/${standaloneNote.noteId}/set-attribute`, {
type: "label",
name: "foo",
value: "",
isInheritable: false
});
});
it("removes boolean normally without inheritance", async () => {
const standaloneNote = buildNote({
title: "New note",
"#foo": ""
});
const attributeId = standaloneNote.getLabel("foo")!.attributeId;
await setBooleanWithInheritance(standaloneNote, "foo", false);
expect(server.remove).toHaveBeenCalledWith(`notes/${standaloneNote.noteId}/attributes/${attributeId}`);
});
it("doesn't call server if value matches inherited", async () => {
const parentNote = buildNote({
title: "Parent note",
"#foo(inheritable)": "",
"children": [
{
title: "Child note"
}
]
});
const childNote = froca.getNoteFromCache(parentNote.children[0])!;
expect(childNote.isLabelTruthy("foo")).toBe(true);
await setBooleanWithInheritance(childNote, "foo", true);
expect(server.put).not.toHaveBeenCalled();
expect(server.remove).not.toHaveBeenCalled();
});
it("overrides boolean with inheritance", async () => {
const parentNote = buildNote({
title: "Parent note",
"#foo(inheritable)": "",
"children": [
{
title: "Child note"
}
]
});
const childNote = froca.getNoteFromCache(parentNote.children[0])!;
expect(childNote.isLabelTruthy("foo")).toBe(true);
await setBooleanWithInheritance(childNote, "foo", false);
expect(server.put).toHaveBeenCalledWith(`notes/${childNote.noteId}/set-attribute`, {
type: "label",
name: "foo",
value: "false",
isInheritable: false
});
});
it("overrides boolean with inherited false", async () => {
const parentNote = buildNote({
title: "Parent note",
"#foo(inheritable)": "false",
"children": [
{
title: "Child note"
}
]
});
const childNote = froca.getNoteFromCache(parentNote.children[0])!;
expect(childNote.isLabelTruthy("foo")).toBe(false);
await setBooleanWithInheritance(childNote, "foo", true);
expect(server.put).toHaveBeenCalledWith(`notes/${childNote.noteId}/set-attribute`, {
type: "label",
name: "foo",
value: "",
isInheritable: false
});
});
it("deletes override boolean with inherited false with already existing value", async () => {
const parentNote = buildNote({
title: "Parent note",
"#foo(inheritable)": "false",
"children": [
{
title: "Child note",
"#foo": "false",
}
]
});
const childNote = froca.getNoteFromCache(parentNote.children[0])!;
expect(childNote.isLabelTruthy("foo")).toBe(false);
await setBooleanWithInheritance(childNote, "foo", true);
expect(server.put).toBeCalledWith(`notes/${childNote.noteId}/set-attribute`, {
type: "label",
name: "foo",
value: "",
isInheritable: false
});
});
});

View File

@@ -1,15 +1,14 @@
import { AttributeType } from "@triliumnext/commons";
import type FNote from "../entities/fnote.js";
import froca from "./froca.js";
import type { AttributeRow } from "./load_results.js";
import server from "./server.js";
import froca from "./froca.js";
import type FNote from "../entities/fnote.js";
import type { AttributeRow } from "./load_results.js";
import { AttributeType } from "@triliumnext/commons";
async function addLabel(noteId: string, name: string, value: string = "", isInheritable = false) {
await server.put(`notes/${noteId}/attribute`, {
type: "label",
name,
value,
name: name,
value: value,
isInheritable
});
}
@@ -17,8 +16,8 @@ async function addLabel(noteId: string, name: string, value: string = "", isInhe
export async function setLabel(noteId: string, name: string, value: string = "", isInheritable = false) {
await server.put(`notes/${noteId}/set-attribute`, {
type: "label",
name,
value,
name: name,
value: value,
isInheritable
});
}
@@ -26,42 +25,12 @@ export async function setLabel(noteId: string, name: string, value: string = "",
export async function setRelation(noteId: string, name: string, value: string = "", isInheritable = false) {
await server.put(`notes/${noteId}/set-attribute`, {
type: "relation",
name,
value,
name: name,
value: value,
isInheritable
});
}
/**
* Sets a boolean label on the given note, taking inheritance into account. If the desired value matches the inherited
* value, any owned label will be removed to allow the inherited value to take effect. If the desired value differs
* from the inherited value, an owned label will be created or updated to reflect the desired value.
*
* When checking if the boolean value is set, don't use `note.hasLabel`; instead use `note.isLabelTruthy`.
*
* @param note the note on which to set the boolean label.
* @param labelName the name of the label to set.
* @param value the boolean value to set for the label.
*/
export async function setBooleanWithInheritance(note: FNote, labelName: string, value: boolean) {
const actualValue = note.isLabelTruthy(labelName);
if (actualValue === value) return;
const hasInheritedValue = !note.hasOwnedLabel(labelName) && note.hasLabel(labelName);
if (hasInheritedValue) {
if (value) {
setLabel(note.noteId, labelName, "");
} else {
// Label is inherited - override to false.
setLabel(note.noteId, labelName, "false");
}
} else if (value) {
setLabel(note.noteId, labelName, "");
} else {
removeOwnedLabelByName(note, labelName);
}
}
async function removeAttributeById(noteId: string, attributeId: string) {
await server.remove(`notes/${noteId}/attributes/${attributeId}`);
}
@@ -173,7 +142,6 @@ export default {
setLabel,
setRelation,
setAttribute,
setBooleanWithInheritance,
removeAttributeById,
removeOwnedLabelByName,
removeOwnedRelationByName,

View File

@@ -1,12 +1,12 @@
import appContext from "../components/app_context.js";
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
import froca from "./froca.js";
import hoistedNoteService from "./hoisted_note.js";
import { t } from "./i18n.js";
import utils from "./utils.js";
import server from "./server.js";
import toastService, { type ToastOptionsWithRequiredId } from "./toast.js";
import utils from "./utils.js";
import froca from "./froca.js";
import hoistedNoteService from "./hoisted_note.js";
import ws from "./ws.js";
import appContext from "../components/app_context.js";
import { t } from "./i18n.js";
import type { ResolveOptions } from "../widgets/dialogs/delete_notes.js";
// TODO: Deduplicate type with server
interface Response {
@@ -66,7 +66,7 @@ async function moveAfterBranch(branchIdsToMove: string[], afterBranchId: string)
}
}
async function moveToParentNote(branchIdsToMove: string[], newParentBranchId: string, componentId?: string) {
async function moveToParentNote(branchIdsToMove: string[], newParentBranchId: string) {
const newParentBranch = froca.getBranch(newParentBranchId);
if (!newParentBranch) {
return;
@@ -86,7 +86,7 @@ async function moveToParentNote(branchIdsToMove: string[], newParentBranchId: st
continue;
}
const resp = await server.put<Response>(`branches/${branchIdToMove}/move-to/${newParentBranchId}`, undefined, componentId);
const resp = await server.put<Response>(`branches/${branchIdToMove}/move-to/${newParentBranchId}`);
if (!resp.success) {
toastService.showError(resp.message);

View File

@@ -23,12 +23,6 @@ export interface RenderOptions {
imageHasZoom?: boolean;
/** If enabled, it will prevent the default behavior in which an empty note would display a list of children. */
noChildrenList?: boolean;
/** If enabled, it will prevent rendering of included notes. */
noIncludedNotes?: boolean;
/** If enabled, it will include archived notes when rendering children list. */
includeArchivedNotes?: boolean;
/** Set of note IDs that have already been seen during rendering to prevent infinite recursion. */
seenNoteIds?: Set<string>;
}
const CODE_MIME_TYPES = new Set(["application/json"]);

View File

@@ -1,132 +0,0 @@
import { trimIndentation } from "@triliumnext/commons";
import { describe, expect, it } from "vitest";
import { buildNote } from "../test/easy-froca";
import renderText from "./content_renderer_text";
describe("Text content renderer", () => {
it("renders included note", async () => {
const contentEl = document.createElement("div");
const includedNote = buildNote({
title: "Included note",
content: "<p>This is the included note.</p>"
});
const note = buildNote({
title: "New note",
content: trimIndentation`
<p>
Hi there
</p>
<section class="include-note" data-note-id="${includedNote.noteId}" data-box-size="medium">
&nbsp;
</section>
`
});
await renderText(note, $(contentEl));
expect(contentEl.querySelectorAll("section.include-note").length).toBe(1);
expect(contentEl.querySelectorAll("section.include-note p").length).toBe(1);
});
it("skips rendering included note", async () => {
const contentEl = document.createElement("div");
const includedNote = buildNote({
title: "Included note",
content: "<p>This is the included note.</p>"
});
const note = buildNote({
title: "New note",
content: trimIndentation`
<p>
Hi there
</p>
<section class="include-note" data-note-id="${includedNote.noteId}" data-box-size="medium">
&nbsp;
</section>
`
});
await renderText(note, $(contentEl), { noIncludedNotes: true });
expect(contentEl.querySelectorAll("section.include-note").length).toBe(0);
});
it("doesn't enter infinite loop on direct recursion", async () => {
const contentEl = document.createElement("div");
const note = buildNote({
title: "New note",
id: "Y7mBwmRjQyb4",
content: trimIndentation`
<p>
Hi there
</p>
<section class="include-note" data-note-id="Y7mBwmRjQyb4" data-box-size="medium">
&nbsp;
</section>
<section class="include-note" data-note-id="Y7mBwmRjQyb4" data-box-size="medium">
&nbsp;
</section>
`
});
await renderText(note, $(contentEl));
expect(contentEl.querySelectorAll("section.include-note").length).toBe(0);
});
it("doesn't enter infinite loop on indirect recursion", async () => {
const contentEl = document.createElement("div");
buildNote({
id: "first",
title: "Included note",
content: trimIndentation`\
<p>This is the included note.</p>
<section class="include-note" data-note-id="second" data-box-size="medium">
&nbsp;
</section>
`
});
const note = buildNote({
id: "second",
title: "New note",
content: trimIndentation`
<p>
Hi there
</p>
<section class="include-note" data-note-id="first" data-box-size="medium">
&nbsp;
</section>
`
});
await renderText(note, $(contentEl));
expect(contentEl.querySelectorAll("section.include-note").length).toBe(1);
});
it("renders children list when note is empty", async () => {
const contentEl = document.createElement("div");
const parentNote = buildNote({
title: "Parent note",
children: [
{ title: "Child note 1" },
{ title: "Child note 2" }
]
});
await renderText(parentNote, $(contentEl));
const items = contentEl.querySelectorAll("a");
expect(items.length).toBe(2);
expect(items[0].textContent).toBe("Child note 1");
expect(items[1].textContent).toBe("Child note 2");
});
it("skips archived notes in children list", async () => {
const contentEl = document.createElement("div");
const parentNote = buildNote({
title: "Parent note",
children: [
{ title: "Child note 1" },
{ title: "Child note 2", "#archived": "" },
{ title: "Child note 3" }
]
});
await renderText(parentNote, $(contentEl));
const items = contentEl.querySelectorAll("a");
expect(items.length).toBe(2);
expect(items[0].textContent).toBe("Child note 1");
expect(items[1].textContent).toBe("Child note 3");
});
});

View File

@@ -15,14 +15,7 @@ export default async function renderText(note: FNote | FAttachment, $renderedCon
if (blob && !isHtmlEmpty(blob.content)) {
$renderedContent.append($('<div class="ck-content">').html(blob.content));
const seenNoteIds = options.seenNoteIds ?? new Set<string>();
seenNoteIds.add("noteId" in note ? note.noteId : note.attachmentId);
if (!options.noIncludedNotes) {
await renderIncludedNotes($renderedContent[0], seenNoteIds);
} else {
$renderedContent.find("section.include-note").remove();
}
await renderIncludedNotes($renderedContent[0]);
if ($renderedContent.find("span.math-tex").length > 0) {
renderMathInElement($renderedContent[0], { trust: true });
@@ -42,11 +35,11 @@ export default async function renderText(note: FNote | FAttachment, $renderedCon
await rewriteMermaidDiagramsInContainer($renderedContent[0] as HTMLDivElement);
await formatCodeBlocks($renderedContent);
} else if (note instanceof FNote && !options.noChildrenList) {
await renderChildrenList($renderedContent, note, options.includeArchivedNotes ?? false);
await renderChildrenList($renderedContent, note);
}
}
async function renderIncludedNotes(contentEl: HTMLElement, seenNoteIds: Set<string>) {
async function renderIncludedNotes(contentEl: HTMLElement) {
// TODO: Consider duplicating with server's share/content_renderer.ts.
const includeNoteEls = contentEl.querySelectorAll("section.include-note");
@@ -73,15 +66,7 @@ async function renderIncludedNotes(contentEl: HTMLElement, seenNoteIds: Set<stri
continue;
}
if (seenNoteIds.has(noteId)) {
console.warn(`Skipping inclusion of ${noteId} to avoid circular reference.`);
includeNoteEl.remove();
continue;
}
const renderedContent = (await content_renderer.getRenderedContent(note, {
seenNoteIds
})).$renderedContent;
const renderedContent = (await content_renderer.getRenderedContent(note)).$renderedContent;
includeNoteEl.replaceChildren(...renderedContent);
}
}
@@ -113,7 +98,7 @@ export async function applyInlineMermaid(container: HTMLDivElement) {
}
}
async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: FNote, includeArchivedNotes: boolean) {
async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: FNote) {
let childNoteIds = note.getChildNoteIds();
if (!childNoteIds.length) {
@@ -123,16 +108,14 @@ async function renderChildrenList($renderedContent: JQuery<HTMLElement>, note: F
$renderedContent.css("padding", "10px");
$renderedContent.addClass("text-with-ellipsis");
// just load the first 10 child notes
if (childNoteIds.length > 10) {
childNoteIds = childNoteIds.slice(0, 10);
}
// just load the first 10 child notes
const childNotes = await froca.getNotes(childNoteIds);
for (const childNote of childNotes) {
if (childNote.isArchived && !includeArchivedNotes) continue;
$renderedContent.append(
await link.createLink(`${note.noteId}/${childNote.noteId}`, {
showTooltip: false,

View File

@@ -1,5 +1,4 @@
import type { AttachmentRow, EtapiTokenRow, NoteType, OptionNames } from "@triliumnext/commons";
import type { AttributeType } from "../entities/fattribute.js";
import type { EntityChange } from "../server_types.js";
@@ -136,14 +135,7 @@ export default class LoadResults {
}
getBranchRows() {
return this.branchRows.map((row) => {
const branch = this.getEntityRow("branches", row.branchId);
if (branch) {
// Merge the componentId from the tracked row with the entity data
return { ...branch, componentId: row.componentId };
}
return null;
}).filter((branch) => !!branch) as BranchRow[];
return this.branchRows.map((row) => this.getEntityRow("branches", row.branchId)).filter((branch) => !!branch);
}
addNoteReordering(parentNoteId: string, componentId: string) {
@@ -161,14 +153,7 @@ export default class LoadResults {
getAttributeRows(componentId = "none"): AttributeRow[] {
return this.attributeRows
.filter((row) => row.componentId !== componentId)
.map((row) => {
const attr = this.getEntityRow("attributes", row.attributeId);
if (attr) {
// Merge the componentId from the tracked row with the entity data
return { ...attr, componentId: row.componentId };
}
return null;
})
.map((row) => this.getEntityRow("attributes", row.attributeId))
.filter((attr) => !!attr) as AttributeRow[];
}

View File

@@ -69,6 +69,24 @@ export function buildNote(noteDef: NoteDefinition) {
});
note.getBlob = async () => blob;
// Manage children.
if (noteDef.children) {
for (const childDef of noteDef.children) {
const childNote = buildNote(childDef);
const branchId = `${note.noteId}_${childNote.noteId}`;
const branch = new FBranch(froca, {
branchId,
noteId: childNote.noteId,
parentNoteId: note.noteId,
notePosition: childNotePosition,
fromSearchNote: false
});
froca.branches[branchId] = branch;
note.addChild(childNote.noteId, branchId, false);
childNotePosition += 10;
}
}
let position = 0;
for (const [ key, value ] of Object.entries(noteDef)) {
const attributeId = utils.randomString(12);
@@ -118,25 +136,5 @@ export function buildNote(noteDef: NoteDefinition) {
}
noteAttributeCache.attributes[note.noteId].push(attribute);
}
// Manage children.
if (noteDef.children) {
for (const childDef of noteDef.children) {
const childNote = buildNote(childDef);
const branchId = `${note.noteId}_${childNote.noteId}`;
const branch = new FBranch(froca, {
branchId,
noteId: childNote.noteId,
parentNoteId: note.noteId,
notePosition: childNotePosition,
fromSearchNote: false
});
froca.branches[branchId] = branch;
note.addChild(childNote.noteId, branchId, false);
childNote.addParent(note.noteId, branchId, false);
childNotePosition += 10;
}
}
return note;
}

View File

@@ -800,8 +800,7 @@
"geo-map": "Geo Map",
"board": "Board",
"presentation": "Presentation",
"include_archived_notes": "Show archived notes",
"hide_child_notes": "Hide child notes in tree"
"include_archived_notes": "Show archived notes"
},
"edited_notes": {
"no_edited_notes_found": "No edited notes on this day yet...",
@@ -1644,7 +1643,6 @@
"tree-context-menu": {
"open-in-a-new-tab": "Open in a new tab",
"open-in-a-new-split": "Open in a new split",
"open-in-a-new-window": "Open in a new window",
"insert-note-after": "Insert note after",
"insert-child-note": "Insert child note",
"archive": "Archive",
@@ -1657,8 +1655,6 @@
"advanced": "Advanced",
"expand-subtree": "Expand subtree",
"collapse-subtree": "Collapse subtree",
"hide-subtree": "Hide subtree",
"show-subtree": "Show subtree",
"sort-by": "Sort by...",
"recent-changes-in-subtree": "Recent changes in subtree",
"convert-to-attachment": "Convert to attachment",
@@ -1776,12 +1772,7 @@
"clone-indicator-tooltip": "This note has {{- count}} parents: {{- parents}}",
"clone-indicator-tooltip-single": "This note is cloned (1 additional parent: {{- parent}})",
"shared-indicator-tooltip": "This note is shared publicly",
"shared-indicator-tooltip-with-url": "This note is shared publicly at: {{- url}}",
"subtree-hidden-tooltip_one": "{{count}} child note that is hidden from the tree",
"subtree-hidden-tooltip_other": "{{count}} child notes that are hidden from the tree",
"subtree-hidden-moved-title": "Added to {{title}}",
"subtree-hidden-moved-description-collection": "This collection hides its child notes in the tree.",
"subtree-hidden-moved-description-other": "Child notes are hidden in the tree for this note."
"shared-indicator-tooltip-with-url": "This note is shared publicly at: {{- url}}"
},
"title_bar_buttons": {
"window-on-top": "Keep Window on Top"

View File

@@ -21,13 +21,7 @@
},
"bundle-error": {
"title": "Hubo un fallo al cargar un script personalizado",
"message": "El script no pudo ser ejecutado debido a:\n\n{{message}}"
},
"widget-list-error": {
"title": "Hubo un fallo al obtener la lista de widgets del servidor"
},
"widget-render-error": {
"title": "Hubo un fallo al renderizar un widget personalizado de React"
"message": "El script de la nota con ID \"{{id}}\", titulado \"{{title}}\" no pudo ser ejecutado debido a:\n\n{{message}}"
}
},
"add_link": {
@@ -697,7 +691,7 @@
"convert_into_attachment_successful": "La nota '{{title}}' ha sido convertida a un archivo adjunto.",
"convert_into_attachment_prompt": "¿Está seguro que desea convertir la nota '{{title}}' en un archivo adjunto de la nota padre?",
"print_pdf": "Exportar como PDF...",
"open_note_on_server": "Abrir nota en servidor"
"open_note_on_server": "Abrir nota en el servidor"
},
"onclick_button": {
"no_click_handler": "El widget de botón '{{componentId}}' no tiene un controlador de clics definido"
@@ -743,7 +737,7 @@
"zpetne_odkazy": {
"relation": "relación",
"backlink_one": "{{count}} Vínculo de retroceso",
"backlink_many": "{{count}} Vínculos de retroceso",
"backlink_many": "",
"backlink_other": "{{count}} vínculos de retroceso"
},
"mobile_detail_menu": {
@@ -756,10 +750,7 @@
"note_icon": {
"change_note_icon": "Cambiar icono de nota",
"search": "Búsqueda:",
"reset-default": "Restablecer a icono por defecto",
"search_placeholder_one": "Buscar {{number}} icono a través de {{count}} paquetes",
"search_placeholder_many": "Buscar {{number}} iconos a través de {{count}} paquetes",
"search_placeholder_other": "Buscar {{number}} iconos a través de {{count}} paquetes"
"reset-default": "Restablecer a icono por defecto"
},
"basic_properties": {
"note_type": "Tipo de nota",
@@ -799,7 +790,7 @@
"file_type": "Tipo de archivo",
"file_size": "Tamaño del archivo",
"download": "Descargar",
"open": "Abrir externamente",
"open": "Abrir",
"upload_new_revision": "Subir nueva revisión",
"upload_success": "Se ha subido una nueva revisión de archivo.",
"upload_failed": "Error al cargar una nueva revisión de archivo.",
@@ -1312,11 +1303,11 @@
"code_mime_types": {
"title": "Tipos MIME disponibles en el menú desplegable",
"tooltip_syntax_highlighting": "Resaltado de sintaxis",
"tooltip_code_block_syntax": "Bloques de Código en notas de Texto",
"tooltip_code_note_syntax": "Notas de Código"
"tooltip_code_block_syntax": "Bloques de código en notas de texto",
"tooltip_code_note_syntax": "Notas de código"
},
"vim_key_bindings": {
"use_vim_keybindings_in_code_notes": "Combinaciones de teclas Vim",
"use_vim_keybindings_in_code_notes": "Atajos de teclas de Vim",
"enable_vim_keybindings": "Habilitar los atajos de teclas de Vim en la notas de código (no es modo ex)"
},
"wrap_lines": {
@@ -1581,7 +1572,7 @@
"will_be_deleted_in": "Este archivo adjunto se eliminará automáticamente en {{time}}",
"will_be_deleted_soon": "Este archivo adjunto se eliminará automáticamente pronto",
"deletion_reason": ", porque el archivo adjunto no está vinculado en el contenido de la nota. Para evitar la eliminación, vuelva a agregar el enlace del archivo adjunto al contenido o convierta el archivo adjunto en una nota.",
"role_and_size": "Rol: {{role}}, tamaño: {{size}}, MIME: {{- mimeType}}",
"role_and_size": "Rol: {{role}}, Tamaño: {{size}}",
"link_copied": "Enlace del archivo adjunto copiado al portapapeles.",
"unrecognized_role": "Rol de archivo adjunto no reconocido '{{role}}'."
},
@@ -1632,7 +1623,7 @@
"import-into-note": "Importar a nota",
"apply-bulk-actions": "Aplicar acciones en lote",
"converted-to-attachments": "{{count}} notas han sido convertidas en archivos adjuntos.",
"convert-to-attachment-confirm": "¿Está seguro que desea convertir las notas seleccionadas en archivos adjuntos de sus notas padres? Esta operación solo aplica a notas de Imagen, otras notas serán omitidas.",
"convert-to-attachment-confirm": "¿Está seguro que desea convertir las notas seleccionadas en archivos adjuntos de sus notas padres?",
"open-in-popup": "Edición rápida",
"archive": "Archivar",
"unarchive": "Desarchivar"
@@ -1727,10 +1718,7 @@
"note_detail": {
"could_not_find_typewidget": "No se pudo encontrar typeWidget para el tipo '{{type}}'",
"printing": "Impresión en curso...",
"printing_pdf": "Exportando a PDF en curso..",
"print_report_collection_content_one": "{{count}} nota en la colección no se puede imprimir porque no son compatibles o está protegida.",
"print_report_collection_content_many": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas.",
"print_report_collection_content_other": "{{count}} notas en la colección no se pueden imprimir porque no son compatibles o están protegidas."
"printing_pdf": "Exportando a PDF en curso.."
},
"note_title": {
"placeholder": "escriba el título de la nota aquí..."
@@ -1942,7 +1930,7 @@
"unknown_widget": "Widget desconocido para \"{{id}}\"."
},
"note_language": {
"not_set": "Idioma no establecido",
"not_set": "No establecido",
"configure-languages": "Configurar idiomas..."
},
"content_language": {
@@ -1981,7 +1969,7 @@
"hide-weekends": "Ocultar fines de semana",
"show-scale": "Mostrar escala",
"display-week-numbers": "Mostrar números de semana",
"map-style": "Estilo de mapa",
"map-style": "Estilo de mapa:",
"max-nesting-depth": "Máxima profundidad de anidamiento:",
"vector_light": "Vector (claro)",
"vector_dark": "Vector (oscuro)",
@@ -2110,36 +2098,5 @@
"clear-color": "Borrar color de nota",
"set-color": "Asignar color de nota",
"set-custom-color": "Asignar color de nota personalizado"
},
"status_bar": {
"backlinks_one": "{{count}} vínculo de retroceso",
"backlinks_many": "{{count}} vínculos de retroceso",
"backlinks_other": "{{count}} vínculos de retroceso",
"backlinks_title_one": "Ver vínculo de retroceso",
"backlinks_title_many": "Ver vínculos de retroceso",
"backlinks_title_other": "Ver vínculos de retroceso",
"attachments_one": "{{count}} adjunto",
"attachments_many": "{{count}} adjuntos",
"attachments_other": "{{count}} adjuntos",
"attachments_title_one": "Ver adjunto en una nueva pestaña",
"attachments_title_many": "Ver adjuntos en una nueva pestaña",
"attachments_title_other": "Ver adjuntos en una nueva pestaña",
"attributes_one": "{{count}} atributo",
"attributes_many": "{{count}} atributos",
"attributes_other": "{{count}} atributos",
"note_paths_one": "{{count}} ruta",
"note_paths_many": "{{count}} rutas",
"note_paths_other": "{{count}} rutas"
},
"pdf": {
"attachments_one": "{{count}} adjunto",
"attachments_many": "{{count}} adjuntos",
"attachments_other": "{{count}} adjuntos",
"layers_one": "{{count}} capa",
"layers_many": "{{count}} capas",
"layers_other": "{{count}} capas",
"pages_one": "{{count}} página",
"pages_many": "{{count}} páginas",
"pages_other": "{{count}} páginas"
}
}

View File

@@ -69,7 +69,7 @@ declare namespace Fancytree {
debug(msg: any): void;
/** Expand (or collapse) all parent nodes. */
expandAll(flag?: boolean, options?: object): void;
expandAll(flag?: boolean, options?: Object): void;
/** [ext-filter] Dimm or hide whole branches.
* @returns {integer} count
@@ -221,7 +221,6 @@ declare namespace Fancytree {
branchId: string;
isProtected: boolean;
noteType: NoteType;
subtreeHidden: boolean;
}
interface FancytreeNewNode extends FancytreeNodeData {
@@ -370,7 +369,7 @@ declare namespace Fancytree {
* @param mode 'before', 'after', or 'child' (default='child')
* @param init NodeData (or simple title string)
*/
editCreateNode(mode?: string, init?: object): void;
editCreateNode(mode?: string, init?: Object): void;
/** [ext-edit] Stop inline editing.
*
@@ -527,7 +526,7 @@ declare namespace Fancytree {
*
* @param opts passed to `setExpanded()`. Defaults to {noAnimation: false, noEvents: false, scrollIntoView: true}
*/
makeVisible(opts?: object): JQueryPromise<any>;
makeVisible(opts?: Object): JQueryPromise<any>;
/** Move this node to targetNode.
*
@@ -590,25 +589,25 @@ declare namespace Fancytree {
* @param effects animation options.
* @param options {topNode: null, effects: ..., parent: ...} this node will remain visible in any case, even if `this` is outside the scroll pane.
*/
scrollIntoView(effects?: boolean, options?: object): JQueryPromise<any>;
scrollIntoView(effects?: boolean, options?: Object): JQueryPromise<any>;
/**
* @param effects animation options.
* @param options {topNode: null, effects: ..., parent: ...} this node will remain visible in any case, even if `this` is outside the scroll pane.
*/
scrollIntoView(effects?: object, options?: object): JQueryPromise<any>;
scrollIntoView(effects?: Object, options?: Object): JQueryPromise<any>;
/**
* @param flag pass false to deactivate
* @param opts additional options. Defaults to {noEvents: false}
*/
setActive(flag?: boolean, opts?: object): JQueryPromise<any>;
setActive(flag?: boolean, opts?: Object): JQueryPromise<any>;
/**
* @param flag pass false to collapse.
* @param opts additional options. Defaults to {noAnimation:false, noEvents:false}
*/
setExpanded(flag?: boolean, opts?: object): JQueryPromise<any>;
setExpanded(flag?: boolean, opts?: Object): JQueryPromise<any>;
/**
* Set keyboard focus to this node.
@@ -1110,7 +1109,7 @@ declare namespace Fancytree {
/** class names added to the node markup (separate with space) */
extraClasses?: string | undefined;
/** all properties from will be copied to `node.data` */
data?: object | undefined;
data?: Object | undefined;
/** Will be added as title attribute of the node's icon span,thus enabling a tooltip. */
iconTooltip?: string | undefined;
@@ -1161,7 +1160,7 @@ declare namespace Fancytree {
escapeHtml(s: string): string;
getEventTarget(event: Event): object;
getEventTarget(event: Event): Object;
getEventTargetType(event: Event): string;
@@ -1180,7 +1179,7 @@ declare namespace Fancytree {
parseHtml($ul: JQuery): NodeData[];
/** Add Fancytree extension definition to the list of globally available extensions. */
registerExtension(definition: object): void;
registerExtension(definition: Object): void;
unescapeHtml(s: string): string;

View File

@@ -215,7 +215,7 @@ export default function NoteDetail() {
return (
<div
ref={containerRef}
class={`component note-detail ${isFullHeight ? "full-height" : ""}`}
class={`note-detail ${isFullHeight ? "full-height" : ""}`}
>
{Object.entries(noteTypesToRender).map(([ itemType, Element ]) => {
return <NoteDetailWrapper

View File

@@ -44,7 +44,6 @@ export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) {
const noteIds = useFilteredNoteIds(note, unfilteredNoteIds);
const { pageNotes, ...pagination } = usePagination(note, noteIds);
const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived");
return (
<div class="note-list grid-view">
@@ -53,7 +52,7 @@ export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }
<div class="note-list-container use-tn-links">
{pageNotes?.map(childNote => (
<GridNoteCard note={childNote} parentNote={note} highlightedTokens={highlightedTokens} includeArchived={includeArchived} />
<GridNoteCard note={childNote} parentNote={note} highlightedTokens={highlightedTokens} />
))}
</div>
@@ -95,16 +94,14 @@ function ListNoteCard({ note, parentNote, highlightedTokens, currentLevel, expan
</h5>
{isExpanded && <>
<NoteContent note={note} highlightedTokens={highlightedTokens} noChildrenList includeArchivedNotes={includeArchived} />
<NoteContent note={note} highlightedTokens={highlightedTokens} noChildrenList />
<NoteChildren note={note} parentNote={parentNote} highlightedTokens={highlightedTokens} currentLevel={currentLevel} expandDepth={expandDepth} includeArchived={includeArchived} />
</>}
</div>
);
}
function GridNoteCard({ note, parentNote, highlightedTokens, includeArchived }: { note: FNote, parentNote: FNote, highlightedTokens: string[] | null | undefined, includeArchived: boolean }) {
const titleRef = useRef<HTMLSpanElement>(null);
const [ noteTitle, setNoteTitle ] = useState<string>();
function GridNoteCard({ note, parentNote, highlightedTokens }: { note: FNote, parentNote: FNote, highlightedTokens: string[] | null | undefined }) {
const notePath = getNotePath(parentNote, note);
return (
@@ -123,7 +120,6 @@ function GridNoteCard({ note, parentNote, highlightedTokens, includeArchived }:
note={note}
trim
highlightedTokens={highlightedTokens}
includeArchivedNotes={includeArchived}
/>
</div>
);
@@ -140,22 +136,14 @@ function NoteAttributes({ note }: { note: FNote }) {
return <span className="note-list-attributes" ref={ref} />;
}
function NoteContent({ note, trim, noChildrenList, highlightedTokens, includeArchivedNotes }: {
note: FNote;
trim?: boolean;
noChildrenList?: boolean;
highlightedTokens: string[] | null | undefined;
includeArchivedNotes: boolean;
}) {
function NoteContent({ note, trim, noChildrenList, highlightedTokens }: { note: FNote, trim?: boolean, noChildrenList?: boolean, highlightedTokens: string[] | null | undefined }) {
const contentRef = useRef<HTMLDivElement>(null);
const highlightSearch = useImperativeSearchHighlighlighting(highlightedTokens);
useEffect(() => {
content_renderer.getRenderedContent(note, {
trim,
noChildrenList,
noIncludedNotes: true,
includeArchivedNotes
noChildrenList
})
.then(({ $renderedContent, type }) => {
if (!contentRef.current) return;

View File

@@ -1,18 +1,17 @@
import { useCallback, useLayoutEffect, useState } from "preact/hooks";
import FNote from "../../entities/fnote";
import froca from "../../services/froca";
import { isDesktop, isMobile } from "../../services/utils";
import CalendarWidget from "./CalendarWidget";
import SpacerWidget from "./SpacerWidget";
import BookmarkButtons from "./BookmarkButtons";
import ProtectedSessionStatusWidget from "./ProtectedSessionStatusWidget";
import SyncStatus from "./SyncStatus";
import HistoryNavigationButton from "./HistoryNavigation";
import { AiChatButton, CommandButton, CustomWidget, NoteLauncher, QuickSearchLauncherWidget, ScriptLauncher, TodayLauncher } from "./LauncherDefinitions";
import { useTriliumEvent } from "../react/hooks";
import { onWheelHorizontalScroll } from "../widget_utils";
import BookmarkButtons from "./BookmarkButtons";
import CalendarWidget from "./CalendarWidget";
import HistoryNavigationButton from "./HistoryNavigation";
import { LaunchBarContext } from "./launch_bar_widgets";
import { AiChatButton, CommandButton, CustomWidget, NoteLauncher, QuickSearchLauncherWidget, ScriptLauncher, TodayLauncher } from "./LauncherDefinitions";
import ProtectedSessionStatusWidget from "./ProtectedSessionStatusWidget";
import SpacerWidget from "./SpacerWidget";
import SyncStatus from "./SyncStatus";
export default function LauncherContainer({ isHorizontalLayout }: { isHorizontalLayout: boolean }) {
const childNotes = useLauncherChildNotes();
@@ -35,19 +34,18 @@ export default function LauncherContainer({ isHorizontalLayout }: { isHorizontal
}}>
{childNotes?.map(childNote => {
if (childNote.type !== "launcher") {
console.warn(`Note '${childNote.noteId}' '${childNote.title}' is not a launcher even though it's in the launcher subtree`);
return false;
throw new Error(`Note '${childNote.noteId}' '${childNote.title}' is not a launcher even though it's in the launcher subtree`);
}
if (!isDesktop() && childNote.isLabelTruthy("desktopOnly")) {
return false;
}
return <Launcher key={childNote.noteId} note={childNote} isHorizontalLayout={isHorizontalLayout} />;
return <Launcher key={childNote.noteId} note={childNote} isHorizontalLayout={isHorizontalLayout} />
})}
</LaunchBarContext.Provider>
</div>
);
)
}
function Launcher({ note, isHorizontalLayout }: { note: FNote, isHorizontalLayout: boolean }) {
@@ -74,7 +72,7 @@ function initBuiltinWidget(note: FNote, isHorizontalLayout: boolean) {
const builtinWidget = note.getLabelValue("builtinWidget");
switch (builtinWidget) {
case "calendar":
return <CalendarWidget launcherNote={note} />;
return <CalendarWidget launcherNote={note} />
case "spacer":
// || has to be inside since 0 is a valid value
const baseSize = parseInt(note.getLabelValue("baseSize") || "40");
@@ -88,15 +86,15 @@ function initBuiltinWidget(note: FNote, isHorizontalLayout: boolean) {
case "syncStatus":
return <SyncStatus />;
case "backInHistoryButton":
return <HistoryNavigationButton launcherNote={note} command="backInNoteHistory" />;
return <HistoryNavigationButton launcherNote={note} command="backInNoteHistory" />
case "forwardInHistoryButton":
return <HistoryNavigationButton launcherNote={note} command="forwardInNoteHistory" />;
return <HistoryNavigationButton launcherNote={note} command="forwardInNoteHistory" />
case "todayInJournal":
return <TodayLauncher launcherNote={note} />;
return <TodayLauncher launcherNote={note} />
case "quickSearch":
return <QuickSearchLauncherWidget />;
return <QuickSearchLauncherWidget />
case "aiChatLauncher":
return <AiChatButton launcherNote={note} />;
return <AiChatButton launcherNote={note} />
default:
throw new Error(`Unrecognized builtin widget ${builtinWidget} for launcher ${note.noteId} "${note.title}"`);
}

View File

@@ -82,13 +82,6 @@ function ViewOptions({ note, viewType }: { note: FNote, viewType: ViewTypeOption
))}
{properties.length > 0 && <FormDropdownDivider />}
<ViewProperty note={note} property={{
type: "checkbox",
icon: "bx bx-hide",
label: t("book_properties.hide_child_notes"),
bindToLabel: "subtreeHidden"
} as CheckBoxProperty} />
<ViewProperty note={note} property={{
type: "checkbox",
icon: "bx bx-archive",

View File

@@ -1,20 +0,0 @@
#left-pane .tree-wrapper {
.note-indicator-icon.subtree-hidden-badge {
font-family: inherit !important;
margin-inline: 0.5em;
margin-top: 0.3em;
background: var(--left-pane-item-action-button-background);
color: var(--left-pane-item-action-button-color);
padding: 0.1em 0.6em;
border-radius: 0.5em;
font-size: 0.7rem;
font-weight: normal;
float: right;
vertical-align: middle;
}
.spotlighted-node {
opacity: 0.8;
font-style: italic;
}
}

View File

@@ -3,13 +3,13 @@ import "jquery.fancytree/dist/modules/jquery.fancytree.dnd5.js";
import "jquery.fancytree/dist/modules/jquery.fancytree.clones.js";
import "jquery.fancytree/dist/modules/jquery.fancytree.filter.js";
import "../stylesheets/tree.css";
import "./note_tree.css";
import appContext, { type CommandListenerData, type EventData } from "../components/app_context.js";
import type { SetNoteOpts } from "../components/note_context.js";
import type { TouchBarItem } from "../components/touch_bar.js";
import type FBranch from "../entities/fbranch.js";
import type FNote from "../entities/fnote.js";
import type { NoteType } from "../entities/fnote.js";
import contextMenu from "../menus/context_menu.js";
import type { TreeCommandNames } from "../menus/tree_context_menu.js";
import branchService from "../services/branches.js";
@@ -153,7 +153,7 @@ const TPL = /*html*/`
const MAX_SEARCH_RESULTS_IN_TREE = 100;
// this has to be hanged on the actual elements to effectively intercept and stop click event
const cancelClickPropagation: (e: Event) => void = (e) => e.stopPropagation();
const cancelClickPropagation: (e: JQuery.ClickEvent) => void = (e) => e.stopPropagation();
// TODO: Fix once we remove Node.js API from public
type Timeout = NodeJS.Timeout | string | number | undefined;
@@ -190,9 +190,6 @@ export interface DragData {
export const TREE_CLIPBOARD_TYPE = "application/x-fancytree-node";
/** Entity changes below the given threshold will be processed without batching to avoid performance degradation. */
const BATCH_UPDATE_THRESHOLD = 10;
export default class NoteTreeWidget extends NoteContextAwareWidget {
private $tree!: JQuery<HTMLElement>;
private $treeActions!: JQuery<HTMLElement>;
@@ -204,8 +201,6 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
private treeName: "main";
private autoCollapseTimeoutId?: Timeout;
private lastFilteredHoistedNotePath?: string | null;
private spotlightedNotePath?: string | null;
private spotlightedNode: Fancytree.FancytreeNode | null = null;
private tree!: Fancytree.Fancytree;
constructor() {
@@ -358,7 +353,6 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
this.$tree.fancytree({
titlesTabbable: true,
keyboard: true,
toggleEffect: options.is("motionEnabled") ? undefined : false,
extensions: ["dnd5", "clones", "filter"],
source: treeData,
scrollOfs: {
@@ -558,7 +552,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
} else if (data.hitMode === "after") {
branchService.moveAfterBranch(selectedBranchIds, node.data.branchId);
} else if (data.hitMode === "over") {
branchService.moveToParentNote(selectedBranchIds, node.data.branchId, this.componentId);
branchService.moveToParentNote(selectedBranchIds, node.data.branchId);
} else {
throw new Error(`Unknown hitMode '${data.hitMode}'`);
}
@@ -604,7 +598,102 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
clones: {
highlightActiveClones: true
},
enhanceTitle: buildEnhanceTitle(),
async enhanceTitle (
event: Event,
data: {
node: Fancytree.FancytreeNode;
noteId: string;
}
) {
const node = data.node;
if (!node.data.noteId) {
// if there's "non-note" node, then don't enhance
// this can happen for e.g. "Load error!" node
return;
}
const note = await froca.getNote(node.data.noteId, true);
if (!note) {
return;
}
const activeNoteContext = appContext.tabManager.getActiveContext();
const $span = $(node.span);
$span.find(".tree-item-button").remove();
$span.find(".note-indicator-icon").remove();
const isHoistedNote = activeNoteContext && activeNoteContext.hoistedNoteId === note.noteId && note.noteId !== "root";
if (note.hasLabel("workspace") && !isHoistedNote) {
const $enterWorkspaceButton = $(`<span class="tree-item-button tn-icon enter-workspace-button bx bx-door-open" title="${t("note_tree.hoist-this-note-workspace")}"></span>`).on(
"click",
cancelClickPropagation
);
$span.append($enterWorkspaceButton);
}
if (note.type === "search") {
const $refreshSearchButton = $(`<span class="tree-item-button tn-icon refresh-search-button bx bx-refresh" title="${t("note_tree.refresh-saved-search-results")}"></span>`).on(
"click",
cancelClickPropagation
);
$span.append($refreshSearchButton);
}
// TODO: Deduplicate with server's notes.ts#getAndValidateParent
if (!["search", "launcher"].includes(note.type)
&& !note.isOptions()
&& !note.isLaunchBarConfig()
&& !note.noteId.startsWith("_help")
) {
const $createChildNoteButton = $(`<span class="tree-item-button tn-icon add-note-button bx bx-plus" title="${t("note_tree.create-child-note")}"></span>`).on(
"click",
cancelClickPropagation
);
$span.append($createChildNoteButton);
}
if (isHoistedNote) {
const $unhoistButton = $(`<span class="tree-item-button tn-icon unhoist-button bx bx-door-open" title="${t("note_tree.unhoist")}"></span>`).on("click", cancelClickPropagation);
$span.append($unhoistButton);
}
// Add clone indicator with tooltip if note has multiple parents
const parentNotes = note.getParentNotes();
const realParents = parentNotes.filter(
(parent) => !["_share", "_lbBookmarks"].includes(parent.noteId) && parent.type !== "search"
);
if (realParents.length > 1) {
const parentTitles = realParents.map((p) => p.title).join(", ");
const tooltipText = realParents.length === 2
? t("note_tree.clone-indicator-tooltip-single", { parent: realParents[1].title })
: t("note_tree.clone-indicator-tooltip", { count: realParents.length, parents: parentTitles });
const $cloneIndicator = $(`<span class="note-indicator-icon clone-indicator"></span>`);
$cloneIndicator.attr("title", tooltipText);
$span.find(".fancytree-title").append($cloneIndicator);
}
// Add shared indicator with tooltip if note is shared
if (note.isShared()) {
const shareId = note.getOwnedLabelValue("shareAlias") || note.noteId;
const shareUrl = `${location.origin}${location.pathname}share/${shareId}`;
const tooltipText = t("note_tree.shared-indicator-tooltip-with-url", { url: shareUrl });
const $sharedIndicator = $(`<span class="note-indicator-icon shared-indicator"></span>`);
$sharedIndicator.attr("title", tooltipText);
$span.find(".fancytree-title").append($sharedIndicator);
}
},
// this is done to automatically lazy load all expanded notes after tree load
loadChildren: (event, data) => {
data.node.visit((subNode) => {
@@ -714,23 +803,6 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
childBranches = childBranches.slice(0, MAX_SEARCH_RESULTS_IN_TREE);
}
if (parentNote.isLabelTruthy("subtreeHidden")) {
// If we have a spotlighted note path, show only the child that leads to it
if (this.spotlightedNotePath) {
const spotlightPathSegments = this.spotlightedNotePath.split('/');
const parentIndex = spotlightPathSegments.indexOf(parentNote.noteId);
if (parentIndex >= 0 && parentIndex < spotlightPathSegments.length - 1) {
const nextNoteIdInPath = spotlightPathSegments[parentIndex + 1];
childBranches = childBranches.filter(branch => branch.noteId === nextNoteIdInPath);
} else {
childBranches = [];
}
} else {
childBranches = [];
}
}
for (const branch of childBranches) {
if (hideArchivedNotes) {
const note = branch.getNoteFromCache();
@@ -802,7 +874,6 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
lazy: true,
folder: isFolder,
expanded: !!branch.isExpanded && note.type !== "search",
subtreeHidden: note.isLabelTruthy("subtreeHidden"),
key: utils.randomString(12) // this should prevent some "duplicate key" errors
};
@@ -861,10 +932,6 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
extraClasses.push(...["tinted", colorClass]);
}
if (this.spotlightedNotePath && this.spotlightedNotePath.endsWith(`/${note.noteId}`)) {
extraClasses.push("spotlighted-node");
}
return extraClasses.join(" ");
}
@@ -1015,43 +1082,18 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
foundChildNode = this.findChildNode(parentNode, childNoteId);
if (!foundChildNode) {
const childNote = await froca.getNote(childNoteId);
if (logErrors) {
// besides real errors, this can be also caused by hiding of e.g. included images
// these are real notes with real notePath, user can display them in a detail,
// but they don't have a node in the tree
if (childNote?.type === "image") return;
const childNote = await froca.getNote(childNoteId);
// The child note can be part of a note with #subtreeHidden, case in which we need to "spotlight" it.
const parentNote = froca.getNoteFromCache(parentNode.data.noteId);
if (parentNote?.isLabelTruthy("subtreeHidden")) {
// Enable spotlight mode and reload the parent to show only the path to this note
this.spotlightedNotePath = notePath;
await parentNode.load(true);
// Try to find the child again after reload
foundChildNode = this.findChildNode(parentNode, childNoteId);
this.spotlightedNode = foundChildNode ?? null;
if (!foundChildNode) {
if (logErrors || !childNote) {
ws.logError(
`Can't find node for child node of noteId=${childNoteId} for parent of noteId=${parentNode.data.noteId} and hoistedNoteId=${hoistedNoteService.getHoistedNoteId()}, requested path is ${notePath}`
);
return;
}
return;
if (!childNote || childNote.type !== "image") {
ws.logError(
`Can't find node for child node of noteId=${childNoteId} for parent of noteId=${parentNode.data.noteId} and hoistedNoteId=${hoistedNoteService.getHoistedNoteId()}, requested path is ${notePath}`
);
}
parentNode = foundChildNode;
continue;
}
// besides real errors, this can be also caused by hiding of e.g. included images
// these are real notes with real notePath, user can display them in a detail,
// but they don't have a node in the tree
if (logErrors || !childNote) {
ws.logError(
`Can't find node for child node of noteId=${childNoteId} for parent of noteId=${parentNode.data.noteId} and hoistedNoteId=${hoistedNoteService.getHoistedNoteId()}, requested path is ${notePath}`
);
return;
}
return;
@@ -1066,7 +1108,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
}
findChildNode(parentNode: Fancytree.FancytreeNode, childNoteId: string) {
return parentNode.getChildren()?.find((childNode) => childNode.data.noteId === childNoteId);
return parentNode.getChildren().find((childNode) => childNode.data.noteId === childNoteId);
}
async expandToNote(notePath: string, logErrors = true) {
@@ -1107,20 +1149,12 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
(!treeService.isNotePathInHiddenSubtree(this.noteContext.notePath) || (await hoistedNoteService.isHoistedInHiddenSubtree())) &&
(await this.getNodeFromPath(this.noteContext.notePath));
if (this.spotlightedNode && newActiveNode !== this.spotlightedNode) {
// Can get removed when switching to another note in a spotlighted subtree.
if (this.spotlightedNode.parent) {
this.spotlightedNode.remove();
}
this.spotlightedNode = null;
this.spotlightedNotePath = null;
}
if (newActiveNode !== oldActiveNode) {
let oldActiveNodeFocused = false;
if (oldActiveNode) {
oldActiveNodeFocused = oldActiveNode.hasFocus();
oldActiveNode.setActive(false);
oldActiveNode.setFocus(false);
}
@@ -1223,18 +1257,10 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
const { movedActiveNode, parentsOfAddedNodes } = await this.#processBranchRows(branchRows, refreshCtx);
for (const noteId of loadResults.getNoteIds()) {
const contentReloaded = loadResults.isNoteContentReloaded(noteId);
if (contentReloaded && !loadResults.isNoteReloaded(noteId, contentReloaded.componentId)) {
// Only the note content was reloaded, not the note itself. This would cause a redundant update on every few seconds while editing a note.
continue;
}
refreshCtx.noteIdsToUpdate.add(noteId);
}
if (refreshCtx.noteIdsToUpdate.size + refreshCtx.noteIdsToReload.size > 0) {
await this.#executeTreeUpdates(refreshCtx, loadResults);
}
await this.#executeTreeUpdates(refreshCtx, loadResults);
await this.#setActiveNode(activeNotePath, activeNodeFocused, movedActiveNode, parentsOfAddedNodes);
@@ -1254,7 +1280,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
} else {
refreshCtx.noteIdsToUpdate.add(attrRow.noteId);
}
} else if (attrRow.type === "label" && (attrRow.name === "archived" || attrRow.name === "subtreeHidden") && attrRow.noteId) {
} else if (attrRow.type === "label" && attrRow.name === "archived" && attrRow.noteId) {
const note = froca.getNoteFromCache(attrRow.noteId);
if (note) {
@@ -1339,34 +1365,18 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
} else if (frocaBranch) {
// make sure it's loaded
// we're forcing lazy since it's not clear if the whole required subtree is in froca
if (!parentNode.data.subtreeHidden) {
const newNode = this.prepareNode(frocaBranch, true);
if (newNode) {
parentNode.addChildren([newNode]);
}
if (frocaBranch?.isExpanded && note && note.hasChildren()) {
refreshCtx.noteIdsToReload.add(frocaBranch.noteId);
}
this.sortChildren(parentNode);
} else if (branchRow.componentId === this.componentId) {
// Display the toast and focus to parent note only if we know for sure that the operation comes from the tree.
const parentNote = froca.getNoteFromCache(parentNode.data.noteId || "");
toastService.showPersistent({
id: `subtree-hidden-moved`,
title: t("note_tree.subtree-hidden-moved-title", { title: parentNote?.title }),
message: parentNote?.type === "book"
? t("note_tree.subtree-hidden-moved-description-collection")
: t("note_tree.subtree-hidden-moved-description-other"),
icon: "bx bx-hide",
timeout: 5_000,
});
parentNode.setActive(true);
const newNode = this.prepareNode(frocaBranch, true);
if (newNode) {
parentNode.addChildren([newNode]);
}
if (frocaBranch?.isExpanded && note && note.hasChildren()) {
refreshCtx.noteIdsToReload.add(frocaBranch.noteId);
}
this.sortChildren(parentNode);
// this might be a first child which would force an icon change
// also update the count if the subtree is hidden.
if (branchRow.parentNoteId) {
refreshCtx.noteIdsToUpdate.add(branchRow.parentNoteId);
}
@@ -1382,7 +1392,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
}
async #executeTreeUpdates(refreshCtx: RefreshContext, loadResults: LoadResults) {
const performUpdates = async () => {
await this.batchUpdate(async () => {
for (const noteId of refreshCtx.noteIdsToReload) {
for (const node of this.getNodesByNoteId(noteId)) {
await node.load(true);
@@ -1398,19 +1408,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
}
}
}
};
if (refreshCtx.noteIdsToReload.size + refreshCtx.noteIdsToUpdate.size >= BATCH_UPDATE_THRESHOLD) {
/**
* Batch updates are used for large number of updates to prevent multiple re-renders, however in the context of small updates (such as changing a note title)
* it can cause up to 400ms of delay for ~8k notes which is not acceptable. Therefore we use batching only for larger number of updates.
* Without batching, the updates would take a couple of milliseconds.
* We still keep the batching for potential cases where there are many updates, for example in a sync.
*/
await this.batchUpdate(performUpdates);
} else {
await performUpdates();
}
});
// for some reason, node update cannot be in the batchUpdate() block (node is not re-rendered)
for (const noteId of refreshCtx.noteIdsToUpdate) {
@@ -1674,7 +1672,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
const toNode = node.getPrevSibling();
if (toNode !== null) {
branchService.moveToParentNote([node.data.branchId], toNode.data.branchId, this.componentId);
branchService.moveToParentNote([node.data.branchId], toNode.data.branchId);
}
}
@@ -1811,12 +1809,12 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
#moveLaunchers(selectedOrActiveBranchIds: string[], desktopParent: string, mobileParent: string) {
const desktopLaunchersToMove = selectedOrActiveBranchIds.filter((branchId) => !branchId.startsWith("_lbMobile"));
if (desktopLaunchersToMove) {
branchService.moveToParentNote(desktopLaunchersToMove, `_lbRoot_${ desktopParent}`, this.componentId);
branchService.moveToParentNote(desktopLaunchersToMove, `_lbRoot_${ desktopParent}`);
}
const mobileLaunchersToMove = selectedOrActiveBranchIds.filter((branchId) => branchId.startsWith("_lbMobile"));
if (mobileLaunchersToMove) {
branchService.moveToParentNote(mobileLaunchersToMove, `_lbMobileRoot_${mobileParent}`, this.componentId);
branchService.moveToParentNote(mobileLaunchersToMove, `_lbMobileRoot_${ mobileParent}`);
}
}
@@ -1884,112 +1882,3 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
return items;
}
}
function buildEnhanceTitle() {
const createChildTemplate = document.createElement("span");
createChildTemplate.className = "tree-item-button tn-icon add-note-button bx bx-plus";
createChildTemplate.title = t("note_tree.create-child-note");
return async function enhanceTitle(event: Event,
data: {
node: Fancytree.FancytreeNode;
noteId: string;
}) {
const node = data.node;
if (!node.data.noteId) {
// if there's "non-note" node, then don't enhance
// this can happen for e.g. "Load error!" node
return;
}
const note = froca.getNoteFromCache(node.data.noteId);
if (!note) return;
const activeNoteContext = appContext.tabManager.getActiveContext();
const $span = $(node.span);
$span.find(".tree-item-button").remove();
$span.find(".note-indicator-icon").remove();
const isHoistedNote = activeNoteContext && activeNoteContext.hoistedNoteId === note.noteId && note.noteId !== "root";
if (note.hasLabel("workspace") && !isHoistedNote) {
const $enterWorkspaceButton = $(`<span class="tree-item-button tn-icon enter-workspace-button bx bx-door-open" title="${t("note_tree.hoist-this-note-workspace")}"></span>`).on(
"click",
cancelClickPropagation
);
$span.append($enterWorkspaceButton);
}
if (note.type === "search") {
const $refreshSearchButton = $(`<span class="tree-item-button tn-icon refresh-search-button bx bx-refresh" title="${t("note_tree.refresh-saved-search-results")}"></span>`).on(
"click",
cancelClickPropagation
);
$span.append($refreshSearchButton);
}
// TODO: Deduplicate with server's notes.ts#getAndValidateParent
const isSubtreeHidden = note.isLabelTruthy("subtreeHidden");
if (!["search", "launcher"].includes(note.type)
&& !note.isOptions()
&& !note.isLaunchBarConfig()
&& !note.noteId.startsWith("_help")
&& !isSubtreeHidden
&& !node.extraClasses.includes("spotlighted-node")
) {
const createChildItem = createChildTemplate.cloneNode();
createChildItem.addEventListener("click", cancelClickPropagation);
node.span.append(createChildItem);
}
if (isHoistedNote) {
const $unhoistButton = $(`<span class="tree-item-button tn-icon unhoist-button bx bx-door-open" title="${t("note_tree.unhoist")}"></span>`).on("click", cancelClickPropagation);
$span.append($unhoistButton);
}
// Add clone indicator with tooltip if note has multiple parents
const parentNotes = note.getParentNotes();
const realParents: FNote[] = [];
for (const parent of parentNotes) {
if (parent.noteId !== "_share" && parent.noteId !== "_lbBookmarks" && parent.type !== "search") {
realParents.push(parent);
}
}
if (realParents.length > 1) {
const parentTitles = realParents.map((p) => p.title).join(", ");
const tooltipText = realParents.length === 2
? t("note_tree.clone-indicator-tooltip-single", { parent: realParents[1].title })
: t("note_tree.clone-indicator-tooltip", { count: realParents.length, parents: parentTitles });
const $cloneIndicator = $(`<span class="note-indicator-icon clone-indicator"></span>`);
$cloneIndicator.attr("title", tooltipText);
$span.find(".fancytree-title").append($cloneIndicator);
}
// Add shared indicator with tooltip if note is shared
if (note.isShared()) {
const shareId = note.getOwnedLabelValue("shareAlias") || note.noteId;
const shareUrl = `${location.origin}${location.pathname}share/${shareId}`;
const tooltipText = t("note_tree.shared-indicator-tooltip-with-url", { url: shareUrl });
const $sharedIndicator = $(`<span class="note-indicator-icon shared-indicator"></span>`);
$sharedIndicator.attr("title", tooltipText);
$span.find(".fancytree-title").append($sharedIndicator);
}
// Add a badge with the number of items if it hides children.
const count = note.getChildNoteIds().length;
if (isSubtreeHidden && count > 0) {
const $badge = $(`<span class="note-indicator-icon subtree-hidden-badge">${count}</span>`);
$badge.attr("title", t("note_tree.subtree-hidden-tooltip", { count }));
$span.find(".fancytree-title").append($badge);
}
};
}

View File

@@ -646,13 +646,17 @@ export function useNoteLabelBoolean(note: FNote | undefined | null, labelName: F
const setter = useCallback((value: boolean) => {
if (note) {
attributes.setBooleanWithInheritance(note, labelName, value);
if (value) {
attributes.setLabel(note.noteId, labelName, "");
} else {
attributes.removeOwnedLabelByName(note, labelName);
}
}
}, [note, labelName]);
}, [note]);
useDebugValue(labelName);
const labelValue = !!note?.isLabelTruthy(labelName);
const labelValue = !!note?.hasLabel(labelName);
return [ labelValue, setter ] as const;
}

View File

@@ -2,14 +2,12 @@ import "./TableOfContents.css";
import { CKTextEditor, ModelElement } from "@triliumnext/ckeditor5";
import clsx from "clsx";
import { useCallback, useEffect, useRef, useState } from "preact/hooks";
import { useCallback, useEffect, useState } from "preact/hooks";
import { t } from "../../services/i18n";
import math from "../../services/math";
import { randomString } from "../../services/utils";
import { useActiveNoteContext, useContentElement, useGetContextData, useIsNoteReadOnly, useNoteProperty, useTextEditor } from "../react/hooks";
import Icon from "../react/Icon";
import RawHtml from "../react/RawHtml";
import RightPanelWidget from "./RightPanelWidget";
//#region Generic impl.
@@ -82,22 +80,6 @@ function TableOfContentsHeading({ heading, scrollToHeading, activeHeadingId }: {
}) {
const [ collapsed, setCollapsed ] = useState(false);
const isActive = heading.id === activeHeadingId;
const contentRef = useRef<HTMLElement>(null);
// Render math equations after component mounts/updates
useEffect(() => {
if (!contentRef.current) return;
const mathElements = contentRef.current.querySelectorAll(".ck-math-tex");
for (const mathEl of mathElements ?? []) {
try {
math.render(mathEl.textContent || "", mathEl as HTMLElement);
} catch (e) {
console.warn("Failed to render math in TOC:", e);
}
}
}, [heading.text]);
return (
<>
<li className={clsx(collapsed && "collapsed", isActive && "active")}>
@@ -108,14 +90,12 @@ function TableOfContentsHeading({ heading, scrollToHeading, activeHeadingId }: {
onClick={() => setCollapsed(!collapsed)}
/>
)}
<RawHtml
containerRef={contentRef}
<span
className="item-content"
onClick={() => scrollToHeading(heading)}
html={heading.text}
/>
>{heading.text}</span>
</li>
{heading.children.length > 0 && (
{heading.children && (
<ol>
{heading.children.map(heading => <TableOfContentsHeading key={heading.id} heading={heading} scrollToHeading={scrollToHeading} activeHeadingId={activeHeadingId} />)}
</ol>
@@ -209,23 +189,9 @@ function extractTocFromTextEditor(editor: CKTextEditor) {
if (type !== "elementStart" || !item.is('element') || !item.name.startsWith('heading')) continue;
const level = Number(item.name.replace( 'heading', '' ));
// Convert model element to view, then to DOM to get HTML
const viewEl = editor.editing.mapper.toViewElement(item);
let text = '';
if (viewEl) {
const domEl = editor.editing.view.domConverter.mapViewToDom(viewEl);
if (domEl instanceof HTMLElement) {
text = domEl.innerHTML;
}
}
// Fallback to plain text if conversion fails
if (!text) {
text = Array.from( item.getChildren() )
.map( c => c.is( '$text' ) ? c.data : '' )
.join( '' );
}
const text = Array.from( item.getChildren() )
.map( c => c.is( '$text' ) ? c.data : '' )
.join( '' );
// Assign a unique ID
let tocId = item.getAttribute(TOC_ID) as string | undefined;

View File

@@ -15,8 +15,6 @@
.note-detail-split .note-detail-split-editor {
width: 100%;
flex-grow: 1;
min-width: 0;
min-height: 0;
}
.note-detail-split .note-detail-split-editor .note-detail-code {
@@ -32,7 +30,6 @@
margin: 5px;
white-space: pre-wrap;
font-size: 0.85em;
overflow: auto;
}
.note-detail-split .note-detail-split-preview {

View File

@@ -1,16 +1,15 @@
import { buildExtraCommands, type EditorConfig, getCkLocale, loadPremiumPlugins, TemplateDefinition } from "@triliumnext/ckeditor5";
import emojiDefinitionsUrl from "@triliumnext/ckeditor5/src/emoji_definitions/en.json?url";
import { ALLOWED_PROTOCOLS, DISPLAYABLE_LOCALE_IDS, MIME_TYPE_AUTO } from "@triliumnext/commons";
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
import { buildExtraCommands, type EditorConfig, getCkLocale, PREMIUM_PLUGINS, TemplateDefinition } from "@triliumnext/ckeditor5";
import { getHighlightJsNameForMime } from "../../../services/mime_types.js";
import options from "../../../services/options.js";
import { ensureMimeTypesForHighlighting, isSyntaxHighlightEnabled } from "../../../services/syntax_highlight.js";
import emojiDefinitionsUrl from "@triliumnext/ckeditor5/src/emoji_definitions/en.json?url";
import { copyTextWithToast } from "../../../services/clipboard_ext.js";
import { t } from "../../../services/i18n.js";
import { getMermaidConfig } from "../../../services/mermaid.js";
import { getHighlightJsNameForMime } from "../../../services/mime_types.js";
import mimeTypesService from "../../../services/mime_types.js";
import noteAutocompleteService, { type Suggestion } from "../../../services/note_autocomplete.js";
import options from "../../../services/options.js";
import { ensureMimeTypesForHighlighting, isSyntaxHighlightEnabled } from "../../../services/syntax_highlight.js";
import mimeTypesService from "../../../services/mime_types.js";
import { normalizeMimeTypeForCKEditor } from "@triliumnext/commons";
import { buildToolbarConfig } from "./toolbar.js";
export const OPEN_SOURCE_LICENSE_KEY = "GPL";
@@ -37,7 +36,7 @@ export async function buildConfig(opts: BuildEditorOptions): Promise<EditorConfi
engine: "katex",
outputType: "span", // or script
lazyLoad: async () => {
(window as any).katex = (await import("../../../services/math.js")).default;
(window as any).katex = (await import("../../../services/math.js")).default
},
forceOutputType: false, // forces output to use outputType
enablePreview: true // Enable preview view
@@ -173,7 +172,7 @@ export async function buildConfig(opts: BuildEditorOptions): Promise<EditorConfi
config.language = {
ui: (typeof config.language === "string" ? config.language : "en"),
content: contentLanguage
};
}
}
// Mention customisation.
@@ -196,9 +195,11 @@ export async function buildConfig(opts: BuildEditorOptions): Promise<EditorConfi
};
}
// Enable premium plugins dynamically to avoid eager loading.
// Enable premium plugins.
if (hasPremiumLicense) {
config.extraPlugins = await loadPremiumPlugins();
config.extraPlugins = [
...PREMIUM_PLUGINS
];
}
return {
@@ -236,7 +237,7 @@ function getLicenseKey() {
}
function getDisabledPlugins() {
const disabledPlugins: string[] = [];
let disabledPlugins: string[] = [];
if (options.get("textNoteEmojiCompletionEnabled") !== "true") {
disabledPlugins.push("EmojiMention");

View File

@@ -1,22 +1,24 @@
/// <reference types='vitest' />
import prefresh from '@prefresh/vite';
import { join } from 'path';
import webpackStatsPlugin from 'rollup-plugin-webpack-stats';
import { defineConfig } from 'vite';
import { join, resolve } from 'path';
import { defineConfig, type Plugin } from 'vite';
import { viteStaticCopy } from 'vite-plugin-static-copy'
import webpackStatsPlugin from 'rollup-plugin-webpack-stats';
import preact from "@preact/preset-vite";
const assets = [ "assets", "stylesheets", "fonts", "translations" ];
const isDev = process.env.NODE_ENV === "development";
let plugins: any = [];
let plugins: any = [
preact({
babel: {
compact: !isDev
}
})
];
if (isDev) {
// Add Prefresh for Preact HMR in development
plugins = [
prefresh()
];
} else {
if (!isDev) {
plugins = [
...plugins,
viteStaticCopy({
targets: assets.map((asset) => ({
src: `src/${asset}/*`,
@@ -38,19 +40,9 @@ if (isDev) {
export default defineConfig(() => ({
root: __dirname,
cacheDir: '../../.cache/vite',
cacheDir: '../../node_modules/.vite/apps/client',
base: "",
plugins,
// Use esbuild for JSX transformation (much faster than Babel)
esbuild: {
jsx: 'automatic',
jsxImportSource: 'preact',
jsxDev: isDev
},
css: {
transformer: 'lightningcss',
devSourcemap: isDev
},
resolve: {
alias: [
{
@@ -70,20 +62,6 @@ export default defineConfig(() => ({
"preact/hooks"
]
},
optimizeDeps: {
include: [
"ckeditor5-premium-features",
"ckeditor5",
"mathlive",
"@triliumnext/ckeditor5-math",
"@triliumnext/ckeditor5-mermaid",
"@triliumnext/ckeditor5-admonition",
"@triliumnext/ckeditor5-footnotes",
"@triliumnext/ckeditor5-keyboard-marker",
"@triliumnext/codemirror",
"@triliumnext/highlightjs"
]
},
build: {
target: "esnext",
outDir: './dist',

View File

@@ -1,6 +1,6 @@
{
"name": "@triliumnext/desktop",
"version": "0.101.3",
"version": "0.101.1",
"description": "Build your personal knowledge base with Trilium Notes",
"private": true,
"main": "src/main.ts",

View File

@@ -1,5 +1,4 @@
import { expect,test } from "@playwright/test";
import { test, expect } from "@playwright/test";
import App from "../support/app";
const NOTE_TITLE = "Trilium Integration Test DB";
@@ -66,21 +65,21 @@ test("Tabs are restored in right order", async ({ page, context }) => {
// Open three tabs.
await app.closeAllTabs();
await app.goToNoteInNewTab("Code notes");
await expect(app.getActiveTab()).toContainText("Code notes");
await app.addNewTab();
await app.goToNoteInNewTab("Text notes");
await expect(app.getActiveTab()).toContainText("Text notes");
await app.addNewTab();
await app.goToNoteInNewTab("Mermaid");
await expect(app.getActiveTab()).toContainText("Mermaid");
// Select the mid one.
await app.getTab(1).click();
await expect(app.noteTreeActiveNote).toContainText("Text notes");
await expect(app.getTab(0)).toContainText("Code notes");
await expect(app.getTab(1)).toContainText("Text notes");
await expect(app.getTab(2)).toContainText("Mermaid");
// Refresh the page and check the order.
await app.goto( { preserveTabs: true });
await expect(app.getTab(0)).toContainText("Code notes");
await expect(app.getTab(0)).toContainText("Code notes", { timeout: 15_000 });
await expect(app.getTab(1)).toContainText("Text notes");
await expect(app.getTab(2)).toContainText("Mermaid");
@@ -129,8 +128,8 @@ test("New tab displays workspaces", async ({ page, context }) => {
const workspaceNotesEl = app.currentNoteSplitContent.locator(".workspace-notes");
await expect(workspaceNotesEl).toBeVisible();
await expect(workspaceNotesEl).toContainText("Personal");
await expect(workspaceNotesEl).toContainText("Work");
expect(workspaceNotesEl).toContainText("Personal");
expect(workspaceNotesEl).toContainText("Work");
await expect(workspaceNotesEl.locator(".bx.bxs-user")).toBeVisible();
await expect(workspaceNotesEl.locator(".bx.bx-briefcase-alt")).toBeVisible();

View File

@@ -1,12 +1,12 @@
import test, { expect, Page } from "@playwright/test";
import test, { BrowserContext, expect, Page } from "@playwright/test";
import App from "../support/app";
test.beforeEach(async ({ page, context }) => {
const app = new App(page, context);
await app.goto();
const app = await setLayout({ page, context }, true);
await app.setOption("rightPaneCollapsedItems", "[]");
});
test.afterEach(async ({ page, context }) => await setLayout({ page, context }, false));
test("Table of contents works", async ({ page, context }) => {
const app = new App(page, context);
@@ -73,15 +73,13 @@ test("Attachments listing works", async ({ page, context }) => {
test("Download original PDF works", async ({ page, context }) => {
const app = new App(page, context);
await app.goto();
await app.goToNoteInNewTab("Layers test.pdf");
await app.goToNoteInNewTab("Dacia Logan.pdf");
const pdfHelper = new PdfHelper(app);
await pdfHelper.toBeInitialized();
const downloadButton = app.currentNoteSplit.locator(".icon-action.bx.bx-download");
await expect(downloadButton).toBeVisible();
const [ download ] = await Promise.all([
page.waitForEvent("download"),
downloadButton.click()
app.currentNoteSplit.locator(".icon-action.bx.bx-download").click()
]);
expect(download).toBeDefined();
});
@@ -107,6 +105,13 @@ test("Layers listing works", async ({ page, context }) => {
await expect(layersList.locator(".pdf-layer-item")).toHaveCount(0);
});
async function setLayout({ page, context}: { page: Page; context: BrowserContext }, newLayout: boolean) {
const app = new App(page, context);
await app.goto();
await app.setOption("newLayout", newLayout ? "true" : "false");
return app;
}
class PdfHelper {
private contentFrame: ReturnType<Page["frameLocator"]>;
@@ -120,6 +125,5 @@ class PdfHelper {
async toBeInitialized() {
await expect(this.contentFrame.locator("#pageNumber")).toBeVisible();
await expect(this.contentFrame.locator(".page")).toBeVisible();
}
}

View File

@@ -1,5 +1,4 @@
import { expect, test } from "@playwright/test";
import { test, expect, Page } from "@playwright/test";
import App from "../support/app";
test("Table of contents is displayed", async ({ page, context }) => {
@@ -9,7 +8,7 @@ test("Table of contents is displayed", async ({ page, context }) => {
await app.goToNoteInNewTab("Table of contents");
await expect(app.sidebar).toContainText("Table of Contents");
const rootList = app.sidebar.locator(".toc > ol");
const rootList = app.sidebar.locator(".toc-widget > span > ol");
// Heading 1.1
// Heading 1.1
@@ -43,7 +42,7 @@ test("Highlights list is displayed", async ({ page, context }) => {
await app.closeAllTabs();
await app.goToNoteInNewTab("Highlights list");
await expect(app.sidebar).toContainText("10 highlights");
await expect(app.sidebar).toContainText("Highlights List");
const rootList = app.sidebar.locator(".highlights-list ol");
let index = 0;
for (const highlightedEl of ["Bold 1", "Italic 1", "Underline 1", "Colored text 1", "Background text 1", "Bold 2", "Italic 2", "Underline 2", "Colored text 2", "Background text 2"]) {
@@ -65,8 +64,6 @@ test("Displays math popup", async ({ page, context }) => {
await expect(mathForm).toBeVisible();
const input = mathForm.locator(".ck-input").first();
await expect(input).toBeVisible();
await expect(input).toBeEnabled();
await input.click();
await input.fill("e=mc^2");
await page.waitForTimeout(100);

View File

@@ -37,7 +37,7 @@ export default class App {
this.noteTreeHoistedNote = this.noteTree.locator(".fancytree-node", { has: page.locator(".unhoist-button") });
this.launcherBar = page.locator("#launcher-container");
this.currentNoteSplit = page.locator(".note-split:not(.hidden-ext)");
this.currentNoteSplitTitle = this.currentNoteSplit.locator(".note-title").first();
this.currentNoteSplitTitle = this.currentNoteSplit.locator(".note-title");
this.currentNoteSplitContent = this.currentNoteSplit.locator(".note-detail-printable.visible");
this.sidebar = page.locator("#right-pane");
}
@@ -68,15 +68,13 @@ export default class App {
async goToNoteInNewTab(noteTitle: string) {
const autocomplete = this.currentNoteSplit.locator(".note-autocomplete");
await expect(autocomplete).toBeVisible();
await autocomplete.fill(noteTitle);
const resultsSelector = this.currentNoteSplit.locator(".note-detail-empty-results");
await expect(resultsSelector).toContainText(noteTitle);
const suggestionSelector = resultsSelector.locator(".aa-suggestion")
.nth(1); // Select the second one (best candidate), as the first one is "Create a new note"
await expect(suggestionSelector).toContainText(noteTitle);
suggestionSelector.click();
await resultsSelector.locator(".aa-suggestion", { hasText: noteTitle })
.nth(1) // Select the second one, as the first one is "Create a new note"
.click();
}
async goToSettings() {

View File

@@ -1,6 +1,6 @@
{
"name": "@triliumnext/server",
"version": "0.101.3",
"version": "0.101.1",
"description": "The server-side component of TriliumNext, which exposes the client via the web, allows for sync and provides a REST API for both internal and external use.",
"private": true,
"main": "./src/main.ts",
@@ -38,6 +38,7 @@
"@anthropic-ai/sdk": "0.71.2",
"@braintree/sanitize-url": "7.1.1",
"@electron/remote": "2.1.3",
"@preact/preset-vite": "2.10.2",
"@triliumnext/commons": "workspace:*",
"@triliumnext/express-partial-content": "workspace:*",
"@triliumnext/highlightjs": "workspace:*",

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -1,95 +0,0 @@
<figure class="image image-style-align-right">
<img style="aspect-ratio:328/45;" src="1_Hiding the subtree_image.png"
width="328" height="45">
<figcaption>An example of a collection with a relatively large number of children
that are hidden from the tree.</figcaption>
</figure>
<p>The tree works well when the notes are structured in a hierarchy so that
the number of items stays small. When a note has a large number of notes
(in the order of thousands or tens of thousands), two problems arise:</p>
<ul>
<li data-list-item-id="e536c86d371061c12f76f7de2a0af67be">Navigating between notes becomes cumbersome and the tree itself gets cluttered
with a large amount of notes.</li>
<li data-list-item-id="ecc37d6c4d0430254e98615842b94429d">The large amount of notes can slow down the application considerably.</li>
</ul>
<p>Since v0.102.0, Trilium allows the tree to hide the child notes of particular
notes. This works for both&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/_help_GTwFsgaA0lCt">Collections</a>&nbsp;and
normal notes.</p>
<h2>Interaction</h2>
<p>When the subtree of a note is hidden, there are a few subtle changes:</p>
<ul>
<li data-list-item-id="ec1ce3d2030f36e4847f3bbd9468d28e3">To indicate that the subtree is hidden, the note will not have an expand
button and it will display the number of children to the right.</li>
<li
data-list-item-id="ea99d38ea6c8a816cf2ab7a7e73cfcac5">It's not possible to add a new note directly from the tree.
<ul>
<li data-list-item-id="ef0132a903a11e9f667b2b2f4c4fff17a">For&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/_help_GTwFsgaA0lCt">Collections</a>,
it's best to use the built-in mechanism to create notes (for example by
creating a new point on a geo-map, or by adding a new row in a table).</li>
<li
data-list-item-id="e7db44100046c8c79bf79841285aacd1f">For normal notes, it's still possible to create children via other means
such as using the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/KSZ04uQ2D1St/iPIMuisry3hd/QEAPj01N5f7w/_help_hrZ1D00cLbal">Internal (reference) links</a>&nbsp;system.</li>
</ul>
</li>
<li data-list-item-id="eb049f46cf91db6de113af1099a14944e">Notes can be dragged from outside the note, case in which they will be
cloned into it.
<ul>
<li data-list-item-id="e96d9b7a0755e9c054bab5db4fc1aa25e">Instead of switching to the child notes that were copied, the parent note
is highlighted instead.</li>
<li data-list-item-id="ec667e3f94a0cfa3fa41ce38d3ed6ee95">A notification will indicate this behavior.</li>
</ul>
</li>
<li data-list-item-id="eb64670dd7ace6764c18602b440f88049">Similarly, features such as cut/copy and then paste into the note will
also work.</li>
</ul>
<h2>Spotlighting</h2>
<figure class="image image-style-align-right">
<img style="aspect-ratio:322/83;" src="Hiding the subtree_image.png"
width="322" height="83">
</figure>
<p>Even if the subtree of a note is hidden, if a child note manages to become
active, it will still appear inside the tree in a special state called <em>spotlighted</em>.</p>
<p>During this state, the note remains under its normal hierarchy, so that
its easy to tell its location. In addition, this means that:</p>
<ul>
<li data-list-item-id="e2490369eb3d99ca694dba23a3410abef">The note position is clearly visible when using the&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/wArbEsdSae6g/_help_eIg8jdvaoNNd">Search</a>.</li>
<li
data-list-item-id="e041d3807f80dc77b022540b0551b8376">The note can still be operated on from the tree, such as adding a&nbsp;
<a
class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/BFs8mudNFgCS/IakOLONlIfGI/_help_TBwsyfadTA18">Branch prefix</a>&nbsp;or moving it outside the collection.</li>
</ul>
<p>The note appears in italics to indicate its temporary display. When switching
to another note, the spotlighted note will disappear.</p>
<aside class="admonition note">
<p>Only one note can be highlighted at the time. When working with multiple
notes such as dragging them into the collection, no note will be spotlighted.
This is intentional to avoid displaying a partial state of the subtree.</p>
</aside>
<h2>Working with collections</h2>
<p>By default, some of the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/_help_GTwFsgaA0lCt">Collections</a>&nbsp;will
automatically hide their child notes, for example the&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/GTwFsgaA0lCt/_help_CtBQqbwXDx1w">Kanban Board</a>&nbsp;or
the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/GTwFsgaA0lCt/_help_2FvYrpmOXm29">Table</a>.</p>
<p>The reasoning behind this is that collections are generally opaque to
the rest of the notes and they can generate a large amount of sub-notes
since they intentionally lack structure (in order to allow easy swapping
between views).</p>
<p>Some types of collections have the child notes intentionally shown, for
example the legacy ones (Grid and List), but also the&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/GTwFsgaA0lCt/_help_zP3PMqaG71Ct">Presentation</a>&nbsp;which
requires the tree structure in order to organize and edit the slides.</p>
<p>To toggle this behavior:</p>
<ul>
<li data-list-item-id="e6d8c8c98802d70f13df626ea1f062122">In the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_IjZS7iK5EXtb">New Layout</a>,
press the Options button underneath the title and uncheck <em>Hide child notes in tree</em>.</li>
<li
data-list-item-id="e2398432e127c54239d679a6b13d8390b">Right click the collection note in the&nbsp;<a class="reference-link"
href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_oPVyFC7WL2Lp">Note Tree</a>&nbsp;and
select <em>Advanced</em><em>Show subtree</em>.</li>
</ul>
<h2>Working with normal notes</h2>
<p>It's possible to hide the subtree for normal notes as well, not just collections.
To do so, right click the note in the&nbsp;<a class="reference-link" href="#root/pOsGYCXsbNQG/gh7bpGYxajRS/Vc8PjrjAGuOp/_help_oPVyFC7WL2Lp">Note Tree</a>&nbsp;and
select <em>Advanced</em><em>Hide subtree.</em>
</p>

View File

@@ -47,7 +47,7 @@
href="#root/_help_tAassRL4RSQL">data directory</a>in the <code spellcheck="false">TRILIUM_DATA_DIR</code> environment
variable and separate port on <code spellcheck="false">TRILIUM_PORT</code> environment
variable. How to do that depends on the platform, in Unix-based systems
you can achieve that by running command such as this:</p><pre><code class="language-text-x-sh">TRILIUM_DATA_DIR=/home/me/path/to/data/dir TRILIUM_PORT=12345 trilium </code></pre>
you can achieve that by running command such as this:</p><pre><code class="language-text-x-trilium-auto">TRILIUM_DATA_DIR=/home/me/path/to/data/dir TRILIUM_PORT=12345 trilium </code></pre>
<p>You can save this command into a <code spellcheck="false">.sh</code> script
file or make an alias. Do this similarly for a second instance with different
data directory and port.</p>

View File

@@ -26,8 +26,10 @@ async function register(app: express.Application) {
const vite = await createViteServer({
server: { middlewareMode: true },
appType: "custom",
configFile: path.join(clientDir, "vite.config.mts"),
base: `/${assetUrlFragment}/`
cacheDir: path.join(srcRoot, "../../.cache/vite"),
base: `/${assetUrlFragment}/`,
root: clientDir,
css: { devSourcemap: true }
});
app.use(`/${assetUrlFragment}/`, (req, res, next) => {
req.url = `/${assetUrlFragment}${req.url}`;

View File

@@ -1,12 +1,7 @@
import { HiddenSubtreeAttribute, HiddenSubtreeItem } from "@triliumnext/commons";
import { HiddenSubtreeItem } from "@triliumnext/commons";
import { t } from "i18next";
export default function buildHiddenSubtreeTemplates() {
const hideSubtreeAttributes: HiddenSubtreeAttribute = {
name: "subtreeHidden",
type: "label"
};
const templates: HiddenSubtreeItem = {
id: "_templates",
title: t("hidden_subtree_templates.built-in-templates"),
@@ -98,7 +93,6 @@ export default function buildHiddenSubtreeTemplates() {
name: "hidePromotedAttributes",
type: "label"
},
hideSubtreeAttributes,
{
name: "label:startDate",
type: "label",
@@ -139,7 +133,6 @@ export default function buildHiddenSubtreeTemplates() {
name: "collection",
type: "label"
},
hideSubtreeAttributes,
{
name: "viewType",
type: "label",
@@ -170,7 +163,6 @@ export default function buildHiddenSubtreeTemplates() {
name: "hidePromotedAttributes",
type: "label"
},
hideSubtreeAttributes,
{
name: "label:geolocation",
type: "label",
@@ -202,7 +194,6 @@ export default function buildHiddenSubtreeTemplates() {
name: "hidePromotedAttributes",
type: "label"
},
hideSubtreeAttributes,
{
name: "label:status",
type: "label",

View File

@@ -115,7 +115,7 @@
},
"social_buttons": {
"github": "GitHub",
"github_discussions": "Discusiones de GitHub",
"github_discussions": "GitHub Discussions",
"matrix": "Matrix",
"reddit": "Reddit"
},

View File

@@ -6,9 +6,7 @@
},
"hero_section": {
"title": "अपने विचारों को व्यवस्थित करें। अपना व्यक्तिगत नॉलेज बेस बनाएं।",
"screenshot_alt": "ट्रिलियम नोट्स डेस्कटॉप एप्लिकेशन का स्क्रीनशॉट",
"get_started": "शुरू करें",
"github": "गिटहब"
"screenshot_alt": "ट्रिलियम नोट्स डेस्कटॉप एप्लिकेशन का स्क्रीनशॉट"
},
"organization_benefits": {
"note_structure_title": "नोट संरचना",
@@ -28,67 +26,5 @@
"collections": {
"calendar_title": "कैलेंडर",
"table_title": "टेबल"
},
"download_now": {
"linux_small": "लिनक्स के लिए",
"more_platforms": "अधिक प्लेटफॉर्म और सर्वर सेटअप"
},
"header": {
"get-started": "शुरू करें",
"support-us": "हमें सपोर्ट करें"
},
"social_buttons": {
"github": "गिटहब",
"matrix": "मैट्रिक्स",
"reddit": "रेडिट"
},
"support_us": {
"title": "हमें सपोर्ट करें"
},
"404": {
"description": "आप जो पेज खोज रहे थे वह नहीं मिल पाया। शायद वह डिलीट हो चुका है या यूआरएल (URL) गलत है।"
},
"download_helper_desktop_windows": {
"title_x64": "Windows 64-bit",
"title_arm64": "ARM पर Windows",
"quick_start": "Winget द्वारा इंस्टॉल करने के लिए:",
"download_exe": "इंस्टॉलर (.exe) डाउनलोड करें",
"download_zip": "पोर्टेबल (.zip)"
},
"download_helper_desktop_linux": {
"title_x64": "Linux 64-bit",
"title_arm64": "ARM पर लिनक्स",
"download_deb": ".deb",
"download_rpm": ".rpm",
"download_flatpak": ".flatpak",
"download_zip": "पोर्टेबल (.zip)",
"download_nixpkgs": "nixpkgs"
},
"download_helper_desktop_macos": {
"title_x64": "Intel के लिए macOS",
"title_arm64": "Apple Silicon के लिए macOS",
"description_x64": "macOS Monterey या उसके बाद के वर्ज़न पर चलने वाले Intel-आधारित Macs के लिए।",
"description_arm64": "Apple Silicon Macs के लिए, जैसे कि M1 और M2 चिप्स वाले मॉडल।",
"quick_start": "Homebrew द्वारा इंस्टॉल करने के लिए:",
"download_dmg": "इंस्टॉलर (.dmg) डाउनलोड करें",
"download_homebrew_cask": "Homebrew Cask",
"download_zip": "पोर्टेबल (.zip)"
},
"download_helper_server_docker": {
"title": "Docker द्वारा सेल्फ-होस्टेड",
"description": "Docker कंटेनर का उपयोग करके Windows, Linux या macOS पर आसानी से डिप्लॉय करें।",
"download_ghcr": "ghcr.io"
},
"download_helper_server_linux": {
"title": "Linux पर सेल्फ-होस्टेड",
"description": "ट्रिलियम नोट्स को अपने खुद के सर्वर या VPS पर डिप्लॉय करें, जो अधिकांश डिस्ट्रीब्यूशनो के साथ कम्पेटिबल है।",
"download_tar_x64": "x64 (.tar.xz)",
"download_tar_arm64": "ARM (.tar.xz)",
"download_nixos": "NixOS मॉड्यूल"
},
"download_helper_server_hosted": {
"title": "पेड होस्टिंग",
"download_pikapod": "PikaPods पर सेटअप करें",
"download_triliumcc": "वैकल्पिक रूप से trilium.cc देखें"
}
}

16
docs/README-de.md vendored
View File

@@ -96,8 +96,8 @@ Unsere Dokumentation ist verfügbar in mehreren Formaten:
für eine sicherere Anmeldung
* [Synchronisierung](https://docs.triliumnotes.org/user-guide/setup/synchronization)
mit einem selbst gehosteten Synchronisierungsserver
* Es gibt [Drittanbieter-Dienste für das Hosting von
Synchronisationsservern](https://docs.triliumnotes.org/user-guide/setup/server/cloud-hosting)
* there are [3rd party services for hosting synchronisation
server](https://docs.triliumnotes.org/user-guide/setup/server/cloud-hosting)
* [Freigabe](https://docs.triliumnotes.org/user-guide/advanced-usage/sharing)
(Veröffentlichung) von Notizen im öffentlichen Internet
* Starke
@@ -105,10 +105,10 @@ Unsere Dokumentation ist verfügbar in mehreren Formaten:
mit Granularität pro Notiz
* Skizzieren von Diagrammen basierend auf [Excalidraw](https://excalidraw.com/)
(Notiztyp „Canvas“)
* [Beziehungskarten](https://docs.triliumnotes.org/user-guide/note-types/relation-map)
und
[Notiz-/Link-Karten](https://docs.triliumnotes.org/user-guide/note-types/note-map)
zur Visualisierung von Notizen und ihren Beziehungen
* [Relation
maps](https://docs.triliumnotes.org/user-guide/note-types/relation-map) and
[note/link maps](https://docs.triliumnotes.org/user-guide/note-types/note-map)
for visualizing notes and their relations
* Mindmaps, basierend auf [Mind Elixir](https://docs.mind-elixir.com/)
* [Geokarten](https://docs.triliumnotes.org/user-guide/collections/geomap) mit
Standortmarkierungen und GPX-Tracks
@@ -132,8 +132,8 @@ Unsere Dokumentation ist verfügbar in mehreren Formaten:
einfachen Speichern von Webinhalten
* Anpassbare Benutzeroberfläche (Seitenleisten-Schaltflächen, benutzerdefinierte
Widgets, ...)
* [Metriken](https://docs.triliumnotes.org/user-guide/advanced-usage/metrics)
zusammen mit einem Grafana-Dashboard.
* [Metrics](https://docs.triliumnotes.org/user-guide/advanced-usage/metrics),
along with a Grafana Dashboard.
✨ Weitere Informationen zu TriliumNext findet man in den folgenden
Ressourcen/Communities von Drittanbietern:

19
docs/README-hi.md vendored
View File

@@ -74,13 +74,13 @@ Our documentation is available in multiple formats:
* Rich WYSIWYG note editor including e.g. tables, images and
[math](https://docs.triliumnotes.org/user-guide/note-types/text) with markdown
[autoformat](https://docs.triliumnotes.org/user-guide/note-types/text/markdown-formatting)
* [सोर्स कोड वाले
नोट्स](https://docs.triliumnotes.org/user-guide/note-types/code) को एडिट करने
की सुविधा, जिसमें सिंटैक्स हाइलाइटिंग (syntax highlighting) भी शामिल है
* तेज़ और आसान [नोट्स के बीच
नेविगेशन](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-navigation),
फुल टेक्स्ट सर्च और [नोट
होइस्टिंग](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-hoisting)
* Support for editing [notes with source
code](https://docs.triliumnotes.org/user-guide/note-types/code), including
syntax highlighting
* Fast and easy [navigation between
notes](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-navigation),
full text search and [note
hoisting](https://docs.triliumnotes.org/user-guide/concepts/navigation/note-hoisting)
* Seamless [note
versioning](https://docs.triliumnotes.org/user-guide/concepts/notes/note-revisions)
* Note
@@ -98,8 +98,9 @@ Our documentation is available in multiple formats:
server](https://docs.triliumnotes.org/user-guide/setup/server/cloud-hosting)
* [Sharing](https://docs.triliumnotes.org/user-guide/advanced-usage/sharing)
(publishing) notes to public internet
* प्रति-नोट granularity के साथ मजबूत [नोट
एन्क्रिप्शन](https://docs.triliumnotes.org/user-guide/concepts/notes/protected-notes)
* Strong [note
encryption](https://docs.triliumnotes.org/user-guide/concepts/notes/protected-notes)
with per-note granularity
* Sketching diagrams, based on [Excalidraw](https://excalidraw.com/) (note type
"canvas")
* [Relation

View File

@@ -1,6 +1,6 @@
{
"formatVersion": 2,
"appVersion": "0.101.3",
"appVersion": "0.101.1",
"files": [
{
"isClone": false,
@@ -61,58 +61,6 @@
"attachments": [],
"dirFileName": "Release Notes",
"children": [
{
"isClone": false,
"noteId": "IlBzLeN3MJhw",
"notePath": [
"hD3V4hiu2VW4",
"IlBzLeN3MJhw"
],
"title": "v0.101.3",
"notePosition": 10,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "relation",
"name": "template",
"value": "wyurrlcDl416",
"isInheritable": false,
"position": 60
}
],
"format": "markdown",
"dataFileName": "v0.101.3.md",
"attachments": []
},
{
"isClone": false,
"noteId": "vcBthaXcwAm6",
"notePath": [
"hD3V4hiu2VW4",
"vcBthaXcwAm6"
],
"title": "v0.101.2",
"notePosition": 20,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "relation",
"name": "template",
"value": "wyurrlcDl416",
"isInheritable": false,
"position": 60
}
],
"format": "markdown",
"dataFileName": "v0.101.2.md",
"attachments": []
},
{
"isClone": false,
"noteId": "AgUcrU9nFXuW",
@@ -121,7 +69,7 @@
"AgUcrU9nFXuW"
],
"title": "v0.101.1",
"notePosition": 30,
"notePosition": 10,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -147,7 +95,7 @@
"uYwlZ594eyJu"
],
"title": "v0.101.0",
"notePosition": 40,
"notePosition": 20,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -173,7 +121,7 @@
"iPGKEk7pwJXK"
],
"title": "v0.100.0",
"notePosition": 50,
"notePosition": 30,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -199,7 +147,7 @@
"7HKMTjmopLcM"
],
"title": "v0.99.5",
"notePosition": 60,
"notePosition": 40,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -225,7 +173,7 @@
"RMBaNYPsRpIr"
],
"title": "v0.99.4",
"notePosition": 70,
"notePosition": 50,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -251,7 +199,7 @@
"yuroLztFfpu5"
],
"title": "v0.99.3",
"notePosition": 80,
"notePosition": 60,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -277,7 +225,7 @@
"z207sehwMJ6C"
],
"title": "v0.99.2",
"notePosition": 90,
"notePosition": 70,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -303,7 +251,7 @@
"WGQsXq2jNyTi"
],
"title": "v0.99.1",
"notePosition": 100,
"notePosition": 80,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -329,7 +277,7 @@
"cyw2Yue9vXf3"
],
"title": "v0.99.0",
"notePosition": 110,
"notePosition": 90,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -355,7 +303,7 @@
"QOJwjruOUr4k"
],
"title": "v0.98.1",
"notePosition": 120,
"notePosition": 100,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -381,7 +329,7 @@
"PLUoryywi0BC"
],
"title": "v0.98.0",
"notePosition": 130,
"notePosition": 110,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -407,7 +355,7 @@
"lvOuiWsLDv8F"
],
"title": "v0.97.2",
"notePosition": 140,
"notePosition": 120,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -433,7 +381,7 @@
"OtFZ6Nd9vM3n"
],
"title": "v0.97.1",
"notePosition": 150,
"notePosition": 130,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -459,7 +407,7 @@
"SJZ5PwfzHSQ1"
],
"title": "v0.97.0",
"notePosition": 160,
"notePosition": 140,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -485,7 +433,7 @@
"mYXFde3LuNR7"
],
"title": "v0.96.0",
"notePosition": 170,
"notePosition": 150,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -511,7 +459,7 @@
"jthwbL0FdaeU"
],
"title": "v0.95.0",
"notePosition": 180,
"notePosition": 160,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -537,7 +485,7 @@
"7HGYsJbLuhnv"
],
"title": "v0.94.1",
"notePosition": 190,
"notePosition": 170,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -563,7 +511,7 @@
"Neq53ujRGBqv"
],
"title": "v0.94.0",
"notePosition": 200,
"notePosition": 180,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -589,7 +537,7 @@
"VN3xnce1vLkX"
],
"title": "v0.93.0",
"notePosition": 210,
"notePosition": 190,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -607,7 +555,7 @@
"WRaBfQqPr6qo"
],
"title": "v0.92.7",
"notePosition": 220,
"notePosition": 200,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -633,7 +581,7 @@
"a2rwfKNmUFU1"
],
"title": "v0.92.6",
"notePosition": 230,
"notePosition": 210,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -651,7 +599,7 @@
"fEJ8qErr0BKL"
],
"title": "v0.92.5-beta",
"notePosition": 240,
"notePosition": 220,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -669,7 +617,7 @@
"kkkZQQGSXjwy"
],
"title": "v0.92.4",
"notePosition": 250,
"notePosition": 230,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -687,7 +635,7 @@
"vAroNixiezaH"
],
"title": "v0.92.3-beta",
"notePosition": 260,
"notePosition": 240,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -705,7 +653,7 @@
"mHEq1wxAKNZd"
],
"title": "v0.92.2-beta",
"notePosition": 270,
"notePosition": 250,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -723,7 +671,7 @@
"IykjoAmBpc61"
],
"title": "v0.92.1-beta",
"notePosition": 280,
"notePosition": 260,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -741,7 +689,7 @@
"dq2AJ9vSBX4Y"
],
"title": "v0.92.0-beta",
"notePosition": 290,
"notePosition": 270,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -759,7 +707,7 @@
"3a8aMe4jz4yM"
],
"title": "v0.91.6",
"notePosition": 300,
"notePosition": 280,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -777,7 +725,7 @@
"8djQjkiDGESe"
],
"title": "v0.91.5",
"notePosition": 310,
"notePosition": 290,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -795,7 +743,7 @@
"OylxVoVJqNmr"
],
"title": "v0.91.4-beta",
"notePosition": 320,
"notePosition": 300,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -813,7 +761,7 @@
"tANGQDvnyhrj"
],
"title": "v0.91.3-beta",
"notePosition": 330,
"notePosition": 310,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -831,7 +779,7 @@
"hMoBfwSoj1SC"
],
"title": "v0.91.2-beta",
"notePosition": 340,
"notePosition": 320,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -849,7 +797,7 @@
"a2XMSKROCl9z"
],
"title": "v0.91.1-beta",
"notePosition": 350,
"notePosition": 330,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -867,7 +815,7 @@
"yqXFvWbLkuMD"
],
"title": "v0.90.12",
"notePosition": 360,
"notePosition": 340,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -885,7 +833,7 @@
"veS7pg311yJP"
],
"title": "v0.90.11-beta",
"notePosition": 370,
"notePosition": 350,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -903,7 +851,7 @@
"sq5W9TQxRqMq"
],
"title": "v0.90.10-beta",
"notePosition": 380,
"notePosition": 360,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -921,7 +869,7 @@
"yFEGVCUM9tPx"
],
"title": "v0.90.9-beta",
"notePosition": 390,
"notePosition": 370,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -939,7 +887,7 @@
"o4wAGqOQuJtV"
],
"title": "v0.90.8",
"notePosition": 400,
"notePosition": 380,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -972,7 +920,7 @@
"i4A5g9iOg9I0"
],
"title": "v0.90.7-beta",
"notePosition": 410,
"notePosition": 390,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -990,7 +938,7 @@
"ThNf2GaKgXUs"
],
"title": "v0.90.6-beta",
"notePosition": 420,
"notePosition": 400,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -1008,7 +956,7 @@
"G4PAi554kQUr"
],
"title": "v0.90.5-beta",
"notePosition": 430,
"notePosition": 410,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -1035,7 +983,7 @@
"zATRobGRCmBn"
],
"title": "v0.90.4",
"notePosition": 440,
"notePosition": 420,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -1053,7 +1001,7 @@
"sCDLf8IKn3Iz"
],
"title": "v0.90.3",
"notePosition": 450,
"notePosition": 430,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -1071,7 +1019,7 @@
"VqqyBu4AuTjC"
],
"title": "v0.90.2-beta",
"notePosition": 460,
"notePosition": 440,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -1089,7 +1037,7 @@
"RX3Nl7wInLsA"
],
"title": "v0.90.1-beta",
"notePosition": 470,
"notePosition": 450,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -1107,7 +1055,7 @@
"GyueACukPWjk"
],
"title": "v0.90.0-beta",
"notePosition": 480,
"notePosition": 460,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -1125,7 +1073,7 @@
"kzjHexDTTeVB"
],
"title": "v0.48",
"notePosition": 490,
"notePosition": 470,
"prefix": null,
"isExpanded": false,
"type": "text",
@@ -1192,7 +1140,7 @@
"wyurrlcDl416"
],
"title": "Release Template",
"notePosition": 500,
"notePosition": 480,
"prefix": null,
"isExpanded": false,
"type": "text",

View File

@@ -1,22 +0,0 @@
# v0.101.2
> [!NOTE]
> If you are interested in an [official mobile application](https://oss.issuehunt.io/r/TriliumNext/Trilium/issues/7447)  ([#7447](https://github.com/TriliumNext/Trilium/issues/7447)) or [multi-user support](https://oss.issuehunt.io/r/TriliumNext/Trilium/issues/4956) ([#4956](https://github.com/TriliumNext/Trilium/issues/4956)), consider offering financial support via IssueHunt (see links).
> [!IMPORTANT]
> If you enjoyed this release, consider showing a token of appreciation by:
>
> * Pressing the “Star” button on [GitHub](https://github.com/TriliumNext/Trilium) (top-right).
> * Considering a one-time or recurrent donation to the [lead developer](https://github.com/eliandoran) via [GitHub Sponsors](https://github.com/sponsors/eliandoran) or [PayPal](https://paypal.me/eliandoran).
## 🐞 Bugfixes
* [SQL Console: cannot copy table data](https://github.com/TriliumNext/Trilium/pull/8268) by @SiriusXT
* [Title is not selected when creating a note via the launcher](https://github.com/TriliumNext/Trilium/pull/8292) by @SiriusXT
* [Popup editor closing after inserting a note link](https://github.com/TriliumNext/Trilium/pull/8224) by @SiriusXT
* [New Mermaid diagrams do not save content](https://github.com/TriliumNext/Trilium/pull/8220) by @lzinga
* [Can't scroll mermaid diagram code](https://github.com/TriliumNext/Trilium/issues/8299)
* [Max content width is not respected when switching between note types in the same tab](https://github.com/TriliumNext/Trilium/issues/8065)
* [Crash When a Note Includes Itself](https://github.com/TriliumNext/Trilium/issues/8294)
* [Severe Performance Degradation and Crash Issues Due to Recursive Inclusion in Included Notes](https://github.com/TriliumNext/Trilium/issues/8017)
* [<note> is not a launcher even though it's in the launcher subtree](https://github.com/TriliumNext/Trilium/issues/8218)
* [Archived subnotes of direct children appear in grid view without #includeArchived](https://github.com/TriliumNext/Trilium/issues/8184)

View File

@@ -1,24 +0,0 @@
# v0.101.3
> [!NOTE]
> If you are interested in an [official mobile application](https://oss.issuehunt.io/r/TriliumNext/Trilium/issues/7447)  ([#7447](https://github.com/TriliumNext/Trilium/issues/7447)) or [multi-user support](https://oss.issuehunt.io/r/TriliumNext/Trilium/issues/4956) ([#4956](https://github.com/TriliumNext/Trilium/issues/4956)), consider offering financial support via IssueHunt (see links).
> [!IMPORTANT]
> If you enjoyed this release, consider showing a token of appreciation by:
>
> * Pressing the “Star” button on [GitHub](https://github.com/TriliumNext/Trilium) (top-right).
> * Considering a one-time or recurrent donation to the [lead developer](https://github.com/eliandoran) via [GitHub Sponsors](https://github.com/sponsors/eliandoran) or [PayPal](https://paypal.me/eliandoran).
This is a re-release of v0.101.2, which had a cache invalidation issue.
## 🐞 Bugfixes
* [SQL Console: cannot copy table data](https://github.com/TriliumNext/Trilium/pull/8268) by @SiriusXT
* [Title is not selected when creating a note via the launcher](https://github.com/TriliumNext/Trilium/pull/8292) by @SiriusXT
* [Popup editor closing after inserting a note link](https://github.com/TriliumNext/Trilium/pull/8224) by @SiriusXT
* [New Mermaid diagrams do not save content](https://github.com/TriliumNext/Trilium/pull/8220) by @lzinga
* [Can't scroll mermaid diagram code](https://github.com/TriliumNext/Trilium/issues/8299)
* [Max content width is not respected when switching between note types in the same tab](https://github.com/TriliumNext/Trilium/issues/8065)
* [Crash When a Note Includes Itself](https://github.com/TriliumNext/Trilium/issues/8294)
* [Severe Performance Degradation and Crash Issues Due to Recursive Inclusion in Included Notes](https://github.com/TriliumNext/Trilium/issues/8017)
* [is not a launcher even though it's in the launcher subtree](https://github.com/TriliumNext/Trilium/issues/8218)
* [Archived subnotes of direct children appear in grid view without #includeArchived](https://github.com/TriliumNext/Trilium/issues/8184)

View File

@@ -1,6 +1,6 @@
{
"formatVersion": 2,
"appVersion": "0.101.3",
"appVersion": "0.101.1",
"files": [
{
"isClone": false,
@@ -2426,122 +2426,6 @@
"format": "markdown",
"dataFileName": "Keyboard shortcuts.md",
"attachments": []
},
{
"isClone": false,
"noteId": "wyaGBBQrl4i3",
"notePath": [
"pOsGYCXsbNQG",
"gh7bpGYxajRS",
"Vc8PjrjAGuOp",
"oPVyFC7WL2Lp",
"wyaGBBQrl4i3"
],
"title": "Hiding the subtree",
"notePosition": 40,
"prefix": null,
"isExpanded": false,
"type": "text",
"mime": "text/html",
"attributes": [
{
"type": "label",
"name": "shareAlias",
"value": "hiding-subtree",
"isInheritable": false,
"position": 30
},
{
"type": "label",
"name": "iconClass",
"value": "bx bx-hide",
"isInheritable": false,
"position": 40
},
{
"type": "relation",
"name": "internalLink",
"value": "GTwFsgaA0lCt",
"isInheritable": false,
"position": 50
},
{
"type": "relation",
"name": "internalLink",
"value": "CtBQqbwXDx1w",
"isInheritable": false,
"position": 60
},
{
"type": "relation",
"name": "internalLink",
"value": "2FvYrpmOXm29",
"isInheritable": false,
"position": 70
},
{
"type": "relation",
"name": "internalLink",
"value": "IjZS7iK5EXtb",
"isInheritable": false,
"position": 80
},
{
"type": "relation",
"name": "internalLink",
"value": "oPVyFC7WL2Lp",
"isInheritable": false,
"position": 90
},
{
"type": "relation",
"name": "internalLink",
"value": "zP3PMqaG71Ct",
"isInheritable": false,
"position": 100
},
{
"type": "relation",
"name": "internalLink",
"value": "hrZ1D00cLbal",
"isInheritable": false,
"position": 110
},
{
"type": "relation",
"name": "internalLink",
"value": "eIg8jdvaoNNd",
"isInheritable": false,
"position": 120
},
{
"type": "relation",
"name": "internalLink",
"value": "TBwsyfadTA18",
"isInheritable": false,
"position": 130
}
],
"format": "markdown",
"dataFileName": "Hiding the subtree.md",
"attachments": [
{
"attachmentId": "d9Sq9avKDptU",
"title": "image.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "Hiding the subtree_image.png"
},
{
"attachmentId": "VmRtx3vS97v1",
"title": "image.png",
"role": "image",
"mime": "image/png",
"position": 10,
"dataFileName": "1_Hiding the subtree_image.png"
}
]
}
]
},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,55 +0,0 @@
# Hiding the subtree
<figure class="image image-style-align-right"><img style="aspect-ratio:328/45;" src="1_Hiding the subtree_image.png" width="328" height="45"><figcaption>An example of a collection with a relatively large number of children that are hidden from the tree.</figcaption></figure>
The tree works well when the notes are structured in a hierarchy so that the number of items stays small. When a note has a large number of notes (in the order of thousands or tens of thousands), two problems arise:
* Navigating between notes becomes cumbersome and the tree itself gets cluttered with a large amount of notes.
* The large amount of notes can slow down the application considerably.
Since v0.102.0, Trilium allows the tree to hide the child notes of particular notes. This works for both <a class="reference-link" href="../../../Collections.md">Collections</a> and normal notes.
## Interaction
When the subtree of a note is hidden, there are a few subtle changes:
* To indicate that the subtree is hidden, the note will not have an expand button and it will display the number of children to the right.
* It's not possible to add a new note directly from the tree.
* For <a class="reference-link" href="../../../Collections.md">Collections</a>, it's best to use the built-in mechanism to create notes (for example by creating a new point on a geo-map, or by adding a new row in a table).
* For normal notes, it's still possible to create children via other means such as using the <a class="reference-link" href="../../../Note%20Types/Text/Links/Internal%20(reference)%20links.md">Internal (reference) links</a> system.
* Notes can be dragged from outside the note, case in which they will be cloned into it.
* Instead of switching to the child notes that were copied, the parent note is highlighted instead.
* A notification will indicate this behavior.
* Similarly, features such as cut/copy and then paste into the note will also work.
## Spotlighting
<figure class="image image-style-align-right"><img style="aspect-ratio:322/83;" src="Hiding the subtree_image.png" width="322" height="83"></figure>
Even if the subtree of a note is hidden, if a child note manages to become active, it will still appear inside the tree in a special state called _spotlighted_.
During this state, the note remains under its normal hierarchy, so that its easy to tell its location. In addition, this means that:
* The note position is clearly visible when using the <a class="reference-link" href="../../Navigation/Search.md">Search</a>.
* The note can still be operated on from the tree, such as adding a <a class="reference-link" href="../../Notes/Cloning%20Notes/Branch%20prefix.md">Branch prefix</a> or moving it outside the collection.
The note appears in italics to indicate its temporary display. When switching to another note, the spotlighted note will disappear.
> [!NOTE]
> Only one note can be highlighted at the time. When working with multiple notes such as dragging them into the collection, no note will be spotlighted. This is intentional to avoid displaying a partial state of the subtree.
## Working with collections
By default, some of the <a class="reference-link" href="../../../Collections.md">Collections</a> will automatically hide their child notes, for example the <a class="reference-link" href="../../../Collections/Kanban%20Board.md">Kanban Board</a> or the <a class="reference-link" href="../../../Collections/Table.md">Table</a>.
The reasoning behind this is that collections are generally opaque to the rest of the notes and they can generate a large amount of sub-notes since they intentionally lack structure (in order to allow easy swapping between views).
Some types of collections have the child notes intentionally shown, for example the legacy ones (Grid and List), but also the <a class="reference-link" href="../../../Collections/Presentation.md">Presentation</a> which requires the tree structure in order to organize and edit the slides.
To toggle this behavior:
* In the <a class="reference-link" href="../New%20Layout.md">New Layout</a>, press the Options button underneath the title and uncheck _Hide child notes in tree_.
* Right click the collection note in the <a class="reference-link" href="../Note%20Tree.md">Note Tree</a> and select _Advanced__Show subtree_.
## Working with normal notes
It's possible to hide the subtree for normal notes as well, not just collections. To do so, right click the note in the <a class="reference-link" href="../Note%20Tree.md">Note Tree</a> and select _Advanced_ → _Hide subtree._

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -44,7 +44,7 @@ No.
These general purpose sync apps are not suitable to sync database files which are open and being worked on by another application. The result is that they will corrupt the database file, resulting in data loss and this message in the Trilium logs:
```
```plain
SqliteError: database disk image is malformed
```

View File

@@ -1,6 +1,6 @@
{
"name": "@triliumnext/source",
"version": "0.101.3",
"version": "0.101.1",
"description": "Build your personal knowledge base with Trilium Notes",
"directories": {
"doc": "docs"
@@ -90,7 +90,7 @@
"url": "https://github.com/TriliumNext/Trilium/issues"
},
"homepage": "https://triliumnotes.org",
"packageManager": "pnpm@10.28.0",
"packageManager": "pnpm@10.27.0",
"pnpm": {
"patchedDependencies": {
"@ckeditor/ckeditor5-mention": "patches/@ckeditor__ckeditor5-mention.patch",

View File

@@ -1,6 +1,9 @@
import ckeditor from './../theme/icons/math.svg?raw';
import './augmentation.js';
import '../theme/mathform.css';
import "../theme/mathform.css";
import 'mathlive';
import 'mathlive/fonts.css';
import 'mathlive/static.css';
export { default as Math } from './math.js';
export { default as MathUI } from './mathui.js';

View File

@@ -2,7 +2,6 @@
// and keeps them in sync for the CKEditor 5 math dialog.
import { View, type Locale, type FocusableView } from 'ckeditor5';
import 'mathlive/fonts.css'; // Auto-bundles offline fonts
import 'mathlive/static.css'; // Static styles for mathlive
declare global {
interface Window {

View File

@@ -1,12 +1,11 @@
import "ckeditor5/ckeditor5.css";
// Premium features CSS loaded dynamically with the plugins
// import 'ckeditor5-premium-features/ckeditor5-premium-features.css';
import 'ckeditor5-premium-features/ckeditor5-premium-features.css';
import "./theme/code_block_toolbar.css";
import { COMMON_PLUGINS, CORE_PLUGINS, POPUP_EDITOR_PLUGINS } from "./plugins.js";
import { BalloonEditor, DecoupledEditor, FindAndReplaceEditing, FindCommand } from "ckeditor5";
import "./translation_overrides.js";
export { default as EditorWatchdog } from "./custom_watchdog";
export { loadPremiumPlugins } from "./plugins.js";
export { PREMIUM_PLUGINS } from "./plugins.js";
export type { EditorConfig, MentionFeed, MentionFeedObjectItem, ModelNode, ModelPosition, ModelElement, ModelText, WatchdogConfig, WatchdogState } from "ckeditor5";
export type { TemplateDefinition } from "ckeditor5-premium-features";
export { default as buildExtraCommands } from "./extra_slash_commands.js";

View File

@@ -1,6 +1,5 @@
import { Autoformat, AutoLink, BlockQuote, BlockToolbar, Bold, CKFinderUploadAdapter, Clipboard, Code, CodeBlock, Enter, Font, FontBackgroundColor, FontColor, GeneralHtmlSupport, Heading, HeadingButtonsUI, HorizontalLine, Image, ImageCaption, ImageInline, ImageResize, ImageStyle, ImageToolbar, ImageUpload, Alignment, Indent, IndentBlock, Italic, Link, List, ListProperties, Mention, PageBreak, Paragraph, ParagraphButtonUI, PasteFromOffice, PictureEditing, RemoveFormat, SelectAll, ShiftEnter, SpecialCharacters, SpecialCharactersEssentials, Strikethrough, Style, Subscript, Superscript, Table, TableCaption, TableCellProperties, TableColumnResize, TableProperties, TableSelection, TableToolbar, TextPartLanguage, TextTransformation, TodoList, Typing, Underline, Undo, Bookmark, EmojiMention, EmojiPicker, FindAndReplaceEditing } from "ckeditor5";
// Premium features loaded dynamically to improve initial load time
// import { SlashCommand, Template, FormatPainter } from "ckeditor5-premium-features";
import { SlashCommand, Template, FormatPainter } from "ckeditor5-premium-features";
import type { Plugin } from "ckeditor5";
import CutToNotePlugin from "./plugins/cuttonote.js";
import UploadimagePlugin from "./plugins/uploadimage.js";
@@ -82,15 +81,13 @@ export const CORE_PLUGINS: typeof Plugin[] = [
];
/**
* Dynamically loads plugins that require a premium CKEditor license key.
* This avoids loading ~6 seconds of premium features code during initial app startup.
* Plugins that require a premium CKEditor license key to work.
*/
export async function loadPremiumPlugins(): Promise<(typeof Plugin)[]> {
const { SlashCommand, Template, FormatPainter } = await import('ckeditor5-premium-features');
// Also load the CSS when premium features are used
await import('ckeditor5-premium-features/ckeditor5-premium-features.css');
return [SlashCommand, Template, FormatPainter];
}
export const PREMIUM_PLUGINS: typeof Plugin[] = [
SlashCommand,
Template,
FormatPainter
];
/**
* The set of plugins that are required for the editor to work. This is used in normal text editors (floating or fixed toolbar) but not in the attribute editor.

View File

@@ -1,6 +1,6 @@
{
"name": "@triliumnext/commons",
"version": "0.101.3",
"version": "0.101.1",
"description": "Shared library between the clients (e.g. browser, Electron) and the server, mostly for type definitions and utility methods.",
"private": true,
"type": "module",

View File

@@ -22,9 +22,6 @@ type Labels = {
pageUrl: string;
dateNote: string;
// Tree specific
subtreeHidden: boolean;
// Search
searchString: string;
ancestorDepth: string;

View File

@@ -18,5 +18,5 @@ export const ALLOWED_PROTOCOLS = [
'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message',
'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp',
'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero', 'geo',
'logseq', 'mid', 'obsidian'
'mid', 'obsidian'
];

306
pnpm-lock.yaml generated
View File

@@ -54,10 +54,10 @@ importers:
version: 24.10.4
'@vitest/browser-webdriverio':
specifier: 4.0.16
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)(webdriverio@9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)(webdriverio@9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
'@vitest/coverage-v8':
specifier: 4.0.16
version: 4.0.16(@vitest/browser@4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16))(vitest@4.0.16)
version: 4.0.16(@vitest/browser@4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16))(vitest@4.0.16)
'@vitest/ui':
specifier: 4.0.16
version: 4.0.16(vitest@4.0.16)
@@ -105,7 +105,7 @@ importers:
version: 0.18.0
rollup-plugin-webpack-stats:
specifier: 2.1.9
version: 2.1.9(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 2.1.9(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
tslib:
specifier: 2.8.1
version: 2.8.1
@@ -123,13 +123,13 @@ importers:
version: 2.0.1
vite:
specifier: 7.3.0
version: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
version: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite-plugin-dts:
specifier: ~4.5.0
version: 4.5.4(@types/node@24.10.4)(rollup@4.52.0)(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 4.5.4(@types/node@24.10.4)(rollup@4.52.0)(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
vitest:
specifier: 4.0.16
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
apps/build-docs:
devDependencies:
@@ -293,8 +293,8 @@ importers:
specifier: 16.5.1
version: 16.5.1(i18next@25.7.3(typescript@5.9.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.9.3)
react-window:
specifier: 2.2.3
version: 2.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
specifier: 2.2.4
version: 2.2.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
reveal.js:
specifier: 5.2.1
version: 5.2.1
@@ -311,6 +311,9 @@ importers:
'@ckeditor/ckeditor5-inspector':
specifier: 5.0.0
version: 5.0.0
'@preact/preset-vite':
specifier: 2.10.2
version: 2.10.2(@babel/core@7.28.0)(preact@10.28.1)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@types/bootstrap':
specifier: 5.2.10
version: 5.2.10
@@ -338,15 +341,12 @@ importers:
happy-dom:
specifier: 20.0.11
version: 20.0.11
lightningcss:
specifier: 1.30.2
version: 1.30.2
script-loader:
specifier: 0.7.2
version: 0.7.2
vite-plugin-static-copy:
specifier: 3.1.4
version: 3.1.4(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 3.1.4(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
apps/db-compare:
dependencies:
@@ -519,6 +519,9 @@ importers:
'@electron/remote':
specifier: 2.1.3
version: 2.1.3(electron@39.2.7)
'@preact/preset-vite':
specifier: 2.10.2
version: 2.10.2(@babel/core@7.28.0)(preact@10.28.1)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@triliumnext/commons':
specifier: workspace:*
version: link:../../packages/commons
@@ -791,7 +794,7 @@ importers:
version: 1.0.1
vite:
specifier: 7.3.0
version: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
version: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
ws:
specifier: 8.18.3
version: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -831,7 +834,7 @@ importers:
devDependencies:
'@preact/preset-vite':
specifier: 2.10.2
version: 2.10.2(@babel/core@7.28.0)(preact@10.28.1)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 2.10.2(@babel/core@7.28.0)(preact@10.28.1)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
eslint:
specifier: 9.39.2
version: 9.39.2(jiti@2.6.1)
@@ -846,10 +849,10 @@ importers:
version: 0.4.2
vite:
specifier: 7.3.0
version: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
version: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vitest:
specifier: 4.0.16
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
packages/ckeditor5:
dependencies:
@@ -904,7 +907,7 @@ importers:
version: 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 4.0.16
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
'@vitest/coverage-istanbul':
specifier: 4.0.16
version: 4.0.16(vitest@4.0.16)
@@ -937,10 +940,10 @@ importers:
version: 5.9.3
vite-plugin-svgo:
specifier: ~2.0.0
version: 2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
vitest:
specifier: 4.0.16
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
webdriverio:
specifier: 9.23.0
version: 9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -964,7 +967,7 @@ importers:
version: 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 4.0.16
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
'@vitest/coverage-istanbul':
specifier: 4.0.16
version: 4.0.16(vitest@4.0.16)
@@ -997,10 +1000,10 @@ importers:
version: 5.9.3
vite-plugin-svgo:
specifier: ~2.0.0
version: 2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
vitest:
specifier: 4.0.16
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
webdriverio:
specifier: 9.23.0
version: 9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -1024,7 +1027,7 @@ importers:
version: 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 4.0.16
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
'@vitest/coverage-istanbul':
specifier: 4.0.16
version: 4.0.16(vitest@4.0.16)
@@ -1057,10 +1060,10 @@ importers:
version: 5.9.3
vite-plugin-svgo:
specifier: ~2.0.0
version: 2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
vitest:
specifier: 4.0.16
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
webdriverio:
specifier: 9.23.0
version: 9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -1091,7 +1094,7 @@ importers:
version: 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 4.0.16
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
'@vitest/coverage-istanbul':
specifier: 4.0.16
version: 4.0.16(vitest@4.0.16)
@@ -1124,10 +1127,10 @@ importers:
version: 5.9.3
vite-plugin-svgo:
specifier: ~2.0.0
version: 2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
vitest:
specifier: 4.0.16
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
webdriverio:
specifier: 9.23.0
version: 9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -1158,7 +1161,7 @@ importers:
version: 8.51.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)
'@vitest/browser':
specifier: 4.0.16
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
version: 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
'@vitest/coverage-istanbul':
specifier: 4.0.16
version: 4.0.16(vitest@4.0.16)
@@ -1191,10 +1194,10 @@ importers:
version: 5.9.3
vite-plugin-svgo:
specifier: ~2.0.0
version: 2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
version: 2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
vitest:
specifier: 4.0.16
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
version: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
webdriverio:
specifier: 9.23.0
version: 9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
@@ -9946,74 +9949,68 @@ packages:
lie@3.3.0:
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
lightningcss-android-arm64@1.30.2:
resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [android]
lightningcss-darwin-arm64@1.30.2:
resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==}
lightningcss-darwin-arm64@1.30.1:
resolution: {integrity: sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
lightningcss-darwin-x64@1.30.2:
resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==}
lightningcss-darwin-x64@1.30.1:
resolution: {integrity: sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
lightningcss-freebsd-x64@1.30.2:
resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==}
lightningcss-freebsd-x64@1.30.1:
resolution: {integrity: sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
lightningcss-linux-arm-gnueabihf@1.30.2:
resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==}
lightningcss-linux-arm-gnueabihf@1.30.1:
resolution: {integrity: sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
lightningcss-linux-arm64-gnu@1.30.2:
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
lightningcss-linux-arm64-gnu@1.30.1:
resolution: {integrity: sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-arm64-musl@1.30.2:
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
lightningcss-linux-arm64-musl@1.30.1:
resolution: {integrity: sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-x64-gnu@1.30.2:
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
lightningcss-linux-x64-gnu@1.30.1:
resolution: {integrity: sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-linux-x64-musl@1.30.2:
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
lightningcss-linux-x64-musl@1.30.1:
resolution: {integrity: sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-win32-arm64-msvc@1.30.2:
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
lightningcss-win32-arm64-msvc@1.30.1:
resolution: {integrity: sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
lightningcss-win32-x64-msvc@1.30.2:
resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==}
lightningcss-win32-x64-msvc@1.30.1:
resolution: {integrity: sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [win32]
lightningcss@1.30.2:
resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
lightningcss@1.30.1:
resolution: {integrity: sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==}
engines: {node: '>= 12.0.0'}
lilconfig@2.1.0:
@@ -12155,8 +12152,8 @@ packages:
peerDependencies:
react: ^18.0.0 || ^19.0.0
react-window@2.2.3:
resolution: {integrity: sha512-gTRqQYC8ojbiXyd9duYFiSn2TJw0ROXCgYjenOvNKITWzK0m0eCvkUsEUM08xvydkMh7ncp+LE0uS3DeNGZxnQ==}
react-window@2.2.4:
resolution: {integrity: sha512-FiZsQHvt2qbnTz6cN+/FXvX62v2xukQ+AajUivkm/Ivdp9rnU3bp0B1eDcCNpQXNaDBdqkEVGNYHlvIUGU9yBw==}
peerDependencies:
react: ^18.0.0 || ^19.0.0
react-dom: ^18.0.0 || ^19.0.0
@@ -15232,8 +15229,6 @@ snapshots:
'@ckeditor/ckeditor5-core': 47.3.0
'@ckeditor/ckeditor5-upload': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-ai@47.3.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)':
dependencies:
@@ -15374,16 +15369,12 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
'@ckeditor/ckeditor5-widget': 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-cloud-services@47.3.0':
dependencies:
'@ckeditor/ckeditor5-core': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-code-block@47.3.0(patch_hash=2361d8caad7d6b5bddacc3a3b4aa37dbfba260b1c1b22a450413a79c1bb1ce95)':
dependencies:
@@ -15576,8 +15567,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-classic@47.3.0':
dependencies:
@@ -15587,8 +15576,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-decoupled@47.3.0':
dependencies:
@@ -15598,8 +15585,6 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-editor-inline@47.3.0':
dependencies:
@@ -15633,6 +15618,8 @@ snapshots:
'@ckeditor/ckeditor5-table': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-emoji@47.3.0':
dependencies:
@@ -15689,6 +15676,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-export-word@47.3.0':
dependencies:
@@ -15722,6 +15711,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-footnotes@47.3.0':
dependencies:
@@ -15752,6 +15743,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-heading@47.3.0':
dependencies:
@@ -15762,6 +15755,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-highlight@47.3.0':
dependencies:
@@ -15770,6 +15765,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-horizontal-line@47.3.0':
dependencies:
@@ -15788,6 +15785,8 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
'@ckeditor/ckeditor5-widget': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-html-support@47.3.0':
dependencies:
@@ -15803,6 +15802,8 @@ snapshots:
'@ckeditor/ckeditor5-widget': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-icons@47.3.0': {}
@@ -15820,6 +15821,8 @@ snapshots:
'@ckeditor/ckeditor5-widget': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-import-word@47.3.0':
dependencies:
@@ -15832,6 +15835,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-indent@47.3.0':
dependencies:
@@ -15843,6 +15848,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-inspector@5.0.0': {}
@@ -15852,6 +15859,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-line-height@47.3.0':
dependencies:
@@ -15876,6 +15885,8 @@ snapshots:
'@ckeditor/ckeditor5-widget': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-list-multi-level@47.3.0':
dependencies:
@@ -15899,6 +15910,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-markdown-gfm@47.3.0':
dependencies:
@@ -15936,6 +15949,8 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
'@ckeditor/ckeditor5-widget': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-mention@47.3.0(patch_hash=5981fb59ba35829e4dff1d39cf771000f8a8fdfa7a34b51d8af9549541f2d62d)':
dependencies:
@@ -15959,6 +15974,8 @@ snapshots:
'@ckeditor/ckeditor5-widget': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-minimap@47.3.0':
dependencies:
@@ -15967,6 +15984,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-operations-compressor@47.3.0':
dependencies:
@@ -16021,6 +16040,8 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
'@ckeditor/ckeditor5-widget': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-pagination@47.3.0':
dependencies:
@@ -16128,6 +16149,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-slash-command@47.3.0':
dependencies:
@@ -16140,6 +16163,8 @@ snapshots:
'@ckeditor/ckeditor5-ui': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-source-editing-enhanced@47.3.0':
dependencies:
@@ -16187,6 +16212,8 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-table@47.3.0':
dependencies:
@@ -16199,6 +16226,8 @@ snapshots:
'@ckeditor/ckeditor5-widget': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-template@47.3.0':
dependencies:
@@ -16309,6 +16338,8 @@ snapshots:
'@ckeditor/ckeditor5-engine': 47.3.0
'@ckeditor/ckeditor5-utils': 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@ckeditor/ckeditor5-widget@47.3.0':
dependencies:
@@ -16328,6 +16359,8 @@ snapshots:
'@ckeditor/ckeditor5-utils': 47.3.0
ckeditor5: 47.3.0
es-toolkit: 1.39.5
transitivePeerDependencies:
- supports-color
'@codemirror/autocomplete@6.18.6':
dependencies:
@@ -18651,18 +18684,18 @@ snapshots:
'@popperjs/core@2.11.8': {}
'@preact/preset-vite@2.10.2(@babel/core@7.28.0)(preact@10.28.1)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
'@preact/preset-vite@2.10.2(@babel/core@7.28.0)(preact@10.28.1)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
dependencies:
'@babel/core': 7.28.0
'@babel/plugin-transform-react-jsx': 7.27.1(@babel/core@7.28.0)
'@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.28.0)
'@prefresh/vite': 2.4.8(preact@10.28.1)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@prefresh/vite': 2.4.8(preact@10.28.1)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@rollup/pluginutils': 4.2.1
babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.28.0)
debug: 4.4.1
picocolors: 1.1.1
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite-prerender-plugin: 0.5.11(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite-prerender-plugin: 0.5.11(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
transitivePeerDependencies:
- preact
- supports-color
@@ -18682,7 +18715,7 @@ snapshots:
'@prefresh/utils@1.2.1': {}
'@prefresh/vite@2.4.8(preact@10.28.1)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
'@prefresh/vite@2.4.8(preact@10.28.1)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
dependencies:
'@babel/core': 7.28.0
'@prefresh/babel-plugin': 0.5.2
@@ -18690,7 +18723,7 @@ snapshots:
'@prefresh/utils': 1.2.1
'@rollup/pluginutils': 4.2.1
preact: 10.28.1
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
transitivePeerDependencies:
- supports-color
@@ -20851,10 +20884,10 @@ snapshots:
- bufferutil
- utf-8-validate
'@vitest/browser-webdriverio@4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)(webdriverio@9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))':
'@vitest/browser-webdriverio@4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)(webdriverio@9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))':
dependencies:
'@vitest/browser': 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
vitest: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
'@vitest/browser': 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
vitest: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
webdriverio: 9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)
transitivePeerDependencies:
- bufferutil
@@ -20862,16 +20895,16 @@ snapshots:
- utf-8-validate
- vite
'@vitest/browser@4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)':
'@vitest/browser@4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)':
dependencies:
'@vitest/mocker': 4.0.16(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@vitest/mocker': 4.0.16(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@vitest/utils': 4.0.16
magic-string: 0.30.21
pixelmatch: 7.1.0
pngjs: 7.0.0
sirv: 3.0.2
tinyrainbow: 3.0.3
vitest: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vitest: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)
transitivePeerDependencies:
- bufferutil
@@ -20892,11 +20925,11 @@ snapshots:
magicast: 0.5.1
obug: 2.1.1
tinyrainbow: 3.0.3
vitest: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vitest: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
transitivePeerDependencies:
- supports-color
'@vitest/coverage-v8@4.0.16(@vitest/browser@4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16))(vitest@4.0.16)':
'@vitest/coverage-v8@4.0.16(@vitest/browser@4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16))(vitest@4.0.16)':
dependencies:
'@bcoe/v8-coverage': 1.0.2
'@vitest/utils': 4.0.16
@@ -20909,9 +20942,9 @@ snapshots:
obug: 2.1.1
std-env: 3.10.0
tinyrainbow: 3.0.3
vitest: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vitest: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
optionalDependencies:
'@vitest/browser': 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
'@vitest/browser': 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)
transitivePeerDependencies:
- supports-color
@@ -20924,14 +20957,14 @@ snapshots:
chai: 6.2.1
tinyrainbow: 3.0.3
'@vitest/mocker@4.0.16(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
'@vitest/mocker@4.0.16(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))':
dependencies:
'@vitest/spy': 4.0.16
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
msw: 2.7.5(@types/node@24.10.4)(typescript@5.9.3)
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
'@vitest/pretty-format@4.0.16':
dependencies:
@@ -20959,7 +20992,7 @@ snapshots:
sirv: 3.0.2
tinyglobby: 0.2.15
tinyrainbow: 3.0.3
vitest: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vitest: 4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
'@vitest/utils@4.0.16':
dependencies:
@@ -22013,6 +22046,8 @@ snapshots:
ckeditor5-collaboration@47.3.0:
dependencies:
'@ckeditor/ckeditor5-collaboration-core': 47.3.0
transitivePeerDependencies:
- supports-color
ckeditor5-premium-features@47.3.0(bufferutil@4.0.9)(ckeditor5@47.3.0)(utf-8-validate@6.0.5):
dependencies:
@@ -25921,54 +25956,51 @@ snapshots:
dependencies:
immediate: 3.0.6
lightningcss-android-arm64@1.30.2:
lightningcss-darwin-arm64@1.30.1:
optional: true
lightningcss-darwin-arm64@1.30.2:
lightningcss-darwin-x64@1.30.1:
optional: true
lightningcss-darwin-x64@1.30.2:
lightningcss-freebsd-x64@1.30.1:
optional: true
lightningcss-freebsd-x64@1.30.2:
lightningcss-linux-arm-gnueabihf@1.30.1:
optional: true
lightningcss-linux-arm-gnueabihf@1.30.2:
lightningcss-linux-arm64-gnu@1.30.1:
optional: true
lightningcss-linux-arm64-gnu@1.30.2:
lightningcss-linux-arm64-musl@1.30.1:
optional: true
lightningcss-linux-arm64-musl@1.30.2:
lightningcss-linux-x64-gnu@1.30.1:
optional: true
lightningcss-linux-x64-gnu@1.30.2:
lightningcss-linux-x64-musl@1.30.1:
optional: true
lightningcss-linux-x64-musl@1.30.2:
lightningcss-win32-arm64-msvc@1.30.1:
optional: true
lightningcss-win32-arm64-msvc@1.30.2:
lightningcss-win32-x64-msvc@1.30.1:
optional: true
lightningcss-win32-x64-msvc@1.30.2:
optional: true
lightningcss@1.30.2:
lightningcss@1.30.1:
dependencies:
detect-libc: 2.1.2
optionalDependencies:
lightningcss-android-arm64: 1.30.2
lightningcss-darwin-arm64: 1.30.2
lightningcss-darwin-x64: 1.30.2
lightningcss-freebsd-x64: 1.30.2
lightningcss-linux-arm-gnueabihf: 1.30.2
lightningcss-linux-arm64-gnu: 1.30.2
lightningcss-linux-arm64-musl: 1.30.2
lightningcss-linux-x64-gnu: 1.30.2
lightningcss-linux-x64-musl: 1.30.2
lightningcss-win32-arm64-msvc: 1.30.2
lightningcss-win32-x64-msvc: 1.30.2
lightningcss-darwin-arm64: 1.30.1
lightningcss-darwin-x64: 1.30.1
lightningcss-freebsd-x64: 1.30.1
lightningcss-linux-arm-gnueabihf: 1.30.1
lightningcss-linux-arm64-gnu: 1.30.1
lightningcss-linux-arm64-musl: 1.30.1
lightningcss-linux-x64-gnu: 1.30.1
lightningcss-linux-x64-musl: 1.30.1
lightningcss-win32-arm64-msvc: 1.30.1
lightningcss-win32-x64-msvc: 1.30.1
optional: true
lilconfig@2.1.0: {}
@@ -28450,7 +28482,7 @@ snapshots:
prop-types: 15.8.1
react: 19.2.3
react-window@2.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
react-window@2.2.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3):
dependencies:
react: 19.2.3
react-dom: 19.2.3(react@19.2.3)
@@ -28796,11 +28828,11 @@ snapshots:
'@rolldown/binding-win32-x64-msvc': 1.0.0-beta.29
optional: true
rollup-plugin-stats@1.5.4(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
rollup-plugin-stats@1.5.4(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
optionalDependencies:
rolldown: 1.0.0-beta.29
rollup: 4.52.0
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
rollup-plugin-styles@4.0.0(rollup@4.52.0):
dependencies:
@@ -28829,13 +28861,13 @@ snapshots:
'@rollup/pluginutils': 5.1.4(rollup@4.52.0)
rollup: 4.52.0
rollup-plugin-webpack-stats@2.1.9(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
rollup-plugin-webpack-stats@2.1.9(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
dependencies:
rollup-plugin-stats: 1.5.4(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
rollup-plugin-stats: 1.5.4(rolldown@1.0.0-beta.29)(rollup@4.52.0)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
optionalDependencies:
rolldown: 1.0.0-beta.29
rollup: 4.52.0
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
rollup@4.52.0:
dependencies:
@@ -30748,7 +30780,7 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.2
vite-plugin-dts@4.5.4(@types/node@24.10.4)(rollup@4.52.0)(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
vite-plugin-dts@4.5.4(@types/node@24.10.4)(rollup@4.52.0)(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
dependencies:
'@microsoft/api-extractor': 7.52.8(@types/node@24.10.4)
'@rollup/pluginutils': 5.1.4(rollup@4.52.0)
@@ -30761,27 +30793,27 @@ snapshots:
magic-string: 0.30.21
typescript: 5.9.3
optionalDependencies:
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
transitivePeerDependencies:
- '@types/node'
- rollup
- supports-color
vite-plugin-static-copy@3.1.4(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
vite-plugin-static-copy@3.1.4(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
dependencies:
chokidar: 3.6.0
p-map: 7.0.3
picocolors: 1.1.1
tinyglobby: 0.2.15
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite-plugin-svgo@2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
vite-plugin-svgo@2.0.0(typescript@5.9.3)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
dependencies:
svgo: 3.3.2
typescript: 5.9.3
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite-prerender-plugin@0.5.11(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
vite-prerender-plugin@0.5.11(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)):
dependencies:
kolorist: 1.8.0
magic-string: 0.30.18
@@ -30789,9 +30821,9 @@ snapshots:
simple-code-frame: 1.3.0
source-map: 0.7.6
stack-trace: 1.0.0-pre2
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1):
vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1):
dependencies:
esbuild: 0.27.1
fdir: 6.5.0(picomatch@4.0.3)
@@ -30804,17 +30836,17 @@ snapshots:
fsevents: 2.3.3
jiti: 2.6.1
less: 4.1.3
lightningcss: 1.30.2
lightningcss: 1.30.1
sass: 1.91.0
sass-embedded: 1.91.0
terser: 5.44.0
tsx: 4.21.0
yaml: 2.8.1
vitest@4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.2)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1):
vitest@4.0.16(@opentelemetry/api@1.9.0)(@types/node@24.10.4)(@vitest/browser-webdriverio@4.0.16)(@vitest/ui@4.0.16)(happy-dom@20.0.11)(jiti@2.6.1)(jsdom@26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))(less@4.1.3)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1):
dependencies:
'@vitest/expect': 4.0.16
'@vitest/mocker': 4.0.16(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@vitest/mocker': 4.0.16(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))
'@vitest/pretty-format': 4.0.16
'@vitest/runner': 4.0.16
'@vitest/snapshot': 4.0.16
@@ -30831,12 +30863,12 @@ snapshots:
tinyexec: 1.0.2
tinyglobby: 0.2.15
tinyrainbow: 3.0.3
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
vite: 7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1)
why-is-node-running: 2.3.0
optionalDependencies:
'@opentelemetry/api': 1.9.0
'@types/node': 24.10.4
'@vitest/browser-webdriverio': 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.2)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)(webdriverio@9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
'@vitest/browser-webdriverio': 4.0.16(bufferutil@4.0.9)(msw@2.7.5(@types/node@24.10.4)(typescript@5.9.3))(utf-8-validate@6.0.5)(vite@7.3.0(@types/node@24.10.4)(jiti@2.6.1)(less@4.1.3)(lightningcss@1.30.1)(sass-embedded@1.91.0)(sass@1.91.0)(terser@5.44.0)(tsx@4.21.0)(yaml@2.8.1))(vitest@4.0.16)(webdriverio@9.23.0(bufferutil@4.0.9)(utf-8-validate@6.0.5))
'@vitest/ui': 4.0.16(vitest@4.0.16)
happy-dom: 20.0.11
jsdom: 26.1.0(bufferutil@4.0.9)(utf-8-validate@6.0.5)

View File

@@ -1,33 +0,0 @@
import { readFileSync } from "fs";
import { join } from "path";
const projectRoot = join(__dirname, '..');
const filesToCheck = [
'package.json',
'apps/server/package.json',
'apps/client/package.json',
'apps/desktop/package.json',
'packages/commons/package.json',
]
function main() {
const expectedVersion = process.argv[2];
if (!expectedVersion) {
console.error('Expected version argument is missing.');
process.exit(1);
}
for (const fileToCheck of filesToCheck) {
const packageJsonPath = join(projectRoot, fileToCheck);
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
const version = packageJson.version;
if (version !== expectedVersion) {
console.error(`Version mismatch in ${fileToCheck}: expected ${expectedVersion}, found ${version}`);
process.exit(1);
}
}
console.log('All versions are consistent:', expectedVersion);
}
main();