Newer
Older
TriliumScripts / highlight_moodlog.js
0xRoM on 21 Mar 6 KB initial commit
const TPL = `<div style="padding: 10px; border-top: 1px solid var(--main-border-color); contain: none;">
    <strong>Moodlog Highlighting Applied</strong>
</div>`;

class MoodlogHighlighterWidget extends api.NoteContextAwareWidget {
    static get parentWidget() { 
        //console.log("MDLG: Getting parent widget: center-pane");
        return 'center-pane'; 
    }

    get position() { 
        //console.log("MDLG: Setting position: 100");
        return 100; 
    }

    isEnabled() {
        const enabled = super.isEnabled() 
            && this.note.type === 'text' 
            && this.note.hasLabel('moodlog');
        //console.log(`MDLG: isEnabled: ${enabled}`);
        return enabled;
    }

    doRender() {
        //console.log("MDLG: Rendering widget...");
        this.$widget = $(TPL);
        //console.log("MDLG: Widget rendered:", this.$widget);
        return this.$widget;
    }

    async refreshWithNote(note) {
        //console.log("MDLG: Refreshing with note:", note);
        const { content } = await note.getNoteComplement();
        //console.log("MDLG: Note content fetched:", content);

        // Check if content is fetched properly
        if (!content) {
            //console.log("MDLG: No content fetched. Exiting refresh.");
            return;
        }

        const highlightedContent = this.applyHighlighting(content);
        //console.log("MDLG: Highlighted content:", highlightedContent);

        if (highlightedContent !== content) {
            //console.log("MDLG: Updating note content with highlighted version");

            // Use the setNoteContent function to update the note content
            try {
                await setNoteContent(note.noteId, highlightedContent);
                //console.log("MDLG: Content updated with highlighted version");
            } catch (error) {
                //console.error("MDLG: Error updating content:", error);
            }
        } else {
            //console.log("MDLG: No changes to content, skipping update.");
        }
    }


 applyHighlighting(content) {
    //console.log("MDLG: Applying highlighting to content...");

    // Replace <br> with \n, then remove all other HTML tags
    const plainTextContent = content.replace(/<br\s*\/?>/gi, '\n').replace(/<[^>]*>/g, ' ');
    //console.log("MDLG: Stripped content:", plainTextContent);

    // Combined regex for date & time
    const dateTimePattern = /([1-2]\d{3}[-/.](0?[1-9]|1[0-2])[-/.](0[1-9]|[12]\d|3[01]))\s+(\d{1,2}:\d{2})/g;
    const projectPattern = /\[\S+?\]/g;
    const contextPattern = /(\s|^)(@\S+)/g;
    const hashtagPattern = /(\s|^)(#\S+)/g;
    const positivePattern = /(\s|^)(\+\S+)/g;
    const negativePattern = /(\s|^)(-\S+)/g;

    // Escape HTML characters to prevent issues with replacements
    function escapeHtml(str) {
        return str.replace(/[&<>"']/g, function (char) {
            return {
                '&': '&amp;',
                '<': '&lt;',
                '>': '&gt;',
                '"': '&quot;',
                "'": '&#039;'
            }[char];
        });
    }

      // Helper function to map the number to a colour based on the gradient
    function getProjectColour(number) {
        const minColor = { r: 107, g: 109, b: 229 };  // #6b6de5
        const maxColor = { r: 70, g: 226, b: 96 };   // #46e260

        const ratio = number / 9; // since we are working with 0-9

        // Interpolate the RGB values between minColor and maxColor
        const r = Math.round(minColor.r + ratio * (maxColor.r - minColor.r));
        const g = Math.round(minColor.g + ratio * (maxColor.g - minColor.g));
        const b = Math.round(minColor.b + ratio * (maxColor.b - minColor.b));

        return `rgb(${r}, ${g}, ${b})`;
    }
     
    // Process each line of the plain text content
    let highlightedLines = plainTextContent.split("\n").map(line => {
        //console.log("MDLG: Processing line:", line);

        // Apply combined date & time highlight
        line = line.replace(dateTimePattern, `<span style="color: rgb(188, 55, 237);">$1</span> <span style="color: rgb(188, 55, 237);">$4</span>`);

        // Apply other highlights
        line = line.replace(projectPattern, (match) => {
            // Extract the number inside square brackets
            const number = parseInt(match.match(/\d+/)[0], 10);
            const colour = getProjectColour(number);
            return `<span style="color: ${colour}; font-weight: bold;">${escapeHtml(match)}</span>`;
        });
        
        // Apply other highlights
        //line = line.replace(projectPattern, `<span style="color: rgb(224, 218, 36); font-weight: bold;">$&</span>`);
        line = line.replace(contextPattern, (_, space, tag) => `${space}<span style="color: rgb(255 165 10);">${escapeHtml(tag)}</span>`);
        line = line.replace(hashtagPattern, (_, space, tag) => `${space}<span style="color: rgb(41, 229, 242);">${escapeHtml(tag)}</span>`);
        line = line.replace(positivePattern, (_, space, tag) => `${space}<span style="color: rgb(44, 227, 34);">${escapeHtml(tag)}</span>`);
        line = line.replace(negativePattern, (_, space, tag) => `${space}<span style="color: rgb(230, 59, 44);">${escapeHtml(tag)}</span>`);

        return line.trim();
    });

    // Join lines with proper <br> handling
    let finalContent = highlightedLines.join("<br>");

    //console.log("MDLG: Highlighted content:", finalContent);
    return finalContent;
}




    async entitiesReloadedEvent({ loadResults }) {
        //console.log("MDLG: Entities reloaded event triggered");
        if (loadResults.isNoteContentReloaded(this.noteId)) {
            //console.log("MDLG: Note content reloaded, refreshing widget...");
            //this.refresh();
        } else {
            //console.log("MDLG: No content reload detected.");
        }
    }
    

}

console.log("MDLG: Starting Moodlog Highlighter Widget");
module.exports = MoodlogHighlighterWidget;

function setNoteContent(noteId, content) {
    /*const noteElement = document.querySelector(`note-detail-readonly-text-content`);

    if (noteElement) {
        noteElement.innerHTML = content; // Update the displayed content
        console.log(`MDLG: Updated note ${noteId} in the DOM.`);
    } else {
        console.warn(`MDLG: Note element with data-note-id='${noteId}' not found.`);
    }*/
    return api.runOnBackend((id, data) => api.getNote(id).setContent(data), [noteId, content]);
}