You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

410 lines
12 KiB

(function() {
'use strict';
const videoExtensions = ['mp4', 'avi', 'mov', 'mkv', 'wmv', 'flv', 'webm'];
const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp'];
function describeTimeElementDate(element) { // {{{
if (!(element instanceof HTMLTimeElement)) {
return "unknown";
}
const startYear = element.getAttribute('startyear');
const startMonth = element.getAttribute('startmonth');
const startDay = element.getAttribute('startday');
if (!startYear || !startMonth || !startDay || isNaN(startYear) || isNaN(startMonth) || isNaN(startDay)) {
return 'Invalid date attributes on the <time> element';
}
const timeElementDate = new Date(startYear, startMonth - 1, startDay);
timeElementDate.setHours(0, 0, 0, 0);
const today = new Date();
today.setHours(0, 0, 0, 0);
const dayDifference = Math.round((timeElementDate - today) / (1000 * 60 * 60 * 24));
const daysOfWeek = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
const dayOfWeek = daysOfWeek[timeElementDate.getDay()];
const monthsOfYear = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'];
const month = monthsOfYear[timeElementDate.getMonth()];
var ret = [dayOfWeek, month];
if (dayDifference === 0) {
ret.push('today');
} else if (dayDifference === 1) {
ret.push('tomorrow');
} else if (dayDifference === -1) {
ret.push('yesterday');
} else {
if (dayDifference < 0) {
ret.push('late');
// if (dayDifference > -8) {
// ret.push('last');
// } else {
// ret.push('older');
// }
} else {
ret.push('future');
// if (dayDifference < 8) {
// ret.push('next');
// } else {
// ret.push('later');
// }
}
}
return ret;
}
// }}}
function safeGetContent(parent, selector) { // {{{
var element = parent.querySelector(selector);
if (element !== null) {
var content = element.innerText;
if (content !== null) {
return content;
}
}
return ""
}
// }}}
function removeClassesStartingWith(element, prefix) { // {{{
const classes = element.classList;
for (const className of classes) {
if (className.startsWith(prefix)) {
element.classList.remove(className);
}
}
}
// }}}
function addImageToAlt(node, imgSrc) { // {{{
var alt = node.getAttribute("alt");
if (alt === null) {
alt = imgSrc;
node.setAttribute("alt", alt);
node.classList.add("image");
}
}
// }}}
function createImageNodeAfterNode(node, imgSrc) { // {{{
var injected = node.getElementsByClassName("inject");
if (injected.length === 0) {
var extension = imgSrc.split('.').pop().toLowerCase();
if (videoExtensions.includes(extension)) {
var link = document.createElement("a");
link.className = 'inject';
link.href = imgSrc;
link.target = "_blank"
var video = document.createElement("video");
video.src = imgSrc;
link.appendChild(video)
node.appendChild(link);
}
// else if (imageExtensions.includes(extension)) {
else {
var link = document.createElement("a");
link.className = 'inject';
link.href = imgSrc;
link.target = "_blank"
var img = document.createElement("img");
img.src = imgSrc;
img.draggable = false;
link.appendChild(img)
node.appendChild(link);
}
}
}
// }}}
function removeImagesFromNode(node) { // {{{
var existingImages = Array.from(node.getElementsByClassName("inject"));
existingImages.forEach(function(imgDiv) {
imgDiv.parentNode.removeChild(imgDiv);
});
}
// }}}
const markdownImageRegex = /\!\[.*\]\((.+)\)/;
function updateProject(projectNode) { // {{{
removeClassesStartingWith(projectNode, "backlinked");
removeClassesStartingWith(projectNode, "link");
removeClassesStartingWith(projectNode, "tag");
removeClassesStartingWith(projectNode, "time");
const names = [];
const notes = [];
const breadcrumbNodes = [];
for (let i = 0; i < projectNode.children.length; i++) {
const child = projectNode.children[i];
if (child.classList.contains('name')) {
names.push(child);
}
if (child.classList.contains('notes')) {
notes.push(child);
}
if (child.classList.contains('_1zok2')) {
breadcrumbNodes.push(child.querySelector('.breadcrumbs'));
}
}
[notes, names].forEach(function(ns) {
if (ns.length > 0) {
const n = ns[0];
const text = safeGetContent(n, ".content > .innerContentContainer");
var matcher = text.match(markdownImageRegex);
if (matcher !== null) {
var imgSrc = matcher[1];
var nameText = names[0].querySelector('.innerContentContainer');
if (nameText.dataset.imgSrc === undefined ) {
nameText.classList.add("image");
nameText.dataset.imgSrc = imgSrc;
nameText.addEventListener('mouseover', function(e) {
const tooltip = document.getElementById('tooltip');
tooltip.style.display = 'block';
tooltip.style.left = e.pageX + 'px';
tooltip.style.top = e.pageY + 'px';
tooltip.src = imgSrc;
nameText.addEventListener('mousemove', function(e) {
tooltip.style.left = e.pageX + 5 + 'px';
tooltip.style.top = e.pageY + 5 + 'px';
});
nameText.addEventListener('mouseleave', function() {
tooltip.style.display = 'none';
});
});
}
}
const tags = n.querySelectorAll('.contentTag');
tags.forEach(tag => {
var tagText = safeGetContent(tag, ".contentTagText").trim();
if (tagText !== "") {
projectNode.classList.add("tagged");
projectNode.classList.add("tagged-" + tagText);
}
});
const links = n.querySelectorAll('.contentLink');
links.forEach(link => {
link.spellcheck = false;
const nonLetterRegex = /[^a-zA-Z0-9]/g;
var linkFull = link.innerText.trim().replace(nonLetterRegex, '');
if (linkFull.startsWith("x") || linkFull.startsWith("y") || linkFull.startsWith("z")) {
var className = "linked-" + linkFull;
var linkClassName = "link-" + linkFull;
projectNode.classList.add("linked");
projectNode.classList.add(className);
link.classList.add("link");
link.classList.add(linkClassName);
}
});
const times = n.querySelectorAll('time');
times.forEach(time => {
var relatives = describeTimeElementDate(time);
projectNode.classList.add("timed");
relatives.forEach(relative => {
projectNode.classList.add("timed-" + relative);
});
});
}
});
if (breadcrumbNodes.length > 0) {
const links = breadcrumbNodes[0].querySelectorAll('a');
for (let i = 0; i < links.length; i++) {
var link = links[i];
if (link.innerHTML == "🌎 planner") {
if (link !== undefined) {
var hotspot = links[i + 1].innerText.split(' ')[1];
var className = "backlinked-" + hotspot;
projectNode.classList.add("backlinked");
projectNode.classList.add(className);
break;
}
}
}
}
}
// }}}
function updateAll() {
const projectNodes = document.querySelectorAll('.project');
projectNodes.forEach(projectNode => {
updateProject(projectNode);
});
}
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
var nodes = null;
if (mutation.addedNodes.length > 0) {
nodes = mutation.addedNodes;
} else if (mutation.removedNodes.length > 0) {
nodes = mutation.addedNodes;
}
if ( nodes !== null ) {
var node = mutation.target;
if ( node !== null ) {
var projectNode = node.closest('.project');
if ( projectNode !== null && projectNode !== node ) {
updateProject(projectNode);
}
}
}
}
});
function addTooltip() {
const tooltip = document.createElement('img');
tooltip.style.position = 'absolute';
tooltip.style.zIndex = '1000';
tooltip.id = 'tooltip';
document.body.appendChild(tooltip);
return tooltip;
}
function getContainerNode(node) {
if (!node.classList) {
node = node.parentNode;
}
if (node.classList.contains('innerContentContainer')) {
return node;
} else if (node.querySelector('.innerContentContainer')) {
return node.querySelector('.innerContentContainer');
} else {
return node.closest('.innerContentContainer');
}
console.log(node);
return null;
}
function getTagNodes(containerNode) {
const tags = containerNode.querySelectorAll('.contentTag');
return tags;
}
function getLinkNodes(containerNode) {
const links = containerNode.querySelectorAll('.contentLink');
return links;
}
function getTagNode(containerNode, tagName) {
const tags = getTagNodes(containerNode);
for (const existingTag of tags) {
if (existingTag.innerText === '@' + tagName) {
return existingTag;
}
}
return null;
}
function getLinkNode(containerNode, linkName) {
const links = getLinkNodes(containerNode);
for (const existingLink of links) {
if (existingLink.innerText === linkName) {
return existingLink;
}
}
return null;
}
function toggleTag(containerNode, tagName) {
const tagNode = getTagNode(containerNode, tagName);
if (tagNode) {
tagNode.remove();
} else {
addTagNode(containerNode, tagName);
}
}
function toggleLink(containerNode, linkName, linkUrl) {
const linkNode = getLinkNode(containerNode, linkName);
if (linkNode) {
linkNode.remove();
} else {
addLinkNode(containerNode, linkName, linkUrl);
}
}
function addTagNode(containerNode, tagName) {
containerNode.innerHTML = containerNode.innerHTML.trim() + ' <span class="contentTag explosive" title="Filter @' + tagName + '" data-val="@' + tagName + '">@<span class="contentTagText">' + tagName + '</span><span class="contentTagNub"></span></span>';
}
function addLinkNode(containerNode, linkName, linkUrl) {
// <a class="contentLink link link-xtask" target="_blank" rel="noreferrer" href="https://workflowy.com/#/b732f37515f4" spellcheck="false">xtask</a>
containerNode.innerHTML = containerNode.innerHTML.trim() + ' <a class="contentLink link link-' + linkName + '" target="_blank" rel="noreferrer" href="' + linkUrl + '" spellcheck="false">' + linkName + '</a>';
}
const quickTags = {
'd': 'done',
'm': 'missed',
'n': 'na',
};
const quickLinks = {
'†': {'name': 'xtask', 'url': 'https://workflowy.com/#/b732f37515f4'}
};
document.addEventListener("keydown", (e) => {
if (e.ctrlKey) {
console.log(e.key);
if (e.key in quickTags) {
e.preventDefault();
const selection = window.getSelection();
const node = selection.anchorNode;
if (node && node.parentNode) {
const containerNode = getContainerNode(node);
console.log({containerNode});
if (containerNode) {
toggleTag(containerNode, quickTags[e.key]);
let lastTextNode = containerNode.lastChild;
while (lastTextNode && lastTextNode.nodeType !== Node.TEXT_NODE) {
lastTextNode = lastTextNode.previousSibling;
}
if (lastTextNode && lastTextNode.nodeType === Node.TEXT_NODE) {
selection.collapse(lastTextNode, lastTextNode.textContent.length);
}
updateProject(containerNode.closest('.project'));
}
}
}
}
});
observer.observe(document.body, { childList: true, subtree: true });
addTooltip();
updateAll();
})();