Optimize bundle size + chunked builds + JIT loading
* Replaced AJV with other JSON schema library * Turndown and Vim mode (very large) now only loaded when used * Chunked builds with ESBuild
This commit is contained in:
@@ -2,12 +2,6 @@ import { syntaxTree } from "@codemirror/language";
|
||||
import { EditorView, ViewPlugin, type ViewUpdate } from "@codemirror/view";
|
||||
import type { Client } from "../client.ts";
|
||||
|
||||
// We use turndown to convert HTML to Markdown
|
||||
import TurndownService from "turndown";
|
||||
|
||||
// With tables and task notation as well
|
||||
// @ts-expect-error - No type definitions available for this package
|
||||
import { tables, taskListItems } from "@joplin/turndown-plugin-gfm";
|
||||
import { lezerToParseTree } from "../markdown_parser/parse_tree.ts";
|
||||
import {
|
||||
addParentPointers,
|
||||
@@ -21,17 +15,30 @@ import { localDateString } from "@silverbulletmd/silverbullet/lib/dates";
|
||||
import type { UploadFile } from "@silverbulletmd/silverbullet/type/client";
|
||||
import { isValidName, isValidPath } from "@silverbulletmd/silverbullet/lib/ref";
|
||||
|
||||
const turndownService = new TurndownService({
|
||||
hr: "---",
|
||||
codeBlockStyle: "fenced",
|
||||
headingStyle: "atx",
|
||||
emDelimiter: "*",
|
||||
bulletListMarker: "*", // Duh!
|
||||
strongDelimiter: "**",
|
||||
linkStyle: "inlined",
|
||||
});
|
||||
turndownService.use(taskListItems);
|
||||
turndownService.use(tables);
|
||||
// Dynamically load the turndown service (only used for clipboard pasete)
|
||||
let turndownService: any = null;
|
||||
async function getTurndownService() {
|
||||
if (!turndownService) {
|
||||
const [{ default: TurndownService }, { tables, taskListItems }] =
|
||||
await Promise.all([
|
||||
import("turndown"),
|
||||
// @ts-expect-error - No type definitions available for this package
|
||||
import("@joplin/turndown-plugin-gfm"),
|
||||
]);
|
||||
turndownService = new TurndownService({
|
||||
hr: "---",
|
||||
codeBlockStyle: "fenced",
|
||||
headingStyle: "atx",
|
||||
emDelimiter: "*",
|
||||
bulletListMarker: "*", // Duh!
|
||||
strongDelimiter: "**",
|
||||
linkStyle: "inlined",
|
||||
});
|
||||
turndownService.use(taskListItems);
|
||||
turndownService.use(tables);
|
||||
}
|
||||
return turndownService;
|
||||
}
|
||||
|
||||
function striptHtmlComments(s: string): string {
|
||||
return s.replace(/<!--[\s\S]*?-->/g, "");
|
||||
@@ -137,7 +144,7 @@ export function documentExtension(editor: Client) {
|
||||
|
||||
// Only do rich text paste if shift is NOT down
|
||||
if (richText && !shiftDown) {
|
||||
// Are we in a fencede code block?
|
||||
// Are we in a fenced code block?
|
||||
const editorText = editor.editorView.state.sliceDoc();
|
||||
const tree = lezerToParseTree(
|
||||
editorText,
|
||||
@@ -161,23 +168,26 @@ export function documentExtension(editor: Client) {
|
||||
}
|
||||
}
|
||||
|
||||
const markdown = striptHtmlComments(
|
||||
turndownService.turndown(richText),
|
||||
).trim();
|
||||
// Prevent default immediately, then do async turndown conversion
|
||||
event.preventDefault();
|
||||
const view = editor.editorView;
|
||||
const selection = view.state.selection.main;
|
||||
view.dispatch({
|
||||
changes: [
|
||||
{
|
||||
from: selection.from,
|
||||
to: selection.to,
|
||||
insert: markdown,
|
||||
safeRun(async () => {
|
||||
const td = await getTurndownService();
|
||||
const markdown = striptHtmlComments(td.turndown(richText)).trim();
|
||||
view.dispatch({
|
||||
changes: [
|
||||
{
|
||||
from: selection.from,
|
||||
to: selection.to,
|
||||
insert: markdown,
|
||||
},
|
||||
],
|
||||
selection: {
|
||||
anchor: selection.from + markdown.length,
|
||||
},
|
||||
],
|
||||
selection: {
|
||||
anchor: selection.from + markdown.length,
|
||||
},
|
||||
scrollIntoView: true,
|
||||
scrollIntoView: true,
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ import {
|
||||
ViewPlugin,
|
||||
type ViewUpdate,
|
||||
} from "@codemirror/view";
|
||||
import { vim } from "@replit/codemirror-vim";
|
||||
import { markdown } from "@codemirror/lang-markdown";
|
||||
import type { Client } from "../client.ts";
|
||||
import { loadVim } from "../vim_loader.ts";
|
||||
import { inlineContentPlugin } from "./inline_content.ts";
|
||||
import { cleanModePlugins } from "./clean.ts";
|
||||
import { lineWrapper } from "./line_wrapper.ts";
|
||||
@@ -63,6 +63,7 @@ export function createEditorState(
|
||||
// Ugly: keep the commandKeyHandler compartment in the client, to be replaced
|
||||
// later once more commands are loaded
|
||||
client.commandKeyHandlerCompartment = new Compartment();
|
||||
client.vimCompartment = new Compartment();
|
||||
const commandKeyBindings = client.commandKeyHandlerCompartment.of(
|
||||
createCommandKeyBindings(client),
|
||||
);
|
||||
@@ -76,6 +77,13 @@ export function createEditorState(
|
||||
client.undoHistoryCompartment = new Compartment();
|
||||
const undoHistory = client.undoHistoryCompartment.of([history()]);
|
||||
|
||||
const vimMode = client.ui.viewState.uiOptions.vimMode;
|
||||
|
||||
// If vim mode is requested, load it async and reconfigure the compartment
|
||||
if (vimMode) {
|
||||
void enableVimMode(client);
|
||||
}
|
||||
|
||||
return EditorState.create({
|
||||
doc: text,
|
||||
extensions: [
|
||||
@@ -93,15 +101,8 @@ export function createEditorState(
|
||||
// bindings wont trigger if they have the same keys.
|
||||
commandKeyBindings,
|
||||
|
||||
// Enable vim mode, or not
|
||||
[
|
||||
...(client.ui.viewState.uiOptions.vimMode
|
||||
? [
|
||||
vim({ status: true }),
|
||||
EditorState.allowMultipleSelections.of(true),
|
||||
]
|
||||
: []),
|
||||
],
|
||||
// Vim mode compartment — starts empty, loaded async if needed
|
||||
client.vimCompartment.of([]),
|
||||
[
|
||||
...(readOnly ||
|
||||
client.ui.viewState.uiOptions.forcedROMode ||
|
||||
@@ -425,6 +426,18 @@ export function createRegularKeyBindings(client: Client): Extension {
|
||||
}
|
||||
}
|
||||
|
||||
async function enableVimMode(client: Client) {
|
||||
const { vim } = await loadVim();
|
||||
if (client.editorView && client.vimCompartment) {
|
||||
client.editorView.dispatch({
|
||||
effects: client.vimCompartment.reconfigure([
|
||||
vim({ status: true }),
|
||||
EditorState.allowMultipleSelections.of(true),
|
||||
]),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current platform is Mac-like (Mac, iPhone, iPod, iPad).
|
||||
* @returns A boolean indicating if the platform is Mac-like.
|
||||
|
||||
Reference in New Issue
Block a user