代码块

This commit is contained in:
1152958806@qq.com 2023-07-17 22:05:08 +08:00
parent 3873a6450b
commit 9bdc745c1c
48 changed files with 624 additions and 6 deletions

View File

@ -1725,6 +1725,233 @@ spec:
label: 全局字体
placeholder: '"PingFang SC", "Hiragino Sans GB", "Microsoft YaHei"'
- group: code
label: 代码块
formSchema:
- $formkit: radio
name: enable
id: enable
key: enable
label: 启用代码块
help: 如果安装代码块插件,可关闭此功能
value: true
options:
- label: 启用
value: true
- label: 禁用
value: false
- $formkit: radio
name: enable_title
if: $get(enable).value
label: 启用代码标题
help: 启用代码块的标题,默认显示语言类型,也可自定义标题
value: true
options:
- label: 启用
value: true
- label: 禁用
value: false
- $formkit: radio
name: enable_hr
if: $get(enable).value
label: 启用代码标题分割线
help: 启用代码标题和内容之间的分割线,不展示时会更加简洁
value: true
options:
- label: 启用
value: true
- label: 禁用
value: false
- $formkit: radio
name: enable_line
if: $get(enable).value
label: 启用代码行号
help: 启用代码块行号功能
value: true
options:
- label: 启用
value: true
- label: 禁用
value: false
- $formkit: radio
name: enable_copy
if: $get(enable).value
label: 启用代码复制
help: 启用代码块复制按钮
value: true
options:
- label: 启用
value: true
- label: 禁用
value: false
- $formkit: radio
name: enable_expander
if: $get(enable).value
label: 启用代码折叠
help: 启用代码折叠功能
value: true
options:
- label: 启用
value: true
- label: 禁用
value: false
- $formkit: select
name: theme_light
if: $get(enable).value
label: 代码块主题(浅色)随着系统主题变化
value: one-light
options:
- value: "one-dark"
label: "one-dark"
- value: "one-light"
label: "one-light"
- value: "a11y-dark"
label: "a11y-dark"
- value: "atom-dark"
label: "atom-dark"
- value: "base16-ateliersulphurpool.light"
label: "base16-ateliersulphurpool.light"
- value: "cb"
label: "cb"
- value: "coldark-cold"
label: "coldark-cold"
- value: "coldark-dark"
label: "coldark-dark"
- value: "coy-without-shadows"
label: "coy-without-shadows"
- value: "darcula"
label: "darcula"
- value: "dracula"
label: "dracula"
- value: "duotone-dark"
label: "duotone-dark"
- value: "duotone-earth"
label: "duotone-earth"
- value: "duotone-forest"
label: "duotone-forest"
- value: "duotone-light"
label: "duotone-light"
- value: "duotone-sea"
label: "duotone-sea"
- value: "duotone-space"
label: "duotone-space"
- value: "ghcolors"
label: "ghcolors"
- value: "gruvbox-dark"
label: "gruvbox-dark"
- value: "gruvbox-light"
label: "gruvbox-light"
- value: "holi-theme"
label: "holi-theme"
- value: "hopscotch"
label: "hopscotch"
- value: "lucario"
label: "lucario"
- value: "material-dark"
label: "material-dark"
- value: "material-light"
label: "material-light"
- value: "material-oceanic"
label: "material-oceanic"
- value: "night-owl"
label: "night-owl"
- value: "nord"
label: "nord"
- value: "pojoaque"
label: "pojoaque"
- value: "shades-of-purple"
label: "shades-of-purple"
- value: "solarized-dark-atom"
label: "solarized-dark-atom"
- value: "synthwave84"
label: "synthwave84"
- value: "vs"
label: "vs"
- value: "vsc-dark-plus"
label: "vsc-dark-plus"
- value: "xonokai"
label: "xonokai"
- value: "z-touch"
label: "z-touch"
- $formkit: select
name: theme_dark
if: $get(enable).value
label: 代码块主题(深色)随着系统主题变化
value: one-dark
options:
- value: "one-dark"
label: "one-dark"
- value: "one-light"
label: "one-light"
- value: "a11y-dark"
label: "a11y-dark"
- value: "atom-dark"
label: "atom-dark"
- value: "base16-ateliersulphurpool.light"
label: "base16-ateliersulphurpool.light"
- value: "cb"
label: "cb"
- value: "coldark-cold"
label: "coldark-cold"
- value: "coldark-dark"
label: "coldark-dark"
- value: "coy-without-shadows"
label: "coy-without-shadows"
- value: "darcula"
label: "darcula"
- value: "dracula"
label: "dracula"
- value: "duotone-dark"
label: "duotone-dark"
- value: "duotone-earth"
label: "duotone-earth"
- value: "duotone-forest"
label: "duotone-forest"
- value: "duotone-light"
label: "duotone-light"
- value: "duotone-sea"
label: "duotone-sea"
- value: "duotone-space"
label: "duotone-space"
- value: "ghcolors"
label: "ghcolors"
- value: "gruvbox-dark"
label: "gruvbox-dark"
- value: "gruvbox-light"
label: "gruvbox-light"
- value: "holi-theme"
label: "holi-theme"
- value: "hopscotch"
label: "hopscotch"
- value: "lucario"
label: "lucario"
- value: "material-dark"
label: "material-dark"
- value: "material-light"
label: "material-light"
- value: "material-oceanic"
label: "material-oceanic"
- value: "night-owl"
label: "night-owl"
- value: "nord"
label: "nord"
- value: "pojoaque"
label: "pojoaque"
- value: "shades-of-purple"
label: "shades-of-purple"
- value: "solarized-dark-atom"
label: "solarized-dark-atom"
- value: "synthwave84"
label: "synthwave84"
- value: "vs"
label: "vs"
- value: "vsc-dark-plus"
label: "vsc-dark-plus"
- value: "xonokai"
label: "xonokai"
- value: "z-touch"
label: "z-touch"
- group: tool
label: 小部件
formSchema:

