Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/uPagge/uBlogger.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDillon <dillonzq@outlook.com>2020-04-18 15:54:54 +0300
committerGitHub <noreply@github.com>2020-04-18 15:54:54 +0300
commit8a0e61085cfc2f2d1a342697c73b10cbc1d27a68 (patch)
tree3bce7f15d61648a3b0dce6d43c938acfc74c1895 /src
parent9f37d7bc2a2580b19c211521b68194faecd3e736 (diff)
feat(code): add copy button for code (#239)
Diffstat (limited to 'src')
-rw-r--r--src/js/theme.js86
1 files changed, 53 insertions, 33 deletions
diff --git a/src/js/theme.js b/src/js/theme.js
index 4f17763..781fb45 100644
--- a/src/js/theme.js
+++ b/src/js/theme.js
@@ -1,9 +1,7 @@
class Util {
forEach(elements, handler) {
elements = elements || [];
- for (let i = 0; i < elements.length; i++) {
- handler(elements[i]);
- }
+ for (let i = 0; i < elements.length; i++) handler(elements[i]);
}
getScrollTop() {
@@ -17,6 +15,17 @@ class Util {
isTocStatic() {
return window.matchMedia('only screen and (max-width: 960px)').matches;
}
+
+ animateCSS(element, animation, reserved, callback) {
+ if (!Array.isArray(animation)) animation = [animation];
+ element.classList.add('animated', ...animation);
+ const handler = () => {
+ element.classList.remove('animated', ...animation);
+ element.removeEventListener('animationend', handler);
+ if (typeof callback === 'function') callback();
+ };
+ if (!reserved) element.addEventListener('animationend', handler, false);
+ }
}
class Theme {
@@ -268,10 +277,12 @@ class Theme {
initHighlight() {
this.util.forEach(document.querySelectorAll('.highlight > .chroma'), $chroma => {
- const $codes = $chroma.querySelectorAll('pre.chroma > code');
- const $code = $codes[$codes.length - 1];
- const lang = $code ? $code.className.toLowerCase() : '';
- $chroma.className += ' ' + lang;
+ const $elements = $chroma.querySelectorAll('pre.chroma > code');
+ if ($elements.length) {
+ $chroma.className += ' ' + $elements[$elements.length - 1].className.toLowerCase();
+ $elements[0].classList.add('lnc');
+ $elements[$elements.length - 1].classList.remove('lnc');
+ }
});
this.util.forEach(document.querySelectorAll('.highlight > pre.chroma'), $preChroma => {
const $chroma = document.createElement('div');
@@ -287,6 +298,20 @@ class Theme {
$preChroma.parentElement.replaceChild($chroma, $preChroma);
$td.appendChild($preChroma);
});
+ this.util.forEach(document.querySelectorAll('pre > code'), $code => {
+ $code.classList.add('block');
+ if ($code.classList.contains('lnc') || !this.config.clipboard) return;
+ const $button = document.createElement('div');
+ $button.classList.add('copy-button');
+ $button.innerHTML = '<i class="far fa-copy fa-fw"></i>';
+ $button.setAttribute('data-clipboard-text', $code.innerText);
+ $button.title = this.config.clipboard.title;
+ const clipboard = new ClipboardJS($button);
+ clipboard.on('success', e => {
+ this.util.animateCSS($code, 'flash');
+ });
+ $code.after($button);
+ });
}
initTable() {
@@ -351,8 +376,8 @@ class Theme {
$toc.style.top = `${TOP_SPACING}px`;
}
- this.util.forEach($tocLinkElements, link => { link.classList.remove('active'); });
- this.util.forEach($tocLiElements, link => { link.classList.remove('has-active'); });
+ this.util.forEach($tocLinkElements, $tocLink => { $tocLink.classList.remove('active'); });
+ this.util.forEach($tocLiElements, $tocLi => { $tocLi.classList.remove('has-active'); });
const INDEX_SPACING = 20 + (headerIsFixed ? headerHeight : 0);
let activeTocIndex = $headerLinkElements.length - 1;
for (let i = 0; i < $headerLinkElements.length - 1; i++) {
@@ -386,10 +411,10 @@ class Theme {
const $mermaidElements = document.getElementsByClassName('mermaid');
if ($mermaidElements.length) {
mermaid.initialize({startOnLoad: false, theme: 'null'});
- this.util.forEach($mermaidElements, element => {
- mermaid.mermaidAPI.render('svg-' + element.id, this.contentData[element.id], svgCode => {
- element.innerHTML = svgCode;
- }, element);
+ this.util.forEach($mermaidElements, $mermaid => {
+ mermaid.mermaidAPI.render('svg-' + $mermaid.id, this.contentData[$mermaid.id], svgCode => {
+ $mermaid.innerHTML = svgCode;
+ }, $mermaid);
});
}
}
@@ -401,9 +426,9 @@ class Theme {
this._echartsArr[i].dispose();
}
this._echartsArr = [];
- this.util.forEach(document.getElementsByClassName('echarts'), element => {
- const chart = echarts.init(element, this.isDark ? 'dark' : 'macarons', {renderer: 'svg'});
- chart.setOption(JSON.parse(this.contentData[element.id]));
+ this.util.forEach(document.getElementsByClassName('echarts'), $echarts => {
+ const chart = echarts.init($echarts, this.isDark ? 'dark' : 'macarons', {renderer: 'svg'});
+ chart.setOption(JSON.parse(this.contentData[$echarts.id]));
this._echartsArr.push(chart);
});
});
@@ -422,11 +447,10 @@ class Theme {
mapboxgl.accessToken = this.config.mapbox.accessToken;
mapboxgl.setRTLTextPlugin(this.config.mapbox.RTLTextPlugin);
this._mapboxArr = this._mapboxArr || [];
- this.util.forEach(document.getElementsByClassName('mapbox'), element => {
- const { lng, lat, zoom, lightStyle, darkStyle, marked, navigation, geolocate, scale, fullscreen } = this.contentData[element.id];
- const options = this.contentData[element.id];
+ this.util.forEach(document.getElementsByClassName('mapbox'), $mapbox => {
+ const { lng, lat, zoom, lightStyle, darkStyle, marked, navigation, geolocate, scale, fullscreen } = this.contentData[$mapbox.id];
const mapbox = new mapboxgl.Map({
- container: element,
+ container: $mapbox,
center: [lng, lat],
zoom: zoom,
minZoom: .2,
@@ -459,8 +483,8 @@ class Theme {
});
this._mapboxOnSwitchTheme = this._mapboxOnSwitchTheme || (() => {
this.util.forEach(this._mapboxArr, mapbox => {
- const element = mapbox.getContainer();
- const { lightStyle, darkStyle } = this.contentData[element.id];
+ const $mapbox = mapbox.getContainer();
+ const { lightStyle, darkStyle } = this.contentData[$mapbox.id];
mapbox.setStyle(this.isDark ? darkStyle : lightStyle);
mapbox.addControl(new MapboxLanguage());
});
@@ -516,10 +540,6 @@ class Theme {
const $headers = [];
if (this.config.desktopHeaderMode === 'auto') $headers.push(document.getElementById('header-desktop'));
if (this.config.mobileHeaderMode === 'auto') $headers.push(document.getElementById('header-mobile'));
- this.util.forEach($headers, $header => {
- $header.classList.add('animated');
- $header.classList.add('faster');
- });
if (document.getElementById('comments')) {
const $viewComments = document.getElementById('view-comments');
$viewComments.href = `#comments`;
@@ -530,23 +550,23 @@ class Theme {
window.addEventListener('scroll', () => {
this.newScrollTop = this.util.getScrollTop();
const scroll = this.newScrollTop - this.oldScrollTop;
- this.util.forEach($headers, header => {
+ this.util.forEach($headers, $header => {
if (scroll > MIN_SCROLL) {
- header.classList.remove('fadeInDown');
- header.classList.add('fadeOutUp');
+ $header.classList.remove('fadeInDown');
+ this.util.animateCSS($header, ['fadeOutUp', 'faster'], true);
} else if (scroll < - MIN_SCROLL) {
- header.classList.remove('fadeOutUp');
- header.classList.add('fadeInDown');
+ $header.classList.remove('fadeOutUp');
+ this.util.animateCSS($header, ['fadeInDown', 'faster'], true);
}
});
if (this.newScrollTop > MIN_SCROLL) {
if (scroll > MIN_SCROLL) {
$fixedButtons.classList.remove('fadeIn');
- $fixedButtons.classList.add('fadeOut');
+ this.util.animateCSS($fixedButtons, ['fadeOut', 'faster'], true);
} else if (scroll < - MIN_SCROLL) {
$fixedButtons.style.display = 'block';
$fixedButtons.classList.remove('fadeOut');
- $fixedButtons.classList.add('fadeIn');
+ this.util.animateCSS($fixedButtons, ['fadeIn', 'faster'], true);
}
} else {
$fixedButtons.style.display = 'none';