diff --git a/assets/ts/gallery.ts b/assets/ts/gallery.ts index 9840f1e..86f9345 100644 --- a/assets/ts/gallery.ts +++ b/assets/ts/gallery.ts @@ -1,186 +1,97 @@ -declare global { - interface Window { - PhotoSwipe: any; - PhotoSwipeUI_Default: any +const wrap = (figures: HTMLElement[]) => { + const galleryContainer = document.createElement('div'); + galleryContainer.className = 'gallery'; + + const parentNode = figures[0].parentNode!, + first = figures[0]; + + parentNode.insertBefore(galleryContainer, first) + + for (const figure of figures) { + galleryContainer.appendChild(figure); } } -interface PhotoSwipeItem { - w: number; - h: number; - src: string; - msrc: string; - title?: string; - el: HTMLElement; -} +export default (container: HTMLElement) => { + /// The process of wrapping image with figure tag is done using JavaScript instead of only Hugo markdown render hook + /// because it can not detect whether image is being wrapped by a link or not + /// and it lead to a invalid HTML construction (
) + const images = container.querySelectorAll('img.gallery-image') as NodeListOf; + for (const img of Array.from(images)) { + /// Images are wrapped with figure tag if the paragraph has only images without texts + /// This is done to allow inline images within paragraphs + const paragraph = img.closest('p'); -class StackGallery { - private galleryUID: number; - private items: PhotoSwipeItem[] = []; + if (!paragraph || !container.contains(paragraph)) continue; - constructor(container: HTMLElement, galleryUID = 1) { - if (window.PhotoSwipe == undefined || window.PhotoSwipeUI_Default == undefined) { - console.error("PhotoSwipe lib not loaded."); - return; + if (paragraph.textContent.trim() == '') { + /// Once we insert figcaption, this check no longer works + /// So we add a class to paragraph to mark it + paragraph.classList.add('no-text'); } - this.galleryUID = galleryUID; + let isNewLineImage = paragraph.classList.contains('no-text'); + if (!isNewLineImage) continue; - StackGallery.createGallery(container); - this.loadItems(container); - this.bindClick(); - } + const hasLink = img.parentElement!.tagName == 'A'; - private loadItems(container: HTMLElement) { - this.items = []; + let el: HTMLElement = img; + /// Wrap image with figure tag, with flex-grow and flex-basis values extracted from img's data attributes + const figure = document.createElement('figure'); + figure.classList.add('gallery-image'); + figure.style.setProperty('flex-grow', img.getAttribute('data-flex-grow') || '1'); + figure.style.setProperty('flex-basis', img.getAttribute('data-flex-basis') || '0'); - const figures = container.querySelectorAll('figure.gallery-image'); + if (hasLink) { + /// Wrap if it exists + el = img.parentElement!; + el.classList.add('image-link'); + el.setAttribute('data-pswp-width', img.getAttribute('width')!); + el.setAttribute('data-pswp-height', img.getAttribute('height')!); + } else { + const a = document.createElement('a'); + a.href = img.src; + a.setAttribute('class', 'image-link'); + a.setAttribute('target', '_blank'); + a.setAttribute('data-pswp-width', img.getAttribute('width')!); + a.setAttribute('data-pswp-height', img.getAttribute('height')!); + img.parentNode!.insertBefore(a, img); + a.appendChild(img); + el = a; + } - for (const el of figures) { - const figcaption = el.querySelector('figcaption'), - img = el.querySelector('img'); + el.parentElement!.insertBefore(figure, el); + figure.appendChild(el); - let aux: PhotoSwipeItem = { - w: parseInt(img.getAttribute('width')), - h: parseInt(img.getAttribute('height')), - src: img.src, - msrc: img.getAttribute('data-thumb') || img.src, - el: el - } - - if (figcaption) { - aux.title = figcaption.innerHTML; - } - - this.items.push(aux); + /// Add figcaption if it exists + if (img.hasAttribute('alt')) { + const figcaption = document.createElement('figcaption'); + figcaption.innerText = img.getAttribute('alt')!; + figure.appendChild(figcaption); } } - public static createGallery(container: HTMLElement) { - /// The process of wrapping image with figure tag is done using JavaScript instead of only Hugo markdown render hook - /// because it can not detect whether image is being wrapped by a link or not - /// and it lead to a invalid HTML construction (
) + const figuresEl = container.querySelectorAll('figure.gallery-image') as NodeListOf; - const images = container.querySelectorAll('img.gallery-image'); - for (const img of Array.from(images)) { - /// Images are wrapped with figure tag if the paragraph has only images without texts - /// This is done to allow inline images within paragraphs - const paragraph = img.closest('p'); + let currentGallery: HTMLElement[] = []; - if (!paragraph || !container.contains(paragraph)) continue; - - if (paragraph.textContent.trim() == '') { - /// Once we insert figcaption, this check no longer works - /// So we add a class to paragraph to mark it - paragraph.classList.add('no-text'); - } - - let isNewLineImage = paragraph.classList.contains('no-text'); - if (!isNewLineImage) continue; - - const hasLink = img.parentElement.tagName == 'A'; - - let el: HTMLElement = img; - /// Wrap image with figure tag, with flex-grow and flex-basis values extracted from img's data attributes - const figure = document.createElement('figure'); - figure.style.setProperty('flex-grow', img.getAttribute('data-flex-grow') || '1'); - figure.style.setProperty('flex-basis', img.getAttribute('data-flex-basis') || '0'); - if (hasLink) { - /// Wrap if it exists - el = img.parentElement; - } - el.parentElement.insertBefore(figure, el); - figure.appendChild(el); - - /// Add figcaption if it exists - if (img.hasAttribute('alt')) { - const figcaption = document.createElement('figcaption'); - figcaption.innerText = img.getAttribute('alt'); - figure.appendChild(figcaption); - } - - /// Wrap img tag with tag if image was not wrapped by tag - if (!hasLink) { - figure.className = 'gallery-image'; - - const a = document.createElement('a'); - a.href = img.src; - a.setAttribute('target', '_blank'); - img.parentNode.insertBefore(a, img); - a.appendChild(img); - } + for (const figure of Array.from(figuresEl)) { + if (!currentGallery.length) { + /// First iteration + currentGallery = [figure]; } - - const figuresEl = container.querySelectorAll('figure.gallery-image'); - - let currentGallery = []; - - for (const figure of figuresEl) { - if (!currentGallery.length) { - /// First iteration - currentGallery = [figure]; - } - else if (figure.previousElementSibling === currentGallery[currentGallery.length - 1]) { - /// Adjacent figures - currentGallery.push(figure); - } - else if (currentGallery.length) { - /// End gallery - StackGallery.wrap(currentGallery); - currentGallery = [figure]; - } + else if (figure.previousElementSibling === currentGallery[currentGallery.length - 1]) { + /// Adjacent figures + currentGallery.push(figure); } - - if (currentGallery.length > 0) { - StackGallery.wrap(currentGallery); + else if (currentGallery.length) { + /// End gallery + wrap(currentGallery); + currentGallery = [figure]; } } - /** - * Wrap adjacent figure tags with div.gallery - * @param figures - */ - public static wrap(figures: HTMLElement[]) { - const galleryContainer = document.createElement('div'); - galleryContainer.className = 'gallery'; - - const parentNode = figures[0].parentNode, - first = figures[0]; - - parentNode.insertBefore(galleryContainer, first) - - for (const figure of figures) { - galleryContainer.appendChild(figure); - } + if (currentGallery.length > 0) { + wrap(currentGallery); } - - public open(index: number) { - const pswp = document.querySelector('.pswp') as HTMLDivElement; - const ps = new window.PhotoSwipe(pswp, window.PhotoSwipeUI_Default, this.items, { - index: index, - galleryUID: this.galleryUID, - getThumbBoundsFn: (index) => { - const thumbnail = this.items[index].el.getElementsByTagName('img')[0], - pageYScroll = window.pageYOffset || document.documentElement.scrollTop, - rect = thumbnail.getBoundingClientRect(); - - return { x: rect.left, y: rect.top + pageYScroll, w: rect.width }; - } - }); - - ps.init(); - } - - private bindClick() { - for (const [index, item] of this.items.entries()) { - const a = item.el.querySelector('a'); - - a.addEventListener('click', (e) => { - e.preventDefault(); - this.open(index); - }) - } - } -} - -export default StackGallery; \ No newline at end of file +}; \ No newline at end of file diff --git a/assets/ts/main.ts b/assets/ts/main.ts index f3160ae..16dea22 100644 --- a/assets/ts/main.ts +++ b/assets/ts/main.ts @@ -5,13 +5,12 @@ * @website: https://jimmycai.com * @link: https://github.com/CaiJimmy/hugo-theme-stack */ -import StackGallery from "ts/gallery"; -import { getColor } from 'ts/color'; -import menu from 'ts/menu'; -import createElement from 'ts/createElement'; -import StackColorScheme from 'ts/colorScheme'; -import { setupScrollspy } from 'ts/scrollspy'; -import { setupSmoothAnchors } from "ts/smoothAnchors"; +import { getColor } from './color'; +import menu from './menu'; +import createElement from './createElement'; +import StackColorScheme from './colorScheme'; +import { setupScrollspy } from './scrollspy'; +import { setupSmoothAnchors } from './smoothAnchors'; let Stack = { init: () => { @@ -22,7 +21,6 @@ let Stack = { const articleContent = document.querySelector('.article-content') as HTMLElement; if (articleContent) { - new StackGallery(articleContent); setupSmoothAnchors(); setupScrollspy(); } @@ -91,7 +89,7 @@ let Stack = { }); }); - new StackColorScheme(document.getElementById('dark-mode-toggle')); + new StackColorScheme(document.getElementById('dark-mode-toggle')!); } } diff --git a/data/external.toml b/data/external.toml new file mode 100644 index 0000000..2475b71 --- /dev/null +++ b/data/external.toml @@ -0,0 +1,19 @@ +Vibrant = [ + { src = "https://cdn.jsdelivr.net/npm/node-vibrant@3.1.6/dist/vibrant.min.js", integrity = "sha256-awcR2jno4kI5X0zL8ex0vi2z+KMkF24hUW8WePSA9HM=", type = "script" }, +] + +KaTeX = [ + { src = "https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css", integrity = "sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV", type = "style" }, + { src = "https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js", integrity = "sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8", type = "script", defer = true }, + { src = "https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js", integrity = "sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05", type = "script", defer = true }, +] + +Cactus = [ + { src = "https://latest.cactus.chat/cactus.js", type = "script" }, + { src = "https://latest.cactus.chat/style.css", type = "style" }, +] + +[PhotoSwipe] + Style = "https://cdn.jsdelivr.net/npm/photoswipe@5.4.4/dist/photoswipe.css" + Core = "https://cdn.jsdelivr.net/npm/photoswipe@5.4.4/dist/photoswipe.esm.min.js" + Lightbox = "https://cdn.jsdelivr.net/npm/photoswipe@5.4.4/dist/photoswipe-lightbox.esm.min.js" diff --git a/data/external.yaml b/data/external.yaml deleted file mode 100644 index 4fc0bca..0000000 --- a/data/external.yaml +++ /dev/null @@ -1,44 +0,0 @@ -Vibrant: - - src: https://cdn.jsdelivr.net/npm/node-vibrant@3.1.6/dist/vibrant.min.js - integrity: sha256-awcR2jno4kI5X0zL8ex0vi2z+KMkF24hUW8WePSA9HM= - type: script - -PhotoSwipe: - - src: https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js - integrity: sha256-ePwmChbbvXbsO02lbM3HoHbSHTHFAeChekF1xKJdleo= - type: script - defer: true - - - src: https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js - integrity: sha256-UKkzOn/w1mBxRmLLGrSeyB4e1xbrp4xylgAWb3M42pU= - type: script - defer: true - - - src: https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css - type: style - - - src: https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css - type: style - -KaTeX: - - src: https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css - integrity: sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV - type: style - - - src: https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js - integrity: sha384-XjKyOOlGwcjNTAIQHIpgOno0Hl1YQqzUOEleOLALmuqehneUG+vnGctmUb0ZY0l8 - type: script - defer: true - - - src: https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js - integrity: sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05 - type: script - defer: true - -Cactus: - - src: https://latest.cactus.chat/cactus.js - integrity: - type: script - - src: https://latest.cactus.chat/style.css - integrity: - type: style diff --git a/layouts/_partials/article/components/photoswipe.html b/layouts/_partials/article/components/photoswipe.html index c33ff49..475a4d0 100644 --- a/layouts/_partials/article/components/photoswipe.html +++ b/layouts/_partials/article/components/photoswipe.html @@ -1,68 +1,32 @@ - -