I couldn't find a way to generate JS dynamically inside href. So, I just hardcoded all the code to href and replaced site URL using go templates variables. Bookmarklet can fetch selected text from HTML page and convert it to mycomarkup, thanks to Umar. Danila Gorelko (1): Added bookmarklet to settings page. web/bookmarklet.js | 91 +++++++++++++++++++++++++++++++++++++++++++++ web/settings.gohtml | 14 +++++++ web/style.css | 12 ++++++ 3 files changed, 117 insertions(+) create mode 100644 web/bookmarklet.js -- 2.38.5
Oh, that's a long-awaited addition! Some issues: You include the original bookmarklet script, but the file `bookmarklet.js` is not really used. I don't see the point of it then. Then, the actual bookmarklet is a condensed one-liner. Neither readable nor editable. The condensed version should be generated on Betula startup somehow. The `bookmarklet.js` is read by embed.FS on startup, so I think something could be done in this direction. You could generate the bookmark URL client-side with some JS party tricks, see the link below. I don't think it's a good idea. => https://stackoverflow.com/questions/7395686/how-can-i-serialize-a-function-in-javascript Also, the bookmarklet uses the URL known at the moment the page was loaded. But the user can change it one the same page! Having one URL written and a different one used doesn't really make sense. I think it makes sense to put the bookmarklet on a different page, `/bookmarklet`. There won't be such conflicts this way. It can be linked on the Settings page. It's not like the bookmarklet is a setting really btw...
betula/patches/.build.yml: FAILED in 49s [Bookmarklet patchset desc.][0] from [~danilax86][1] [0]: https://lists.sr.ht/~bouncepaw/betula/patches/42709 [1]: mailto:danila@danilax86.space ✗ #1024770 FAILED betula/patches/.build.yml https://builds.sr.ht/~bouncepaw/job/1024770
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~bouncepaw/betula/patches/42709/mbox | git am -3Learn more about email & git
From: Danila Gorelko <danila@danilax86.space> Thanks to Umar, https://handlerug.me/betula-save-bookmarklet Fixes: https://todo.sr.ht/~bouncepaw/betula/59 --- web/bookmarklet.js | 91 +++++++++++++++++++++++++++++++++++++++++++++ web/settings.gohtml | 14 +++++++ web/style.css | 12 ++++++ 3 files changed, 117 insertions(+) create mode 100644 web/bookmarklet.js diff --git a/web/bookmarklet.js b/web/bookmarklet.js new file mode 100644 index 0000000..4d4fad2 --- /dev/null +++ b/web/bookmarklet.js @@ -0,0 +1,91 @@ +// Save link bookmarklet for Betula +// 2023 Umar Getagazov <umar@handlerug.me> +// Public domain, but attribution appreciated. +// https://handlerug.me/betula-save-bookmarklet + +(($) => { + function getSelectionInMycomarkup() { + function convert(node, parentNodeName = '') { + if (node instanceof Text) { + if (node.textContent.trim() === '') { + return ''; + } + + return node.textContent + .replace(/\\/g, '\\\\') + .replace(/\*\*/g, '\\**') + .replace(/\/\//g, '\\//') + .replace(/\+\+/g, '\\++'); + } + + let nodeName = node.nodeName.toLowerCase(); + + let result = ''; + for (const child of node.childNodes) { + result += convert(child, nodeName); + } + + if (nodeName === 'p') { + return `\n\n${result.trim()}\n\n`; + } else if (nodeName === 'br') { + return '\n'; + } else if (nodeName === 'a') { + return `[[${decodeURI(node.href)} | ${result}]]`; + } else if (nodeName === 'b' || nodeName === 'strong') { + return `**${result}**`; + } else if (nodeName === 'i' || nodeName === 'em') { + return `//${result}//`; + } else if (nodeName === 'h1') { + return `\n\n${result}\n\n`; + } else if (nodeName === 'h2') { + return `= ${result}\n\n`; + } else if (nodeName === 'h3') { + return `== ${result}\n\n`; + } else if (nodeName === 'h4') { + return `=== ${result}\n\n`; + } else if (nodeName === 'h5') { + return `==== ${result}\n\n`; + } else if (nodeName === 'li') { + if (node.children.length === 1) { + let link = node.children[0]; + if (link.nodeName.toLowerCase() === 'a') { + if (link.href === link.innerText || decodeURI(link.href) === link.innerText) { + return `=> ${decodeURI(link.href)}\n`; + } else { + return `=> ${decodeURI(link.href)} | ${link.innerText}\n`; + } + } + } + return parentNodeName === 'ol' + ? `*. ${result}\n` + : `* ${result}\n`; + } else { + return result; + } + } + + let selection = window.getSelection(); + if (selection.rangeCount === 0) { + return ''; + } + let range = selection.getRangeAt(0); + let contents = range.cloneContents(); + return convert(contents).replace(/\n\n+/g, '\n\n'); + } + + let u = 'https://links.handlerug.me/save-link?' + new URLSearchParams({ + url: ($('link[rel=canonical]') || location).href, + title: $('meta[property="og:title"]')?.content || document.title, + description: ( + getSelectionInMycomarkup() || + $('meta[property="og:description"]')?.content || + $('meta[name=description]')?.content + )?.trim().replace(/^/gm, '> ') || '' + }); + + try { + window.open(u, '_blank', 'location=yes,width=600,height=800,scrollbars=yes,status=yes,noopener,noreferrer'); + } catch { + location.href = u; + } +})(document.querySelector.bind(document)); diff --git a/web/settings.gohtml b/web/settings.gohtml index c692111..ac66e9d 100644 --- a/web/settings.gohtml +++ b/web/settings.gohtml @@ -38,6 +38,20 @@ </p> </div> + <h3>Bookmarklet</h3> + + <p class="input-caption"> + This special link allows you to add a link to your betula directly by using a bookmark in your web browser. + </p> + <div class="bookmarklet"> + <a href="javascript:(function(){(e=>{let n="{{.SiteURL}}/save-link?"+new URLSearchParams({url:(e("link[rel=canonical]")||location).href,title:e('meta[property="og:title"]')?.content||document.title,description:(function(){let e=window.getSelection();return 0===e.rangeCount?"":function e(n,t=""){if(n instanceof Text)return""===n.textContent.trim()?"":n.textContent.replace(/\\/g,"\\\\").replace(/\*\*/g,"\\**").replace(/\/\//g,"\\//").replace(/\+\+/g,"\\++");let r=n.nodeName.toLowerCase(),o="";for(const t of n.childNodes)o+=e(t,r);if("p"===r)return`\n\n${o.trim()}\n\n`;if("br"===r)return"\n";if("a"===r)return`[[${decodeURI(n.href)} | ${o}]]`;if("b"===r||"strong"===r)return`**${o}**`;if("i"===r||"em"===r)return`//${o}//`;if("h1"===r)return`\n\n${o}\n\n`;if("h2"===r)return`= ${o}\n\n`;if("h3"===r)return`== ${o}\n\n`;if("h4"===r)return`=== ${o}\n\n`;if("h5"===r)return`==== ${o}\n\n`;if("li"===r){if(1===n.children.length){let e=n.children[0];if("a"===e.nodeName.toLowerCase())return e.href===e.innerText||decodeURI(e.href)===e.innerText?`=> ${decodeURI(e.href)}\n`:`=> ${decodeURI(e.href)} | ${e.innerText}\n`}return"ol"===t?`*. ${o}\n`:`* ${o}\n`}return o}(e.getRangeAt(0).cloneContents()).replace(/\n\n+/g,"\n\n")}()||e('meta[property="og:description"]')?.content||e("meta[name=description]")?.content)?.trim().replace(/^/gm,"> ")||""});try{window.open(n,"_blank","location=yes,width=600,height=800,scrollbars=yes,status=yes,noopener,noreferrer")}catch{location.href=n}})(document.querySelector.bind(document));}());"> + Add to Betula + </a> + </div> + <p class="input-caption"> + Drag and drop this link to your bookmarks. + </p> + <h3>Advanced</h3> <div> diff --git a/web/style.css b/web/style.css index 47bd7ae..eafeb9b 100644 --- a/web/style.css +++ b/web/style.css @@ -391,6 +391,18 @@ a.btn_destructive:visited, color: white; } +.bookmarklet { + border: 1px dashed #999; + border-radius: 5px; + padding: 15px; + text-align: center; +} + +.bookmarklet a { + text-decoration: none; + font-weight: bold; +} + @media (prefers-color-scheme: dark) { .btn { border: #444 solid 1px; -- 2.38.5
Oh, that's a long-awaited addition! Some issues: You include the original bookmarklet script, but the file `bookmarklet.js` is not really used. I don't see the point of it then. Then, the actual bookmarklet is a condensed one-liner. Neither readable nor editable. The condensed version should be generated on Betula startup somehow. The `bookmarklet.js` is read by embed.FS on startup, so I think something could be done in this direction. You could generate the bookmark URL client-side with some JS party tricks, see the link below. I don't think it's a good idea. => https://stackoverflow.com/questions/7395686/how-can-i-serialize-a-function-in-javascript Also, the bookmarklet uses the URL known at the moment the page was loaded. But the user can change it one the same page! Having one URL written and a different one used doesn't really make sense. I think it makes sense to put the bookmarklet on a different page, `/bookmarklet`. There won't be such conflicts this way. It can be linked on the Settings page. It's not like the bookmarklet is a setting really btw...
builds.sr.ht <builds@sr.ht>betula/patches/.build.yml: FAILED in 49s [Bookmarklet patchset desc.][0] from [~danilax86][1] [0]: https://lists.sr.ht/~bouncepaw/betula/patches/42709 [1]: mailto:danila@danilax86.space ✗ #1024770 FAILED betula/patches/.build.yml https://builds.sr.ht/~bouncepaw/job/1024770