Make index page configurable
This commit is contained in:
parent
b29b175b40
commit
7111fb6b1e
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
4
packages/server/SETTINGS_template.md
Normal file
4
packages/server/SETTINGS_template.md
Normal 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
|
||||||
|
```
|
@ -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!`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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" });
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user