Skip to content

Instantly share code, notes, and snippets.

@laundmo
Last active October 19, 2024 01:28
Show Gist options
  • Save laundmo/de1f386fac9f9e797fd77022d63967c9 to your computer and use it in GitHub Desktop.
Save laundmo/de1f386fac9f9e797fd77022d63967c9 to your computer and use it in GitHub Desktop.
Trilium widget to open italicized file paths. Only works in Desktop app. Add as "JS Frontend" note and make sure it has the #widget property.
/* License: MIT https://opensource.org/licenses/MIT
* Made by: GEOsens GmbH 2023
*
* Usage: Italicize the file path. The italicized file or folder can be opened with a double click.
*
* Note: there is not indication that a path is clickable, thanks ckeditor.
*/
async function onClickOpenPath(event) {
// check if event was on Italicised
if (event.target.tagName == "I") {
var path = event.target.innerText;
// check if content is path (rudimentary)
if (/[a-zA-Z]:.*|\\\\\w.*?\\\w/.test(path)) {
// use backend to open file from path
await document.PathLinkerApi.runOnBackend(async (path) => {
const shell = require('electron').shell;
await shell.openPath(path);
return;
}, [path]);
}
}
}
const TEMPLATE = `
<div style="padding: 10px; border-top: 1px solid var(--main-border-color); contain: none;">
<script>
${onClickOpenPath.toString()}
document.addEventListener('dblclick', onClickOpenPath);
</script>
</div>`;
class PathLinkerWidget extends api.NoteContextAwareWidget {
constructor(...args) {
super(...args);
this.balloonEditorCreate = null;
}
get position() {
// higher value means position towards the bottom/right
return 100;
}
get parentWidget() { return 'center-pane'; }
doRender() {
this.$widget = $(TEMPLATE);
this.$widget.hide();
// store API in document to access it from callback
document.PathLinkerApi = api;
return this.$widget;
}
}
let widget = new PathLinkerWidget();
console.log("Loaded PathLinkerWidget");
module.exports = widget;
@meichthys
Copy link

meichthys commented Apr 6, 2023

@laundmo I feel like i may have asked this somewhere in the past, but i can't seem to get this script to work. Do you know if it's still relevant in recent Trilium release versions?

I did set the note to JS Backend and added the #widget attribute

I receive the following error when trying to run the script:

Class extends value undefined is not a constructor or null

@laundmo
Copy link
Author

laundmo commented Apr 6, 2023

I'm not sure, at work we haven't updated yet, so there was no need to try.

have you checked whether NoteContextAwareWidget was removed in a changelog?

@laundmo
Copy link
Author

laundmo commented Apr 6, 2023

nvm, just checked. it still exists. hmm, wierd.

@meichthys
Copy link

meichthys commented Apr 6, 2023

@laundmo Lol, it just needs to be setup as a "JS Frontend" note instead of JS Backend
Perhaps you could update the description for future reference?

@laundmo
Copy link
Author

laundmo commented Apr 6, 2023

oof really? allright I'll fix it

@SiriusXT
Copy link

SiriusXT commented May 6, 2023

Could not open path: %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

@connectluole
Copy link

connectluole commented Jan 20, 2024

Add new update for the usage of this script.
16 line: await document.PathLinkerApi.runOnBackend(async (path) => {
need update to below
16 line: await document.PathLinkerApi.runAsyncOnBackendWithManualTransactionHandling(async (path) => {

This update is due to trilium app (win 0.62.5) notice me like below once i double click on the file link line.
ERROR: You're passing an async function to api.runOnBackend() which will likely not work as you intended. Either make the function synchronous (by removing 'async' keyword), or use api.runAsyncOnBackendWithManualTransactionHandling()

@connectluole
Copy link

connectluole commented Jun 24, 2024

add the enhanced code below, which no need the special format for the file path

async function OpenLocalPath(event) {
// Check if the event was a Ctrl+double click.
if (event.ctrlKey) {
var path = event.target.innerText.trim();
console.log(>> ctrl + double_click get line content:\n${path})
//------ Check if the text content contain a file path. ------
if (/[A-Z]:\./.test(path)) {
var path = path.match(/[A-Z]:\.
/)[0]
// --- replace the special string
path = path.replace("USER",require('os').userInfo().username)

        console.log(`>> Open local path: ${path}`)
        // Use the PathLinkerApi to open the file at the path.
        await document.PathLinkerApi.runAsyncOnBackendWithManualTransactionHandling(async (path) => { 
            const shell = require('electron').shell;
            await shell.openPath(path);
            return;
        }, [path]);
    }
}

}

const TEMPLATE = <div style="padding: 10px; border-top: 1px solid var(--main-border-color); contain: none;"> <script> ${OpenLocalPath.toString()} document.addEventListener('dblclick', OpenLocalPath); </script> </div>;

class PathLinkerWidget extends api.NoteContextAwareWidget {
constructor(...args) {
super(...args);
this.balloonEditorCreate = null;
}

get position() { 
    // higher value means position towards the bottom/right
    return 100; 
} 

get parentWidget() { return 'center-pane'; }

doRender() {
    this.$widget = $(TEMPLATE);
    this.$widget.hide();
    
    // store API in document to access it from callback
    document.PathLinkerApi = api;
    return this.$widget;
}

}

let widget = new PathLinkerWidget();
console.log(">> Loaded PathLinkerWidget");
module.exports = widget;

@brianvanderburg2
Copy link

I'm unable to get either of these working. I get an error about "require" not being defined, using Trilium Next 0.90.7

frontend_script_api.js:203 Uncaught (in promise) Error: server error: require is not defined
    at x.__runOnBackendInner (frontend_script_api.js:203:19)
    at async x.runAsyncOnBackendWithManualTransactionHandling (frontend_script_api.js:243:36)
    at async HTMLDocument.onClickOpenPath (<anonymous>:9:13)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment