diff --git a/assets/css/_page/_single.scss b/assets/css/_page/_single.scss index c36c5a91..5421be4c 100644 --- a/assets/css/_page/_single.scss +++ b/assets/css/_page/_single.scss @@ -514,6 +514,7 @@ @import '../_partials/_single/alert'; @import '../_partials/_single/code'; + @import '../_partials/_single/diagram-copy-btn'; @import '../_shortcodes'; } diff --git a/assets/css/_partials/_single/_diagram-copy-btn.scss b/assets/css/_partials/_single/_diagram-copy-btn.scss new file mode 100644 index 00000000..9aefb9f5 --- /dev/null +++ b/assets/css/_partials/_single/_diagram-copy-btn.scss @@ -0,0 +1,57 @@ +// Diagram copy button styles +.diagram-copy-btn { + position: absolute; + top: 0.5rem; + right: 0.5rem; + line-height: 1; + padding: 0.5rem; + z-index: 1; + user-select: none; + border: 1px solid; + border-radius: 6px; + color: var(#{$rootPrefix}dcb-color, #25292e); + border-color: var(#{$rootPrefix}dcb-border-color, #d1d9e0); + background-color: var(#{$rootPrefix}dcb-background-color, #f6f8fa); + box-shadow: var(#{$rootPrefix}dcb-box-shadow, 0px 1px 0px 0px #1f23280a); + transition: 80ms cubic-bezier(0.33, 1, 0.68, 1); + transition-property: color, background-color, box-shadow, border-color; + @extend .print-d-none; + + [data-theme='dark'] & { + #{$rootPrefix}dcb-color: #d1d7e0; + #{$rootPrefix}dcb-border-color: #3d444d; + #{$rootPrefix}dcb-background-color: #2a313c; + #{$rootPrefix}dcb-box-shadow: 0px 0px 0px 0px #000000; + } + + &:hover { + #{$rootPrefix}dcb-border-color: #d1d9e0; + #{$rootPrefix}dcb-background-color: #eff2f5; + transition-duration: .1s; + + [data-theme='dark'] & { + #{$rootPrefix}dcb-border-color: #3d444d; + #{$rootPrefix}dcb-background-color: #2f3742; + } + } + + .fa-check { + padding-inline: 1px; + display: none; + } + + &[data-copied] { + .fa-check { + display: inline-block; + } + .fa-clone { + display: none; + } + } +} + +// Diagram containers +.mermaid-container, +.echarts-container { + position: relative; +} diff --git a/assets/js/theme.js b/assets/js/theme.js index 477c7d60..07081e06 100644 --- a/assets/js/theme.js +++ b/assets/js/theme.js @@ -519,6 +519,27 @@ class FixIt { }); } + /** + * init diagram copy button + */ + initDiagramCopyBtn() { + this.util.forEach(document.querySelectorAll('.diagram-copy-btn'), ($btn) => { + $btn.addEventListener('click', () => { + const _tempEl = document.createElement('div'); + _tempEl.appendChild($btn.parentElement.querySelector('template').content.cloneNode(true)); + const code = _tempEl.innerText.trim(); + this.util.copyText(code).then(() => { + $btn.toggleAttribute('data-copied', true); + setTimeout(() => { + $btn.toggleAttribute('data-copied', false); + }, 2000); + }, () => { + console.error('Clipboard write failed!', 'Your browser does not support clipboard API!'); + }); + }, false); + }); + } + initTable(target = document) { this.util.forEach(target.querySelectorAll('.content table'), ($table) => { const $wrapper = document.createElement('div'); @@ -1123,6 +1144,7 @@ class FixIt { this.initDetails(); this.initLightGallery(); this.initCodeWrapper(); + this.initDiagramCopyBtn(); this.initTable(); this.initMermaid(); this.initEcharts(); @@ -1142,6 +1164,7 @@ class FixIt { this.initDetails($content); this.initLightGallery(); this.initCodeWrapper(); + this.initDiagramCopyBtn(); this.initTable($content); this.initMermaid(); this.initEcharts(); @@ -1343,6 +1366,7 @@ class FixIt { this.initDetails(); this.initLightGallery(); this.initCodeWrapper(); + this.initDiagramCopyBtn(); this.initTable(); this.initMermaid(); this.initEcharts(); diff --git a/layouts/_partials/head/link.html b/layouts/_partials/head/link.html index f9e1d0f6..9f389d20 100644 --- a/layouts/_partials/head/link.html +++ b/layouts/_partials/head/link.html @@ -5,6 +5,7 @@ {{- $title = site.Title -}} {{- end -}} +{{/* FIXME)) use relURL for rel permalink */}} {{- if not .Site.Params.app.noFavicon -}} {{- with .Site.Params.app.svgFavicon -}} diff --git a/layouts/_partials/init/index.html b/layouts/_partials/init/index.html index 4c1463f3..b2f5ca7f 100644 --- a/layouts/_partials/init/index.html +++ b/layouts/_partials/init/index.html @@ -1,4 +1,4 @@ -{{- hugo.Store.Set "version" "v0.4.0-alpha-20250813071532-311501ad" -}} +{{- hugo.Store.Set "version" "v0.4.0-alpha-20250813091452-bfafc151" -}} {{- .Store.Set "this" dict -}} {{- partial "init/detection-env.html" . -}} diff --git a/layouts/_partials/plugin/diagram-copy-btn.html b/layouts/_partials/plugin/diagram-copy-btn.html new file mode 100644 index 00000000..6fa1ee65 --- /dev/null +++ b/layouts/_partials/plugin/diagram-copy-btn.html @@ -0,0 +1,9 @@ +{{- /* Diagram copy button */ -}} +{{- $label := .Label | default "Copy Diagram code" -}} +{{- $iconCopy := dict "Class" "fa-regular fa-clone" -}} +{{- $iconCheck := dict "Class" "fa-solid fa-check text-success" -}} + +
+ {{- $iconCopy | partial "plugin/icon.html" -}} + {{- $iconCheck | partial "plugin/icon.html" -}} +
diff --git a/layouts/_partials/plugin/echarts.html b/layouts/_partials/plugin/echarts.html index 0bd9755a..5d51962d 100644 --- a/layouts/_partials/plugin/echarts.html +++ b/layouts/_partials/plugin/echarts.html @@ -1,4 +1,4 @@ -{{- /* Echarts support for code fences extended and shortcodes. */ -}} +{{- /* ECharts support for code fences extended and shortcodes. */ -}} {{- $width := .Options.width | default "100%" -}} {{- $height := .Options.height | default "30rem" -}} {{- $js := .Options.js | default false -}} @@ -6,6 +6,9 @@ {{- $data := .Options.data -}} {{- $file := .Options.file -}} {{- $attrs := printf `style="width: %v; height: %v;"` $width $height -}} + +
+{{- dict "Label" "Copy ECharts code" | partial "plugin/diagram-copy-btn.html" -}}
{{- $content := strings.TrimSpace .Inner -}} {{- if $js | or (hasSuffix $file ".js") -}} @@ -38,3 +41,5 @@ {{- end -}} {{- end -}} +
+{{- /* EOF */ -}} diff --git a/layouts/_partials/plugin/mermaid.html b/layouts/_partials/plugin/mermaid.html index 8f6f2ed6..c45093d1 100644 --- a/layouts/_partials/plugin/mermaid.html +++ b/layouts/_partials/plugin/mermaid.html @@ -1,4 +1,7 @@ {{- /* Mermaid support for code fences extended and shortcodes. */ -}} -
{{ .Inner | safeHTML }}
- +
+ {{- dict "Label" "Copy Mermaid code" | partial "plugin/diagram-copy-btn.html" -}} +
{{ .Inner | safeHTML }}
+ +
{{- /* EOF */ -}}