Remove "syntax" support from plugs
parent
aaacec6d61
commit
ad4a795e7f
|
@ -27,40 +27,8 @@ export type SilverBulletHooks =
|
||||||
& EndpointHookT
|
& EndpointHookT
|
||||||
& PlugNamespaceHookT;
|
& PlugNamespaceHookT;
|
||||||
|
|
||||||
/** Syntax extension allow plugs to declaratively add new *inline* parse tree nodes to the markdown parser. */
|
|
||||||
export type SyntaxExtensions = {
|
|
||||||
/** A map of node **name** (also called "type"), to parsing and highlighting instructions. Each entry defines a new node. By convention node names (types) are UpperCamelCase (PascalCase).
|
|
||||||
*
|
|
||||||
* see: plug-api/lib/tree.ts#ParseTree
|
|
||||||
*/
|
|
||||||
syntax?: { [key: string]: NodeDef };
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Parsing and highlighting instructions for SyntaxExtension */
|
|
||||||
export type NodeDef = {
|
|
||||||
/** An array of possible first characters to begin matching on.
|
|
||||||
*
|
|
||||||
* **Example**: If this node has the regex '[abc][123]', NodeDef.firstCharacters should be ["a", "b", "c"].
|
|
||||||
*/
|
|
||||||
firstCharacters: string[];
|
|
||||||
|
|
||||||
/** A regular expression that matches the *entire* syntax, including the first character. */
|
|
||||||
regex: string;
|
|
||||||
|
|
||||||
/** CSS styles to apply to the matched text.
|
|
||||||
*
|
|
||||||
* Key-value pair of CSS key to value:
|
|
||||||
*
|
|
||||||
* **Example**: `backgroundColor: "rgba(22,22,22,0.07)"`
|
|
||||||
*/
|
|
||||||
styles?: { [key: string]: string };
|
|
||||||
|
|
||||||
/** CSS class name to apply to the matched text */
|
|
||||||
className?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** A plug manifest configures hooks, declares syntax extensions, and describes plug metadata.
|
/** A plug manifest configures hooks, declares syntax extensions, and describes plug metadata.
|
||||||
*
|
*
|
||||||
* Typically the manifest file is in a plug's root directory, named `${plugName}.plug.yaml`.
|
* Typically the manifest file is in a plug's root directory, named `${plugName}.plug.yaml`.
|
||||||
*/
|
*/
|
||||||
export type Manifest = plugos.Manifest<SilverBulletHooks> & SyntaxExtensions;
|
export type Manifest = plugos.Manifest<SilverBulletHooks>;
|
||||||
|
|
|
@ -17,6 +17,12 @@ export const AttributeTag = Tag.define();
|
||||||
export const AttributeNameTag = Tag.define();
|
export const AttributeNameTag = Tag.define();
|
||||||
export const AttributeValueTag = Tag.define();
|
export const AttributeValueTag = Tag.define();
|
||||||
|
|
||||||
|
export const NamedAnchorTag = Tag.define();
|
||||||
|
|
||||||
export const TaskTag = Tag.define();
|
export const TaskTag = Tag.define();
|
||||||
export const TaskMarkTag = Tag.define();
|
export const TaskMarkTag = Tag.define();
|
||||||
export const TaskStateTag = Tag.define();
|
export const TaskStateTag = Tag.define();
|
||||||
|
export const TaskDeadlineTag = Tag.define();
|
||||||
|
|
||||||
|
export const HashtagTag = Tag.define();
|
||||||
|
export const NakedURLTag = Tag.define();
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
import { Tag } from "../deps.ts";
|
|
||||||
import type { MarkdownConfig } from "../deps.ts";
|
|
||||||
import { System } from "../../plugos/system.ts";
|
|
||||||
import { Manifest, NodeDef } from "../manifest.ts";
|
|
||||||
|
|
||||||
export type MDExt = {
|
|
||||||
// unicode char code for efficiency .charCodeAt(0)
|
|
||||||
firstCharCodes: number[];
|
|
||||||
regex: RegExp;
|
|
||||||
nodeType: string;
|
|
||||||
tag: Tag;
|
|
||||||
styles?: { [key: string]: string };
|
|
||||||
className?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function mdExtensionSyntaxConfig({
|
|
||||||
regex,
|
|
||||||
firstCharCodes,
|
|
||||||
nodeType,
|
|
||||||
}: MDExt): MarkdownConfig {
|
|
||||||
return {
|
|
||||||
defineNodes: [nodeType],
|
|
||||||
parseInline: [
|
|
||||||
{
|
|
||||||
name: nodeType,
|
|
||||||
parse(cx, next, pos) {
|
|
||||||
if (!firstCharCodes.includes(next)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
const match = regex.exec(cx.slice(pos, cx.end));
|
|
||||||
if (!match) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return cx.addElement(cx.elt(nodeType, pos, pos + match[0].length));
|
|
||||||
},
|
|
||||||
// after: "Emphasis",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mdExtensionStyleTags({ nodeType, tag }: MDExt): {
|
|
||||||
[selector: string]: Tag | readonly Tag[];
|
|
||||||
} {
|
|
||||||
return {
|
|
||||||
[nodeType]: tag,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function loadMarkdownExtensions(system: System<any>): MDExt[] {
|
|
||||||
const mdExtensions: MDExt[] = [];
|
|
||||||
for (const plug of system.loadedPlugs.values()) {
|
|
||||||
const manifest = plug.manifest as Manifest;
|
|
||||||
if (manifest.syntax) {
|
|
||||||
for (const [nodeType, def] of Object.entries(manifest.syntax)) {
|
|
||||||
mdExtensions.push(nodeDefToMDExt(nodeType, def));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mdExtensions;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function nodeDefToMDExt(nodeType: string, def: NodeDef): MDExt {
|
|
||||||
return {
|
|
||||||
nodeType,
|
|
||||||
tag: Tag.define(),
|
|
||||||
firstCharCodes: def.firstCharacters.map((ch) => ch.charCodeAt(0)),
|
|
||||||
regex: new RegExp("^" + def.regex),
|
|
||||||
styles: def.styles,
|
|
||||||
className: def.className,
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { parse } from "./parse_tree.ts";
|
import { parse } from "./parse_tree.ts";
|
||||||
import buildMarkdown from "./parser.ts";
|
|
||||||
import {
|
import {
|
||||||
collectNodesOfType,
|
collectNodesOfType,
|
||||||
findNodeOfType,
|
findNodeOfType,
|
||||||
renderToText,
|
renderToText,
|
||||||
} from "../../plug-api/lib/tree.ts";
|
} from "../../plug-api/lib/tree.ts";
|
||||||
import { assertEquals, assertNotEquals } from "../../test_deps.ts";
|
import { assertEquals, assertNotEquals } from "../../test_deps.ts";
|
||||||
|
import { extendedMarkdownLanguage } from "./parser.ts";
|
||||||
|
|
||||||
const sample1 = `---
|
const sample1 = `---
|
||||||
type: page
|
type: page
|
||||||
|
@ -26,8 +26,7 @@ name: Zef
|
||||||
Supper`;
|
Supper`;
|
||||||
|
|
||||||
Deno.test("Test parser", () => {
|
Deno.test("Test parser", () => {
|
||||||
const lang = buildMarkdown([]);
|
let tree = parse(extendedMarkdownLanguage, sample1);
|
||||||
let tree = parse(lang, sample1);
|
|
||||||
// console.log("tree", JSON.stringify(tree, null, 2));
|
// console.log("tree", JSON.stringify(tree, null, 2));
|
||||||
// Check if rendering back to text works
|
// Check if rendering back to text works
|
||||||
assertEquals(renderToText(tree), sample1);
|
assertEquals(renderToText(tree), sample1);
|
||||||
|
@ -45,7 +44,7 @@ Deno.test("Test parser", () => {
|
||||||
// Find frontmatter
|
// Find frontmatter
|
||||||
let node = findNodeOfType(tree, "FrontMatter");
|
let node = findNodeOfType(tree, "FrontMatter");
|
||||||
assertNotEquals(node, undefined);
|
assertNotEquals(node, undefined);
|
||||||
tree = parse(lang, sampleInvalid1);
|
tree = parse(extendedMarkdownLanguage, sampleInvalid1);
|
||||||
node = findNodeOfType(tree, "FrontMatter");
|
node = findNodeOfType(tree, "FrontMatter");
|
||||||
// console.log("Invalid node", node);
|
// console.log("Invalid node", node);
|
||||||
assertEquals(node, undefined);
|
assertEquals(node, undefined);
|
||||||
|
@ -62,8 +61,7 @@ And one with nested brackets: [array: [1, 2, 3]]
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Deno.test("Test inline attribute syntax", () => {
|
Deno.test("Test inline attribute syntax", () => {
|
||||||
const lang = buildMarkdown([]);
|
const tree = parse(extendedMarkdownLanguage, inlineAttributeSample);
|
||||||
const tree = parse(lang, inlineAttributeSample);
|
|
||||||
// console.log("Attribute parsed", JSON.stringify(tree, null, 2));
|
// console.log("Attribute parsed", JSON.stringify(tree, null, 2));
|
||||||
const attributes = collectNodesOfType(tree, "Attribute");
|
const attributes = collectNodesOfType(tree, "Attribute");
|
||||||
let nameNode = findNodeOfType(attributes[0], "AttributeName");
|
let nameNode = findNodeOfType(attributes[0], "AttributeName");
|
||||||
|
@ -89,8 +87,7 @@ const multiStatusTaskExample = `
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Deno.test("Test multi-status tasks", () => {
|
Deno.test("Test multi-status tasks", () => {
|
||||||
const lang = buildMarkdown([]);
|
const tree = parse(extendedMarkdownLanguage, multiStatusTaskExample);
|
||||||
const tree = parse(lang, multiStatusTaskExample);
|
|
||||||
// console.log("Tasks parsed", JSON.stringify(tree, null, 2));
|
// console.log("Tasks parsed", JSON.stringify(tree, null, 2));
|
||||||
const tasks = collectNodesOfType(tree, "Task");
|
const tasks = collectNodesOfType(tree, "Task");
|
||||||
assertEquals(tasks.length, 3);
|
assertEquals(tasks.length, 3);
|
||||||
|
@ -107,8 +104,7 @@ const commandLinkSample = `
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Deno.test("Test command links", () => {
|
Deno.test("Test command links", () => {
|
||||||
const lang = buildMarkdown([]);
|
const tree = parse(extendedMarkdownLanguage, commandLinkSample);
|
||||||
const tree = parse(lang, commandLinkSample);
|
|
||||||
const commands = collectNodesOfType(tree, "CommandLink");
|
const commands = collectNodesOfType(tree, "CommandLink");
|
||||||
console.log("Command links parsed", JSON.stringify(commands, null, 2));
|
console.log("Command links parsed", JSON.stringify(commands, null, 2));
|
||||||
assertEquals(commands.length, 3);
|
assertEquals(commands.length, 3);
|
||||||
|
@ -125,8 +121,7 @@ const commandLinkArgsSample = `
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Deno.test("Test command link arguments", () => {
|
Deno.test("Test command link arguments", () => {
|
||||||
const lang = buildMarkdown([]);
|
const tree = parse(extendedMarkdownLanguage, commandLinkArgsSample);
|
||||||
const tree = parse(lang, commandLinkArgsSample);
|
|
||||||
const commands = collectNodesOfType(tree, "CommandLink");
|
const commands = collectNodesOfType(tree, "CommandLink");
|
||||||
assertEquals(commands.length, 2);
|
assertEquals(commands.length, 2);
|
||||||
|
|
||||||
|
@ -138,7 +133,6 @@ Deno.test("Test command link arguments", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
Deno.test("Test template directives", () => {
|
Deno.test("Test template directives", () => {
|
||||||
const lang = buildMarkdown([]);
|
const tree = parse(extendedMarkdownLanguage, `Hello there {{name}}!`);
|
||||||
const tree = parse(lang, `Hello there {{name}}!`);
|
|
||||||
console.log("Template directive", JSON.stringify(tree, null, 2));
|
console.log("Template directive", JSON.stringify(tree, null, 2));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import {
|
import {
|
||||||
BlockContext,
|
BlockContext,
|
||||||
Language,
|
|
||||||
LeafBlock,
|
LeafBlock,
|
||||||
LeafBlockParser,
|
LeafBlockParser,
|
||||||
Line,
|
Line,
|
||||||
|
@ -9,16 +8,14 @@ import {
|
||||||
StreamLanguage,
|
StreamLanguage,
|
||||||
Strikethrough,
|
Strikethrough,
|
||||||
styleTags,
|
styleTags,
|
||||||
|
Tag,
|
||||||
tags as t,
|
tags as t,
|
||||||
yamlLanguage,
|
yamlLanguage,
|
||||||
} from "../deps.ts";
|
} from "../deps.ts";
|
||||||
import * as ct from "./customtags.ts";
|
import * as ct from "./customtags.ts";
|
||||||
|
import { HashtagTag, TaskDeadlineTag } from "./customtags.ts";
|
||||||
|
import { NakedURLTag } from "./customtags.ts";
|
||||||
import { TaskList } from "./extended_task.ts";
|
import { TaskList } from "./extended_task.ts";
|
||||||
import {
|
|
||||||
MDExt,
|
|
||||||
mdExtensionStyleTags,
|
|
||||||
mdExtensionSyntaxConfig,
|
|
||||||
} from "./markdown_ext.ts";
|
|
||||||
|
|
||||||
export const pageLinkRegex = /^\[\[([^\]\|]+)(\|([^\]]+))?\]\]/;
|
export const pageLinkRegex = /^\[\[([^\]\|]+)(\|([^\]]+))?\]\]/;
|
||||||
|
|
||||||
|
@ -313,6 +310,77 @@ export const Comment: MarkdownConfig = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type RegexParserExtension = {
|
||||||
|
// unicode char code for efficiency .charCodeAt(0)
|
||||||
|
firstCharCode: number;
|
||||||
|
regex: RegExp;
|
||||||
|
nodeType: string;
|
||||||
|
tag: Tag;
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
function regexParser({
|
||||||
|
regex,
|
||||||
|
firstCharCode,
|
||||||
|
nodeType,
|
||||||
|
}: RegexParserExtension): MarkdownConfig {
|
||||||
|
return {
|
||||||
|
defineNodes: [nodeType],
|
||||||
|
parseInline: [
|
||||||
|
{
|
||||||
|
name: nodeType,
|
||||||
|
parse(cx, next, pos) {
|
||||||
|
if (firstCharCode !== next) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
const match = regex.exec(cx.slice(pos, cx.end));
|
||||||
|
if (!match) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return cx.addElement(cx.elt(nodeType, pos, pos + match[0].length));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const NakedURL = regexParser(
|
||||||
|
{
|
||||||
|
firstCharCode: 104, // h
|
||||||
|
regex:
|
||||||
|
/^https?:\/\/[-a-zA-Z0-9@:%._\+~#=]{1,256}([-a-zA-Z0-9()@:%_\+.~#?&=\/]*)/,
|
||||||
|
nodeType: "NakedURL",
|
||||||
|
className: "sb-naked-url",
|
||||||
|
tag: NakedURLTag,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const Hashtag = regexParser(
|
||||||
|
{
|
||||||
|
firstCharCode: 35, // #
|
||||||
|
regex: /^#[^#\d\s\[\]]+\w+/,
|
||||||
|
nodeType: "Hashtag",
|
||||||
|
className: "sb-hashtag",
|
||||||
|
tag: ct.HashtagTag,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const TaskDeadline = regexParser({
|
||||||
|
firstCharCode: 55357, // 📅
|
||||||
|
regex: /^📅\s*\d{4}\-\d{2}\-\d{2}/,
|
||||||
|
className: "sb-task-deadline",
|
||||||
|
nodeType: "DeadlineDate",
|
||||||
|
tag: ct.TaskDeadlineTag,
|
||||||
|
});
|
||||||
|
|
||||||
|
const NamedAnchor = regexParser({
|
||||||
|
firstCharCode: 36, // $
|
||||||
|
regex: /^\$[a-zA-Z\.\-\/]+[\w\.\-\/]*/,
|
||||||
|
className: "sb-named-anchor",
|
||||||
|
nodeType: "NamedAnchor",
|
||||||
|
tag: ct.NamedAnchorTag,
|
||||||
|
});
|
||||||
|
|
||||||
import { Table } from "./table_parser.ts";
|
import { Table } from "./table_parser.ts";
|
||||||
import { foldNodeProp } from "@codemirror/language";
|
import { foldNodeProp } from "@codemirror/language";
|
||||||
|
|
||||||
|
@ -379,54 +447,56 @@ export const FrontMatter: MarkdownConfig = {
|
||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function buildMarkdown(mdExtensions: MDExt[]): Language {
|
export const extendedMarkdownLanguage = markdown({
|
||||||
return markdown({
|
extensions: [
|
||||||
extensions: [
|
WikiLink,
|
||||||
WikiLink,
|
CommandLink,
|
||||||
CommandLink,
|
Attribute,
|
||||||
Attribute,
|
FrontMatter,
|
||||||
FrontMatter,
|
TaskList,
|
||||||
TaskList,
|
Comment,
|
||||||
Comment,
|
Highlight,
|
||||||
Highlight,
|
TemplateDirective,
|
||||||
TemplateDirective,
|
Strikethrough,
|
||||||
Strikethrough,
|
Table,
|
||||||
Table,
|
NakedURL,
|
||||||
...mdExtensions.map(mdExtensionSyntaxConfig),
|
Hashtag,
|
||||||
{
|
TaskDeadline,
|
||||||
props: [
|
NamedAnchor,
|
||||||
foldNodeProp.add({
|
{
|
||||||
// Don't fold at the list level
|
props: [
|
||||||
BulletList: () => null,
|
foldNodeProp.add({
|
||||||
OrderedList: () => null,
|
// Don't fold at the list level
|
||||||
// Fold list items
|
BulletList: () => null,
|
||||||
ListItem: (tree, state) => ({
|
OrderedList: () => null,
|
||||||
from: state.doc.lineAt(tree.from).to,
|
// Fold list items
|
||||||
to: tree.to,
|
ListItem: (tree, state) => ({
|
||||||
}),
|
from: state.doc.lineAt(tree.from).to,
|
||||||
// Fold frontmatter
|
to: tree.to,
|
||||||
FrontMatter: (tree) => ({
|
|
||||||
from: tree.from,
|
|
||||||
to: tree.to,
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
|
// Fold frontmatter
|
||||||
|
FrontMatter: (tree) => ({
|
||||||
|
from: tree.from,
|
||||||
|
to: tree.to,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
|
||||||
styleTags({
|
styleTags({
|
||||||
Task: ct.TaskTag,
|
Task: ct.TaskTag,
|
||||||
TaskMark: ct.TaskMarkTag,
|
TaskMark: ct.TaskMarkTag,
|
||||||
Comment: ct.CommentTag,
|
Comment: ct.CommentTag,
|
||||||
"TableDelimiter SubscriptMark SuperscriptMark StrikethroughMark":
|
"TableDelimiter SubscriptMark SuperscriptMark StrikethroughMark":
|
||||||
t.processingInstruction,
|
t.processingInstruction,
|
||||||
"TableHeader/...": t.heading,
|
"TableHeader/...": t.heading,
|
||||||
TableCell: t.content,
|
TableCell: t.content,
|
||||||
CodeInfo: ct.CodeInfoTag,
|
CodeInfo: ct.CodeInfoTag,
|
||||||
HorizontalRule: ct.HorizontalRuleTag,
|
HorizontalRule: ct.HorizontalRuleTag,
|
||||||
}),
|
Hashtag: ct.HashtagTag,
|
||||||
...mdExtensions.map((mdExt) =>
|
NakedURL: ct.NakedURLTag,
|
||||||
styleTags(mdExtensionStyleTags(mdExt))
|
DeadlineDate: ct.TaskDeadlineTag,
|
||||||
),
|
NamedAnchor: ct.NamedAnchorTag,
|
||||||
],
|
}),
|
||||||
},
|
],
|
||||||
],
|
},
|
||||||
}).language;
|
],
|
||||||
}
|
}).language;
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { SysCallMapping } from "../../plugos/system.ts";
|
import { SysCallMapping } from "../../plugos/system.ts";
|
||||||
import { parse } from "../markdown_parser/parse_tree.ts";
|
import { parse } from "../markdown_parser/parse_tree.ts";
|
||||||
import { Language } from "../../web/deps.ts";
|
|
||||||
import type { ParseTree } from "$sb/lib/tree.ts";
|
import type { ParseTree } from "$sb/lib/tree.ts";
|
||||||
|
import { extendedMarkdownLanguage } from "../markdown_parser/parser.ts";
|
||||||
|
|
||||||
export function markdownSyscalls(lang: Language): SysCallMapping {
|
export function markdownSyscalls(): SysCallMapping {
|
||||||
return {
|
return {
|
||||||
"markdown.parseMarkdown": (_ctx, text: string): ParseTree => {
|
"markdown.parseMarkdown": (_ctx, text: string): ParseTree => {
|
||||||
return parse(lang, text);
|
return parse(extendedMarkdownLanguage, text);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import "$sb/lib/syscall_mock.ts";
|
import "$sb/lib/syscall_mock.ts";
|
||||||
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
||||||
import buildMarkdown from "../../common/markdown_parser/parser.ts";
|
|
||||||
import { extractAttributes } from "$sb/lib/attribute.ts";
|
import { extractAttributes } from "$sb/lib/attribute.ts";
|
||||||
import { assertEquals } from "../../test_deps.ts";
|
import { assertEquals } from "../../test_deps.ts";
|
||||||
import { renderToText } from "$sb/lib/tree.ts";
|
import { renderToText } from "$sb/lib/tree.ts";
|
||||||
|
import { extendedMarkdownLanguage } from "../../common/markdown_parser/parser.ts";
|
||||||
|
|
||||||
const inlineAttributeSample = `
|
const inlineAttributeSample = `
|
||||||
# My document
|
# My document
|
||||||
|
@ -26,8 +26,7 @@ Top level attributes:
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Deno.test("Test attribute extraction", async () => {
|
Deno.test("Test attribute extraction", async () => {
|
||||||
const lang = buildMarkdown([]);
|
const tree = parse(extendedMarkdownLanguage, inlineAttributeSample);
|
||||||
const tree = parse(lang, inlineAttributeSample);
|
|
||||||
const toplevelAttributes = await extractAttributes(tree, false);
|
const toplevelAttributes = await extractAttributes(tree, false);
|
||||||
// console.log("All attributes", toplevelAttributes);
|
// console.log("All attributes", toplevelAttributes);
|
||||||
assertEquals(toplevelAttributes.name, "sup");
|
assertEquals(toplevelAttributes.name, "sup");
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import "$sb/lib/syscall_mock.ts";
|
import "$sb/lib/syscall_mock.ts";
|
||||||
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
||||||
import buildMarkdown from "../../common/markdown_parser/parser.ts";
|
|
||||||
import { assertEquals } from "../../test_deps.ts";
|
import { assertEquals } from "../../test_deps.ts";
|
||||||
import { extractFeedItems } from "$sb/lib/feed.ts";
|
import { extractFeedItems } from "$sb/lib/feed.ts";
|
||||||
import { nodeDefToMDExt } from "../../common/markdown_parser/markdown_ext.ts";
|
import { extendedMarkdownLanguage } from "../../common/markdown_parser/parser.ts";
|
||||||
|
|
||||||
const feedSample1 = `---
|
const feedSample1 = `---
|
||||||
test: ignore me
|
test: ignore me
|
||||||
|
@ -25,11 +24,7 @@ Completely free form
|
||||||
|
|
||||||
Deno.test("Test feed parsing", async () => {
|
Deno.test("Test feed parsing", async () => {
|
||||||
// Ad hoc added the NamedAnchor extension from the core plug-in inline here
|
// Ad hoc added the NamedAnchor extension from the core plug-in inline here
|
||||||
const lang = buildMarkdown([nodeDefToMDExt("NamedAnchor", {
|
const tree = parse(extendedMarkdownLanguage, feedSample1);
|
||||||
firstCharacters: ["$"],
|
|
||||||
regex: "\\$[a-zA-Z\\.\\-\\/]+[\\w\\.\\-\\/]*",
|
|
||||||
})]);
|
|
||||||
const tree = parse(lang, feedSample1);
|
|
||||||
const items = await extractFeedItems(tree);
|
const items = await extractFeedItems(tree);
|
||||||
assertEquals(items.length, 3);
|
assertEquals(items.length, 3);
|
||||||
assertEquals(items[0], {
|
assertEquals(items[0], {
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import wikiMarkdownLang from "../../common/markdown_parser/parser.ts";
|
|
||||||
import type { ParseTree } from "$sb/lib/tree.ts";
|
import type { ParseTree } from "$sb/lib/tree.ts";
|
||||||
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
||||||
|
import { extendedMarkdownLanguage } from "../../common/markdown_parser/parser.ts";
|
||||||
|
|
||||||
export function parseMarkdown(text: string): ParseTree {
|
export function parseMarkdown(text: string): ParseTree {
|
||||||
const lang = wikiMarkdownLang([]);
|
return parse(extendedMarkdownLanguage, text);
|
||||||
return parse(lang, text);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,9 @@ import {
|
||||||
renderToText,
|
renderToText,
|
||||||
replaceNodesMatching,
|
replaceNodesMatching,
|
||||||
} from "./tree.ts";
|
} from "./tree.ts";
|
||||||
import wikiMarkdownLang from "../../common/markdown_parser/parser.ts";
|
|
||||||
import { assertEquals, assertNotEquals } from "../../test_deps.ts";
|
import { assertEquals, assertNotEquals } from "../../test_deps.ts";
|
||||||
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
||||||
|
import { extendedMarkdownLanguage } from "../../common/markdown_parser/parser.ts";
|
||||||
|
|
||||||
const mdTest1 = `
|
const mdTest1 = `
|
||||||
# Heading
|
# Heading
|
||||||
|
@ -49,8 +49,7 @@ name: something
|
||||||
`;
|
`;
|
||||||
|
|
||||||
Deno.test("Test parsing", () => {
|
Deno.test("Test parsing", () => {
|
||||||
const lang = wikiMarkdownLang([]);
|
const mdTree = parse(extendedMarkdownLanguage, mdTest1);
|
||||||
const mdTree = parse(lang, mdTest1);
|
|
||||||
addParentPointers(mdTree);
|
addParentPointers(mdTree);
|
||||||
// console.log(JSON.stringify(mdTree, null, 2));
|
// console.log(JSON.stringify(mdTree, null, 2));
|
||||||
const wikiLink = nodeAtPos(mdTree, mdTest1.indexOf("Wiki Page"))!;
|
const wikiLink = nodeAtPos(mdTree, mdTest1.indexOf("Wiki Page"))!;
|
||||||
|
@ -75,12 +74,11 @@ Deno.test("Test parsing", () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// console.log(JSON.stringify(mdTree, null, 2));
|
// console.log(JSON.stringify(mdTree, null, 2));
|
||||||
let mdTree3 = parse(lang, mdTest3);
|
let mdTree3 = parse(extendedMarkdownLanguage, mdTest3);
|
||||||
// console.log(JSON.stringify(mdTree3, null, 2));
|
// console.log(JSON.stringify(mdTree3, null, 2));
|
||||||
});
|
});
|
||||||
|
|
||||||
Deno.test("AST functions", () => {
|
Deno.test("AST functions", () => {
|
||||||
const lang = wikiMarkdownLang([]);
|
const mdTree = parse(extendedMarkdownLanguage, mdTest1);
|
||||||
const mdTree = parse(lang, mdTest1);
|
|
||||||
console.log(JSON.stringify(parseTreeToAST(mdTree), null, 2));
|
console.log(JSON.stringify(parseTreeToAST(mdTree), null, 2));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,4 @@
|
||||||
name: editor
|
name: editor
|
||||||
syntax:
|
|
||||||
NakedURL:
|
|
||||||
firstCharacters:
|
|
||||||
- "h"
|
|
||||||
regex: "https?:\\/\\/[-a-zA-Z0-9@:%._\\+~#=]{1,256}([-a-zA-Z0-9()@:%_\\+.~#?&=\\/]*)"
|
|
||||||
className: sb-naked-url
|
|
||||||
functions:
|
functions:
|
||||||
setEditorMode:
|
setEditorMode:
|
||||||
path: "./editor.ts:setEditorMode"
|
path: "./editor.ts:setEditorMode"
|
||||||
|
|
|
@ -1,15 +1,4 @@
|
||||||
name: index
|
name: index
|
||||||
syntax:
|
|
||||||
Hashtag:
|
|
||||||
firstCharacters:
|
|
||||||
- "#"
|
|
||||||
regex: "#[^#\\d\\s\\[\\]]+\\w+"
|
|
||||||
className: sb-hashtag
|
|
||||||
NamedAnchor:
|
|
||||||
firstCharacters:
|
|
||||||
- "$"
|
|
||||||
regex: "\\$[a-zA-Z\\.\\-\\/]+[\\w\\.\\-\\/]*"
|
|
||||||
className: sb-named-anchor
|
|
||||||
functions:
|
functions:
|
||||||
loadBuiltinsIntoIndex:
|
loadBuiltinsIntoIndex:
|
||||||
path: builtins.ts:loadBuiltinsIntoIndex
|
path: builtins.ts:loadBuiltinsIntoIndex
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import buildMarkdown from "../../common/markdown_parser/parser.ts";
|
|
||||||
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
||||||
import { System } from "../../plugos/system.ts";
|
import { System } from "../../plugos/system.ts";
|
||||||
|
|
||||||
import { createSandbox } from "../../plugos/sandboxes/deno_worker_sandbox.ts";
|
import { createSandbox } from "../../plugos/sandboxes/deno_worker_sandbox.ts";
|
||||||
import { loadMarkdownExtensions } from "../../common/markdown_parser/markdown_ext.ts";
|
|
||||||
import { renderMarkdownToHtml } from "./markdown_render.ts";
|
import { renderMarkdownToHtml } from "./markdown_render.ts";
|
||||||
|
import { extendedMarkdownLanguage } from "../../common/markdown_parser/parser.ts";
|
||||||
|
|
||||||
Deno.test("Markdown render", async () => {
|
Deno.test("Markdown render", async () => {
|
||||||
const system = new System<any>("server");
|
const system = new System<any>("server");
|
||||||
|
@ -20,11 +19,10 @@ Deno.test("Markdown render", async () => {
|
||||||
new URL("../../dist_plug_bundle/_plug/tasks.plug.js", import.meta.url),
|
new URL("../../dist_plug_bundle/_plug/tasks.plug.js", import.meta.url),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
const lang = buildMarkdown(loadMarkdownExtensions(system));
|
|
||||||
const testFile = Deno.readTextFileSync(
|
const testFile = Deno.readTextFileSync(
|
||||||
new URL("test/example.md", import.meta.url).pathname,
|
new URL("test/example.md", import.meta.url).pathname,
|
||||||
);
|
);
|
||||||
const tree = parse(lang, testFile);
|
const tree = parse(extendedMarkdownLanguage, testFile);
|
||||||
renderMarkdownToHtml(tree, {
|
renderMarkdownToHtml(tree, {
|
||||||
failOnUnknown: true,
|
failOnUnknown: true,
|
||||||
});
|
});
|
||||||
|
@ -35,8 +33,7 @@ Deno.test("Markdown render", async () => {
|
||||||
Deno.test("Smart hard break test", () => {
|
Deno.test("Smart hard break test", () => {
|
||||||
const example = `**Hello**
|
const example = `**Hello**
|
||||||
*world!*`;
|
*world!*`;
|
||||||
const lang = buildMarkdown([]);
|
const tree = parse(extendedMarkdownLanguage, example);
|
||||||
const tree = parse(lang, example);
|
|
||||||
const html = renderMarkdownToHtml(tree, {
|
const html = renderMarkdownToHtml(tree, {
|
||||||
failOnUnknown: true,
|
failOnUnknown: true,
|
||||||
smartHardBreak: true,
|
smartHardBreak: true,
|
||||||
|
@ -58,7 +55,7 @@ And another
|
||||||
Server: something else
|
Server: something else
|
||||||
📅 last_updated - [Release notes](release_notes_url)`;
|
📅 last_updated - [Release notes](release_notes_url)`;
|
||||||
|
|
||||||
const tree2 = parse(lang, example2);
|
const tree2 = parse(extendedMarkdownLanguage, example2);
|
||||||
const html2 = renderMarkdownToHtml(tree2, {
|
const html2 = renderMarkdownToHtml(tree2, {
|
||||||
failOnUnknown: true,
|
failOnUnknown: true,
|
||||||
smartHardBreak: true,
|
smartHardBreak: true,
|
||||||
|
|
|
@ -1,23 +1,4 @@
|
||||||
name: tasks
|
name: tasks
|
||||||
syntax:
|
|
||||||
DeadlineDate:
|
|
||||||
firstCharacters:
|
|
||||||
- "📅"
|
|
||||||
regex: "📅\\s*\\d{4}\\-\\d{2}\\-\\d{2}"
|
|
||||||
styles:
|
|
||||||
backgroundColor: "rgba(22,22,22,0.07)"
|
|
||||||
CompletedDate:
|
|
||||||
firstCharacters:
|
|
||||||
- "✅"
|
|
||||||
regex: "✅\\s*\\d{4}\\-\\d{2}\\-\\d{2}"
|
|
||||||
styles:
|
|
||||||
backgroundColor: "rgba(22,22,22,0.07)"
|
|
||||||
RepeatInterval:
|
|
||||||
firstCharacters:
|
|
||||||
- "🔁"
|
|
||||||
regex: "🔁\\s*every\\s+\\w+"
|
|
||||||
styles:
|
|
||||||
backgroundColor: "rgba(22,22,22,0.07)"
|
|
||||||
functions:
|
functions:
|
||||||
# API
|
# API
|
||||||
updateTaskState:
|
updateTaskState:
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { PlugNamespaceHook } from "../common/hooks/plug_namespace.ts";
|
import { PlugNamespaceHook } from "../common/hooks/plug_namespace.ts";
|
||||||
import { SilverBulletHooks } from "../common/manifest.ts";
|
import { SilverBulletHooks } from "../common/manifest.ts";
|
||||||
import { loadMarkdownExtensions } from "../common/markdown_parser/markdown_ext.ts";
|
|
||||||
import buildMarkdown from "../common/markdown_parser/parser.ts";
|
|
||||||
import { EventedSpacePrimitives } from "../common/spaces/evented_space_primitives.ts";
|
import { EventedSpacePrimitives } from "../common/spaces/evented_space_primitives.ts";
|
||||||
import { PlugSpacePrimitives } from "../common/spaces/plug_space_primitives.ts";
|
import { PlugSpacePrimitives } from "../common/spaces/plug_space_primitives.ts";
|
||||||
import { createSandbox } from "../plugos/sandboxes/web_worker_sandbox.ts";
|
import { createSandbox } from "../plugos/sandboxes/web_worker_sandbox.ts";
|
||||||
|
@ -135,7 +133,7 @@ export class ServerSystem {
|
||||||
dataStoreSyscalls(this.ds),
|
dataStoreSyscalls(this.ds),
|
||||||
debugSyscalls(),
|
debugSyscalls(),
|
||||||
codeWidgetSyscalls(codeWidgetHook),
|
codeWidgetSyscalls(codeWidgetHook),
|
||||||
markdownSyscalls(buildMarkdown([])), // Will later be replaced with markdown extensions
|
markdownSyscalls(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Syscalls that require some additional permissions
|
// Syscalls that require some additional permissions
|
||||||
|
@ -151,12 +149,6 @@ export class ServerSystem {
|
||||||
|
|
||||||
await this.loadPlugs();
|
await this.loadPlugs();
|
||||||
|
|
||||||
// Load markdown syscalls based on all new syntax (if any)
|
|
||||||
this.system.registerSyscalls(
|
|
||||||
[],
|
|
||||||
markdownSyscalls(buildMarkdown(loadMarkdownExtensions(this.system))),
|
|
||||||
);
|
|
||||||
|
|
||||||
this.listInterval = setInterval(() => {
|
this.listInterval = setInterval(() => {
|
||||||
// runWithSystemLock(this.system, async () => {
|
// runWithSystemLock(this.system, async () => {
|
||||||
// await space.updatePageList();
|
// await space.updatePageList();
|
||||||
|
|
|
@ -94,17 +94,6 @@ export class Client {
|
||||||
.catch((e) => console.error("Error dispatching editor:updated event", e));
|
.catch((e) => console.error("Error dispatching editor:updated event", e));
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
debouncedPlugsUpdatedEvent = throttle(async () => {
|
|
||||||
// To register new commands, update editor state based on new plugs
|
|
||||||
this.rebuildEditorState();
|
|
||||||
await this.dispatchAppEvent(
|
|
||||||
"editor:pageLoaded",
|
|
||||||
this.currentPage,
|
|
||||||
undefined,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
// Track if plugs have been updated since sync cycle
|
// Track if plugs have been updated since sync cycle
|
||||||
fullSyncCompleted = false;
|
fullSyncCompleted = false;
|
||||||
|
|
||||||
|
@ -195,7 +184,7 @@ export class Client {
|
||||||
|
|
||||||
this.focus();
|
this.focus();
|
||||||
|
|
||||||
await this.system.init();
|
this.system.init();
|
||||||
|
|
||||||
await this.loadSettings();
|
await this.loadSettings();
|
||||||
|
|
||||||
|
@ -773,7 +762,6 @@ export class Client {
|
||||||
|
|
||||||
async loadPlugs() {
|
async loadPlugs() {
|
||||||
await this.system.reloadPlugsFromSpace(this.space);
|
await this.system.reloadPlugsFromSpace(this.space);
|
||||||
this.rebuildEditorState();
|
|
||||||
await this.eventHook.dispatchEvent("system:ready");
|
await this.eventHook.dispatchEvent("system:ready");
|
||||||
await this.dispatchAppEvent("plugs:loaded");
|
await this.dispatchAppEvent("plugs:loaded");
|
||||||
}
|
}
|
||||||
|
@ -782,12 +770,7 @@ export class Client {
|
||||||
const editorView = this.editorView;
|
const editorView = this.editorView;
|
||||||
console.log("Rebuilding editor state");
|
console.log("Rebuilding editor state");
|
||||||
|
|
||||||
this.system.updateMarkdownParser();
|
|
||||||
|
|
||||||
if (this.currentPage) {
|
if (this.currentPage) {
|
||||||
// And update the editor if a page is loaded
|
|
||||||
// this.openPages.saveState(this.currentPage);
|
|
||||||
|
|
||||||
editorView.setState(
|
editorView.setState(
|
||||||
createEditorState(
|
createEditorState(
|
||||||
this,
|
this,
|
||||||
|
@ -801,8 +784,6 @@ export class Client {
|
||||||
editorView.contentDOM,
|
editorView.contentDOM,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.openPages.restoreState(this.currentPage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,8 +911,6 @@ export class Client {
|
||||||
const editorView = this.editorView;
|
const editorView = this.editorView;
|
||||||
const previousPage = this.currentPage;
|
const previousPage = this.currentPage;
|
||||||
|
|
||||||
// console.log("Navigating to", pageName, restoreState);
|
|
||||||
|
|
||||||
// Persist current page state and nicely close page
|
// Persist current page state and nicely close page
|
||||||
if (previousPage) {
|
if (previousPage) {
|
||||||
// this.openPages.saveState(previousPage);
|
// this.openPages.saveState(previousPage);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { PlugNamespaceHook } from "../common/hooks/plug_namespace.ts";
|
import { PlugNamespaceHook } from "../common/hooks/plug_namespace.ts";
|
||||||
import { Manifest, SilverBulletHooks } from "../common/manifest.ts";
|
import { SilverBulletHooks } from "../common/manifest.ts";
|
||||||
import buildMarkdown from "../common/markdown_parser/parser.ts";
|
|
||||||
import { CronHook } from "../plugos/hooks/cron.ts";
|
import { CronHook } from "../plugos/hooks/cron.ts";
|
||||||
import { EventHook } from "../plugos/hooks/event.ts";
|
import { EventHook } from "../plugos/hooks/event.ts";
|
||||||
import { createSandbox } from "../plugos/sandboxes/web_worker_sandbox.ts";
|
import { createSandbox } from "../plugos/sandboxes/web_worker_sandbox.ts";
|
||||||
|
@ -23,10 +22,6 @@ import { syncSyscalls } from "./syscalls/sync.ts";
|
||||||
import { systemSyscalls } from "./syscalls/system.ts";
|
import { systemSyscalls } from "./syscalls/system.ts";
|
||||||
import { yamlSyscalls } from "../common/syscalls/yaml.ts";
|
import { yamlSyscalls } from "../common/syscalls/yaml.ts";
|
||||||
import { Space } from "./space.ts";
|
import { Space } from "./space.ts";
|
||||||
import {
|
|
||||||
loadMarkdownExtensions,
|
|
||||||
MDExt,
|
|
||||||
} from "../common/markdown_parser/markdown_ext.ts";
|
|
||||||
import { MQHook } from "../plugos/hooks/mq.ts";
|
import { MQHook } from "../plugos/hooks/mq.ts";
|
||||||
import { mqSyscalls } from "../plugos/syscalls/mq.ts";
|
import { mqSyscalls } from "../plugos/syscalls/mq.ts";
|
||||||
import { mqProxySyscalls } from "./syscalls/mq.proxy.ts";
|
import { mqProxySyscalls } from "./syscalls/mq.proxy.ts";
|
||||||
|
@ -51,7 +46,6 @@ export class ClientSystem {
|
||||||
slashCommandHook: SlashCommandHook;
|
slashCommandHook: SlashCommandHook;
|
||||||
namespaceHook: PlugNamespaceHook;
|
namespaceHook: PlugNamespaceHook;
|
||||||
codeWidgetHook: CodeWidgetHook;
|
codeWidgetHook: CodeWidgetHook;
|
||||||
mdExtensions: MDExt[] = [];
|
|
||||||
system: System<SilverBulletHooks>;
|
system: System<SilverBulletHooks>;
|
||||||
panelWidgetHook: PanelWidgetHook;
|
panelWidgetHook: PanelWidgetHook;
|
||||||
|
|
||||||
|
@ -139,22 +133,17 @@ export class ClientSystem {
|
||||||
const plugName = plugNameExtractRegex.exec(path)![1];
|
const plugName = plugNameExtractRegex.exec(path)![1];
|
||||||
console.log("Plug updated, reloading", plugName, "from", path);
|
console.log("Plug updated, reloading", plugName, "from", path);
|
||||||
this.system.unload(path);
|
this.system.unload(path);
|
||||||
const plug = await this.system.load(
|
await this.system.load(
|
||||||
plugName,
|
plugName,
|
||||||
createSandbox(new URL(`/${path}`, location.href)),
|
createSandbox(new URL(`/${path}`, location.href)),
|
||||||
newHash,
|
newHash,
|
||||||
);
|
);
|
||||||
if ((plug.manifest! as Manifest).syntax) {
|
|
||||||
// If there are syntax extensions, rebuild the markdown parser immediately
|
|
||||||
this.updateMarkdownParser();
|
|
||||||
}
|
|
||||||
this.client.debouncedPlugsUpdatedEvent();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
init() {
|
||||||
// Slash command hook
|
// Slash command hook
|
||||||
this.slashCommandHook = new SlashCommandHook(this.client);
|
this.slashCommandHook = new SlashCommandHook(this.client);
|
||||||
this.system.addHook(this.slashCommandHook);
|
this.system.addHook(this.slashCommandHook);
|
||||||
|
@ -166,7 +155,7 @@ export class ClientSystem {
|
||||||
editorSyscalls(this.client),
|
editorSyscalls(this.client),
|
||||||
spaceSyscalls(this.client),
|
spaceSyscalls(this.client),
|
||||||
systemSyscalls(this.system, this.client),
|
systemSyscalls(this.system, this.client),
|
||||||
markdownSyscalls(buildMarkdown(this.mdExtensions)),
|
markdownSyscalls(),
|
||||||
assetSyscalls(this.system),
|
assetSyscalls(this.system),
|
||||||
yamlSyscalls(),
|
yamlSyscalls(),
|
||||||
handlebarsSyscalls(),
|
handlebarsSyscalls(),
|
||||||
|
@ -222,16 +211,6 @@ export class ClientSystem {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMarkdownParser() {
|
|
||||||
// Load all syntax extensions
|
|
||||||
this.mdExtensions = loadMarkdownExtensions(this.system);
|
|
||||||
// And reload the syscalls to use the new syntax extensions
|
|
||||||
this.system.registerSyscalls(
|
|
||||||
[],
|
|
||||||
markdownSyscalls(buildMarkdown(this.mdExtensions)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
localSyscall(name: string, args: any[]) {
|
localSyscall(name: string, args: any[]) {
|
||||||
return this.system.localSyscall(name, args);
|
return this.system.localSyscall(name, args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { Diagnostic, linter } from "@codemirror/lint";
|
import { Diagnostic, linter } from "@codemirror/lint";
|
||||||
import type { Client } from "../client.ts";
|
import type { Client } from "../client.ts";
|
||||||
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
||||||
import buildMarkdown from "../../common/markdown_parser/parser.ts";
|
|
||||||
import { LintEvent } from "$sb/app_event.ts";
|
import { LintEvent } from "$sb/app_event.ts";
|
||||||
|
import { extendedMarkdownLanguage } from "../../common/markdown_parser/parser.ts";
|
||||||
|
|
||||||
export function plugLinter(client: Client) {
|
export function plugLinter(client: Client) {
|
||||||
return linter(async (view): Promise<Diagnostic[]> => {
|
return linter(async (view): Promise<Diagnostic[]> => {
|
||||||
const tree = parse(
|
const tree = parse(
|
||||||
buildMarkdown(client.system.mdExtensions),
|
extendedMarkdownLanguage,
|
||||||
view.state.sliceDoc(),
|
view.state.sliceDoc(),
|
||||||
);
|
);
|
||||||
const results = (await client.dispatchAppEvent("editor:lint", {
|
const results = (await client.dispatchAppEvent("editor:lint", {
|
||||||
|
|
|
@ -4,8 +4,8 @@ import type { CodeWidgetButton, CodeWidgetCallback } from "$sb/types.ts";
|
||||||
import { renderMarkdownToHtml } from "../../plugs/markdown/markdown_render.ts";
|
import { renderMarkdownToHtml } from "../../plugs/markdown/markdown_render.ts";
|
||||||
import { resolveAttachmentPath } from "$sb/lib/resolve.ts";
|
import { resolveAttachmentPath } from "$sb/lib/resolve.ts";
|
||||||
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
import { parse } from "../../common/markdown_parser/parse_tree.ts";
|
||||||
import buildMarkdown from "../../common/markdown_parser/parser.ts";
|
|
||||||
import { parsePageRef } from "$sb/lib/page.ts";
|
import { parsePageRef } from "$sb/lib/page.ts";
|
||||||
|
import { extendedMarkdownLanguage } from "../../common/markdown_parser/parser.ts";
|
||||||
|
|
||||||
const activeWidgets = new Set<MarkdownWidget>();
|
const activeWidgets = new Set<MarkdownWidget>();
|
||||||
|
|
||||||
|
@ -59,9 +59,8 @@ export class MarkdownWidget extends WidgetType {
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const lang = buildMarkdown(this.client.system.mdExtensions);
|
|
||||||
let mdTree = parse(
|
let mdTree = parse(
|
||||||
lang,
|
extendedMarkdownLanguage,
|
||||||
widgetContent.markdown!,
|
widgetContent.markdown!,
|
||||||
);
|
);
|
||||||
mdTree = await this.client.system.localSyscall(
|
mdTree = await this.client.system.localSyscall(
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { CompletionContext, CompletionResult } from "../deps.ts";
|
||||||
import { PageMeta } from "$sb/types.ts";
|
import { PageMeta } from "$sb/types.ts";
|
||||||
import { isFederationPath } from "$sb/lib/resolve.ts";
|
import { isFederationPath } from "$sb/lib/resolve.ts";
|
||||||
|
|
||||||
const tagRegex = /#[^#\d\s\[\]]+\w+/g;
|
export const tagRegex = /#[^#\d\s\[\]]+\w+/g;
|
||||||
|
|
||||||
export function PageNavigator({
|
export function PageNavigator({
|
||||||
allPages,
|
allPages,
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import buildMarkdown, {
|
import { commandLinkRegex } from "../common/markdown_parser/parser.ts";
|
||||||
commandLinkRegex,
|
|
||||||
} from "../common/markdown_parser/parser.ts";
|
|
||||||
import { readonlyMode } from "./cm_plugins/readonly.ts";
|
import { readonlyMode } from "./cm_plugins/readonly.ts";
|
||||||
import customMarkdownStyle from "./style.ts";
|
import customMarkdownStyle from "./style.ts";
|
||||||
import {
|
import {
|
||||||
|
@ -46,6 +44,7 @@ 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";
|
||||||
import { Compartment, Extension } from "@codemirror/state";
|
import { Compartment, Extension } from "@codemirror/state";
|
||||||
|
import { extendedMarkdownLanguage } from "../common/markdown_parser/parser.ts";
|
||||||
|
|
||||||
export function createEditorState(
|
export function createEditorState(
|
||||||
client: Client,
|
client: Client,
|
||||||
|
@ -55,8 +54,6 @@ export function createEditorState(
|
||||||
): EditorState {
|
): EditorState {
|
||||||
let touchCount = 0;
|
let touchCount = 0;
|
||||||
|
|
||||||
const markdownLanguage = buildMarkdown(client.system.mdExtensions);
|
|
||||||
|
|
||||||
// Ugly: keep the keyhandler compartment in the client, to be replaced later once more commands are loaded
|
// Ugly: keep the keyhandler compartment in the client, to be replaced later once more commands are loaded
|
||||||
client.keyHandlerCompartment = new Compartment();
|
client.keyHandlerCompartment = new Compartment();
|
||||||
const keyBindings = client.keyHandlerCompartment.of(
|
const keyBindings = client.keyHandlerCompartment.of(
|
||||||
|
@ -82,7 +79,7 @@ export function createEditorState(
|
||||||
|
|
||||||
// The uber markdown mode
|
// The uber markdown mode
|
||||||
markdown({
|
markdown({
|
||||||
base: markdownLanguage,
|
base: extendedMarkdownLanguage,
|
||||||
codeLanguages: (info) => {
|
codeLanguages: (info) => {
|
||||||
const lang = languageFor(info);
|
const lang = languageFor(info);
|
||||||
if (lang) {
|
if (lang) {
|
||||||
|
@ -96,10 +93,10 @@ export function createEditorState(
|
||||||
},
|
},
|
||||||
addKeymap: true,
|
addKeymap: true,
|
||||||
}),
|
}),
|
||||||
markdownLanguage.data.of({
|
extendedMarkdownLanguage.data.of({
|
||||||
closeBrackets: { brackets: ["(", "{", "[", "`"] },
|
closeBrackets: { brackets: ["(", "{", "[", "`"] },
|
||||||
}),
|
}),
|
||||||
syntaxHighlighting(customMarkdownStyle(client.system.mdExtensions)),
|
syntaxHighlighting(customMarkdownStyle()),
|
||||||
autocompletion({
|
autocompletion({
|
||||||
override: [
|
override: [
|
||||||
client.editorComplete.bind(client),
|
client.editorComplete.bind(client),
|
||||||
|
|
10
web/style.ts
10
web/style.ts
|
@ -1,9 +1,8 @@
|
||||||
import { HighlightStyle } from "../common/deps.ts";
|
import { HighlightStyle } from "../common/deps.ts";
|
||||||
import { tagHighlighter, tags as t } from "./deps.ts";
|
import { tagHighlighter, tags as t } from "./deps.ts";
|
||||||
import * as ct from "../common/markdown_parser/customtags.ts";
|
import * as ct from "../common/markdown_parser/customtags.ts";
|
||||||
import { MDExt } from "../common/markdown_parser/markdown_ext.ts";
|
|
||||||
|
|
||||||
export default function highlightStyles(mdExtension: MDExt[]) {
|
export default function highlightStyles() {
|
||||||
tagHighlighter;
|
tagHighlighter;
|
||||||
return HighlightStyle.define([
|
return HighlightStyle.define([
|
||||||
{ tag: t.heading1, class: "sb-h1" },
|
{ tag: t.heading1, class: "sb-h1" },
|
||||||
|
@ -49,8 +48,9 @@ export default function highlightStyles(mdExtension: MDExt[]) {
|
||||||
{ tag: t.processingInstruction, class: "sb-meta" },
|
{ tag: t.processingInstruction, class: "sb-meta" },
|
||||||
{ tag: t.punctuation, class: "sb-punctuation" },
|
{ tag: t.punctuation, class: "sb-punctuation" },
|
||||||
{ tag: ct.HorizontalRuleTag, class: "sb-hr" },
|
{ tag: ct.HorizontalRuleTag, class: "sb-hr" },
|
||||||
...mdExtension.map((mdExt) => {
|
{ tag: ct.HashtagTag, class: "sb-hashtag" },
|
||||||
return { tag: mdExt.tag, ...mdExt.styles, class: mdExt.className };
|
{ tag: ct.NakedURLTag, class: "sb-naked-url" },
|
||||||
}),
|
{ tag: ct.TaskDeadlineTag, class: "sb-task-deadline" },
|
||||||
|
{ tag: ct.NamedAnchorTag, class: "sb-named-anchor" },
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,6 +317,10 @@
|
||||||
font-size: 91%;
|
font-size: 91%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sb-task-deadline {
|
||||||
|
background-color: rgba(22, 22, 22, 0.07)
|
||||||
|
}
|
||||||
|
|
||||||
.sb-line-frontmatter-outside,
|
.sb-line-frontmatter-outside,
|
||||||
.sb-line-code-outside {
|
.sb-line-code-outside {
|
||||||
.sb-meta {
|
.sb-meta {
|
||||||
|
|
|
@ -6,7 +6,9 @@ release.
|
||||||
## Edge
|
## Edge
|
||||||
_The changes below are not yet released “properly”. To them out early, check out [the docs on edge](https://community.silverbullet.md/t/living-on-the-edge-builds/27)._
|
_The changes below are not yet released “properly”. To them out early, check out [the docs on edge](https://community.silverbullet.md/t/living-on-the-edge-builds/27)._
|
||||||
|
|
||||||
* Nothing new yet, be patient, but check out 0.6.0 below.
|
* Internal changes:
|
||||||
|
* Big refactor: of navigation and browser history, fixed some {[Page: Rename]} bugs along the way
|
||||||
|
* Plugs now can no longer define their own markdown syntax, migrated all plug-specific syntax into the main parser. This should remove a bunch of editor “flashing” especially during sync.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue