Preparing for an initial release
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
"name": "Zef Hemel",
|
||||
"email": "zef@zef.me"
|
||||
},
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.7",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "6.0.1",
|
||||
@@ -16,8 +16,12 @@
|
||||
"@codemirror/search": "6.0.0",
|
||||
"@codemirror/state": "6.0.0",
|
||||
"@codemirror/view": "6.0.0",
|
||||
"@lezer/common": "1.0.0",
|
||||
"@lezer/highlight": "1.0.0",
|
||||
"@lezer/markdown": "1.0.0",
|
||||
"@lezer/common": "1.0.0"
|
||||
"@silverbulletmd/common": "^0.0.7",
|
||||
"@silverbulletmd/plugs": "^0.0.7",
|
||||
"@silverbulletmd/web": "^0.0.7",
|
||||
"server": "^1.0.37"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ export class DiskSpacePrimitives implements SpacePrimitives {
|
||||
perm: "rw",
|
||||
};
|
||||
} catch (e) {
|
||||
console.error("Error while getting page meta", pageName, e);
|
||||
// console.error("Error while getting page meta", pageName, e);
|
||||
throw Error(`Could not get meta for ${pageName}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,17 +18,17 @@ test("Test store", async () => {
|
||||
async function conflictResolver(pageMeta1: PageMeta, pageMeta2: PageMeta) {}
|
||||
|
||||
// Write one page to primary
|
||||
await primary.writePage("start", "Hello");
|
||||
await primary.writePage("index", "Hello");
|
||||
expect((await secondary.listPages()).size).toBe(0);
|
||||
await syncPages(conflictResolver);
|
||||
expect((await secondary.listPages()).size).toBe(1);
|
||||
expect((await secondary.readPage("start")).text).toBe("Hello");
|
||||
expect((await secondary.readPage("index")).text).toBe("Hello");
|
||||
|
||||
// Should be a no-op
|
||||
expect(await syncPages()).toBe(0);
|
||||
|
||||
// Now let's make a change on the secondary
|
||||
await secondary.writePage("start", "Hello!!");
|
||||
await secondary.writePage("index", "Hello!!");
|
||||
await secondary.writePage("test", "Test page");
|
||||
|
||||
// And sync it
|
||||
@@ -37,13 +37,13 @@ test("Test store", async () => {
|
||||
expect(primary.listPages().size).toBe(2);
|
||||
expect(secondary.listPages().size).toBe(2);
|
||||
|
||||
expect((await primary.readPage("start")).text).toBe("Hello!!");
|
||||
expect((await primary.readPage("index")).text).toBe("Hello!!");
|
||||
|
||||
// Let's make some random edits on both ends
|
||||
await primary.writePage("start", "1");
|
||||
await primary.writePage("start2", "2");
|
||||
await secondary.writePage("start3", "3");
|
||||
await secondary.writePage("start4", "4");
|
||||
await primary.writePage("index", "1");
|
||||
await primary.writePage("index2", "2");
|
||||
await secondary.writePage("index3", "3");
|
||||
await secondary.writePage("index4", "4");
|
||||
await syncPages();
|
||||
|
||||
expect((await primary.listPages()).size).toBe(5);
|
||||
@@ -53,8 +53,8 @@ test("Test store", async () => {
|
||||
|
||||
console.log("Deleting pages");
|
||||
// Delete some pages
|
||||
await primary.deletePage("start");
|
||||
await primary.deletePage("start3");
|
||||
await primary.deletePage("index");
|
||||
await primary.deletePage("index3");
|
||||
|
||||
console.log("Pages", await primary.listPages());
|
||||
console.log("Trash", await primary.listTrash());
|
||||
@@ -67,8 +67,8 @@ test("Test store", async () => {
|
||||
// No-op
|
||||
expect(await syncPages()).toBe(0);
|
||||
|
||||
await secondary.deletePage("start4");
|
||||
await primary.deletePage("start2");
|
||||
await secondary.deletePage("index4");
|
||||
await primary.deletePage("index2");
|
||||
|
||||
await syncPages();
|
||||
|
||||
@@ -79,15 +79,15 @@ test("Test store", async () => {
|
||||
// No-op
|
||||
expect(await syncPages()).toBe(0);
|
||||
|
||||
await secondary.writePage("start", "I'm back");
|
||||
await secondary.writePage("index", "I'm back");
|
||||
|
||||
await syncPages();
|
||||
|
||||
expect((await primary.readPage("start")).text).toBe("I'm back");
|
||||
expect((await primary.readPage("index")).text).toBe("I'm back");
|
||||
|
||||
// Cause a conflict
|
||||
await primary.writePage("start", "Hello 1");
|
||||
await secondary.writePage("start", "Hello 2");
|
||||
await primary.writePage("index", "Hello 1");
|
||||
await secondary.writePage("index", "Hello 2");
|
||||
|
||||
await syncPages(SpaceSync.primaryConflictResolver(primary, secondary));
|
||||
|
||||
@@ -95,10 +95,10 @@ test("Test store", async () => {
|
||||
await syncPages();
|
||||
|
||||
// Verify that primary won
|
||||
expect((await primary.readPage("start")).text).toBe("Hello 1");
|
||||
expect((await secondary.readPage("start")).text).toBe("Hello 1");
|
||||
expect((await primary.readPage("index")).text).toBe("Hello 1");
|
||||
expect((await secondary.readPage("index")).text).toBe("Hello 1");
|
||||
|
||||
// test + start + start.conflicting copy
|
||||
// test + index + index.conflicting copy
|
||||
expect((await primary.listPages()).size).toBe(3);
|
||||
expect((await secondary.listPages()).size).toBe(3);
|
||||
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
"name": "Zef Hemel",
|
||||
"email": "zef@zef.me"
|
||||
},
|
||||
"version": "0.0.2",
|
||||
"license": "MIT"
|
||||
"version": "0.0.7",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@silverbulletmd/common": "^0.0.7",
|
||||
"@silverbulletmd/plugs": "^0.0.7",
|
||||
"@silverbulletmd/web": "^0.0.7",
|
||||
"server": "^1.0.37"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
"name": "Zef Hemel",
|
||||
"email": "zef@zef.me"
|
||||
},
|
||||
"version": "0.0.2",
|
||||
"license": "MIT"
|
||||
"version": "0.0.7",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@silverbulletmd/common": "^0.0.7",
|
||||
"@silverbulletmd/plugs": "^0.0.7",
|
||||
"@silverbulletmd/web": "^0.0.7",
|
||||
"server": "^1.0.37"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "Zef Hemel",
|
||||
"email": "zef@zef.me"
|
||||
},
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.7",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"plugos-bundle": "./dist/plugos/plugos-bundle.js",
|
||||
@@ -40,6 +40,9 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/globals": "^27.5.1",
|
||||
"@silverbulletmd/common": "^0.0.7",
|
||||
"@silverbulletmd/plugs": "^0.0.7",
|
||||
"@silverbulletmd/web": "^0.0.7",
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/jsonwebtoken": "^8.5.8",
|
||||
@@ -56,12 +59,13 @@
|
||||
"node-cron": "^3.0.0",
|
||||
"node-fetch": "2",
|
||||
"node-watch": "^0.7.3",
|
||||
"server": "^1.0.37",
|
||||
"supertest": "^6.2.2",
|
||||
"typescript": "^4.6.2",
|
||||
"vm2": "^3.9.9",
|
||||
"ws": "^8.5.0",
|
||||
"yaml": "^1.10.2",
|
||||
"yargs": "^17.3.1",
|
||||
"typescript": "^4.6.2"
|
||||
"yargs": "^17.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lezer/lr": "1.0.0",
|
||||
|
||||
@@ -279,7 +279,6 @@ function $11a7e2bff790f35a$export$195ba6d62321b933(message, defaultValue = "") {
|
||||
}
|
||||
|
||||
|
||||
const $c3893eec0c49ec96$var$dateMatchRegex = /(\d{4}\-\d{2}\-\d{2})/g;
|
||||
function $c3893eec0c49ec96$export$5dc1410f87262ed6(d) {
|
||||
return d.toISOString().split("T")[0];
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -35,6 +35,13 @@ functions:
|
||||
path: "./page.ts:parseIndexTextRepublish"
|
||||
events:
|
||||
- page:index_text
|
||||
reindexSpaceCommand:
|
||||
path: "./page.ts:reindexCommand"
|
||||
command:
|
||||
name: "Space: Reindex"
|
||||
reindexSpace:
|
||||
path: "./page.ts:reindexSpace"
|
||||
env: server
|
||||
indexLinks:
|
||||
path: "./page.ts:indexLinks"
|
||||
events:
|
||||
@@ -43,25 +50,10 @@ functions:
|
||||
path: ./page.ts:linkQueryProvider
|
||||
events:
|
||||
- query:link
|
||||
# indexItems:
|
||||
# path: "./item.ts:indexItems"
|
||||
# events:
|
||||
# - page:index
|
||||
# itemQueryProvider:
|
||||
# path: ./item.ts:queryProvider
|
||||
# events:
|
||||
# - query:item
|
||||
deletePage:
|
||||
path: "./page.ts:deletePage"
|
||||
command:
|
||||
name: "Page: Delete"
|
||||
reindexSpaceCommand:
|
||||
path: "./page.ts:reindexCommand"
|
||||
command:
|
||||
name: "Space: Reindex"
|
||||
reindexSpace:
|
||||
path: "./page.ts:reindexSpace"
|
||||
env: server
|
||||
renamePage:
|
||||
path: "./page.ts:renamePage"
|
||||
command:
|
||||
@@ -82,38 +74,39 @@ functions:
|
||||
path: "./navigate.ts:clickNavigate"
|
||||
events:
|
||||
- page:click
|
||||
insertToday:
|
||||
path: "./dates.ts:insertToday"
|
||||
slashCommand:
|
||||
name: today
|
||||
insertTomorrow:
|
||||
path: "./dates.ts:insertTomorrow"
|
||||
slashCommand:
|
||||
name: tomorrow
|
||||
parseServerCommand:
|
||||
path: ./debug.ts:parseServerPageCommand
|
||||
command:
|
||||
name: "Debug: Parse Document on Server"
|
||||
parsePage:
|
||||
path: ./debug.ts:parsePage
|
||||
parseCommand:
|
||||
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"
|
||||
|
||||
# Full text search
|
||||
searchIndex:
|
||||
path: ./search.ts:index
|
||||
events:
|
||||
- log:reload
|
||||
hideBhsCommand:
|
||||
path: ./debug.ts:hideBhsCommand
|
||||
- page:index
|
||||
searchUnindex:
|
||||
path: "./search.ts:unindex"
|
||||
env: server
|
||||
events:
|
||||
- page:deleted
|
||||
searchQueryProvider:
|
||||
path: ./search.ts:queryProvider
|
||||
events:
|
||||
- query:full-text
|
||||
searchCommand:
|
||||
path: ./search.ts:searchCommand
|
||||
command:
|
||||
name: "UI: Hide BHS"
|
||||
key: "Ctrl-Alt-b"
|
||||
mac: "Cmd-Alt-b"
|
||||
name: "Search Space"
|
||||
key: Ctrl-Shift-f
|
||||
mac: Cmd-Shift-f
|
||||
readPageSearch:
|
||||
path: ./search.ts:readPageSearch
|
||||
pageNamespace:
|
||||
pattern: "@search/.+"
|
||||
operation: readPage
|
||||
getPageMetaSearch:
|
||||
path: ./search.ts:getPageMetaSearch
|
||||
pageNamespace:
|
||||
pattern: "@search/.+"
|
||||
operation: getPageMeta
|
||||
|
||||
# Template commands
|
||||
insertPageMeta:
|
||||
path: "./page.ts:insertPageMeta"
|
||||
slashCommand:
|
||||
@@ -132,7 +125,16 @@ functions:
|
||||
path: ./template.ts:instantiateTemplateCommand
|
||||
command:
|
||||
name: "Template: Instantiate for Page"
|
||||
insertToday:
|
||||
path: "./dates.ts:insertToday"
|
||||
slashCommand:
|
||||
name: today
|
||||
insertTomorrow:
|
||||
path: "./dates.ts:insertTomorrow"
|
||||
slashCommand:
|
||||
name: tomorrow
|
||||
|
||||
# Text editing commands
|
||||
quoteSelection:
|
||||
path: ./text.ts:quoteSelection
|
||||
command:
|
||||
@@ -159,3 +161,40 @@ functions:
|
||||
name: "Text: Italic"
|
||||
key: "Ctrl-i"
|
||||
mac: "Cmd-i"
|
||||
|
||||
# Plug manager
|
||||
updatePlugsCommand:
|
||||
path: ./plugmanager.ts:updatePlugsCommand
|
||||
command:
|
||||
name: "Plugs: Update"
|
||||
key: "Ctrl-Shift-p"
|
||||
mac: "Cmd-Shift-p"
|
||||
updatePlugs:
|
||||
path: ./plugmanager.ts:updatePlugs
|
||||
env: server
|
||||
|
||||
# Debug commands
|
||||
parseServerCommand:
|
||||
path: ./debug.ts:parseServerPageCommand
|
||||
command:
|
||||
name: "Debug: Parse Document on Server"
|
||||
parsePage:
|
||||
path: ./debug.ts:parsePage
|
||||
parseCommand:
|
||||
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"
|
||||
events:
|
||||
- log:reload
|
||||
hideBhsCommand:
|
||||
path: ./debug.ts:hideBhsCommand
|
||||
command:
|
||||
name: "UI: Hide BHS"
|
||||
key: "Ctrl-Alt-b"
|
||||
mac: "Cmd-Alt-b"
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { insertAtCursor } from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
||||
|
||||
const dateMatchRegex = /(\d{4}\-\d{2}\-\d{2})/g;
|
||||
|
||||
export function niceDate(d: Date): string {
|
||||
return d.toISOString().split("T")[0];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { getLogs } from "@plugos/plugos-syscall/sandbox";
|
||||
import { LogEntry } from "@plugos/plugos/sandbox";
|
||||
import {
|
||||
getText,
|
||||
hideBhs,
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
import {
|
||||
getCursor,
|
||||
getText,
|
||||
insertAtPos,
|
||||
replaceRange,
|
||||
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
||||
|
||||
export async function toggleH1() {
|
||||
await togglePrefix("# ");
|
||||
}
|
||||
|
||||
export async function toggleH2() {
|
||||
await togglePrefix("## ");
|
||||
}
|
||||
|
||||
function lookBack(s: string, pos: number, backString: string): boolean {
|
||||
return s.substring(pos - backString.length, pos) === backString;
|
||||
}
|
||||
|
||||
async function togglePrefix(prefix: string) {
|
||||
let text = await getText();
|
||||
let pos = await getCursor();
|
||||
if (text[pos] === "\n") {
|
||||
pos--;
|
||||
}
|
||||
while (pos > 0 && text[pos] !== "\n") {
|
||||
if (lookBack(text, pos, prefix)) {
|
||||
// Already has this prefix, let's flip it
|
||||
await replaceRange(pos - prefix.length, pos, "");
|
||||
return;
|
||||
}
|
||||
pos--;
|
||||
}
|
||||
if (pos) {
|
||||
pos++;
|
||||
}
|
||||
await insertAtPos(prefix, pos);
|
||||
}
|
||||
@@ -8,8 +8,6 @@ import {
|
||||
import { parseMarkdown } from "@silverbulletmd/plugos-silverbullet-syscall/markdown";
|
||||
import { nodeAtPos, ParseTree } from "@silverbulletmd/common/tree";
|
||||
|
||||
const materializedQueryPrefix = /<!--\s*#query\s+/;
|
||||
|
||||
async function actionClickOrActionEnter(mdTree: ParseTree | null) {
|
||||
if (!mdTree) {
|
||||
return;
|
||||
|
||||
@@ -35,9 +35,7 @@ import {
|
||||
replaceNodesMatching,
|
||||
} from "@silverbulletmd/common/tree";
|
||||
import { applyQuery, QueryProviderEvent } from "../query/engine";
|
||||
import { PageMeta } from "@silverbulletmd/common/types";
|
||||
import { extractMeta } from "../query/data";
|
||||
import { jsonToMDTable } from "../query/util";
|
||||
|
||||
// Key space:
|
||||
// pl:toPage:pos => pageName
|
||||
@@ -101,8 +99,8 @@ export async function linkQueryProvider({
|
||||
|
||||
export async function deletePage() {
|
||||
let pageName = await getCurrentPage();
|
||||
console.log("Navigating to start page");
|
||||
await navigate("start");
|
||||
console.log("Navigating to index page");
|
||||
await navigate("index");
|
||||
console.log("Deleting page from space");
|
||||
await deletePageSyscall(pageName);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { dispatch } from "@plugos/plugos-syscall/event";
|
||||
import { findNodeOfType } from "@silverbulletmd/common/tree";
|
||||
import { flashNotification } from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
||||
import { parseMarkdown } from "@silverbulletmd/plugos-silverbullet-syscall/markdown";
|
||||
import {
|
||||
deletePage,
|
||||
listPages,
|
||||
readPage,
|
||||
writePage,
|
||||
} from "@silverbulletmd/plugos-silverbullet-syscall/space";
|
||||
import {
|
||||
invokeFunction,
|
||||
reloadPlugs,
|
||||
} from "@silverbulletmd/plugos-silverbullet-syscall/system";
|
||||
import YAML from "yaml";
|
||||
|
||||
async function listPlugs(): Promise<string[]> {
|
||||
let unfilteredPages = await listPages(true);
|
||||
return unfilteredPages
|
||||
.filter((p) => p.name.startsWith("_plug/"))
|
||||
.map((p) => p.name.substring("_plug/".length));
|
||||
}
|
||||
|
||||
export async function updatePlugsCommand() {
|
||||
flashNotification("Updating plugs...");
|
||||
await invokeFunction("server", "updatePlugs");
|
||||
flashNotification("And... done!");
|
||||
await reloadPlugs();
|
||||
}
|
||||
|
||||
export async function updatePlugs() {
|
||||
let { text: plugPageText } = await readPage("PLUGS");
|
||||
|
||||
let tree = await parseMarkdown(plugPageText);
|
||||
|
||||
let codeTextNode = findNodeOfType(tree, "CodeText");
|
||||
if (!codeTextNode) {
|
||||
console.error("Could not find yaml block in PLUGS");
|
||||
return;
|
||||
}
|
||||
let plugYaml = codeTextNode.children![0].text;
|
||||
let plugList = YAML.parse(plugYaml!);
|
||||
console.log("Plug YAML", plugList);
|
||||
let allPlugNames: string[] = [];
|
||||
for (let plugUri of plugList) {
|
||||
let [protocol, ...rest] = plugUri.split(":");
|
||||
let manifests = await dispatch(`get-plug:${protocol}`, rest.join(":"));
|
||||
if (manifests.length === 0) {
|
||||
console.error("Could not resolve plug", plugUri);
|
||||
}
|
||||
// console.log("Got manifests", plugUri, protocol, manifests);
|
||||
let manifest = manifests[0];
|
||||
allPlugNames.push(manifest.name);
|
||||
// console.log("Writing", `_plug/${manifest.name}`);
|
||||
await writePage(
|
||||
`_plug/${manifest.name}`,
|
||||
JSON.stringify(manifest, null, 2)
|
||||
);
|
||||
}
|
||||
|
||||
// And delete extra ones
|
||||
for (let existingPlug of await listPlugs()) {
|
||||
if (!allPlugNames.includes(existingPlug)) {
|
||||
console.log("Removing plug", existingPlug);
|
||||
await deletePage(`_plug/${existingPlug}`);
|
||||
}
|
||||
}
|
||||
await reloadPlugs();
|
||||
}
|
||||
@@ -1,4 +1,8 @@
|
||||
import { fullTextIndex, fullTextSearch } from "@plugos/plugos-syscall/fulltext";
|
||||
import {
|
||||
fullTextDelete,
|
||||
fullTextIndex,
|
||||
fullTextSearch,
|
||||
} from "@plugos/plugos-syscall/fulltext";
|
||||
import { renderToText } from "@silverbulletmd/common/tree";
|
||||
import { PageMeta } from "@silverbulletmd/common/types";
|
||||
import { queryPrefix } from "@silverbulletmd/plugos-silverbullet-syscall";
|
||||
@@ -16,6 +20,10 @@ export async function index(data: IndexTreeEvent) {
|
||||
await fullTextIndex(data.name, cleanText);
|
||||
}
|
||||
|
||||
export async function unindex(pageName: string) {
|
||||
await fullTextDelete(pageName);
|
||||
}
|
||||
|
||||
export async function queryProvider({
|
||||
query,
|
||||
}: QueryProviderEvent): Promise<any[]> {
|
||||
@@ -1,12 +0,0 @@
|
||||
import {
|
||||
EndpointRequest,
|
||||
EndpointResponse,
|
||||
} from "@plugos/plugos/hooks/endpoint";
|
||||
|
||||
export function endpointTest(req: EndpointRequest): EndpointResponse {
|
||||
console.log("I'm running on the server!", req);
|
||||
return {
|
||||
status: 200,
|
||||
body: "Hello world!",
|
||||
};
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
function countWords(str: string): number {
|
||||
const matches = str.match(/[\w\d\'-]+/gi);
|
||||
return matches ? matches.length : 0;
|
||||
}
|
||||
|
||||
function readingTime(wordCount: number): number {
|
||||
// 225 is average word reading speed for adults
|
||||
return Math.ceil(wordCount / 225);
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
import emojis from "./emoji.json";
|
||||
import { matchBefore } from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
||||
|
||||
const emojiMatcher = /\(([^\)]+)\)\s+(.+)$/;
|
||||
|
||||
export async function emojiCompleter() {
|
||||
let prefix = await matchBefore(":[\\w]+");
|
||||
if (!prefix) {
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
name: ghost
|
||||
functions:
|
||||
downloadAllPostsCommand:
|
||||
path: "./ghost.ts:downloadAllPostsCommand"
|
||||
command:
|
||||
name: "Ghost: Download Posts"
|
||||
downloadAllPosts:
|
||||
path: "./ghost.ts:downloadAllPosts"
|
||||
env: server
|
||||
publishCommand:
|
||||
path: "./ghost.ts:publishCommand"
|
||||
command:
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
readPage,
|
||||
writePage,
|
||||
} from "@silverbulletmd/plugos-silverbullet-syscall/space";
|
||||
import { readPage } from "@silverbulletmd/plugos-silverbullet-syscall/space";
|
||||
import { invokeFunction } from "@silverbulletmd/plugos-silverbullet-syscall/system";
|
||||
import {
|
||||
getCurrentPage,
|
||||
@@ -195,21 +192,6 @@ async function getConfig(): Promise<GhostConfig> {
|
||||
return pageMeta as GhostConfig;
|
||||
}
|
||||
|
||||
export async function downloadAllPostsCommand() {
|
||||
await invokeFunction("server", "downloadAllPosts");
|
||||
}
|
||||
|
||||
export async function downloadAllPosts() {
|
||||
let config = await getConfig();
|
||||
let admin = new GhostAdmin(config.url, config.adminKey);
|
||||
await admin.init();
|
||||
let allPosts = await admin.listMarkdownPosts();
|
||||
for (let post of allPosts) {
|
||||
let text = mobileDocToMarkdown(post.mobiledoc);
|
||||
text = `# ${post.title}\n${text}`;
|
||||
await writePage(`${config.postPrefix}/${post.slug}`, text);
|
||||
}
|
||||
}
|
||||
export async function publishCommand() {
|
||||
await invokeFunction(
|
||||
"server",
|
||||
|
||||
@@ -7,7 +7,6 @@ export async function togglePreview() {
|
||||
await clientStore.set("enableMarkdownPreview", !currentValue);
|
||||
if (!currentValue) {
|
||||
await invokeFunction("client", "preview");
|
||||
// updateMarkdownPreview();
|
||||
} else {
|
||||
await hideMarkdownPreview();
|
||||
}
|
||||
|
||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@silverbulletmd/plugs",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.7",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@silverbulletmd/plugs",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.7",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jest/globals": "^27.5.1",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "Zef Hemel",
|
||||
"email": "zef@zef.me"
|
||||
},
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.7",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"generate": "lezer-generator query/query.grammar -o query/parse-query.js",
|
||||
@@ -34,13 +34,17 @@
|
||||
"@jest/globals": "^27.5.1",
|
||||
"@lezer/generator": "1.0.0",
|
||||
"@lezer/lr": "1.0.0",
|
||||
"@mattermost/client": "^6.7.0-0",
|
||||
"@mattermost/types": "^6.7.0-0",
|
||||
"@mattermost/client": "^7.0.0",
|
||||
"@mattermost/types": "^7.0.0",
|
||||
"@silverbulletmd/common": "^0.0.7",
|
||||
"@silverbulletmd/plugs": "^0.0.7",
|
||||
"@silverbulletmd/web": "^0.0.7",
|
||||
"@types/yaml": "^1.9.7",
|
||||
"handlebars": "^4.7.7",
|
||||
"markdown-it": "^12.3.2",
|
||||
"markdown-it-task-lists": "^2.1.1",
|
||||
"yaml": "^2.0.0",
|
||||
"handlebars": "^4.7.7"
|
||||
"server": "^1.0.37",
|
||||
"yaml": "^2.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/markdown-it": "^12.2.3"
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
name: plugmanager
|
||||
functions:
|
||||
updatePlugsCommand:
|
||||
path: ./plugmanager.ts:updatePlugsCommand
|
||||
command:
|
||||
name: "Plugs: Update"
|
||||
key: "Ctrl-Shift-p"
|
||||
mac: "Cmd-Shift-p"
|
||||
updatePlugs:
|
||||
path: ./plugmanager.ts:updatePlugs
|
||||
env: server
|
||||
check:
|
||||
path: "./plugmanager.ts:checkCommand"
|
||||
command:
|
||||
name: "Plug: Check"
|
||||
mac: "Cmd-Alt-c"
|
||||
key: "Ctrl-Alt-c"
|
||||
compile:
|
||||
path: "./plugmanager.ts:compileCommand"
|
||||
command:
|
||||
name: "Plug: Compile"
|
||||
mac: "Cmd-Shift-c"
|
||||
key: "Ctrl-Shift-c"
|
||||
compileJS:
|
||||
path: "./plugmanager.ts:compileJS"
|
||||
env: server
|
||||
compileModule:
|
||||
path: "./plugmanager.ts:compileModule"
|
||||
env: server
|
||||
getPlugPlugMd:
|
||||
path: "./plugmanager.ts:getPlugPlugMd"
|
||||
events:
|
||||
- get-plug:plugmd
|
||||
@@ -0,0 +1,24 @@
|
||||
name: plugmd
|
||||
functions:
|
||||
check:
|
||||
path: "./plugmd.ts:checkCommand"
|
||||
command:
|
||||
name: "Plug: Check"
|
||||
mac: "Cmd-Alt-c"
|
||||
key: "Ctrl-Alt-c"
|
||||
compile:
|
||||
path: "./plugmd.ts:compileCommand"
|
||||
command:
|
||||
name: "Plug: Compile"
|
||||
mac: "Cmd-Shift-c"
|
||||
key: "Ctrl-Shift-c"
|
||||
compileJS:
|
||||
path: "./plugmd.ts:compileJS"
|
||||
env: server
|
||||
compileModule:
|
||||
path: "./plugmd.ts:compileModule"
|
||||
env: server
|
||||
getPlugPlugMd:
|
||||
path: "./plugmd.ts:getPlugPlugMd"
|
||||
events:
|
||||
- get-plug:plugmd
|
||||
@@ -1,19 +1,14 @@
|
||||
import { dispatch } from "@plugos/plugos-syscall/event";
|
||||
import {
|
||||
addParentPointers,
|
||||
collectNodesOfType,
|
||||
findNodeOfType,
|
||||
} from "@silverbulletmd/common/tree";
|
||||
import {
|
||||
flashNotification,
|
||||
getText,
|
||||
hideBhs,
|
||||
showBhs,
|
||||
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
||||
import { parseMarkdown } from "@silverbulletmd/plugos-silverbullet-syscall/markdown";
|
||||
import {
|
||||
deletePage,
|
||||
listPages,
|
||||
readPage,
|
||||
writePage,
|
||||
} from "@silverbulletmd/plugos-silverbullet-syscall/space";
|
||||
@@ -23,8 +18,6 @@ import {
|
||||
} from "@silverbulletmd/plugos-silverbullet-syscall/system";
|
||||
import YAML from "yaml";
|
||||
|
||||
import { extractMeta } from "../query/data";
|
||||
|
||||
import type { Manifest } from "@silverbulletmd/common/manifest";
|
||||
|
||||
export async function compileCommand() {
|
||||
@@ -131,64 +124,6 @@ export async function compileModule(moduleName: string): Promise<string> {
|
||||
return self.syscall("esbuild.compileModule", moduleName);
|
||||
}
|
||||
|
||||
async function listPlugs(): Promise<string[]> {
|
||||
let unfilteredPages = await listPages(true);
|
||||
return unfilteredPages
|
||||
.filter((p) => p.name.startsWith("_plug/"))
|
||||
.map((p) => p.name.substring("_plug/".length));
|
||||
}
|
||||
|
||||
export async function listCommand() {
|
||||
console.log(await listPlugs());
|
||||
}
|
||||
|
||||
export async function updatePlugsCommand() {
|
||||
flashNotification("Updating plugs...");
|
||||
await invokeFunction("server", "updatePlugs");
|
||||
flashNotification("And... done!");
|
||||
await reloadPlugs();
|
||||
}
|
||||
|
||||
export async function updatePlugs() {
|
||||
let { text: plugPageText } = await readPage("PLUGS");
|
||||
|
||||
let tree = await parseMarkdown(plugPageText);
|
||||
|
||||
let codeTextNode = findNodeOfType(tree, "CodeText");
|
||||
if (!codeTextNode) {
|
||||
console.error("Could not find yaml block in PLUGS");
|
||||
return;
|
||||
}
|
||||
let plugYaml = codeTextNode.children![0].text;
|
||||
let plugList = YAML.parse(plugYaml!);
|
||||
console.log("Plug YAML", plugList);
|
||||
let allPlugNames: string[] = [];
|
||||
for (let plugUri of plugList) {
|
||||
let [protocol, ...rest] = plugUri.split(":");
|
||||
let manifests = await dispatch(`get-plug:${protocol}`, rest.join(":"));
|
||||
if (manifests.length === 0) {
|
||||
console.error("Could not resolve plug", plugUri);
|
||||
}
|
||||
// console.log("Got manifests", plugUri, protocol, manifests);
|
||||
let manifest = manifests[0];
|
||||
allPlugNames.push(manifest.name);
|
||||
// console.log("Writing", `_plug/${manifest.name}`);
|
||||
await writePage(
|
||||
`_plug/${manifest.name}`,
|
||||
JSON.stringify(manifest, null, 2)
|
||||
);
|
||||
}
|
||||
|
||||
// And delete extra ones
|
||||
for (let existingPlug of await listPlugs()) {
|
||||
if (!allPlugNames.includes(existingPlug)) {
|
||||
console.log("Removing plug", existingPlug);
|
||||
await deletePage(`_plug/${existingPlug}`);
|
||||
}
|
||||
}
|
||||
await reloadPlugs();
|
||||
}
|
||||
|
||||
export async function getPlugPlugMd(pageName: string): Promise<Manifest> {
|
||||
let { text } = await readPage(pageName);
|
||||
console.log("Compiling", pageName);
|
||||
@@ -1,7 +1,4 @@
|
||||
name: query
|
||||
# dependencies:
|
||||
# yaml: "yaml@2"
|
||||
# "@lezer/lr": "@lezer/lr@0.15.4"
|
||||
functions:
|
||||
updateMaterializedQueriesOnPage:
|
||||
path: ./materialized_queries.ts:updateMaterializedQueriesOnPage
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
name: search
|
||||
functions:
|
||||
index:
|
||||
path: ./search.ts:index
|
||||
events:
|
||||
- page:index
|
||||
queryProvider:
|
||||
path: ./search.ts:queryProvider
|
||||
events:
|
||||
- query:full-text
|
||||
searchCommand:
|
||||
path: ./search.ts:searchCommand
|
||||
command:
|
||||
name: "Search Space"
|
||||
key: Ctrl-Shift-f
|
||||
mac: Cmd-Shift-f
|
||||
readPageSearch:
|
||||
path: ./search.ts:readPageSearch
|
||||
pageNamespace:
|
||||
pattern: "@search/.+"
|
||||
operation: readPage
|
||||
getPageMetaSearch:
|
||||
path: ./search.ts:getPageMetaSearch
|
||||
pageNamespace:
|
||||
pattern: "@search/.+"
|
||||
operation: getPageMeta
|
||||
@@ -41,7 +41,7 @@ functions:
|
||||
taskPostponeCommand:
|
||||
path: ./task.ts:postponeCommand
|
||||
command:
|
||||
name: "Task: Postpone by 1 day"
|
||||
name: "Task: Postpone"
|
||||
key: Alt-+
|
||||
contexts:
|
||||
- DeadlineDate
|
||||
|
||||
@@ -57,7 +57,7 @@ export type ServerOptions = {
|
||||
pagesPath: string;
|
||||
distDir: string;
|
||||
builtinPlugDir: string;
|
||||
token?: string;
|
||||
password?: string;
|
||||
};
|
||||
export class ExpressServer {
|
||||
app: Express;
|
||||
@@ -69,21 +69,27 @@ export class ExpressServer {
|
||||
private port: number;
|
||||
private server?: Server;
|
||||
builtinPlugDir: string;
|
||||
token?: string;
|
||||
password?: string;
|
||||
|
||||
constructor(options: ServerOptions) {
|
||||
this.port = options.port;
|
||||
this.app = express();
|
||||
this.builtinPlugDir = options.builtinPlugDir;
|
||||
this.distDir = options.distDir;
|
||||
this.system = new System<SilverBulletHooks>("server");
|
||||
this.token = options.token;
|
||||
this.password = options.password;
|
||||
|
||||
// Setup system
|
||||
// Set up the PlugOS System
|
||||
this.system = new System<SilverBulletHooks>("server");
|
||||
|
||||
// Instantiate the event bus hook
|
||||
this.eventHook = new EventHook();
|
||||
this.system.addHook(this.eventHook);
|
||||
|
||||
// And the page namespace hook
|
||||
let namespaceHook = new PageNamespaceHook();
|
||||
this.system.addHook(namespaceHook);
|
||||
|
||||
// The space
|
||||
this.space = new Space(
|
||||
new EventedSpacePrimitives(
|
||||
new PlugSpacePrimitives(
|
||||
@@ -94,6 +100,8 @@ export class ExpressServer {
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
// The database used for persistence (SQLite)
|
||||
this.db = knex({
|
||||
client: "better-sqlite3",
|
||||
connection: {
|
||||
@@ -102,9 +110,11 @@ export class ExpressServer {
|
||||
useNullAsDefault: true,
|
||||
});
|
||||
|
||||
this.system.registerSyscalls(["shell"], shellSyscalls(options.pagesPath));
|
||||
// The cron hook
|
||||
this.system.addHook(new NodeCronHook());
|
||||
|
||||
// Register syscalls available on the server sid
|
||||
this.system.registerSyscalls(["shell"], shellSyscalls(options.pagesPath));
|
||||
this.system.registerSyscalls(
|
||||
[],
|
||||
pageIndexSyscalls(this.db),
|
||||
@@ -117,10 +127,13 @@ export class ExpressServer {
|
||||
sandboxSyscalls(this.system),
|
||||
jwtSyscalls()
|
||||
);
|
||||
|
||||
// Register the HTTP endpoint hook (with "/_/<plug-name>"" prefix, hardcoded for now)
|
||||
this.system.addHook(new EndpointHook(this.app, "/_"));
|
||||
|
||||
this.system.on({
|
||||
plugLoaded: (plug) => {
|
||||
// Automatically inject some modules into each plug
|
||||
safeRun(async () => {
|
||||
for (let [modName, code] of Object.entries(
|
||||
globalModules.dependencies
|
||||
@@ -131,6 +144,8 @@ export class ExpressServer {
|
||||
},
|
||||
});
|
||||
|
||||
// Hook into some "get-plug:" to allow loading plugs from disk (security of this TBD)
|
||||
// First, for builtins (loaded from the packages/plugs/ folder)
|
||||
this.eventHook.addLocalListener(
|
||||
"get-plug:builtin",
|
||||
async (plugName: string): Promise<Manifest> => {
|
||||
@@ -149,6 +164,7 @@ export class ExpressServer {
|
||||
}
|
||||
);
|
||||
|
||||
// Second, for loading plug JSON files with absolute or relative (from CWD) paths
|
||||
this.eventHook.addLocalListener(
|
||||
"get-plug:file",
|
||||
async (plugPath: string): Promise<Manifest> => {
|
||||
@@ -169,9 +185,12 @@ export class ExpressServer {
|
||||
}
|
||||
);
|
||||
|
||||
// Rescan disk every 5s to detect any out-of-process file changes
|
||||
setInterval(() => {
|
||||
this.space.updatePageList().catch(console.error);
|
||||
}, 5000);
|
||||
|
||||
// Load plugs
|
||||
this.reloadPlugs().catch(console.error);
|
||||
}
|
||||
|
||||
@@ -182,6 +201,7 @@ export class ExpressServer {
|
||||
);
|
||||
}
|
||||
|
||||
// In case of a new space with no `PLUGS` file, generate a default one based on all built-in plugs
|
||||
private async bootstrapBuiltinPlugs() {
|
||||
let allPlugFiles = await readdir(this.builtinPlugDir);
|
||||
let pluginNames = [];
|
||||
@@ -225,9 +245,10 @@ export class ExpressServer {
|
||||
}
|
||||
|
||||
async start() {
|
||||
const tokenMiddleware: (req: any, res: any, next: any) => void = this.token
|
||||
const passwordMiddleware: (req: any, res: any, next: any) => void = this
|
||||
.password
|
||||
? (req, res, next) => {
|
||||
if (req.headers.authorization === `Bearer ${this.token}`) {
|
||||
if (req.headers.authorization === `Bearer ${this.password}`) {
|
||||
next();
|
||||
} else {
|
||||
res.status(401).send("Unauthorized");
|
||||
@@ -239,6 +260,7 @@ export class ExpressServer {
|
||||
|
||||
await ensureTable(this.db);
|
||||
await ensureFTSTable(this.db, "fts");
|
||||
await this.ensureIndexPage();
|
||||
console.log("Setting up router");
|
||||
|
||||
let auth = new Authenticator(this.db);
|
||||
@@ -328,7 +350,7 @@ export class ExpressServer {
|
||||
|
||||
this.app.use(
|
||||
"/fs",
|
||||
tokenMiddleware,
|
||||
passwordMiddleware,
|
||||
cors({
|
||||
methods: "GET,HEAD,PUT,OPTIONS,POST,DELETE",
|
||||
preflightContinue: true,
|
||||
@@ -393,7 +415,7 @@ export class ExpressServer {
|
||||
|
||||
this.app.use(
|
||||
"/plug",
|
||||
tokenMiddleware,
|
||||
passwordMiddleware,
|
||||
cors({
|
||||
methods: "GET,HEAD,PUT,OPTIONS,POST,DELETE",
|
||||
preflightContinue: true,
|
||||
@@ -412,6 +434,14 @@ export class ExpressServer {
|
||||
});
|
||||
}
|
||||
|
||||
async ensureIndexPage() {
|
||||
try {
|
||||
await this.space.getPageMeta("index");
|
||||
} catch (e) {
|
||||
await this.space.writePage("index", `Welcome to your new space!`);
|
||||
}
|
||||
}
|
||||
|
||||
async stop() {
|
||||
if (this.server) {
|
||||
console.log("Stopping");
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "Zef Hemel",
|
||||
"email": "zef@zef.me"
|
||||
},
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.7",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"silverbullet": "./dist/server/server.js"
|
||||
@@ -41,11 +41,15 @@
|
||||
"@codemirror/legacy-modes": "6.0.0",
|
||||
"@jest/globals": "^27.5.1",
|
||||
"@lezer/markdown": "1.0.0",
|
||||
"@silverbulletmd/common": "^0.0.7",
|
||||
"@silverbulletmd/plugs": "^0.0.7",
|
||||
"@silverbulletmd/web": "^0.0.7",
|
||||
"better-sqlite3": "^7.5.0",
|
||||
"body-parser": "^1.19.2",
|
||||
"buffer": "^6.0.3",
|
||||
"cors": "^2.8.5",
|
||||
"dexie": "^3.2.1",
|
||||
"esbuild": "^0.14.27",
|
||||
"events": "^3.3.0",
|
||||
"express": "^4.17.3",
|
||||
"fake-indexeddb": "^3.1.7",
|
||||
@@ -56,6 +60,7 @@
|
||||
"node-fetch": "2",
|
||||
"node-watch": "^0.7.3",
|
||||
"nodemon": "^2.0.15",
|
||||
"server": "^1.0.37",
|
||||
"uuid": "^8.3.2",
|
||||
"vm2": "^3.9.9",
|
||||
"ws": "^8.5.0",
|
||||
|
||||
@@ -11,14 +11,14 @@ let args = yargs(hideBin(process.argv))
|
||||
type: "number",
|
||||
default: 3000,
|
||||
})
|
||||
.option("token", {
|
||||
.option("password", {
|
||||
type: "string",
|
||||
})
|
||||
.parse();
|
||||
|
||||
if (!args._.length) {
|
||||
console.error(
|
||||
"Usage: silverbullet [--port 3000] [--token mysecrettoken] <path-to-pages>"
|
||||
"Usage: silverbullet [--port 3000] [--password mysecretpassword] <path-to-pages>"
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
@@ -40,7 +40,7 @@ const expressServer = new ExpressServer({
|
||||
pagesPath: pagesPath,
|
||||
distDir: webappDistDir,
|
||||
builtinPlugDir: plugDistDir,
|
||||
token: args.token,
|
||||
password: args.password,
|
||||
});
|
||||
expressServer.start().catch((e) => {
|
||||
console.error(e);
|
||||
|
||||
@@ -6,22 +6,23 @@ import { HttpSpacePrimitives } from "@silverbulletmd/common/spaces/http_space_pr
|
||||
safeRun(async () => {
|
||||
// let localSpace = new Space(new IndexedDBSpacePrimitives("pages"), true);
|
||||
// localSpace.watch();
|
||||
let token: string | undefined = localStorage.getItem("token") || undefined;
|
||||
let password: string | undefined =
|
||||
localStorage.getItem("password") || undefined;
|
||||
|
||||
let httpPrimitives = new HttpSpacePrimitives("", token);
|
||||
let httpPrimitives = new HttpSpacePrimitives("", password);
|
||||
while (true) {
|
||||
try {
|
||||
await httpPrimitives.getPageMeta("start");
|
||||
await httpPrimitives.getPageMeta("index");
|
||||
break;
|
||||
} catch (e: any) {
|
||||
if (e.message === "Unauthorized") {
|
||||
token = prompt("Token: ") || undefined;
|
||||
if (!token) {
|
||||
alert("Sorry, that's it then");
|
||||
password = prompt("Password: ") || undefined;
|
||||
if (!password) {
|
||||
alert("Sorry, need a password");
|
||||
return;
|
||||
}
|
||||
localStorage.setItem("token", token!);
|
||||
httpPrimitives = new HttpSpacePrimitives("", token);
|
||||
localStorage.setItem("password", password!);
|
||||
httpPrimitives = new HttpSpacePrimitives("", password);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import { EditorSelection, StateCommand, Transaction } from "@codemirror/state";
|
||||
import { Text } from "@codemirror/state";
|
||||
|
||||
export function insertMarker(marker: string): StateCommand {
|
||||
return ({ state, dispatch }) => {
|
||||
const changes = state.changeByRange((range) => {
|
||||
const isBoldBefore =
|
||||
state.sliceDoc(range.from - marker.length, range.from) === marker;
|
||||
const isBoldAfter =
|
||||
state.sliceDoc(range.to, range.to + marker.length) === marker;
|
||||
const changes = [];
|
||||
|
||||
changes.push(
|
||||
isBoldBefore
|
||||
? {
|
||||
from: range.from - marker.length,
|
||||
to: range.from,
|
||||
insert: Text.of([""]),
|
||||
}
|
||||
: {
|
||||
from: range.from,
|
||||
insert: Text.of([marker]),
|
||||
}
|
||||
);
|
||||
|
||||
changes.push(
|
||||
isBoldAfter
|
||||
? {
|
||||
from: range.to,
|
||||
to: range.to + marker.length,
|
||||
insert: Text.of([""]),
|
||||
}
|
||||
: {
|
||||
from: range.to,
|
||||
insert: Text.of([marker]),
|
||||
}
|
||||
);
|
||||
|
||||
const extendBefore = isBoldBefore ? -marker.length : marker.length;
|
||||
const extendAfter = isBoldAfter ? -marker.length : marker.length;
|
||||
|
||||
return {
|
||||
changes,
|
||||
range: EditorSelection.range(
|
||||
range.from + extendBefore,
|
||||
range.to + extendAfter
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
dispatch(
|
||||
state.update(changes, {
|
||||
scrollIntoView: true,
|
||||
annotations: Transaction.userEvent.of("input"),
|
||||
})
|
||||
);
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
@@ -221,7 +221,7 @@ export class Editor {
|
||||
});
|
||||
|
||||
if (this.pageNavigator.getCurrentPage() === "") {
|
||||
await this.pageNavigator.navigate("start");
|
||||
await this.pageNavigator.navigate("index");
|
||||
}
|
||||
await this.reloadPlugs();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "Zef Hemel",
|
||||
"email": "zef@zef.me"
|
||||
},
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.7",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"watch": "rm -rf .parcel-cache && parcel watch",
|
||||
@@ -41,12 +41,16 @@
|
||||
"@jest/globals": "^27.5.1",
|
||||
"@lezer/highlight": "1.0.0",
|
||||
"@lezer/markdown": "1.0.0",
|
||||
"@silverbulletmd/common": "^0.0.7",
|
||||
"@silverbulletmd/plugs": "^0.0.7",
|
||||
"@silverbulletmd/web": "^0.0.7",
|
||||
"fake-indexeddb": "^3.1.7",
|
||||
"fuzzysort": "^1.9.0",
|
||||
"jest": "^27.5.1",
|
||||
"knex": "^1.0.4",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2"
|
||||
"react-dom": "^17.0.2",
|
||||
"server": "^1.0.37"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@parcel/packager-raw-url": "2.5.0",
|
||||
|
||||
@@ -21,9 +21,9 @@ export function spaceSyscalls(editor: Editor): SysCallMapping {
|
||||
return await editor.space.writePage(name, text);
|
||||
},
|
||||
"space.deletePage": async (ctx, name: string) => {
|
||||
// If we're deleting the current page, navigate to the start page
|
||||
// If we're deleting the current page, navigate to the index page
|
||||
if (editor.currentPage === name) {
|
||||
await editor.navigate("start");
|
||||
await editor.navigate("index");
|
||||
}
|
||||
// Remove page from open pages in editor
|
||||
editor.openPages.delete(name);
|
||||
|
||||
Reference in New Issue
Block a user