Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加對 ChartJS 雙模式的支持 #1575

Merged
merged 2 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ npm i hexo-theme-butterfly
- [x] Busuanzi visitor counter
- [x] Medium Zoom/Fancybox
- [x] Mermaid
- [x] Chart.js
- [x] Justified Gallery
- [x] Lazyload images
- [x] Instantpage/Pangu/Snackbar notification toast/PWA......
Expand Down
1 change: 1 addition & 0 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ theme: butterfly
- [x] 不蒜子訪問統計
- [x] 兩種大圖模式(Medium Zoom/Fancybox)
- [x] Mermaid 圖表顯示
- [x] Chart.js 圖表顯示
- [x] 照片牆
- [x] 圖片懶加載
- [x] Instantpage/Pangu/Snackbar彈窗/PWA......
Expand Down
22 changes: 21 additions & 1 deletion _config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ facebook_comments:
pageSize: 10
# Choose: social / time / reverse_time
order_by: social
lang: zh_TW
lang: en_US

# Twikoo
# https://github.com/imaegoo/twikoo
Expand Down Expand Up @@ -924,6 +924,25 @@ mermaid:
light: default
dark: dark

# chartjs
# see https://www.chartjs.org/docs/latest/
chartjs:
enable: false
# Do not modify unless you understand how they work.
# The default settings are only used when the MD syntax is not specified.
# General font color for the chart
fontColor:
light: "rgba(0, 0, 0, 0.8)"
dark: "rgba(255, 255, 255, 0.8)"
# General border color for the chart
borderColor:
light: "rgba(0, 0, 0, 0.1)"
dark: "rgba(255, 255, 255, 0.2)"
# Background color for scale labels on radar and polar area charts
scale_ticks_backdropColor:
light: "transparent"
dark: "transparent"

# Note - Bootstrap Callout
note:
# Note tag style values:
Expand Down Expand Up @@ -1050,6 +1069,7 @@ CDN:
# canvas_fluttering_ribbon:
# canvas_nest:
# canvas_ribbon:
# chartjs:
# click_heart:
# clickShowText:
# disqusjs:
Expand Down
91 changes: 91 additions & 0 deletions layout/includes/third-party/math/chartjs.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
- const { fontColor, borderColor, scale_ticks_backdropColor } = theme.chartjs

script.
(() => {
const $chartjs = document.querySelectorAll('#article-container .chartjs-container')
if ($chartjs.length === 0) return

const applyThemeDefaultsConfig = theme => {
if (theme === 'dark-mode') {
Chart.defaults.color = "!{fontColor.dark}"
Chart.defaults.borderColor = "!{borderColor.dark}"
Chart.defaults.scale.ticks.backdropColor = "!{scale_ticks_backdropColor.dark}"
} else {
Chart.defaults.color = "!{fontColor.light}"
Chart.defaults.borderColor = "!{borderColor.light}"
Chart.defaults.scale.ticks.backdropColor = "!{scale_ticks_backdropColor.light}"
}
}

// Recursively traverse the config object and automatically apply theme-specific color schemes
const applyThemeConfig = (obj, theme) => {
if (typeof obj !== 'object' || obj === null) return

Object.keys(obj).forEach(key => {
const value = obj[key]
// If the property is an object and has theme-specific options, apply them
if (typeof value === 'object' && value !== null) {
if (value[theme]) {
obj[key] = value[theme] // Apply the value for the current theme
} else {
// Recursively process child objects
applyThemeConfig(value, theme)
}
}
})
}

const runChartJS = () => {
window.loadChartJS = true

Array.from($chartjs).forEach((item, index) => {
const chartSrc = item.firstElementChild
const chartID = item.getAttribute('data-chartjs-id') || ('chartjs-' + index) // Use custom ID or default ID
const width = item.getAttribute('data-width')
const existingCanvas = document.getElementById(chartID)

// If a canvas already exists, remove it to avoid rendering duplicates
if (existingCanvas) {
existingCanvas.parentNode.remove()
}

const chartDefinition = chartSrc.textContent
const canvas = document.createElement('canvas')
canvas.id = chartID

const div = document.createElement('div')
div.className = 'chartjs-wrap'

if (width) {
div.style.width = width
}

div.appendChild(canvas)
chartSrc.insertAdjacentElement('afterend', div)

const ctx = document.getElementById(chartID).getContext('2d')

const config = JSON.parse(chartDefinition)

const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark-mode' : 'light-mode'

// Set default styles (initial setup)
applyThemeDefaultsConfig(theme)

// Automatically traverse the config and apply dual-mode color schemes
applyThemeConfig(config, theme)

new Chart(ctx, config)
})
}

const loadChartJS = () => {
window.loadChartJS ? runChartJS() : btf.getScript('!{url_for(theme.asset.chartjs)}').then(runChartJS)
}

// Listen for theme change events
btf.addGlobalFn('themeChange', runChartJS, 'chartjs')
btf.addGlobalFn('encrypt', runChartJS, 'chartjs')

window.pjax ? loadChartJS() : document.addEventListener('DOMContentLoaded', loadChartJS)
})()
5 changes: 4 additions & 1 deletion layout/includes/third-party/math/index.pug
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ case theme.math.use
include ./katex.pug

