diff --git a/layout/includes/page/shuoshuo.pug b/layout/includes/page/shuoshuo.pug index fd93334..de4dbf6 100644 --- a/layout/includes/page/shuoshuo.pug +++ b/layout/includes/page/shuoshuo.pug @@ -161,7 +161,7 @@ container.innerHTML = content window.lazyLoadInstance && window.lazyLoadInstance.update() - btf.loadLightbox(document.querySelectorAll('#article-container img:not(.no-lightbox)')) + document.dispatchEvent(new Event('shuoshuo:rendered')) } const setupNavEvents = (nav) => { diff --git a/package.json b/package.json index f7ee6a9..ec3cdce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hexo-theme-butterfly", - "version": "5.6.1", + "version": "5.6.2", "description": "A Simple and Card UI Design theme for Hexo", "main": "package.json", "scripts": { diff --git a/scripts/helpers/page.js b/scripts/helpers/page.js index a9cf5bb..2fb0ef8 100644 --- a/scripts/helpers/page.js +++ b/scripts/helpers/page.js @@ -157,8 +157,27 @@ hexo.extend.helper.register('shuoshuoFN', (data, page) => { processedData.forEach(item => { const parsed = moment.utc(item.date) item.date = moment.tz(parsed.format('YYYY-MM-DD HH:mm:ss'), timezone).format('YYYY-MM-DD HH:mm:ss') - // markdown + + // Render the content using Hexo's rendering engine to process any tags or markdown + const mockPost = { content: item.content } + hexo.execFilterSync('before_post_render', mockPost, { context: hexo }) + item.content = mockPost.content + + const codeBlocks = [] + item.content = item.content.replace(/([\s\S]*?)<\/hexoPostRenderCodeBlock>/g, (_, c) => { + codeBlocks.push(c) + return `` + }) + + try { + item.content = hexo.extend.tag.env.renderString(item.content, {}) + } catch (e) { + // ignore tag plugin errors, fallback to markdown-only rendering + } + item.content = hexo.render.renderSync({ text: item.content, engine: 'markdown' }) + + item.content = item.content.replace(//g, (_, i) => codeBlocks[+i]) }) return processedData diff --git a/source/js/main.js b/source/js/main.js index 5fc6dca..4cca9aa 100644 --- a/source/js/main.js +++ b/source/js/main.js @@ -267,23 +267,23 @@ document.addEventListener('DOMContentLoaded', () => { const fetchUrl = async url => { try { const response = await fetch(url) - if (!response.ok) throw new Error(`HTTP ${response.status}`) + if (!response.ok) throw new Error(`HTTP ${response.status}`) return await response.json() - } catch (error) { - console.error('Failed to fetch URL:', error) - throw error - } + } catch (error) { + console.error('Failed to fetch URL:', error) + throw error + } } const runJustifiedGallery = (container, data, config) => { - const { isButton, tabs } = config - const limit = Math.max(1, Number(config.limit) || 20) - const firstLimit = Math.max(1, Number(config.firstLimit) || limit) + const { isButton, tabs } = config + const limit = Math.max(1, Number(config.limit) || 20) + const firstLimit = Math.max(1, Number(config.firstLimit) || limit) const dataLength = data.length - const maxGroupKey = dataLength - ? Math.ceil(Math.max(0, dataLength - firstLimit) / limit) + 1 - : 0 + const maxGroupKey = dataLength + ? Math.ceil(Math.max(0, dataLength - firstLimit) / limit) + 1 + : 0 // Gallery configuration const igConfig = { @@ -300,19 +300,19 @@ document.addEventListener('DOMContentLoaded', () => { let isLayoutHidden = false // Utility functions - const sanitizeString = str => String(str ?? '') - .replace(/&/g, '&') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(//g, '>') + const sanitizeString = str => String(str ?? '') + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(/'/g, ''') + .replace(//g, '>') const createImageItem = item => { const alt = item.alt ? `alt="${sanitizeString(item.alt)}"` : '' const title = item.title ? `title="${sanitizeString(item.title)}"` : '' - const url = item.url ? sanitizeString(item.url) : '' + const url = item.url ? sanitizeString(item.url) : '' return `
- +
` } @@ -381,13 +381,13 @@ document.addEventListener('DOMContentLoaded', () => { btf.setLoading.add(container) ig.on('renderComplete', handleRenderComplete) - if (isButton && dataLength) { + if (isButton && dataLength) { appendItems(1, firstLimit, true) - } else if (dataLength) { + } else if (dataLength) { ig.on('requestAppend', handleRequestAppend) ig.renderItems() - } else { - btf.setLoading.remove(container) + } else { + btf.setLoading.remove(container) } btf.addGlobalFn('pjaxSendOnce', () => ig.destroy()) @@ -412,9 +412,9 @@ document.addEventListener('DOMContentLoaded', () => { container.textContent = '' try { const data = element.getAttribute('data-type') === 'url' ? await fetchUrl(content) : JSON.parse(content) - if (!Array.isArray(data)) throw new TypeError('Gallery data must be an array') + if (!Array.isArray(data)) throw new TypeError('Gallery data must be an array') runJustifiedGallery(container, data, config) - element.classList.add('loaded') + element.classList.add('loaded') } catch (error) { console.error('Gallery data parsing failed:', error) } @@ -456,7 +456,7 @@ document.addEventListener('DOMContentLoaded', () => { // 檢查文檔高度是否小於視窗高度 const checkDocumentHeight = () => { - if (document.body.scrollHeight <= window.innerHeight + 56) { + if (document.body.scrollHeight <= window.innerHeight + 56) { $rightside.classList.add('rightside-show') return true } @@ -472,8 +472,8 @@ document.addEventListener('DOMContentLoaded', () => { let flag = '' const scrollTask = btf.rafThrottle(() => { - if (checkDocumentHeight()) return - + if (checkDocumentHeight()) return + const currentTop = window.scrollY || document.documentElement.scrollTop const isDown = scrollDirection(currentTop) if (currentTop > 56) { @@ -501,14 +501,14 @@ document.addEventListener('DOMContentLoaded', () => { $header.classList.remove('nav-fixed', 'nav-visible') } $rightside.classList.remove('rightside-show') - } - - isShowPercent && rightsideScrollPercent(currentTop) - }) - - checkDocumentHeight() - btf.addEventListenerPjax(window, 'scroll', scrollTask, { passive: true }) - } + } + + isShowPercent && rightsideScrollPercent(currentTop) + }) + + checkDocumentHeight() + btf.addEventListenerPjax(window, 'scroll', scrollTask, { passive: true }) + } /** * toc, anchor @@ -995,8 +995,11 @@ document.addEventListener('DOMContentLoaded', () => { GLOBAL_CONFIG_SITE.pageType === 'home' && scrollDownInIndex() scrollFn() - forPostFn() - GLOBAL_CONFIG_SITE.pageType !== 'shuoshuo' && btf.switchComments(document) + if (GLOBAL_CONFIG_SITE.pageType !== 'shuoshuo') { + forPostFn() + btf.switchComments(document) + } + openMobileMenu() } @@ -1012,4 +1015,6 @@ document.addEventListener('DOMContentLoaded', () => { fn() }) }) + + document.addEventListener('shuoshuo:rendered', forPostFn) })