Fixes #576 supporting markdown in headers and refactoring some stuff

pull/596/head
Zef Hemel 2023-11-27 16:29:19 +01:00
parent 1335820abd
commit 259ad5b488
8 changed files with 36 additions and 31 deletions

View File

@ -80,7 +80,7 @@ export function filterBox(
} }
export function showPanel( export function showPanel(
id: "lhs" | "rhs" | "bhs" | "modal" | "ps" | "preface", id: "lhs" | "rhs" | "bhs" | "modal" | "bottom" | "top",
mode: number, mode: number,
html: string, html: string,
script = "", script = "",
@ -89,7 +89,7 @@ export function showPanel(
} }
export function hidePanel( export function hidePanel(
id: "lhs" | "rhs" | "bhs" | "modal" | "ps" | "preface", id: "lhs" | "rhs" | "bhs" | "modal" | "bottom" | "top",
): Promise<void> { ): Promise<void> {
return syscall("editor.hidePanel", id); return syscall("editor.hidePanel", id);
} }

View File

@ -176,13 +176,13 @@ functions:
# TOC # TOC
toggleTOC: toggleTOC:
path: toc_preface.ts:toggleTOC path: toc.ts:toggleTOC
command: command:
name: "Table of Contents: Toggle" name: "Table of Contents: Toggle"
key: ctrl-alt-t key: ctrl-alt-t
renderTOC: renderTOC:
path: toc_preface.ts:renderTOC path: toc.ts:renderTOC
env: client env: client
events: events:
- editor:pageLoaded - editor:pageLoaded

View File

@ -12,7 +12,7 @@ export async function toggleMentions() {
if (!hideMentions) { if (!hideMentions) {
await renderMentions(); await renderMentions();
} else { } else {
await editor.hidePanel("ps"); await editor.hidePanel("bottom");
} }
} }
@ -53,13 +53,13 @@ export async function renderMentions() {
}); });
if (linksResult.length === 0) { if (linksResult.length === 0) {
// Don't show the panel if there are no links here. // Don't show the panel if there are no links here.
await editor.hidePanel("ps"); await editor.hidePanel("bottom");
} else { } else {
const css = await asset.readAsset("asset/style.css"); const css = await asset.readAsset("asset/style.css");
const js = await asset.readAsset("asset/linked_mentions.js"); const js = await asset.readAsset("asset/linked_mentions.js");
await editor.showPanel( await editor.showPanel(
"ps", "bottom",
1, 1,
` <style>${css}</style> ` <style>${css}</style>
<div id="sb-main"><div id="sb-editor"><div class="cm-editor"> <div id="sb-main"><div id="sb-editor"><div class="cm-editor">

View File

@ -1,5 +1,10 @@
import { clientStore, editor, markdown } from "$sb/silverbullet-syscall/mod.ts"; import {
import { renderToText, traverseTree } from "$sb/lib/tree.ts"; clientStore,
editor,
markdown,
system,
} from "$sb/silverbullet-syscall/mod.ts";
import { renderToText, traverseTree, traverseTreeAsync } from "$sb/lib/tree.ts";
import { asset } from "$sb/syscalls.ts"; import { asset } from "$sb/syscalls.ts";
const hideTOCKey = "hideTOC"; const hideTOCKey = "hideTOC";
@ -21,18 +26,24 @@ export async function toggleTOC() {
await renderTOC(); // This will hide it if needed await renderTOC(); // This will hide it if needed
} }
async function markdownToHtml(text: string): Promise<string> {
return system.invokeFunction("markdown.markdownToHtml", text);
}
export async function renderTOC(reload = false) { export async function renderTOC(reload = false) {
if (await clientStore.get(hideTOCKey)) { if (await clientStore.get(hideTOCKey)) {
return editor.hidePanel("preface"); return editor.hidePanel("top");
} }
const page = await editor.getCurrentPage(); const page = await editor.getCurrentPage();
const text = await editor.getText(); const text = await editor.getText();
const tree = await markdown.parseMarkdown(text); const tree = await markdown.parseMarkdown(text);
const headers: Header[] = []; const headers: Header[] = [];
traverseTree(tree, (n) => { await traverseTreeAsync(tree, async (n) => {
if (n.type?.startsWith("ATXHeading")) { if (n.type?.startsWith("ATXHeading")) {
headers.push({ headers.push({
name: n.children!.slice(1).map(renderToText).join("").trim(), name: await markdownToHtml(
n.children!.slice(1).map(renderToText).join("").trim(),
),
pos: n.from!, pos: n.from!,
level: +n.type[n.type.length - 1], level: +n.type[n.type.length - 1],
}); });
@ -49,20 +60,14 @@ export async function renderTOC(reload = false) {
cachedTOC = JSON.stringify(headers); cachedTOC = JSON.stringify(headers);
if (headers.length < headerThreshold) { if (headers.length < headerThreshold) {
console.log("Not enough headers, not showing TOC", headers.length); console.log("Not enough headers, not showing TOC", headers.length);
await editor.hidePanel("preface"); await editor.hidePanel("top");
return; return;
} }
let tocMarkdown = "";
for (const header of headers) {
tocMarkdown += `${
" ".repeat(3 * (header.level - 1))
}* [${header.name}](/${page}@${header.pos})\n`;
}
const css = await asset.readAsset("asset/style.css"); const css = await asset.readAsset("asset/style.css");
const js = await asset.readAsset("asset/toc.js"); const js = await asset.readAsset("asset/toc.js");
await editor.showPanel( await editor.showPanel(
"preface", "top",
1, 1,
` <style>${css}</style> ` <style>${css}</style>
<div id="sb-main"><div id="sb-editor"><div class="cm-editor"> <div id="sb-main"><div id="sb-editor"><div class="cm-editor">

View File

@ -42,26 +42,26 @@ class IFrameWidget extends WidgetType {
export function postScriptPrefacePlugin(editor: Client) { export function postScriptPrefacePlugin(editor: Client) {
return decoratorStateField((state: EditorState) => { return decoratorStateField((state: EditorState) => {
const widgets: any[] = []; const widgets: any[] = [];
if (editor.ui.viewState.panels.preface.html) { if (editor.ui.viewState.panels.top.html) {
widgets.push( widgets.push(
Decoration.widget({ Decoration.widget({
widget: new IFrameWidget( widget: new IFrameWidget(
editor, editor,
editor.ui.viewState.panels.preface, editor.ui.viewState.panels.top,
"sb-preface-iframe", "sb-top-iframe",
), ),
side: -1, side: -1,
block: true, block: true,
}).range(0), }).range(0),
); );
} }
if (editor.ui.viewState.panels.ps.html) { if (editor.ui.viewState.panels.bottom.html) {
widgets.push( widgets.push(
Decoration.widget({ Decoration.widget({
widget: new IFrameWidget( widget: new IFrameWidget(
editor, editor,
editor.ui.viewState.panels.ps, editor.ui.viewState.panels.bottom,
"sb-ps-iframe", "sb-bottom-iframe",
), ),
side: 1, side: 1,
block: true, block: true,

View File

@ -40,7 +40,7 @@ import {
pasteLinkExtension, pasteLinkExtension,
} from "./cm_plugins/editor_paste.ts"; } from "./cm_plugins/editor_paste.ts";
import { TextChange } from "$sb/lib/change.ts"; import { TextChange } from "$sb/lib/change.ts";
import { postScriptPrefacePlugin } from "./cm_plugins/preface_ps.ts"; import { postScriptPrefacePlugin } from "./cm_plugins/top_bottom_panels.ts";
import { languageFor } from "../common/languages.ts"; import { languageFor } from "../common/languages.ts";
import { plugLinter } from "./cm_plugins/lint.ts"; import { plugLinter } from "./cm_plugins/lint.ts";

View File

@ -147,14 +147,14 @@ body {
flex: 1; flex: 1;
} }
.sb-ps-iframe { .sb-bottom-iframe {
width: 100%; width: 100%;
margin-top: 10px; margin-top: 10px;
border: 1px solid var(--editor-directive-background-color); border: 1px solid var(--editor-directive-background-color);
border-radius: 5px; border-radius: 5px;
} }
.sb-preface-iframe { .sb-top-iframe {
width: 100%; width: 100%;
margin-top: 10px; margin-top: 10px;
border: 1px solid var(--editor-directive-background-color); border: 1px solid var(--editor-directive-background-color);

View File

@ -90,8 +90,8 @@ export const initialViewState: AppViewState = {
rhs: {}, rhs: {},
bhs: {}, bhs: {},
modal: {}, modal: {},
ps: {}, top: {},
preface: {}, bottom: {},
}, },
allPages: [], allPages: [],
commands: new Map(), commands: new Map(),