View File

@ -5,8 +5,214 @@ let halo = {
if(commentDOMclass.contains('light'))
commentDOMclass.replace('light','dark')
else
commentDOMclass.replace('dark','light')
commentDOMclass.replace('dark','light')
}
},
dataCodeTheme : ()=>{
var t = document.documentElement.getAttribute('data-theme')
var e = document.querySelector("link[data-code-theme=light]"),
o = document.querySelector("link[data-code-theme=dark]");
(o || e) && ("light" === t ? (o.disabled = !0, e.disabled = !1) : (e.disabled = !0, o.disabled = !1))
},
/**
* 代码
* 只适用于halo的代码渲染
*/
addPrismTool : ()=>{
if (typeof Prism === 'undefined' || typeof document === 'undefined') {
return;
}
if (!Prism.plugins.toolbar) {
console.warn('Copy to Clipboard plugin loaded before Toolbar plugin.');
return;
}
const enable = GLOBAL_CONFIG.prism.enable;
if (!enable) return;
const isEnableTitle = GLOBAL_CONFIG.prism.enable_title;
const isEnableHr = GLOBAL_CONFIG.prism.enable_hr;
const isEnableLine = GLOBAL_CONFIG.prism.enable_line;
const isEnableCopy = GLOBAL_CONFIG.prism.enable_copy;
const isEnableExpander = GLOBAL_CONFIG.prism.enable_expander;
const prismLimit = GLOBAL_CONFIG.prism.prism_limit;
// https://stackoverflow.com/a/30810322/7595472
/** @param {CopyInfo} copyInfo */
function fallbackCopyTextToClipboard(copyInfo) {
var textArea = document.createElement('textarea');
textArea.value = copyInfo.getText();
// Avoid scrolling to bottom
textArea.style.top = '0';
textArea.style.left = '0';
textArea.style.position = 'fixed';
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
setTimeout(function () {
if (successful) {
copyInfo.success();
} else {
copyInfo.error();
}
}, 1);
} catch (err) {
setTimeout(function () {
copyInfo.error(err);
}, 1);
}
document.body.removeChild(textArea);
}
/** @param {CopyInfo} copyInfo */
function copyTextToClipboard(copyInfo) {
if (navigator.clipboard) {
navigator.clipboard.writeText(copyInfo.getText()).then(copyInfo.success, function () {
// try the fallback in case `writeText` didn't work
fallbackCopyTextToClipboard(copyInfo);
});
} else {
fallbackCopyTextToClipboard(copyInfo);
}
}
/**
* Selects the text content of the given element.
*
* @param {Element} element
*/
function selectElementText(element) {
// https://stackoverflow.com/a/20079910/7595472
window.getSelection().selectAllChildren(element);
}
/**
* Traverses up the DOM tree to find data attributes that override the default plugin settings.
*
* @param {Element} startElement An element to start from.
* @returns {Settings} The plugin settings.
* @typedef {Record<"copy" | "copy-error" | "copy-success" | "copy-timeout", string | number>} Settings
*/
function getSettings(startElement) {
/** @type {Settings} */
var settings = {
'copy': 'Copy',
'copy-error': 'Press Ctrl+C to copy',
'copy-success': 'Copied!',
'copy-timeout': 5000
};
var prefix = 'data-prismjs-';
for (var key in settings) {
var attr = prefix + key;
var element = startElement;
while (element && !element.hasAttribute(attr)) {
element = element.parentElement;
}
if (element) {
settings[key] = element.getAttribute(attr);
}
}
return settings;
}
var r = Prism.plugins.toolbar.hook = function (a) {
var r = a.element.parentNode;
var toolbar = r.nextElementSibling;
//标题
isEnableTitle && toolbar.classList.add("c-title")
//标题分割线
isEnableHr && toolbar.classList.add("c-hr")
var customItem = document.createElement("div");
customItem.className = 'custom-item absolute top-0'
//复制
if(isEnableCopy){
var copy = document.createElement("i");
copy.className = 'haofont hao-icon-paste copy-button code-copy cursor-pointer'
customItem.appendChild(copy)
copy.addEventListener('click', function () {
copyTextToClipboard({
getText: function () {
return a.element.textContent;
},
success: function () {
btf.snackbarShow('复制成功')
setState('copy-success');
resetText();
},
error: function () {
setState('copy-error');
setTimeout(function () {
selectElementText(a.element);
}, 1);
resetText();
}
});
});
}
//折叠
if(isEnableExpander){
var expander = document.createElement("i");
expander.className = 'fa-sharp fa-solid fa-caret-down code-expander cursor-pointer'
customItem.appendChild(expander)
const expanderCode = function () {
r.firstElementChild.classList.toggle('c-toggle')
toolbar.classList.toggle('c-expander')
}
expander.addEventListener('click', expanderCode)
}
toolbar.appendChild(customItem)
var settings = getSettings(a.element);
function resetText() {
setTimeout(function () {
setState('copy');
}, settings['copy-timeout']);
}
/** @param {"copy" | "copy-error" | "copy-success"} state */
function setState(state) {
copy.setAttribute('data-copy-state', state);
}
};
Prism.hooks.add("complete", r)
}
}

