diff --git a/.gitignore b/.gitignore index 0548422..ad00db7 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -nuggets +pages diff --git a/plugins/core/click.ts b/plugins/core/click.ts new file mode 100644 index 0000000..4a30afa --- /dev/null +++ b/plugins/core/click.ts @@ -0,0 +1,13 @@ +import { ClickEvent } from "../../webapp/src/app_event.ts"; +import { syscall } from "./lib/syscall.ts"; + +export default async function click(event: ClickEvent) { + console.log("Event", event); + if (event.ctrlKey || event.metaKey) { + let syntaxNode = await syscall("editor.getSyntaxNodeAtPos", event.pos); + console.log("Here", syntaxNode); + if (syntaxNode && syntaxNode.name === "WikiLinkPage") { + await syscall("editor.navigate", syntaxNode.text); + } + } +} diff --git a/plugins/core/core.plugin.json b/plugins/core/core.plugin.json index 020b435..9f8e31d 100644 --- a/plugins/core/core.plugin.json +++ b/plugins/core/core.plugin.json @@ -1,16 +1,12 @@ { "commands": { "Count Words": { - "invoke": "word_count_command", - "requiredContext": { - "text": true - } + "invoke": "word_count_command" }, "Navigate To page": { "invoke": "link_navigate", "key": "Ctrl-Enter", - "mac": "Cmd-Enter", - "requiredContext": {} + "mac": "Cmd-Enter" }, "Insert Current Date": { "invoke": "insert_nice_date", @@ -28,12 +24,16 @@ } }, "events": { - "ready": ["welcome"] + "app:ready": ["welcome"], + "page:click": ["click"] }, "functions": { "welcome": { "path": "./welcome.ts" }, + "click": { + "path": "./click.ts" + }, "word_count_command": { "path": "./word_count_command.ts:wordCount" }, diff --git a/plugins/core/link_navigate.ts b/plugins/core/link_navigate.ts index b8c2485..864bede 100644 --- a/plugins/core/link_navigate.ts +++ b/plugins/core/link_navigate.ts @@ -1,6 +1,6 @@ import { syscall } from "./lib/syscall.ts"; -export async function linkNavigate({ text }: { text: string }) { +export async function linkNavigate() { let syntaxNode = await syscall("editor.getSyntaxNodeUnderCursor"); if (syntaxNode && syntaxNode.name === "WikiLinkPage") { await syscall("editor.navigate", syntaxNode.text); diff --git a/server/server.ts b/server/server.ts index dcc9827..c601812 100644 --- a/server/server.ts +++ b/server/server.ts @@ -6,21 +6,21 @@ import { oakCors } from "https://deno.land/x/cors@v1.2.0/mod.ts"; import { readAll } from "https://deno.land/std@0.126.0/streams/mod.ts"; import { exists } from "https://deno.land/std@0.126.0/fs/mod.ts"; -type NuggetMeta = { +type PageMeta = { name: string; lastModified: number; }; const fsPrefix = "/fs"; -const nuggetsPath = "../pages"; +const pagesPath = "../pages"; const fsRouter = new Router(); fsRouter.use(oakCors({ methods: ["OPTIONS", "GET", "PUT", "POST"] })); fsRouter.get("/", async (context) => { - const localPath = nuggetsPath; - let fileNames: NuggetMeta[] = []; + const localPath = pagesPath; + let fileNames: PageMeta[] = []; for await (const dirEntry of Deno.readDir(localPath)) { if (dirEntry.isFile) { const stat = await Deno.stat(`${localPath}/${dirEntry.name}`); @@ -36,9 +36,9 @@ fsRouter.get("/", async (context) => { context.response.body = JSON.stringify(fileNames); }); -fsRouter.get("/:nugget", async (context) => { - const nuggetName = context.params.nugget; - const localPath = `${nuggetsPath}/${nuggetName}.md`; +fsRouter.get("/:page", async (context) => { + const pageName = context.params.page; + const localPath = `${pagesPath}/${pageName}.md`; try { const stat = await Deno.stat(localPath); const text = await Deno.readTextFile(localPath); @@ -50,8 +50,8 @@ fsRouter.get("/:nugget", async (context) => { } }); -fsRouter.options("/:nugget", async (context) => { - const localPath = `${nuggetsPath}/${context.params.nugget}.md`; +fsRouter.options("/:page", async (context) => { + const localPath = `${pagesPath}/${context.params.page}.md`; try { const stat = await Deno.stat(localPath); context.response.headers.set("Content-length", `${stat.size}`); @@ -63,10 +63,10 @@ fsRouter.options("/:nugget", async (context) => { } }); -fsRouter.put("/:nugget", async (context) => { - const nuggetName = context.params.nugget; - const localPath = `${nuggetsPath}/${nuggetName}.md`; - const existingNugget = await exists(localPath); +fsRouter.put("/:page", async (context) => { + const pageName = context.params.page; + const localPath = `${pagesPath}/${pageName}.md`; + const existingPage = await exists(localPath); let file; try { file = await Deno.create(localPath); @@ -82,7 +82,7 @@ fsRouter.put("/:nugget", async (context) => { file.close(); const stat = await Deno.stat(localPath); console.log("Wrote to", localPath); - context.response.status = existingNugget ? 200 : 201; + context.response.status = existingPage ? 200 : 201; context.response.headers.set("Last-Modified", "" + stat.mtime?.getTime()); context.response.body = "OK"; }); diff --git a/webapp/src/app_event.ts b/webapp/src/app_event.ts new file mode 100644 index 0000000..3d5f33e --- /dev/null +++ b/webapp/src/app_event.ts @@ -0,0 +1,8 @@ +export type AppEvent = "app:ready" | "page:save" | "page:load" | "page:click"; + +export type ClickEvent = { + pos: number; + metaKey: boolean; + ctrlKey: boolean; + altKey: boolean; +}; diff --git a/webapp/src/boot.ts b/webapp/src/boot.ts index c57217d..e26a748 100644 --- a/webapp/src/boot.ts +++ b/webapp/src/boot.ts @@ -1,9 +1,9 @@ import { Editor } from "./editor"; -import { HttpFileSystem } from "./fs"; +import { HttpRemoteSpace } from "./space"; import { safeRun } from "./util"; let editor = new Editor( - new HttpFileSystem(`http://${location.hostname}:2222/fs`), + new HttpRemoteSpace(`http://${location.hostname}:2222/fs`), document.getElementById("root")! ); diff --git a/webapp/src/buildContext.tsx b/webapp/src/buildContext.tsx deleted file mode 100644 index 1783e19..0000000 --- a/webapp/src/buildContext.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Editor } from "./editor"; -import { AppCommand, CommandContext } from "./types"; - -export function buildContext(cmd: AppCommand, editor: Editor) { - let ctx: CommandContext = {}; - if (!cmd.command.requiredContext) { - return ctx; - } - if (cmd.command.requiredContext.text) { - ctx.text = editor.editorView?.state.sliceDoc(); - } - return ctx; -} diff --git a/webapp/src/components/navigation_bar.tsx b/webapp/src/components/navigation_bar.tsx index dc94d22..2424f2e 100644 --- a/webapp/src/components/navigation_bar.tsx +++ b/webapp/src/components/navigation_bar.tsx @@ -1,16 +1,16 @@ -import { NuggetMeta } from "../types"; +import { PageMeta } from "../types"; export function NavigationBar({ - currentNugget, + currentPage, onClick, }: { - currentNugget?: NuggetMeta; + currentPage?: PageMeta; onClick: () => void; }) { return (
-
- » {currentNugget?.name} +
+ » {currentPage?.name}
); diff --git a/webapp/src/components/nugget_navigator.tsx b/webapp/src/components/page_navigator.tsx similarity index 58% rename from webapp/src/components/nugget_navigator.tsx rename to webapp/src/components/page_navigator.tsx index 14dcac0..056cb01 100644 --- a/webapp/src/components/nugget_navigator.tsx +++ b/webapp/src/components/page_navigator.tsx @@ -1,23 +1,23 @@ -import { NuggetMeta } from "../types"; +import { PageMeta } from "../types"; import { FilterList } from "./filter"; -export function NuggetNavigator({ - allNuggets: allNuggets, +export function PageNavigator({ + allPages: allPages, onNavigate, }: { - allNuggets: NuggetMeta[]; - onNavigate: (nugget: string | undefined) => void; + allPages: PageMeta[]; + onNavigate: (page: string | undefined) => void; }) { return ( ({ + options={allPages.map((meta) => ({ ...meta, // Order by last modified date in descending order orderId: -meta.lastModified.getTime(), }))} allowNew={true} - newHint="Create nugget" + newHint="Create page" onSelect={(opt) => { onNavigate(opt?.name); }} diff --git a/webapp/src/editor.tsx b/webapp/src/editor.tsx index 244b225..7d243a8 100644 --- a/webapp/src/editor.tsx +++ b/webapp/src/editor.tsx @@ -23,13 +23,12 @@ import { import React, { useEffect, useReducer } from "react"; import ReactDOM from "react-dom"; import coreManifest from "../../plugins/dist/core.plugin.json"; -import { buildContext } from "./buildContext"; import * as commands from "./commands"; import { CommandPalette } from "./components/command_palette"; import { NavigationBar } from "./components/navigation_bar"; -import { NuggetNavigator } from "./components/nugget_navigator"; +import { PageNavigator } from "./components/page_navigator"; import { StatusBar } from "./components/status_bar"; -import { FileSystem } from "./fs"; +import { Space } from "./space"; import { lineWrapper } from "./lineWrapper"; import { markdown } from "./markdown"; import customMarkDown from "./parser"; @@ -43,20 +42,19 @@ import editorSyscalls from "./syscalls/editor.browser"; import { Action, AppCommand, - AppEvent, AppViewState, - CommandContext, initialViewState, - NuggetMeta, + PageMeta, } from "./types"; +import { AppEvent, ClickEvent } from "./app_event"; import { safeRun } from "./util"; -class NuggetState { +class PageState { editorState: EditorState; scrollTop: number; - meta: NuggetMeta; + meta: PageMeta; - constructor(editorState: EditorState, scrollTop: number, meta: NuggetMeta) { + constructor(editorState: EditorState, scrollTop: number, meta: PageMeta) { this.editorState = editorState; this.scrollTop = scrollTop; this.meta = meta; @@ -70,14 +68,14 @@ export class Editor { viewState: AppViewState; viewDispatch: React.Dispatch; $hashChange?: () => void; - openNuggets: Map; - fs: FileSystem; + openPages: Map; + fs: Space; editorCommands: Map; plugins: Plugin[]; - constructor(fs: FileSystem, parent: Element) { + constructor(fs: Space, parent: Element) { this.editorCommands = new Map(); - this.openNuggets = new Map(); + this.openPages = new Map(); this.plugins = []; this.fs = fs; this.viewState = initialViewState; @@ -92,11 +90,11 @@ export class Editor { } async init() { - await this.loadNuggetList(); + await this.loadPageList(); await this.loadPlugins(); this.$hashChange!(); this.focus(); - await this.dispatchAppEvent("ready"); + await this.dispatchAppEvent("app:ready"); } async loadPlugins() { @@ -123,7 +121,7 @@ export class Editor { let cmd = cmds[name]; this.editorCommands.set(name, { command: cmd, - run: async (arg: CommandContext): Promise => { + run: async (arg): Promise => { return await plugin.invoke(cmd.invoke, [arg]); }, }); @@ -137,8 +135,8 @@ export class Editor { } } - get currentNugget(): NuggetMeta | undefined { - return this.viewState.currentNugget; + get currentPage(): PageMeta | undefined { + return this.viewState.currentPage; } createEditorState(text: string): EditorState { @@ -152,7 +150,7 @@ export class Editor { run: (): boolean => { Promise.resolve() .then(async () => { - await def.run(buildContext(def, this)); + await def.run(null); }) .catch((e) => console.error(e)); return true; @@ -173,7 +171,7 @@ export class Editor { closeBrackets(), autocompletion({ override: [ - this.nuggetCompleter.bind(this), + this.pageCompleter.bind(this), this.commandCompleter.bind(this), ], }), @@ -232,7 +230,17 @@ export class Editor { }, ]), EditorView.domEventHandlers({ - click: this.click.bind(this), + click: (event: MouseEvent, view: EditorView) => { + safeRun(async () => { + let clickEvent: ClickEvent = { + ctrlKey: event.ctrlKey, + metaKey: event.metaKey, + altKey: event.altKey, + pos: view.posAtCoords(event)!, + }; + await this.dispatchAppEvent("page:click", clickEvent); + }); + }, }), markdown({ base: customMarkDown, @@ -245,16 +253,16 @@ export class Editor { }); } - nuggetCompleter(ctx: CompletionContext): CompletionResult | null { + pageCompleter(ctx: CompletionContext): CompletionResult | null { let prefix = ctx.matchBefore(/\[\[[\w\s]*/); if (!prefix) { return null; } return { from: prefix.from + 2, - options: this.viewState.allNuggets.map((nuggetMeta) => ({ - label: nuggetMeta.name, - type: "nugget", + options: this.viewState.allPages.map((pageMeta) => ({ + label: pageMeta.name, + type: "page", })), }; } @@ -281,7 +289,7 @@ export class Editor { }, }); safeRun(async () => { - def.run(buildContext(def, this)); + def.run(null); }); }, }); @@ -295,7 +303,7 @@ export class Editor { update(value: null, transaction: Transaction): null { if (transaction.docChanged) { this.viewDispatch({ - type: "nugget-updated", + type: "page-updated", }); } @@ -303,91 +311,83 @@ export class Editor { } click(event: MouseEvent, view: EditorView) { - if (event.metaKey || event.ctrlKey) { - let coords = view.posAtCoords(event)!; - let node = syntaxTree(view.state).resolveInner(coords); - if (node && node.name === "WikiLinkPage") { - let nuggetName = view.state.sliceDoc(node.from, node.to); - this.navigate(nuggetName); - } - if (node && node.name === "TaskMarker") { - let checkBoxText = view.state.sliceDoc(node.from, node.to); - if (checkBoxText === "[x]" || checkBoxText === "[X]") { - view.dispatch({ - changes: { from: node.from, to: node.to, insert: "[ ]" }, - }); - } else { - view.dispatch({ - changes: { from: node.from, to: node.to, insert: "[x]" }, - }); - } - } - return false; - } + // if (event.metaKey || event.ctrlKey) { + // let coords = view.posAtCoords(event)!; + // let node = syntaxTree(view.state).resolveInner(coords); + // if (node && node.name === "WikiLinkPage") { + // let pageName = view.state.sliceDoc(node.from, node.to); + // this.navigate(pageName); + // } + // if (node && node.name === "TaskMarker") { + // let checkBoxText = view.state.sliceDoc(node.from, node.to); + // if (checkBoxText === "[x]" || checkBoxText === "[X]") { + // view.dispatch({ + // changes: { from: node.from, to: node.to, insert: "[ ]" }, + // }); + // } else { + // view.dispatch({ + // changes: { from: node.from, to: node.to, insert: "[x]" }, + // }); + // } + // } + // return false; + // } } async save() { const editorState = this.editorView!.state; - if (!this.currentNugget) { + if (!this.currentPage) { return; } // Write to file system - let nuggetMeta = await this.fs.writeNugget( - this.currentNugget.name, + let pageMeta = await this.fs.writePage( + this.currentPage.name, editorState.sliceDoc() ); - // Update in open nugget cache - this.openNuggets.set( - this.currentNugget.name, - new NuggetState( - editorState, - this.editorView!.scrollDOM.scrollTop, - nuggetMeta - ) + // Update in open page cache + this.openPages.set( + this.currentPage.name, + new PageState(editorState, this.editorView!.scrollDOM.scrollTop, pageMeta) ); // Dispatch update to view - this.viewDispatch({ type: "nugget-saved", meta: nuggetMeta }); + this.viewDispatch({ type: "page-saved", meta: pageMeta }); - // If a new nugget was created, let's refresh the nugget list - if (nuggetMeta.created) { - await this.loadNuggetList(); + // If a new page was created, let's refresh the page list + if (pageMeta.created) { + await this.loadPageList(); } } - async loadNuggetList() { - let nuggetsMeta = await this.fs.listNuggets(); + async loadPageList() { + let pagesMeta = await this.fs.listPages(); this.viewDispatch({ - type: "nuggets-listed", - nuggets: nuggetsMeta, + type: "pages-listed", + pages: pagesMeta, }); } watch() { setInterval(() => { safeRun(async () => { - if (!this.currentNugget) { + if (!this.currentPage) { return; } - const currentNuggetName = this.currentNugget.name; - let newNuggetMeta = await this.fs.getMeta(currentNuggetName); + const currentPageName = this.currentPage.name; + let newPageMeta = await this.fs.getPageMeta(currentPageName); if ( - this.currentNugget.lastModified.getTime() < - newNuggetMeta.lastModified.getTime() + this.currentPage.lastModified.getTime() < + newPageMeta.lastModified.getTime() ) { console.log("File changed on disk, reloading"); - let nuggetData = await this.fs.readNugget(currentNuggetName); - this.openNuggets.set( - newNuggetMeta.name, - new NuggetState( - this.createEditorState(nuggetData.text), - 0, - newNuggetMeta - ) + let pageData = await this.fs.readPage(currentPageName); + this.openPages.set( + newPageMeta.name, + new PageState(this.createEditorState(pageData.text), 0, newPageMeta) ); - await this.loadNugget(currentNuggetName); + await this.loadPage(currentPageName); } }); }, watchInterval); @@ -405,37 +405,37 @@ export class Editor { Promise.resolve() .then(async () => { await this.save(); - const nuggetName = decodeURIComponent(location.hash.substring(1)); - console.log("Now navigating to", nuggetName); + const pageName = decodeURIComponent(location.hash.substring(1)); + console.log("Now navigating to", pageName); if (!this.editorView) { return; } - await this.loadNugget(nuggetName); + await this.loadPage(pageName); }) .catch((e) => { console.error(e); }); } - async loadNugget(nuggetName: string) { - let nuggetState = this.openNuggets.get(nuggetName); - if (!nuggetState) { - let nuggetData = await this.fs.readNugget(nuggetName); - nuggetState = new NuggetState( - this.createEditorState(nuggetData.text), + async loadPage(pageName: string) { + let pageState = this.openPages.get(pageName); + if (!pageState) { + let pageData = await this.fs.readPage(pageName); + pageState = new PageState( + this.createEditorState(pageData.text), 0, - nuggetData.meta + pageData.meta ); - this.openNuggets.set(nuggetName, nuggetState!); + this.openPages.set(pageName, pageState!); } - this.editorView!.setState(nuggetState!.editorState); - this.editorView!.scrollDOM.scrollTop = nuggetState!.scrollTop; + this.editorView!.setState(pageState!.editorState); + this.editorView!.scrollDOM.scrollTop = pageState!.scrollTop; this.viewDispatch({ - type: "nugget-loaded", - meta: nuggetState.meta, + type: "page-loaded", + meta: pageState.meta, }); } @@ -476,27 +476,27 @@ export class Editor { let editor = this; useEffect(() => { - if (viewState.currentNugget) { - document.title = viewState.currentNugget.name; + if (viewState.currentPage) { + document.title = viewState.currentPage.name; } - }, [viewState.currentNugget]); + }, [viewState.currentPage]); return ( <> - {viewState.showNuggetNavigator && ( - { + {viewState.showPageNavigator && ( + { dispatch({ type: "stop-navigate" }); editor!.focus(); - if (nugget) { + if (page) { editor ?.save() .then(() => { - editor!.navigate(nugget); + editor!.navigate(page); }) .catch((e) => { - alert("Could not save nugget, not switching"); + alert("Could not save page, not switching"); }); } }} @@ -509,7 +509,7 @@ export class Editor { editor!.focus(); if (cmd) { safeRun(async () => { - let result = await cmd.run(buildContext(cmd, editor)); + let result = await cmd.run(null); console.log("Result of command", result); }); } @@ -518,7 +518,7 @@ export class Editor { /> )} { dispatch({ type: "start-navigate" }); }} diff --git a/webapp/src/function_worker.js b/webapp/src/function_worker.js index cec7131..db3e668 100644 --- a/webapp/src/function_worker.js +++ b/webapp/src/function_worker.js @@ -1,4 +1,4 @@ -// Nugget: this file is not built by Parcel, it's simply copied to the distribution +// Page: this file is not built by Parcel, it's simply copied to the distribution // The reason is that somehow Parcel cannot accept using importScripts otherwise function safeRun(fn) { fn().catch((e) => { diff --git a/webapp/src/index.html b/webapp/src/index.html index 76cee25..9c4304c 100644 --- a/webapp/src/index.html +++ b/webapp/src/index.html @@ -2,7 +2,7 @@ - Nugget + Page diff --git a/webapp/src/plugins/types.ts b/webapp/src/plugins/types.ts index 905e487..1131204 100644 --- a/webapp/src/plugins/types.ts +++ b/webapp/src/plugins/types.ts @@ -21,11 +21,6 @@ export interface CommandDef { // If to show in slash invoked menu and if so, with what label // should match slashCommandRegexp slashCommand?: string; - - // Required context to be passed in as function arguments - requiredContext?: { - text?: boolean; - }; } export interface FunctionDef { diff --git a/webapp/src/reducer.ts b/webapp/src/reducer.ts index 02d4444..fd7861e 100644 --- a/webapp/src/reducer.ts +++ b/webapp/src/reducer.ts @@ -6,19 +6,19 @@ export default function reducer( ): AppViewState { console.log("Got action", action); switch (action.type) { - case "nugget-loaded": + case "page-loaded": return { ...state, - currentNugget: action.meta, + currentPage: action.meta, isSaved: true, }; - case "nugget-saved": + case "page-saved": return { ...state, - currentNugget: action.meta, + currentPage: action.meta, isSaved: true, }; - case "nugget-updated": + case "page-updated": // Minor rerender optimization, this is triggered a lot if (!state.isSaved) { return state; @@ -30,17 +30,17 @@ export default function reducer( case "start-navigate": return { ...state, - showNuggetNavigator: true, + showPageNavigator: true, }; case "stop-navigate": return { ...state, - showNuggetNavigator: false, + showPageNavigator: false, }; - case "nuggets-listed": + case "pages-listed": return { ...state, - allNuggets: action.nuggets, + allPages: action.pages, }; case "show-palette": return { diff --git a/webapp/src/fs.ts b/webapp/src/space.ts similarity index 59% rename from webapp/src/fs.ts rename to webapp/src/space.ts index e8aa20e..35de6ee 100644 --- a/webapp/src/fs.ts +++ b/webapp/src/space.ts @@ -1,18 +1,18 @@ -import { NuggetMeta } from "./types"; +import { PageMeta } from "./types"; -export interface FileSystem { - listNuggets(): Promise; - readNugget(name: string): Promise<{ text: string; meta: NuggetMeta }>; - writeNugget(name: string, text: string): Promise; - getMeta(name: string): Promise; +export interface Space { + listPages(): Promise; + readPage(name: string): Promise<{ text: string; meta: PageMeta }>; + writePage(name: string, text: string): Promise; + getPageMeta(name: string): Promise; } -export class HttpFileSystem implements FileSystem { +export class HttpRemoteSpace implements Space { url: string; constructor(url: string) { this.url = url; } - async listNuggets(): Promise { + async listPages(): Promise { let req = await fetch(this.url, { method: "GET", }); @@ -22,7 +22,7 @@ export class HttpFileSystem implements FileSystem { lastModified: new Date(meta.lastModified), })); } - async readNugget(name: string): Promise<{ text: string; meta: NuggetMeta }> { + async readPage(name: string): Promise<{ text: string; meta: PageMeta }> { let req = await fetch(`${this.url}/${name}`, { method: "GET", }); @@ -34,12 +34,12 @@ export class HttpFileSystem implements FileSystem { }, }; } - async writeNugget(name: string, text: string): Promise { + async writePage(name: string, text: string): Promise { let req = await fetch(`${this.url}/${name}`, { method: "PUT", body: text, }); - // 201 (Created) means a new nugget was created + // 201 (Created) means a new page was created return { lastModified: new Date(+req.headers.get("Last-Modified")!), name: name, @@ -47,7 +47,7 @@ export class HttpFileSystem implements FileSystem { }; } - async getMeta(name: string): Promise { + async getPageMeta(name: string): Promise { let req = await fetch(`${this.url}/${name}`, { method: "OPTIONS", }); diff --git a/webapp/src/styles.css b/webapp/src/styles.css index 02c9a67..12a1e82 100644 --- a/webapp/src/styles.css +++ b/webapp/src/styles.css @@ -164,7 +164,7 @@ body { background-color: #ddd; } -.current-nugget { +.current-page { font-family: var(--editor-font); margin-left: 10px; margin-top: 10px; diff --git a/webapp/src/syscalls/editor.browser.ts b/webapp/src/syscalls/editor.browser.ts index c699355..e9073f6 100644 --- a/webapp/src/syscalls/editor.browser.ts +++ b/webapp/src/syscalls/editor.browser.ts @@ -69,4 +69,17 @@ export default (editor: Editor) => ({ } } }, + "editor.getSyntaxNodeAtPos": ( + ctx: SyscallContext, + pos: number + ): { name: string; text: string } | undefined => { + const editorState = editor.editorView!.state; + let node = syntaxTree(editorState).resolveInner(pos); + if (node) { + return { + name: node.name, + text: editorState.sliceDoc(node.from, node.to), + }; + } + }, }); diff --git a/webapp/src/types.ts b/webapp/src/types.ts index cadc5ab..4d087db 100644 --- a/webapp/src/types.ts +++ b/webapp/src/types.ts @@ -1,46 +1,40 @@ import { CommandDef } from "./plugins/types"; -export type NuggetMeta = { +export type PageMeta = { name: string; lastModified: Date; created?: boolean; }; -export type CommandContext = { - text?: string; -}; - export type AppCommand = { command: CommandDef; - run: (ctx: CommandContext) => Promise; + run: (arg: any) => Promise; }; export type AppViewState = { - currentNugget?: NuggetMeta; + currentPage?: PageMeta; isSaved: boolean; - showNuggetNavigator: boolean; + showPageNavigator: boolean; showCommandPalette: boolean; - allNuggets: NuggetMeta[]; + allPages: PageMeta[]; commands: Map; }; export const initialViewState: AppViewState = { isSaved: false, - showNuggetNavigator: false, + showPageNavigator: false, showCommandPalette: false, - allNuggets: [], + allPages: [], commands: new Map(), }; export type Action = - | { type: "nugget-loaded"; meta: NuggetMeta } - | { type: "nugget-saved"; meta: NuggetMeta } - | { type: "nugget-updated" } - | { type: "nuggets-listed"; nuggets: NuggetMeta[] } + | { type: "page-loaded"; meta: PageMeta } + | { type: "page-saved"; meta: PageMeta } + | { type: "page-updated" } + | { type: "pages-listed"; pages: PageMeta[] } | { type: "start-navigate" } | { type: "stop-navigate" } | { type: "update-commands"; commands: Map } | { type: "show-palette" } | { type: "hide-palette" }; - -export type AppEvent = "ready" | "change" | "switch" | "click";