diff --git a/.markdownlint.json b/.markdownlint.json
index a991f3ff..967af391 100644
--- a/.markdownlint.json
+++ b/.markdownlint.json
@@ -21,5 +21,8 @@
},
"fenced-code-language": false,
"code-block-style": false,
- "emphasis-style": false
+ "emphasis-style": false,
+ "no-hard-tabs": {
+ "spaces_per_tab": 2
+ }
}
diff --git a/docs/.vuepress/notes.ts b/docs/.vuepress/notes.ts
index 9ff61d0c..fb958cae 100644
--- a/docs/.vuepress/notes.ts
+++ b/docs/.vuepress/notes.ts
@@ -12,20 +12,24 @@ export const zhNotes = definePlumeNotesConfig({
text: '快速开始',
collapsed: false,
icon: 'carbon:idea',
- items: ['介绍', '安装与使用', '博客', '知识笔记', '部署'],
+ items: ['介绍', '安装与使用', '博客', '知识笔记', '编写文章', '国际化', '部署'],
},
{
text: '写作',
icon: 'fluent-mdl2:edit-create',
collapsed: false,
items: [
- '编写文章',
- '国际化',
{
text: 'markdown',
icon: 'material-symbols:markdown-outline',
dir: 'markdown',
- items: ['基础', '扩展', '进阶', '试验性'],
+ items: ['基础', '扩展', '进阶'],
+ },
+ {
+ text: '代码块',
+ dir: '代码',
+ icon: 'ph:code-bold',
+ items: ['介绍', '特性支持', '代码组', '导入代码', 'codepen', 'jsFiddle', 'codeSandbox', 'replit', 'twoslash', '代码演示'],
},
{
text: '图表',
@@ -87,7 +91,7 @@ export const zhNotes = definePlumeNotesConfig({
text: '内置插件',
dir: 'plugins',
collapsed: false,
- items: ['', '代码复制', '代码高亮', '搜索', '阅读统计', 'markdown增强', '百度统计'],
+ items: ['', '代码复制', '代码高亮', '搜索', '阅读统计', 'markdown增强', 'markdownPower', '百度统计'],
},
],
},
@@ -102,6 +106,7 @@ export const zhNotes = definePlumeNotesConfig({
'caniuse',
'iconify',
'shiki',
+ 'md-power',
'content-updated',
{
text: 'plugin-netlify-functions',
diff --git a/docs/README.md b/docs/README.md
index 60737bc4..ef215379 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -78,7 +78,7 @@ config:
description: 支持全站加密、部分加密(加密目录、加密文章)。
-
title: 代码
- description: 代码复制,CodePen演示,Replit演示
+ description: 代码复制,CodePen演示,Replit演示,JSFiddle演示,CodeSandbox演示,\n代码组,行高亮,行聚焦,行警告,差异对比等。\n
-
title: 资源嵌入
description: 图表,视频,PDF
diff --git a/docs/notes/plugins/README.md b/docs/notes/plugins/README.md
index 534aa323..df6dacf3 100644
--- a/docs/notes/plugins/README.md
+++ b/docs/notes/plugins/README.md
@@ -14,4 +14,6 @@ permalink: /plugins/
- [@vuepress-plume/plugin-caniuse](/plugins/plugin-caniuse/)
- [@vuepress-plume/plugin-iconify](/plugins/plugin-iconify/)
- [@vuepress-plume/plugin-shikiji](/plugins/plugin-shikiji/)
+- [@vuepress-plume/plugin-content-update](/plugins/plugin-content-update/)
- [vuepress-plugin-netlify-functions](/plugins/plugin-netlify-functions/)
+- [vuepress-plugin-md-power](/plugins/plugin-md-power/)
diff --git a/docs/notes/plugins/md-power.md b/docs/notes/plugins/md-power.md
new file mode 100644
index 00000000..4aa7243a
--- /dev/null
+++ b/docs/notes/plugins/md-power.md
@@ -0,0 +1,282 @@
+---
+title: plugin-md-power
+author: pengzhanbo
+createTime: 2024/04/04 18:44:57
+permalink: /plugins/plugin-md-power/
+---
+
+## 指南
+
+插件为 vuepress markdown 注入更多的功能支持。
+
+其中,`@[xxx](xx)` 形式的语法,主要用于 资源嵌入类型的支持,包括 嵌入 PDF、视频、代码演示等。
+
+同时,还提供了其它的语法支持。
+
+## 安装
+
+::: code-tabs
+@tab npm
+
+``` sh
+npm install vuepress-plugin-md-power
+```
+
+@tab:active yarn
+
+``` sh
+yarn add vuepress-plugin-md-power
+```
+
+@tab pnpm
+
+``` sh
+pnpm add vuepress-plugin-md-power
+```
+
+:::
+
+## 使用
+
+```ts
+// .vuepress/config.ts
+import { markdownPowerPlugin } from 'vuepress-plugin-md-power'
+module.exports = {
+ // ...
+ plugins: [
+ markdownPowerPlugin({
+ pdf: true
+ })
+ ]
+ // ...
+}
+```
+
+## Options
+
+```ts
+interface MarkdownPowerPluginOptions {
+ pdf?: boolean | PDFOptions
+
+ // new syntax
+ icons?: boolean | IconsOptions
+
+ // video embed
+ bilibili?: boolean
+ youtube?: boolean
+
+ // code embed
+ codepen?: boolean
+ replit?: boolean
+ codeSandbox?: boolean
+ jsfiddle?: boolean
+
+ caniuse?: boolean | CanIUseOptions
+}
+```
+
+## 使用
+
+### caniuse
+
+插件默认不启用该功能,你需要手动设置 `caniuse` 为 `true`
+
+#### 语法
+
+```md
+@[caniuse](feature)
+@[caniuse image](feature)
+@[caniuse embed{versions}](feature)
+```
+
+你可以从 [caniuse](https://caniuse.bitsofco.de/) 获取 feature 的值。
+
+默认情况下,插件通过 `iframe` 嵌入 `caniuse` 的支持情况查看器。
+你也可以使用 `@[caniuse image](feature)` 直接嵌入图片。
+
+caniuse 默认查看最近的5个浏览器版本。你可以通过 `{versions}` 手动设置查看的浏览器版本。
+格式为 `{number,number,...}`。取值范围为 `-5 ~ 3` 。
+
+- 小于0 表示低于当前浏览器版本的支持情况
+- 0 表示当前浏览器版本的支持情况
+- 大于0 表示高于当前浏览器版本的支持情况
+
+如 `{-2,-1,1,2}` 表示查看低于当前 2 个版本 到 高于当前 2 个版本的支持情况。
+
+### pdf
+
+插件默认不启用该功能,你需要手动设置 `pdf` 为 `true`
+
+#### 语法
+
+```md
+@[pdf](url)
+@[pdf 1](url)
+@[pdf 1 no-toolbar width="100%" height="600px" zoom="1" ratio="16:9"](url)
+```
+
+`url` 只支持绝对路径以及完整的资源链接地址,请勿传入相对路径。
+
+你可以在 `pdf` 后紧跟空格,设置一个数字表示默认显示的 pdf 页码
+
+- `no-toolbar` 表示不显示工具栏
+- `width` 设置宽度
+- `height` 设置高度
+- `zoom` 设置缩放
+- `ratio` 设置宽高比, 仅当 `width` 有值, `height` 未设置时有效
+
+### icons
+
+插件默认不启用该功能,你需要手动设置 `icons` 为 `true`。
+
+你还需要手动安装 `@iconify/json` 依赖。
+
+```sh
+pnpm add @iconify/json
+```
+
+#### 语法
+
+```md
+:[collect:icon]:
+:[collect:icon size]:
+:[collect:icon /color]:
+:[collect:icon size/color]:
+```
+
+你可以从 [icon-sets.iconify](https://icon-sets.iconify.design/) 获取 图标集。
+
+显示 `logos` 图标集合下的 `vue` 图标
+
+```md
+:[logos:vue]:
+```
+
+图标默认大小为 `1em` ,你可以通过 `size` 设置图标大小
+
+```md
+:[logos:vue 1.2em]:
+```
+
+图标默认颜色为 `currentColor` 你可以通过 `/color` 设置图标颜色
+
+```md
+:[logos:vue /blue]:
+```
+
+也可以通过 `size/color` 设置图标大小和颜色
+
+```md
+:[logos:vue 1.2em/blue]:
+```
+
+### bilibili
+
+插件默认不启用该功能,你需要手动设置 `bilibili` 为 `true`
+
+#### 语法
+
+```md
+@[bilibili](bvid)
+@[bilibili autoplay time="0"](bvid)
+@[bilibili p1 autoplay time="0" ratio="16:9"](aid cid)
+```
+
+- 设置 `autoplay` 以自动播放视频。
+- 设置 `time` 以指定开始播放的时间点,单位为秒。还可以传入 `mm:ss` 或者 `hh:mm:ss`。
+- 如果为 分p(非合集),还可以设置 `p\d` (第\d 个分p),此时可以只传入 `aid` 和 `cid`。
+- 设置 `ratio` 以指定视频的宽高比。
+
+### youtube
+
+插件默认不启用该功能,你需要手动设置 `youtube` 为 `true`
+
+#### 语法
+
+```md
+@[youtube](id)
+@[youtube autoplay loop ratio="16:9" star="0" end="0"](id)
+```
+
+- `id` 为 YouTube 视频 ID
+- `autoplay` 为是否自动播放
+- `loop` 为是否循环播放
+- `ratio` 为视频的宽高比
+- `star` 为开始时间,单位为秒,还可以传入 `mm:ss` 或者 `hh:mm:ss`。
+- `end` 为结束时间,单位为秒,还可以传入 `mm:ss` 或者 `hh:mm:ss`。
+
+### CodePen
+
+插件默认不启用该功能,你需要手动设置 `codepen` 为 `true`
+
+#### 语法
+
+```md
+@[codepen](user/slash)
+@[codepen preview editable title="" height="400px" tab="css,result" theme="dark"](user/slash)
+```
+
+- `user` 为 CodePen 用户名
+- `slash` 为 CodePen slash
+- `preview` 为是否为预览模式
+- `editable` 为是否为可编辑模式
+- `title` 为标题
+- `height` 为高度
+- `tab` 为选项卡,默认为 `result`, 多个以逗号分隔,如 `css,result`
+- `theme` 为主题, 可选值包括 `dark` 和 `light`
+
+### Replit
+
+插件默认不启用该功能,你需要手动设置 `replit` 为 `true`
+
+#### 语法
+
+```md
+@[replit](user/repl-name)
+@[replit title="" height="450px" theme="dark"](user/repl-name#filepath)
+```
+
+- `user` 为 Replit 用户名
+- `repl-name` 为 Replit Repl 名
+- `filepath` 为文件路径
+- `title` 为标题
+- `height` 为高度
+- `theme` 为主题, 可选值包括 `dark` 和 `light`
+
+### CodeSandbox
+
+插件默认不启用该功能,你需要手动设置 `codesandbox` 为 `true`
+
+#### 语法
+
+```md
+@[codesandbox](id)
+@[codesandbox button](workspace/id)
+@[codesanbox title="xxx" layout="Editor+Preview" height="500px" navbar="false" console](id#filepath)
+```
+
+- `id`: Code Sandbox ID
+- `title`: Code Sandbox 标题
+- `layout`: 代码预览布局 可选值: `Preview`, `Editor`, `Editor+Preview`
+- `height`: 代码预览高度
+- `navbar`: 是否显示导航栏,默认为 true
+- `console`: 是否显示控制台,默认为 false
+- `filepath`: 文件路径
+
+### JSFiddle
+
+插件默认不启用该功能,你需要手动设置 `jsfiddle` 为 `true`
+
+#### 语法
+
+```md
+@[jsfiddle](user/id)
+@[jsfiddle theme="dark" tab="js,css,html,result" height="500px"](user/id)
+```
+
+- `user`: 用户
+- `id`: jsfiddle id
+- `theme`: 主题模式, 可选值: `"light" | "dark"`
+- `tab`: 选项卡, 可选值:`"js" | "css" | "html" | "result"`, 多个用 `","` 分割,
+ 顺序将决定选项卡的排序,默认为 `js,css,html,result`
+- `height`: 高度
diff --git a/docs/notes/theme/config/plugins/markdownPower.md b/docs/notes/theme/config/plugins/markdownPower.md
new file mode 100644
index 00000000..a49554f0
--- /dev/null
+++ b/docs/notes/theme/config/plugins/markdownPower.md
@@ -0,0 +1,42 @@
+---
+title: Markdown Power
+author: pengzhanbo
+createTime: 2024/04/04 06:56:33
+permalink: /config/plugin/markdown-power/
+---
+
+## 概述
+
+提供 Markdown 增强功能。
+
+关联插件: [@vuepress-plume/plugin-md-power](/)
+
+默认配置:
+
+```ts
+import { plumeTheme } from 'vuepress-theme-plume'
+import { defineUserConfig } from 'vuepress'
+
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: {
+ markdownPower: {
+ // 默认不启用任何功能,你需要手动开启它们
+ // pdf: true, // @[pdf](url) 嵌入 PDF 文件
+ // icons: true, // :[collect:name]: 内联 iconify 图标
+ // bilibili: true, // @[bilibili](bvid) 嵌入 bilibili 视频
+ // youtube: true, // @[youtube](id) 嵌入 youtube 视频
+ // codepen: true, // @[codepen](user/slash) 嵌入 codepen
+ // replit: true, // @[replit](user/repl-name) 嵌入 Replit
+ // codeSandbox: true, // @[codesandbox](id) 嵌入 CodeSandbox
+ // jsfiddle: true, // @[jsfiddle](id) 嵌入 jsfiddle
+ // caniuse: true, // @[caniuse](feature) 嵌入 caniuse
+ }
+ }
+ }),
+})
+```
+
+## 配置
+
+查看 [文档](/plugins/plugin-md-power/)
diff --git a/docs/notes/theme/config/plugins/markdown增强.md b/docs/notes/theme/config/plugins/markdown增强.md
index a3ade416..b74ba696 100644
--- a/docs/notes/theme/config/plugins/markdown增强.md
+++ b/docs/notes/theme/config/plugins/markdown增强.md
@@ -1,5 +1,5 @@
---
-title: markdown增强
+title: Markdown Enhance
author: pengzhanbo
createTime: 2024/03/06 20:25:36
permalink: /config/plugins/markdown-enhance/
diff --git a/docs/notes/theme/guide/markdown/扩展.md b/docs/notes/theme/guide/markdown/扩展.md
index 59bc9ccc..b731ae9e 100644
--- a/docs/notes/theme/guide/markdown/扩展.md
+++ b/docs/notes/theme/guide/markdown/扩展.md
@@ -222,383 +222,6 @@ console.log('Hello, VitePress!')
> [!CAUTION]
> 行为可能带来的负面影响。
-## 代码块中的语法高亮
-
-主题 使用 [Shiki](https://github.com/shikijs/shiki) 在 Markdown 代码块中使用彩色文本实现语法高亮。
-Shiki 支持多种编程语言。需要做的就是将有效的语言别名附加到代码块的开头:
-
-**输入:**
-
-````
-```js
-export default {
- name: 'MyComponent',
- // ...
-}
-```
-````
-
-````
-```html
-
-```
-````
-
-**输出:**
-
-```js
-export default {
- name: 'MyComponent',
- // ...
-}
-```
-
-```html
-
-```
-
-在 Shiki 的代码仓库中,可以找到 [合法的编程语言列表](https://shiki.style/languages)。
-
-## 在代码块中实现行高亮
-
-**输入:**
-
-````
-```js{4}
-export default {
- data () {
- return {
- msg: 'Highlighted!'
- }
- }
-}
-```
-````
-
-**输出:**
-
-```js{4}
-export default {
- data () {
- return {
- msg: 'Highlighted!'
- }
- }
-}
-```
-
-除了单行之外,还可以指定多个单行、多行,或两者均指定:
-
-- 多行:例如 `{5-8}`、`{3-10}`、`{10-17}`
-- 多个单行:例如 `{4,7,9}`
-- 多行与单行:例如 `{4,7-13,16,23-27,40}`
-
-**输入:**
-
-````
-```js{1,4,6-8}
-export default { // Highlighted
- data () {
- return {
- msg: `Highlighted!
- This line isn't highlighted,
- but this and the next 2 are.`,
- motd: 'VitePress is awesome',
- lorem: 'ipsum'
- }
- }
-}
-```
-````
-
-**输出:**
-
-```js{1,4,6-8}
-export default { // Highlighted
- data () {
- return {
- msg: `Highlighted!
- This line isn't highlighted,
- but this and the next 2 are.`,
- motd: 'VitePress is awesome',
- lorem: 'ipsum'
- }
- }
-}
-```
-
-也可以使用 `// [!code highlight]` 注释实现行高亮。
-
-**输入:**
-
-````
-```js
-export default {
- data () {
- return {
- msg: 'Highlighted!' // [\!code highlight]
- }
- }
-}
-```
-````
-
-**输出:**
-
-```js
-export default {
- data() {
- return {
- msg: 'Highlighted!' // [!code highlight]
- }
- }
-}
-```
-
-## 代码块中聚焦
-
-在某一行上添加 `// [!code focus]` 注释将聚焦它并模糊代码的其他部分。
-
-此外,可以使用 `// [!code focus:]` 定义要聚焦的行数。
-
-**输入:**
-
-````
-```js
-export default {
- data () {
- return {
- msg: 'Focused!' // [\!code focus]
- }
- }
-}
-```
-````
-
-**输出:**
-
-```js
-export default {
- data() {
- return {
- msg: 'Focused!' // [!code focus]
- }
- }
-}
-```
-
-## 代码块中的颜色差异
-
-在某一行添加 `// [!code --]` 或 `// [!code ++]` 注释将会为该行创建 diff,同时保留代码块的颜色。
-
-**输入:**
-
-````
-```js
-export default {
- data () {
- return {
- msg: 'Removed', // [\!code --]
- msg: 'Added' // [\!code ++]
- }
- }
-}
-```
-````
-
-**输出:**
-
-```js
-export default {
- data() {
- return {
- msg: 'Removed', // [!code --]
- msg: 'Added' // [!code ++]
- }
- }
-}
-```
-
-## 高亮“错误”和“警告”
-
-在某一行添加 `// [!code warning]` 或 `// [!code error]` 注释将会为该行相应的着色。
-
-**输入:**
-
-````
-```js
-export default {
- data () {
- return {
- msg: 'Error', // [\!code error]
- msg: 'Warning' // [\!code warning]
- }
- }
-}
-```
-````
-
-**输出:**
-
-```js
-export default {
- data() {
- return {
- msg: 'Error', // [!code error]
- msg: 'Warning' // [!code warning]
- }
- }
-}
-```
-
-## 代码块中 词高亮
-
-**输入:**
-
-````
-```ts
-export function foo() { // [\!code word:Hello]
- const msg = 'Hello World'
- console.log(msg) // prints Hello World
-}
-```
-````
-
-**输出:**
-
-```ts
-export function foo() { // [!code word:Hello]
- const msg = 'Hello World'
- console.log(msg) // prints Hello World
-}
-```
-
-你还可以指定高亮显示的次数,例如 `[!code word:options:2]` 会高亮显示近两个 `options`。
-
-**输入:**
-
-````
-```ts
-// [\!code word:options:2]
-const options = { foo: 'bar' }
-options.foo = 'baz'
-console.log(options.foo) // 这个不会被高亮显示
-```
-````
-
-**输出:**
-
-```ts
-// [!code word:options:2]
-const options = { foo: 'bar' }
-options.foo = 'baz'
-console.log(options.foo) // 这个不会被高亮显示
-```
-
-## 代码组
-
-可以像这样对多个代码块进行分组:
-
-**输入:**
-
-````md
-::: code-tabs
-@tab config.js
-```js
-/**
- * @type {import('vuepress').UserConfig}
- */
-const config = {
- // ..
-}
-
-export default config
-```
-
-@tab config.ts
-```ts
-import type { UserConfig } from 'vuepress'
-
-const config: UserConfig = {
- // ..
-}
-
-export default config
-```
-:::
-````
-
-**输出:**
-
-::: code-tabs
-@tab config.js
-
-```js
-/**
- * @type {import('vuepress').UserConfig}
- */
-const config = {
- // ..
-}
-
-export default config
-```
-
-@tab config.ts
-
-```ts
-import type { UserConfig } from 'vuepress'
-
-const config: UserConfig = {
- // ..
-}
-
-export default config
-```
-
-:::
-
-你还可以通过 `@tab:active`
-
-## 导入代码块
-
-**输入:**
-
-你可以使用下面的语法,从文件中导入代码块:
-
-```md
-@[code](../snippet/snippet-1.js)
-```
-
-**输出:**
-
-@[code](../../snippet/snippet-1.js)
-
-如果你只想导入这个文件的一部分:
-
-```md
-
-@[code{1-10}](../snippet/snippet-1.js)
-```
-
-代码语言会根据文件扩展名进行推断,但我们建议你显式指定:
-
-```md
-
-@[code js](../snippet/snippet-1.js)
-
-
-@[code js{2,4-5}](../foo.js)
-```
-
## 数学方程
**输入:**
diff --git a/docs/notes/theme/guide/markdown/进阶.md b/docs/notes/theme/guide/markdown/进阶.md
index 29c2f016..5ef2a619 100644
--- a/docs/notes/theme/guide/markdown/进阶.md
+++ b/docs/notes/theme/guide/markdown/进阶.md
@@ -1,5 +1,5 @@
---
-title: 高阶
+title: 更多
author: pengzhanbo
icon: ic:outline-auto-fix-high
createTime: 2024/03/05 16:27:59
@@ -392,147 +392,6 @@ export default defineUserConfig({
@[caniuse{-2,-1,1,2,3}](css-matches-pseudo)
-## CodePen
-
-主题支持在 Markdown 文件中嵌入 [CodePen](https://codepen.io/)。
-
-### 配置
-
-此功能默认不启用,你可以在配置文件中启用它。
-
-::: code-tabs
-@tab .vuepress/config.ts
-
-```ts
-export default defineUserConfig({
- theme: plumeTheme({
- plugins: {
- markdownPower: {
- codepen: true, // [!code highlight]
- },
- }
- })
-})
-```
-
-:::
-
-### 语法
-
-简单语法:
-
-```md
-@[codepen](user/slash)
-```
-
-更多选项支持:
-
-```md
-@[codepen preview editable tab="css,result" theme="dark" height="500px" width="100%"](user/slash)
-```
-
-- `preview`: 是否渲染为预览模式
-- `editable`: 是否可编辑
-- `tab`: 默认显示的标签, 默认为 `result`,多个使用 `,` 分隔
-- `theme`: 主题, 可选值 `dark` 和 `light`
-- `height`: 容器高度, 默认为 `400px`
-- `width`: 容器宽度, 默认为 `100%`
-- `user`: CodePen 用户名
-- `slash`: CodePen 代码文件名
-
-### 示例
-
-输入:
-
-```md
-@[codepen](leimapapa/RwOZQOW)
-```
-
-输出:
-
-@[codepen](leimapapa/RwOZQOW)
-
-**预览模式:**
-
-输入:
-
-```md
-@[codepen preview](leimapapa/RwOZQOW)
-```
-
-输出:
-
-@[codepen preview](leimapapa/RwOZQOW)
-
-**编辑模式:**
-
-输入:
-
-```md
-@[codepen editable tab="html,result"](leimapapa/RwOZQOW)
-```
-
-输出:
-
-@[codepen editable tab="html,result"](leimapapa/RwOZQOW)
-
-## Replit
-
-主题支持在 Markdown 文件中嵌入 [Replit](https://replit.com/)。
-
-### 配置
-
-此功能默认不启用,你可以在配置文件中启用它。
-
-::: code-tabs
-@tab .vuepress/config.ts
-
-```ts
-export default defineUserConfig({
- theme: plumeTheme({
- plugins: {
- markdownPower: {
- replit: true, // [!code highlight]
- },
- }
- })
-})
-```
-
-:::
-
-### 语法
-
-简单的语法
-
-```md
-@[replit](user/repl-name)
-```
-
-更多选项
-
-```md
-@[replit title="" width="100%" height="450px" theme="dark"](user/repl-name#filepath)
-```
-
-- `title`: 标题
-- `width`: 容器宽度
-- `height`: 容器高度
-- `theme`: 主题, 可选值 `dark` 和 `light`
-- `user`: Replit 用户名
-- `repl-name`: Replit repl 名称
-- `filepath`: Replit 默认打开的文件路径
-
-输入:
-
-```md
-@[replit](@TechPandaPro/Cursor-Hangout#package.json)
-````
-
-输出:
-
-@[replit](@TechPandaPro/Cursor-Hangout#package.json)
-
## 导入文件
主题支持在 Markdown 文件中导入文件切片。
@@ -705,458 +564,3 @@ export default defineUserConfig({
:::: demo-wrapper title="Include by file region"
::::
-
-## 代码演示
-
-代码演示 默认不启用,你可以通过配置来启用它。
-
-::: code-tabs
-@tab .vuepress/config.ts
-
-```ts
-export default defineUserConfig({
- theme: plumeTheme({
- plugins: {
- markdownEnhance: {
- demo: true,
- },
- }
- })
-})
-```
-
-:::
-
-### 语法
-
-```` md
-::: [类型]-demo 可选的标题文字
-
-```html
-
-
-
-```
-
-```json
-// json block 作为插件配置存放处
-{
- // 放置你的配置 (可选的)
-}
-```
-
-:::
-````
-
-::: tip 提示
-JSON 块是可选的,可用的配置详见[配置](https://vuepress-theme-hope.github.io/v2/md-enhance/zh/config.html)
-:::
-
-插件支持三种类型
-
-- normal(默认)
-- vue
-- react
-
-### 可用的语言
-
-你可以在演示块中使用不同语言。
-
-当你设置一些不能在浏览器上直接运行的语言时,由于插件无法解析它们,因此网页演示将被禁用。插件只显示代码。同时提供一个 "在 CodePen 中打开" 按钮允许用户直接在 CodePen 打开并浏览代码。
-
-可用的 HTML 语言:
-
-- `"html"` (默认)
-- `"slim"`
-- `"haml"`
-- `"markdown"`
-
-可用的 JS 语言:
-
-- `"javascript"` (default)
-- `"coffeescript"`
-- `"babel"`
-- `"livescript"`
-- `"typescript"`
-
-> 你也可以在代码块中使用 `js`, `ts`, `coffee` 和 `ls。`
-
-可用的 CSS 语言:
-
-- `"css"` (default)
-- `"less"`
-- `"scss"`
-- `"sass"`
-- `"stylus"`
-
-### 不支持的语言
-
-::: normal-demo 一个使用浏览器不支持解析语言 Demo
-
-```md
-# 标题
-
-十分强大
-```
-
-```ts
-const message: string = 'VuePress Theme Hope'
-
-document.querySelector('h1').innerHTML = message
-```
-
-```scss
-h1 {
- font-style: italic;
-
- + p {
- color: red;
- }
-}
-```
-
-:::
-
-:::: details 代码
-
-```` md
-::: normal-demo 一个使用浏览器不支持解析语言 Demo
-
-```md
-# 标题
-
-十分强大
-```
-
-```ts
-const message: string = 'VuePress Theme Hope'
-
-document.querySelector('h1').innerHTML = message
-```
-
-```scss
-h1 {
- font-style: italic;
-
- + p {
- color: red;
- }
-}
-```
-
-:::
-````
-
-::::
-
-### 普通代码演示
-
-格式:
-
-```` md
-::: normal-demo 可选的标题文字
-
-```html
-
-```
-
-```js
-// js code
-```
-
-```css
-/* css code */
-```
-
-```json
-// 配置 (可选)
-{
- "jsLib": [
- // ...
- ],
- "cssLib": [
- // ...
- ]
-}
-```
-
-:::
-````
-
-::: warning 注意事项
-我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document,请访问` `window.document`。
-:::
-
-#### 例子
-
-::: normal-demo Demo 演示
-
-```html
-Hello Word!
-非常强大!
-```
-
-```js
-document.querySelector('#very').addEventListener('click', () => {
- alert('非常强大')
-})
-```
-
-```css
-span {
- color: red;
-}
-```
-
-:::
-
-:::: details 代码
-
-```` md
-::: normal-demo Demo 演示
-
-```html
-Hello Word!
-非常强大!
-```
-
-```js
-document.querySelector('#very').addEventListener('click', () => {
- alert('非常强大')
-})
-```
-
-```css
-span {
- color: red;
-}
-```
-
-:::
-````
-
-::::
-
-### Vue 代码演示
-
-#### 格式
-
-```` md
-::: vue-demo 可选的标题文字
-
-```vue
-
-
-
-
-
- demo
-
-
-
-```
-
-```json
-// 配置 (可选)
-{}
-```
-
-:::
-````
-
-::: warning 注意事项
-
-- 你只能使用 `Vue3`。
-- 必须将组件通过 `export default` 默认导出
-- 我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document`,请访问 `window.document`。
-:::
-
-#### 演示
-
-::: vue-demo 一个 Vue Composition 演示
-
-```vue
-
-
-
-
- Hello Word is
- {{ message }}!
-
-
-
-
-```
-
-:::
-
-:::: details 代码
-
-```` md
-::: vue-demo 一个 Vue Composition 演示
-
-```vue
-
-
-
-
- Hello Word is
- {{ message }}!
-
-
-
-
-```
-
-:::
-````
-
-::::
-
-### React 代码演示
-
-#### 格式
-
-```` md
-::: react-demo 可选的标题文字
-
-```js
-// 放置脚本,并通过 `export default` 导出你的 react 组件
-```
-
-```css
-/* 你的 css 内容 */
-```
-
-```json
-// 配置 (可选)
-{}
-```
-
-:::
-````
-
-::: warning 注意事项
-
-- 使用 React 的时候,为了解析 JSX 必须引入 Babel,此过程由插件自动完成。
-- 必须将组件通过 `export default` 默认导出
-- 我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document`,请访问 `window.document`。
-:::
-
-#### 演示
-
-::: react-demo 一个函数式 React Demo
-
-```js
-const { useState } = React
-
-export default () => {
- const [message, setMessage] = useState(' 强大')
-
- const handler = () => {
- setMessage(`十分${message}`)
- }
-
- return (
-
- Hello Word !
-
- {message}
-
-
- )
-}
-```
-
-```css
-.box #powerful {
- color: blue;
-}
-```
-
-:::
-
-:::: details 代码
-
-```` md
-::: react-demo 一个函数式 React Demo
-
-```js
-const { useState } = React
-
-export default () => {
- const [message, setMessage] = useState(' 强大')
-
- const handler = () => {
- setMessage(`十分${message}`)
- }
-
- return (
-
- Hello Word !
-
- {message}
-
-
- )
-}
-```
-
-```css
-.box #powerful {
- color: blue;
-}
-```
-
-:::
-````
-
-::::
diff --git a/docs/notes/theme/guide/介绍.md b/docs/notes/theme/guide/介绍.md
index d1b89e2f..249a7778 100644
--- a/docs/notes/theme/guide/介绍.md
+++ b/docs/notes/theme/guide/介绍.md
@@ -42,6 +42,6 @@ VuePress 是一个 [静态站点生成器](https://en.wikipedia.org/wiki/Static_
- 👀 支持 搜索、文章评论
- 👨💻 支持 浅色/深色 主题 (包括代码高亮)
- 📠 markdown 增强,支持 代码块分组、提示容器、任务列表、数学公式、代码演示 等
-- 📚 代码演示,支持 CodePen, Replit
-- 📊 嵌入图标,支持 chart.js,Echarts,Mermaid,flowchart
+- 📚 代码演示,支持 CodePen, Replit, JSFiddle, CodeSandbox
+- 📊 嵌入图标,支持 chart.js,Echarts,Mermaid,flowchart 等
- 🎛 资源嵌入,支持 PDF, bilibili视频,youtube视频等
diff --git a/docs/notes/theme/guide/代码/codeSandbox.md b/docs/notes/theme/guide/代码/codeSandbox.md
new file mode 100644
index 00000000..76364d6d
--- /dev/null
+++ b/docs/notes/theme/guide/代码/codeSandbox.md
@@ -0,0 +1,82 @@
+---
+title: Code Sandbox
+author: pengzhanbo
+icon: lucide:codesandbox
+createTime: 2024/04/04 03:42:13
+permalink: /guide/code/code-sandbox/
+---
+
+主题支持在 Markdown 文件中嵌入 [Code Sandbox](https://codesandbox.io)。
+
+## 配置
+
+此功能默认不启用,你可以在配置文件中启用它。
+
+::: code-tabs
+@tab .vuepress/config.ts
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: {
+ markdownPower: {
+ codesandbox: true, // [!code highlight]
+ },
+ }
+ })
+})
+```
+
+:::
+
+## 语法
+
+### 简单语法
+
+将 Code Sandbox 嵌入到页面中
+
+```md
+@[codesandbox](id)
+```
+
+使用 Code Sandbox 跳转按钮
+
+```md
+@[codesandbox button](workspace/id)
+```
+
+### 更多选项
+
+```md
+@[codesanbox title="xxx" layout="Editor+Preview" height="500px" navbar="false" console](id#filepath)
+```
+
+- `id`: Code Sandbox ID
+- `title`: Code Sandbox 标题
+- `layout`: 代码预览布局 可选值: `Preview`, `Editor`, `Editor+Preview`
+- `height`: 代码预览高度
+- `navbar`: 是否显示导航栏,默认为 true
+- `console`: 是否显示控制台,默认为 false
+- `filepath`: 文件路径
+
+## 示例
+
+codeSandbox 跳转按钮:
+
+```md
+@[codesandbox button](reaction/5wyzu)
+```
+
+输出:
+
+@[codesandbox button](reaction/5wyzu)
+
+codeSandbox 内嵌到页面中:
+
+```md
+@[codesandbox](5wyzu)
+```
+
+输出:
+
+@[codesandbox](5wyzu)
diff --git a/docs/notes/theme/guide/代码/codepen.md b/docs/notes/theme/guide/代码/codepen.md
new file mode 100644
index 00000000..508a7a13
--- /dev/null
+++ b/docs/notes/theme/guide/代码/codepen.md
@@ -0,0 +1,89 @@
+---
+title: Code Pen
+author: pengzhanbo
+icon: mingcute:codepen-line
+createTime: 2024/04/04 10:41:58
+permalink: /guide/code/code-pen/
+---
+
+主题支持在 Markdown 文件中嵌入 [CodePen](https://codepen.io/)。
+
+## 配置
+
+此功能默认不启用,你可以在配置文件中启用它。
+
+::: code-tabs
+@tab .vuepress/config.ts
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: {
+ markdownPower: {
+ codepen: true, // [!code highlight]
+ },
+ }
+ })
+})
+```
+
+:::
+
+## 语法
+
+简单语法:
+
+```md
+@[codepen](user/slash)
+```
+
+更多选项支持:
+
+```md
+@[codepen preview editable tab="css,result" theme="dark" height="500px" width="100%"](user/slash)
+```
+
+- `preview`: 是否渲染为预览模式
+- `editable`: 是否可编辑
+- `tab`: 默认显示的标签, 默认为 `result`,多个使用 `,` 分隔
+- `theme`: 主题, 可选值 `dark` 和 `light`
+- `height`: 容器高度, 默认为 `400px`
+- `width`: 容器宽度, 默认为 `100%`
+- `user`: CodePen 用户名
+- `slash`: CodePen 代码文件名
+
+## 示例
+
+输入:
+
+```md
+@[codepen](leimapapa/RwOZQOW)
+```
+
+输出:
+
+@[codepen](leimapapa/RwOZQOW)
+
+**预览模式:**
+
+输入:
+
+```md
+@[codepen preview](leimapapa/RwOZQOW)
+```
+
+输出:
+
+@[codepen preview](leimapapa/RwOZQOW)
+
+**编辑模式:**
+
+输入:
+
+```md
+@[codepen editable tab="html,result"](leimapapa/RwOZQOW)
+```
+
+输出:
+
+@[codepen editable tab="html,result"](leimapapa/RwOZQOW)
diff --git a/docs/notes/theme/guide/代码/jsFiddle.md b/docs/notes/theme/guide/代码/jsFiddle.md
new file mode 100644
index 00000000..0fc0e63f
--- /dev/null
+++ b/docs/notes/theme/guide/代码/jsFiddle.md
@@ -0,0 +1,73 @@
+---
+title: Js Fiddle
+author: pengzhanbo
+icon: bxl:jsfiddle
+createTime: 2024/04/04 10:42:21
+permalink: /guide/code/jsfiddle/
+---
+
+主题支持在 Markdown 文件中嵌入 [JS Fiddle](https://jsfiddle.net/)。
+
+## 配置
+
+此功能默认不启用,你可以在配置文件中启用它。
+
+::: code-tabs
+@tab .vuepress/config.ts
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: {
+ markdownPower: {
+ jsfiddle: true, // [!code highlight]
+ },
+ }
+ })
+})
+```
+
+:::
+
+## 语法
+
+### 简单语法
+
+```md
+@[jsfiddle](user/id)
+```
+
+### 更多选项
+
+```md
+@[jsfiddle theme="dark" tab="js,css,html,result" height="500px"](user/id)
+```
+
+- `user`: 用户
+- `id`: jsfiddle id
+- `theme`: 主题模式, 可选值: `"light" | "dark"`
+- `tab`: 选项卡, 可选值:`"js" | "css" | "html" | "result"`, 多个用 `","` 分割,
+ 顺序将决定选项卡的排序,默认为 `js,css,html,result`
+- `height`: 高度
+
+## 示例
+
+输入:
+
+```md
+@[jsfiddle](pengzhanbo/1xbwz2p9)
+```
+
+输出:
+
+@[jsfiddle](pengzhanbo/1xbwz2p9)
+
+输入:
+
+```md
+@[jsfiddle tab="result,js,css,html"](pengzhanbo/1xbwz2p9)
+```
+
+输出:
+
+@[jsfiddle tab="result,js,css,html"](pengzhanbo/1xbwz2p9)
diff --git a/docs/notes/theme/guide/代码/replit.md b/docs/notes/theme/guide/代码/replit.md
new file mode 100644
index 00000000..eee3a3f9
--- /dev/null
+++ b/docs/notes/theme/guide/代码/replit.md
@@ -0,0 +1,64 @@
+---
+title: Replit
+author: pengzhanbo
+icon: simple-icons:replit
+createTime: 2024/04/04 10:42:05
+permalink: /guide/code/replit/
+---
+
+主题支持在 Markdown 文件中嵌入 [Replit](https://replit.com/)。
+
+## 配置
+
+此功能默认不启用,你可以在配置文件中启用它。
+
+::: code-tabs
+@tab .vuepress/config.ts
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: {
+ markdownPower: {
+ replit: true, // [!code highlight]
+ },
+ }
+ })
+})
+```
+
+:::
+
+## 语法
+
+简单的语法
+
+```md
+@[replit](user/repl-name)
+```
+
+更多选项
+
+```md
+@[replit title="" width="100%" height="450px" theme="dark"](user/repl-name#filepath)
+```
+
+- `title`: 标题
+- `width`: 容器宽度
+- `height`: 容器高度
+- `theme`: 主题, 可选值 `dark` 和 `light`
+- `user`: Replit 用户名
+- `repl-name`: Replit repl 名称
+- `filepath`: Replit 默认打开的文件路径
+
+## 示例
+
+输入:
+
+```md
+@[replit](@TechPandaPro/Cursor-Hangout#package.json)
+````
+
+输出:
+
+@[replit](@TechPandaPro/Cursor-Hangout#package.json)
diff --git a/docs/notes/theme/guide/markdown/试验性.md b/docs/notes/theme/guide/代码/twoslash.md
similarity index 99%
rename from docs/notes/theme/guide/markdown/试验性.md
rename to docs/notes/theme/guide/代码/twoslash.md
index f6a308c0..970cee10 100644
--- a/docs/notes/theme/guide/markdown/试验性.md
+++ b/docs/notes/theme/guide/代码/twoslash.md
@@ -1,5 +1,5 @@
---
-title: 试验性
+title: Two Slash
author: pengzhanbo
icon: material-symbols:experiment-outline
createTime: 2024/03/06 11:46:49
@@ -21,6 +21,7 @@ permalink: /guide/markdown/experiment/
> - [x] `vuepress@2.0.0-rc.2`
> - [x] `vuepress@2.0.0-rc.7`
> - [x] `vuepress@2.0.0-rc.8`
+> - [x] `vuepress@2.0.0-rc.9`
### 概述
diff --git a/docs/notes/theme/guide/代码/介绍.md b/docs/notes/theme/guide/代码/介绍.md
new file mode 100644
index 00000000..614cfd4c
--- /dev/null
+++ b/docs/notes/theme/guide/代码/介绍.md
@@ -0,0 +1,75 @@
+---
+title: 介绍
+author: pengzhanbo
+icon: ic:outline-code
+createTime: 2024/04/04 10:35:45
+permalink: /guide/code/intro/
+---
+
+## 概述
+
+主题 使用 [Shiki](https://github.com/shikijs/shiki) 在 Markdown 代码块实现语法高亮。
+
+## 语言
+
+[Shiki](https://github.com/shikijs/shiki) 支持 超过 190+ 种语言,
+你可以在 [languages](https://shiki.style/languages) 查看所有支持的语言列表。
+
+你可以通过以下语法为你使用的 语言所编写的代码 实现高亮效果:
+
+````md
+```[lang]
+```
+````
+
+其中,`[lang]` 为你使用的语言。
+
+示例:
+
+````md
+```js
+const a = 1
+console.log(a)
+```
+````
+
+```js
+const a = 1
+console.log(a)
+```
+
+## 高亮主题
+
+[Shiki](https://github.com/shikijs/shiki) 支持 超过 40+ 种高亮主题。
+
+你可以在 [Themes](https://shiki.style/themes) 找到所有支持的主题列表,根据个人的喜欢自定义
+高亮主题。
+
+Theme Plume 默认为 代码块使用的主题配置:
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: {
+ shiki: {
+ theme: { light: 'vitesse-light', dark: 'vitesse-dark' }, // [!code highlight]
+ }
+ }
+ })
+})
+```
+
+默认配置支持在 亮色/暗色 模式分别使用 `vitesse-light`/`vitesse-dark` 主题。
+
+## 更多支持
+
+得益于 [Shiki](https://github.com/shikijs/shiki) 的强大能力,Theme Plume 还为 代码块
+提供了 更多的 [特性支持](/guide/code/features/),它们让 代码块具备更强的表达能力。
+
+同时,为了方便 更好的 完成 代码演示,Theme Plume 还提供了嵌入 [CodePen](/guide/code/code-pen/),
+[Js Fiddle](/guide/code/jsfiddle/),[Code Sandbox](/guide/code/code-sandbox/),
+[Replit](/guide/code/replit/) 的语法支持,你可以很方便的嵌入代码演示。
+
+## 示例
+
+
diff --git a/docs/notes/theme/guide/代码/代码演示.md b/docs/notes/theme/guide/代码/代码演示.md
new file mode 100644
index 00000000..d4991a04
--- /dev/null
+++ b/docs/notes/theme/guide/代码/代码演示.md
@@ -0,0 +1,462 @@
+---
+title: 代码演示
+author: pengzhanbo
+icon: carbon:demo
+createTime: 2024/04/04 11:39:05
+permalink: /guide/code/demo/
+---
+
+## 概述
+
+代码演示 默认不启用,你可以通过配置来启用它。
+
+::: code-tabs
+@tab .vuepress/config.ts
+
+```ts
+export default defineUserConfig({
+ theme: plumeTheme({
+ plugins: {
+ markdownEnhance: {
+ demo: true,
+ },
+ }
+ })
+})
+```
+
+:::
+
+## 语法
+
+```` md
+::: [类型]-demo 可选的标题文字
+
+```html
+
+
+
+```
+
+```json
+// json block 作为插件配置存放处
+{
+ // 放置你的配置 (可选的)
+}
+```
+
+:::
+````
+
+::: tip 提示
+JSON 块是可选的,可用的配置详见[配置](https://vuepress-theme-hope.github.io/v2/md-enhance/zh/config.html)
+:::
+
+插件支持三种类型
+
+- normal(默认)
+- vue
+- react
+
+## 可用的语言
+
+你可以在演示块中使用不同语言。
+
+当你设置一些不能在浏览器上直接运行的语言时,由于插件无法解析它们,因此网页演示将被禁用。插件只显示代码。同时提供一个 "在 CodePen 中打开" 按钮允许用户直接在 CodePen 打开并浏览代码。
+
+可用的 HTML 语言:
+
+- `"html"` (默认)
+- `"slim"`
+- `"haml"`
+- `"markdown"`
+
+可用的 JS 语言:
+
+- `"javascript"` (default)
+- `"coffeescript"`
+- `"babel"`
+- `"livescript"`
+- `"typescript"`
+
+> 你也可以在代码块中使用 `js`, `ts`, `coffee` 和 `ls。`
+
+可用的 CSS 语言:
+
+- `"css"` (default)
+- `"less"`
+- `"scss"`
+- `"sass"`
+- `"stylus"`
+
+## 不支持的语言
+
+::: normal-demo 一个使用浏览器不支持解析语言 Demo
+
+```md
+# 标题
+
+十分强大
+```
+
+```ts
+const message: string = 'VuePress Theme Hope'
+
+document.querySelector('h1').innerHTML = message
+```
+
+```scss
+h1 {
+ font-style: italic;
+
+ + p {
+ color: red;
+ }
+}
+```
+
+:::
+
+:::: details 代码
+
+```` md
+::: normal-demo 一个使用浏览器不支持解析语言 Demo
+
+```md
+# 标题
+
+十分强大
+```
+
+```ts
+const message: string = 'VuePress Theme Hope'
+
+document.querySelector('h1').innerHTML = message
+```
+
+```scss
+h1 {
+ font-style: italic;
+
+ + p {
+ color: red;
+ }
+}
+```
+
+:::
+````
+
+::::
+
+## 普通代码演示
+
+格式:
+
+```` md
+::: normal-demo 可选的标题文字
+
+```html
+
+```
+
+```js
+// js code
+```
+
+```css
+/* css code */
+```
+
+```json
+// 配置 (可选)
+{
+ "jsLib": [
+ // ...
+ ],
+ "cssLib": [
+ // ...
+ ]
+}
+```
+
+:::
+````
+
+::: warning 注意事项
+我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document,请访问` `window.document`。
+:::
+
+## 例子
+
+::: normal-demo Demo 演示
+
+```html
+Hello Word!
+非常强大!
+```
+
+```js
+document.querySelector('#very').addEventListener('click', () => {
+ alert('非常强大')
+})
+```
+
+```css
+span {
+ color: red;
+}
+```
+
+:::
+
+:::: details 代码
+
+```` md
+::: normal-demo Demo 演示
+
+```html
+Hello Word!
+非常强大!
+```
+
+```js
+document.querySelector('#very').addEventListener('click', () => {
+ alert('非常强大')
+})
+```
+
+```css
+span {
+ color: red;
+}
+```
+
+:::
+````
+
+::::
+
+### Vue 代码演示
+
+#### 格式
+
+```` md
+::: vue-demo 可选的标题文字
+
+```vue
+
+
+
+
+
+ demo
+
+
+
+```
+
+```json
+// 配置 (可选)
+{}
+```
+
+:::
+````
+
+::: warning 注意事项
+
+- 你只能使用 `Vue3`。
+- 必须将组件通过 `export default` 默认导出
+- 我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document`,请访问 `window.document`。
+:::
+
+#### 演示
+
+::: vue-demo 一个 Vue Composition 演示
+
+```vue
+
+
+
+
+ Hello Word is
+ {{ message }}!
+
+
+
+
+```
+
+:::
+
+:::: details 代码
+
+```` md
+::: vue-demo 一个 Vue Composition 演示
+
+```vue
+
+
+
+
+ Hello Word is
+ {{ message }}!
+
+
+
+
+```
+
+:::
+````
+
+::::
+
+### React 代码演示
+
+#### 格式
+
+```` md
+::: react-demo 可选的标题文字
+
+```js
+// 放置脚本,并通过 `export default` 导出你的 react 组件
+```
+
+```css
+/* 你的 css 内容 */
+```
+
+```json
+// 配置 (可选)
+{}
+```
+
+:::
+````
+
+::: warning 注意事项
+
+- 使用 React 的时候,为了解析 JSX 必须引入 Babel,此过程由插件自动完成。
+- 必须将组件通过 `export default` 默认导出
+- 我们使用 `"ShadowDOM"` 进行样式隔离,并已经将 `document` 替换为了 `shadowRoot` 对象。如果需要访问页面的 `document`,请访问 `window.document`。
+:::
+
+#### 演示
+
+::: react-demo 一个函数式 React Demo
+
+```js
+const { useState } = React
+
+export default () => {
+ const [message, setMessage] = useState(' 强大')
+
+ const handler = () => {
+ setMessage(`十分${message}`)
+ }
+
+ return (
+
+ Hello Word !
+
+ {message}
+
+
+ )
+}
+```
+
+```css
+.box #powerful {
+ color: blue;
+}
+```
+
+:::
+
+:::: details 代码
+
+```` md
+::: react-demo 一个函数式 React Demo
+
+```js
+const { useState } = React
+
+export default () => {
+ const [message, setMessage] = useState(' 强大')
+
+ const handler = () => {
+ setMessage(`十分${message}`)
+ }
+
+ return (
+
+ Hello Word !
+
+ {message}
+
+
+ )
+}
+```
+
+```css
+.box #powerful {
+ color: blue;
+}
+```
+
+:::
+````
+
+::::
diff --git a/docs/notes/theme/guide/代码/代码组.md b/docs/notes/theme/guide/代码/代码组.md
new file mode 100644
index 00000000..c189e04f
--- /dev/null
+++ b/docs/notes/theme/guide/代码/代码组.md
@@ -0,0 +1,72 @@
+---
+title: 代码组
+author: pengzhanbo
+icon: fluent:group-list-20-filled
+createTime: 2024/04/04 10:36:59
+permalink: /guide/code/group/
+---
+
+## 语法
+
+可以像这样对多个代码块进行分组:
+
+**输入:**
+
+````md
+::: code-tabs
+@tab config.js
+```js
+/**
+ * @type {import('vuepress').UserConfig}
+ */
+const config = {
+ // ..
+}
+
+export default config
+```
+
+@tab config.ts
+```ts
+import type { UserConfig } from 'vuepress'
+
+const config: UserConfig = {
+ // ..
+}
+
+export default config
+```
+:::
+````
+
+**输出:**
+
+::: code-tabs
+@tab config.js
+
+```js
+/**
+ * @type {import('vuepress').UserConfig}
+ */
+const config = {
+ // ..
+}
+
+export default config
+```
+
+@tab config.ts
+
+```ts
+import type { UserConfig } from 'vuepress'
+
+const config: UserConfig = {
+ // ..
+}
+
+export default config
+```
+
+:::
+
+你还可以通过 `@tab:active` 选择其中一个代码块作为默认显示的代码块。
diff --git a/docs/notes/theme/guide/代码/导入代码.md b/docs/notes/theme/guide/代码/导入代码.md
new file mode 100644
index 00000000..7fb470a9
--- /dev/null
+++ b/docs/notes/theme/guide/代码/导入代码.md
@@ -0,0 +1,44 @@
+---
+title: 导入代码
+author: pengzhanbo
+icon: mdi:import
+createTime: 2024/04/04 10:39:22
+permalink: /guide/code/import/
+---
+
+## 概述
+
+导入代码 可以让你在 md 文件中 导入另一个文件的 代码,并为其高亮显示。
+
+它可以帮助你在文章中引用其他文件的代码,避免编写重复的代码。
+
+## 语法
+
+你可以使用下面的语法,从文件中导入代码块:
+
+**输入:**
+
+```md
+@[code](../snippet/snippet-1.js)
+```
+
+**输出:**
+
+@[code](../../snippet/snippet-1.js)
+
+如果你只想导入这个文件的一部分:
+
+```md
+
+@[code{1-10}](../snippet/snippet-1.js)
+```
+
+代码语言会根据文件扩展名进行推断,但我们建议你显式指定:
+
+```md
+
+@[code js](../snippet/snippet-1.js)
+
+
+@[code js{2,4-5}](../foo.js)
+```
diff --git a/docs/notes/theme/guide/代码/特性支持.md b/docs/notes/theme/guide/代码/特性支持.md
new file mode 100644
index 00000000..1b10ecdf
--- /dev/null
+++ b/docs/notes/theme/guide/代码/特性支持.md
@@ -0,0 +1,247 @@
+---
+title: 特性支持
+author: pengzhanbo
+icon: majesticons:code-block-line
+createTime: 2024/04/04 10:41:28
+permalink: /guide/code/features/
+---
+
+主题在代码高亮功能上,进一步支持了更多的特性,它们能够帮助你的代码块更加具备表达力。
+
+## 在代码块中实现行高亮
+
+在 `[lang]` 之后紧跟随 `{xxxx}` ,可以实现行高亮,其中 `xxx` 表示要高亮的行号。
+
+**输入:**
+
+````
+```js{4}
+export default {
+ data () {
+ return {
+ msg: 'Highlighted!'
+ }
+ }
+}
+```
+````
+
+**输出:**
+
+```js{4}
+export default {
+ data () {
+ return {
+ msg: 'Highlighted!'
+ }
+ }
+}
+```
+
+除了单行之外,还可以指定多个单行、多行,或两者均指定:
+
+- 多行:例如 `{5-8}`、`{3-10}`、`{10-17}`
+- 多个单行:例如 `{4,7,9}`
+- 多行与单行:例如 `{4,7-13,16,23-27,40}`
+
+**输入:**
+
+````
+```js{1,4,6-8}
+export default { // Highlighted
+ data () {
+ return {
+ msg: `Highlighted!
+ This line isn't highlighted,
+ but this and the next 2 are.`,
+ motd: 'VitePress is awesome',
+ lorem: 'ipsum'
+ }
+ }
+}
+```
+````
+
+**输出:**
+
+```js{1,4,6-8}
+export default { // Highlighted
+ data () {
+ return {
+ msg: `Highlighted!
+ This line isn't highlighted,
+ but this and the next 2 are.`,
+ motd: 'VitePress is awesome',
+ lorem: 'ipsum'
+ }
+ }
+}
+```
+
+也可以使用 `// [!code highlight]` 注释实现行高亮。
+
+**输入:**
+
+````
+```js
+export default {
+ data () {
+ return {
+ msg: 'Highlighted!' // [\!code highlight]
+ }
+ }
+}
+```
+````
+
+**输出:**
+
+```js
+export default {
+ data() {
+ return {
+ msg: 'Highlighted!' // [!code highlight]
+ }
+ }
+}
+```
+
+## 代码块中聚焦
+
+在某一行上添加 `// [!code focus]` 注释将聚焦它并模糊代码的其他部分。
+
+此外,可以使用 `// [!code focus:]` 定义要聚焦的行数。
+
+**输入:**
+
+````
+```js
+export default {
+ data () {
+ return {
+ msg: 'Focused!' // [\!code focus]
+ }
+ }
+}
+```
+````
+
+**输出:**
+
+```js
+export default {
+ data() {
+ return {
+ msg: 'Focused!' // [!code focus]
+ }
+ }
+}
+```
+
+## 代码块中的颜色差异
+
+在某一行添加 `// [!code --]` 或 `// [!code ++]` 注释将会为该行创建 diff,同时保留代码块的颜色。
+
+**输入:**
+
+````
+```js
+export default {
+ data () {
+ return {
+ msg: 'Removed', // [\!code --]
+ msg: 'Added' // [\!code ++]
+ }
+ }
+}
+```
+````
+
+**输出:**
+
+```js
+export default {
+ data() {
+ return {
+ msg: 'Removed', // [!code --]
+ msg: 'Added' // [!code ++]
+ }
+ }
+}
+```
+
+## 高亮“错误”和“警告”
+
+在某一行添加 `// [!code warning]` 或 `// [!code error]` 注释将会为该行相应的着色。
+
+**输入:**
+
+````
+```js
+export default {
+ data () {
+ return {
+ msg: 'Error', // [\!code error]
+ msg: 'Warning' // [\!code warning]
+ }
+ }
+}
+```
+````
+
+**输出:**
+
+```js
+export default {
+ data() {
+ return {
+ msg: 'Error', // [!code error]
+ msg: 'Warning' // [!code warning]
+ }
+ }
+}
+```
+
+## 代码块中 词高亮
+
+**输入:**
+
+````
+```ts
+export function foo() { // [\!code word:Hello]
+ const msg = 'Hello World'
+ console.log(msg) // prints Hello World
+}
+```
+````
+
+**输出:**
+
+```ts
+export function foo() { // [!code word:Hello]
+ const msg = 'Hello World'
+ console.log(msg) // prints Hello World
+}
+```
+
+你还可以指定高亮显示的次数,例如 `[!code word:options:2]` 会高亮显示近两个 `options`。
+
+**输入:**
+
+````
+```ts
+// [\!code word:options:2]
+const options = { foo: 'bar' }
+options.foo = 'baz'
+console.log(options.foo) // 这个不会被高亮显示
+```
+````
+
+**输出:**
+
+```ts
+// [!code word:options:2]
+const options = { foo: 'bar' }
+options.foo = 'baz'
+console.log(options.foo) // 这个不会被高亮显示
+```
diff --git a/docs/notes/theme/guide/安装与使用.md b/docs/notes/theme/guide/安装与使用.md
index 69cd9293..7c412da4 100644
--- a/docs/notes/theme/guide/安装与使用.md
+++ b/docs/notes/theme/guide/安装与使用.md
@@ -95,7 +95,7 @@ npm i -D vuepress-theme-plume @vuepress/bundler-vite@next
:::
:::warning
-主题当前版本 已适配至 `vuepress@2.0.0-rc.8`,你应该安装这个版本的 VuePress。
+主题当前版本 已适配至 `vuepress@2.0.0-rc.9`,你应该安装这个版本的 VuePress。
高于或低于这个版本,可能会存在潜在的兼容性问题。
:::
diff --git a/docs/notes/theme/guide/编写文章.md b/docs/notes/theme/guide/编写文章.md
index f573fc5e..4d9678fe 100644
--- a/docs/notes/theme/guide/编写文章.md
+++ b/docs/notes/theme/guide/编写文章.md
@@ -50,4 +50,4 @@ __example:__
## 文章写作
你可以使用 `markdown` 语法开始在 `sourceDir` 下新建 `Markdown` 文件,编写你自己的文章了,
-关于 markdown 扩展的功能支持,请查看 [这个文档](/guide/markdown/)。
+关于 markdown 扩展的功能支持,请查看 [这个文档](/guide/markdown/extensions/)。
diff --git a/docs/notes/theme/snippet/code-block.snippet.md b/docs/notes/theme/snippet/code-block.snippet.md
new file mode 100644
index 00000000..3f13ba24
--- /dev/null
+++ b/docs/notes/theme/snippet/code-block.snippet.md
@@ -0,0 +1,1176 @@
+::: code-tabs
+@tab C
+
+``` c
+#include
+
+#define ARR_LEN 7
+
+void qsort(int v[], int left, int right);
+void printArr(int v[], int len);
+
+int main()
+{
+ int i;
+ int v[ARR_LEN] = { 4, 3, 1, 7, 9, 6, 2 };
+ printArr(v, ARR_LEN);
+ qsort(v, 0, ARR_LEN-1);
+ printArr(v, ARR_LEN);
+ return 0;
+}
+
+void qsort(int v[], int left, int right)
+{
+ int i, last;
+ void swap(int v[], int i, int j);
+
+ if (left >= right)
+ return;
+ swap(v, left, (left + right) / 2);
+ last = left;
+ for (i = left+1; i <= right; i++)
+ if (v[i] < v[left])
+ swap(v, ++last, i);
+ swap(v, left, last);
+ qsort(v, left, last-1);
+ qsort(v, last+1, right);
+}
+
+void swap(int v[], int i, int j)
+{
+ int temp;
+
+ temp = v[i];
+ v[i] = v[j];
+ v[j] = temp;
+}
+
+void printArr(int v[], int len)
+{
+ int i;
+ for (i = 0; i < len; i++)
+ printf("%d ", v[i]);
+ printf("\n");
+}
+```
+
+@tab C++
+
+```c++
+// Working of implicit type-conversion
+
+#include
+using namespace std;
+
+int main() {
+
+ int num_int;
+ double num_double = 9.99;
+
+ // implicit conversion
+ // assigning a double value to an int variable
+ num_int = num_double;
+
+ cout << "num_int = " << num_int << endl;
+ cout << "num_double = " << num_double << endl;
+
+ return 0;
+}
+```
+
+@tab Java
+
+```java
+import java.awt.Rectangle;
+
+public class ObjectVarsAsParameters
+{ public static void main(String[] args)
+ { go();
+ }
+
+ public static void go()
+ { Rectangle r1 = new Rectangle(0,0,5,5);
+ System.out.println("In method go. r1 " + r1 + "\n");
+ // could have been
+ //System.out.prinltn("r1" + r1.toString());
+ r1.setSize(10, 15);
+ System.out.println("In method go. r1 " + r1 + "\n");
+ alterPointee(r1);
+ System.out.println("In method go. r1 " + r1 + "\n");
+
+ alterPointer(r1);
+ System.out.println("In method go. r1 " + r1 + "\n");
+ }
+
+ public static void alterPointee(Rectangle r)
+ { System.out.println("In method alterPointee. r " + r + "\n");
+ r.setSize(20, 30);
+ System.out.println("In method alterPointee. r " + r + "\n");
+ }
+
+ public static void alterPointer(Rectangle r)
+ { System.out.println("In method alterPointer. r " + r + "\n");
+ r = new Rectangle(5, 10, 30, 35);
+ System.out.println("In method alterPointer. r " + r + "\n");
+ }
+
+}
+```
+
+@tab Kotlin
+
+```kotlin
+package com.example.kotlin
+
+import java.util.Random as Rand
+import android.support.v7.app.AppCompatActivity
+import org.amshove.kluent.`should equal` as Type
+
+fun main(@NonNull args: Array) {
+ println("Hello Kotlin! ${/*test*/}")
+
+ val map = mutableMapOf("A" to "B")
+
+ thing.apply("random string here \n\t\r")
+ thing.let { test: -> }
+
+ val string = "${getThing()}"
+}
+
+val items = listOf("apple", "banana", "kiwifruit")
+var x = 9
+const val CONSTANT = 99
+
+@get:Rule
+val activityRule = ActivityTestRule(SplashActivity::class.java)
+
+val oneMillion = 1_000_000
+val creditCardNumber = 1234_5678_9012_3456L
+val socialSecurityNumber = 999_99_9999L
+val hexBytes = 0xFF_EC_DE_5E
+val float = 0.043_331F
+val bytes = 0b11010010_01101001_10010100_10010010
+
+if(test == "") {
+ 1 and 2 not 3
+} else {
+
+}
+
+fun foo() {
+ val x = Bar::class
+ val y = hello?.test
+}
+
+suspend fun SequenceBuilder.yieldIfOdd(x: Int) {
+ if (x % 2 != 0) yield(x)
+}
+
+val function = fun(@Inject x: Int, y: Int, lamda: (A, B) -> Unit): Int {
+ test.test()
+ return x + y;
+}
+
+abstract fun onCreate(savedInstanceState: Bundle?)
+
+fun isOdd(x: Int) = x % 2 != 0
+fun isOdd(s: String) = s == "brillig" || s == "slithy" || s == "tove"
+
+val numbers = listOf(1, 2, 3)
+println(numbers.filter(::isOdd))
+
+fun foo(node: Node?): String? {
+ val parent = node.getParent() ?: return null
+}
+
+interface Greetable {
+ fun greet()
+}
+
+open class Greeter: Greetable {
+ companion object {
+ private const val GREETING = "Hello, World!"
+ }
+
+ override fun greet() {
+ println(GREETING)
+ }
+}
+
+expect class Foo(bar: String) {
+ fun frob()
+}
+
+actual class Foo actual constructor(val bar: String) {
+ actual fun frob() {
+ println("Frobbing the $bar")
+ }
+}
+
+expect fun formatString(source: String, vararg args: Any): String
+expect annotation class Test
+
+actual fun formatString(source: String, vararg args: Any) = String.format(source, args)
+actual typealias Test = org.junit.Test
+
+sealed class Expr
+data class Const(val number: Double) : Expr()
+data class Sum(val e1: Expr, val e2: Expr) : Expr()
+object NotANumber : Expr()
+
+@file:JvmName("Foo")
+private sealed class InjectedClass @Inject constructor(
+ val test: Int = 50,
+ var anotherVar: String = "hello world"
+) : SomeSuperClass(test, anotherVar) {
+
+ init {
+ //
+ }
+
+ constructor(param1: String, param2: Int): this(param1, param2) {
+ //
+ }
+
+ companion object {
+ //
+ }
+}
+annotation class Suspendable
+val f = @Suspendable { Fiber.sleep(10) }
+
+private data class Foo(
+ /**
+ * ```
+ * ($)
+ * ```
+ */
+ val variables: Map
+)
+
+data class Response(@SerializedName("param1") val param1: String,
+ @SerializedName("param2") val param2: String,
+ @SerializedName("param3") val param3: String) {
+}
+
+object DefaultListener : MouseAdapter() {
+ override fun mouseClicked(e: MouseEvent) { }
+
+ override fun mouseEntered(e: MouseEvent) { }
+}
+
+class Feature : Node("Title", "Content", "Description") {
+
+}
+
+class Outer {
+ inner class Inner {}
+}
+```
+
+@tab Python
+
+```py
+def fib(n): # write Fibonacci series up to n
+ """Print a Fibonacci series up to n."""
+ a, b = 0, 1
+ while a < n:
+ print(a, end=' ')
+ a, b = b, a+b
+ print()
+
+# Now call the function we just defined:
+fib(2000)
+```
+
+@tab Go
+
+```go
+package main
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+)
+
+func handler(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
+}
+
+func main() {
+ http.HandleFunc("/", handler)
+ log.Fatal(http.ListenAndServe(":8080", nil))
+}
+```
+
+@tab Ruby
+
+```ruby
+class LotteryTicket
+
+ NUMERIC_RANGE = 1..25
+
+ attr_reader :picks, :purchased
+
+ def initialize( *picks )
+ if picks.length != 3
+ raise ArgumentError, "three numbers must be picked"
+ elsif picks.uniq.length != 3
+ raise ArgumentError, "the three picks must be different numbers"
+ elsif picks.detect { |p| not NUMERIC_RANGE === p }
+ raise ArgumentError, "the three picks must be numbers between 1 and 25"
+ end
+ @picks = picks
+ @purchased = Time.now
+ end
+
+end
+```
+
+@tab Makefile
+
+```make
+edit : main.o kbd.o command.o display.o \
+ insert.o search.o files.o utils.o
+ cc -o edit main.o kbd.o command.o display.o \
+ insert.o search.o files.o utils.o
+
+main.o : main.c defs.h
+ cc -c main.c
+kbd.o : kbd.c defs.h command.h
+ cc -c kbd.c
+command.o : command.c defs.h command.h
+ cc -c command.c
+display.o : display.c defs.h buffer.h
+ cc -c display.c
+insert.o : insert.c defs.h buffer.h
+ cc -c insert.c
+search.o : search.c defs.h buffer.h
+ cc -c search.c
+files.o : files.c defs.h buffer.h command.h
+ cc -c files.c
+utils.o : utils.c defs.h
+ cc -c utils.c
+clean :
+ rm edit main.o kbd.o command.o display.o \
+ insert.o search.o files.o utils.o
+```
+
+@tab Object-C
+
+```objc
+@interface classname : superclassname {
+ // instance variables
+}
++ classMethod1;
++ (return_type)classMethod2;
++ (return_type)classMethod3:(param1_type)param1_varName;
+
+- (return_type)instanceMethod1With1Parameter:(param1_type)param1_varName;
+- (return_type)instanceMethod2With2Parameters:(param1_type)param1_varName
+ param2_callName:(param2_type)param2_varName;
+@end
+```
+
+@tab Swift
+
+```swift
+class Residence {
+ var rooms: [Room] = []
+ var numberOfRooms: Int {
+ return rooms.count
+ }
+ subscript(i: Int) -> Room {
+ get {
+ return rooms[i]
+ }
+ set {
+ rooms[i] = newValue
+ }
+ }
+ func printNumberOfRooms() {
+ print("The number of rooms is \(numberOfRooms)")
+ }
+ var address: Address?
+}
+```
+
+@tab PHP
+
+```php
+command('inspire')->hourly();
+ }
+
+ /**
+ * Register the commands for the application.
+ */
+ protected function commands(): void
+ {
+ $this->load(__DIR__.'/Commands');
+
+ require base_path('routes/console.php');
+ }
+}
+```
+
+@tab Rust
+
+```rs
+// Unlike C/C++, there's no restriction on the order of function definitions
+fn main() {
+ // We can use this function here, and define it somewhere later
+ fizzbuzz_to(100);
+}
+
+// Function that returns a boolean value
+fn is_divisible_by(lhs: u32, rhs: u32) -> bool {
+ // Corner case, early return
+ if rhs == 0 {
+ return false;
+ }
+
+ // This is an expression, the `return` keyword is not necessary here
+ lhs % rhs == 0
+}
+
+// Functions that "don't" return a value, actually return the unit type `()`
+fn fizzbuzz(n: u32) -> () {
+ if is_divisible_by(n, 15) {
+ println!("fizzbuzz");
+ } else if is_divisible_by(n, 3) {
+ println!("fizz");
+ } else if is_divisible_by(n, 5) {
+ println!("buzz");
+ } else {
+ println!("{}", n);
+ }
+}
+
+// When a function returns `()`, the return type can be omitted from the
+// signature
+fn fizzbuzz_to(n: u32) {
+ for n in 1..=n {
+ fizzbuzz(n);
+ }
+}
+```
+
+@tab SQL
+
+```sql
+USE AdventureWorks2022;
+GO
+IF OBJECT_ID('dbo.NewProducts', 'U') IS NOT NULL
+ DROP TABLE dbo.NewProducts;
+GO
+ALTER DATABASE AdventureWorks2022 SET RECOVERY BULK_LOGGED;
+GO
+
+SELECT * INTO dbo.NewProducts
+FROM Production.Product
+WHERE ListPrice > $25
+AND ListPrice < $100;
+GO
+ALTER DATABASE AdventureWorks2022 SET RECOVERY FULL;
+GO
+```
+
+@tab XML
+
+```xml
+
+
+
+ Gambardella, Matthew
+ XML Developer's Guide
+ Computer
+ 44.95
+ 2000-10-01
+ An in-depth look at creating applications
+ with XML.
+
+
+ Ralls, Kim
+ Midnight Rain
+ Fantasy
+ 5.95
+ 2000-12-16
+ A former architect battles corporate zombies,
+ an evil sorceress, and her own childhood to become queen
+ of the world.
+
+
+ Corets, Eva
+ Maeve Ascendant
+ Fantasy
+ 5.95
+ 2000-11-17
+ After the collapse of a nanotechnology
+ society in England, the young survivors lay the
+ foundation for a new society.
+
+
+ Corets, Eva
+ Oberon's Legacy
+ Fantasy
+ 5.95
+ 2001-03-10
+ In post-apocalypse England, the mysterious
+ agent known only as Oberon helps to create a new life
+ for the inhabitants of London. Sequel to Maeve
+ Ascendant.
+
+
+ Corets, Eva
+ The Sundered Grail
+ Fantasy
+ 5.95
+ 2001-09-10
+ The two daughters of Maeve, half-sisters,
+ battle one another for control of England. Sequel to
+ Oberon's Legacy.
+
+
+ Randall, Cynthia
+ Lover Birds
+ Romance
+ 4.95
+ 2000-09-02
+ When Carla meets Paul at an ornithology
+ conference, tempers fly as feathers get ruffled.
+
+
+ Thurman, Paula
+ Splish Splash
+ Romance
+ 4.95
+ 2000-11-02
+ A deep sea diver finds true love twenty
+ thousand leagues beneath the sea.
+
+
+ Knorr, Stefan
+ Creepy Crawlies
+ Horror
+ 4.95
+ 2000-12-06
+ An anthology of horror stories about roaches,
+ centipedes, scorpions and other insects.
+
+
+ Kress, Peter
+ Paradox Lost
+ Science Fiction
+ 6.95
+ 2000-11-02
+ After an inadvertant trip through a Heisenberg
+ Uncertainty Device, James Salway discovers the problems
+ of being quantum.
+
+
+ O'Brien, Tim
+ Microsoft .NET: The Programming Bible
+ Computer
+ 36.95
+ 2000-12-09
+ Microsoft's .NET initiative is explored in
+ detail in this deep programmer's reference.
+
+
+ O'Brien, Tim
+ MSXML3: A Comprehensive Guide
+ Computer
+ 36.95
+ 2000-12-01
+ The Microsoft MSXML3 parser is covered in
+ detail, with attention to XML DOM interfaces, XSLT processing,
+ SAX and more.
+
+
+ Galos, Mike
+ Visual Studio 7: A Comprehensive Guide
+ Computer
+ 49.95
+ 2001-04-16
+ Microsoft Visual Studio 7 is explored in depth,
+ looking at how Visual Basic, Visual C++, C#, and ASP+ are
+ integrated into a comprehensive development
+ environment.
+
+
+```
+
+@tab Zig
+
+```zig
+const std = @import("std");
+const parseInt = std.fmt.parseInt;
+
+test "parse integers" {
+ const input = "123 67 89,99";
+ const ally = std.testing.allocator;
+
+ var list = std.ArrayList(u32).init(ally);
+ // Ensure the list is freed at scope exit.
+ // Try commenting out this line!
+ defer list.deinit();
+
+ var it = std.mem.tokenize(u8, input, " ,");
+ while (it.next()) |num| {
+ const n = try parseInt(u32, num, 10);
+ try list.append(n);
+ }
+
+ const expected = [_]u32{ 123, 67, 89, 99 };
+
+ for (expected, list.items) |exp, actual| {
+ try std.testing.expectEqual(exp, actual);
+ }
+}
+```
+:::
+
+::: code-tabs
+@tab HTML
+
+``` html
+
+
+
+
+
+ MDN Web Docs Example: Toggling full-screen mode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+