diff --git a/_config.yml b/_config.yml index 8316d81..0f70126 100644 --- a/_config.yml +++ b/_config.yml @@ -158,7 +158,7 @@ subtitle: # Choose: false/1/2/3 # false - disable the function # 1 - hitokoto.cn - # 2 - yijuzhan.com + # 2 - https://api.aa1.cn/doc/yiyan.html # 3 - jinrishici.com source: false # If you close the typewriter effect, the subtitle will only show the first line of sub diff --git a/layout/includes/third-party/abcjs/abcjs.pug b/layout/includes/third-party/abcjs/abcjs.pug index 453f84b..9de2b97 100644 --- a/layout/includes/third-party/abcjs/abcjs.pug +++ b/layout/includes/third-party/abcjs/abcjs.pug @@ -1,17 +1,46 @@ script. - (() => { - const abcjsInit = () => { - const abcjsFn = () => setTimeout(() => { - document.querySelectorAll(".abc-music-sheet").forEach(ele => { - if (ele.children.length > 0) return - ABCJS.renderAbc(ele, ele.innerHTML, {responsive: 'resize'}) - }) - }, 100) - - typeof ABCJS === 'object' ? abcjsFn() - : btf.getScript('!{url_for(theme.asset.abcjs_basic_js)}').then(abcjsFn) + (function() { + const abcjsInit = function() { + const abcjsFn = function() { + setTimeout(function() { + const sheets = document.querySelectorAll(".abc-music-sheet") + for (let i = 0; i < sheets.length; i++) { + const ele = sheets[i] + if (ele.children.length > 0) continue + + // Parse parameters from data-params attribute + let params = {} + const dp = ele.getAttribute("data-params") + if (dp) { + try { + params = JSON.parse(dp) + } catch (e) { + console.error("Failed to parse data-params:", e) + } + } + + // Merge parsed parameters with the responsive option + // Ensures params content appears before responsive + const options = { ...params, responsive: "resize" } + + // Render the music score using ABCJS.renderAbc + ABCJS.renderAbc(ele, ele.innerHTML, options) + } + }, 100) + } + + if (typeof ABCJS === "object") { + abcjsFn() + } else { + btf.getScript("!{url_for(theme.asset.abcjs_basic_js)}").then(abcjsFn) + } } - window.pjax ? abcjsInit() : window.addEventListener('load', abcjsInit) - btf.addGlobalFn('encrypt', abcjsInit, 'abcjs') - })() \ No newline at end of file + if (window.pjax) { + abcjsInit() + } else { + window.addEventListener("load", abcjsInit) + } + + btf.addGlobalFn("encrypt", abcjsInit, "abcjs") + })() diff --git a/layout/includes/third-party/pjax.pug b/layout/includes/third-party/pjax.pug index a8094f1..94ec038 100644 --- a/layout/includes/third-party/pjax.pug +++ b/layout/includes/third-party/pjax.pug @@ -59,7 +59,10 @@ script. document.addEventListener('pjax:error', e => { if (e.request.status === 404) { - window.location.href = e.request.responseURL + const usePjax = !{theme.pjax && theme.pjax.enable} + !{theme.error_404 && theme.error_404.enable} + ? (usePjax ? pjax.loadUrl('!{url_for("/404.html")}') : window.location.href = '!{url_for("/404.html")}') + : window.location.href = e.request.responseURL } }) - })() \ No newline at end of file + })() diff --git a/layout/includes/third-party/subtitle.pug b/layout/includes/third-party/subtitle.pug index 3969604..0d0c523 100644 --- a/layout/includes/third-party/subtitle.pug +++ b/layout/includes/third-party/subtitle.pug @@ -1,4 +1,4 @@ -- const { effect,source,sub,typed_option } = theme.subtitle +- const { effect, source, sub, typed_option } = theme.subtitle - let subContent = sub || new Array() script. @@ -22,6 +22,26 @@ script. } else { subtitleType() } + }, + processSubtitle: (content, extraContents = []) => { + if (!{effect}) { + const sub = !{JSON.stringify(subContent)}.slice() + + if (extraContents.length > 0) { + sub.unshift(...extraContents) + } + + if (typeof content === 'string') { + sub.unshift(content) + } else if (Array.isArray(content)) { + sub.unshift(...content) + } + + sub.length > 0 && typedJSFn.init(sub) + } else { + document.getElementById('subtitle').textContent = typeof content === 'string' ? content : + (Array.isArray(content) && content.length > 0 ? content[0] : '') + } } } btf.addGlobalFn('pjaxSendOnce', () => { typed.destroy() }, 'typedDestroy') @@ -33,14 +53,12 @@ case source fetch('https://v1.hitokoto.cn') .then(response => response.json()) .then(data => { - if (!{effect}) { - const from = '出自 ' + data.from - const sub = !{JSON.stringify(subContent)} - sub.unshift(data.hitokoto, from) - typedJSFn.init(sub) - } else { - document.getElementById('subtitle').textContent = data.hitokoto - } + const from = '出自 ' + data.from + typedJSFn.processSubtitle(data.hitokoto, [from]) + }) + .catch(err => { + console.error('Failed to get the Hitokoto API:', err) + typedJSFn.processSubtitle(!{JSON.stringify(subContent)}) }) } typedJSFn.run(subtitleType) @@ -48,46 +66,48 @@ case source when 2 script. function subtitleType () { - btf.getScript('https://yijuzhan.com/api/word.php?m=js').then(() => { - const con = str[0] - if (!{effect}) { - const from = '出自 ' + str[1] - const sub = !{JSON.stringify(subContent)} - sub.unshift(con, from) - typedJSFn.init(sub) - } else { - document.getElementById('subtitle').textContent = con - } - }) + fetch('https://v.api.aa1.cn/api/yiyan/index.php') + .then(response => response.text()) + .then(data => { + const reg = /

