Merge branch 'feature/copy-snippet' (resolve #396, close #400)

This commit is contained in:
Cotes Chung 2021-09-11 00:33:02 +08:00
commit aadda0347c
11 changed files with 133 additions and 77 deletions

View file

@ -14,7 +14,7 @@
{% if page.layout == 'post' or page.layout == 'page' %} {% if page.layout == 'post' or page.layout == 'page' %}
<!-- image lazy-loading & popup --> <!-- image lazy-loading & popup -->
<script src="https://cdn.jsdelivr.net/combine/npm/lozad/dist/lozad.min.js,npm/magnific-popup@1/dist/jquery.magnific-popup.min.js"></script> <script src="https://cdn.jsdelivr.net/combine/npm/lozad/dist/lozad.min.js,npm/magnific-popup@1/dist/jquery.magnific-popup.min.js,npm/clipboard@2/dist/clipboard.min.js"></script>
{% endif %} {% endif %}
{% if page.layout == 'home' {% if page.layout == 'home'

View file

@ -102,7 +102,7 @@
{% endif %} {% endif %}
<!-- Add lang-badge for code snippets --> <!-- Add header for code snippets -->
{% if _content contains '<div class="language-' %} {% if _content contains '<div class="language-' %}
{% assign _code_splits = _content | split: '<div class="language-' %} {% assign _code_splits = _content | split: '<div class="language-' %}
@ -113,8 +113,13 @@
{% assign _new_content = _snippet %} {% assign _new_content = _snippet %}
{% else %} {% else %}
{% assign _lang = _snippet | split: ' ' | first %} {% assign _lang = _snippet | split: ' ' | first %}
{% capture _tag_head %}<div lang="{{_lang}}" class="language-{% endcapture %} {% capture _tag_head %}<div class="language-{% endcapture %}
{% assign _new_content = _new_content | append: _tag_head | append: _snippet %} {% assign _replacement = '-rouge"><div class="code-header" data-lang="'
| append: _lang
| append: '"><button><i class="fa-fw far fa-clipboard"></i></button></div><div class="highlight">'
%}
{% capture _tag_tail %}{{ _snippet | replace: '-rouge"><div class="highlight">', _replacement }}{% endcapture %}
{% assign _new_content = _new_content | append: _tag_head | append: _tag_tail %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}

View file

@ -0,0 +1,40 @@
/*
* Initial the clipboard.js object, see: <https://github.com/zenorocha/clipboard.js>
*
* Dependencies:
* - popper.js (https://github.com/popperjs/popper-core)
* - clipboard.js (https://github.com/zenorocha/clipboard.js)
*/
$(function() {
const btnSelector = '.code-header>button';
var clipboard = new ClipboardJS(btnSelector, {
target(trigger) {
return trigger.parentNode.nextElementSibling;
}
});
function setTooltip(btn, msg) {
$(btn).tooltip('hide')
.attr('data-original-title', msg)
.tooltip('show');
}
function hideTooltip(btn) {
setTimeout(function() {
$(btn).tooltip('hide');
}, 1000);
}
$(btnSelector).tooltip({
trigger: 'click',
placement: 'left'
});
clipboard.on('success', function(e) {
e.clearSelection();
setTooltip(e.trigger, 'Copied!');
hideTooltip(e.trigger);
});
});

View file

@ -1,22 +0,0 @@
/*
* Copy current page url to clipboard.
*/
function copyLink(url, msg) {
if (!url || 0 === url.length) {
url = window.location.href;
}
const $temp = $("<input>");
$("body").append($temp);
$temp.val(url).select();
document.execCommand("copy");
$temp.remove();
let feedback = "Link copied successfully!";
if (msg && msg.length > 0) {
feedback = msg;
}
alert(feedback);
}

View file

@ -27,16 +27,18 @@ html[mode=dark] {
/* -- Codes Snippet -- */ /* -- Codes Snippet -- */
$code-radius: 6px;
%code-snippet-bg { %code-snippet-bg {
background: var(--highlight-bg-color); background: var(--highlight-bg-color);
} }
%code-snippet-radius { %code-snippet-radius {
border-radius: 6px; border-radius: $code-radius;
} }
%code-snippet-padding { %code-snippet-padding {
padding: 1.5rem; padding: 1.2rem;
} }
div > pre { div > pre {
@ -86,12 +88,10 @@ div > pre {
} }
.lineno { .lineno {
margin-left: 0.2rem;
padding-right: 0.5rem; padding-right: 0.5rem;
min-width: 2.2rem; min-width: 2.2rem;
text-align: right; text-align: right;
color: var(--highlight-lineno-color); color: var(--highlight-lineno-color);
border-right: 1px solid var(--highlight-lineno-border-color);
-webkit-user-select: none; -webkit-user-select: none;
-khtml-user-select: none; -khtml-user-select: none;
-moz-user-select: none; -moz-user-select: none;
@ -135,7 +135,7 @@ code {
} }
td.rouge-code { td.rouge-code {
padding: 1.5rem 1.5rem 1.5rem 1rem; padding: 1.2rem 1.5rem 1.2rem 1rem;
// Prevent some browser extends from // Prevent some browser extends from
// changing the URL string of code block. // changing the URL string of code block.
@ -162,25 +162,64 @@ div {
} }
} }
div[class^='language-']::before { .code-header {
content: attr(lang); background: var(--code-header-bg);
position: absolute; border-top-left-radius: $code-radius;
right: 2rem; border-top-right-radius: $code-radius;
margin-top: 3px; display: flex;
font-size: 0.7rem; justify-content: space-between;
font-weight: 600; align-items: center;
color: var(--highlight-lineno-color); line-height: 1.85rem;
text-transform: uppercase;
// language badge
&::before {
content: attr(data-lang);
color: var(--lang-badge-color);
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
padding-left: 1em;
}
// clipboard
button {
border: 0;
background-color: inherit;
border-top-right-radius: $code-radius;
color: var(--highlight-lineno-color);
&:hover {
background-color: gray;
color: white;
}
&:focus {
outline: none;
}
i {
font-size: 85%;
}
}
} }
@media (min-width: 768px) { @media all and (max-width: 576px) {
div[class^='language-']::before { .post-content {
right: 3.1rem; > div[class^='language-'] {
} @include ml-mr(-1.25rem);
}
@media (min-width: 1650px) { border-radius: 0;
div[class^='language-']::before {
right: 3.5rem; .code-header {
border-radius: 0;
padding-left: 0.4rem;
button {
border-top-right-radius: 0;
}
}
}
} }
} }

View file

@ -3,20 +3,6 @@
*/ */
@mixin dark-syntax { @mixin dark-syntax {
/* ----- My styles ------ */
--highlight-bg-color: #252525;
--highlighter-rouge-color: #de6b18;
--highlight-lineno-color: #6c6c6d;
--highlight-lineno-border-color: #303435;
--inline-code-bg: #272822;
.highlight {
.gp { color: #818c96; }
}
pre { color: #bfbfbf; } /* override Bootstrap */
kbd { background-color: black; }
/* syntax highlight colors from https://raw.githubusercontent.com/jwarby/pygments-css/master/monokai.css */ /* syntax highlight colors from https://raw.githubusercontent.com/jwarby/pygments-css/master/monokai.css */
.highlight pre { background-color: var(--highlight-bg-color); } .highlight pre { background-color: var(--highlight-bg-color); }
.highlight .hll { background-color: var(--highlight-bg-color); } .highlight .hll { background-color: var(--highlight-bg-color); }
@ -81,4 +67,20 @@
.highlight .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */ .highlight .gu { color: #75715e; } /* Generic.Subheading & Diff Unified/Comment? */
.highlight .gd { color: #f92672; background-color: #561c08; } /* Generic.Deleted & Diff Deleted */ .highlight .gd { color: #f92672; background-color: #561c08; } /* Generic.Deleted & Diff Deleted */
.highlight .gi { color: #a6e22e; background-color: #0b5858; } /* Generic.Inserted & Diff Inserted */ .highlight .gi { color: #a6e22e; background-color: #0b5858; } /* Generic.Inserted & Diff Inserted */
/* ----- custom styles ------ */
--highlight-bg-color: #252525;
--highlighter-rouge-color: #de6b18;
--highlight-lineno-color: #6c6c6d;
--inline-code-bg: #272822;
--code-header-bg: #353535;
--lang-badge-color: #6c6c6d;
.highlight {
.gp { color: #818c96; }
}
pre { color: #bfbfbf; } /* override Bootstrap */
kbd { background-color: black; }
} }

View file

@ -70,6 +70,8 @@
--highlight-bg-color: #f7f7f7; --highlight-bg-color: #f7f7f7;
--highlighter-rouge-color: #2f2f2f; --highlighter-rouge-color: #2f2f2f;
--highlight-lineno-color: #c2c6cc; --highlight-lineno-color: #c2c6cc;
--highlight-lineno-border-color: #e9ecef;
--inline-code-bg: #f3f3f3; --inline-code-bg: #f3f3f3;
--code-header-bg: #eaeaea;
--lang-badge-color: #a4a7ab;
} // light-syntax } // light-syntax

View file

@ -299,16 +299,6 @@
margin-top: 1rem; margin-top: 1rem;
} }
} }
.post-content > div[class^='language-'] {
@include ml-mr(-1.25rem);
border-radius: 0;
&::before { // the lang badge
right: 1rem;
}
}
} }
@media all and (max-width: 768px) { @media all and (max-width: 768px) {

View file

@ -3,4 +3,4 @@
* © 2019 Cotes Chung * © 2019 Cotes Chung
* MIT Licensed * MIT Licensed
*/ */
function copyLink(e,o){e&&0!==e.length||(e=window.location.href);const t=$("<input>");$("body").append(t),t.val(e).select(),document.execCommand("copy"),t.remove();let s="Link copied successfully!";o&&o.length>0&&(s=o),alert(s)}$(function(){$(window).scroll(()=>{$(this).scrollTop()>50&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){const e=$("#sidebar-trigger"),o=$("#search-trigger"),t=$("#search-cancel"),s=$("#search-cleaner"),a=$("#main"),l=$("#topbar-title"),n=$("#search-wrapper"),i=$("#search-result-wrapper"),c=$("#search-results"),d=$("#search-input"),r=$("#search-hints"),u=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset:()=>e}}(),p={on(){e.addClass("unloaded"),l.addClass("unloaded"),o.addClass("unloaded"),n.addClass("d-flex"),t.addClass("loaded")},off(){t.removeClass("loaded"),n.removeClass("d-flex"),e.removeClass("unloaded"),l.removeClass("unloaded"),o.removeClass("unloaded")}},f=function(){let e=!1;return{on(){e||(u.block(),i.removeClass("unloaded"),a.addClass("unloaded"),e=!0)},off(){e&&(c.empty(),r.hasClass("unloaded")&&r.removeClass("unloaded"),i.addClass("unloaded"),s.removeClass("visible"),a.removeClass("unloaded"),u.release(),d.val(""),e=!1)},isVisible:()=>e}}();function h(){return t.hasClass("loaded")}o.click(function(){p.on(),f.on(),d.focus()}),t.click(function(){p.off(),f.off()}),d.focus(function(){n.addClass("input-focus")}),d.focusout(function(){n.removeClass("input-focus")}),d.on("keyup",function(e){8===e.keyCode&&""===d.val()?h()?r.removeClass("unloaded"):f.off():""!==d.val()&&(f.on(),s.hasClass("visible")||s.addClass("visible"),h()&&r.addClass("unloaded"))}),s.on("click",function(){d.val(""),h()?(r.removeClass("unloaded"),c.empty()):f.off(),d.focus(),s.removeClass("visible")})}),$(function(){const e=function(){let e=!1;const o=$("body");return{toggle(){!1===e?o.attr("sidebar-display",""):o.removeAttr("sidebar-display"),e=!e}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const e=$("#topbar-wrapper"),o=$("#toc-wrapper"),t=$(".access"),s=$("#search-input");let a,l=0;const n=5,i=e.outerHeight();$(window).scroll(function(e){$("#topbar-title").is(":hidden")&&(a=!0)}),setInterval(function(){a&&(!function(){var a=$(this).scrollTop();Math.abs(l-a)<=n||(a>l&&a>i?(e.removeClass("topbar-down").addClass("topbar-up"),o.length>0&&o.removeClass("topbar-down"),t.length>0&&t.removeClass("topbar-down"),s.is(":focus")&&s.blur()):a+$(window).height()<$(document).height()&&(e.removeClass("topbar-up").addClass("topbar-down"),o.length>0&&o.addClass("topbar-down"),t.length>0&&t.addClass("topbar-down")),l=a)}(),a=!1)},250)}),$(function(){const e=$("#topbar-title"),o=$("div.post>h1"),t=e.text().trim();let s=o.length>0?o.text().trim():$("h1").text().trim();($("#page-category").length||$("#page-tag").length)&&/\s/.test(s)&&(s=s.replace(/[0-9]/g,"").trim()),$(window).scroll(function(){if($("#post-list").length||o.is(":hidden")||e.is(":hidden")||$("#sidebar.sidebar-expand").length)return!1;$(this).scrollTop()>=95?e.text()!==s&&e.text(s):e.text()!==t&&e.text(t)}),e.click(function(){$("body,html").animate({scrollTop:0},800)})}),$(function(){$("input[type=checkbox]").addClass("unloaded"),$("input[type=checkbox][checked]").before('<i class="fas fa-check-circle checked"></i>'),$("input[type=checkbox]:not([checked])").before('<i class="far fa-circle"></i>')}),$(function(){const e="#main > div.row:first-child > div:first-child";if($(`${e} img`).length<=0)return;const o=document.querySelectorAll(`${e} img[data-src]`);lozad(o).observe(),$(`${e} p > img[data-src],${e} img[data-src].preview-img`).each(function(){let e=$(this).next();const o="EM"===e.prop("tagName")?e.text():"",t=$(this).attr("data-src");$(this).wrap(`<a href="${t}" title="${o}" class="popup"></a>`)}),$(".popup").magnificPopup({type:"image",closeOnContentClick:!0,showCloseBtn:!1,zoom:{enabled:!0,duration:300,easing:"ease-in-out"}}),$(`${e} a`).has("img").addClass("img-link")}); $(function(){$(window).scroll(()=>{$(this).scrollTop()>50&&"none"===$("#sidebar-trigger").css("display")?$("#back-to-top").fadeIn():$("#back-to-top").fadeOut()}),$("#back-to-top").click(()=>($("body,html").animate({scrollTop:0},800),!1))}),$(function(){const e=$("#sidebar-trigger"),t=$("#search-trigger"),o=$("#search-cancel"),a=$("#search-cleaner"),s=$("#main"),l=$("#topbar-title"),n=$("#search-wrapper"),i=$("#search-result-wrapper"),r=$("#search-results"),d=$("#search-input"),c=$("#search-hints"),u=function(){let e=0;return{block(){e=window.scrollY,$("html,body").scrollTop(0)},release(){$("html,body").scrollTop(e)},getOffset:()=>e}}(),p={on(){e.addClass("unloaded"),l.addClass("unloaded"),t.addClass("unloaded"),n.addClass("d-flex"),o.addClass("loaded")},off(){o.removeClass("loaded"),n.removeClass("d-flex"),e.removeClass("unloaded"),l.removeClass("unloaded"),t.removeClass("unloaded")}},f=function(){let e=!1;return{on(){e||(u.block(),i.removeClass("unloaded"),s.addClass("unloaded"),e=!0)},off(){e&&(r.empty(),c.hasClass("unloaded")&&c.removeClass("unloaded"),i.addClass("unloaded"),a.removeClass("visible"),s.removeClass("unloaded"),u.release(),d.val(""),e=!1)},isVisible:()=>e}}();function h(){return o.hasClass("loaded")}t.click(function(){p.on(),f.on(),d.focus()}),o.click(function(){p.off(),f.off()}),d.focus(function(){n.addClass("input-focus")}),d.focusout(function(){n.removeClass("input-focus")}),d.on("keyup",function(e){8===e.keyCode&&""===d.val()?h()?c.removeClass("unloaded"):f.off():""!==d.val()&&(f.on(),a.hasClass("visible")||a.addClass("visible"),h()&&c.addClass("unloaded"))}),a.on("click",function(){d.val(""),h()?(c.removeClass("unloaded"),r.empty()):f.off(),d.focus(),a.removeClass("visible")})}),$(function(){const e=function(){let e=!1;const t=$("body");return{toggle(){!1===e?t.attr("sidebar-display",""):t.removeAttr("sidebar-display"),e=!e}}}();$("#sidebar-trigger").click(e.toggle),$("#mask").click(e.toggle)}),$(function(){$('[data-toggle="tooltip"]').tooltip()}),$(function(){const e=$("#topbar-wrapper"),t=$("#toc-wrapper"),o=$(".access"),a=$("#search-input");let s,l=0;const n=5,i=e.outerHeight();$(window).scroll(function(e){$("#topbar-title").is(":hidden")&&(s=!0)}),setInterval(function(){s&&(!function(){var s=$(this).scrollTop();Math.abs(l-s)<=n||(s>l&&s>i?(e.removeClass("topbar-down").addClass("topbar-up"),t.length>0&&t.removeClass("topbar-down"),o.length>0&&o.removeClass("topbar-down"),a.is(":focus")&&a.blur()):s+$(window).height()<$(document).height()&&(e.removeClass("topbar-up").addClass("topbar-down"),t.length>0&&t.addClass("topbar-down"),o.length>0&&o.addClass("topbar-down")),l=s)}(),s=!1)},250)}),$(function(){const e=$("#topbar-title"),t=$("div.post>h1"),o=e.text().trim();let a=t.length>0?t.text().trim():$("h1").text().trim();($("#page-category").length||$("#page-tag").length)&&/\s/.test(a)&&(a=a.replace(/[0-9]/g,"").trim()),$(window).scroll(function(){if($("#post-list").length||t.is(":hidden")||e.is(":hidden")||$("#sidebar.sidebar-expand").length)return!1;$(this).scrollTop()>=95?e.text()!==a&&e.text(a):e.text()!==o&&e.text(o)}),e.click(function(){$("body,html").animate({scrollTop:0},800)})}),$(function(){$("input[type=checkbox]").addClass("unloaded"),$("input[type=checkbox][checked]").before('<i class="fas fa-check-circle checked"></i>'),$("input[type=checkbox]:not([checked])").before('<i class="far fa-circle"></i>')}),$(function(){const e="#main > div.row:first-child > div:first-child";if($(`${e} img`).length<=0)return;const t=document.querySelectorAll(`${e} img[data-src]`);lozad(t).observe(),$(`${e} p > img[data-src],${e} img[data-src].preview-img`).each(function(){let e=$(this).next();const t="EM"===e.prop("tagName")?e.text():"",o=$(this).attr("data-src");$(this).wrap(`<a href="${o}" title="${t}" class="popup"></a>`)}),$(".popup").magnificPopup({type:"image",closeOnContentClick:!0,showCloseBtn:!1,zoom:{enabled:!0,duration:300,easing:"ease-in-out"}}),$(`${e} a`).has("img").addClass("img-link")}),$(function(){var e=new ClipboardJS(".code-header>button",{target:e=>e.parentNode.nextElementSibling});$(".code-header>button").tooltip({trigger:"click",placement:"left"}),e.on("success",function(e){var t,o;e.clearSelection(),t=e.trigger,o="Copied!",$(t).tooltip("hide").attr("data-original-title",o).tooltip("show"),function(e){setTimeout(function(){$(e).tooltip("hide")},1e3)}(e.trigger)})});

File diff suppressed because one or more lines are too long

View file

@ -46,7 +46,7 @@ const postJs = () => {
`${JS_SRC}/utils/img-extra.js`, `${JS_SRC}/utils/img-extra.js`,
`${JS_SRC}/utils/timeago.js`, `${JS_SRC}/utils/timeago.js`,
`${JS_SRC}/utils/checkbox.js`, `${JS_SRC}/utils/checkbox.js`,
`${JS_SRC}/utils/copy-link.js`, `${JS_SRC}/utils/clipboard.js`,
// 'smooth-scroll.js' must be called after ToC is ready // 'smooth-scroll.js' must be called after ToC is ready
`${JS_SRC}/utils/smooth-scroll.js` `${JS_SRC}/utils/smooth-scroll.js`
], 'post' ], 'post'
@ -66,7 +66,7 @@ const pageJs = () => {
`${JS_SRC}/commons/*.js`, `${JS_SRC}/commons/*.js`,
`${JS_SRC}/utils/checkbox.js`, `${JS_SRC}/utils/checkbox.js`,
`${JS_SRC}/utils/img-extra.js`, `${JS_SRC}/utils/img-extra.js`,
`${JS_SRC}/utils/copy-link.js`, `${JS_SRC}/utils/clipboard.js`
], 'page' ], 'page'
); );
}; };