Use shiki as code highlighter (#521)

This commit is contained in:
Ryan Wang
2025-10-29 18:18:23 +08:00
committed by GitHub
parent ec35171d48
commit 461b7e089e
63 changed files with 823 additions and 141 deletions

View File

@@ -7,7 +7,7 @@ description: 元数据表单组件
## 使用示例
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -7,7 +7,7 @@ description: 附件文件类型图标组件
## 使用示例
```html
```vue
<script lang="ts" setup></script>
<template>

View File

@@ -11,7 +11,7 @@ description: 附件选择组件
## 使用示例
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -5,7 +5,7 @@ description: 过滤器清除按钮组件
## 使用示例
```html
```vue
<script lang="ts" setup>
function onClear () {
console.log("clear")

View File

@@ -7,7 +7,7 @@ description: 过滤器下拉组件
## 使用示例
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -7,7 +7,7 @@ description: 权限判断组件
## 使用方式
```html
```vue
<script lang="ts" setup>
import { VButton } from "@halo-dev/components"
</script>

View File

@@ -17,7 +17,7 @@ pnpm install @halo-dev/components
在 Vue 组件中:
```html
```vue
<script lang="ts" setup>
import { VButton } from "@halo-dev/components";
</script>

View File

@@ -7,7 +7,7 @@ description: 插件详情弹窗组件
## 使用方式
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -7,7 +7,7 @@ description: 搜索输入框组件
## 使用方式
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -5,7 +5,7 @@ description: 文件上传组件
## 使用方式
```html
```vue
<script lang="ts" setup>
const policyName = ref('my-test-policy')
const groupName = ref('my-test-group')

View File

@@ -7,7 +7,7 @@ description: 代码编辑器组件
## 使用方式
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -7,7 +7,7 @@ description: 权限指令
## 使用方式
```html
```vue
<script lang="ts" setup>
import { VButton } from "@halo-dev/components"
</script>

View File

@@ -7,7 +7,7 @@ description: Tooltip 指令
## 使用方式
```html
```vue
<script lang="ts" setup>
import { IconDeleteBin } from "@halo-dev/components"
</script>

View File

@@ -281,7 +281,7 @@ export default definePlugin({
3. 更新项目根目录的 `build.gradle` 文件
```gradle
```groovy
plugins {
id 'java'
id "io.freefair.lombok" version "8.13"
@@ -336,7 +336,7 @@ export default definePlugin({
4. 在 ui 或者 console 目录新建 `build.gradle` 文件,内容如下:
```gradle
```groovy
plugins {
id 'base'
id "com.github.node-gradle.node" version "7.1.0"

View File

@@ -168,7 +168,7 @@ export default definePlugin({
2. ` pnpm install todomvc-app-css `
3. 修改 `ui/src/views/HomeView.vue` 最底部的 `style` 标签。
```diff
```vue
- <style>
+ <style scoped>
- @import "https://unpkg.com/todomvc-app-css@2.4.1/index.css";
@@ -241,7 +241,7 @@ export interface TodoList {
编辑 `ui/src/views/HomeView.vue` 文件,将所有内容替换为如下写法:
```typescript
```vue
<script setup lang="ts">
import axios from "axios";
import type { Todo, TodoList } from "../types";
@@ -466,14 +466,16 @@ const handleDelete = (todo: Todo) => {
需要修改 `ui/src/views/HomeView.vue` 示例如下:
```diff
+ import Logo from "@/assets/logo.svg";
```vue
// [!code ++]
import Logo from "@/assets/logo.svg";
// ...
<template>
<section class="todoapp">
<header class="header">
<h1>
+ <img :src="Logo" alt="logo" style="display: inline; width: 64px" />
// [!code ++]
<img :src="Logo" alt="logo" style="display: inline; width: 64px" />
todos
</h1>
//...

View File

@@ -95,7 +95,7 @@ export default definePlugin({
});
```
```html title="StickerSelectorProvider.vue"
```vue title="StickerSelectorProvider.vue"
<script lang="ts" setup>
const props = withDefaults(
defineProps<{

View File

@@ -87,7 +87,7 @@ export interface DashboardWidgetDefinition {
### 小部件组件开发
```html
```vue
<template>
<WidgetCard v-bind="$attrs" :body-class="['!p-0']">
<template #title>
@@ -221,7 +221,7 @@ export default definePlugin({
自定义组件:
```html
```vue
<template>
<div class="group relative cursor-pointer rounded-lg bg-blue-50 p-4 transition-all hover:bg-blue-100">
<div class="flex items-center gap-3">

View File

@@ -76,7 +76,7 @@ export default definePlugin({
});
```
```html title="./components/markdown-editor.vue"
```vue title="./components/markdown-editor.vue"
<script setup lang="ts">
import { marked } from "marked";
import { debounce } from "lodash-es";

View File

@@ -65,7 +65,7 @@ export default definePlugin({
});
```
```html title="./views/my-component.vue"
```vue title="./views/my-component.vue"
<script lang="ts" setup>
const plugin = inject<Ref<Plugin | undefined>>("plugin");
</script>

View File

@@ -145,7 +145,7 @@ my-halo-plugin/
`api/build.gradle` 配置如下:
```gradle
```groovy
plugins {
id 'java-library'
id 'maven-publish'

View File

@@ -122,7 +122,7 @@ public class CustomEventPublisher {
1. 插件 A 将包含了 `CustomSharedEvent` 这个类的依赖 `plugin-a-api` 发布到 Maven 仓库
2. 插件 B 引入 `plugin-a-api` 作为项目依赖并将其作为 `compileOnly`,必须是 `compileOnly` 依赖
```gradle
```groovy
dependencies {
compileOnly "run.halo.example:plugin-a-api:1.0.0"
}

View File

@@ -31,7 +31,7 @@ helm install halo halo/halo
命令执行成功后会返回类似下文中的提示,通过提示中的命令可以获取到 NodePort 方式的 Halo 访问地址及默认的控制台管理员用户名和密码。
```text
```bash
NAME: halo
LAST DEPLOYED: Sun Jun 25 15:49:53 2023
NAMESPACE: halo

View File

@@ -31,7 +31,7 @@ tar zxvf halo-offline-installer-v2.17.0-amd64.tar.gz
:::info
安装包目录说明
```text
```bash
[root@localhost halo-offline-installer-v2.17.0-amd64]# tree
.
├── docker # 离线安装 Docker 使用到的文件
@@ -75,7 +75,7 @@ cd halo-offline-installer-v2.17.0-amd64
:::info
假设采用默认安装位置 /opt/halo 完成安装,安装目录的文件结构如下:
```text
```bash
[root@meter-prototype halo]# tree
.
├── data # 数据存储目录

View File

@@ -123,7 +123,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
[Unit]
Description=The halo container
Wants=network-online.target
@@ -201,7 +201,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
# /etc/containers/systemd/halo.container
[Unit]
Description=The halo container

View File

@@ -1,6 +1,11 @@
const { bundledLanguages } = require("shiki");
const VersionsArchived = require("./versionsArchived.json");
const { themes } = require("prism-react-renderer");
const darkCodeTheme = themes.palenight;
const { default: rehypeShiki } = require("@shikijs/rehype");
const { transformerMetaHighlight } = require("@shikijs/transformers");
const { transformerNotationDiff } = require("@shikijs/transformers");
const { transformerNotationFocus } = require("@shikijs/transformers");
const { transformerNotationErrorLevel } = require("@shikijs/transformers");
const { transformerAddMeta } = require("./src/shiki/meta-transformer");
/** @type {import('@docusaurus/types').Config} */
const config = {
@@ -42,10 +47,29 @@ const config = {
path: "next",
},
},
beforeDefaultRehypePlugins: [
[
rehypeShiki,
{
theme: "catppuccin-mocha",
langs: Object.keys(bundledLanguages),
transformers: [
transformerMetaHighlight(),
transformerNotationDiff(),
transformerNotationFocus(),
transformerNotationErrorLevel(),
transformerAddMeta(),
],
},
],
],
},
blog: false,
theme: {
customCss: require.resolve("./src/css/custom.css"),
customCss: [
require.resolve("./src/css/custom.css"),
require.resolve("./src/css/shiki.scss"),
],
},
sitemap: {
changefreq: "weekly",
@@ -199,16 +223,14 @@ const config = {
},
],
},
prism: {
theme: darkCodeTheme,
darkTheme: darkCodeTheme,
additionalLanguages: ["java", "json", "sql", "diff"],
},
zoom: {
selector: ".markdown :not(a) > img",
},
}),
plugins: [require.resolve("docusaurus-plugin-image-zoom")],
plugins: [
require.resolve("docusaurus-plugin-image-zoom"),
require.resolve("docusaurus-plugin-sass"),
],
scripts: [
{
src: "https://track.halo.run/api/script.js",

View File

@@ -1,57 +0,0 @@
const fs = require('fs');
const path = require('path');
// 指定要扫描的目录
const directoryPath = './docs';
// 递归读取目录中的所有 Markdown 文件
function readDirectory(directory) {
fs.readdir(directory, (err, files) => {
if (err) {
return console.log('无法扫描目录: ' + err);
}
files.forEach(file => {
const filePath = path.join(directory, file);
fs.stat(filePath, (err, stats) => {
if (err) {
return console.log('无法获取文件信息: ' + err);
}
if (stats.isDirectory()) {
// 如果是目录,递归读取
readDirectory(filePath);
} else if (path.extname(file) === '.md') {
// 如果是 Markdown 文件,处理文件内容
processMarkdownFile(filePath);
}
});
});
});
}
// 处理 Markdown 文件内容
function processMarkdownFile(filePath) {
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
return console.log('无法读取文件: ' + err);
}
// 使用正则表达式匹配 <https://ryanc.cc> 形式的链接
const updatedData = data.replace(/<https:\/\/[^\s]+>/g, match => {
const url = match.slice(1, -1); // 去掉尖括号
return `[${url}](${url})`;
});
// 将更新后的内容写回文件
fs.writeFile(filePath, updatedData, 'utf8', err => {
if (err) {
return console.log('无法写入文件: ' + err);
}
console.log(`已处理文件: ${filePath}`);
});
});
}
// 开始扫描目录
readDirectory(directoryPath);

View File

@@ -36,6 +36,8 @@
"@docusaurus/theme-common": "3.8.0",
"@docusaurus/theme-mermaid": "3.8.0",
"@mdx-js/react": "^3.1.0",
"@shikijs/rehype": "^3.14.0",
"@shikijs/transformers": "^3.14.0",
"@svgr/webpack": "^5.5.0",
"clsx": "^1.2.1",
"docusaurus-plugin-image-zoom": "^1.0.1",
@@ -45,13 +47,16 @@
"prism-react-renderer": "^2.4.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"shiki": "^3.14.0",
"url-loader": "^4.1.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "3.8.0",
"docusaurus-plugin-sass": "^0.2.6",
"husky": "^7.0.4",
"markdownlint": "^0.25.1",
"markdownlint-cli2": "^0.4.0"
"markdownlint-cli2": "^0.4.0",
"sass": "^1.93.2"
},
"engines": {
"node": ">=18.0"

392
pnpm-lock.yaml generated
View File

@@ -32,6 +32,12 @@ importers:
'@mdx-js/react':
specifier: ^3.1.0
version: 3.1.0(@types/react@18.3.12)(react@18.3.1)
'@shikijs/rehype':
specifier: ^3.14.0
version: 3.14.0
'@shikijs/transformers':
specifier: ^3.14.0
version: 3.14.0
'@svgr/webpack':
specifier: ^5.5.0
version: 5.5.0
@@ -59,6 +65,9 @@ importers:
react-dom:
specifier: ^18.3.1
version: 18.3.1(react@18.3.1)
shiki:
specifier: ^3.14.0
version: 3.14.0
url-loader:
specifier: ^4.1.1
version: 4.1.1(file-loader@6.2.0(webpack@5.95.0(@swc/core@1.7.42)))(webpack@5.95.0(@swc/core@1.7.42))
@@ -66,6 +75,9 @@ importers:
'@docusaurus/module-type-aliases':
specifier: 3.8.0
version: 3.8.0(@swc/core@1.7.42)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
docusaurus-plugin-sass:
specifier: ^0.2.6
version: 0.2.6(@docusaurus/core@3.8.0(@docusaurus/faster@3.8.0(@docusaurus/types@3.8.0(@swc/core@1.7.42)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@mdx-js/react@3.1.0(@types/react@18.3.12)(react@18.3.1))(@rspack/core@1.3.12)(@swc/core@1.7.42)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(@rspack/core@1.3.12)(sass@1.93.2)(webpack@5.95.0(@swc/core@1.7.42))
husky:
specifier: ^7.0.4
version: 7.0.4
@@ -75,6 +87,9 @@ importers:
markdownlint-cli2:
specifier: ^0.4.0
version: 0.4.0
sass:
specifier: ^1.93.2
version: 1.93.2
packages:
@@ -1296,6 +1311,88 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
'@parcel/watcher-android-arm64@2.5.1':
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [android]
'@parcel/watcher-darwin-arm64@2.5.1':
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [darwin]
'@parcel/watcher-darwin-x64@2.5.1':
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [darwin]
'@parcel/watcher-freebsd-x64@2.5.1':
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [freebsd]
'@parcel/watcher-linux-arm-glibc@2.5.1':
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
'@parcel/watcher-linux-arm-musl@2.5.1':
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
'@parcel/watcher-linux-arm64-glibc@2.5.1':
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-arm64-musl@2.5.1':
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-x64-glibc@2.5.1':
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
'@parcel/watcher-linux-x64-musl@2.5.1':
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
'@parcel/watcher-win32-arm64@2.5.1':
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [win32]
'@parcel/watcher-win32-ia32@2.5.1':
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
engines: {node: '>= 10.0.0'}
cpu: [ia32]
os: [win32]
'@parcel/watcher-win32-x64@2.5.1':
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [win32]
'@parcel/watcher@2.5.1':
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
engines: {node: '>= 10.0.0'}
'@pnpm/config.env-replace@1.1.0':
resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==}
engines: {node: '>=12.22.0'}
@@ -1372,6 +1469,33 @@ packages:
resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==}
engines: {node: '>=16.0.0'}
'@shikijs/core@3.14.0':
resolution: {integrity: sha512-qRSeuP5vlYHCNUIrpEBQFO7vSkR7jn7Kv+5X3FO/zBKVDGQbcnlScD3XhkrHi/R8Ltz0kEjvFR9Szp/XMRbFMw==}
'@shikijs/engine-javascript@3.14.0':
resolution: {integrity: sha512-3v1kAXI2TsWQuwv86cREH/+FK9Pjw3dorVEykzQDhwrZj0lwsHYlfyARaKmn6vr5Gasf8aeVpb8JkzeWspxOLQ==}
'@shikijs/engine-oniguruma@3.14.0':
resolution: {integrity: sha512-TNcYTYMbJyy+ZjzWtt0bG5y4YyMIWC2nyePz+CFMWqm+HnZZyy9SWMgo8Z6KBJVIZnx8XUXS8U2afO6Y0g1Oug==}
'@shikijs/langs@3.14.0':
resolution: {integrity: sha512-DIB2EQY7yPX1/ZH7lMcwrK5pl+ZkP/xoSpUzg9YC8R+evRCCiSQ7yyrvEyBsMnfZq4eBzLzBlugMyTAf13+pzg==}
'@shikijs/rehype@3.14.0':
resolution: {integrity: sha512-In2G6yvT0ZFDqNGbJumd7gEAwtxuaXuchCc0O3qOytIUTlpzs8/D0CQF3wktdfOB6B869eab6Z6EIJr4Td4hQQ==}
'@shikijs/themes@3.14.0':
resolution: {integrity: sha512-fAo/OnfWckNmv4uBoUu6dSlkcBc+SA1xzj5oUSaz5z3KqHtEbUypg/9xxgJARtM6+7RVm0Q6Xnty41xA1ma1IA==}
'@shikijs/transformers@3.14.0':
resolution: {integrity: sha512-i67zQnY9wLMMnKasonVW1L9fKneSLZDj1ePsA4o0AZWU4uUobmJY9baRDa36z+a9/g0aG76/2tybQvm4hrwxIQ==}
'@shikijs/types@3.14.0':
resolution: {integrity: sha512-bQGgC6vrY8U/9ObG1Z/vTro+uclbjjD/uG58RvfxKZVD5p9Yc1ka3tVyEFy7BNJLzxuWyHH5NWynP9zZZS59eQ==}
'@shikijs/vscode-textmate@10.0.2':
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
'@sideway/address@4.1.5':
resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==}
@@ -2300,6 +2424,10 @@ packages:
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
engines: {node: '>= 8.10.0'}
chokidar@4.0.3:
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
engines: {node: '>= 14.16.0'}
chrome-trace-event@1.0.4:
resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==}
engines: {node: '>=6.0'}
@@ -2908,6 +3036,12 @@ packages:
peerDependencies:
'@docusaurus/theme-classic': '>=2.2.0'
docusaurus-plugin-sass@0.2.6:
resolution: {integrity: sha512-2hKQQDkrufMong9upKoG/kSHJhuwd+FA3iAe/qzS/BmWpbIpe7XKmq5wlz4J5CJaOPu4x+iDJbgAxZqcoQf0kg==}
peerDependencies:
'@docusaurus/core': ^2.0.0-beta || ^3.0.0-alpha
sass: ^1.30.0
dom-converter@0.2.0:
resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==}
@@ -3398,12 +3532,18 @@ packages:
hast-util-to-estree@3.1.0:
resolution: {integrity: sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==}
hast-util-to-html@9.0.5:
resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==}
hast-util-to-jsx-runtime@2.3.2:
resolution: {integrity: sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==}
hast-util-to-parse5@8.0.0:
resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==}
hast-util-to-string@3.0.1:
resolution: {integrity: sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==}
hast-util-whitespace@3.0.0:
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
@@ -3530,6 +3670,9 @@ packages:
engines: {node: '>=16.x'}
hasBin: true
immutable@5.1.4:
resolution: {integrity: sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==}
import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'}
@@ -4345,6 +4488,9 @@ packages:
no-case@3.0.4:
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
node-emoji@2.1.3:
resolution: {integrity: sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==}
engines: {node: '>=18'}
@@ -4438,6 +4584,12 @@ packages:
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
engines: {node: '>=6'}
oniguruma-parser@0.12.1:
resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==}
oniguruma-to-es@4.3.3:
resolution: {integrity: sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==}
open@8.4.2:
resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==}
engines: {node: '>=12'}
@@ -5004,6 +5156,9 @@ packages:
property-information@6.5.0:
resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==}
property-information@7.1.0:
resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==}
proto-list@1.2.4:
resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
@@ -5112,6 +5267,10 @@ packages:
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
engines: {node: '>=8.10.0'}
readdirp@4.1.2:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
recma-build-jsx@1.0.0:
resolution: {integrity: sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==}
@@ -5137,6 +5296,15 @@ packages:
regenerator-transform@0.15.2:
resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==}
regex-recursion@6.0.2:
resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==}
regex-utilities@2.3.0:
resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==}
regex@6.0.1:
resolution: {integrity: sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==}
regexp.prototype.flags@1.5.3:
resolution: {integrity: sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==}
engines: {node: '>= 0.4'}
@@ -5281,6 +5449,32 @@ packages:
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
sass-loader@16.0.6:
resolution: {integrity: sha512-sglGzId5gmlfxNs4gK2U3h7HlVRfx278YK6Ono5lwzuvi1jxig80YiuHkaDBVsYIKFhx8wN7XSCI0M2IDS/3qA==}
engines: {node: '>= 18.12.0'}
peerDependencies:
'@rspack/core': 0.x || 1.x
node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
sass: ^1.3.0
sass-embedded: '*'
webpack: ^5.0.0
peerDependenciesMeta:
'@rspack/core':
optional: true
node-sass:
optional: true
sass:
optional: true
sass-embedded:
optional: true
webpack:
optional: true
sass@1.93.2:
resolution: {integrity: sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==}
engines: {node: '>=14.0.0'}
hasBin: true
sax@1.2.4:
resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
@@ -5388,6 +5582,9 @@ packages:
shell-quote@1.8.1:
resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==}
shiki@3.14.0:
resolution: {integrity: sha512-J0yvpLI7LSig3Z3acIuDLouV5UCKQqu8qOArwMx+/yPVC3WRMgrP67beaG8F+j4xfEWE0eVC4GeBCIXeOPra1g==}
side-channel@1.0.6:
resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==}
engines: {node: '>= 0.4'}
@@ -8160,6 +8357,67 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.17.1
'@parcel/watcher-android-arm64@2.5.1':
optional: true
'@parcel/watcher-darwin-arm64@2.5.1':
optional: true
'@parcel/watcher-darwin-x64@2.5.1':
optional: true
'@parcel/watcher-freebsd-x64@2.5.1':
optional: true
'@parcel/watcher-linux-arm-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-arm-musl@2.5.1':
optional: true
'@parcel/watcher-linux-arm64-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-arm64-musl@2.5.1':
optional: true
'@parcel/watcher-linux-x64-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-x64-musl@2.5.1':
optional: true
'@parcel/watcher-win32-arm64@2.5.1':
optional: true
'@parcel/watcher-win32-ia32@2.5.1':
optional: true
'@parcel/watcher-win32-x64@2.5.1':
optional: true
'@parcel/watcher@2.5.1':
dependencies:
detect-libc: 1.0.3
is-glob: 4.0.3
micromatch: 4.0.8
node-addon-api: 7.1.1
optionalDependencies:
'@parcel/watcher-android-arm64': 2.5.1
'@parcel/watcher-darwin-arm64': 2.5.1
'@parcel/watcher-darwin-x64': 2.5.1
'@parcel/watcher-freebsd-x64': 2.5.1
'@parcel/watcher-linux-arm-glibc': 2.5.1
'@parcel/watcher-linux-arm-musl': 2.5.1
'@parcel/watcher-linux-arm64-glibc': 2.5.1
'@parcel/watcher-linux-arm64-musl': 2.5.1
'@parcel/watcher-linux-x64-glibc': 2.5.1
'@parcel/watcher-linux-x64-musl': 2.5.1
'@parcel/watcher-win32-arm64': 2.5.1
'@parcel/watcher-win32-ia32': 2.5.1
'@parcel/watcher-win32-x64': 2.5.1
optional: true
'@pnpm/config.env-replace@1.1.0': {}
'@pnpm/network.ca-file@1.0.2':
@@ -8222,6 +8480,53 @@ snapshots:
'@rspack/lite-tapable@1.0.1': {}
'@shikijs/core@3.14.0':
dependencies:
'@shikijs/types': 3.14.0
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
hast-util-to-html: 9.0.5
'@shikijs/engine-javascript@3.14.0':
dependencies:
'@shikijs/types': 3.14.0
'@shikijs/vscode-textmate': 10.0.2
oniguruma-to-es: 4.3.3
'@shikijs/engine-oniguruma@3.14.0':
dependencies:
'@shikijs/types': 3.14.0
'@shikijs/vscode-textmate': 10.0.2
'@shikijs/langs@3.14.0':
dependencies:
'@shikijs/types': 3.14.0
'@shikijs/rehype@3.14.0':
dependencies:
'@shikijs/types': 3.14.0
'@types/hast': 3.0.4
hast-util-to-string: 3.0.1
shiki: 3.14.0
unified: 11.0.5
unist-util-visit: 5.0.0
'@shikijs/themes@3.14.0':
dependencies:
'@shikijs/types': 3.14.0
'@shikijs/transformers@3.14.0':
dependencies:
'@shikijs/core': 3.14.0
'@shikijs/types': 3.14.0
'@shikijs/types@3.14.0':
dependencies:
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
'@shikijs/vscode-textmate@10.0.2': {}
'@sideway/address@4.1.5':
dependencies:
'@hapi/hoek': 9.3.0
@@ -9279,6 +9584,10 @@ snapshots:
optionalDependencies:
fsevents: 2.3.3
chokidar@4.0.3:
dependencies:
readdirp: 4.1.2
chrome-trace-event@1.0.4: {}
ci-info@3.9.0: {}
@@ -9912,6 +10221,17 @@ snapshots:
medium-zoom: 1.1.0
validate-peer-dependencies: 2.2.0
docusaurus-plugin-sass@0.2.6(@docusaurus/core@3.8.0(@docusaurus/faster@3.8.0(@docusaurus/types@3.8.0(@swc/core@1.7.42)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@mdx-js/react@3.1.0(@types/react@18.3.12)(react@18.3.1))(@rspack/core@1.3.12)(@swc/core@1.7.42)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3))(@rspack/core@1.3.12)(sass@1.93.2)(webpack@5.95.0(@swc/core@1.7.42)):
dependencies:
'@docusaurus/core': 3.8.0(@docusaurus/faster@3.8.0(@docusaurus/types@3.8.0(@swc/core@1.7.42)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)))(@mdx-js/react@3.1.0(@types/react@18.3.12)(react@18.3.1))(@rspack/core@1.3.12)(@swc/core@1.7.42)(acorn@8.14.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.3)
sass: 1.93.2
sass-loader: 16.0.6(@rspack/core@1.3.12)(sass@1.93.2)(webpack@5.95.0(@swc/core@1.7.42))
transitivePeerDependencies:
- '@rspack/core'
- node-sass
- sass-embedded
- webpack
dom-converter@0.2.0:
dependencies:
utila: 0.4.0
@@ -10535,6 +10855,20 @@ snapshots:
transitivePeerDependencies:
- supports-color
hast-util-to-html@9.0.5:
dependencies:
'@types/hast': 3.0.4
'@types/unist': 3.0.3
ccount: 2.0.1
comma-separated-tokens: 2.0.3
hast-util-whitespace: 3.0.0
html-void-elements: 3.0.0
mdast-util-to-hast: 13.2.0
property-information: 7.1.0
space-separated-tokens: 2.0.2
stringify-entities: 4.0.4
zwitch: 2.0.4
hast-util-to-jsx-runtime@2.3.2:
dependencies:
'@types/estree': 1.0.6
@@ -10565,6 +10899,10 @@ snapshots:
web-namespaces: 2.0.1
zwitch: 2.0.4
hast-util-to-string@3.0.1:
dependencies:
'@types/hast': 3.0.4
hast-util-whitespace@3.0.0:
dependencies:
'@types/hast': 3.0.4
@@ -10718,6 +11056,8 @@ snapshots:
image-size@2.0.2: {}
immutable@5.1.4: {}
import-fresh@3.3.0:
dependencies:
parent-module: 1.0.1
@@ -11763,6 +12103,9 @@ snapshots:
lower-case: 2.0.2
tslib: 2.8.0
node-addon-api@7.1.1:
optional: true
node-emoji@2.1.3:
dependencies:
'@sindresorhus/is': 4.6.0
@@ -11849,6 +12192,14 @@ snapshots:
dependencies:
mimic-fn: 2.1.0
oniguruma-parser@0.12.1: {}
oniguruma-to-es@4.3.3:
dependencies:
oniguruma-parser: 0.12.1
regex: 6.0.1
regex-recursion: 6.0.2
open@8.4.2:
dependencies:
define-lazy-prop: 2.0.0
@@ -12457,6 +12808,8 @@ snapshots:
property-information@6.5.0: {}
property-information@7.1.0: {}
proto-list@1.2.4: {}
proxy-addr@2.0.7:
@@ -12576,6 +12929,8 @@ snapshots:
dependencies:
picomatch: 2.3.1
readdirp@4.1.2: {}
recma-build-jsx@1.0.0:
dependencies:
'@types/estree': 1.0.6
@@ -12618,6 +12973,16 @@ snapshots:
dependencies:
'@babel/runtime': 7.26.0
regex-recursion@6.0.2:
dependencies:
regex-utilities: 2.3.0
regex-utilities@2.3.0: {}
regex@6.0.1:
dependencies:
regex-utilities: 2.3.0
regexp.prototype.flags@1.5.3:
dependencies:
call-bind: 1.0.7
@@ -12816,6 +13181,22 @@ snapshots:
safer-buffer@2.1.2: {}
sass-loader@16.0.6(@rspack/core@1.3.12)(sass@1.93.2)(webpack@5.95.0(@swc/core@1.7.42)):
dependencies:
neo-async: 2.6.2
optionalDependencies:
'@rspack/core': 1.3.12
sass: 1.93.2
webpack: 5.95.0(@swc/core@1.7.42)
sass@1.93.2:
dependencies:
chokidar: 4.0.3
immutable: 5.1.4
source-map-js: 1.2.1
optionalDependencies:
'@parcel/watcher': 2.5.1
sax@1.2.4: {}
sax@1.4.1: {}
@@ -12954,6 +13335,17 @@ snapshots:
shell-quote@1.8.1: {}
shiki@3.14.0:
dependencies:
'@shikijs/core': 3.14.0
'@shikijs/engine-javascript': 3.14.0
'@shikijs/engine-oniguruma': 3.14.0
'@shikijs/langs': 3.14.0
'@shikijs/themes': 3.14.0
'@shikijs/types': 3.14.0
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
side-channel@1.0.6:
dependencies:
call-bind: 1.0.7

View File

@@ -1,4 +1,5 @@
onlyBuiltDependencies:
- '@parcel/watcher'
- '@swc/core'
- core-js
- core-js-pure

185
src/css/shiki.scss Normal file
View File

@@ -0,0 +1,185 @@
.shiki-code-wrapper {
overflow: hidden;
margin-bottom: var(--ifm-leading);
color-scheme: dark;
.shiki-code-header {
padding: 0.5rem 0.75rem;
border-bottom: 1px solid var(--ifm-color-gray-700);
font-size: var(--ifm-code-font-size);
}
.shiki-code-content {
position: relative;
pre {
position: relative;
padding: 0.75rem;
margin: 0;
border-radius: initial;
code {
z-index: 1;
display: block;
width: max-content;
position: relative;
min-width: 100%;
counter-reset: step;
counter-increment: step 0;
.line {
position: relative;
}
// line numbers start
.line::before {
content: counter(step);
counter-increment: step;
width: 0.6rem;
margin-right: 1.1rem;
display: inline-block;
text-align: right;
color: rgba(115, 138, 148, 0.5);
user-select: none;
}
.line:last-child:empty::before {
content: none;
counter-increment: none;
}
// line numbers end
// highlighted lines start
.highlighted {
width: 100%;
display: inline-block;
position: relative;
}
.highlighted::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: -0.75rem;
right: -0.75rem;
background: rgba(101, 117, 133, 0.16);
border-left: 1px solid rgba(34, 197, 94, 0.8);
z-index: 0;
}
.highlighted.error::after {
background: rgba(244, 63, 94, 0.16) !important;
}
.highlighted.warning::after {
background: rgba(234, 179, 8, 0.16) !important;
}
// highlighted lines end
}
// focus line start
&.has-focused .line:not(.focused) {
opacity: 0.7;
filter: blur(0.095rem);
transition: filter 0.35s, opacity 0.35s;
}
&.has-focused:hover .line:not(.focused) {
opacity: 1;
filter: blur(0);
}
// focus line end
// diff start
&.has-diff .diff {
width: 100%;
display: inline-block;
position: relative;
}
&.has-diff .diff.remove::before {
content: "-";
}
&.has-diff .diff.add::before {
content: "+";
}
&.has-diff .diff.remove::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: -0.75rem;
right: -0.75rem;
background: rgb(239 68 68 / 0.15);
border-left: 1px solid rgb(239 68 68 / 0.8);
z-index: -1;
}
&.has-diff .diff.add::after {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: -0.75rem;
right: -0.75rem;
background: rgb(34 197 94 / 0.15);
border-left: 1px solid rgb(34 197 94 / 0.8);
z-index: -1;
}
// diff end
}
.shiki-code-copy-button {
position: absolute;
top: 0.5rem;
right: 0.5rem;
opacity: 0;
z-index: 2;
width: 2rem;
height: 2rem;
display: flex;
align-items: center;
justify-content: center;
padding: 0.4rem;
border: none;
cursor: pointer;
}
}
&:hover {
.shiki-code-copy-button {
opacity: 1;
}
}
.tabler--copy {
display: inline-block;
width: 28px;
height: 28px;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='M7 9.667A2.667 2.667 0 0 1 9.667 7h8.666A2.667 2.667 0 0 1 21 9.667v8.666A2.667 2.667 0 0 1 18.333 21H9.667A2.667 2.667 0 0 1 7 18.333z'/%3E%3Cpath d='M4.012 16.737A2 2 0 0 1 3 15V5c0-1.1.9-2 2-2h10c.75 0 1.158.385 1.5 1'/%3E%3C/g%3E%3C/svg%3E");
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
.tabler--check {
display: inline-block;
width: 28px;
height: 28px;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m5 12l5 5L20 7'/%3E%3C/svg%3E");
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
}
}

View File

@@ -0,0 +1,32 @@
function parseTitleFromMeta(meta) {
if (!meta) {
return "";
}
const kvList = meta.split(" ").filter(Boolean);
for (const item of kvList) {
const [k, v = ""] = item.split("=").filter(Boolean);
if (k === "title" && v.length > 0) {
return v.replace(/["'`]/g, "");
}
}
return "";
}
/** @type {import('shiki').ShikiTransformer} */
export function transformerAddMeta() {
return {
name: "shiki-transformer:add-meta",
pre(pre) {
const title = parseTitleFromMeta(this.options.meta?.__raw);
const lang = this.options.lang;
if (title.length > 0) {
pre.properties = {
...pre.properties,
"data-title": title,
"data-lang": lang,
};
}
return pre;
},
};
}

View File

@@ -0,0 +1,27 @@
import type { ComponentProps, ReactNode } from "react";
import React from "react";
import CodeInline from "@theme/CodeInline";
import type { Props } from "@theme/MDXComponents/Code";
function shouldBeInline(props: Props) {
return (
// empty code blocks have no props.children,
// see https://github.com/facebook/docusaurus/pull/9704
typeof props.children !== "undefined" &&
React.Children.toArray(props.children).every(
(el) => typeof el === "string" && !el.includes("\n")
)
);
}
function CodeBlock(props: ComponentProps<"code">): JSX.Element {
return <code {...props} />;
}
export default function MDXCode(props: Props): ReactNode {
return shouldBeInline(props) ? (
<CodeInline {...props} />
) : (
<CodeBlock {...(props as ComponentProps<typeof CodeBlock>)} />
);
}

View File

@@ -0,0 +1,71 @@
import React, { type ReactNode, useRef, useState } from "react";
import type { Props } from "@theme/MDXComponents/Pre";
type PreWithDataTitle = Props & { "data-title"?: string };
export default function MDXPre(props: PreWithDataTitle): ReactNode | undefined {
const title = props["data-title"];
const preRef = useRef<HTMLPreElement>(null);
const [copied, setCopied] = useState(false);
const handleCopy = () => {
const code = preRef.current?.innerText || preRef.current?.textContent || "";
copyText(code, () => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
});
};
return (
<div
style={{
...props.style,
borderRadius: "var(--ifm-pre-border-radius)",
}}
className="shiki-code-wrapper"
>
{title && (
<div className="shiki-code-header">
<span>{title}</span>
</div>
)}
<div className="shiki-code-content">
<button
className="shiki-code-copy-button"
onClick={handleCopy}
title={copied ? "已复制!" : "复制代码"}
style={{ ...props.style }}
>
<i className={copied ? "tabler--check" : "tabler--copy"}></i>
</button>
<pre {...props} ref={preRef} />
</div>
</div>
);
}
export function copyText(text: string, cb: () => void) {
if (navigator.clipboard) {
navigator.clipboard.writeText(text).then(() => {
cb();
});
} else {
const textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.position = "fixed";
textArea.style.opacity = "0";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand("copy");
if (successful) {
cb();
}
} catch (err) {
console.error("Fallback: Oops, unable to copy", err);
}
document.body.removeChild(textArea);
}
}

View File

@@ -119,7 +119,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
[Unit]
Description=The halo container
Wants=network-online.target
@@ -197,7 +197,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
# /etc/containers/systemd/halo.container
[Unit]
Description=The halo container

View File

@@ -119,7 +119,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
[Unit]
Description=The halo container
Wants=network-online.target
@@ -197,7 +197,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
# /etc/containers/systemd/halo.container
[Unit]
Description=The halo container

View File

@@ -119,7 +119,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
[Unit]
Description=The halo container
Wants=network-online.target
@@ -197,7 +197,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
# /etc/containers/systemd/halo.container
[Unit]
Description=The halo container

View File

@@ -119,7 +119,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
[Unit]
Description=The halo container
Wants=network-online.target
@@ -197,7 +197,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
# /etc/containers/systemd/halo.container
[Unit]
Description=The halo container

View File

@@ -145,7 +145,7 @@ my-halo-plugin/
`api/build.gradle` 配置如下:
```gradle
```groovy
plugins {
id 'java-library'
id 'maven-publish'

View File

@@ -117,7 +117,7 @@ public class CustomEventPublisher {
1. 插件 A 将包含了 `CustomSharedEvent` 这个类的依赖 `plugin-a-api` 发布到 Maven 仓库
2. 插件 B 引入 `plugin-a-api` 作为项目依赖并将其作为 `compileOnly`,必须是 `compileOnly` 依赖
```gradle
```groovy
dependencies {
compileOnly "run.halo.example:plugin-a-api:1.0.0"
}

View File

@@ -123,7 +123,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
[Unit]
Description=The halo container
Wants=network-online.target
@@ -201,7 +201,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
# /etc/containers/systemd/halo.container
[Unit]
Description=The halo container

View File

@@ -7,7 +7,7 @@ description: 元数据表单组件
## 使用示例
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -7,7 +7,7 @@ description: 附件文件类型图标组件
## 使用示例
```html
```vue
<script lang="ts" setup></script>
<template>

View File

@@ -11,7 +11,7 @@ description: 附件选择组件
## 使用示例
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -5,7 +5,7 @@ description: 过滤器清除按钮组件
## 使用示例
```html
```vue
<script lang="ts" setup>
function onClear () {
console.log("clear")

View File

@@ -7,7 +7,7 @@ description: 过滤器下拉组件
## 使用示例
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -7,7 +7,7 @@ description: 权限判断组件
## 使用方式
```html
```vue
<script lang="ts" setup>
import { VButton } from "@halo-dev/components"
</script>

View File

@@ -17,7 +17,7 @@ pnpm install @halo-dev/components
在 Vue 组件中:
```html
```vue
<script lang="ts" setup>
import { VButton } from "@halo-dev/components";
</script>

View File

@@ -7,7 +7,7 @@ description: 插件详情弹窗组件
## 使用方式
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -7,7 +7,7 @@ description: 搜索输入框组件
## 使用方式
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -5,7 +5,7 @@ description: 文件上传组件
## 使用方式
```html
```vue
<script lang="ts" setup>
const policyName = ref('my-test-policy')
const groupName = ref('my-test-group')

View File

@@ -7,7 +7,7 @@ description: 代码编辑器组件
## 使用方式
```html
```vue
<script lang="ts" setup>
import { ref } from "vue"

View File

@@ -7,7 +7,7 @@ description: 权限指令
## 使用方式
```html
```vue
<script lang="ts" setup>
import { VButton } from "@halo-dev/components"
</script>

View File

@@ -7,7 +7,7 @@ description: Tooltip 指令
## 使用方式
```html
```vue
<script lang="ts" setup>
import { IconDeleteBin } from "@halo-dev/components"
</script>

View File

@@ -281,7 +281,7 @@ export default definePlugin({
3. 更新项目根目录的 `build.gradle` 文件
```gradle
```groovy
plugins {
id 'java'
id "io.freefair.lombok" version "8.13"
@@ -336,7 +336,7 @@ export default definePlugin({
4. 在 ui 或者 console 目录新建 `build.gradle` 文件,内容如下:
```gradle
```groovy
plugins {
id 'base'
id "com.github.node-gradle.node" version "7.1.0"

View File

@@ -241,7 +241,7 @@ export interface TodoList {
编辑 `ui/src/views/HomeView.vue` 文件,将所有内容替换为如下写法:
```typescript
```vue
<script setup lang="ts">
import axios from "axios";
import type { Todo, TodoList } from "../types";
@@ -466,14 +466,16 @@ const handleDelete = (todo: Todo) => {
需要修改 `ui/src/views/HomeView.vue` 示例如下:
```diff
+ import Logo from "@/assets/logo.svg";
```vue
// [!code ++]
import Logo from "@/assets/logo.svg";
// ...
<template>
<section class="todoapp">
<header class="header">
<h1>
+ <img :src="Logo" alt="logo" style="display: inline; width: 64px" />
// [!code ++]
<img :src="Logo" alt="logo" style="display: inline; width: 64px" />
todos
</h1>
//...

View File

@@ -95,7 +95,7 @@ export default definePlugin({
});
```
```html title="StickerSelectorProvider.vue"
```vue title="StickerSelectorProvider.vue"
<script lang="ts" setup>
const props = withDefaults(
defineProps<{

View File

@@ -87,7 +87,7 @@ export interface DashboardWidgetDefinition {
### 小部件组件开发
```html
```vue
<template>
<WidgetCard v-bind="$attrs" :body-class="['!p-0']">
<template #title>
@@ -221,7 +221,7 @@ export default definePlugin({
自定义组件:
```html
```vue
<template>
<div class="group relative cursor-pointer rounded-lg bg-blue-50 p-4 transition-all hover:bg-blue-100">
<div class="flex items-center gap-3">

View File

@@ -76,7 +76,7 @@ export default definePlugin({
});
```
```html title="./components/markdown-editor.vue"
```vue title="./components/markdown-editor.vue"
<script setup lang="ts">
import { marked } from "marked";
import { debounce } from "lodash-es";

View File

@@ -65,7 +65,7 @@ export default definePlugin({
});
```
```html title="./views/my-component.vue"
```vue title="./views/my-component.vue"
<script lang="ts" setup>
const plugin = inject<Ref<Plugin | undefined>>("plugin");
</script>

View File

@@ -145,7 +145,7 @@ my-halo-plugin/
`api/build.gradle` 配置如下:
```gradle
```groovy
plugins {
id 'java-library'
id 'maven-publish'

View File

@@ -122,7 +122,7 @@ public class CustomEventPublisher {
1. 插件 A 将包含了 `CustomSharedEvent` 这个类的依赖 `plugin-a-api` 发布到 Maven 仓库
2. 插件 B 引入 `plugin-a-api` 作为项目依赖并将其作为 `compileOnly`,必须是 `compileOnly` 依赖
```gradle
```groovy
dependencies {
compileOnly "run.halo.example:plugin-a-api:1.0.0"
}

View File

@@ -31,7 +31,7 @@ tar zxvf halo-offline-installer-v2.17.0-amd64.tar.gz
:::info
安装包目录说明
```text
```bash
[root@localhost halo-offline-installer-v2.17.0-amd64]# tree
.
├── docker # 离线安装 Docker 使用到的文件
@@ -75,7 +75,7 @@ cd halo-offline-installer-v2.17.0-amd64
:::info
假设采用默认安装位置 /opt/halo 完成安装,安装目录的文件结构如下:
```text
```bash
[root@meter-prototype halo]# tree
.
├── data # 数据存储目录

View File

@@ -123,7 +123,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
[Unit]
Description=The halo container
Wants=network-online.target
@@ -201,7 +201,7 @@ mkdir -p /etc/containers/systemd
vim /etc/containers/systemd/halo.container
```
```conf
```ini
# /etc/containers/systemd/halo.container
[Unit]
Description=The halo container