···3939// Validation
4040import validateHTML from "./plugins/validateHTML.ts";
41414242+// Open in Editor
4343+import openInEditor from "./plugins/openInEditor.ts";
4444+4245// Disabled Plugins:
4346// import nav from "lume/plugins/nav.ts";
4447// import og_images from "lume/plugins/og_images.ts";
···162165// Minify HTML Output
163166site.use(minify_html({
164167 options: {
168168+ do_not_minify_doctype: true,
169169+ keep_closing_tags: false,
165170 keep_html_and_head_opening_tags: true,
166171 keep_spaces_between_attributes: true,
172172+ ensure_spec_compliant_unquoted_attribute_values: true,
173173+ keep_comments: false,
167174 },
168175}));
169176···234241 ],
235242 }),
236243);
244244+245245+// Open in Editor in Dev mode
246246+site.data("production", Deno.env.get("PRODUCTION"));
247247+if (Deno.env.get("PRODUCTION") == "false") {
248248+ site.use(openInEditor());
249249+ site.add("static/scripts/open-in-editor.js");
250250+}
237251238252// Get current commit as a version number
239253// Taken from https://github.com/pixeldesu/pixelde.su/blob/main/_config.ts
+75
plugins/openInEditor.ts
···11+// deno-lint-ignore-file no-explicit-any
22+// ^- NOTE: No idea for the typing of markdown-it plugin context, so we disable this check
33+// Taken from https://github.com/pixeldesu/pixelde.su/blob/main/plugins/markdown-it/vscode.ts and edited for my use
44+55+import "lume/types.ts";
66+77+// Cache object for frontmatter line counts so we only reload files once
88+const FRONTMATTER_LINE_CACHE: Record<string, number> = {};
99+1010+function markdownItOpenInEditor(md: any) {
1111+ // Override the default paragraph renderer
1212+ const defaultRender = md.renderer.rules.paragraph_open ||
1313+ function (
1414+ tokens: Record<number, any>,
1515+ idx: number,
1616+ options: any,
1717+ _env: any,
1818+ self: any,
1919+ ) {
2020+ return self.renderToken(tokens, idx, options);
2121+ };
2222+2323+ md.renderer.rules.paragraph_open = function (
2424+ tokens: Record<number, any>,
2525+ idx: number,
2626+ options: any,
2727+ env: any,
2828+ self: any,
2929+ ) {
3030+ const token = tokens[idx];
3131+ const filePath = env.data.page.src.entry.src || "";
3232+3333+ // FIXME: This is extremely ugly, having to reload the file to get the full context to
3434+ // calculate the line number offset for the frontmatter. For some reason this is
3535+ // pretty fast however, so I'll let it slide for now.
3636+ if (!FRONTMATTER_LINE_CACHE[filePath]) {
3737+ FRONTMATTER_LINE_CACHE[filePath] = countFrontMatterLines(
3838+ Deno.readTextFileSync(filePath),
3939+ );
4040+ }
4141+ const lineNumber = FRONTMATTER_LINE_CACHE[filePath] +
4242+ (token.map ? token.map[0] : 1);
4343+4444+ // Create a wrapper element with context to open the file in VS Code
4545+ const clickableElementStart = `<div data-editor-file="${filePath}:${lineNumber}">`;
4646+4747+ return clickableElementStart +
4848+ defaultRender(tokens, idx, options, env, self);
4949+ };
5050+5151+ md.renderer.rules.paragraph_close = function (
5252+ tokens: Record<number, any>,
5353+ idx: number,
5454+ options: any,
5555+ _env: any,
5656+ self: any,
5757+ ) {
5858+ return self.renderToken(tokens, idx, options) + "</div>";
5959+ };
6060+}
6161+6262+function countFrontMatterLines(content: string) {
6363+ const frontMatterPattern = /^---\s*\n([\s\S]*?)\n---\s*\n/;
6464+ const match = content.match(frontMatterPattern);
6565+ if (match) {
6666+ return match[0].split("\n").length;
6767+ }
6868+ return 0;
6969+}
7070+7171+export default function () {
7272+ return function (site: Lume.Site) {
7373+ site.hooks.addMarkdownItPlugin(markdownItOpenInEditor);
7474+ };
7575+}
+3
src/_components/head.vto
···2323{{# Page Metadata #}}
2424<link rel="canonical" href="{{ url |> url(true) }}" />
2525<title>{{ title }}</title>
2626+{{ if production == "false" }}
2727+ <script defer="defer" src="/static/scripts/open-in-editor.js"></script>
2828+{{ /if }}