Fixes #8: SETTINGS page to keep all settings
parent
a8274d225c
commit
a69289f1ab
|
@ -107,6 +107,15 @@ export function findNodeOfType(
|
||||||
return collectNodesMatching(tree, (n) => n.type === nodeType)[0];
|
return collectNodesMatching(tree, (n) => n.type === nodeType)[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function traverseTree(
|
||||||
|
tree: ParseTree,
|
||||||
|
// Return value = should stop traversal?
|
||||||
|
matchFn: (tree: ParseTree) => boolean
|
||||||
|
): void {
|
||||||
|
// Do a collect, but ignore the result
|
||||||
|
collectNodesMatching(tree, matchFn);
|
||||||
|
}
|
||||||
|
|
||||||
// Finds non-text node at position
|
// Finds non-text node at position
|
||||||
export function nodeAtPos(tree: ParseTree, pos: number): ParseTree | null {
|
export function nodeAtPos(tree: ParseTree, pos: number): ParseTree | null {
|
||||||
if (pos < tree.from! || pos > tree.to!) {
|
if (pos < tree.from! || pos > tree.to!) {
|
||||||
|
|
|
@ -12,11 +12,8 @@ import { set as storeSet } from "@plugos/plugos-syscall/store";
|
||||||
import {
|
import {
|
||||||
flashNotification,
|
flashNotification,
|
||||||
getCurrentPage,
|
getCurrentPage,
|
||||||
getCursor,
|
|
||||||
getText,
|
getText,
|
||||||
insertAtCursor,
|
|
||||||
matchBefore,
|
matchBefore,
|
||||||
moveCursor,
|
|
||||||
navigate,
|
navigate,
|
||||||
prompt,
|
prompt,
|
||||||
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
||||||
|
|
|
@ -1,22 +1,20 @@
|
||||||
import { dispatch } from "@plugos/plugos-syscall/event";
|
import { dispatch } from "@plugos/plugos-syscall/event";
|
||||||
import { Manifest } from "@silverbulletmd/common/manifest";
|
import { Manifest } from "@silverbulletmd/common/manifest";
|
||||||
import { findNodeOfType } from "@silverbulletmd/common/tree";
|
|
||||||
import {
|
import {
|
||||||
flashNotification,
|
flashNotification,
|
||||||
save,
|
save,
|
||||||
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
} from "@silverbulletmd/plugos-silverbullet-syscall/editor";
|
||||||
import { parseMarkdown } from "@silverbulletmd/plugos-silverbullet-syscall/markdown";
|
|
||||||
import {
|
import {
|
||||||
deletePage,
|
deletePage,
|
||||||
listPages,
|
listPages,
|
||||||
readPage,
|
|
||||||
writePage,
|
writePage,
|
||||||
} from "@silverbulletmd/plugos-silverbullet-syscall/space";
|
} from "@silverbulletmd/plugos-silverbullet-syscall/space";
|
||||||
import {
|
import {
|
||||||
invokeFunction,
|
invokeFunction,
|
||||||
reloadPlugs,
|
reloadPlugs,
|
||||||
} from "@silverbulletmd/plugos-silverbullet-syscall/system";
|
} from "@silverbulletmd/plugos-silverbullet-syscall/system";
|
||||||
import YAML from "yaml";
|
|
||||||
|
import { readYamlPage } from "../lib/yaml_page";
|
||||||
|
|
||||||
async function listPlugs(): Promise<string[]> {
|
async function listPlugs(): Promise<string[]> {
|
||||||
let unfilteredPages = await listPages(true);
|
let unfilteredPages = await listPages(true);
|
||||||
|
@ -28,23 +26,22 @@ async function listPlugs(): Promise<string[]> {
|
||||||
export async function updatePlugsCommand() {
|
export async function updatePlugsCommand() {
|
||||||
await save();
|
await save();
|
||||||
flashNotification("Updating plugs...");
|
flashNotification("Updating plugs...");
|
||||||
await invokeFunction("server", "updatePlugs");
|
try {
|
||||||
flashNotification("And... done!");
|
await invokeFunction("server", "updatePlugs");
|
||||||
await reloadPlugs();
|
flashNotification("And... done!");
|
||||||
|
await reloadPlugs();
|
||||||
|
} catch (e: any) {
|
||||||
|
flashNotification("Error updating plugs: " + e.message, "error");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updatePlugs() {
|
export async function updatePlugs() {
|
||||||
let { text: plugPageText } = await readPage("PLUGS");
|
let plugList: string[] = [];
|
||||||
|
try {
|
||||||
let tree = await parseMarkdown(plugPageText);
|
plugList = await readYamlPage("PLUGS");
|
||||||
|
} catch (e: any) {
|
||||||
let codeTextNode = findNodeOfType(tree, "CodeText");
|
throw new Error(`Error processing PLUGS: ${e.message}`);
|
||||||
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);
|
console.log("Plug YAML", plugList);
|
||||||
let allPlugNames: string[] = [];
|
let allPlugNames: string[] = [];
|
||||||
for (let plugUri of plugList) {
|
for (let plugUri of plugList) {
|
||||||
|
|
|
@ -16,12 +16,14 @@ import { parseMarkdown } from "@silverbulletmd/plugos-silverbullet-syscall/markd
|
||||||
import { extractMeta } from "../query/data";
|
import { extractMeta } from "../query/data";
|
||||||
import { renderToText } from "@silverbulletmd/common/tree";
|
import { renderToText } from "@silverbulletmd/common/tree";
|
||||||
import { niceDate } from "./dates";
|
import { niceDate } from "./dates";
|
||||||
|
import { readSettings } from "../lib/settings_page";
|
||||||
const pageTemplatePrefix = `template/page/`;
|
|
||||||
const snippetPrefix = `snippet/`;
|
|
||||||
|
|
||||||
export async function instantiateTemplateCommand() {
|
export async function instantiateTemplateCommand() {
|
||||||
let allPages = await listPages();
|
let allPages = await listPages();
|
||||||
|
let { pageTemplatePrefix } = await readSettings({
|
||||||
|
pageTemplatePrefix: "template/page/",
|
||||||
|
});
|
||||||
|
|
||||||
let allPageTemplates = allPages.filter((pageMeta) =>
|
let allPageTemplates = allPages.filter((pageMeta) =>
|
||||||
pageMeta.name.startsWith(pageTemplatePrefix)
|
pageMeta.name.startsWith(pageTemplatePrefix)
|
||||||
);
|
);
|
||||||
|
@ -54,11 +56,17 @@ export async function instantiateTemplateCommand() {
|
||||||
|
|
||||||
export async function insertSnippet() {
|
export async function insertSnippet() {
|
||||||
let allPages = await listPages();
|
let allPages = await listPages();
|
||||||
|
let { snippetPrefix } = await readSettings({
|
||||||
|
snippetPrefix: "snippet/",
|
||||||
|
});
|
||||||
let cursorPos = await getCursor();
|
let cursorPos = await getCursor();
|
||||||
let page = await getCurrentPage();
|
let page = await getCurrentPage();
|
||||||
let allSnippets = allPages.filter((pageMeta) =>
|
let allSnippets = allPages
|
||||||
pageMeta.name.startsWith(snippetPrefix)
|
.filter((pageMeta) => pageMeta.name.startsWith(snippetPrefix))
|
||||||
);
|
.map((pageMeta) => ({
|
||||||
|
...pageMeta,
|
||||||
|
name: pageMeta.name.slice(snippetPrefix.length),
|
||||||
|
}));
|
||||||
|
|
||||||
let selectedSnippet = await filterBox(
|
let selectedSnippet = await filterBox(
|
||||||
"Snippet",
|
"Snippet",
|
||||||
|
@ -69,7 +77,7 @@ export async function insertSnippet() {
|
||||||
if (!selectedSnippet) {
|
if (!selectedSnippet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let { text } = await readPage(selectedSnippet.name);
|
let { text } = await readPage(`${snippetPrefix}${selectedSnippet.name}`);
|
||||||
|
|
||||||
let templateText = replaceTemplateVars(text, page);
|
let templateText = replaceTemplateVars(text, page);
|
||||||
let carretPos = templateText.indexOf("|^|");
|
let carretPos = templateText.indexOf("|^|");
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { readYamlPage } from "./yaml_page";
|
||||||
|
|
||||||
|
export async function readSettings<T extends object>(settings: T): Promise<T> {
|
||||||
|
try {
|
||||||
|
let allSettings = (await readYamlPage("SETTINGS", ["yaml"])) || {};
|
||||||
|
// TODO: I'm sure there's a better way to type this than "any"
|
||||||
|
let collectedSettings: any = {};
|
||||||
|
for (let [key, defaultVal] of Object.entries(settings)) {
|
||||||
|
if (allSettings[key]) {
|
||||||
|
collectedSettings[key] = allSettings[key];
|
||||||
|
} else {
|
||||||
|
collectedSettings[key] = defaultVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return collectedSettings as T;
|
||||||
|
} catch (e: any) {
|
||||||
|
if (e.message === "Page not found") {
|
||||||
|
// No settings yet, return default values for all
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { findNodeOfType, traverseTree } from "@silverbulletmd/common/tree";
|
||||||
|
import { parseMarkdown } from "@silverbulletmd/plugos-silverbullet-syscall/markdown";
|
||||||
|
import { readPage } from "@silverbulletmd/plugos-silverbullet-syscall/space";
|
||||||
|
import YAML from "yaml";
|
||||||
|
|
||||||
|
export async function readYamlPage(
|
||||||
|
pageName: string,
|
||||||
|
allowedLanguages = ["yaml"]
|
||||||
|
): Promise<any> {
|
||||||
|
const { text } = await readPage(pageName);
|
||||||
|
let tree = await parseMarkdown(text);
|
||||||
|
let data: any = {};
|
||||||
|
|
||||||
|
traverseTree(tree, (t): boolean => {
|
||||||
|
// Find a fenced code block
|
||||||
|
if (t.type !== "FencedCode") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let codeInfoNode = findNodeOfType(t, "CodeInfo");
|
||||||
|
if (!codeInfoNode) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!allowedLanguages.includes(codeInfoNode.children![0].text!)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let codeTextNode = findNodeOfType(t, "CodeText");
|
||||||
|
if (!codeTextNode) {
|
||||||
|
// Honestly, this shouldn't happen
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let codeText = codeTextNode.children![0].text!;
|
||||||
|
try {
|
||||||
|
data = YAML.parse(codeText);
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error("YAML Page parser error", e);
|
||||||
|
throw new Error(`YAML Error: ${e.message}`);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
Loading…
Reference in New Issue