Fixes #576 supporting markdown in headers and refactoring some stuff
parent
1335820abd
commit
259ad5b488
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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">
|
|
@ -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,
|
|
@ -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";
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
Loading…
Reference in New Issue