Javascript and Typescript highlighting

This commit is contained in:
Zef Hemel
2022-04-24 18:06:34 +02:00
parent a2cb2727d2
commit 6a10cbd9b7
21 changed files with 229 additions and 744 deletions
@@ -5,6 +5,10 @@ export function getCurrentPage(): Promise<string> {
return syscall("editor.getCurrentPage");
}
export function setPage(newName: string): Promise<void> {
return syscall("editor.setPage", newName);
}
export function getText(): Promise<string> {
return syscall("editor.getText");
}
+5
View File
@@ -0,0 +1,5 @@
functions:
toggleDraftMode:
path: "./draft.ts:toggleMode"
command:
name: "Draft: Toggle Mode"
+7
View File
@@ -0,0 +1,7 @@
import * as clientStore from "@silverbulletmd/plugos-silverbullet-syscall/clientStore";
export async function toggleMode() {
let currentValue = !!(await clientStore.get("enableDraftMode"));
console.log("New draft mode", !currentValue);
await clientStore.set("enableDraftMode", !currentValue);
}
@@ -7,6 +7,7 @@ export class HttpSpacePrimitives implements SpacePrimitives {
private plugUrl: string;
constructor(url: string) {
console.log("UR", url);
this.pageUrl = url + "/fs";
this.plugUrl = url + "/plug";
}
+45 -20
View File
@@ -22,6 +22,7 @@ import { createSandbox } from "@silverbulletmd/plugos/environments/node_sandbox"
import { jwtSyscalls } from "@silverbulletmd/plugos/syscalls/jwt";
import buildMarkdown from "@silverbulletmd/web/parser";
import { loadMarkdownExtensions } from "@silverbulletmd/web/markdown_ext";
import http, { Server } from "http";
export class ExpressServer {
app: Express;
@@ -31,21 +32,19 @@ export class ExpressServer {
private distDir: string;
private eventHook: EventHook;
private db: Knex<any, unknown[]>;
private port: number;
private server?: Server;
constructor(
app: Express,
rootPath: string,
distDir: string,
system: System<SilverBulletHooks>
) {
this.app = app;
constructor(port: number, rootPath: string, distDir: string) {
this.port = port;
this.app = express();
this.rootPath = rootPath;
this.distDir = distDir;
this.system = system;
this.system = new System<SilverBulletHooks>("server");
// Setup system
this.eventHook = new EventHook();
system.addHook(this.eventHook);
this.system.addHook(this.eventHook);
this.space = new Space(
new EventedSpacePrimitives(
new DiskSpacePrimitives(rootPath),
@@ -61,15 +60,15 @@ export class ExpressServer {
useNullAsDefault: true,
});
system.registerSyscalls(["shell"], shellSyscalls(rootPath));
system.addHook(new NodeCronHook());
this.system.registerSyscalls(["shell"], shellSyscalls(rootPath));
this.system.addHook(new NodeCronHook());
system.registerSyscalls([], pageIndexSyscalls(this.db));
system.registerSyscalls([], spaceSyscalls(this.space));
system.registerSyscalls([], eventSyscalls(this.eventHook));
system.registerSyscalls([], markdownSyscalls(buildMarkdown([])));
system.registerSyscalls([], jwtSyscalls());
system.addHook(new EndpointHook(app, "/_/"));
this.system.registerSyscalls([], pageIndexSyscalls(this.db));
this.system.registerSyscalls([], spaceSyscalls(this.space));
this.system.registerSyscalls([], eventSyscalls(this.eventHook));
this.system.registerSyscalls([], markdownSyscalls(buildMarkdown([])));
this.system.registerSyscalls([], jwtSyscalls());
this.system.addHook(new EndpointHook(this.app, "/_/"));
let throttledRebuildMdExtensions = throttle(() => {
this.rebuildMdExtensions();
@@ -79,14 +78,14 @@ export class ExpressServer {
plugLoaded: (plugName, plug) => {
safeRun(async () => {
console.log("Plug load", plugName);
await system.load(plugName, plug, createSandbox);
await this.system.load(plugName, plug, createSandbox);
});
throttledRebuildMdExtensions();
},
plugUnloaded: (plugName) => {
safeRun(async () => {
console.log("Plug unload", plugName);
await system.unload(plugName);
await this.system.unload(plugName);
});
throttledRebuildMdExtensions();
},
@@ -105,10 +104,12 @@ export class ExpressServer {
);
}
async init() {
async start() {
await ensurePageIndexTable(this.db);
console.log("Setting up router");
this.app.use("/", express.static(this.distDir));
let fsRouter = express.Router();
// Page list
@@ -267,5 +268,29 @@ export class ExpressServer {
}
res.status(200).header("Content-Type", "text/html").send(cachedIndex);
});
this.server = http.createServer(this.app);
this.server.listen(this.port, () => {
console.log(`Server listening on port ${this.port}`);
});
}
async stop() {
if (this.server) {
console.log("Stopping");
await this.system.unloadAll();
console.log("Stopped plugs");
return new Promise<void>((resolve, reject) => {
this.server!.close((err) => {
this.server = undefined;
console.log("stopped server");
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
}
}
+4 -21
View File
@@ -1,12 +1,8 @@
#!/usr/bin/env node
import express from "express";
import http from "http";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
import { SilverBulletHooks } from "@silverbulletmd/common/manifest";
import { ExpressServer } from "./api_server";
import { System } from "@silverbulletmd/plugos/system";
import path from "path";
let args = yargs(hideBin(process.argv))
@@ -23,23 +19,10 @@ if (!args._.length) {
const pagesPath = args._[0] as string;
const app = express();
const server = http.createServer(app);
const system = new System<SilverBulletHooks>("server");
const port = args.port;
const distDir = path.resolve(`${__dirname}/../../silverbullet-web/dist`);
app.use("/", express.static(distDir));
const expressServer = new ExpressServer(app, pagesPath, distDir, system);
expressServer
.init()
.then(async () => {
server.listen(port, () => {
console.log(`Server listening on port ${port}`);
});
})
.catch((e) => {
console.error(e);
});
const expressServer = new ExpressServer(port, pagesPath, distDir);
expressServer.start().catch((e) => {
console.error(e);
});
+2 -5
View File
@@ -9,10 +9,7 @@ import { HttpSpacePrimitives } from "@silverbulletmd/common/spaces/http_space_pr
// @ts-ignore
let isDesktop = typeof window.desktop !== "undefined";
// @ts-ignore
let url = isDesktop ? window.desktop.url : "";
let serverSpace = new Space(new HttpSpacePrimitives(url), true);
let serverSpace = new Space(new HttpSpacePrimitives(""), true);
serverSpace.watch();
// // @ts-ignore
@@ -46,6 +43,6 @@ if (!isDesktop) {
navigator.serviceWorker
.register(new URL("service_worker.ts", import.meta.url), { type: "module" })
.then((r) => {
// console.log("Service worker registered", r);
console.log("Service worker registered", r);
});
}
+1 -2
View File
@@ -2,8 +2,7 @@ import { Tag } from "@codemirror/highlight";
export const WikiLinkTag = Tag.define();
export const WikiLinkPageTag = Tag.define();
export const TagTag = Tag.define();
export const MentionTag = Tag.define();
export const CodeInfoTag = Tag.define();
export const TaskTag = Tag.define();
export const TaskMarkerTag = Tag.define();
export const CommentTag = Tag.define();
+15 -4
View File
@@ -46,13 +46,24 @@ export class PathPageNavigator {
cb();
}
decodeURI(): [string, number] {
let parts = decodeURI(location.pathname).substring(1).split("@");
let page =
parts.length > 1 ? parts.slice(0, parts.length - 1).join("@") : parts[0];
let pos = parts.length > 1 ? parts[parts.length - 1] : "0";
if (pos.match(/^\d+$/)) {
return [page, +pos];
} else {
return [`${page}@${pos}`, 0];
}
}
getCurrentPage(): string {
let [page] = decodeURI(location.pathname).substring(1).split("@");
return decodePageUrl(page);
return decodePageUrl(this.decodeURI()[0]);
}
getCurrentPos(): number {
let [, pos] = decodeURI(location.pathname).substring(1).split("@");
return +pos || 0;
console.log("Pos", this.decodeURI()[1]);
return this.decodeURI()[1];
}
}
+7 -1
View File
@@ -5,7 +5,7 @@ import * as ct from "./customtags";
import { Language, LanguageDescription, LanguageSupport } from "@codemirror/language";
import { StreamLanguage } from "@codemirror/stream-parser";
import { yaml } from "@codemirror/legacy-modes/mode/yaml";
import { javascriptLanguage } from "@codemirror/lang-javascript";
import { javascriptLanguage, typescriptLanguage } from "@codemirror/lang-javascript";
import { MDExt, mdExtensionStyleTags, mdExtensionSyntaxConfig } from "./markdown_ext";
export const pageLinkRegex = /^\[\[([^\]]+)\]\]/;
@@ -87,6 +87,11 @@ export default function buildMarkdown(mdExtensions: MDExt[]): Language {
alias: ["js"],
support: new LanguageSupport(javascriptLanguage),
}),
LanguageDescription.of({
name: "typescript",
alias: ["ts"],
support: new LanguageSupport(typescriptLanguage),
}),
]),
}),
{
@@ -101,6 +106,7 @@ export default function buildMarkdown(mdExtensions: MDExt[]): Language {
t.processingInstruction,
"TableHeader/...": t.heading,
TableCell: t.content,
CodeInfo: ct.CodeInfoTag,
}),
...mdExtensions.map((mdExt) =>
styleTags(mdExtensionStyleTags(mdExt))
+18
View File
@@ -1,4 +1,7 @@
import { KeyBinding } from "@codemirror/view";
import { syntaxTree } from "@codemirror/language";
const straightQuoteContexts = ["CommentBlock", "FencedCode", "InlineCode"];
// TODO: Add support for selection (put quotes around or create blockquote block?)
function keyBindingForQuote(
@@ -11,6 +14,21 @@ function keyBindingForQuote(
run: (target): boolean => {
let cursorPos = target.state.selection.main.from;
let chBefore = target.state.sliceDoc(cursorPos - 1, cursorPos);
// Figure out the context, if in some sort of code/comment fragment don't be smart
let node = syntaxTree(target.state).resolveInner(cursorPos);
while (node) {
if (straightQuoteContexts.includes(node.type.name)) {
return false;
}
if (node.parent) {
node = node.parent;
} else {
break;
}
}
// Ok, still here, let's use a smart quote
let quote = right;
if (/\W/.exec(chBefore) && !/[!\?,\.\-=“]/.exec(chBefore)) {
quote = left;
+3 -2
View File
@@ -14,10 +14,9 @@ export default function highlightStyles(mdExtension: MDExt[]) {
{ tag: t.url, class: "url" },
{ tag: ct.WikiLinkTag, class: "wiki-link" },
{ tag: ct.WikiLinkPageTag, class: "wiki-link-page" },
{ tag: ct.TagTag, class: "tag" },
{ tag: ct.MentionTag, class: "mention" },
{ tag: ct.TaskTag, class: "task" },
{ tag: ct.TaskMarkerTag, class: "task-marker" },
{ tag: ct.CodeInfoTag, class: "code-info" },
{ tag: ct.CommentTag, class: "comment" },
{ tag: ct.CommentMarkerTag, class: "comment-marker" },
{ tag: t.emphasis, class: "emphasis" },
@@ -28,12 +27,14 @@ export default function highlightStyles(mdExtension: MDExt[]) {
{ tag: t.inserted, class: "inserted" },
{ tag: t.deleted, class: "deleted" },
{ tag: t.literal, class: "literal" },
{ tag: t.keyword, class: "keyword" },
{ tag: t.list, class: "list" },
{ tag: t.definition, class: "li" },
{ tag: t.string, class: "string" },
{ tag: t.number, class: "number" },
{ tag: [t.regexp, t.escape, t.special(t.string)], class: "string2" },
{ tag: t.variableName, class: "variableName" },
{ tag: t.typeName, class: "typeName" },
{ tag: t.comment, class: "comment" },
{ tag: t.invalid, class: "invalid" },
{ tag: t.processingInstruction, class: "meta" },
@@ -87,6 +87,38 @@
.code {
background-color: transparent;
}
// Set this to defaults
.comment {
color: #989797;
background-color: transparent;
border-radius: 0;
font-style: inherit;
font-size: inherit;
line-height: inherit;
}
.keyword {
color: #830000;
}
.variableName {
color: #036d9b;
}
.typeName {
color: #038138;
}
.string,.string2 {
color: #440377;
}
//.code-info {
// background: black;
// border-radius: 3px;
//}
}
.meta {
@@ -31,6 +31,13 @@ export function editorSyscalls(editor: Editor): SysCallMapping {
"editor.getCurrentPage": (): string => {
return editor.currentPage!;
},
// sets the current page name, without changing the content
"editor.setPage": (ctx, newName: string) => {
return editor.viewDispatch({
type: "page-loaded",
name: newName,
});
},
"editor.getText": () => {
return editor.editorView?.state.sliceDoc();
},