After a long series of experiments refining a script that could work in all conditions and with both version desktop/bmobile browsers I get two collage scripts with the same goal but based on 2 different scripts, but still neither of them works perfectly.
On both desktop and mobile as reference application in the and I chose Brave because being very intrusive with removing trackers and ads I think what works with it should also work well with Chrome.
The first script, which I will call “A”, is based on this one by kepeno.
It never works on desktop. It always works perfectly on mobile
Script A:
javascript: Promise.all([import('https://unpkg.com/[email protected]?module'), import('https://unpkg.com/@tehshrike/[email protected]'), ]).then(async ([{
default: Turndown
}, {
default: Readability
}]) => {
/* Optional vault name */
const vault = "Note";
/* Optional folder name such as "Clippings/" */
const folder = "";
/* Optional tags */
let tags = "clippings";
/* Parse the site's meta keywords content into tags, if present */
if (document.querySelector('meta[name="keywords" i]')) {
var keywords = document.querySelector('meta[name="keywords" i]').getAttribute('content').split(',');
keywords.forEach(function(keyword) {
let tag = ' ' + keyword.split(' ').join('');
tags += tag;
});
}
function getSelectionHtml() {
var html = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
}
const selection = getSelectionHtml();
const {
title,
byline,
excerpt,
content
} = new Readability(document.cloneNode(true)).parse();
function getFileName(fileName) {
fileName = fileName.replace(/:/g, "").replace(/[^a-zA-Z0-9 ]+/g, " ").replace(/[_-]+/g, " ").replace(/\s+/g, " ");
return fileName;
}
const fileName = getFileName(title);
if (selection) {
var markdownify = selection;
} else {
var markdownify = content;
}
if (vault) {
var vaultName = '&vault=' + encodeURIComponent(`${vault}`);
} else {
var vaultName = '';
}
const markdownBody = new Turndown({
headingStyle: 'atx',
hr: '---',
bulletListMarker: '-',
codeBlockStyle: 'fenced',
emDelimiter: '*',
}).turndown(markdownify);
var date = new Date();
function convertDate(date) {
var yyyy = date.getFullYear().toString();
var mm = (date.getMonth()+1).toString();
var dd = date.getDate().toString();
var mmChars = mm.split('');
var ddChars = dd.split('');
return yyyy + '.' + (mmChars[1]?mm:"0"+mmChars[0]) + '.' + (ddChars[1]?dd:"0"+ddChars[0]);
}
const today = convertDate(date);
/* "convertDateB" to get a dd/mm/yyyy "today" format */
function convertDateB(date) {
var yyyy = date.getFullYear().toString();
var mm = (date.getMonth()+1).toString();
var dd = date.getDate().toString();
var mmChars = mm.split('');
var ddChars = dd.split('');
return (ddChars[1]?dd:"0"+ddChars[0]) + '/' + (mmChars[1]?mm:"0"+mmChars[0]) + '/' + yyyy;
}
/* "todayB" to get a dd/mm/yyyy "today" format */
const todayB = convertDateB(date);
/* Utility function to get meta content by name or property */
function getMetaContent(attr, value) {
var element = document.querySelector(`meta[${attr}='${value}']`);
return element ? element.getAttribute("content").trim() : "";
}
/* Fetch byline, meta author, property author, or site name */
var author = byline || getMetaContent("name", "author") || getMetaContent("property", "author") || getMetaContent("property", "og:site_name");
/* Check if there's an author and add brackets */
var authorBrackets = author ? `"[[${author}]]"` : "";
/* Try to get published date with botj yyyy.mm.dd and dd/mm/yyyy format */
var timeElement = document.querySelector("time");
var publishedDate = timeElement ? timeElement.getAttribute("datetime") : "";
if (publishedDate && publishedDate.trim() !== "") {
var date = new Date(publishedDate);
var year = date.getFullYear();
var month = date.getMonth() + 1; // Months are 0-based in JavaScript
var day = date.getDate();
// Pad month and day with leading zeros if necessary
month = month < 10 ? '0' + month : month;
day = day < 10 ? '0' + day : day;
var published = year + '.' + month + '.' + day;
var publishedB = day + '/' + month + '/' + year;
} else {
var published = ''
}
/* My custom YAML front matter */
const fileContent =
"---\n"
+ "alias:" + "\n"
+ "tags:" + "\n"
+ "source:" + "\n"
+ "date: " + today + "\n"
+ "published: " + published + "\n"
+ "---\n"
+ "# " + "[" + title + "]" + "(" + document.URL + ")" + "\n\n"
+ publishedB + "\n\n"
+ markdownBody ;
document.location.href = "obsidian://new?"
+ "file=" + encodeURIComponent(folder + today + " - " + fileName)
+ "&content=" + encodeURIComponent(fileContent)
+ vaultName ;
})
The second one, which I will call “B”, is based on this one by kvdogan.
On desktop, after being launched, it opens Obsidian and asks for this
and doesen’t fetch the web page, if I close that and relaunch the bookmarklet then clipping is successful. On mobile similar problem: on first launch this message appears
if I close the window and relaunch the bookmarklet a second time on the web page then clipping is successful.
Script B:
javascript: Promise.all([import('https://unpkg.com/[email protected]?module'), import('https://unpkg.com/@tehshrike/[email protected]'),]).then(async ([{
default: Turndown
}, {
default: Readability
}]) => {
/* Optional vault name */
const vault = "Note";
/* Optional folder name such as "Clippings/" */
const folder = "";
/* Optional tags */
let tags = "clippings";
function getSelectionHtml() {
var html = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
return html;
}
const selection = getSelectionHtml();
const {
title,
byline,
excerpt,
content
} = new Readability(document.cloneNode(true)).parse();
function getFileName(fileName) {
fileName = fileName.replace(/:/g, "").replace(/[^a-zA-Z0-9 ]+/g, " ").replace(/[_-]+/g, " ").replace(/\s+/g, " ");
return fileName;
}
const fileName = getFileName(title);
if (selection) {
var markdownify = selection;
} else {
var markdownify = content;
}
if (vault) {
var vaultName = '&vault=' + encodeURIComponent(`${vault}`);
} else {
var vaultName = '';
}
const markdownBody = new Turndown({
headingStyle: 'atx',
hr: '~~~',
bulletListMarker: '-',
codeBlockStyle: 'fenced',
emDelimiter: '*',
}).turndown(markdownify);
var date = new Date();
function convertDate(date) {
var yyyy = date.getFullYear().toString();
var mm = (date.getMonth() + 1).toString();
var dd = date.getDate().toString();
var mmChars = mm.split('');
var ddChars = dd.split('');
return yyyy + '.' + (mmChars[1] ? mm : "0" + mmChars[0]) + '.' + (ddChars[1] ? dd : "0" + ddChars[0]);
}
const today = convertDate(date);
/* "convertDateB" to get a dd/mm/yyyy "today" format */
function convertDateB(date) {
var yyyy = date.getFullYear().toString();
var mm = (date.getMonth()+1).toString();
var dd = date.getDate().toString();
var mmChars = mm.split('');
var ddChars = dd.split('');
return (ddChars[1]?dd:"0"+ddChars[0]) + '/' + (mmChars[1]?mm:"0"+mmChars[0]) + '/' + yyyy;
}
/* "todayB" to get a dd/mm/yyyy "today" format */
const todayB = convertDateB(date);
/* Utility function to get meta content by name or property */
function getMetaContent(attr, value) {
var element = document.querySelector(`meta[${attr}='${value}']`);
return element ? element.getAttribute("content").trim() : "";
}
/* Fetch byline, meta author, property author, or site name */
var author = byline || getMetaContent("name", "author") || getMetaContent("property", "author") || getMetaContent("property", "og:site_name");
/* Check if there's an author and add brackets */
var authorBrackets = author ? `"[[${author}]]"` : "";
/* Try to get published date with botj yyyy.mm.dd and dd/mm/yyyy format */
var timeElement = document.querySelector("time");
var publishedDate = timeElement ? timeElement.getAttribute("datetime") : "";
if (publishedDate && publishedDate.trim() !== "") {
var date = new Date(publishedDate);
var year = date.getFullYear();
var month = date.getMonth() + 1; // Months are 0-based in JavaScript
var day = date.getDate();
// Pad month and day with leading zeros if necessary
month = month < 10 ? '0' + month : month;
day = day < 10 ? '0' + day : day;
var published = year + '.' + month + '.' + day;
var publishedB = day + '/' + month + '/' + year;
} else {
var published = ''
}
const fileContent =
"---\n"
+ "alias:" + "\n"
+ "tags:" + "\n"
+ "source:" + "\n"
+ "date: " + today + "\n"
+ "published: " + published + "\n"
+ "---\n"
+ "# " + "[" + title + "]" + "(" + document.URL + ")" + "\n\n"
+ publishedB + "\n\n"
+ markdownBody ;
/* This function must be called in a visible page, such as a browserAction popup */
/* or a content script. Calling it in a background page has no effect! */
async function copyContent() {
try {
await navigator.clipboard.writeText(fileContent);
} catch (err) {
console.error('Failed to copy: ', err);
}
}
copyContent();
document.location.href = "obsidian://advanced-uri?"
+ "vault=" + vaultName
+ "&clipboard=true"
+ "&mode=new"
+ "&filepath=" + encodeURIComponent(folder + today + " - " + fileName);
})
Basically I would like “B” to work weel without those strange messages like “A” does only on mobile. It seems to me that in the end, the biggest difference of the two scripts is the final part.
Does anyone have an idea of what might be in B that produces those strange screens when the bookmarkelt is first launched?