From 9ee52a22a7f0336fcc3871e7e992691b1a4424de Mon Sep 17 00:00:00 2001 From: dish Date: Tue, 25 Feb 2025 16:36:09 -0500 Subject: [PATCH] add openInEditor plugin Base code is from https://github.com/pixeldesu/pixelde.su but adopted for my use --- .env.dev | 1 + .env.prod | 1 + _config.ts | 14 ++++++ plugins/openInEditor.ts | 75 ++++++++++++++++++++++++++++ src/_components/head.vto | 3 ++ src/static/scripts/open-in-editor.js | 11 ++++ src/static/styles.css | 14 ++++++ 7 files changed, 119 insertions(+) create mode 100644 plugins/openInEditor.ts create mode 100644 src/static/scripts/open-in-editor.js diff --git a/.env.dev b/.env.dev index 1c13b80..8e43d43 100644 --- a/.env.dev +++ b/.env.dev @@ -1 +1,2 @@ export LUME_DRAFTS="true" +export PRODUCTION="false" diff --git a/.env.prod b/.env.prod index 42df04d..5bc976d 100644 --- a/.env.prod +++ b/.env.prod @@ -1 +1,2 @@ export LUME_DRAFTS="false" +export PRODUCTION="true" diff --git a/_config.ts b/_config.ts index a01df58..693ee24 100644 --- a/_config.ts +++ b/_config.ts @@ -39,6 +39,9 @@ import lightningcss from "lume/plugins/lightningcss.ts"; // Validation import validateHTML from "./plugins/validateHTML.ts"; +// Open in Editor +import openInEditor from "./plugins/openInEditor.ts"; + // Disabled Plugins: // import nav from "lume/plugins/nav.ts"; // import og_images from "lume/plugins/og_images.ts"; @@ -162,8 +165,12 @@ site.use(validateHTML()); // Minify HTML Output site.use(minify_html({ options: { + do_not_minify_doctype: true, + keep_closing_tags: false, keep_html_and_head_opening_tags: true, keep_spaces_between_attributes: true, + ensure_spec_compliant_unquoted_attribute_values: true, + keep_comments: false, }, })); @@ -235,6 +242,13 @@ site.use( }), ); +// Open in Editor in Dev mode +site.data("production", Deno.env.get("PRODUCTION")); +if (Deno.env.get("PRODUCTION") == "false") { + site.use(openInEditor()); + site.add("static/scripts/open-in-editor.js"); +} + // Get current commit as a version number // Taken from https://github.com/pixeldesu/pixelde.su/blob/main/_config.ts const commitCmd = new Deno.Command("git", { args: ["rev-parse", "HEAD"] }); diff --git a/plugins/openInEditor.ts b/plugins/openInEditor.ts new file mode 100644 index 0000000..bcf4aa3 --- /dev/null +++ b/plugins/openInEditor.ts @@ -0,0 +1,75 @@ +// deno-lint-ignore-file no-explicit-any +// ^- NOTE: No idea for the typing of markdown-it plugin context, so we disable this check +// Taken from https://github.com/pixeldesu/pixelde.su/blob/main/plugins/markdown-it/vscode.ts and edited for my use + +import "lume/types.ts"; + +// Cache object for frontmatter line counts so we only reload files once +const FRONTMATTER_LINE_CACHE: Record = {}; + +function markdownItOpenInEditor(md: any) { + // Override the default paragraph renderer + const defaultRender = md.renderer.rules.paragraph_open || + function ( + tokens: Record, + idx: number, + options: any, + _env: any, + self: any, + ) { + return self.renderToken(tokens, idx, options); + }; + + md.renderer.rules.paragraph_open = function ( + tokens: Record, + idx: number, + options: any, + env: any, + self: any, + ) { + const token = tokens[idx]; + const filePath = env.data.page.src.entry.src || ""; + + // FIXME: This is extremely ugly, having to reload the file to get the full context to + // calculate the line number offset for the frontmatter. For some reason this is + // pretty fast however, so I'll let it slide for now. + if (!FRONTMATTER_LINE_CACHE[filePath]) { + FRONTMATTER_LINE_CACHE[filePath] = countFrontMatterLines( + Deno.readTextFileSync(filePath), + ); + } + const lineNumber = FRONTMATTER_LINE_CACHE[filePath] + + (token.map ? token.map[0] : 1); + + // Create a wrapper element with context to open the file in VS Code + const clickableElementStart = `
`; + + return clickableElementStart + + defaultRender(tokens, idx, options, env, self); + }; + + md.renderer.rules.paragraph_close = function ( + tokens: Record, + idx: number, + options: any, + _env: any, + self: any, + ) { + return self.renderToken(tokens, idx, options) + "
"; + }; +} + +function countFrontMatterLines(content: string) { + const frontMatterPattern = /^---\s*\n([\s\S]*?)\n---\s*\n/; + const match = content.match(frontMatterPattern); + if (match) { + return match[0].split("\n").length; + } + return 0; +} + +export default function () { + return function (site: Lume.Site) { + site.hooks.addMarkdownItPlugin(markdownItOpenInEditor); + }; +} diff --git a/src/_components/head.vto b/src/_components/head.vto index e12aace..a94c0c8 100644 --- a/src/_components/head.vto +++ b/src/_components/head.vto @@ -23,3 +23,6 @@ {{# Page Metadata #}} {{ title }} +{{ if production == "false" }} + +{{ /if }} diff --git a/src/static/scripts/open-in-editor.js b/src/static/scripts/open-in-editor.js new file mode 100644 index 0000000..8611d0c --- /dev/null +++ b/src/static/scripts/open-in-editor.js @@ -0,0 +1,11 @@ +// Taken from https://github.com/pixeldesu/pixelde.su/blob/main/src/assets/js/modules/vscode.js +// Adopted by dish +const editorTargets = document.querySelectorAll("[data-editor-file]"); +editorTargets.forEach((target) => { + target.addEventListener("click", (event) => { + globalThis.open( + `zed://file/${event.currentTarget.dataset.editorFile}`, + "_self", + ); + }); +}); diff --git a/src/static/styles.css b/src/static/styles.css index b7fffbb..115c2ae 100644 --- a/src/static/styles.css +++ b/src/static/styles.css @@ -107,6 +107,16 @@ --color-crust: var(--ctp-crust); } +@layer components { + [data-editor-file] { + @apply transition-all rounded-md; + } + [data-editor-file]:hover { + @apply transition-all outline-blue outline-2 outline-offset-4 + dark:bg-blue/10 bg-blue/10 pl-1; + } +} + @utility h-entry { a { @apply text-blue underline; @@ -160,6 +170,10 @@ .callout-content { @apply overflow-x-auto pl-2; + + [data-editor-file]:hover { + @apply relative top-2 mr-2; + } } &[data-callout="todo"], &[data-callout="info"], -- 2.51.2