Closed HKohlhoff closed 1 month ago
Nice catch. I published the update.
Btw, here's my updated publish.css and publish.js - in case you find it helpful:
@font-face {font-family: "Virgil";src: url("https://excalidraw.com/Virgil.woff2");}
@font-face {font-family: "Cascadia";src: url("https://excalidraw.com/Cascadia.woff2");}
@font-face {font-family: "Assistant";src: url("https://excalidraw.com/Assistant-Regular.woff2");}
div.markdown-embed-title {
display: none;
}
div.markdown-embed {
border: none;
padding: 0px;
background-color: inherit;
}
div.excalidraw-svg {
/*width: fit-content;*/
height: 100%;
}
svg.excalidraw-svg {
max-width:100%;
max-height: 90vh;
width: var(--page-width);
}
svg.excalidraw-svg.ex-pageheight {
width: initial;
height: 100%;
}
svg.excalidraw-svg.ex-pagewidth {
width: 90vw;
height: initial;
}
.excalidraw-svg .text {
width: 100%;
text-align: center;
}
div.excalidraw-svg.enlarged {
position: fixed;
top: 0;
left: 0;
z-index: 10;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
body {
--background-primary: #FFF6F0;
}
a.site-body-left-column-site-name {
display: none;
}
div.site-footer {
display: none;
}
svg a {
text-decoration: none;
}
svg.excalidraw-svg.ex-w200 {
width: 200px;
}
svg.excalidraw-svg.ex-w300 {
width: 300px;
}
svg.excalidraw-svg.ex-w400 {
width: 400px;
}
svg.excalidraw-svg.ex-w500 {
width: 500px;
}
svg.excalidraw-svg.ex-w600 {
width: 600px;
}
div.excalidraw-svg:has(.ex-center) {
text-align: center;
}
svg.ex-16em { width: 16em !important; }
svg.ex-17em { width: 17em !important; }
svg.ex-18em { width: 18em !important; }
svg.ex-19em { width: 19em !important; }
svg.ex-20em { width: 20em !important; }
svg.ex-21em { width: 21em !important; }
svg.ex-22em { width: 22em !important; }
svg.ex-23em { width: 23em !important; }
svg.ex-24em { width: 24em !important; }
svg.ex-25em { width: 25em !important; }
svg.ex-26em { width: 26em !important; }
svg.ex-27em { width: 27em !important; }
svg.ex-28em { width: 28em !important; }
svg.ex-29em { width: 29em !important; }
svg.ex-30em { width: 30em !important; }
svg.ex-31em { width: 31em !important; }
svg.ex-32em { width: 32em !important; }
svg.ex-33em { width: 33em !important; }
svg.ex-34em { width: 34em !important; }
svg.ex-35em { width: 35em !important; }
svg.ex-36em { width: 36em !important; }
svg.ex-37em { width: 37em !important; }
svg.ex-38em { width: 38em !important; }
svg.ex-39em { width: 39em !important; }
svg.ex-40em { width: 40em !important; }
svg.ex-41em { width: 41em !important; }
svg.ex-42em { width: 42em !important; }
svg.ex-43em { width: 43em !important; }
svg.ex-44em { width: 44em !important; }
svg.ex-45em { width: 45em !important; }
svg.ex-46em { width: 46em !important; }
svg.ex-47em { width: 47em !important; }
svg.ex-48em { width: 48em !important; }
svg.ex-49em { width: 49em !important; }
svg.ex-50em { width: 50em !important; }
svg.ex-51em { width: 51em !important; }
svg.ex-52em { width: 52em !important; }
svg.ex-53em { width: 53em !important; }
svg.ex-54em { width: 54em !important; }
svg.ex-55em { width: 55em !important; }
svg.ex-56em { width: 56em !important; }
svg.ex-57em { width: 57em !important; }
svg.ex-58em { width: 58em !important; }
svg.ex-59em { width: 59em !important; }
svg.ex-60em { width: 60em !important; }
svg.ex-61em { width: 61em !important; }
svg.ex-62em { width: 62em !important; }
svg.ex-63em { width: 63em !important; }
svg.ex-64em { width: 64em !important; }
svg.ex-65em { width: 65em !important; }
span[alt="center"] {
display: flex;
justify-content: center;
}
span[alt="center-25"] {
display: flex;
justify-content: center;
}
img[alt="center-25"] {
width: 25em;
}
const clickToEnlarge = "Click and hold to enlarge. SHIFT + wheel to zoom. ESC to reset.";
const clickToCollapse = "ESC to reset. Click and hold to collapse. SHIFT + wheel to zoom";
//check if in iFrame - if yes the page is assumed to be an embedded frame
if(window.self !== window.top) {
const elements = [
"div.site-body-right-column",
"div.site-body-left-column",
"div.site-header",
"div.site-footer"
];
elements.forEach(x=>{
document.querySelectorAll(x).forEach(div=>{
div.style.display = "none";
});
});
}
const baseUrl = `${window.location.origin}/`;
const [isDesktop, isMobile, isTablet] = (()=>{
const userAgent = navigator.userAgent;
const mobileKeywords = ['Mobile', 'Android', 'iPhone', 'iPad', 'Windows Phone'];
const isMobile = mobileKeywords.some(keyword => userAgent.includes(keyword));
const isTablet = /iPad/i.test(userAgent) || (isMobile && !/Mobile/i.test(userAgent));
const isDesktop = !isMobile && !isTablet;
return [isDesktop, isMobile, isTablet];
})();
const addNavigationToDiv = (container) => {
const svgElement = container?.querySelector('.excalidraw-svg');
if(!svgElement) return;
container.addClass("excalidraw-svg");
svgElement.removeAttribute("width");
svgElement.removeAttribute("height");
if(!isDesktop) return;
const textDiv = document.createElement('div');
textDiv.className = 'text';
textDiv.textContent = clickToEnlarge;
container.appendChild(textDiv);
let isEnlarged = false;
let timeout = null;
let isReadyToPan = false;
let isPanning = false;
let zoomLevel = 1;
let panX = 0;
let panY = 0;
let pinchStartDistance = 0;
let panStartX = 0;
let panStartY = 0;
const clearEnlargeTimeout = () => {
if(timeout) clearTimeout(timeout);
timeout = null;
}
const enablePointerEvents = (val) => {
svgElement.querySelectorAll("a").forEach(el=>{
el.style.pointerEvents = val ? "all" : "none";
});
}
const applyTransform = () => {
svgElement.style.transform = `scale(${zoomLevel}) translate(${panX}px, ${panY}px)`;
clearEnlargeTimeout();
};
//Wheel zoom
svgElement.addEventListener('wheel', (event) => {
if(!event.shiftKey ) return;
if (event.deltaY > 0) {
zoomLevel -= zoomLevel > 4
? (zoomLevel > 6
? (zoomLevel > 10 ? 0.4 : 0.3)
: 0.2)
: 0.1;
} else {
zoomLevel += zoomLevel > 4
? (zoomLevel > 6
? (zoomLevel > 10 ? 0.4 : 0.3)
: 0.2)
: 0.1;
}
applyTransform();
});
// Panning
svgElement.addEventListener('mousedown', (event) => {
isReadyToPan = true;
panStartX = event.clientX;
panStartY = event.clientY;
});
svgElement.addEventListener('mousemove', (event) => {
const deltaX = event.clientX - panStartX;
const deltaY = event.clientY - panStartY;
const distance = Math.sqrt(deltaX**2+deltaY**2);
if (isReadyToPan && (distance > 20)) {
if(!isPanning) {
enablePointerEvents(false);
isPanning = true;
}
panX += deltaX/zoomLevel;
panY += deltaY/zoomLevel;
panStartX = event.clientX;
panStartY = event.clientY;
applyTransform();
}
});
svgElement.addEventListener('mouseup', () => {
enablePointerEvents(true);
isPanning = false;
isReadyToPan = false;
});
svgElement.addEventListener('mouseleave', () => {
enablePointerEvents(true);
isPanning = false;
isReadyToPan = false;
});
//abort on Escape
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
enablePointerEvents(true);
isEnlarged = false;
isPanning = false;
isReadyToPan = false;
container.classList.remove("enlarged");
textDiv.textContent = clickToEnlarge;
zoomLevel = 1;
panX = 0;
panY = 0;
applyTransform();
}
});
//Enlarge on long click
svgElement.addEventListener('mouseup', () => clearEnlargeTimeout());
svgElement.addEventListener('mousedown', () => {
timeout = setTimeout(()=> {
timeout = null;
if(isPanning) return;
isReadyToPan = false;
if (isEnlarged) {
// Collapse the image
container.classList.remove("enlarged");
textDiv.textContent = clickToEnlarge;
} else {
// Enlarge the image
container.addClass("enlarged");
textDiv.textContent = clickToCollapse;
}
isEnlarged = !isEnlarged;
},1000);
});
applyTransform();
}
const processIMG = (img) => {
const svgURL = img.src;
const container = img.parentElement;
fetch(svgURL)
.then((response) => {
if (response.ok) {
return response.text();
}
throw new Error('Failed to fetch SVG');
})
.then((svgContent) => {
svgContainer = document.createElement('div');
svgContainer.innerHTML = svgContent;
svgContainer.querySelectorAll(`a[href^="obsidian://open?vault="`).forEach(el=>{
el.setAttribute("href",unescape(el.getAttribute("href").replace(/.*&file=/,baseUrl).replaceAll(" ","+")));
});
svgContainer.querySelectorAll(`iframe[src^="obsidian://open?vault="`).forEach(el=>{
el.setAttribute("src",unescape(el.getAttribute("src").replace(/.*&file=/,baseUrl).replaceAll(" ","+")));
});
container.removeChild(img);
container.appendChild(svgContainer);
addNavigationToDiv(svgContainer);
})
.catch((error) => {
console.error('Error: ' + error);
});
}
const processIframe = (iframe) => {
const p = iframe.parentElement;
if(!p || p.tagName.toLowerCase()!=="p") return;
const div = p.parentElement;
if(!div || div.tagName.toLowerCase()!=="div") return;
div.style.maxWidth = '600px';
div.style.maxHeight = '350px';
div.style.overflow = 'hidden';
p.style.position = 'relative';
p.style.width = '100%';
p.style.paddingBottom = '56.25%'; // 16:9 aspect ratio
p.style.height = '0';
// Apply inline styles to the iframe
iframe.style.position = 'absolute';
iframe.style.top = '0';
iframe.style.left = '0';
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.border = '0';
};
const addMutationObserver = () => {
const targetElement = document.body;
const handler = (mutationsList, observer) => {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach(node => {
if (node instanceof Element) {
// Process SVG images as before
if (node.querySelector(`img[alt$=".svg"]`)) {
processIMG(node.querySelector(`img[alt$=".svg"]`));
}
// Process iframes with the class 'external-embed'
const iframe = node.querySelector('iframe.external-embed');
if (iframe) {
processIframe(iframe);
}
}
});
}
}
};
const observer = new MutationObserver(handler);
const config = { childList: true, subtree: true };
observer.observe(targetElement, config);
};
//process images after loading
document.body.querySelectorAll(`img[alt$=".svg"`).forEach(img => {
processIMG(img);
});
addMutationObserver();
// -----------------------------------
// Page redirect for 404 pages
// -----------------------------------
const pageNotFoundObserver = new MutationObserver(() => {
handlePageNotFound();
});
function handlePageNotFound() {
const container = document.querySelector('div.published-container.has-not-found');
if (container) {
pageNotFoundObserver.disconnect(); // Stop observing once the .published-container is found
const currentLocation = window.location.href;
const newLocation = currentLocation.replace(/Hobbies\/Excalidraw\+Blog\//, '');
// Update the content of the div.not-found-description
const notFoundDescription = document.querySelector('div.not-found-description');
if (notFoundDescription) {
notFoundDescription.innerHTML = `
<p style="text-align: center;">This page may have moved. You will be redirected in <span id="countdown" style="color:red;">10</span><span style="color:red;"> seconds</span>.</p>
<p style="text-align: center;">If you arrived from an external link, please email details to
<a href="mailto:webmaster@visual-thinking-workshop.com">webmaster@visual-thinking-workshop.com</a>.</p>
<p style="text-align: center;"><a href="${newLocation}">Click here to redirect now.</a></p>
`;
}
// Countdown timer
let countdown = 10;
const countdownElement = document.getElementById('countdown');
const interval = setInterval(() => {
//abort if the user has moved to another page
if(currentLocation !== window.location.href) {
clearInterval(interval);
}
countdown -= 1;
countdownElement.textContent = countdown;
// Once the countdown reaches 0, redirect the page
if (countdown <= 0) {
clearInterval(interval);
window.location.href = newLocation;
}
}, 1000); // Update every second
console.log(`Redirecting to: ${newLocation}`);
return true;
}
return false;
}
if(!handlePageNotFound()) {
const target = document.querySelector("div.published-container") ?? document.body;
pageNotFoundObserver.observe(target, { childList: true, attributes: true });
}
Have you searched for existing issues (including closed ones)?
Does this bug persist in a new vault with only Excalidraw installed?
Your environment
No response
Describe the bug
In the publish.css-file there is one little typo - at least to my opinion: div.excalidraw-svg { /width: fit-content;/ height: 100%> } should read: div.excalidraw-svg { /width: fit-content;/ height: 100%; } change the > to ;
Steps to reproduce
No response
Expected behavior
No response
Additional context
No response