mirror of
https://github.com/zadam/trilium.git
synced 2025-11-18 03:00:41 +01:00
Compare commits
31 Commits
feat/rice-
...
feat/ui/no
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d441bccf8b | ||
|
|
e6847355e7 | ||
|
|
72051c8660 | ||
|
|
87afc64f16 | ||
|
|
870fef3ea6 | ||
|
|
e5ac8a0a67 | ||
|
|
87fcc0afe6 | ||
|
|
79830870dd | ||
|
|
69ad40c27f | ||
|
|
1ac7ce00fb | ||
|
|
e239bca0f2 | ||
|
|
8729fe48c3 | ||
|
|
441c55eb31 | ||
|
|
5291a6856e | ||
|
|
e011f99161 | ||
|
|
fc8042aa25 | ||
|
|
2b6220beb8 | ||
|
|
78426a6c7b | ||
|
|
620e53c255 | ||
|
|
753fc6c769 | ||
|
|
3d6e1dfc0a | ||
|
|
d92431ad65 | ||
|
|
ca08a52998 | ||
|
|
e54822f3b0 | ||
|
|
3863e657ef | ||
|
|
341ef79b49 | ||
|
|
335f34b824 | ||
|
|
c864863be4 | ||
|
|
309d7e704c | ||
|
|
ecf9ce586c | ||
|
|
d0de9e5e21 |
@@ -55,7 +55,7 @@
|
||||
"mark.js": "8.11.1",
|
||||
"marked": "16.4.2",
|
||||
"mermaid": "11.12.1",
|
||||
"mind-elixir": "5.3.5",
|
||||
"mind-elixir": "5.3.6",
|
||||
"normalize.css": "8.0.1",
|
||||
"panzoom": "9.4.3",
|
||||
"preact": "10.27.2",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { KeyboardActionNames } from "@triliumnext/commons";
|
||||
import keyboardActionService, { getActionSync } from "../services/keyboard_actions.js";
|
||||
import note_tooltip from "../services/note_tooltip.js";
|
||||
import utils from "../services/utils.js";
|
||||
import { should } from "vitest";
|
||||
import { h, JSX, render } from "preact";
|
||||
|
||||
export interface ContextMenuOptions<T> {
|
||||
x: number;
|
||||
@@ -15,6 +15,11 @@ export interface ContextMenuOptions<T> {
|
||||
onHide?: () => void;
|
||||
}
|
||||
|
||||
export interface CustomMenuItem {
|
||||
kind: "custom",
|
||||
componentFn: () => JSX.Element | null;
|
||||
}
|
||||
|
||||
export interface MenuSeparatorItem {
|
||||
kind: "separator";
|
||||
}
|
||||
@@ -51,7 +56,7 @@ export interface MenuCommandItem<T> {
|
||||
columns?: number;
|
||||
}
|
||||
|
||||
export type MenuItem<T> = MenuCommandItem<T> | MenuSeparatorItem | MenuHeader;
|
||||
export type MenuItem<T> = MenuCommandItem<T> | CustomMenuItem | MenuSeparatorItem | MenuHeader;
|
||||
export type MenuHandler<T> = (item: MenuCommandItem<T>, e: JQuery.MouseDownEvent<HTMLElement, undefined, HTMLElement, HTMLElement>) => void;
|
||||
export type ContextMenuEvent = PointerEvent | MouseEvent | JQuery.ContextMenuEvent;
|
||||
|
||||
@@ -202,118 +207,14 @@ class ContextMenu {
|
||||
$group.append($("<h6>").addClass("dropdown-header").text(item.title));
|
||||
shouldResetGroup = true;
|
||||
} else {
|
||||
const $icon = $("<span>");
|
||||
|
||||
if ("uiIcon" in item || "checked" in item) {
|
||||
const icon = (item.checked ? "bx bx-check" : item.uiIcon);
|
||||
if (icon) {
|
||||
$icon.addClass(icon);
|
||||
} else {
|
||||
$icon.append(" ");
|
||||
}
|
||||
if ("kind" in item && item.kind === "custom") {
|
||||
// Custom menu item
|
||||
$group.append(this.createCustomMenuItem(item));
|
||||
} else {
|
||||
// Standard menu item
|
||||
$group.append(this.createMenuItem(item));
|
||||
}
|
||||
|
||||
const $link = $("<span>")
|
||||
.append($icon)
|
||||
.append(" ") // some space between icon and text
|
||||
.append(item.title);
|
||||
|
||||
if ("badges" in item && item.badges) {
|
||||
for (let badge of item.badges) {
|
||||
const badgeElement = $(`<span class="badge">`).text(badge.title);
|
||||
|
||||
if (badge.className) {
|
||||
badgeElement.addClass(badge.className);
|
||||
}
|
||||
|
||||
$link.append(badgeElement);
|
||||
}
|
||||
}
|
||||
|
||||
if ("keyboardShortcut" in item && item.keyboardShortcut) {
|
||||
const shortcuts = getActionSync(item.keyboardShortcut).effectiveShortcuts;
|
||||
if (shortcuts) {
|
||||
const allShortcuts: string[] = [];
|
||||
for (const effectiveShortcut of shortcuts) {
|
||||
allShortcuts.push(effectiveShortcut.split("+")
|
||||
.map(key => `<kbd>${key}</kbd>`)
|
||||
.join("+"));
|
||||
}
|
||||
|
||||
if (allShortcuts.length) {
|
||||
const container = $("<span>").addClass("keyboard-shortcut");
|
||||
container.append($(allShortcuts.join(",")));
|
||||
$link.append(container);
|
||||
}
|
||||
}
|
||||
} else if ("shortcut" in item && item.shortcut) {
|
||||
$link.append($("<kbd>").text(item.shortcut));
|
||||
}
|
||||
|
||||
const $item = $("<li>")
|
||||
.addClass("dropdown-item")
|
||||
.append($link)
|
||||
.on("contextmenu", (e) => false)
|
||||
// important to use mousedown instead of click since the former does not change focus
|
||||
// (especially important for focused text for spell check)
|
||||
.on("mousedown", (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
if (e.which !== 1) {
|
||||
// only left click triggers menu items
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isMobile && "items" in item && item.items) {
|
||||
const $item = $(e.target).closest(".dropdown-item");
|
||||
|
||||
$item.toggleClass("submenu-open");
|
||||
$item.find("ul.dropdown-menu").toggleClass("show");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ("handler" in item && item.handler) {
|
||||
item.handler(item, e);
|
||||
}
|
||||
|
||||
this.options?.selectMenuItemHandler(item, e);
|
||||
|
||||
// it's important to stop the propagation especially for sub-menus, otherwise the event
|
||||
// might be handled again by top-level menu
|
||||
return false;
|
||||
});
|
||||
|
||||
$item.on("mouseup", (e) => {
|
||||
// Prevent submenu from failing to expand on mobile
|
||||
if (!this.isMobile || !("items" in item && item.items)) {
|
||||
e.stopPropagation();
|
||||
// Hide the content menu on mouse up to prevent the mouse event from propagating to the elements below.
|
||||
this.hide();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if ("enabled" in item && item.enabled !== undefined && !item.enabled) {
|
||||
$item.addClass("disabled");
|
||||
}
|
||||
|
||||
if ("items" in item && item.items) {
|
||||
$item.addClass("dropdown-submenu");
|
||||
$link.addClass("dropdown-toggle");
|
||||
|
||||
const $subMenu = $("<ul>").addClass("dropdown-menu");
|
||||
const hasColumns = !!item.columns && item.columns > 1;
|
||||
if (!this.isMobile && hasColumns) {
|
||||
$subMenu.css("column-count", item.columns!);
|
||||
}
|
||||
|
||||
this.addItems($subMenu, item.items, hasColumns);
|
||||
|
||||
$item.append($subMenu);
|
||||
}
|
||||
|
||||
$group.append($item);
|
||||
|
||||
// After adding a menu item, if the previous item was a separator or header,
|
||||
// reset the group so that the next item will be appended directly to the parent.
|
||||
if (shouldResetGroup) {
|
||||
@@ -324,6 +225,126 @@ class ContextMenu {
|
||||
}
|
||||
}
|
||||
|
||||
private createCustomMenuItem(item: CustomMenuItem) {
|
||||
const element = document.createElement("li");
|
||||
element.classList.add("dropdown-custom-item");
|
||||
render(h(item.componentFn, {}), element);
|
||||
return element;
|
||||
}
|
||||
|
||||
private createMenuItem(item: MenuCommandItem<any>) {
|
||||
const $icon = $("<span>");
|
||||
|
||||
if ("uiIcon" in item || "checked" in item) {
|
||||
const icon = (item.checked ? "bx bx-check" : item.uiIcon);
|
||||
if (icon) {
|
||||
$icon.addClass(icon);
|
||||
} else {
|
||||
$icon.append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
const $link = $("<span>")
|
||||
.append($icon)
|
||||
.append(" ") // some space between icon and text
|
||||
.append(item.title);
|
||||
|
||||
if ("badges" in item && item.badges) {
|
||||
for (let badge of item.badges) {
|
||||
const badgeElement = $(`<span class="badge">`).text(badge.title);
|
||||
|
||||
if (badge.className) {
|
||||
badgeElement.addClass(badge.className);
|
||||
}
|
||||
|
||||
$link.append(badgeElement);
|
||||
}
|
||||
}
|
||||
|
||||
if ("keyboardShortcut" in item && item.keyboardShortcut) {
|
||||
const shortcuts = getActionSync(item.keyboardShortcut).effectiveShortcuts;
|
||||
if (shortcuts) {
|
||||
const allShortcuts: string[] = [];
|
||||
for (const effectiveShortcut of shortcuts) {
|
||||
allShortcuts.push(effectiveShortcut.split("+")
|
||||
.map(key => `<kbd>${key}</kbd>`)
|
||||
.join("+"));
|
||||
}
|
||||
|
||||
if (allShortcuts.length) {
|
||||
const container = $("<span>").addClass("keyboard-shortcut");
|
||||
container.append($(allShortcuts.join(",")));
|
||||
$link.append(container);
|
||||
}
|
||||
}
|
||||
} else if ("shortcut" in item && item.shortcut) {
|
||||
$link.append($("<kbd>").text(item.shortcut));
|
||||
}
|
||||
|
||||
const $item = $("<li>")
|
||||
.addClass("dropdown-item")
|
||||
.append($link)
|
||||
.on("contextmenu", (e) => false)
|
||||
// important to use mousedown instead of click since the former does not change focus
|
||||
// (especially important for focused text for spell check)
|
||||
.on("mousedown", (e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
if (e.which !== 1) {
|
||||
// only left click triggers menu items
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.isMobile && "items" in item && item.items) {
|
||||
const $item = $(e.target).closest(".dropdown-item");
|
||||
|
||||
$item.toggleClass("submenu-open");
|
||||
$item.find("ul.dropdown-menu").toggleClass("show");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ("handler" in item && item.handler) {
|
||||
item.handler(item, e);
|
||||
}
|
||||
|
||||
this.options?.selectMenuItemHandler(item, e);
|
||||
|
||||
// it's important to stop the propagation especially for sub-menus, otherwise the event
|
||||
// might be handled again by top-level menu
|
||||
return false;
|
||||
});
|
||||
|
||||
$item.on("mouseup", (e) => {
|
||||
// Prevent submenu from failing to expand on mobile
|
||||
if (!this.isMobile || !("items" in item && item.items)) {
|
||||
e.stopPropagation();
|
||||
// Hide the content menu on mouse up to prevent the mouse event from propagating to the elements below.
|
||||
this.hide();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if ("enabled" in item && item.enabled !== undefined && !item.enabled) {
|
||||
$item.addClass("disabled");
|
||||
}
|
||||
|
||||
if ("items" in item && item.items) {
|
||||
$item.addClass("dropdown-submenu");
|
||||
$link.addClass("dropdown-toggle");
|
||||
|
||||
const $subMenu = $("<ul>").addClass("dropdown-menu");
|
||||
const hasColumns = !!item.columns && item.columns > 1;
|
||||
if (!this.isMobile && hasColumns) {
|
||||
$subMenu.css("column-count", item.columns!);
|
||||
}
|
||||
|
||||
this.addItems($subMenu, item.items, hasColumns);
|
||||
|
||||
$item.append($subMenu);
|
||||
}
|
||||
return $item;
|
||||
}
|
||||
|
||||
async hide() {
|
||||
this.options?.onHide?.();
|
||||
this.$widget.removeClass("show");
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
.color-picker-menu-item {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.color-picker-menu-item > .color-cell {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.color-picker-menu-item > .color-cell.disabled-color-cell {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.color-picker-menu-item > .color-cell.selected {
|
||||
outline: 2px solid royalblue;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
import "./NoteColorPickerMenuItem.css";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import attributes from "../../services/attributes";
|
||||
import FNote from "../../entities/fnote";
|
||||
import froca from "../../services/froca";
|
||||
|
||||
const COLORS = ["blue", "green", "cyan", "red", "magenta", "brown", "yellow", ""];
|
||||
|
||||
export interface NoteColorPickerMenuItemProps {
|
||||
/** The target Note instance or its ID string. */
|
||||
note: FNote | string | null;
|
||||
}
|
||||
|
||||
export default function NoteColorPickerMenuItem(props: NoteColorPickerMenuItemProps) {
|
||||
if (!props.note) return null;
|
||||
|
||||
const [note, setNote] = useState<FNote | null>(null);
|
||||
const [currentColor, setCurrentColor] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const retrieveNote = async (noteId: string) => {
|
||||
const result = await froca.getNote(noteId, true);
|
||||
if (result) {
|
||||
setNote(result);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof props.note === "string") {
|
||||
retrieveNote(props.note); // Get the note from the given ID string
|
||||
} else {
|
||||
setNote(props.note);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setCurrentColor(note?.getLabel("color")?.value ?? "");
|
||||
}, [note]);
|
||||
|
||||
const onColorCellClicked = (color: string) => {
|
||||
if (note) {
|
||||
attributes.setLabel(note.noteId, "color", color);
|
||||
setCurrentColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
return <div className="color-picker-menu-item">
|
||||
{COLORS.map((color) => (
|
||||
<ColorCell key={color}
|
||||
color={color}
|
||||
isSelected={(color === currentColor)}
|
||||
isDisabled={(note === null)}
|
||||
onClick={() => onColorCellClicked(color)} />
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
|
||||
interface ColorCellProps {
|
||||
color: string,
|
||||
isSelected: boolean,
|
||||
isDisabled?: boolean,
|
||||
onClick?: () => void
|
||||
}
|
||||
|
||||
function ColorCell(props: ColorCellProps) {
|
||||
return <div class={`color-cell ${props.isSelected ? "selected" : ""} ${props.isDisabled ? "disabled-color-cell" : ""}`}
|
||||
style={`background-color: ${props.color}`}
|
||||
onClick={props.onClick}>
|
||||
</div>;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import NoteColorPickerMenuItem from "./custom-items/NoteColorPickerMenuItem.jsx";
|
||||
import treeService from "../services/tree.js";
|
||||
import froca from "../services/froca.js";
|
||||
import clipboard from "../services/clipboard.js";
|
||||
@@ -255,7 +256,20 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree
|
||||
keyboardShortcut: "searchInSubtree",
|
||||
uiIcon: "bx bx-search",
|
||||
enabled: notSearch && noSelectedNotes
|
||||
}
|
||||
},
|
||||
|
||||
{ kind: "separator"},
|
||||
|
||||
{
|
||||
kind: "custom",
|
||||
componentFn: () => {
|
||||
if (notOptionsOrHelp && selectedNotes.length === 1) {
|
||||
return NoteColorPickerMenuItem({note});
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
];
|
||||
return items.filter((row) => row !== null) as MenuItem<TreeCommandNames>[];
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import FNote from "../../../entities/fnote";
|
||||
import NoteColorPickerMenuItem from "../../../menus/custom-items/NoteColorPickerMenuItem";
|
||||
import contextMenu, { ContextMenuEvent } from "../../../menus/context_menu";
|
||||
import link_context_menu from "../../../menus/link_context_menu";
|
||||
import attributes from "../../../services/attributes";
|
||||
@@ -74,6 +75,11 @@ export function openNoteContextMenu(api: Api, event: ContextMenuEvent, note: FNo
|
||||
uiIcon: "bx bx-trash",
|
||||
handler: () => branches.deleteNotes([ branchId ], false, false)
|
||||
},
|
||||
{ kind: "separator" },
|
||||
{
|
||||
kind: "custom",
|
||||
componentFn: () => NoteColorPickerMenuItem({note})
|
||||
}
|
||||
],
|
||||
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, note.noteId),
|
||||
});
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import NoteColorPickerMenuItem from "../../../menus/custom-items/NoteColorPickerMenuItem";
|
||||
import FNote from "../../../entities/fnote";
|
||||
import contextMenu, { ContextMenuEvent } from "../../../menus/context_menu";
|
||||
import link_context_menu from "../../../menus/link_context_menu";
|
||||
import branches from "../../../services/branches";
|
||||
import froca from "../../../services/froca";
|
||||
import { note } from "mermaid/dist/rendering-util/rendering-elements/shapes/note.js";
|
||||
import { t } from "../../../services/i18n";
|
||||
|
||||
export function openCalendarContextMenu(e: ContextMenuEvent, noteId: string, parentNote: FNote) {
|
||||
@@ -34,6 +36,11 @@ export function openCalendarContextMenu(e: ContextMenuEvent, noteId: string, par
|
||||
await branches.deleteNotes([ branchIdToDelete ], false, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
{ kind: "separator" },
|
||||
{
|
||||
kind: "custom",
|
||||
componentFn: () => NoteColorPickerMenuItem({note: noteId})
|
||||
}
|
||||
],
|
||||
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, noteId),
|
||||
|
||||
@@ -91,6 +91,7 @@ export default function CalendarView({ note, noteIds }: ViewModeProps<CalendarVi
|
||||
const [ hideWeekends ] = useNoteLabelBoolean(note, "calendar:hideWeekends");
|
||||
const [ weekNumbers ] = useNoteLabelBoolean(note, "calendar:weekNumbers");
|
||||
const [ calendarView, setCalendarView ] = useNoteLabel(note, "calendar:view");
|
||||
const [ initialDate ] = useNoteLabel(note, "calendar:initialDate");
|
||||
const initialView = useRef(calendarView);
|
||||
const viewSpacedUpdate = useSpacedUpdate(() => setCalendarView(initialView.current));
|
||||
useResizeObserver(containerRef, () => calendarRef.current?.updateSize());
|
||||
@@ -134,6 +135,7 @@ export default function CalendarView({ note, noteIds }: ViewModeProps<CalendarVi
|
||||
height="90%"
|
||||
nowIndicator
|
||||
handleWindowResize={false}
|
||||
initialDate={initialDate || undefined}
|
||||
locale={locale}
|
||||
{...editingProps}
|
||||
eventDidMount={eventDidMount}
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { LatLng, LeafletMouseEvent } from "leaflet";
|
||||
import appContext, { type CommandMappings } from "../../../components/app_context.js";
|
||||
import contextMenu, { type MenuItem } from "../../../menus/context_menu.js";
|
||||
import linkContextMenu from "../../../menus/link_context_menu.js";
|
||||
import NoteColorPickerMenuItem from "../../../menus/custom-items/NoteColorPickerMenuItem.jsx";
|
||||
import { t } from "../../../services/i18n.js";
|
||||
import { createNewNote } from "./api.js";
|
||||
import { copyTextWithToast } from "../../../services/clipboard_ext.js";
|
||||
@@ -18,7 +19,12 @@ export default function openContextMenu(noteId: string, e: LeafletMouseEvent, is
|
||||
items = [
|
||||
...items,
|
||||
{ kind: "separator" },
|
||||
{ title: t("geo-map-context.remove-from-map"), command: "deleteFromMap", uiIcon: "bx bx-trash" }
|
||||
{ title: t("geo-map-context.remove-from-map"), command: "deleteFromMap", uiIcon: "bx bx-trash" },
|
||||
{ kind: "separator"},
|
||||
{
|
||||
kind: "custom",
|
||||
componentFn: () => NoteColorPickerMenuItem({note: noteId})
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import link_context_menu from "../../../menus/link_context_menu.js";
|
||||
import froca from "../../../services/froca.js";
|
||||
import branches from "../../../services/branches.js";
|
||||
import Component from "../../../components/component.js";
|
||||
import NoteColorPickerMenuItem from "../../../menus/custom-items/NoteColorPickerMenuItem.jsx";
|
||||
import { RefObject } from "preact";
|
||||
|
||||
export function useContextMenu(parentNote: FNote, parentComponent: Component | null | undefined, tabulator: RefObject<Tabulator>): Partial<EventCallBackMethods> {
|
||||
@@ -219,6 +220,11 @@ export function showRowContextMenu(parentComponent: Component, e: MouseEvent, ro
|
||||
title: t("table_context_menu.delete_row"),
|
||||
uiIcon: "bx bx-trash",
|
||||
handler: () => branches.deleteNotes([ rowData.branchId ], false, false)
|
||||
},
|
||||
{ kind: "separator"},
|
||||
{
|
||||
kind: "custom",
|
||||
componentFn: () => NoteColorPickerMenuItem({note: rowData.noteId})
|
||||
}
|
||||
],
|
||||
selectMenuItemHandler: ({ command }) => link_context_menu.handleLinkContextMenuItem(command, rowData.noteId),
|
||||
|
||||
2
apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json
generated
vendored
2
apps/server/src/assets/doc_notes/en/User Guide/!!!meta.json
generated
vendored
File diff suppressed because one or more lines are too long
6
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Collections/Calendar.html
generated
vendored
6
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Collections/Calendar.html
generated
vendored
@@ -112,6 +112,12 @@
|
||||
<td>When present (regardless of value), it will show the number of the week
|
||||
on the calendar.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>#calendar:initialDate</code>
|
||||
</td>
|
||||
<td>Change the date the calendar opens on. When not present, the calendar
|
||||
opens on the current date.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>#calendar:view</code>
|
||||
</td>
|
||||
|
||||
@@ -135,7 +135,7 @@ docker run -d --name trilium -p 8080:8080 --user $(id -u):$(id -g) -v ~/trilium-
|
||||
(default: <code>/home/node/trilium-data</code>)</li>
|
||||
</ul>
|
||||
<p>For a complete list of configuration environment variables (network settings,
|
||||
authentication, sync, etc.), see <a class="reference-link" href="#root/_help_dmi3wz9muS2O">Configuration (config.ini or environment variables)</a>.</p>
|
||||
authentication, sync, etc.), see <a class="reference-link" href="#root/_help_Gzjqa934BdH4">Configuration (config.ini or environment variables)</a>.</p>
|
||||
<h3>Volume Permissions</h3>
|
||||
<p>If you encounter permission issues with the data volume, ensure that:</p>
|
||||
<ol>
|
||||
|
||||
48
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik.html
generated
vendored
Normal file
48
apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik.html
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<p>Configure Traefik proxy and HTTPS. See <a href="https://github.com/TriliumNext/Trilium/issues/7768#issuecomment-3539165814">#7768</a> for
|
||||
reference</p>
|
||||
<h3>Build the docker-compose file</h3>
|
||||
<p>Setting up Traefik as reverse proxy requires setting the following labels:</p><pre><code class="language-text-x-yaml"> labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.trilium.entrypoints=https
|
||||
- traefik.http.routers.trilium.rule=Host(`trilium.mydomain.tld`)
|
||||
- traefik.http.routers.trilium.tls=true
|
||||
- traefik.http.routers.trilium.service=trilium
|
||||
- traefik.http.services.trilium.loadbalancer.server.port=8080
|
||||
# scheme must be HTTP instead of the usual HTTPS because Trilium listens on HTTP internally
|
||||
- traefik.http.services.trilium.loadbalancer.server.scheme=http
|
||||
- traefik.docker.network=proxy
|
||||
# forward HTTP to HTTPS
|
||||
- traefik.http.routers.trilium.middlewares=trilium-headers@docker
|
||||
- traefik.http.middlewares.trilium-headers.headers.customrequestheaders.X-Forwarded-Proto=https</code></pre>
|
||||
<h3>Setup needed environment variables</h3>
|
||||
<p>After setting up a reverse proxy, make sure to configure the <a class="reference-link"
|
||||
href="Trusted%20proxy.md">[missing note]</a>.</p>
|
||||
<h3>Example <code>docker-compose.yaml</code></h3><pre><code class="language-text-x-yaml">services:
|
||||
trilium:
|
||||
image: triliumnext/trilium
|
||||
container_name: trilium
|
||||
networks:
|
||||
- traefik-proxy
|
||||
environment:
|
||||
- TRILIUM_NETWORK_TRUSTEDREVERSEPROXY=my-traefik-host-ip # e.g., 172.18.0.0/16
|
||||
volumes:
|
||||
- /path/to/data:/home/node/trilium-data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.trilium.entrypoints=https
|
||||
- traefik.http.routers.trilium.rule=Host(`trilium.mydomain.tld`)
|
||||
- traefik.http.routers.trilium.tls=true
|
||||
- traefik.http.routers.trilium.service=trilium
|
||||
- traefik.http.services.trilium.loadbalancer.server.port=8080
|
||||
# scheme must be HTTP instead of the usual HTTPS because of how trilium works
|
||||
- traefik.http.services.trilium.loadbalancer.server.scheme=http
|
||||
- traefik.docker.network=traefik-proxy
|
||||
# Tell Trilium the original request was HTTPS
|
||||
- traefik.http.routers.trilium.middlewares=trilium-headers@docker
|
||||
- traefik.http.middlewares.trilium-headers.headers.customrequestheaders.X-Forwarded-Proto=https
|
||||
|
||||
networks:
|
||||
traefik-proxy:
|
||||
external: true</code></pre>
|
||||
14
docs/Developer Guide/!!!meta.json
vendored
14
docs/Developer Guide/!!!meta.json
vendored
@@ -1961,6 +1961,13 @@
|
||||
"isInheritable": false,
|
||||
"position": 10
|
||||
},
|
||||
{
|
||||
"type": "relation",
|
||||
"name": "internalLink",
|
||||
"value": "lXjOyKpUSKgE",
|
||||
"isInheritable": false,
|
||||
"position": 20
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"name": "iconClass",
|
||||
@@ -1974,13 +1981,6 @@
|
||||
"value": "i18n",
|
||||
"isInheritable": false,
|
||||
"position": 20
|
||||
},
|
||||
{
|
||||
"type": "relation",
|
||||
"name": "internalLink",
|
||||
"value": "lXjOyKpUSKgE",
|
||||
"isInheritable": false,
|
||||
"position": 30
|
||||
}
|
||||
],
|
||||
"format": "markdown",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Documentation
|
||||
There are multiple types of documentation for Trilium:<img class="image-style-align-right" src="api/images/5q5br2G87GtN/Documentation_image.png" width="205" height="162">
|
||||
There are multiple types of documentation for Trilium:<img class="image-style-align-right" src="api/images/eyrnitqBQ2w6/Documentation_image.png" width="205" height="162">
|
||||
|
||||
* The _User Guide_ represents the user-facing documentation. This documentation can be browsed by users directly from within Trilium, by pressing <kbd>F1</kbd>.
|
||||
* The _Developer's Guide_ represents a set of Markdown documents that present the internals of Trilium, for developers.
|
||||
|
||||
36
docs/User Guide/!!!meta.json
vendored
36
docs/User Guide/!!!meta.json
vendored
@@ -681,6 +681,13 @@
|
||||
"isInheritable": false,
|
||||
"position": 20
|
||||
},
|
||||
{
|
||||
"type": "relation",
|
||||
"name": "internalLink",
|
||||
"value": "Gzjqa934BdH4",
|
||||
"isInheritable": false,
|
||||
"position": 30
|
||||
},
|
||||
{
|
||||
"type": "label",
|
||||
"name": "shareAlias",
|
||||
@@ -1044,6 +1051,35 @@
|
||||
"format": "markdown",
|
||||
"dataFileName": "Trusted proxy.md",
|
||||
"attachments": []
|
||||
},
|
||||
{
|
||||
"isClone": false,
|
||||
"noteId": "5ERVJb9s4FRD",
|
||||
"notePath": [
|
||||
"pOsGYCXsbNQG",
|
||||
"Otzi9La2YAUX",
|
||||
"WOcw2SLH6tbX",
|
||||
"vcjrb3VVYPZI",
|
||||
"5ERVJb9s4FRD"
|
||||
],
|
||||
"title": "Traefik",
|
||||
"notePosition": 40,
|
||||
"prefix": null,
|
||||
"isExpanded": false,
|
||||
"type": "text",
|
||||
"mime": "text/html",
|
||||
"attributes": [
|
||||
{
|
||||
"type": "label",
|
||||
"name": "shareAlias",
|
||||
"value": "traefik",
|
||||
"isInheritable": false,
|
||||
"position": 30
|
||||
}
|
||||
],
|
||||
"format": "markdown",
|
||||
"dataFileName": "Traefik.md",
|
||||
"attachments": []
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -48,7 +48,7 @@ In the _Collections_ tab in the <a class="reference-link" href="../Basic%20Conc
|
||||
|
||||
The following attributes can be added to the Collection type:
|
||||
|
||||
<table><thead><tr><th>Name</th><th>Description</th></tr></thead><tbody><tr><td><code>#calendar:hideWeekends</code></td><td>When present (regardless of value), it will hide Saturday and Sundays from the calendar.</td></tr><tr><td><code>#calendar:weekNumbers</code></td><td>When present (regardless of value), it will show the number of the week on the calendar.</td></tr><tr><td><code>#calendar:view</code></td><td><p>Which view to display in the calendar:</p><ul><li><code>timeGridWeek</code> for the <em>week</em> view;</li><li><code>dayGridMonth</code> for the <em>month</em> view;</li><li><code>multiMonthYear</code> for the <em>year</em> view;</li><li><code>listMonth</code> for the <em>list</em> view.</li></ul><p>Any other value will be dismissed and the default view (month) will be used instead.</p><p>The value of this label is automatically updated when changing the view using the UI buttons.</p></td></tr><tr><td><code>~child:template</code></td><td>Defines the template for newly created notes in the calendar (via dragging or clicking).</td></tr></tbody></table>
|
||||
<table><thead><tr><th>Name</th><th>Description</th></tr></thead><tbody><tr><td><code>#calendar:hideWeekends</code></td><td>When present (regardless of value), it will hide Saturday and Sundays from the calendar.</td></tr><tr><td><code>#calendar:weekNumbers</code></td><td>When present (regardless of value), it will show the number of the week on the calendar.</td></tr><tr><td><code>#calendar:initialDate</code></td><td>Change the date the calendar opens on. When not present, the calendar opens on the current date.</td></tr><tr><td><code>#calendar:view</code></td><td><p>Which view to display in the calendar:</p><ul><li><code>timeGridWeek</code> for the <em>week</em> view;</li><li><code>dayGridMonth</code> for the <em>month</em> view;</li><li><code>multiMonthYear</code> for the <em>year</em> view;</li><li><code>listMonth</code> for the <em>list</em> view.</li></ul><p>Any other value will be dismissed and the default view (month) will be used instead.</p><p>The value of this label is automatically updated when changing the view using the UI buttons.</p></td></tr><tr><td><code>~child:template</code></td><td>Defines the template for newly created notes in the calendar (via dragging or clicking).</td></tr></tbody></table>
|
||||
|
||||
In addition, the first day of the week can be either Sunday or Monday and can be adjusted from the application settings.
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ docker run -d --name trilium -p 8080:8080 --user $(id -u):$(id -g) -v ~/trilium-
|
||||
* `TRILIUM_GID`: GID to use for the container process (passed to Docker's `--user` flag)
|
||||
* `TRILIUM_DATA_DIR`: Path to the data directory inside the container (default: `/home/node/trilium-data`)
|
||||
|
||||
For a complete list of configuration environment variables (network settings, authentication, sync, etc.), see <a class="reference-link" href="#root/dmi3wz9muS2O">Configuration (config.ini or environment variables)</a>.
|
||||
For a complete list of configuration environment variables (network settings, authentication, sync, etc.), see <a class="reference-link" href="../../../Advanced%20Usage/Configuration%20(config.ini%20or%20e.md">Configuration (config.ini or environment variables)</a>.
|
||||
|
||||
### Volume Permissions
|
||||
|
||||
|
||||
60
docs/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik.md
vendored
Normal file
60
docs/User Guide/User Guide/Installation & Setup/Server Installation/2. Reverse proxy/Traefik.md
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
# Traefik
|
||||
Configure Traefik proxy and HTTPS. See [#7768](https://github.com/TriliumNext/Trilium/issues/7768#issuecomment-3539165814) for reference
|
||||
|
||||
### Build the docker-compose file
|
||||
|
||||
Setting up Traefik as reverse proxy requires setting the following labels:
|
||||
|
||||
```yaml
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.trilium.entrypoints=https
|
||||
- traefik.http.routers.trilium.rule=Host(`trilium.mydomain.tld`)
|
||||
- traefik.http.routers.trilium.tls=true
|
||||
- traefik.http.routers.trilium.service=trilium
|
||||
- traefik.http.services.trilium.loadbalancer.server.port=8080
|
||||
# scheme must be HTTP instead of the usual HTTPS because Trilium listens on HTTP internally
|
||||
- traefik.http.services.trilium.loadbalancer.server.scheme=http
|
||||
- traefik.docker.network=proxy
|
||||
# forward HTTP to HTTPS
|
||||
- traefik.http.routers.trilium.middlewares=trilium-headers@docker
|
||||
- traefik.http.middlewares.trilium-headers.headers.customrequestheaders.X-Forwarded-Proto=https
|
||||
```
|
||||
|
||||
### Setup needed environment variables
|
||||
|
||||
After setting up a reverse proxy, make sure to configure the <a class="reference-link" href="Trusted%20proxy.md">[missing note]</a>.
|
||||
|
||||
### Example `docker-compose.yaml`
|
||||
|
||||
```yaml
|
||||
services:
|
||||
trilium:
|
||||
image: triliumnext/trilium
|
||||
container_name: trilium
|
||||
networks:
|
||||
- traefik-proxy
|
||||
environment:
|
||||
- TRILIUM_NETWORK_TRUSTEDREVERSEPROXY=my-traefik-host-ip # e.g., 172.18.0.0/16
|
||||
volumes:
|
||||
- /path/to/data:/home/node/trilium-data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.routers.trilium.entrypoints=https
|
||||
- traefik.http.routers.trilium.rule=Host(`trilium.mydomain.tld`)
|
||||
- traefik.http.routers.trilium.tls=true
|
||||
- traefik.http.routers.trilium.service=trilium
|
||||
- traefik.http.services.trilium.loadbalancer.server.port=8080
|
||||
# scheme must be HTTP instead of the usual HTTPS because of how trilium works
|
||||
- traefik.http.services.trilium.loadbalancer.server.scheme=http
|
||||
- traefik.docker.network=traefik-proxy
|
||||
# Tell Trilium the original request was HTTPS
|
||||
- traefik.http.routers.trilium.middlewares=trilium-headers@docker
|
||||
- traefik.http.middlewares.trilium-headers.headers.customrequestheaders.X-Forwarded-Proto=https
|
||||
|
||||
networks:
|
||||
traefik-proxy:
|
||||
external: true
|
||||
```
|
||||
@@ -33,6 +33,7 @@ type Labels = {
|
||||
"calendar:hideWeekends": boolean;
|
||||
"calendar:weekNumbers": boolean;
|
||||
"calendar:view": string;
|
||||
"calendar:initialDate": string;
|
||||
"map:style": string;
|
||||
"map:scale": boolean;
|
||||
"board:groupBy": string;
|
||||
|
||||
42
pnpm-lock.yaml
generated
42
pnpm-lock.yaml
generated
@@ -186,7 +186,7 @@ importers:
|
||||
version: 0.2.0(mermaid@11.12.1)
|
||||
'@mind-elixir/node-menu':
|
||||
specifier: 5.0.1
|
||||
version: 5.0.1(mind-elixir@5.3.5)
|
||||
version: 5.0.1(mind-elixir@5.3.6)
|
||||
'@popperjs/core':
|
||||
specifier: 2.11.8
|
||||
version: 2.11.8
|
||||
@@ -275,8 +275,8 @@ importers:
|
||||
specifier: 11.12.1
|
||||
version: 11.12.1
|
||||
mind-elixir:
|
||||
specifier: 5.3.5
|
||||
version: 5.3.5
|
||||
specifier: 5.3.6
|
||||
version: 5.3.6
|
||||
normalize.css:
|
||||
specifier: 8.0.1
|
||||
version: 8.0.1
|
||||
@@ -10377,8 +10377,8 @@ packages:
|
||||
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
mind-elixir@5.3.5:
|
||||
resolution: {integrity: sha512-GKYTqU7qsbmPmdTvJlM0g/chrHIkikV7sYhQIz4GTa7Xp8H7hqL5y8gMeJLeR2gdJi3sLUyoVUzBwF7tmKIffw==}
|
||||
mind-elixir@5.3.6:
|
||||
resolution: {integrity: sha512-LU5HuRrtq/Fq/YkgZHUu4gb1Vg6tNQq0Ob7bQKNDTP3A8prcohHF5D7ca5blvqVkyf9+xUdBWsdFMNffMNPnkA==}
|
||||
|
||||
mini-css-extract-plugin@2.4.7:
|
||||
resolution: {integrity: sha512-euWmddf0sk9Nv1O0gfeeUAvAkoSlWncNLF77C0TP2+WoPvy8mAHKOzMajcCz2dzvyt3CNgxb1obIEVFIRxaipg==}
|
||||
@@ -15616,6 +15616,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-ui': 47.2.0
|
||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-block-quote@47.2.0':
|
||||
dependencies:
|
||||
@@ -15626,6 +15628,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-ui': 47.2.0
|
||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-bookmark@47.2.0':
|
||||
dependencies:
|
||||
@@ -15636,6 +15640,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||
'@ckeditor/ckeditor5-widget': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-case-change@47.2.0':
|
||||
dependencies:
|
||||
@@ -15946,6 +15952,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
es-toolkit: 1.39.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-editor-multi-root@47.2.0':
|
||||
dependencies:
|
||||
@@ -15968,6 +15976,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-table': 47.2.0
|
||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-emoji@47.2.0':
|
||||
dependencies:
|
||||
@@ -15980,6 +15990,8 @@ snapshots:
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
es-toolkit: 1.39.5
|
||||
fuzzysort: 3.1.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-engine@47.2.0':
|
||||
dependencies:
|
||||
@@ -16022,6 +16034,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-ui': 47.2.0
|
||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-export-word@47.2.0':
|
||||
dependencies:
|
||||
@@ -16087,6 +16101,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-ui': 47.2.0
|
||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-heading@47.2.0':
|
||||
dependencies:
|
||||
@@ -16097,6 +16113,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-ui': 47.2.0
|
||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-highlight@47.2.0':
|
||||
dependencies:
|
||||
@@ -16142,6 +16160,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-widget': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
es-toolkit: 1.39.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-icons@47.2.0': {}
|
||||
|
||||
@@ -16173,6 +16193,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-ui': 47.2.0
|
||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-indent@47.2.0':
|
||||
dependencies:
|
||||
@@ -16309,6 +16331,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-widget': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
es-toolkit: 1.39.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-minimap@47.2.0':
|
||||
dependencies:
|
||||
@@ -16692,6 +16716,8 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-utils': 47.2.0
|
||||
ckeditor5: 47.2.0(patch_hash=8331a09d41443b39ea1c784daaccfeb0da4f9065ed556e7de92e9c77edd9eb41)
|
||||
es-toolkit: 1.39.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@codemirror/autocomplete@6.18.6':
|
||||
dependencies:
|
||||
@@ -18575,9 +18601,9 @@ snapshots:
|
||||
|
||||
'@microsoft/tsdoc@0.15.1': {}
|
||||
|
||||
'@mind-elixir/node-menu@5.0.1(mind-elixir@5.3.5)':
|
||||
'@mind-elixir/node-menu@5.0.1(mind-elixir@5.3.6)':
|
||||
dependencies:
|
||||
mind-elixir: 5.3.5
|
||||
mind-elixir: 5.3.6
|
||||
|
||||
'@mixmark-io/domino@2.2.0': {}
|
||||
|
||||
@@ -27043,7 +27069,7 @@ snapshots:
|
||||
|
||||
mimic-response@3.1.0: {}
|
||||
|
||||
mind-elixir@5.3.5: {}
|
||||
mind-elixir@5.3.6: {}
|
||||
|
||||
mini-css-extract-plugin@2.4.7(webpack@5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.27.0)):
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user