A Tampermonkey script to open an elm compiler error link in your editor straight from the browser

Hey folks,
Cursor, Claude and I build this script to help my dev flow. Basically I can not jump from the browser straight to the offending line of code in my editor.

I’ve only tested it with lamdera live.

Feedback and improvements welcomed.

gist: elmErrorLink.js · GitHub

code:

// ==UserScript==
// @name         VS Code WSL File Links
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Create VS Code links for WSL files and line numbers
// @match        http://localhost:/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // Configuration flags
    const useWSL = true;
    const editorPrefix = 'cursor://';

    const wslPrefix = useWSL ? 'vscode-remote/wsl+Ubuntu' : '';
    const protocol = editorPrefix ? 'vscode://' : 'cursor://';

    function createLinks() {
        // Updated regex to capture the entire path
        const regex = /((?:\/[^\/]+)*\/src(?:\/[^\/]+)*\/[^\/]+\.elm)$/;
        // Find all span elements
        const spans = document.querySelectorAll('span');

        let linksCreated = 0;

        spans.forEach((span, index) => {
            const text = span.textContent.trim();
            const match = text.match(regex);

            if (match) {
                // Extract the full path
                const fullPath = match[1];

                // Create a new anchor element
                const link = document.createElement('a');

                // Updated URI to use the protocol and wslPrefix
                const uri = `${protocol}${wslPrefix}${encodeURIComponent(fullPath)}:1`;
                link.href = uri;
                link.textContent = text;
                link.style.cursor = 'pointer';

                // Create a line break element
                const lineBreak = document.createElement('br');
                const lineBreak2 = document.createElement('br');

                // Replace the span with the new link and link display
                const container = document.createElement('span');
                container.appendChild(link);
                container.appendChild(lineBreak);
                container.appendChild(lineBreak2);

                // Process the remaining content of the parent span
                const remainingContent = document.createElement('span');

                const parentSpan = span.parentElement;

                const lines = parentSpan.textContent.split('\n');
                lines.slice(1).forEach(line => {
                    const lineNumberMatch = line.match(/^(\d+)\|/);
                    if (lineNumberMatch) {
                        const lineNumber = lineNumberMatch[1];
                        const lineNumberLink = document.createElement('a');
                        // Updated to use the protocol and wslPrefix
                        lineNumberLink.href = `${protocol}${wslPrefix}${encodeURIComponent(fullPath)}:${lineNumber}`;
                        lineNumberLink.textContent = `${lineNumber}|`;
                        lineNumberLink.style.cursor = 'pointer';

                        link.href = lineNumberLink.href;
                    }
                });

                span.innerHTML = '';
                span.appendChild(container);
                span.appendChild(remainingContent);
                linksCreated++;
            }
        });

        if (linksCreated > 0) {
            clearInterval(intervalId);
        }
    }

    // Run the function every 2 seconds
    const intervalId = setInterval(createLinks, 200);

    // Stop trying after 30 seconds
    setTimeout(() => {
        clearInterval(intervalId);
    }, 30000);
})();
5 Likes

PS if you’re not using WSL, you can set that flag to false.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.