1
0

Make index page configurable

This commit is contained in:
Zef Hemel 2022-08-02 12:43:39 +02:00
parent b29b175b40
commit 7111fb6b1e
10 changed files with 81 additions and 25 deletions

View File

@ -18,6 +18,7 @@
"@codemirror/view": "^6.0.0", "@codemirror/view": "^6.0.0",
"@lezer/common": "1.0.0", "@lezer/common": "1.0.0",
"@lezer/highlight": "1.0.0", "@lezer/highlight": "1.0.0",
"@lezer/markdown": "1.0.1" "@lezer/markdown": "1.0.1",
"yaml": "^1.10.2"
} }
} }

View File

@ -1,3 +1,5 @@
import YAML from "yaml";
export function safeRun(fn: () => Promise<void>) { export function safeRun(fn: () => Promise<void>) {
fn().catch((e) => { fn().catch((e) => {
console.error(e); console.error(e);
@ -19,3 +21,17 @@ export function throttle(func: () => void, limit: number) {
} }
}; };
} }
// TODO: This is naive, may be better to use a proper parser
const yamlSettingsRegex = /```yaml([^`]+)```/;
export function parseYamlSettings(settingsMarkdown: string): {
[key: string]: any;
} {
const match = yamlSettingsRegex.exec(settingsMarkdown);
if (!match) {
return {};
}
const yaml = match[1];
return YAML.parse(yaml);
}

View File

@ -107,7 +107,7 @@ functions:
command: command:
name: "Navigate: Home" name: "Navigate: Home"
key: "Alt-h" key: "Alt-h"
page: "index" page: ""
# Hashtags # Hashtags
indexTags: indexTags:

View File

@ -101,7 +101,7 @@ export async function linkQueryProvider({
export async function deletePage() { export async function deletePage() {
let pageName = await getCurrentPage(); let pageName = await getCurrentPage();
console.log("Navigating to index page"); console.log("Navigating to index page");
await navigate("index"); await navigate("");
console.log("Deleting page from space"); console.log("Deleting page from space");
await deletePageSyscall(pageName); await deletePageSyscall(pageName);
} }
@ -201,7 +201,7 @@ export async function reindexCommand() {
// Completion // Completion
export async function pageComplete() { export async function pageComplete() {
let prefix = await matchBefore("\\[\\[[\\w\\s]*"); let prefix = await matchBefore("\\[\\[[^\\]]*");
if (!prefix) { if (!prefix) {
return null; return null;
} }

View File

@ -0,0 +1,4 @@
This page contains settings for configuring SilverBullet and its plugs. Any changes outside of the yaml block will be overwritten.
```yaml
indexPage: index
```

View File

@ -30,8 +30,8 @@ import { systemSyscalls } from "./syscalls/system";
import { plugPrefix } from "@silverbulletmd/common/spaces/constants"; import { plugPrefix } from "@silverbulletmd/common/spaces/constants";
import sandboxSyscalls from "@plugos/plugos/syscalls/sandbox"; import sandboxSyscalls from "@plugos/plugos/syscalls/sandbox";
// @ts-ignore
// import globalModules from "../common/dist/global.plug.json"; import settingsTemplate from "bundle-text:./SETTINGS_TEMPLATE.md";
const globalModules: any = JSON.parse( const globalModules: any = JSON.parse(
readFileSync( readFileSync(
@ -53,6 +53,7 @@ import {
storeSyscalls, storeSyscalls,
ensureTable as ensureStoreTable, ensureTable as ensureStoreTable,
} from "@plugos/plugos/syscalls/store.knex_node"; } from "@plugos/plugos/syscalls/store.knex_node";
import { parseYamlSettings } from "@silverbulletmd/common/util";
const safeFilename = /^[a-zA-Z0-9_\-\.]+$/; const safeFilename = /^[a-zA-Z0-9_\-\.]+$/;
@ -74,6 +75,7 @@ export class ExpressServer {
private server?: Server; private server?: Server;
builtinPlugDir: string; builtinPlugDir: string;
password?: string; password?: string;
settings: { [key: string]: any } = {};
constructor(options: ServerOptions) { constructor(options: ServerOptions) {
this.port = options.port; this.port = options.port;
@ -268,7 +270,7 @@ export class ExpressServer {
await ensureIndexTable(this.db); await ensureIndexTable(this.db);
await ensureStoreTable(this.db, "store"); await ensureStoreTable(this.db, "store");
await ensureFTSTable(this.db, "fts"); await ensureFTSTable(this.db, "fts");
await this.ensureIndexPage(); await this.ensureAndLoadSettings();
// Serve static files (javascript, css, html) // Serve static files (javascript, css, html)
this.app.use("/", express.static(this.distDir)); this.app.use("/", express.static(this.distDir));
@ -444,11 +446,26 @@ export class ExpressServer {
}); });
} }
async ensureIndexPage() { async ensureAndLoadSettings() {
try { try {
await this.space.getPageMeta("index"); await this.space.getPageMeta("SETTINGS");
} catch (e) { } catch (e) {
await this.space.writePage("index", `Welcome to your new space!`); await this.space.writePage("SETTINGS", settingsTemplate, true);
}
let { text: settingsText } = await this.space.readPage("SETTINGS");
this.settings = parseYamlSettings(settingsText);
if (!this.settings.indexPage) {
this.settings.indexPage = "index";
}
try {
await this.space.getPageMeta(this.settings.indexPage);
} catch (e) {
await this.space.writePage(
this.settings.indexPage,
`Welcome to your new space!`
);
} }
} }

View File

@ -1,5 +1,5 @@
import { Editor } from "./editor"; import { Editor } from "./editor";
import { safeRun } from "@silverbulletmd/common/util"; import { parseYamlSettings, safeRun } from "@silverbulletmd/common/util";
import { Space } from "@silverbulletmd/common/spaces/space"; import { Space } from "@silverbulletmd/common/spaces/space";
import { HttpSpacePrimitives } from "@silverbulletmd/common/spaces/http_space_primitives"; import { HttpSpacePrimitives } from "@silverbulletmd/common/spaces/http_space_primitives";
@ -8,9 +8,10 @@ safeRun(async () => {
localStorage.getItem("password") || undefined; localStorage.getItem("password") || undefined;
let httpPrimitives = new HttpSpacePrimitives("", password); let httpPrimitives = new HttpSpacePrimitives("", password);
let settingsPageText = "";
while (true) { while (true) {
try { try {
await httpPrimitives.getPageMeta("index"); settingsPageText = (await httpPrimitives.readPage("SETTINGS")).text;
break; break;
} catch (e: any) { } catch (e: any) {
if (e.message === "Unauthorized") { if (e.message === "Unauthorized") {
@ -29,7 +30,14 @@ safeRun(async () => {
console.log("Booting..."); console.log("Booting...");
let editor = new Editor(serverSpace, document.getElementById("sb-root")!, ""); let settings = parseYamlSettings(settingsPageText);
let editor = new Editor(
serverSpace,
document.getElementById("sb-root")!,
"",
settings.indexPage || "index"
);
await editor.init(); await editor.init();
// @ts-ignore // @ts-ignore
window.editor = editor; window.editor = editor;

View File

@ -114,12 +114,19 @@ export class Editor {
private system = new System<SilverBulletHooks>("client"); private system = new System<SilverBulletHooks>("client");
private mdExtensions: MDExt[] = []; private mdExtensions: MDExt[] = [];
urlPrefix: string; urlPrefix: string;
indexPage: string;
constructor(space: Space, parent: Element, urlPrefix: string) { constructor(
space: Space,
parent: Element,
urlPrefix: string,
indexPage: string
) {
this.space = space; this.space = space;
this.urlPrefix = urlPrefix; this.urlPrefix = urlPrefix;
this.viewState = initialViewState; this.viewState = initialViewState;
this.viewDispatch = () => {}; this.viewDispatch = () => {};
this.indexPage = indexPage;
// Event hook // Event hook
this.eventHook = new EventHook(); this.eventHook = new EventHook();
@ -146,7 +153,7 @@ export class Editor {
state: this.createEditorState("", ""), state: this.createEditorState("", ""),
parent: document.getElementById("sb-editor")!, parent: document.getElementById("sb-editor")!,
}); });
this.pageNavigator = new PathPageNavigator(urlPrefix); this.pageNavigator = new PathPageNavigator(indexPage, urlPrefix);
this.system.registerSyscalls( this.system.registerSyscalls(
[], [],
@ -242,11 +249,7 @@ export class Editor {
}, },
}); });
if (this.pageNavigator.getCurrentPage() === "") {
await this.pageNavigator.navigate("index");
}
await this.reloadPlugs(); await this.reloadPlugs();
await this.dispatchAppEvent("editor:init"); await this.dispatchAppEvent("editor:init");
} }
@ -558,6 +561,9 @@ export class Editor {
} }
async navigate(name: string, pos?: number, replaceState = false) { async navigate(name: string, pos?: number, replaceState = false) {
if (!name) {
name = this.indexPage;
}
await this.pageNavigator.navigate(name, pos, replaceState); await this.pageNavigator.navigate(name, pos, replaceState);
} }
@ -712,7 +718,7 @@ export class Editor {
dispatch({ type: "start-navigate" }); dispatch({ type: "start-navigate" });
}} }}
onHomeClick={() => { onHomeClick={() => {
editor.navigate("index"); editor.navigate("");
}} }}
onActionClick={() => { onActionClick={() => {
dispatch({ type: "show-palette" }); dispatch({ type: "show-palette" });

View File

@ -11,20 +11,24 @@ function decodePageUrl(url: string): string {
export class PathPageNavigator { export class PathPageNavigator {
navigationResolve?: () => void; navigationResolve?: () => void;
constructor(readonly root: string = "") {} constructor(readonly indexPage: string, readonly root: string = "") {}
async navigate(page: string, pos?: number, replaceState = false) { async navigate(page: string, pos?: number, replaceState = false) {
let encodedPage = encodePageUrl(page);
if (page === this.indexPage) {
encodedPage = "";
}
if (replaceState) { if (replaceState) {
window.history.replaceState( window.history.replaceState(
{ page, pos }, { page, pos },
page, page,
`${this.root}/${encodePageUrl(page)}` `${this.root}/${encodedPage}`
); );
} else { } else {
window.history.pushState( window.history.pushState(
{ page, pos }, { page, pos },
page, page,
`${this.root}/${encodePageUrl(page)}` `${this.root}/${encodedPage}`
); );
} }
window.dispatchEvent( window.dispatchEvent(
@ -75,7 +79,7 @@ export class PathPageNavigator {
} }
getCurrentPage(): string { getCurrentPage(): string {
return decodePageUrl(this.decodeURI()[0]); return decodePageUrl(this.decodeURI()[0]) || this.indexPage;
} }
getCurrentPos(): number { getCurrentPos(): number {

View File

@ -23,7 +23,7 @@ export function spaceSyscalls(editor: Editor): SysCallMapping {
"space.deletePage": async (ctx, name: string) => { "space.deletePage": async (ctx, name: string) => {
// If we're deleting the current page, navigate to the index page // If we're deleting the current page, navigate to the index page
if (editor.currentPage === name) { if (editor.currentPage === name) {
await editor.navigate("index"); await editor.navigate("");
} }
// Remove page from open pages in editor // Remove page from open pages in editor
editor.openPages.delete(name); editor.openPages.delete(name);