View File

@ -52,3 +52,153 @@ ul li {
padding: 0.3rem 0.5rem;
}
/*代码块*/
[data-theme=light] {
--rl-code-bar-shadow: 0 5px 10px 0 rgba(144, 164, 174, 0.4);
}
[data-theme=dark] {
--rl-code-bar-shadow: 0 0 6px 2px #272727;
}
#article-container .code-toolbar {
margin: 18px 0;
overflow: hidden;
-webkit-box-shadow: var(--rl-code-bar-shadow);
box-shadow: var(--rl-code-bar-shadow);
border-radius: 7px
}
#article-container .code-toolbar:before {
content: "";
position: absolute;
top: 11px;
left: 12px;
z-index: 1;
width: 12px;
height: 12px;
border-radius: 50%;
background-color: #fc625d;
-webkit-box-shadow: 20px 0 #fdbc40,40px 0 #35cd4b;
box-shadow: 20px 0 #fdbc40,40px 0 #35cd4b
}
#article-container .code-toolbar .toolbar {
position: absolute;
pointer-events: none;
opacity: 1;
left: 0;
right: 0;
top: 0;
z-index: unset;
height: 35px;
line-height: 32px;
text-align: center
}
#article-container .code-toolbar .toolbar-item:first-child {
display: none
}
#article-container .code-toolbar .toolbar-item:first-child span {
background-color: transparent;
-webkit-box-shadow: none;
box-shadow: none;
font-weight: 700;
font-size: 0.9em;
}
#article-container .code-toolbar .toolbar .custom-item {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
font-size: 1rem;
right: 12px;
color: #999;
pointer-events: all
}
#article-container .code-toolbar .toolbar .custom-item>i {
margin-left: 10px;
-webkit-transition: -webkit-transform .2s;
transition: transform .2s;
transition: transform .2s,-webkit-transform .2s
}
#article-container .code-toolbar .toolbar .custom-item>i:hover {
-webkit-filter: brightness(1.2);
filter: brightness(1.2)
}
#article-container .code-toolbar .toolbar.c-expander i.code-expander {
-webkit-transform: rotate(90deg);
transform: rotate(90deg)
}
#article-container .code-toolbar .toolbar.c-title .toolbar-item:first-child {
display: block
}
#article-container .code-toolbar .toolbar.c-hr {
border-bottom: 1px solid #b2a8a84d
}
#article-container .code-toolbar pre[class*=language-] {
position: relative;
margin: 0;
padding: 35px 0 0;
overflow: hidden;
white-space: pre;
text-shadow: none;
border-radius: 5px
}
#article-container .code-toolbar pre[class*=language-] .line-numbers-rows {
border-right: none;
left: 0;
top: 0;
bottom: 0;
padding-top: 12px;
width: 2.7em;
}
#article-container .code-toolbar pre[class*=language-] code[class*=language-] {
display: block;
margin-bottom: 0;
overflow-x: auto;
padding: 5px 18px 10px;
border-radius: 0 0 8px 8px;
text-shadow: none
}
#article-container .code-toolbar pre[class*=language-] code[class*=language-]::-webkit-scrollbar {
width: 5px;
height: 5px
}
#article-container .code-toolbar pre[class*=language-] code[class*=language-] .style .token.string,#article-container .code-toolbar pre[class*=language-] code[class*=language-] .token.entity,#article-container .code-toolbar pre[class*=language-] code[class*=language-] .token.operator,#article-container .code-toolbar pre[class*=language-] code[class*=language-] .token.string,#article-container .code-toolbar pre[class*=language-] code[class*=language-] .token.url {
background-color: transparent
}
#article-container .code-toolbar pre[class*=language-].line-numbers code[class*=language-] {
padding: 10px 20px 10px 48px;
}
.absolute {
position: absolute;
}
.top-0 {
top: 0;
}
#article-container .code-toolbar pre[class*=language-] code[class*=language-].c-toggle{
display: none;
}
/*代码块*/

