-
-
Save solarkraft/b05e9058ca2cda40a4d6e03c52dff025 to your computer and use it in GitHub Desktop.
/*** Publishing: Hide things that aren't very useful for a read-only view */ | |
/** Hide page properties (public pages will always have public: true) */ | |
.content .pre-block { display: none; } | |
/** Title */ | |
/* Make title non-editable */ | |
#main-container .page-title { pointer-events: none; } | |
/** Hide useless sidebar stuff */ | |
.nav-header .flashcards-nav { display: none; } | |
.nav-header .journals-nav { display: none; } | |
/*.nav-header .graph-view-nav { display: none; }*/ | |
/** Header */ | |
/* Hide right side of header buttons (only useful setting is light/dark theme and can still be done using tt, graph is somewhat broken, home is covered by "All Pages") */ | |
#head div.r { display: none; } | |
/** All pages */ | |
/* Hide selection checkbox (nothing can be done with it) */ | |
.cp__all_pages table .selector { display: none; } | |
/* Hide more columns (not that they don't work, they just don't seem very useful) */ | |
.cp__all_pages table .backlinks { display: none; } | |
.cp__all_pages table .created-at { display: none; } | |
/* Hide delete button */ | |
.cp__all_pages .actions .actions-wrap { display: none; } | |
/* Hide more page modification options/things that don't work */ | |
.cp__all_pages .actions div.r { display: none; } | |
/* Fix search bar spacing */ | |
.cp__all_pages .actions .search-wrap { margin-left: 0; padding-left: 0; } | |
/** Image */ | |
/* Remove delete button */ | |
a.delete { display: none; } | |
/* Disable resizing */ | |
.resize { resize:none; } | |
/** Hide graph settings (they're ineffective, only the desktop app's while exporting seem to matter, search doesn't work either) */ | |
.graph-filters { display: none; } | |
/** Hide recent pages (seems to be ineffective on web)*/ | |
.nav-content-item.recent { display: none; } | |
/* Hide context menu (mostly ineffective) */ | |
#custom-context-menu { display: none; } | |
/** Disable dragging of blocks (also disables zooming) */ | |
.ls-block > div > div > a:not(.block-control) { pointer-events: none; } | |
/** Remove superfluous spacing on block embeds in Firefox */ | |
.block-content.inline { white-space: revert; } |
// Interact.js (https://interactjs.io/) is for editing gestures we don't need in a read-only version anyway, | |
// so let's hijack it for our purposes. | |
console.debug("Hijacked :-)"); | |
let page_title = "Lamentable Technology"; | |
let start_page = "start"; | |
// This script is loaded before main.js (which is huge), so we can inject a loading message heee. | |
let loaderImage = "data:image/svg+xml,%3Csvg width='44' height='44' viewBox='0 0 44 44' xmlns='http://www.w3.org/2000/svg' stroke='%23ccc'%3E%3Cg fill='none' fill-rule='evenodd' stroke-width='2'%3E%3Ccircle cx='22' cy='22' r='1'%3E%3Canimate attributeName='r' begin='0s' dur='1.8s' values='1; 20' calcMode='spline' keyTimes='0; 1' keySplines='0.165, 0.84, 0.44, 1' repeatCount='indefinite' /%3E%3Canimate attributeName='stroke-opacity' begin='0s' dur='1.8s' values='1; 0' calcMode='spline' keyTimes='0; 1' keySplines='0.3, 0.61, 0.355, 1' repeatCount='indefinite' /%3E%3C/circle%3E%3Ccircle cx='22' cy='22' r='1'%3E%3Canimate attributeName='r' begin='-0.9s' dur='1.8s' values='1; 20' calcMode='spline' keyTimes='0; 1' keySplines='0.165, 0.84, 0.44, 1' repeatCount='indefinite' /%3E%3Canimate attributeName='stroke-opacity' begin='-0.9s' dur='1.8s' values='1; 0' calcMode='spline' keyTimes='0; 1' keySplines='0.3, 0.61, 0.355, 1' repeatCount='indefinite' /%3E%3C/circle%3E%3C/g%3E%3C/svg%3E"; | |
let root = document.childNodes[1].childNodes[1].childNodes[0]; | |
root.innerHTML = `<div class="loading"><span>Logseq is loading ...</span><span class="apology">Sorry about the current size of the bundle. We\'re working on slimming it down. </span><img src="${loaderImage}"/></div>`; | |
// Add styles that become relevant when this injection is active | |
let styles = ` | |
.title { | |
font-size: 1.2em; | |
color: var(--ls-primary-text-color); | |
} | |
#head .button.title { opacity: 1; } | |
/* Add margin the hamburger button used to have to the head area */ | |
#head > .l { margin-left: .4rem; } | |
/* Loader */ | |
#root .loading { | |
color: darkgray; | |
margin-top: 20vh; | |
margin-left: 2rem; | |
margin-right: 2rem; | |
font-size: 2.5rem; | |
text-align: center; | |
} | |
#root .loading span { | |
display: block; | |
line-height: 1.5em; | |
margin-bottom: 1rem; | |
} | |
#root .loading .apology { font-size: .3em; } | |
#root .loading img { height: 8rem; margin-top: 3rem; } | |
/* Page title in header */ | |
#head .page-title { | |
display: block; | |
overflow: hidden; | |
transition: width 1s; | |
} | |
`; | |
let styleSheet = document.createElement("style"); | |
styleSheet.type = "text/css"; | |
styleSheet.innerText = styles; | |
document.head.appendChild(styleSheet); | |
let redirect = () => { | |
let hash = window.location.hash; | |
console.debug("Page hash:", hash); | |
// Start page redirect (otherweise Logseq opens either the "All Pages" view or the latest Journal page if no page is provided) | |
if (!hash || hash == "#" || hash == "#/") { | |
console.debug("Start page redirect"); | |
window.location.hash = `#/page/${start_page}`; | |
} | |
// "All pages" view on #/page/ (equivalent of index) | |
if (hash == "#/page" || hash == "#/page/") { | |
console.debug("All pages redirect"); | |
window.location.hash = "#/all-pages"; | |
} | |
// Todo: Something about "404" pages | |
} | |
let showOrHideHeadPageTitle = () => { | |
let el = document.getElementById("main-content-container"); | |
if(!el) return; | |
// Yup, that's slow | |
let title = document.querySelector("#main-content-container .page-title"); | |
let headTitle = document.querySelector("#head .page-title"); | |
let y = title.getBoundingClientRect().y; | |
let titleInView = y > 0; | |
headTitle.style.width = titleInView? "0px" : headerPageTitleOriginalWidth + "px"; | |
}; | |
// Update the page title in the header | |
let headerPageTitleOriginalWidth; | |
let updatePageTitle = () => { | |
let headButtons = document.querySelector("#head > .l"); | |
// Remove old element if it already exists | |
document.querySelector("#head .page-title")?.remove(); | |
let pageTitle = document.title || ""; // hacky indeed | |
headPageTitle = document.createElement("div"); | |
headPageTitle.innerHTML = `<a class="title page-title" href="${window.location}">${pageTitle}</a>`; | |
// After title | |
headButtons?.insertBefore(headPageTitle, document.querySelector("#head .title").parentNode.nextSibling); | |
// Title width | |
headerPageTitleOriginalWidth = headPageTitle.getBoundingClientRect().width; | |
showOrHideHeadPageTitle(); | |
}; | |
let onPageChange = () => { | |
redirect(); | |
updatePageTitle(); | |
}; | |
onPageChange(); | |
// window.addEventListener('hashchange', () => onPageChange()); | |
// hashchange doesn't reliably fire for some reason ... Yep, it's getting hackier and hackier. :-) | |
new MutationObserver(() => { onPageChange(); }).observe(document.querySelector('title'), { childList: true }); | |
window.addEventListener("load", () => { | |
// If you explicitly set it I have to explicitly reset it ... | |
document.querySelector("#head").style.fontSize = ""; | |
// Add title | |
let headButtons = document.querySelector("#head > .l"); | |
let title = document.createElement("div"); | |
title.innerHTML = `<a href="#/page/start" class="button title">${page_title}</a>` | |
headButtons.prepend(title); | |
// Remove hamburger menu button because now the title can navigate to the start page | |
// To do: Re-add Graph view and All pages | |
document.getElementById("left-menu").parentElement.remove(); | |
//// Cool title-in-header effect | |
// Add page name to header | |
updatePageTitle(); | |
// Title width | |
let lastScroll = 0; | |
document.getElementById("main-content-container").addEventListener("scroll", ev => { | |
showOrHideHeadPageTitle(); | |
}, { passive: true }); | |
}); |
Thanks for your interest!
interact.js is located in static/js/
in your web export. You can replace it with the file provided here because it's not needed for a read-only version (and there is no other way to get "custom.js" file into an export that I am aware of so far).
@solarkraft So I should generate the web export first, and then add this file?
Yep! That means you either need to do it after every export or write-protect the file. I have added an ignore rule to Syncthing so the original Logseq versions of these files don't get copied over to the server.
Hey @solarkraft ! Do you know how solve this with CSS?
@candideu I haven't used this in a while so I'm not sure whether it still works, but I initially solved this using #main-container .page-title { pointer-events: none; }
.
@candideu I haven't used this in a while so I'm not sure whether it still works, but I initially solved this using
#main-container .page-title { pointer-events: none; }
.
It still appears to work. Thanks again for this Gist, it's been invaluable to my project.
Also added this:
/* Make TODO non-clickable */
span:is(.todo, .done) > :is(.marker-switch, input) { pointer-events: none; }
/* Make block ref icon non-clickable, clicking causes a crash for some reason */
.open-block-ref-link { pointer-events: none; }
Where should interact.js be placed?