Skip to content

Commit d194704

Browse files
committedOct 10, 2022
feat:#1 添加代码高亮插件
1 parent 2651b7d commit d194704

File tree

11 files changed

+423
-5
lines changed

11 files changed

+423
-5
lines changed
 

‎assets/scss/index.dark.scss

+33-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
html.dark body{
1+
html.dark body {
22
/* 自定义深色背景颜色 */
3-
--custom-app-color:#ffffff;
3+
--custom-app-color: #ffffff;
44
--custom-app-bg-color: #000000;
55
}
66

@@ -18,4 +18,35 @@ html.dark .post-detail-content-box table th {
1818
html.dark .post-detail-content-box table td {
1919
border-color: #ccc;
2020
background-color: #161616;
21+
}
22+
23+
/** dark code */
24+
html.dark .post-detail-content-box .hljs {
25+
color: #ffffff;
26+
background-color: #161616 !important;
27+
border: 1px solid #ccc !important;
28+
}
29+
30+
html.dark code {
31+
color: #2fd945 !important;
32+
}
33+
34+
html.dark .hljs-keyword,
35+
html.dark .hljs-selector-tag,
36+
html.dark .hljs-built_in,
37+
html.dark .hljs-name,
38+
html.dark .hljs-tag {
39+
color: #539dc5 !important;
40+
}
41+
42+
html.dark .post-detail-content-box .hljs-string,
43+
html.dark .post-detail-content-box .hljs-title,
44+
html.dark .post-detail-content-box .hljs-section,
45+
html.dark .post-detail-content-box .hljs-attribute,
46+
html.dark .post-detail-content-box .hljs-literal,
47+
html.dark .post-detail-content-box .hljs-template-tag,
48+
html.dark .post-detail-content-box .hljs-template-variable,
49+
html.dark .post-detail-content-box .hljs-type,
50+
html.dark .post-detail-content-box .hljs-addition {
51+
color: #2fd945 !important;
2152
}

‎package.json

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"@fortawesome/vue-fontawesome": "^3.0.1",
3030
"arraybuffer-xml-parser": "^0.6.0",
3131
"element-plus": "^2.2.15",
32+
"highlight.js": "^11.6.0",
3233
"pinia": "^2.0.23",
3334
"showdown": "^2.1.0",
3435
"vue": "^3.2.40",

‎pages/post/[postid].vue

+1-3
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,9 @@
3636
-->
3737

3838
<!-- 文章详情 -->
39-
<!--
40-
v-hilight
41-
-->
4239
<div
4340
id="postContent"
41+
v-highlight
4442
v-html="postObj.description"
4543
></div>
4644

File renamed without changes.

‎plugins/hljs/codecopy/codecopy.css

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
.hljs-copy-wrapper {
2+
position: relative;
3+
overflow: hidden;
4+
}
5+
.hljs-copy-wrapper:hover .hljs-copy-button,
6+
.hljs-copy-button:focus {
7+
transform: translateX(0);
8+
}
9+
.hljs-copy-button {
10+
position: absolute;
11+
transform: translateX(calc(100% + 1.125em));
12+
top: 1em;
13+
right: 1em;
14+
width: 2rem;
15+
height: 2rem;
16+
text-indent: -9999px; /* Hide the inner text */
17+
color: #fff;
18+
border-radius: 0.25rem;
19+
border: 1px solid #ffffff22;
20+
/*background-color: #2d2b57;*/
21+
background-color: #0d6efd;
22+
background-image: url('data:image/svg+xml;utf-8,<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M6 5C5.73478 5 5.48043 5.10536 5.29289 5.29289C5.10536 5.48043 5 5.73478 5 6V20C5 20.2652 5.10536 20.5196 5.29289 20.7071C5.48043 20.8946 5.73478 21 6 21H18C18.2652 21 18.5196 20.8946 18.7071 20.7071C18.8946 20.5196 19 20.2652 19 20V6C19 5.73478 18.8946 5.48043 18.7071 5.29289C18.5196 5.10536 18.2652 5 18 5H16C15.4477 5 15 4.55228 15 4C15 3.44772 15.4477 3 16 3H18C18.7956 3 19.5587 3.31607 20.1213 3.87868C20.6839 4.44129 21 5.20435 21 6V20C21 20.7957 20.6839 21.5587 20.1213 22.1213C19.5587 22.6839 18.7957 23 18 23H6C5.20435 23 4.44129 22.6839 3.87868 22.1213C3.31607 21.5587 3 20.7957 3 20V6C3 5.20435 3.31607 4.44129 3.87868 3.87868C4.44129 3.31607 5.20435 3 6 3H8C8.55228 3 9 3.44772 9 4C9 4.55228 8.55228 5 8 5H6Z" fill="white"/><path fill-rule="evenodd" clip-rule="evenodd" d="M7 3C7 1.89543 7.89543 1 9 1H15C16.1046 1 17 1.89543 17 3V5C17 6.10457 16.1046 7 15 7H9C7.89543 7 7 6.10457 7 5V3ZM15 3H9V5H15V3Z" fill="white"/></svg>');
23+
background-repeat: no-repeat;
24+
background-position: center;
25+
transition: background-color 200ms ease, transform 200ms ease-out;
26+
cursor: pointer;
27+
}
28+
.hljs-copy-button:hover {
29+
border-color: #ffffff44;
30+
}
31+
.hljs-copy-button:active {
32+
border-color: #ffffff66;
33+
}
34+
.hljs-copy-button[data-copied="true"] {
35+
text-indent: 0px; /* Shows the inner text */
36+
width: auto;
37+
background-image: none;
38+
}
39+
@media (prefers-reduced-motion) {
40+
.hljs-copy-button {
41+
transition: none;
42+
}
43+
}
44+
45+
/* visually-hidden */
46+
.hljs-copy-alert {
47+
clip: rect(0 0 0 0);
48+
clip-path: inset(50%);
49+
height: 1px;
50+
overflow: hidden;
51+
position: absolute;
52+
white-space: nowrap;
53+
width: 1px;
54+
}

‎plugins/hljs/codecopy/index.js

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/**
2+
* @file highlight-copy.js
3+
* @author Arron Hunt <arronjhunt@gmail.com>
4+
* @copyright Copyright 2021. All rights reserved.
5+
*/
6+
7+
/**
8+
* Adds a copy button to highlightjs code blocks
9+
*/
10+
export class CopyButtonPlugin {
11+
/**
12+
* Create a new CopyButtonPlugin class instance
13+
* @param {Object} [options] - Functions that will be called when a copy event fires
14+
* @param {CopyCallback} [options.callback]
15+
* @param {Hook} [options.hook]
16+
*/
17+
constructor(options = {}) {
18+
// this.hook = options.hook;
19+
// this.callback = options.callback;
20+
}
21+
22+
// @ts-ignore
23+
"after:highlightElement"({el, text}) {
24+
// Create the copy button and append it to the codeblock.
25+
const button = Object.assign(document.createElement("button"), {
26+
innerHTML: "Copy",
27+
className: "hljs-copy-button"
28+
});
29+
// @ts-ignore
30+
button.dataset.copied = false;
31+
el.parentElement.classList.add("hljs-copy-wrapper");
32+
el.parentElement.appendChild(button);
33+
34+
// Add a custom proprety to the code block so that the copy button can reference and match its background-color value.
35+
el.parentElement.style.setProperty(
36+
"--hljs-theme-background",
37+
window.getComputedStyle(el).backgroundColor
38+
);
39+
40+
button.onclick = function () {
41+
if (!navigator.clipboard) return;
42+
43+
let newText = text;
44+
// @ts-ignore
45+
// eslint-disable-next-line no-undef
46+
// if (hook && typeof hook === "function") {
47+
// // @ts-ignore
48+
// // eslint-disable-next-line no-undef
49+
// newText = hook(text, el) || text;
50+
// }
51+
52+
navigator.clipboard
53+
.writeText(newText)
54+
.then(function () {
55+
button.innerHTML = "复制成功";
56+
// @ts-ignore
57+
button.dataset.copied = true;
58+
59+
let alert = Object.assign(document.createElement("div"), {
60+
role: "status",
61+
className: "hljs-copy-alert",
62+
innerHTML: "复制到剪贴板"
63+
});
64+
el.parentElement.appendChild(alert);
65+
66+
setTimeout(() => {
67+
button.innerHTML = "Copy";
68+
// @ts-ignore
69+
button.dataset.copied = false;
70+
el.parentElement.removeChild(alert);
71+
// @ts-ignore
72+
alert = null;
73+
}, 2000);
74+
})
75+
.then(function () {
76+
// @ts-ignore
77+
// eslint-disable-next-line no-undef
78+
if (typeof callback === "function") return callback(newText, el);
79+
});
80+
};
81+
}
82+
}
83+
84+
/**
85+
* @typedef {function} CopyCallback
86+
* @param {string} text - The raw text copied to the clipboard.
87+
* @param {HTMLElement} el - The code block element that was copied from.
88+
* @returns {undefined}
89+
*/
90+
/**
91+
* @typedef {function} Hook
92+
* @param {string} text - The raw text copied to the clipboard.
93+
* @param {HTMLElement} el - The code block element that was copied from.
94+
* @returns {string|undefined}
95+
*/

‎plugins/hljs/vue-hljs/main.js

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import Hljs from "highlight.js";
2+
import {CopyButtonPlugin} from "../codecopy";
3+
import "../codecopy/codecopy.css";
4+
import "./vs.css";
5+
6+
const vueHljs = {};
7+
8+
vueHljs.install = Vue => {
9+
// 代码复制
10+
Hljs.addPlugin(
11+
new CopyButtonPlugin()
12+
);
13+
14+
Vue.directive("highlight", el => {
15+
const blocks = el.querySelectorAll("pre code");
16+
Array.prototype.forEach.call(blocks, Hljs.highlightBlock);
17+
18+
// 代码选项卡
19+
// 代码块
20+
const codeGroups = el.querySelectorAll("code-group");
21+
// 处理每个代码块
22+
codeGroups.forEach(group => {
23+
// 防止重复添加
24+
if (group.getElementsByTagName("ul").length === 0) {
25+
const newNode = document.createElement("ul");
26+
newNode.setAttribute("class", "code-tab");
27+
28+
const codeBlocks = group.querySelectorAll("code-block");
29+
codeBlocks.forEach(block => {
30+
const title = block.attributes.getNamedItem("title")?.value;
31+
const active = block.attributes.getNamedItem("active")?.value;
32+
const isActive = active !== undefined;
33+
// console.log(block.attributes.length)
34+
// console.log(title)
35+
// console.log(isActive)
36+
37+
const item = document.createElement("li");
38+
item.setAttribute(
39+
"class",
40+
isActive ? "code-tab-item current" : "code-tab-item"
41+
);
42+
item.innerHTML = title || "";
43+
item.addEventListener("click", function (event) {
44+
const targetElement = event.target;
45+
// 选择状态
46+
// console.log(codeBlocks[0].innerHTML)
47+
const allLis = targetElement.parentElement.querySelectorAll("li");
48+
allLis.forEach(li => {
49+
li.setAttribute("class", "code-tab-item");
50+
});
51+
targetElement.setAttribute("class", "code-tab-item current");
52+
53+
// 设置tab
54+
codeBlocks.forEach(cb => {
55+
if (
56+
cb.attributes.getNamedItem("title")?.value ===
57+
targetElement.innerHTML
58+
) {
59+
cb.setAttribute("active", "");
60+
} else {
61+
cb.removeAttribute("active");
62+
}
63+
});
64+
// console.log(targetElement.innerHTML);
65+
});
66+
67+
newNode.append(item);
68+
});
69+
70+
const firstBlock = codeBlocks[0];
71+
firstBlock?.parentNode?.insertBefore(newNode, firstBlock);
72+
// console.log("tab")
73+
}
74+
});
75+
});
76+
};
77+
78+
export default vueHljs;

‎plugins/hljs/vue-hljs/vs.css

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
code{
2+
font-family: "LXGW WenKai","Wenquanyi Micro Hei","Wenquanyi Micro Hei Mono","Microsoft YaHei", "PT Sans", "-apple-system", "Liberation Mono", monospace, dejavu sans mono,Fira Code,Microsoft Yahei,Consolas,Courier New,monospace,Menlo,Monaco !important;
3+
font-size: 14px; color: red;
4+
}
5+
.hljs {
6+
font-family: "LXGW WenKai","Wenquanyi Micro Hei","Wenquanyi Micro Hei Mono","Microsoft YaHei", "PT Sans", "-apple-system", "Liberation Mono", monospace, dejavu sans mono,Fira Code,Microsoft Yahei,Consolas,Courier New,monospace,Menlo,Monaco !important;
7+
font-size: 14px;
8+
display: block;
9+
overflow-x: auto;
10+
padding: .5em;
11+
line-height: 1.6;
12+
color: black;
13+
background-color: #f5f5f5!important;
14+
/*border: 1px solid #ccc!important;*/
15+
border-radius: 3px!important;
16+
}
17+
18+
.hljs-comment, .hljs-quote, .hljs-variable {
19+
color: #008000
20+
}
21+
22+
.hljs-keyword, .hljs-selector-tag, .hljs-built_in, .hljs-name, .hljs-tag {
23+
color: #00f
24+
}
25+
26+
.hljs-string, .hljs-title, .hljs-section, .hljs-attribute, .hljs-literal, .hljs-template-tag, .hljs-template-variable, .hljs-type, .hljs-addition {
27+
color: #a31515
28+
}
29+
30+
.hljs-deletion, .hljs-selector-attr, .hljs-selector-pseudo, .hljs-meta {
31+
color: #2b91af
32+
}
33+
34+
.hljs-doctag {
35+
color: #808080
36+
}
37+
38+
.hljs-attr {
39+
color: #f00
40+
}
41+
42+
.hljs-symbol, .hljs-bullet, .hljs-link {
43+
color: #00b0e8
44+
}
45+
46+
.hljs-emphasis {
47+
font-style: italic
48+
}
49+
50+
.hljs-strong {
51+
font-weight: bold
52+
}

‎plugins/hljs/vue-hljs/vs2015.css

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
code{
2+
font-family: "LXGW WenKai","Wenquanyi Micro Hei","Wenquanyi Micro Hei Mono","Microsoft YaHei", "PT Sans", "-apple-system", "Liberation Mono", monospace, dejavu sans mono,Fira Code,Microsoft Yahei,Consolas,Courier New,monospace,Menlo,Monaco !important;
3+
color: #D69D85;
4+
font-size: 14px;
5+
}
6+
.hljs {
7+
font-family: "LXGW WenKai","Wenquanyi Micro Hei","Wenquanyi Micro Hei Mono","Microsoft YaHei", "PT Sans", "-apple-system", "Liberation Mono", monospace, dejavu sans mono,Fira Code,Microsoft Yahei,Consolas,Courier New,monospace,Menlo,Monaco !important;
8+
font-size: 14px;
9+
display: block;
10+
overflow-x: auto;
11+
padding: .5em;
12+
background: #181818;
13+
color: #DCDCDC;
14+
border: solid 1px #181818;
15+
border-radius: 5px;
16+
line-height: 1.6;
17+
}
18+
19+
.hljs-keyword, .hljs-literal, .hljs-symbol, .hljs-name {
20+
color: #569CD6
21+
}
22+
23+
.hljs-link {
24+
color: #569CD6;
25+
text-decoration: underline
26+
}
27+
28+
.hljs-built_in, .hljs-type {
29+
color: #4EC9B0
30+
}
31+
32+
.hljs-number, .hljs-class {
33+
color: #B8D7A3
34+
}
35+
36+
.hljs-string, .hljs-meta-string {
37+
color: #D69D85
38+
}
39+
40+
.hljs-regexp, .hljs-template-tag {
41+
color: #9A5334
42+
}
43+
44+
.hljs-subst, .hljs-function, .hljs-title, .hljs-params, .hljs-formula {
45+
color: #DCDCDC
46+
}
47+
48+
.hljs-comment, .hljs-quote {
49+
color: #57A64A;
50+
font-style: italic
51+
}
52+
53+
.hljs-doctag {
54+
color: #608B4E
55+
}
56+
57+
.hljs-meta, .hljs-meta-keyword, .hljs-tag {
58+
color: #9B9B9B
59+
}
60+
61+
.hljs-variable, .hljs-template-variable {
62+
color: #BD63C5
63+
}
64+
65+
.hljs-attr, .hljs-attribute, .hljs-builtin-name {
66+
color: #9CDCFE
67+
}
68+
69+
.hljs-section {
70+
color: gold
71+
}
72+
73+
.hljs-emphasis {
74+
font-style: italic
75+
}
76+
77+
.hljs-strong {
78+
font-weight: bold
79+
}
80+
81+
.hljs-bullet, .hljs-selector-tag, .hljs-selector-id, .hljs-selector-class, .hljs-selector-attr, .hljs-selector-pseudo {
82+
color: #D7BA7D
83+
}
84+
85+
.hljs-addition {
86+
background-color: #144212;
87+
display: inline-block;
88+
width: 100%
89+
}
90+
91+
.hljs-deletion {
92+
background-color: #600;
93+
display: inline-block;
94+
width: 100%
95+
}

‎plugins/vuehljs.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import vueHljs from "~/plugins/hljs/vue-hljs/main.js";
2+
3+
/**
4+
* 代码高亮插件
5+
*/
6+
export default defineNuxtPlugin((nuxtApp) => {
7+
// vueHljs
8+
nuxtApp.vueApp.use(vueHljs)
9+
});

‎yarn.lock

+5
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,11 @@ hash-sum@^2.0.0:
25472547
resolved "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz#81d01bb5de8ea4a214ad5d6ead1b523460b0b45a"
25482548
integrity sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==
25492549

2550+
highlight.js@^11.6.0:
2551+
version "11.6.0"
2552+
resolved "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.6.0.tgz#a50e9da05763f1bb0c1322c8f4f755242cff3f5a"
2553+
integrity sha512-ig1eqDzJaB0pqEvlPVIpSSyMaO92bH1N2rJpLMN/nX396wTpDA4Eq0uK+7I/2XG17pFaaKE0kjV/XPeGt7Evjw==
2554+
25502555
hookable@^5.3.0:
25512556
version "5.3.0"
25522557
resolved "https://registry.yarnpkg.com/hookable/-/hookable-5.3.0.tgz#eabdd7bef9e04cb3505c49153b669d5d53974e7d"

0 commit comments

Comments
 (0)
Please sign in to comment.