View File

@ -205,6 +205,12 @@ rm.switchDarkMode = function () {
navFn.switchDarkMode();
rm.hideRightMenu();
heo.darkModeStatus();
//代码块
if(GLOBAL_CONFIG.prism.enable){
halo.dataCodeTheme();
}
//halo.darkComment();
}

View File

@ -1195,7 +1195,7 @@ blockquote footer cite::before {
/* 代码块增加边框 */
#article-container pre {
border: var(--style-border-always);
/*border: var(--style-border-always);*/
}

View File

@ -43,6 +43,18 @@
<!-- 代码块-->
<th:block th:if="${theme.config.code.enable}">
<link rel="preload" as="style" onload="this.rel='stylesheet'"
th:href="${assets_link+'/libs/prism/prism.min.css'}">
<link rel="preload" as="style" onload="this.rel='stylesheet'" data-code-theme="light"
th:href="${assets_link+ '/libs/prism/themes/prism-'+theme.config.code.theme_light+'.css'}">
<link rel="preload" as="style" onload="this.rel='stylesheet'" data-code-theme="dark"
th:href="${assets_link+'/libs/prism/themes/prism-'+theme.config.code.theme_dark+'.css'}">
<script data-pjax type="text/javascript" th:src="${assets_link+'/libs/prism/prism.min.js'}"></script>
</th:block>
<script th:if="${theme.config.footer.footerContent.footerStyle == 'one'}" async="async">(function () {
var grt = new Date("[[${#strings.arraySplit(theme.config.basics.siteStartTime, '-')[1]}]]/[[${#strings.arraySplit(theme.config.basics.siteStartTime, '-')[2]}]]/[[${#strings.arraySplit(theme.config.basics.siteStartTime, '-')[0]}]] 00:00:00"); //设置网站上线时间
var now = new Date();
@ -283,6 +295,15 @@
bgDark: "#121212",
position: "top-center",
},
prism: {
enable: [[${ theme.config.code.enable }]],
enable_title: [[${ theme.config.code.enable_title }]],
enable_hr: [[${ theme.config.code.enable_hr }]],
enable_line: [[${ theme.config.code.enable_line }]],
enable_copy: [[${ theme.config.code.enable_copy }]],
enable_expander: [[${ theme.config.code.enable_expander }]],
prism_limit: 330,
},
};

View File

@ -360,6 +360,14 @@
heo.changeMusicBg(false);
}
//代码块
if(GLOBAL_CONFIG.prism.enable){
halo.addPrismTool()
halo.dataCodeTheme()
}
</script>
</body>

View File

@ -11,7 +11,7 @@
<div class="post-tips">统计信息来自 <a href="https://invite.51.la/1NzKqTeb?target=V6" rel="noopener nofollow"
target="_blank">51la网站统计</a></div>
<div class="banner-button-group"><a class="banner-button" onclick="pjax.loadUrl('/archives')"
data-pjax-state=""><i class="haofont hao-icon-arrow-circle-right"></i><span
data-pjax-state=""><i class="haofont hao-icon-circle-arrow-up-right-1"></i><span
class="banner-button-text">文章隧道</span></a></div>
</div>
</div>

View File

@ -11,7 +11,7 @@
</header>
<main class="layout hide-aside" id="content-inner">
<div id="page">
<div id="article-container" th:utext="${singlePage.content.content}"></div>
<div id="article-container" th:utext="${singlePage.content.content}"></div>
<hr>
<!--/* 评论组件 */-->
<th:block

View File

@ -119,7 +119,7 @@
</div>
<!-- 文章内容 -->
<article class="post-content line-numbers" id="article-container" th:utext="${post.content.content}">
<article th:class="'post-content '+${ theme.config.code.enable_line ? 'line-numbers' : ''}" id="article-container" th:utext="${post.content.content}">
</article>