(.*?)<\/p>/g + const result = reg.exec(data) + if (result && result[1]) { + typedJSFn.processSubtitle(result[1]) + } else { + throw new Error('Failed to parse the return value of the Yiyan API') + } + }) + .catch(err => { + console.error('Failed to get the Yiyan API:', err) + typedJSFn.processSubtitle(!{JSON.stringify(subContent.length)}) + }) } typedJSFn.run(subtitleType) when 3 script. function subtitleType () { - btf.getScript('https://sdk.jinrishici.com/v2/browser/jinrishici.js').then(() => { - jinrishici.load(result =>{ - if (!{effect}) { - const sub = !{JSON.stringify(subContent)} - const content = result.data.content - sub.unshift(content) - typedJSFn.init(sub) - } else { - document.getElementById('subtitle').textContent = result.data.content - } + btf.getScript('https://sdk.jinrishi8ci.com/v2/browser/jinrishici.js') + .then(() => { + jinrishici.load(result => { + if (result && result.data && result.data.content) { + typedJSFn.processSubtitle(result.data.content) + } else { + throw new Error('Failed to parse the return value of Jinrishici API') + } + }) + }) + .catch(err => { + console.error('Failed to get the Jinrishici API:', err) + typedJSFn.processSubtitle(!{JSON.stringify(subContent.length)}) }) - }) } typedJSFn.run(subtitleType) default - - subContent = subContent.length ? subContent : new Array(config.subtitle) - script. - function subtitleType () { - if (!{effect}) { - typedJSFn.init(!{JSON.stringify(subContent)}) - } else { - document.getElementById("subtitle").textContent = !{JSON.stringify(subContent[0])} + if subContent.length > 0 + script. + function subtitleType () { + typedJSFn.processSubtitle(!{JSON.stringify(subContent)}) } - } - typedJSFn.run(subtitleType) \ No newline at end of file + typedJSFn.run(subtitleType) \ No newline at end of file diff --git a/package.json b/package.json index 27543bf..4db56e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hexo-theme-butterfly", - "version": "5.3.3", + "version": "5.3.4", "description": "A Simple and Card UI Design theme for Hexo", "main": "package.json", "scripts": { diff --git a/plugins.yml b/plugins.yml index dd0e9d7..c79ad44 100644 --- a/plugins.yml +++ b/plugins.yml @@ -9,7 +9,7 @@ activate_power_mode: algolia_search: name: algoliasearch file: dist/lite/builds/browser.umd.js - version: 5.20.2 + version: 5.20.3 aplayer_css: name: aplayer file: dist/APlayer.min.css @@ -45,7 +45,7 @@ canvas_ribbon: chartjs: name: chart.js file: dist/chart.umd.js - version: 4.4.7 + version: 4.4.8 clickShowText: name: butterfly-extsrc file: dist/click-show-text.min.js @@ -66,12 +66,12 @@ docsearch_css: name: '@docsearch/css' other_name: docsearch-css file: dist/style.css - version: 3.8.3 + version: 3.9.0 docsearch_js: name: '@docsearch/js' other_name: docsearch-js file: dist/umd/index.js - version: 3.8.3 + version: 3.9.0 egjs_infinitegrid: name: '@egjs/infinitegrid' other_name: egjs-infinitegrid @@ -203,9 +203,9 @@ waline_css: name: '@waline/client' file: dist/waline.css other_name: waline - version: 3.5.2 + version: 3.5.5 waline_js: name: '@waline/client' file: dist/waline.js other_name: waline - version: 3.5.2 + version: 3.5.5 diff --git a/scripts/helpers/inject_head_js.js b/scripts/helpers/inject_head_js.js index 5598674..16e9b9a 100644 --- a/scripts/helpers/inject_head_js.js +++ b/scripts/helpers/inject_head_js.js @@ -89,7 +89,7 @@ hexo.extend.helper.register('inject_head_js', function () { darkmodeJs += ` const mediaQueryDark = window.matchMedia('(prefers-color-scheme: dark)') const mediaQueryLight = window.matchMedia('(prefers-color-scheme: light)') - + if (theme === undefined) { if (mediaQueryLight.matches) activateLightMode() else if (mediaQueryDark.matches) activateDarkMode() diff --git a/scripts/tag/score.js b/scripts/tag/score.js index dc380a5..df345e5 100644 --- a/scripts/tag/score.js +++ b/scripts/tag/score.js @@ -6,17 +6,45 @@ 'use strict' const score = (args, content) => { + // Escape HTML tags and some special characters, including curly braces const escapeHtmlTags = s => { const lookup = { '&': '&', '"': '"', - '\'': ''', + "'": ''', '<': '<', - '>': '>' + '>': '>', + '{': '{', + '}': '}' } - return s.replace(/[&"'<>]/g, c => lookup[c]) + return s.replace(/[&"'<>{}]/g, c => lookup[c]) } - return `

${escapeHtmlTags(content)}
` + + const trimmed = content.trim() + // Split content using six dashes as a delimiter + const parts = trimmed.split('------') + + if (parts.length < 2) { + // If no delimiter is found, treat the entire content as the score + return `
${escapeHtmlTags(trimmed)}
` + } + + // First part is parameters (JSON string), the rest is the score content + const paramPart = parts[0].trim() + const scorePart = parts.slice(1).join('------').trim() + + let paramsObj = {} + try { + paramsObj = JSON.parse(paramPart) + } catch (e) { + console.error("Failed to parse JSON in score tag:", e) + } + + // Use double quotes for data-params attribute value, + // ensuring JSON internal double quotes are escaped + return `
+ ${escapeHtmlTags(scorePart)} +
` } -hexo.extend.tag.register('score', score, { ends: true }) +hexo.extend.tag.register("score", score, { ends: true }) \ No newline at end of file diff --git a/source/css/_global/index.styl b/source/css/_global/index.styl index 0ddabb0..212f654 100644 --- a/source/css/_global/index.styl +++ b/source/css/_global/index.styl @@ -10,8 +10,8 @@ --preloader-bg: $preloader-bg --preloader-color: $preloader-word-color --tab-border-color: $tab-border-color - --tab-botton-bg: $tab-botton-bg - --tab-botton-color: $tab-botton-color + --tab-button-bg: $tab-button-bg + --tab-button-color: $tab-button-color --tab-button-hover-bg: $tab-button-hover-bg --tab-button-active-bg: $tab-button-active-bg --card-bg: $card-bg diff --git a/source/css/_mode/darkmode.styl b/source/css/_mode/darkmode.styl index ef397cc..bcd5334 100644 --- a/source/css/_mode/darkmode.styl +++ b/source/css/_mode/darkmode.styl @@ -10,8 +10,8 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark' --preloader-bg: darken(#121212, 2) --preloader-color: alpha(#FFFFFF, .7) --tab-border-color: #2c2c2c - --tab-botton-bg: #2c2c2c - --tab-botton-color: alpha(#FFFFFF, .7) + --tab-button-bg: #2c2c2c + --tab-button-color: alpha(#FFFFFF, .7) --tab-button-hover-bg: lighten(#121212, 15) --tab-button-active-bg: #121212 --card-bg: #121212 diff --git a/source/css/_tags/tabs.styl b/source/css/_tags/tabs.styl index d57ba59..2eba12d 100644 --- a/source/css/_tags/tabs.styl +++ b/source/css/_tags/tabs.styl @@ -14,14 +14,14 @@ flex-wrap: wrap margin: 0 padding: 0 - background: var(--tab-botton-bg) + background: var(--tab-button-bg) > .tab flex-grow: 1 padding: 8px 18px border-top: 2px solid var(--tab-border-color) - background: var(--tab-botton-bg) - color: var(--tab-botton-color) + background: var(--tab-button-bg) + color: var(--tab-button-color) line-height: 2 transition: all .4s diff --git a/source/css/var.styl b/source/css/var.styl index 479c3b7..fd6ead8 100644 --- a/source/css/var.styl +++ b/source/css/var.styl @@ -14,18 +14,18 @@ $code-background = $themeColorEnable && hexo-config('theme_color.code_background $theme-toc-color = $themeColorEnable && hexo-config('theme_color.toc_color') ? convert(hexo-config('theme_color.toc_color')) : $strong-cyan // font -$chinseFont = $language == 'zh-CN' ? 'Microsoft YaHei' : 'Microsoft JhengHei' -$dafault-font-family = -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Lato, Roboto, 'PingFang SC', $chinseFont, sans-serif -$dafault-code-font = consolas, Menlo, monospace, 'PingFang SC', $chinseFont, sans-serif +$chineseFont = $language == 'zh-CN' ? 'Microsoft YaHei' : 'Microsoft JhengHei' +$default-font-family = -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Lato, Roboto, 'PingFang SC', $chineseFont, sans-serif +$default-code-font = consolas, Menlo, monospace, 'PingFang SC', $chineseFont, sans-serif -$font-family = hexo-config('font.font_family') ? unquote(hexo-config('font.font_family')) : $dafault-font-family -$code-font-family = hexo-config('font.code_font_family') ? unquote(hexo-config('font.code_font_family')) : $dafault-code-font +$font-family = hexo-config('font.font_family') ? unquote(hexo-config('font.font_family')) : $default-font-family +$code-font-family = hexo-config('font.code_font_family') ? unquote(hexo-config('font.code_font_family')) : $default-code-font $site-name-font = hexo-config('blog_title_font.font_family') && unquote(hexo-config('blog_title_font.font_family')) // hr $hrEnable = hexo-config('hr_icon') && hexo-config('hr_icon.enable') $hr-icon = $hrEnable && hexo-config('hr_icon.icon') ? hexo-config('hr_icon.icon') : '\f0c4' $hr-icon-top = $hrEnable && hexo-config('hr_icon.icon_top') ? convert(hexo-config('hr_icon.icon_top')) : -10px -// page beatutify +// page beautify $beautifyEnable = hexo-config('beautify.enable') $title-prefix-icon = $beautifyEnable && hexo-config('beautify.title_prefix_icon') ? hexo-config('beautify.title_prefix_icon') : '\f0c1' $title-prefix-icon-color = $beautifyEnable && hexo-config('beautify.title_prefix_icon_color') ? convert(hexo-config('beautify.title_prefix_icon_color')) : $light-red @@ -175,8 +175,8 @@ $tagsP-purple-color = #6f42c1 $tagsP-green-color = #5cb85c // Tag Plugins - Tab $tab-border-color = #f0f0f0 -$tab-botton-bg = #f0f0f0 -$tab-botton-color = $font-color +$tab-button-bg = #f0f0f0 +$tab-button-color = $font-color $tab-button-hover-bg = darken($tab-border-color, 8) $tab-active-border-color = $theme-color $tab-button-active-bg = $card-bg