mirror of
https://github.com/nunocoracao/blowfish.git
synced 2026-01-30 15:31:52 +00:00
Merge pull request #2656 from ZhenShuo2021/feat/codeblock-title
✨ Feat: support title in code block
This commit is contained in:
@@ -3323,13 +3323,37 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
@layer utilities {
|
@layer utilities {
|
||||||
.prose .chroma {
|
.highlight-wrapper {
|
||||||
position: static;
|
position: relative;
|
||||||
|
z-index: 0;
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
border-radius: var(--radius-md);
|
border-radius: var(--radius-md);
|
||||||
}
|
|
||||||
.prose .highlight:not(:has(table)) .chroma, .prose .highlight > .chroma {
|
|
||||||
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
||||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||||
|
margin-top: 1.7142857em;
|
||||||
|
margin-bottom: 1.7142857em;
|
||||||
|
}
|
||||||
|
.highlight-wrapper pre, .highlight-wrapper table, .highlight-wrapper div {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.highlight-wrapper:has(.codeblock-title) pre {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.codeblock-title {
|
||||||
|
border-bottom-style: var(--tw-border-style);
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
border-color: rgba(var(--color-neutral-200), 1);
|
||||||
|
padding-inline: calc(var(--spacing) * 4);
|
||||||
|
padding-block: calc(var(--spacing) * 2);
|
||||||
|
&:is(.dark *) {
|
||||||
|
border-color: rgba(var(--color-neutral-800), 1);
|
||||||
|
}
|
||||||
|
background-color: #fff;
|
||||||
|
&:is(.dark *) {
|
||||||
|
background-color: #0d1117;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.chroma .lntd, .chroma .lntd pre {
|
.chroma .lntd, .chroma .lntd pre {
|
||||||
margin: calc(var(--spacing) * 0);
|
margin: calc(var(--spacing) * 0);
|
||||||
@@ -4056,14 +4080,11 @@ button, [role="button"] {
|
|||||||
margin-right: calc(var(--spacing) * 0);
|
margin-right: calc(var(--spacing) * 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.highlight-wrapper {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.highlight {
|
.highlight {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
.highlight:hover > .copy-button {
|
.highlight-wrapper:hover > .copy-button {
|
||||||
visibility: visible;
|
visibility: visible;
|
||||||
}
|
}
|
||||||
.copy-button {
|
.copy-button {
|
||||||
|
|||||||
@@ -1,12 +1,24 @@
|
|||||||
/* -- Chroma Highlight -- */
|
/* -- Chroma Highlight -- */
|
||||||
/* Background */
|
/* margins for codeblock title */
|
||||||
.prose .chroma {
|
.highlight-wrapper {
|
||||||
@apply static rounded-md;
|
@apply block relative z-0 overflow-hidden shadow rounded-md;
|
||||||
|
margin-top: 1.7142857em;
|
||||||
|
margin-bottom: 1.7142857em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prose .highlight:not(:has(table)) .chroma,
|
.highlight-wrapper pre,
|
||||||
.prose .highlight > .chroma {
|
.highlight-wrapper table, .highlight-wrapper div {
|
||||||
@apply shadow;
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight-wrapper:has(.codeblock-title) pre {
|
||||||
|
@apply rounded-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeblock-title {
|
||||||
|
@apply px-4 py-2 border-b border-neutral-200 dark:border-neutral-800;
|
||||||
|
@apply bg-white dark:bg-[#0d1117];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LineTableTD */
|
/* LineTableTD */
|
||||||
|
|||||||
+1
-5
@@ -95,15 +95,11 @@ button,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Code Copy */
|
/* Code Copy */
|
||||||
.highlight-wrapper {
|
|
||||||
@apply block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.highlight {
|
.highlight {
|
||||||
@apply relative z-0;
|
@apply relative z-0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.highlight:hover > .copy-button {
|
.highlight-wrapper:hover > .copy-button {
|
||||||
@apply visible;
|
@apply visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-17
@@ -2,31 +2,26 @@ var scriptBundle = document.getElementById("script-bundle");
|
|||||||
var copyText = scriptBundle?.getAttribute("data-copy") || "Copy";
|
var copyText = scriptBundle?.getAttribute("data-copy") || "Copy";
|
||||||
var copiedText = scriptBundle?.getAttribute("data-copied") || "Copied";
|
var copiedText = scriptBundle?.getAttribute("data-copied") || "Copied";
|
||||||
|
|
||||||
function createCopyButton(highlightDiv) {
|
function createCopyButton(highlightWrapper) {
|
||||||
const button = document.createElement("button");
|
const button = document.createElement("button");
|
||||||
button.className = "copy-button";
|
button.className = "copy-button";
|
||||||
button.type = "button";
|
button.type = "button";
|
||||||
button.ariaLabel = copyText;
|
button.ariaLabel = copyText;
|
||||||
button.innerText = copyText;
|
button.innerText = copyText;
|
||||||
button.addEventListener("click", () => copyCodeToClipboard(button, highlightDiv));
|
button.addEventListener("click", () => copyCodeToClipboard(button, highlightWrapper));
|
||||||
|
highlightWrapper.insertBefore(button, highlightWrapper.firstChild);
|
||||||
highlightDiv.insertBefore(button, highlightDiv.firstChild);
|
|
||||||
const wrapper = document.createElement("div");
|
|
||||||
wrapper.className = "highlight-wrapper";
|
|
||||||
highlightDiv.parentNode.insertBefore(wrapper, highlightDiv);
|
|
||||||
wrapper.appendChild(highlightDiv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function copyCodeToClipboard(button, highlightDiv) {
|
async function copyCodeToClipboard(button, highlightWrapper) {
|
||||||
const codeToCopy = getCodeText(highlightDiv);
|
const codeToCopy = getCodeText(highlightWrapper);
|
||||||
|
|
||||||
function fallback(codeToCopy, highlightDiv) {
|
function fallback(codeToCopy, highlightWrapper) {
|
||||||
const textArea = document.createElement("textArea");
|
const textArea = document.createElement("textArea");
|
||||||
textArea.contentEditable = "true";
|
textArea.contentEditable = "true";
|
||||||
textArea.readOnly = "false";
|
textArea.readOnly = "false";
|
||||||
textArea.className = "copy-textarea";
|
textArea.className = "copy-textarea";
|
||||||
textArea.value = codeToCopy;
|
textArea.value = codeToCopy;
|
||||||
highlightDiv.insertBefore(textArea, highlightDiv.firstChild);
|
highlightWrapper.insertBefore(textArea, highlightWrapper.firstChild);
|
||||||
const range = document.createRange();
|
const range = document.createRange();
|
||||||
range.selectNodeContents(textArea);
|
range.selectNodeContents(textArea);
|
||||||
const sel = window.getSelection();
|
const sel = window.getSelection();
|
||||||
@@ -34,7 +29,7 @@ async function copyCodeToClipboard(button, highlightDiv) {
|
|||||||
sel.addRange(range);
|
sel.addRange(range);
|
||||||
textArea.setSelectionRange(0, 999999);
|
textArea.setSelectionRange(0, 999999);
|
||||||
document.execCommand("copy");
|
document.execCommand("copy");
|
||||||
highlightDiv.removeChild(textArea);
|
highlightWrapper.removeChild(textArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -42,10 +37,10 @@ async function copyCodeToClipboard(button, highlightDiv) {
|
|||||||
if (result.state == "granted" || result.state == "prompt") {
|
if (result.state == "granted" || result.state == "prompt") {
|
||||||
await navigator.clipboard.writeText(codeToCopy);
|
await navigator.clipboard.writeText(codeToCopy);
|
||||||
} else {
|
} else {
|
||||||
fallback(codeToCopy, highlightDiv);
|
fallback(codeToCopy, highlightWrapper);
|
||||||
}
|
}
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
fallback(codeToCopy, highlightDiv);
|
fallback(codeToCopy, highlightWrapper);
|
||||||
} finally {
|
} finally {
|
||||||
button.blur();
|
button.blur();
|
||||||
button.innerText = copiedText;
|
button.innerText = copiedText;
|
||||||
@@ -55,7 +50,10 @@ async function copyCodeToClipboard(button, highlightDiv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCodeText(highlightDiv) {
|
function getCodeText(highlightWrapper) {
|
||||||
|
const highlightDiv = highlightWrapper.querySelector(".highlight");
|
||||||
|
if (!highlightDiv) return "";
|
||||||
|
|
||||||
const codeBlock = highlightDiv.querySelector("code");
|
const codeBlock = highlightDiv.querySelector("code");
|
||||||
const inlineLines = codeBlock?.querySelectorAll(".cl"); // linenos=inline
|
const inlineLines = codeBlock?.querySelectorAll(".cl"); // linenos=inline
|
||||||
const tableCodeCell = highlightDiv?.querySelector(".lntable .lntd:last-child code"); // linenos=table
|
const tableCodeCell = highlightDiv?.querySelector(".lntable .lntd:last-child code"); // linenos=table
|
||||||
@@ -75,5 +73,5 @@ function getCodeText(highlightDiv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener("DOMContentLoaded", (event) => {
|
window.addEventListener("DOMContentLoaded", (event) => {
|
||||||
document.querySelectorAll(".highlight").forEach((highlightDiv) => createCopyButton(highlightDiv));
|
document.querySelectorAll(".highlight-wrapper").forEach((highlightWrapper) => createCopyButton(highlightWrapper));
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ Tables aren't part of the core Markdown spec, but Hugo supports supports them ou
|
|||||||
|
|
||||||
## Code Blocks
|
## Code Blocks
|
||||||
|
|
||||||
### Code block with backticks
|
### General code block
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@@ -80,23 +80,9 @@ Tables aren't part of the core Markdown spec, but Hugo supports supports them ou
|
|||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Code block indented with four spaces
|
### Code block with title and line highlight
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Example HTML5 Document</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p>Test</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
### Code block with Hugo's internal highlight shortcode
|
|
||||||
|
|
||||||
{{< highlight html "linenos=table,hl_lines=4 7-9" >}}
|
|
||||||
|
|
||||||
|
```html {title="example.html" lineNos=inline hl_lines=[4,"7-9"]}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@@ -107,7 +93,7 @@ Tables aren't part of the core Markdown spec, but Hugo supports supports them ou
|
|||||||
<p>Test</p>
|
<p>Test</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
{{< /highlight >}}
|
```
|
||||||
|
|
||||||
## List Types
|
## List Types
|
||||||
|
|
||||||
|
|||||||
@@ -80,34 +80,20 @@ Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sap
|
|||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4スペースのインデントによるコードブロック
|
### タイトルと行ハイライト機能付きのコードブロック
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="ja">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>HTML5 資料の例</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p>テスト</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
### Hugo 内のショートコード・ハイライトを利用したコードブロック
|
|
||||||
|
|
||||||
{{< highlight html "linenos=table,hl_lines=4 7-9" >}}
|
|
||||||
|
|
||||||
|
```html {title="example.html" lineNos=inline hl_lines=[4,"7-9"]}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="ja">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>HTML5 資料の例</title>
|
<title>Example HTML5 Document</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<p>テスト</p>
|
<p>Test</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
{{< /highlight >}}
|
```
|
||||||
|
|
||||||
## リスト形式
|
## リスト形式
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ Tables aren't part of the core Markdown spec, but Hugo supports supports them ou
|
|||||||
|
|
||||||
## Code Blocks
|
## Code Blocks
|
||||||
|
|
||||||
### Code block with backticks
|
### General code block
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@@ -80,23 +80,9 @@ Tables aren't part of the core Markdown spec, but Hugo supports supports them ou
|
|||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Code block indented with four spaces
|
### Code block with title and line highlight
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Example HTML5 Document</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p>Test</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
### Code block with Hugo's internal highlight shortcode
|
|
||||||
|
|
||||||
{{< highlight html "linenos=table,hl_lines=4 7-9" >}}
|
|
||||||
|
|
||||||
|
```html {title="example.html" lineNos=inline hl_lines=[4,"7-9"]}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@@ -107,7 +93,7 @@ Tables aren't part of the core Markdown spec, but Hugo supports supports them ou
|
|||||||
<p>Test</p>
|
<p>Test</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
{{< /highlight >}}
|
```
|
||||||
|
|
||||||
## List Types
|
## List Types
|
||||||
|
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sap
|
|||||||
|
|
||||||
## 代码块
|
## 代码块
|
||||||
|
|
||||||
### 带反引号的代码块
|
### 一般的代码块
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
@@ -80,23 +80,9 @@ Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sap
|
|||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
### 缩进四个空格的代码块
|
### 带有标题和行高亮的代码块
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Example HTML5 Document</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<p>Test</p>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
### 带有 Hugo 内部高亮简码的代码块
|
|
||||||
|
|
||||||
{{< highlight html "linenos=table,hl_lines=4 7-9" >}}
|
|
||||||
|
|
||||||
|
```html {title="example.html" lineNos=inline hl_lines=[4,"7-9"]}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@@ -107,7 +93,7 @@ Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sap
|
|||||||
<p>Test</p>
|
<p>Test</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
{{< /highlight >}}
|
```
|
||||||
|
|
||||||
## 列表
|
## 列表
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{{- $title := or .Attributes.title "" -}}
|
||||||
|
{{- $lang := or .Type "text" -}}
|
||||||
|
<div class="highlight-wrapper">
|
||||||
|
{{- with $title -}}
|
||||||
|
<div class="codeblock-title">
|
||||||
|
{{- $title -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
{{- transform.Highlight .Inner $lang .Options -}}
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user