mirror of
https://github.com/zadam/trilium.git
synced 2025-12-20 23:29:55 +01:00
Compare commits
26 Commits
main
...
feature/pr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f8bf301d12 | ||
|
|
2c25786fa2 | ||
|
|
1093acfe45 | ||
|
|
76f054bbd5 | ||
|
|
c558255450 | ||
|
|
1e94125133 | ||
|
|
64a770175f | ||
|
|
e0416097e1 | ||
|
|
6c1b327f5f | ||
|
|
284b66acd2 | ||
|
|
dcd73ff9f9 | ||
|
|
645557b505 | ||
|
|
22a83d9f82 | ||
|
|
f64de3acca | ||
|
|
34d5793888 | ||
|
|
44ca9f457c | ||
|
|
4d7e5bc8f6 | ||
|
|
644ff07a50 | ||
|
|
41220a9d1d | ||
|
|
88945788d6 | ||
|
|
fe8f033409 | ||
|
|
eee7c49f6e | ||
|
|
d036bf0870 | ||
|
|
fa8ff4bfbf | ||
|
|
3619c0c3e4 | ||
|
|
883e32f5c9 |
@@ -62,6 +62,7 @@
|
||||
"preact": "10.28.0",
|
||||
"react-i18next": "16.5.0",
|
||||
"reveal.js": "5.2.1",
|
||||
"sucrase": "3.35.1",
|
||||
"svg-pan-zoom": "3.6.2",
|
||||
"tabulator-tables": "6.3.1",
|
||||
"vanilla-js-wheel-zoom": "9.0.4"
|
||||
|
||||
@@ -184,7 +184,7 @@ export default class DesktopLayout {
|
||||
.child(new HighlightsListWidget())
|
||||
.child(...this.customWidgets.get("right-pane"))
|
||||
)
|
||||
.optChild(isNewLayout, <RightPanelContainer customWidgets={this.customWidgets.get("right-pane")} />)
|
||||
.optChild(isNewLayout, <RightPanelContainer widgetsByParent={this.customWidgets} />)
|
||||
)
|
||||
.optChild(!launcherPaneIsHorizontal && isNewLayout, <StatusBar />)
|
||||
)
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
import { h, VNode } from "preact";
|
||||
|
||||
import Component from "../components/component.js";
|
||||
import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||
import RightPanelWidget from "../widgets/right_panel_widget.js";
|
||||
import froca from "./froca.js";
|
||||
import type { Entity } from "./frontend_script_api.js";
|
||||
import { WidgetDefinitionWithType } from "./frontend_script_api_preact.js";
|
||||
import { t } from "./i18n.js";
|
||||
import ScriptContext from "./script_context.js";
|
||||
import server from "./server.js";
|
||||
import toastService, { showError } from "./toast.js";
|
||||
import froca from "./froca.js";
|
||||
import utils from "./utils.js";
|
||||
import { t } from "./i18n.js";
|
||||
import type { Entity } from "./frontend_script_api.js";
|
||||
import toastService, { showErrorForScriptNote } from "./toast.js";
|
||||
import utils, { getErrorMessage } from "./utils.js";
|
||||
|
||||
// TODO: Deduplicate with server.
|
||||
export interface Bundle {
|
||||
@@ -14,9 +20,12 @@ export interface Bundle {
|
||||
allNoteIds: string[];
|
||||
}
|
||||
|
||||
interface Widget {
|
||||
type LegacyWidget = (BasicWidget | RightPanelWidget) & {
|
||||
parentWidget?: string;
|
||||
}
|
||||
};
|
||||
export type Widget = (LegacyWidget | WidgetDefinitionWithType) & {
|
||||
_noteId: string;
|
||||
};
|
||||
|
||||
async function getAndExecuteBundle(noteId: string, originEntity = null, script = null, params = null) {
|
||||
const bundle = await server.post<Bundle>(`script/bundle/${noteId}`, {
|
||||
@@ -27,6 +36,8 @@ async function getAndExecuteBundle(noteId: string, originEntity = null, script =
|
||||
return await executeBundle(bundle, originEntity);
|
||||
}
|
||||
|
||||
export type ParentName = "left-pane" | "center-pane" | "note-detail-pane" | "right-pane";
|
||||
|
||||
export async function executeBundle(bundle: Bundle, originEntity?: Entity | null, $container?: JQuery<HTMLElement>) {
|
||||
const apiContext = await ScriptContext(bundle.noteId, bundle.allNoteIds, originEntity, $container);
|
||||
|
||||
@@ -52,7 +63,7 @@ export async function executeBundle(bundle: Bundle, originEntity?: Entity | null
|
||||
|
||||
async function executeStartupBundles() {
|
||||
const isMobile = utils.isMobile();
|
||||
const scriptBundles = await server.get<Bundle[]>("script/startup" + (isMobile ? "?mobile=true" : ""));
|
||||
const scriptBundles = await server.get<Bundle[]>(`script/startup${ isMobile ? "?mobile=true" : ""}`);
|
||||
|
||||
for (const bundle of scriptBundles) {
|
||||
await executeBundle(bundle);
|
||||
@@ -60,68 +71,106 @@ async function executeStartupBundles() {
|
||||
}
|
||||
|
||||
export class WidgetsByParent {
|
||||
private byParent: Record<string, Widget[]>;
|
||||
private legacyWidgets: Record<string, LegacyWidget[]>;
|
||||
private preactWidgets: Record<string, WidgetDefinitionWithType[]>;
|
||||
|
||||
constructor() {
|
||||
this.byParent = {};
|
||||
this.legacyWidgets = {};
|
||||
this.preactWidgets = {};
|
||||
}
|
||||
|
||||
add(widget: Widget) {
|
||||
if (!widget.parentWidget) {
|
||||
console.log(`Custom widget does not have mandatory 'parentWidget' property defined`);
|
||||
return;
|
||||
let hasParentWidget = false;
|
||||
let isPreact = false;
|
||||
if ("type" in widget && widget.type === "preact-widget") {
|
||||
// React-based script.
|
||||
const reactWidget = widget as WidgetDefinitionWithType;
|
||||
this.preactWidgets[reactWidget.parent] = this.preactWidgets[reactWidget.parent] || [];
|
||||
this.preactWidgets[reactWidget.parent].push(reactWidget);
|
||||
isPreact = true;
|
||||
hasParentWidget = !!reactWidget.parent;
|
||||
} else if ("parentWidget" in widget && widget.parentWidget) {
|
||||
this.legacyWidgets[widget.parentWidget] = this.legacyWidgets[widget.parentWidget] || [];
|
||||
this.legacyWidgets[widget.parentWidget].push(widget);
|
||||
hasParentWidget = !!widget.parentWidget;
|
||||
}
|
||||
|
||||
this.byParent[widget.parentWidget] = this.byParent[widget.parentWidget] || [];
|
||||
this.byParent[widget.parentWidget].push(widget);
|
||||
if (!hasParentWidget) {
|
||||
showErrorForScriptNote(widget._noteId, t("toast.widget-missing-parent", {
|
||||
property: isPreact ? "parent" : "parentWidget"
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
get(parentName: string) {
|
||||
if (!this.byParent[parentName]) {
|
||||
return [];
|
||||
get(parentName: ParentName) {
|
||||
const widgets: (Component | VNode)[] = this.getLegacyWidgets(parentName);
|
||||
for (const preactWidget of this.getPreactWidgets(parentName)) {
|
||||
const el = h(preactWidget.render, {});
|
||||
const widget = new ReactWrappedWidget(el);
|
||||
widget.contentSized();
|
||||
// TODO: set position here.
|
||||
widgets.push(widget);
|
||||
}
|
||||
|
||||
return widgets;
|
||||
}
|
||||
|
||||
getLegacyWidgets(parentName: ParentName): (BasicWidget | RightPanelWidget)[] {
|
||||
if (!this.legacyWidgets[parentName]) return [];
|
||||
|
||||
return (
|
||||
this.byParent[parentName]
|
||||
this.legacyWidgets[parentName]
|
||||
// previously, custom widgets were provided as a single instance, but that has the disadvantage
|
||||
// for splits where we actually need multiple instaces and thus having a class to instantiate is better
|
||||
// https://github.com/zadam/trilium/issues/4274
|
||||
.map((w: any) => (w.prototype ? new w() : w))
|
||||
);
|
||||
}
|
||||
|
||||
getPreactWidgets(parentName: ParentName) {
|
||||
return this.preactWidgets[parentName] ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
async function getWidgetBundlesByParent() {
|
||||
const scriptBundles = await server.get<Bundle[]>("script/widgets");
|
||||
|
||||
const widgetsByParent = new WidgetsByParent();
|
||||
|
||||
for (const bundle of scriptBundles) {
|
||||
let widget;
|
||||
try {
|
||||
const scriptBundles = await server.get<Bundle[]>("script/widgets");
|
||||
|
||||
try {
|
||||
widget = await executeBundle(bundle);
|
||||
if (widget) {
|
||||
widget._noteId = bundle.noteId;
|
||||
widgetsByParent.add(widget);
|
||||
for (const bundle of scriptBundles) {
|
||||
let widget;
|
||||
|
||||
try {
|
||||
widget = await executeBundle(bundle);
|
||||
if (widget) {
|
||||
widget._noteId = bundle.noteId;
|
||||
widgetsByParent.add(widget);
|
||||
}
|
||||
} catch (e: any) {
|
||||
const noteId = bundle.noteId;
|
||||
const note = await froca.getNote(noteId);
|
||||
toastService.showPersistent({
|
||||
id: `custom-script-failure-${noteId}`,
|
||||
title: t("toast.bundle-error.title"),
|
||||
icon: "bx bx-error-circle",
|
||||
message: t("toast.bundle-error.message", {
|
||||
id: noteId,
|
||||
title: note?.title,
|
||||
message: e.message
|
||||
})
|
||||
});
|
||||
|
||||
logError("Widget initialization failed: ", e);
|
||||
continue;
|
||||
}
|
||||
} catch (e: any) {
|
||||
const noteId = bundle.noteId;
|
||||
const note = await froca.getNote(noteId);
|
||||
toastService.showPersistent({
|
||||
id: `custom-script-failure-${noteId}`,
|
||||
title: t("toast.bundle-error.title"),
|
||||
icon: "bx bx-error-circle",
|
||||
message: t("toast.bundle-error.message", {
|
||||
id: noteId,
|
||||
title: note?.title,
|
||||
message: e.message
|
||||
})
|
||||
});
|
||||
|
||||
logError("Widget initialization failed: ", e);
|
||||
continue;
|
||||
}
|
||||
} catch (e) {
|
||||
toastService.showPersistent({
|
||||
title: t("toast.widget-list-error.title"),
|
||||
message: getErrorMessage(e),
|
||||
icon: "bx bx-error-circle"
|
||||
});
|
||||
}
|
||||
|
||||
return widgetsByParent;
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
import server from "./server.js";
|
||||
import utils from "./utils.js";
|
||||
import toastService from "./toast.js";
|
||||
import linkService from "./link.js";
|
||||
import { dayjs, formatLogMessage } from "@triliumnext/commons";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import type Component from "../components/component.js";
|
||||
import type NoteContext from "../components/note_context.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
|
||||
import RightPanelWidget from "../widgets/right_panel_widget.js";
|
||||
import dateNotesService from "./date_notes.js";
|
||||
import dialogService from "./dialog.js";
|
||||
import froca from "./froca.js";
|
||||
import { preactAPI } from "./frontend_script_api_preact.js";
|
||||
import { t } from "./i18n.js";
|
||||
import linkService from "./link.js";
|
||||
import noteTooltipService from "./note_tooltip.js";
|
||||
import protectedSessionService from "./protected_session.js";
|
||||
import dateNotesService from "./date_notes.js";
|
||||
import searchService from "./search.js";
|
||||
import RightPanelWidget from "../widgets/right_panel_widget.js";
|
||||
import ws from "./ws.js";
|
||||
import appContext from "../components/app_context.js";
|
||||
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
|
||||
import BasicWidget, { ReactWrappedWidget } from "../widgets/basic_widget.js";
|
||||
import SpacedUpdate from "./spaced_update.js";
|
||||
import server from "./server.js";
|
||||
import shortcutService from "./shortcuts.js";
|
||||
import dialogService from "./dialog.js";
|
||||
import type FNote from "../entities/fnote.js";
|
||||
import { t } from "./i18n.js";
|
||||
import { dayjs } from "@triliumnext/commons";
|
||||
import type NoteContext from "../components/note_context.js";
|
||||
import type Component from "../components/component.js";
|
||||
import { formatLogMessage } from "@triliumnext/commons";
|
||||
import SpacedUpdate from "./spaced_update.js";
|
||||
import toastService from "./toast.js";
|
||||
import utils from "./utils.js";
|
||||
import ws from "./ws.js";
|
||||
|
||||
/**
|
||||
* A whole number
|
||||
@@ -464,6 +465,8 @@ export interface Api {
|
||||
* Log given message to the log pane in UI
|
||||
*/
|
||||
log(message: string | object): void;
|
||||
|
||||
preact: typeof preactAPI;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -533,9 +536,9 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
|
||||
return params.map((p) => {
|
||||
if (typeof p === "function") {
|
||||
return `!@#Function: ${p.toString()}`;
|
||||
} else {
|
||||
return p;
|
||||
}
|
||||
return p;
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@@ -562,9 +565,9 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
|
||||
await ws.waitForMaxKnownEntityChangeId();
|
||||
|
||||
return ret.executionResult;
|
||||
} else {
|
||||
throw new Error(`server error: ${ret.error}`);
|
||||
}
|
||||
throw new Error(`server error: ${ret.error}`);
|
||||
|
||||
};
|
||||
|
||||
this.runOnBackend = async (func, params = []) => {
|
||||
@@ -721,6 +724,8 @@ function FrontendScriptApi(this: Api, startNote: FNote, currentNote: FNote, orig
|
||||
this.logMessages[noteId].push(message);
|
||||
this.logSpacedUpdates[noteId].scheduleUpdate();
|
||||
};
|
||||
|
||||
this.preact = preactAPI;
|
||||
}
|
||||
|
||||
export default FrontendScriptApi as any as {
|
||||
|
||||
37
apps/client/src/services/frontend_script_api_preact.ts
Normal file
37
apps/client/src/services/frontend_script_api_preact.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { Fragment, h, VNode } from "preact";
|
||||
import * as hooks from "preact/hooks";
|
||||
|
||||
import * as triliumHooks from "../widgets/react/hooks";
|
||||
import RightPanelWidget from "../widgets/sidebar/RightPanelWidget";
|
||||
|
||||
export interface WidgetDefinition {
|
||||
parent: "right-pane",
|
||||
render: () => VNode
|
||||
}
|
||||
|
||||
export interface WidgetDefinitionWithType extends WidgetDefinition {
|
||||
type: "preact-widget"
|
||||
}
|
||||
|
||||
export const preactAPI = Object.freeze({
|
||||
// Core
|
||||
h,
|
||||
Fragment,
|
||||
|
||||
/**
|
||||
* Method that must be run for widget scripts that run on Preact, using JSX. The method just returns the same definition, reserved for future typechecking and perhaps validation purposes.
|
||||
*
|
||||
* @param definition the widget definition.
|
||||
*/
|
||||
defineWidget(definition: WidgetDefinition) {
|
||||
return {
|
||||
type: "preact-widget",
|
||||
...definition
|
||||
};
|
||||
},
|
||||
|
||||
RightPanelWidget,
|
||||
|
||||
...hooks,
|
||||
...triliumHooks
|
||||
});
|
||||
@@ -133,11 +133,11 @@ async function call<T>(method: string, url: string, componentId?: string, option
|
||||
};
|
||||
|
||||
ipc.send("server-request", {
|
||||
requestId: requestId,
|
||||
headers: headers,
|
||||
method: method,
|
||||
requestId,
|
||||
headers,
|
||||
method,
|
||||
url: `/${window.glob.baseApiUrl}${url}`,
|
||||
data: data
|
||||
data
|
||||
});
|
||||
})) as any;
|
||||
} else {
|
||||
@@ -161,7 +161,7 @@ function ajax(url: string, method: string, data: unknown, headers: Headers, sile
|
||||
const options: JQueryAjaxSettings = {
|
||||
url: window.glob.baseApiUrl + url,
|
||||
type: method,
|
||||
headers: headers,
|
||||
headers,
|
||||
timeout: 60000,
|
||||
success: (body, textStatus, jqXhr) => {
|
||||
const respHeaders: Headers = {};
|
||||
@@ -288,8 +288,8 @@ async function reportError(method: string, url: string, statusCode: number, resp
|
||||
t("server.unknown_http_error_content", { statusCode, method, url, message: messageStr }),
|
||||
15_000);
|
||||
}
|
||||
const { throwError } = await import("./ws.js");
|
||||
throwError(`${statusCode} ${method} ${url} - ${message}`);
|
||||
const { logError } = await import("./ws.js");
|
||||
logError(`${statusCode} ${method} ${url} - ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { signal } from "@preact/signals";
|
||||
|
||||
import appContext from "../components/app_context.js";
|
||||
import froca from "./froca.js";
|
||||
import { t } from "./i18n.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
export interface ToastOptions {
|
||||
@@ -61,6 +64,24 @@ function showErrorTitleAndMessage(title: string, message: string, timeout = 1000
|
||||
});
|
||||
}
|
||||
|
||||
export async function showErrorForScriptNote(noteId: string, message: string) {
|
||||
const note = await froca.getNote(noteId, true);
|
||||
|
||||
showPersistent({
|
||||
id: `custom-widget-failure-${noteId}`,
|
||||
title: note?.title ?? "",
|
||||
icon: note?.getIcon() ?? "bx bx-error-circle",
|
||||
message,
|
||||
timeout: 15_000,
|
||||
buttons: [
|
||||
{
|
||||
text: t("toast.open-script-note"),
|
||||
onClick: () => appContext.tabManager.openInNewTab(noteId, null, true)
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
//#region Toast store
|
||||
export const toasts = signal<ToastOptionsWithRequiredId[]>([]);
|
||||
|
||||
@@ -74,7 +95,7 @@ function addToast(opts: ToastOptions) {
|
||||
function updateToast(id: string, partial: Partial<ToastOptions>) {
|
||||
toasts.value = toasts.value.map(toast => {
|
||||
if (toast.id === id) {
|
||||
return { ...toast, ...partial }
|
||||
return { ...toast, ...partial };
|
||||
}
|
||||
return toast;
|
||||
});
|
||||
|
||||
@@ -22,7 +22,15 @@
|
||||
"bundle-error": {
|
||||
"title": "Failed to load a custom script",
|
||||
"message": "Script from note with ID \"{{id}}\", titled \"{{title}}\" could not be executed due to:\n\n{{message}}"
|
||||
}
|
||||
},
|
||||
"widget-list-error": {
|
||||
"title": "Failed to obtain the list of widgets from the server"
|
||||
},
|
||||
"widget-render-error": {
|
||||
"title": "Failed to render a custom React widget"
|
||||
},
|
||||
"widget-missing-parent": "Custom widget does not have mandatory '{{property}}' property defined.",
|
||||
"open-script-note": "Open script note"
|
||||
},
|
||||
"add_link": {
|
||||
"add_link": "Add link",
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { isValidElement, VNode } from "preact";
|
||||
|
||||
import Component, { TypedComponent } from "../components/component.js";
|
||||
import froca from "../services/froca.js";
|
||||
import { t } from "../services/i18n.js";
|
||||
import toastService from "../services/toast.js";
|
||||
import toastService, { showErrorForScriptNote } from "../services/toast.js";
|
||||
import { renderReactWidget } from "./react/react_utils.jsx";
|
||||
|
||||
export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedComponent<T> {
|
||||
@@ -56,9 +57,9 @@ export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedCompon
|
||||
optChild(condition: boolean, ...components: (T | VNode)[]) {
|
||||
if (condition) {
|
||||
return this.child(...components);
|
||||
} else {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
id(id: string) {
|
||||
@@ -172,16 +173,11 @@ export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedCompon
|
||||
const noteId = this._noteId;
|
||||
if (this._noteId) {
|
||||
froca.getNote(noteId, true).then((note) => {
|
||||
toastService.showPersistent({
|
||||
id: `custom-widget-failure-${noteId}`,
|
||||
title: t("toast.widget-error.title"),
|
||||
icon: "bx bx-error-circle",
|
||||
message: t("toast.widget-error.message-custom", {
|
||||
id: noteId,
|
||||
title: note?.title,
|
||||
message: e.message || e.toString()
|
||||
})
|
||||
});
|
||||
showErrorForScriptNote(noteId, t("toast.widget-error.message-custom", {
|
||||
id: noteId,
|
||||
title: note?.title,
|
||||
message: e.message || e.toString()
|
||||
}));
|
||||
});
|
||||
} else {
|
||||
toastService.showPersistent({
|
||||
@@ -213,7 +209,7 @@ export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedCompon
|
||||
|
||||
toggleInt(show: boolean | null | undefined) {
|
||||
this.$widget.toggleClass("hidden-int", !show)
|
||||
.toggleClass("visible", !!show);
|
||||
.toggleClass("visible", !!show);
|
||||
}
|
||||
|
||||
isHiddenInt() {
|
||||
@@ -222,7 +218,7 @@ export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedCompon
|
||||
|
||||
toggleExt(show: boolean | null | "" | undefined) {
|
||||
this.$widget.toggleClass("hidden-ext", !show)
|
||||
.toggleClass("visible", !!show);
|
||||
.toggleClass("visible", !!show);
|
||||
}
|
||||
|
||||
isHiddenExt() {
|
||||
@@ -250,9 +246,9 @@ export class TypedBasicWidget<T extends TypedComponent<any>> extends TypedCompon
|
||||
getClosestNtxId() {
|
||||
if (this.$widget) {
|
||||
return this.$widget.closest("[data-ntx-id]").attr("data-ntx-id");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
cleanup() {}
|
||||
|
||||
@@ -2,10 +2,11 @@
|
||||
import "./RightPanelContainer.css";
|
||||
|
||||
import Split from "@triliumnext/split.js";
|
||||
import { VNode } from "preact";
|
||||
import { isValidElement, VNode } from "preact";
|
||||
import { useEffect, useRef } from "preact/hooks";
|
||||
|
||||
import appContext from "../../components/app_context";
|
||||
import { WidgetsByParent } from "../../services/bundle";
|
||||
import { t } from "../../services/i18n";
|
||||
import options from "../../services/options";
|
||||
import { DEFAULT_GUTTER_SIZE } from "../../services/resizer";
|
||||
@@ -26,9 +27,9 @@ interface RightPanelWidgetDefinition {
|
||||
position: number;
|
||||
}
|
||||
|
||||
export default function RightPanelContainer({ customWidgets }: { customWidgets: BasicWidget[] }) {
|
||||
export default function RightPanelContainer({ widgetsByParent }: { widgetsByParent: WidgetsByParent }) {
|
||||
const [ rightPaneVisible, setRightPaneVisible ] = useTriliumOptionBool("rightPaneVisible");
|
||||
const items = useItems(rightPaneVisible, customWidgets);
|
||||
const items = useItems(rightPaneVisible, widgetsByParent);
|
||||
useSplit(rightPaneVisible);
|
||||
|
||||
return (
|
||||
@@ -51,7 +52,7 @@ export default function RightPanelContainer({ customWidgets }: { customWidgets:
|
||||
);
|
||||
}
|
||||
|
||||
function useItems(rightPaneVisible: boolean, customWidgets: BasicWidget[]) {
|
||||
function useItems(rightPaneVisible: boolean, widgetsByParent: WidgetsByParent) {
|
||||
const { note } = useActiveNoteContext();
|
||||
const noteType = useNoteProperty(note, "type");
|
||||
const [ highlightsList ] = useTriliumOptionJson<string[]>("highlightsList");
|
||||
@@ -68,11 +69,18 @@ function useItems(rightPaneVisible: boolean, customWidgets: BasicWidget[]) {
|
||||
enabled: noteType === "text" && highlightsList.length > 0,
|
||||
position: 20,
|
||||
},
|
||||
...customWidgets.map((w, i) => ({
|
||||
el: <CustomWidget key={w._noteId} originalWidget={w as LegacyRightPanelWidget} />,
|
||||
...widgetsByParent.getLegacyWidgets("right-pane").map((widget, i) => ({
|
||||
el: <CustomLegacyWidget key={widget._noteId} originalWidget={widget as LegacyRightPanelWidget} />,
|
||||
enabled: true,
|
||||
position: w.position ?? 30 + i * 10
|
||||
}))
|
||||
position: widget.position ?? 30 + i * 10
|
||||
})),
|
||||
...widgetsByParent.getPreactWidgets("right-pane").map((widget) => {
|
||||
const El = widget.render;
|
||||
return {
|
||||
el: <El />,
|
||||
enabled: true
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
return definitions
|
||||
@@ -99,7 +107,7 @@ function useSplit(visible: boolean) {
|
||||
}, [ visible ]);
|
||||
}
|
||||
|
||||
function CustomWidget({ originalWidget }: { originalWidget: LegacyRightPanelWidget }) {
|
||||
function CustomLegacyWidget({ originalWidget }: { originalWidget: LegacyRightPanelWidget }) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
return (
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
"dependencies": {
|
||||
"better-sqlite3": "12.5.0",
|
||||
"html-to-text": "9.0.5",
|
||||
"node-html-parser": "7.0.1"
|
||||
"node-html-parser": "7.0.1",
|
||||
"sucrase": "3.35.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@anthropic-ai/sdk": "0.71.2",
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
"use strict";
|
||||
|
||||
import protectedSessionService from "../../services/protected_session.js";
|
||||
import log from "../../services/log.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import optionService from "../../services/options.js";
|
||||
import eraseService from "../../services/erase.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import dateUtils from "../../services/date_utils.js";
|
||||
import AbstractBeccaEntity from "./abstract_becca_entity.js";
|
||||
import BRevision from "./brevision.js";
|
||||
import BAttachment from "./battachment.js";
|
||||
import TaskContext from "../../services/task_context.js";
|
||||
import { dayjs } from "@triliumnext/commons";
|
||||
import eventService from "../../services/events.js";
|
||||
import type { AttachmentRow, AttributeType, CloneResponse, NoteRow, NoteType, RevisionRow } from "@triliumnext/commons";
|
||||
import type BBranch from "./bbranch.js";
|
||||
import BAttribute from "./battribute.js";
|
||||
import type { NotePojo } from "../becca-interface.js";
|
||||
import searchService from "../../services/search/services/search.js";
|
||||
import { dayjs } from "@triliumnext/commons";
|
||||
|
||||
import cloningService from "../../services/cloning.js";
|
||||
import noteService from "../../services/notes.js";
|
||||
import dateUtils from "../../services/date_utils.js";
|
||||
import eraseService from "../../services/erase.js";
|
||||
import eventService from "../../services/events.js";
|
||||
import handlers from "../../services/handlers.js";
|
||||
import log from "../../services/log.js";
|
||||
import noteService from "../../services/notes.js";
|
||||
import optionService from "../../services/options.js";
|
||||
import protectedSessionService from "../../services/protected_session.js";
|
||||
import searchService from "../../services/search/services/search.js";
|
||||
import sql from "../../services/sql.js";
|
||||
import TaskContext from "../../services/task_context.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import type { NotePojo } from "../becca-interface.js";
|
||||
import AbstractBeccaEntity from "./abstract_becca_entity.js";
|
||||
import BAttachment from "./battachment.js";
|
||||
import BAttribute from "./battribute.js";
|
||||
import type BBranch from "./bbranch.js";
|
||||
import BRevision from "./brevision.js";
|
||||
|
||||
const LABEL = "label";
|
||||
const RELATION = "relation";
|
||||
@@ -296,6 +295,10 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
);
|
||||
}
|
||||
|
||||
isJsx() {
|
||||
return (this.type === "code" && this.mime === "text/jsx");
|
||||
}
|
||||
|
||||
/** @returns true if this note is HTML */
|
||||
isHtml() {
|
||||
return ["code", "file", "render"].includes(this.type) && this.mime === "text/html";
|
||||
@@ -355,9 +358,9 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
return this.__attributeCache.filter((attr) => attr.type === type);
|
||||
} else if (name) {
|
||||
return this.__attributeCache.filter((attr) => attr.name === name);
|
||||
} else {
|
||||
return this.__attributeCache;
|
||||
}
|
||||
return this.__attributeCache;
|
||||
|
||||
}
|
||||
|
||||
private __ensureAttributeCacheIsAvailable() {
|
||||
@@ -692,9 +695,9 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
return this.ownedAttributes.filter((attr) => attr.type === type);
|
||||
} else if (name) {
|
||||
return this.ownedAttributes.filter((attr) => attr.name === name);
|
||||
} else {
|
||||
return this.ownedAttributes;
|
||||
}
|
||||
return this.ownedAttributes;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -745,9 +748,9 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
return 1;
|
||||
} else if (a.parentNote?.isHiddenCompletely()) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
});
|
||||
|
||||
this.parents = this.parentBranches.map((branch) => branch.parentNote).filter((note) => !!note) as BNote[];
|
||||
@@ -1178,9 +1181,9 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
return a.isArchived ? 1 : -1;
|
||||
} else if (a.isHidden !== b.isHidden) {
|
||||
return a.isHidden ? 1 : -1;
|
||||
} else {
|
||||
return a.notePath.length - b.notePath.length;
|
||||
}
|
||||
return a.notePath.length - b.notePath.length;
|
||||
|
||||
});
|
||||
|
||||
return notePaths;
|
||||
@@ -1257,9 +1260,9 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
} else {
|
||||
new BAttribute({
|
||||
noteId: this.noteId,
|
||||
type: type,
|
||||
name: name,
|
||||
value: value
|
||||
type,
|
||||
name,
|
||||
value
|
||||
}).save();
|
||||
}
|
||||
}
|
||||
@@ -1292,11 +1295,11 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
addAttribute(type: AttributeType, name: string, value: string = "", isInheritable: boolean = false, position: number | null = null): BAttribute {
|
||||
return new BAttribute({
|
||||
noteId: this.noteId,
|
||||
type: type,
|
||||
name: name,
|
||||
value: value,
|
||||
isInheritable: isInheritable,
|
||||
position: position
|
||||
type,
|
||||
name,
|
||||
value,
|
||||
isInheritable,
|
||||
position
|
||||
}).save();
|
||||
}
|
||||
|
||||
@@ -1470,10 +1473,10 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
role: "image",
|
||||
mime: this.mime,
|
||||
title: this.title,
|
||||
content: content
|
||||
content
|
||||
});
|
||||
|
||||
let parentContent = parentNote.getContent();
|
||||
const parentContent = parentNote.getContent();
|
||||
|
||||
const oldNoteUrl = `api/images/${this.noteId}/`;
|
||||
const newAttachmentUrl = `api/attachments/${attachment.attachmentId}/image/`;
|
||||
@@ -1712,14 +1715,14 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
} else if (this.type === "text") {
|
||||
if (this.isFolder()) {
|
||||
return "bx bx-folder";
|
||||
} else {
|
||||
return "bx bx-note";
|
||||
}
|
||||
return "bx bx-note";
|
||||
|
||||
} else if (this.type === "code" && this.mime.startsWith("text/x-sql")) {
|
||||
return "bx bx-data";
|
||||
} else {
|
||||
return NOTE_TYPE_ICONS[this.type];
|
||||
}
|
||||
return NOTE_TYPE_ICONS[this.type];
|
||||
|
||||
}
|
||||
|
||||
// TODO: Deduplicate with fnote
|
||||
@@ -1729,7 +1732,7 @@ class BNote extends AbstractBeccaEntity<BNote> {
|
||||
|
||||
// TODO: Deduplicate with fnote
|
||||
getFilteredChildBranches() {
|
||||
let childBranches = this.getChildBranches();
|
||||
const childBranches = this.getChildBranches();
|
||||
|
||||
if (!childBranches) {
|
||||
console.error(`No children for '${this.noteId}'. This shouldn't happen.`);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { trimIndentation } from "@triliumnext/commons";
|
||||
|
||||
import becca from "../becca/becca.js";
|
||||
import { note, NoteBuilder } from "../test/becca_mocking.js";
|
||||
import cls from "./cls.js";
|
||||
import { executeBundle, getScriptBundle } from "./script.js";
|
||||
import BBranch from "../becca/entities/bbranch.js";
|
||||
import BNote from "../becca/entities/bnote.js";
|
||||
import { note, NoteBuilder } from "../test/becca_mocking.js";
|
||||
import cls from "./cls.js";
|
||||
import { buildJsx, executeBundle, getScriptBundle } from "./script.js";
|
||||
|
||||
|
||||
describe("Script", () => {
|
||||
@@ -84,3 +86,96 @@ describe("Script", () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("JSX building", () => {
|
||||
it("processes basic JSX", () => {
|
||||
const script = trimIndentation`\
|
||||
function MyComponent() {
|
||||
return <p>Hello world.</p>;
|
||||
}
|
||||
`;
|
||||
const expected = trimIndentation`\
|
||||
"use strict";const _jsxFileName = "";function MyComponent() {
|
||||
return api.preact.h('p', {__self: this, __source: {fileName: _jsxFileName, lineNumber: 2}}, "Hello world." );
|
||||
}
|
||||
`;
|
||||
expect(buildJsx(script).code).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it("processes fragments", () => {
|
||||
const script = trimIndentation`\
|
||||
function MyComponent() {
|
||||
return <>
|
||||
<p>Hi</p>
|
||||
<p>there</p>
|
||||
</>;
|
||||
}
|
||||
`;
|
||||
const expected = trimIndentation`\
|
||||
"use strict";const _jsxFileName = "";function MyComponent() {
|
||||
return api.preact.h(api.preact.Fragment, null
|
||||
, api.preact.h('p', {__self: this, __source: {fileName: _jsxFileName, lineNumber: 3}}, "Hi")
|
||||
, api.preact.h('p', {__self: this, __source: {fileName: _jsxFileName, lineNumber: 4}}, "there")
|
||||
);
|
||||
}
|
||||
`;
|
||||
expect(buildJsx(script).code).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it("rewrites export", () => {
|
||||
const script = trimIndentation`\
|
||||
const { defineWidget } = api.preact;
|
||||
|
||||
export default defineWidget({
|
||||
parent: "right-pane",
|
||||
render() {
|
||||
return <></>;
|
||||
}
|
||||
});
|
||||
`;
|
||||
const expected = trimIndentation`\
|
||||
"use strict";Object.defineProperty(exports, "__esModule", {value: true});const { defineWidget } = api.preact;
|
||||
|
||||
module.exports = defineWidget({
|
||||
parent: "right-pane",
|
||||
render() {
|
||||
return api.preact.h(api.preact.Fragment, null);
|
||||
}
|
||||
});
|
||||
`;
|
||||
expect(buildJsx(script).code).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it("rewrites React API imports", () => {
|
||||
const script = trimIndentation`\
|
||||
import { defineWidget, RightPanelWidget} from "trilium:preact";
|
||||
defineWidget({
|
||||
render() {
|
||||
return <RightPanelWidget />;
|
||||
}
|
||||
});
|
||||
`;
|
||||
const expected = trimIndentation`\
|
||||
"use strict";const _jsxFileName = "";const _triliumpreact = api.preact;
|
||||
_triliumpreact.defineWidget.call(void 0, {
|
||||
render() {
|
||||
return api.preact.h(_triliumpreact.RightPanelWidget, {__self: this, __source: {fileName: _jsxFileName, lineNumber: 4}} );
|
||||
}
|
||||
});
|
||||
`;
|
||||
expect(buildJsx(script).code).toStrictEqual(expected);
|
||||
});
|
||||
|
||||
it("rewrites internal API imports", () => {
|
||||
const script = trimIndentation`\
|
||||
import { log } from "trilium:api";
|
||||
log("Hi");
|
||||
`;
|
||||
const expected = trimIndentation`\
|
||||
"use strict";const _triliumapi = api;
|
||||
_triliumapi.log.call(void 0, "Hi");
|
||||
`;
|
||||
console.log(buildJsx(script).code);
|
||||
expect(buildJsx(script).code).toStrictEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import ScriptContext from "./script_context.js";
|
||||
import cls from "./cls.js";
|
||||
import log from "./log.js";
|
||||
import { transform } from "sucrase";
|
||||
|
||||
import becca from "../becca/becca.js";
|
||||
import type BNote from "../becca/entities/bnote.js";
|
||||
import type { ApiParams } from "./backend_script_api_interface.js";
|
||||
import cls from "./cls.js";
|
||||
import log from "./log.js";
|
||||
import ScriptContext from "./script_context.js";
|
||||
|
||||
export interface Bundle {
|
||||
note?: BNote;
|
||||
@@ -110,9 +112,9 @@ function getParams(params?: ScriptParams) {
|
||||
.map((p) => {
|
||||
if (typeof p === "string" && p.startsWith("!@#Function: ")) {
|
||||
return p.substr(13);
|
||||
} else {
|
||||
return JSON.stringify(p);
|
||||
}
|
||||
return JSON.stringify(p);
|
||||
|
||||
})
|
||||
.join(",");
|
||||
}
|
||||
@@ -145,7 +147,7 @@ export function getScriptBundle(note: BNote, root: boolean = true, scriptEnv: st
|
||||
return;
|
||||
}
|
||||
|
||||
if (!note.isJavaScript() && !note.isHtml()) {
|
||||
if (!(note.isJavaScript() || note.isHtml() || note.isJsx())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -158,7 +160,7 @@ export function getScriptBundle(note: BNote, root: boolean = true, scriptEnv: st
|
||||
}
|
||||
|
||||
const bundle: Bundle = {
|
||||
note: note,
|
||||
note,
|
||||
script: "",
|
||||
html: "",
|
||||
allNotes: [note]
|
||||
@@ -192,12 +194,18 @@ export function getScriptBundle(note: BNote, root: boolean = true, scriptEnv: st
|
||||
// only frontend scripts are async. Backend cannot be async because of transaction management.
|
||||
const isFrontend = scriptEnv === "frontend";
|
||||
|
||||
if (note.isJavaScript()) {
|
||||
if (note.isJsx() || note.isJavaScript()) {
|
||||
let scriptContent = note.getContent();
|
||||
|
||||
if (note.isJsx()) {
|
||||
scriptContent = buildJsx(scriptContent).code;
|
||||
}
|
||||
|
||||
bundle.script += `
|
||||
apiContext.modules['${note.noteId}'] = { exports: {} };
|
||||
${root ? "return " : ""}${isFrontend ? "await" : ""} ((${isFrontend ? "async" : ""} function(exports, module, require, api${modules.length > 0 ? ", " : ""}${modules.map((child) => sanitizeVariableName(child.title)).join(", ")}) {
|
||||
try {
|
||||
${overrideContent || note.getContent()};
|
||||
${overrideContent || scriptContent};
|
||||
} catch (e) { throw new Error("Load of script note \\"${note.title}\\" (${note.noteId}) failed with: " + e.message); }
|
||||
for (const exportKey in exports) module.exports[exportKey] = exports[exportKey];
|
||||
return module.exports;
|
||||
@@ -210,6 +218,38 @@ return module.exports;
|
||||
return bundle;
|
||||
}
|
||||
|
||||
export function buildJsx(contentRaw: string | Buffer) {
|
||||
const content = Buffer.isBuffer(contentRaw) ? contentRaw.toString("utf-8") : contentRaw;
|
||||
const output = transform(content, {
|
||||
transforms: ["jsx", "imports"],
|
||||
jsxPragma: "api.preact.h",
|
||||
jsxFragmentPragma: "api.preact.Fragment",
|
||||
});
|
||||
|
||||
let code = output.code;
|
||||
|
||||
// Rewrite ESM-like exports to `module.exports =`.
|
||||
code = output.code.replaceAll(
|
||||
/\bexports\s*\.\s*default\s*=\s*/g,
|
||||
'module.exports = '
|
||||
);
|
||||
|
||||
// Rewrite ESM-like imports to Preact, to `const { foo } = api.preact`
|
||||
code = code.replaceAll(
|
||||
/var\s+(\w+)\s*=\s*require\(['"]trilium:preact['"]\);?/g,
|
||||
'const $1 = api.preact;'
|
||||
);
|
||||
|
||||
// Rewrite ESM-like imports to internal API, to `const { foo } = api.preact`
|
||||
code = code.replaceAll(
|
||||
/var\s+(\w+)\s*=\s*require\(['"]trilium:api['"]\);?/g,
|
||||
'const $1 = api;'
|
||||
);
|
||||
|
||||
output.code = code;
|
||||
return output;
|
||||
}
|
||||
|
||||
function sanitizeVariableName(str: string) {
|
||||
return str.replace(/[^a-z0-9_]/gim, "");
|
||||
}
|
||||
|
||||
71
pnpm-lock.yaml
generated
71
pnpm-lock.yaml
generated
@@ -295,6 +295,9 @@ importers:
|
||||
reveal.js:
|
||||
specifier: 5.2.1
|
||||
version: 5.2.1
|
||||
sucrase:
|
||||
specifier: 3.35.1
|
||||
version: 3.35.1
|
||||
svg-pan-zoom:
|
||||
specifier: 3.6.2
|
||||
version: 3.6.2
|
||||
@@ -494,6 +497,9 @@ importers:
|
||||
node-html-parser:
|
||||
specifier: 7.0.1
|
||||
version: 7.0.1
|
||||
sucrase:
|
||||
specifier: 3.35.1
|
||||
version: 3.35.1
|
||||
devDependencies:
|
||||
'@anthropic-ai/sdk':
|
||||
specifier: 0.71.2
|
||||
@@ -6255,6 +6261,9 @@ packages:
|
||||
any-base@1.1.0:
|
||||
resolution: {integrity: sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==}
|
||||
|
||||
any-promise@1.3.0:
|
||||
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
|
||||
|
||||
anymatch@3.1.3:
|
||||
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -6951,6 +6960,10 @@ packages:
|
||||
commander@2.20.3:
|
||||
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
|
||||
|
||||
commander@4.1.1:
|
||||
resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
commander@5.1.0:
|
||||
resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==}
|
||||
engines: {node: '>= 6'}
|
||||
@@ -10618,6 +10631,9 @@ packages:
|
||||
resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
|
||||
engines: {node: ^18.17.0 || >=20.5.0}
|
||||
|
||||
mz@2.7.0:
|
||||
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
|
||||
|
||||
nan@2.22.2:
|
||||
resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==}
|
||||
|
||||
@@ -11238,6 +11254,10 @@ packages:
|
||||
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
pirates@4.0.7:
|
||||
resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
pixelmatch@5.3.0:
|
||||
resolution: {integrity: sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==}
|
||||
hasBin: true
|
||||
@@ -13136,6 +13156,11 @@ packages:
|
||||
stylis@4.3.6:
|
||||
resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==}
|
||||
|
||||
sucrase@3.35.1:
|
||||
resolution: {integrity: sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==}
|
||||
engines: {node: '>=16 || 14 >=14.17'}
|
||||
hasBin: true
|
||||
|
||||
sugarss@4.0.1:
|
||||
resolution: {integrity: sha512-WCjS5NfuVJjkQzK10s8WOBY+hhDxxNt/N6ZaGwxFZ+wN3/lKKFSaaKUNecULcTTvE4urLcKaZFQD8vO0mOZujw==}
|
||||
engines: {node: '>=12.0'}
|
||||
@@ -13279,6 +13304,13 @@ packages:
|
||||
text-decoder@1.2.3:
|
||||
resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==}
|
||||
|
||||
thenify-all@1.6.0:
|
||||
resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
|
||||
engines: {node: '>=0.8'}
|
||||
|
||||
thenify@3.3.1:
|
||||
resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
|
||||
|
||||
thingies@2.5.0:
|
||||
resolution: {integrity: sha512-s+2Bwztg6PhWUD7XMfeYm5qliDdSiZm7M7n8KjTkIsm3l/2lgVRc2/Gx/v+ZX8lT4FMA+i8aQvhcWylldc+ZNw==}
|
||||
engines: {node: '>=10.18'}
|
||||
@@ -13430,6 +13462,9 @@ packages:
|
||||
resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==}
|
||||
engines: {node: '>=6.10'}
|
||||
|
||||
ts-interface-checker@0.1.13:
|
||||
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
||||
|
||||
ts-loader@9.5.4:
|
||||
resolution: {integrity: sha512-nCz0rEwunlTZiy6rXFByQU1kVVpCIgUpc/psFiKVrUwrizdnIbRFu8w7bxhUF0X613DYwT4XzrZHpVyMe758hQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
@@ -15225,6 +15260,8 @@ snapshots:
|
||||
'@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:
|
||||
@@ -15290,8 +15327,6 @@ snapshots:
|
||||
'@ckeditor/ckeditor5-utils': 47.3.0
|
||||
'@ckeditor/ckeditor5-watchdog': 47.3.0
|
||||
es-toolkit: 1.39.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@ckeditor/ckeditor5-dev-build-tools@54.2.2(@swc/helpers@0.5.17)(tslib@2.8.1)(typescript@5.9.3)':
|
||||
dependencies:
|
||||
@@ -21149,6 +21184,8 @@ snapshots:
|
||||
|
||||
any-base@1.1.0: {}
|
||||
|
||||
any-promise@1.3.0: {}
|
||||
|
||||
anymatch@3.1.3:
|
||||
dependencies:
|
||||
normalize-path: 3.0.0
|
||||
@@ -22097,6 +22134,8 @@ snapshots:
|
||||
|
||||
commander@2.20.3: {}
|
||||
|
||||
commander@4.1.1: {}
|
||||
|
||||
commander@5.1.0: {}
|
||||
|
||||
commander@6.2.0: {}
|
||||
@@ -26816,6 +26855,12 @@ snapshots:
|
||||
mute-stream@2.0.0:
|
||||
optional: true
|
||||
|
||||
mz@2.7.0:
|
||||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
object-assign: 4.1.1
|
||||
thenify-all: 1.6.0
|
||||
|
||||
nan@2.22.2:
|
||||
optional: true
|
||||
|
||||
@@ -27473,6 +27518,8 @@ snapshots:
|
||||
pify@4.0.1:
|
||||
optional: true
|
||||
|
||||
pirates@4.0.7: {}
|
||||
|
||||
pixelmatch@5.3.0:
|
||||
dependencies:
|
||||
pngjs: 6.0.0
|
||||
@@ -29714,6 +29761,16 @@ snapshots:
|
||||
|
||||
stylis@4.3.6: {}
|
||||
|
||||
sucrase@3.35.1:
|
||||
dependencies:
|
||||
'@jridgewell/gen-mapping': 0.3.13
|
||||
commander: 4.1.1
|
||||
lines-and-columns: 1.2.4
|
||||
mz: 2.7.0
|
||||
pirates: 4.0.7
|
||||
tinyglobby: 0.2.15
|
||||
ts-interface-checker: 0.1.13
|
||||
|
||||
sugarss@4.0.1(postcss@8.5.6):
|
||||
dependencies:
|
||||
postcss: 8.5.6
|
||||
@@ -29950,6 +30007,14 @@ snapshots:
|
||||
dependencies:
|
||||
b4a: 1.6.7
|
||||
|
||||
thenify-all@1.6.0:
|
||||
dependencies:
|
||||
thenify: 3.3.1
|
||||
|
||||
thenify@3.3.1:
|
||||
dependencies:
|
||||
any-promise: 1.3.0
|
||||
|
||||
thingies@2.5.0(tslib@2.8.1):
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
@@ -30085,6 +30150,8 @@ snapshots:
|
||||
|
||||
ts-dedent@2.2.0: {}
|
||||
|
||||
ts-interface-checker@0.1.13: {}
|
||||
|
||||
ts-loader@9.5.4(typescript@5.0.4)(webpack@5.101.3(@swc/core@1.11.29(@swc/helpers@0.5.17))(esbuild@0.27.2)):
|
||||
dependencies:
|
||||
chalk: 4.1.2
|
||||
|
||||
Reference in New Issue
Block a user