if theme.mermaid.enable
include ./mermaid.pug
include ./mermaid.pug

if theme.chartjs.enable
include ./chartjs.pug
4 changes: 4 additions & 0 deletions plugins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ canvas_ribbon:
name: butterfly-extsrc
file: dist/canvas-ribbon.min.js
version: 1.1.4
chartjs:
name: chart.js
file: dist/chart.umd.min.js
version: 4.4.4
clickShowText:
name: butterfly-extsrc
file: dist/click-show-text.min.js
Expand Down
17 changes: 16 additions & 1 deletion scripts/events/merge_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ hexo.extend.filter.register('before_generate', () => {
user_id: null,
pageSize: 10,
order_by: 'social',
lang: 'zh_TW'
lang: 'en_US'
},
twikoo: {
envId: null,
Expand Down Expand Up @@ -512,6 +512,21 @@ hexo.extend.filter.register('before_generate', () => {
dark: 'dark'
}
},
chartjs: {
enable: false,
fontColor: {
light: 'rgba(0, 0, 0, 0.8)',
dark: 'rgba(255, 255, 255, 0.8)'
},
borderColor: {
light: 'rgba(0, 0, 0, 0.1)',
dark: 'rgba(255, 255, 255, 0.2)'
},
scale_ticks_backdropColor: {
light: 'transparent',
dark: 'transparent'
}
},
note: {
style: 'flat',
icons: true,
Expand Down
49 changes: 49 additions & 0 deletions scripts/tag/chartjs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Butterfly
* chartjs
* https://www.chartjs.org/
* {% chartjs [width, abreast, chartId] %}
* <!-- chart -->
* <!-- endchart -->
* <!-- desc -->
* <!-- enddesc -->
* {% endchartjs %}
*/

'use strict'

const { escapeHTML } = require('hexo-util')

const chartjs = (args, content) => {
if (!content) return

const chartRegex = /<!--\s*chart\s*-->\n([\w\W\s\S]*?)<!--\s*endchart\s*-->/
const descRegex = /<!--\s*desc\s*-->\n([\w\W\s\S]*?)<!--\s*enddesc\s*-->/
const selfConfig = args.join(' ').trim()

const [width = '', layout = false, chartId = ''] = selfConfig.split(',').map(s => s.trim())

const chartMatch = content.match(chartRegex)
const descMatch = content.match(descRegex)

if (!chartMatch) {
hexo.log.warn('chartjs tag: chart content is required!')
return
}

const chartConfig = chartMatch && chartMatch[1] ? chartMatch[1] : ''
const descContent = descMatch && descMatch[1] ? descMatch[1] : ''

const renderedDesc = descContent ? hexo.render.renderSync({ text: descContent, engine: 'markdown' }).trim() : ''

const descDOM = renderedDesc ? `<div class="chartjs-desc">${renderedDesc}</div>` : ''
const abreastClass = layout ? ' chartjs-abreast' : ''
const widthStyle = width ? `data-width="${width}%"` : ''

return `<div class="chartjs-container${abreastClass}" data-chartjs-id="${chartId}" ${widthStyle}>
<pre class="chartjs-src" hidden>${escapeHTML(chartConfig)}</pre>
${descDOM}
</div>`
}

hexo.extend.tag.register('chartjs', chartjs, { ends: true })
26 changes: 26 additions & 0 deletions source/css/_layout/third-party.styl
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,32 @@ if hexo-config('mermaid.enable')
pre > code.mermaid
display: none

if hexo-config('chartjs.enable')
.chartjs-container
display: flex
flex-direction: column
justify-content: center
align-items: center
margin: 0 0 20px
text-align: center
gap: 20px

+maxWidth600()
.chartjs-wrap
width: 100% !important

&.chartjs-abreast
flex-direction: row

+maxWidth600()
flex-direction: column

.chartjs-wrap
width: -webkit-fill-available

canvas
display: inline-block !important

.utterances,
.fb-comments iframe
width: 100% !important
Expand Down