1
0

Lots of tweaks

This commit is contained in:
Zef Hemel 2022-05-09 14:59:12 +02:00
parent 35dc75d94e
commit f6758dbbaf
25 changed files with 336 additions and 62 deletions

View File

@ -46,24 +46,36 @@ export function filterBox(
return syscall("editor.filterBox", label, options, helpText, placeHolder);
}
export function showRhs(html: string, flex = 1): Promise<void> {
return syscall("editor.showRhs", html, flex);
export function showRhs(
html: string,
script?: string,
flex = 1
): Promise<void> {
return syscall("editor.showRhs", html, script, flex);
}
export function hideRhs(): Promise<void> {
return syscall("editor.hideRhs");
}
export function showLhs(html: string, flex = 1): Promise<void> {
return syscall("editor.showLhs", html, flex);
export function showLhs(
html: string,
script?: string,
flex = 1
): Promise<void> {
return syscall("editor.showLhs", html, script, flex);
}
export function hideLhs(): Promise<void> {
return syscall("editor.hideLhs");
}
export function showBhs(html: string, flex = 1): Promise<void> {
return syscall("editor.showBhs", html, flex);
export function showBhs(
html: string,
script?: string,
flex = 1
): Promise<void> {
return syscall("editor.showBhs", html, script, flex);
}
export function hideBhs(): Promise<void> {

View File

@ -0,0 +1,5 @@
import type { LogEntry } from "@plugos/plugos/sandbox";
export async function getServerLogs(): Promise<LogEntry[]> {
return syscall("sandbox.getServerLogs");
}

View File

@ -0,0 +1,5 @@
import type { LogEntry } from "@plugos/plugos/sandbox";
export async function getLogs(): Promise<LogEntry[]> {
return syscall("sandbox.getLogs");
}

View File

@ -0,0 +1,61 @@
export type LogLevel = "info" | "warn" | "error" | "log";
export class ConsoleLogger {
print: boolean;
callback: (level: LogLevel, entry: string) => void;
constructor(
callback: (level: LogLevel, entry: string) => void,
print: boolean = true
) {
this.print = print;
this.callback = callback;
}
log(...args: any[]): void {
this.push("log", args);
}
warn(...args: any[]): void {
this.push("warn", args);
}
error(...args: any[]): void {
this.push("error", args);
}
info(...args: any[]): void {
this.push("info", args);
}
push(level: LogLevel, args: any[]) {
this.callback(level, this.logMessage(args));
if (this.print) {
console[level](...args);
}
}
logMessage(values: any[]): string {
let pieces: string[] = [];
for (let val of values) {
switch (typeof val) {
case "string":
case "number":
pieces.push("" + val);
break;
default:
try {
let s = JSON.stringify(val, null, 2);
if (s.length > 500) {
s = s.substring(0, 500) + "...";
}
pieces.push(s);
} catch {
// May be cyclical reference
pieces.push("[circular object]");
}
}
}
return pieces.join(" ");
}
}

View File

@ -1,3 +1,5 @@
import { ConsoleLogger } from "./custom_logger";
const {
parentPort,
workerData: { preloadedModules, nodeModulesPath },
@ -16,10 +18,18 @@ let pendingRequests = new Map<
let syscallReqId = 0;
let consoleLogger = new ConsoleLogger((level, message) => {
parentPort.postMessage({
type: "log",
level,
message,
});
}, false);
let vm = new VM({
sandbox: {
// Exposing some "safe" APIs
console,
console: consoleLogger,
setTimeout,
clearTimeout,
setInterval,

View File

@ -1,4 +1,5 @@
import { safeRun } from "../util";
import { ConsoleLogger } from "./custom_logger";
import { ControllerMessage, WorkerMessage } from "./worker";
let loadedFunctions = new Map<string, Function>();
@ -53,6 +54,11 @@ self.require = (moduleName: string): any => {
return preloadedModules[moduleName];
};
// @ts-ignore
self.console = new ConsoleLogger((level, message) => {
workerPostMessage({ type: "log", level, message });
}, false);
function wrapScript(code: string) {
return `return (${code})["default"]`;
}

View File

@ -1,11 +1,14 @@
export type ControllerMessageType = "inited" | "result" | "syscall";
import type { LogLevel } from "./custom_logger";
export type ControllerMessageType = "inited" | "result" | "syscall" | "log";
export type ControllerMessage = {
type: ControllerMessageType;
id?: number;
name?: string;
args?: any[];
error?: string;
level?: LogLevel;
message?: string;
result?: any;
};

View File

@ -1,8 +1,19 @@
import { ControllerMessage, WorkerLike, WorkerMessage } from "./environments/worker";
import type { LogLevel } from "./environments/custom_logger";
import {
ControllerMessage,
WorkerLike,
WorkerMessage,
} from "./environments/worker";
import { Plug } from "./plug";
export type SandboxFactory<HookT> = (plug: Plug<HookT>) => Sandbox;
export type LogEntry = {
level: LogLevel;
message: string;
date: number;
};
export class Sandbox {
protected worker: WorkerLike;
protected reqId = 0;
@ -13,6 +24,8 @@ export class Sandbox {
>();
protected loadedFunctions = new Set<string>();
protected plug: Plug<any>;
public logBuffer: LogEntry[] = [];
public maxLogBufferSize = 100;
constructor(plug: Plug<any>, worker: WorkerLike) {
worker.onMessage = this.onMessage.bind(this);
@ -84,6 +97,17 @@ export class Sandbox {
resultCbs && resultCbs.resolve(data.result);
}
break;
case "log":
this.logBuffer.push({
level: data.level!,
message: data.message!,
date: Date.now(),
});
if (this.logBuffer.length > this.maxLogBufferSize) {
this.logBuffer.shift();
}
console.log(`[Sandbox ${data.level}]`, data.message);
break;
default:
console.error("Unknown message type", data);
}

View File

@ -0,0 +1,15 @@
import { LogEntry } from "../sandbox";
import { SysCallMapping, System } from "../system";
export default function sandboxSyscalls(system: System<any>): SysCallMapping {
return {
"sandbox.getLogs": async (ctx): Promise<LogEntry[]> => {
let allLogs: LogEntry[] = [];
for (let plug of system.loadedPlugs.values()) {
allLogs = allLogs.concat(plug.sandbox.logBuffer);
}
allLogs = allLogs.sort((a, b) => a.date - b.date);
return allLogs;
},
};
}

View File

@ -232,20 +232,20 @@ function $11a7e2bff790f35a$export$4f02334034b5dd8c(message) {
function $11a7e2bff790f35a$export$83b9d7a71bc0a208(label, options, helpText = "", placeHolder = "") {
return $4ba3510c824e3aea$export$c5be9092dbf465c("editor.filterBox", label, options, helpText, placeHolder);
}
function $11a7e2bff790f35a$export$53ed0b99a5f8822e(html, flex = 1) {
return $4ba3510c824e3aea$export$c5be9092dbf465c("editor.showRhs", html, flex);
function $11a7e2bff790f35a$export$53ed0b99a5f8822e(html, script, flex = 1) {
return $4ba3510c824e3aea$export$c5be9092dbf465c("editor.showRhs", html, script, flex);
}
function $11a7e2bff790f35a$export$f19f28e8a128fabe() {
return $4ba3510c824e3aea$export$c5be9092dbf465c("editor.hideRhs");
}
function $11a7e2bff790f35a$export$dcf0ace441f4b3a4(html, flex = 1) {
return $4ba3510c824e3aea$export$c5be9092dbf465c("editor.showLhs", html, flex);
function $11a7e2bff790f35a$export$dcf0ace441f4b3a4(html, script, flex = 1) {
return $4ba3510c824e3aea$export$c5be9092dbf465c("editor.showLhs", html, script, flex);
}
function $11a7e2bff790f35a$export$1be2ad20c6324dcf() {
return $4ba3510c824e3aea$export$c5be9092dbf465c("editor.hideLhs");
}
function $11a7e2bff790f35a$export$6ebe231c70cc6efb(html, flex = 1) {
return $4ba3510c824e3aea$export$c5be9092dbf465c("editor.showBhs", html, flex);
function $11a7e2bff790f35a$export$6ebe231c70cc6efb(html, script, flex = 1) {
return $4ba3510c824e3aea$export$c5be9092dbf465c("editor.showBhs", html, script, flex);
}
function $11a7e2bff790f35a$export$a7a5aa8ba1cd9dc3() {
return $4ba3510c824e3aea$export$c5be9092dbf465c("editor.hideBhs");

File diff suppressed because one or more lines are too long

View File

@ -67,9 +67,6 @@ functions:
name: "Page: Rename"
mac: Cmd-Alt-r
key: Ctrl-Alt-r
button:
label: "📝"
tooltip: "Rename page"
pageComplete:
path: "./page.ts:pageComplete"
events:
@ -93,15 +90,27 @@ functions:
slashCommand:
name: tomorrow
parseServerCommand:
path: ./page.ts:parseServerPageCommand
path: ./debug.ts:parseServerPageCommand
command:
name: "Debug: Parse Document on Server"
parsePage:
path: ./page.ts:parsePage
path: ./debug.ts:parsePage
parseCommand:
path: ./page.ts:parsePageCommand
path: ./debug.ts:parsePageCommand
command:
name: "Debug: Parse Document"
showLogsCommand:
path: ./debug.ts:showLogsCommand
command:
name: "Debug: Show Logs"
key: "Ctrl-Alt-l"
mac: "Cmd-Alt-l"
hideBhsCommand:
path: ./debug.ts:hideBhsCommand
command:
name: "UI: Hide BHS"
key: "Ctrl-Alt-b"
mac: "Cmd-Alt-b"
insertPageMeta:
path: "./page.ts:insertPageMeta"
slashCommand:
@ -111,6 +120,8 @@ functions:
command:
name: "Template: Quick Note"
key: "Alt-Shift-n"
button:
label: "🗒"
quickTaskCommand:
path: ./template.ts:quickTaskCommand
command:

View File

@ -0,0 +1,82 @@
import { getLogs } from "@plugos/plugos-syscall/sandbox";
import { LogEntry } from "@plugos/plugos/sandbox";
import {
getText,
hideBhs,
showBhs,
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
import { parseMarkdown } from "@silverbulletmd/plugos-silverbullet-syscall/markdown";
import { getServerLogs } from "@silverbulletmd/plugos-silverbullet-syscall/sandbox";
import { invokeFunction } from "@silverbulletmd/plugos-silverbullet-syscall/system";
export async function parseServerPageCommand() {
console.log(await invokeFunction("server", "parsePage", await getText()));
}
export async function parsePageCommand() {
parsePage(await getText());
}
export async function parsePage(text: string) {
console.log("AST", JSON.stringify(await parseMarkdown(text), null, 2));
}
export async function showLogsCommand() {
let clientLogs = await getLogs();
let serverLogs = await getServerLogs();
await showBhs(
`
<style>
#client-log-header {
position: absolute;
left: 0;
top: 5px;
}
#server-log-header {
position: absolute;
right: 0;
top: 5px;
width: 50%;
}
#client-log {
position: absolute;
left: 0;
top: 30px;
bottom: 0;
width: 50%;
overflow: scroll;
}
#server-log {
position: absolute;
right: 0;
top: 30px;
bottom: 0;
width: 50%;
overflow: scroll;
}
</style>
<div id="client-log-header">Client logs (max 100)</div>
<div id="client-log">
<pre>${clientLogs
.map((le) => `[${le.level}] ${le.message}`)
.join("\n")}</pre>
</div>
<div id="server-log-header">Server logs (max 100)</div>
<div id="server-log">
<pre>${serverLogs
.map((le) => `[${le.level}] ${le.message}`)
.join("\n")}</pre>
</div>`,
`
var clientDiv = document.getElementById("client-log");
clientDiv.scrollTop = clientDiv.scrollHeight;
var serverDiv = document.getElementById("server-log");
serverDiv.scrollTop = serverDiv.scrollHeight;
`
);
}
export async function hideBhsCommand() {
await hideBhs();
}

View File

@ -239,18 +239,6 @@ export async function parseIndexTextRepublish({ name, text }: IndexEvent) {
});
}
export async function parseServerPageCommand() {
console.log(await invokeFunction("server", "parsePage", await getText()));
}
export async function parsePageCommand() {
parsePage(await getText());
}
export async function parsePage(text: string) {
console.log("AST", JSON.stringify(await parseMarkdown(text), null, 2));
}
export async function insertPageMeta() {
let cursorPos = await getCursor();
await insertAtCursor("```meta\n\n```");

View File

@ -78,6 +78,7 @@ export async function updateMarkdownPreview() {
let cleanMd = await cleanMarkdown(text);
await showRhs(
`<html><head>${css}</head><body>${md.render(cleanMd)}</body></html>`,
undefined,
2
);
}

View File

@ -28,7 +28,6 @@ export async function updateMaterializedQueriesCommand() {
currentPage
);
await reloadPage();
await flashNotification("Updated materialized queries");
}
export async function whiteOutQueriesCommand() {

View File

@ -28,6 +28,7 @@ import { plugPrefix } from "@silverbulletmd/common/spaces/constants";
import { Authenticator } from "./auth";
import { nextTick } from "process";
import sandboxSyscalls from "@plugos/plugos/syscalls/sandbox";
const safeFilename = /^[a-zA-Z0-9_\-\.]+$/;
@ -90,6 +91,7 @@ export class ExpressServer {
markdownSyscalls(buildMarkdown([])),
esbuildSyscalls(),
systemSyscalls(this),
sandboxSyscalls(this.system),
jwtSyscalls()
);
this.system.addHook(new EndpointHook(this.app, "/_/"));

View File

@ -2,7 +2,15 @@ import { useEffect, useRef } from "react";
// @ts-ignore
import iframeHtml from "bundle-text:./panel.html";
export function Panel({ html, flex }: { html: string; flex: number }) {
export function Panel({
html,
script,
flex,
}: {
html: string;
script?: string;
flex: number;
}) {
const iFrameRef = useRef<HTMLIFrameElement>(null);
useEffect(() => {
function loadContent() {
@ -10,6 +18,7 @@ export function Panel({ html, flex }: { html: string; flex: number }) {
iFrameRef.current.contentWindow.postMessage({
type: "html",
html: html,
script: script,
});
}
}

View File

@ -3,6 +3,13 @@ window.addEventListener("message", (message) => {
switch (data.type) {
case "html":
document.body.innerHTML = data.html;
if (data.script) {
try {
eval(data.script);
} catch (e: any) {
console.error("Error evaling script", e);
}
}
break;
}
});

View File

@ -58,6 +58,7 @@ import {
import { FilterList } from "./components/filter";
import { FilterOption } from "@silverbulletmd/common/types";
import { syntaxTree } from "@codemirror/language";
import sandboxSyscalls from "@plugos/plugos/syscalls/sandbox";
class PageState {
constructor(
@ -120,15 +121,16 @@ export class Editor {
});
this.pageNavigator = new PathPageNavigator();
this.system.registerSyscalls([], editorSyscalls(this));
this.system.registerSyscalls([], spaceSyscalls(this));
this.system.registerSyscalls([], indexerSyscalls(this.space));
this.system.registerSyscalls([], systemSyscalls(this));
this.system.registerSyscalls(
[],
markdownSyscalls(buildMarkdown(this.mdExtensions))
editorSyscalls(this),
spaceSyscalls(this),
indexerSyscalls(this.space),
systemSyscalls(this),
markdownSyscalls(buildMarkdown(this.mdExtensions)),
clientStoreSyscalls(),
sandboxSyscalls(this.system)
);
this.system.registerSyscalls([], clientStoreSyscalls());
}
get currentPage(): string | undefined {
@ -636,16 +638,28 @@ export class Editor {
/>
<div id="main">
{!!viewState.showLHS && (
<Panel html={viewState.lhsHTML} flex={viewState.showLHS} />
<Panel
html={viewState.lhsHTML}
script={viewState.lhsScript}
flex={viewState.showLHS}
/>
)}
<div id="editor" />
{!!viewState.showRHS && (
<Panel html={viewState.rhsHTML} flex={viewState.showRHS} />
<Panel
html={viewState.rhsHTML}
script={viewState.rhsScript}
flex={viewState.showRHS}
/>
)}
</div>
{!!viewState.showBHS && (
<div id="bhs">
<Panel html={viewState.bhsHTML} flex={1} />
<Panel
html={viewState.bhsHTML}
script={viewState.bhsScript}
flex={1}
/>
</div>
)}
<StatusBar editorView={editor.editorView} />

View File

@ -72,7 +72,7 @@ export default function reducer(
case "show-notification":
return {
...state,
notifications: [action.notification, ...state.notifications],
notifications: [...state.notifications, action.notification],
};
case "dismiss-notification":
return {
@ -84,36 +84,42 @@ export default function reducer(
...state,
showRHS: action.flex,
rhsHTML: action.html,
rhsScript: action.script,
};
case "hide-rhs":
return {
...state,
showRHS: 0,
rhsHTML: "",
rhsScript: undefined,
};
case "show-lhs":
return {
...state,
showLHS: action.flex,
lhsHTML: action.html,
lhsScript: action.script,
};
case "hide-lhs":
return {
...state,
showLHS: 0,
lhsHTML: "",
lhsScript: undefined,
};
case "show-bhs":
return {
...state,
showBHS: action.flex,
bhsHTML: action.html,
bhsScript: action.script,
};
case "hide-bhs":
return {
...state,
showBHS: 0,
bhsHTML: "",
bhsScript: undefined,
};
case "show-filterbox":
return {

View File

@ -73,13 +73,18 @@ body {
font-size: 28px;
padding: 10px 20px;
.status {
float: right;
position: absolute;
font-family: "iA-Mono";
bottom: 45px;
left: 5px;
right: 5px;
background-color: rgb(187, 221, 247);
border: rgb(41, 41, 41) 1px solid;
border-radius: 5px;
padding: 3px;
font-size: 14px;
font-size: 15px;
z-index: 100;
}
.current-page {
@ -113,13 +118,10 @@ body {
font-size: 80%;
}
}
}
.panel {
flex: 1;
}
}
@ -141,10 +143,8 @@ body {
margin: 0;
}
}
}
#editor {
overflow-y: scroll;
flex: 2;
@ -152,10 +152,13 @@ body {
}
#bhs {
height: 200px;
height: 300px;
width: 100%;
border-top: rgb(193, 193, 193) 1px solid;
.panel {
height: 100%;
.panel {
iframe {
border: 0;
width: 100%;
@ -173,4 +176,5 @@ body {
text-align: right;
background-color: rgb(213, 213, 213);
border-top: rgb(193, 193, 193) 1px solid;
font-family: "iA-Mono";
}

View File

@ -71,11 +71,12 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
): Promise<FilterOption | undefined> => {
return editor.filterBox(label, options, helpText, placeHolder);
},
"editor.showRhs": (ctx, html: string, flex: number) => {
"editor.showRhs": (ctx, html: string, script: string, flex: number) => {
editor.viewDispatch({
type: "show-rhs",
flex,
html,
script,
});
},
"editor.hideRhs": (ctx) => {
@ -83,11 +84,12 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
type: "hide-rhs",
});
},
"editor.showLhs": (ctx, html: string, flex: number) => {
"editor.showLhs": (ctx, html: string, script: string, flex: number) => {
editor.viewDispatch({
type: "show-lhs",
flex,
html,
script,
});
},
"editor.hideLhs": (ctx) => {
@ -95,11 +97,12 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
type: "hide-lhs",
});
},
"editor.showBhs": (ctx, html: string, flex: number) => {
"editor.showBhs": (ctx, html: string, script: string, flex: number) => {
editor.viewDispatch({
type: "show-bhs",
flex,
html,
script,
});
},
"editor.hideBhs": (ctx) => {

View File

@ -22,5 +22,9 @@ export function systemSyscalls(editor: Editor): SysCallMapping {
"system.reloadPlugs": async () => {
return editor.reloadPlugs();
},
"sandbox.getServerLogs": async (ctx) => {
return editor.space.proxySyscall(ctx.plug, "sandbox.getLogs", []);
},
};
}

View File

@ -27,6 +27,9 @@ export type AppViewState = {
rhsHTML: string;
lhsHTML: string;
bhsHTML: string;
rhsScript?: string;
lhsScript?: string;
bhsScript?: string;
allPages: Set<PageMeta>;
commands: Map<string, AppCommand>;
notifications: Notification[];
@ -78,11 +81,11 @@ export type Action =
| { type: "hide-palette" }
| { type: "show-notification"; notification: Notification }
| { type: "dismiss-notification"; id: number }
| { type: "show-rhs"; html: string; flex: number }
| { type: "show-rhs"; html: string; flex: number; script?: string }
| { type: "hide-rhs" }
| { type: "show-lhs"; html: string; flex: number }
| { type: "show-lhs"; html: string; flex: number; script?: string }
| { type: "hide-lhs" }
| { type: "show-bhs"; html: string; flex: number }
| { type: "show-bhs"; html: string; flex: number; script?: string }
| { type: "hide-bhs" }
| {
type: "show-filterbox";