2026-03-05 15:34:11 +08:00

17 KiB

title, icon, createTime, permalink
title icon createTime permalink
Frontend Demo icon-park-outline:html-five 2025/01/08 21:34:26 /en/guide/repl/frontend/

::: important Legacy Frontend Code Demo Deprecated - Please Migrate to New Solution

The legacy solution was provided by vuepress-plugin-md-enhance. We appreciate its support for code demos in the past. The code demo functionality in vuepress-plugin-md-enhance will be migrated to vuepress/ecosystem. For details, please refer to vuepress/ecosystem#293.

:::

::: details Why Redesign?

Frontend code demos are a highly useful feature, but the legacy implementation did not align with actual usage scenario expectations.

In the legacy solution, for example, vue-demo only supported simple Vue component demonstrations and could not directly import dependencies from the project. It relied on loading external scripts for additional functionality and did not provide full support for Vue SFC, being limited to simple code demonstrations.

Furthermore, script code compilation occurred in the browser runtime. It required loading babel from a CDN first, then performing the transformation via babel, which introduced additional waiting time. Additionally, for internal enterprise projects within an intranet environment that cannot access external resources, the demos failed to display properly.

In the new solution, all demo code is compiled and transformed during the Node.js runtime. Therefore, demo code can be displayed directly in the browser runtime without extra waiting time. Leveraging Node.js's powerful capabilities, it fully supports all features of Vue SFC and allows direct import of project dependencies, enabling richer demonstrations that better match real-world usage scenarios. :::

Overview

This feature supports embedding code demonstration functionality within pages. A frontend code demo consists of two main areas: ==Render Area== and ==Code Area==.

The Render Area displays the execution results of the code, including UI rendering and interactions. The Code Area displays the source code and is collapsed by default.

The theme provides support for three different types of frontend code demos:

  • ==Vue Component Demo==: Supports demonstrations of Vue components. Write your demo code as you would a Vue component. It can be used to demonstrate external dependencies like component libraries or Composables API.
  • ==Markdown Demo==: Supports demonstrations of Markdown.
  • ==Normal Code Demo==: Supports native HTML + JS/TS + CSS/Less/Sass/Stylus code demos. Write your demo code as you would a web page.

The theme also provides two different methods for writing demo code:

  • Embed Demo Code Files:

    @[demo type](url)
    

    Use simple embedding syntax to import demo code from files.

  • Inline Demo Code within Demo Container:

    ::: demo type
    ``` [lang]
    code
    ```
    :::
    

    Write demo code directly within the markdown file, wrapped in a demo container.

Configuration

Frontend code demos are powered by vuepress-plugin-md-power.

Frontend code demos are disabled by default. You can enable them via configuration.

export default defineUserConfig({
  theme: plumeTheme({
    markdown: {
      demo: true, // [!code ++]
    },
  })
})

Language Support

Code demos support the following languages:

  • javascript
  • typescript
  • html
  • css
  • less
  • sass
  • stylus

For CSS preprocessor languages, you need to install the corresponding preprocessor in your project, such as less, sass, or stylus.

Embed Syntax

Different code demos use the same embed syntax, allowing you to quickly grasp their usage.

<!-- Syntax -->
@[demo](url)
@[demo [type]](url)
@[demo [type] title="" desc="" expanded code-setting=""](url)

@[demo](url) is a fixed syntax format.

[type] indicates the type and supports three different values:

  • normal: Normal code demo type. This is the default type when the [type] parameter is omitted.
  • vue: Vue component demo type.
  • markdown: Markdown demo type.

url indicates the path to the demo code file, which can be relative or absolute.

  • Relative paths start with ./ or ../ and are relative to the current markdown file's path.
  • Absolute paths start with / and are resolved from the VuePress source directory path.
<!-- Normal Code Demo -->
@[demo](./demo/normal.html)
@[demo normal](./demo/normal.html)
@[demo](/.vuepress/demo/normal.html)

<!-- Vue Component Demo -->
@[demo vue](./demo/Counter.vue)
@[demo vue](./demo/Counter.ts)
@[demo](/.vuepress/demo/Counter.vue)

<!-- Markdown Demo -->
@[demo markdown](./demo/example.md)
@[demo markdown](/.vuepress/demo/example.md)

Additional parameters:

  • title="xxx": Demo title.

  • desc="xxx": Demo description.

  • expanded: Expand the code area.

  • code-setting="xxx": Code settings. The value will be appended after ``` [lang]` and is used to add configurations to the code block.

    code-setting=":lines-number" will add :lines-number after the code block, enabling line numbers.

    code-setting=":collapsed-lines=10" will add :collapsed-lines=10 after the code block, causing the code block to be collapsed starting from line 10.

@[demo vue expanded title="Title" desc="Description" code-setting=":collapsed-lines=10"](./demo/Counter.vue)

Demo Container Inline Demo

Demo container inline demos use the demo container to wrap the demo code, allowing quick writing of demo code within the markdown file:

::: demo [type] title="" desc="" expanded
<!-- Code Block -->
:::

All parameters are the same as the @[demo](url) syntax.

<!-- Normal Code Demo -->
::: demo
```html
<!-- html code -->
```
``` js
// js code
```
``` css
/* css code */
```
:::

<!-- Vue Component Demo -->
::: demo vue
``` vue
<!-- vue code -->
```
:::

<!-- Markdown Demo -->
::: demo markdown
``` md
<!-- markdown code -->
```
:::

You can also wrap code blocks with the ::: code-tabs container within the ::: demo container for better interactive presentation.

:::: demo
::: code-tabs
@tab HTML
```html
<!-- html code -->
```
@tab javascript
``` js
// js code
```
@tab css
``` css
/* css code */
```
:::
:::::

When using TypeScript or Less/Sass/Stylus, simply modify the value of ``` [lang]:

:::: demo
::: code-tabs
@tab HTML
```html
<!-- html code -->
```
@tab Typescript
``` ts
// ts code
```
@tab Scss
``` scss
/* scss code */
```
:::
:::::

Vue Component Demo

Vue component demo is a powerful feature with no restrictions on the demo code—it ultimately depends on the bundler's support for Vue. You can directly import dependencies installed in your project within the demo code, just as you would when writing a component in a Vue project.

Therefore, you can use it directly to provide demonstration examples for your component library or for your Composables API.

Embed Syntax

You can directly embed a Vue component demo in a page using the following method:

Input:

@[demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"](./demo/Counter.vue)

::: details View ./demo/Counter.vue Code

@code

:::

Output:

@demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"


You can also embed a Vue component written in .ts:

Input:

@[demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"](./demo/Counter.ts)

::: details View ./demo/Counter.ts Code

::: code-tabs @tab Counter.ts @code @tab Counter.module.css @code :::

Output:

@demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"

:::info For components written in .js/.ts, use CSS Module to write styles for style isolation. :::


You can import external dependencies in the demo code. Example using useToggle() from @vueuse/core:

Input:

@[demo vue title="useToggle" desc="useToggle() Demo"](./demo/Toggle.vue)

::: details ./demo/Toggle.vue @code :::

Output:

@demo vue title="useToggle" desc="useToggle() Demo"

Container Syntax

Using the demo container to wrap demo code in a markdown file allows for quick demo code writing:

Input:

:::: details Expand to view full code

::: demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"
```vue
<script setup lang="ts">
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <div class="counter">
    <p>Counter: {{ count }}</p>
    <button type="button" class="btn" @click="count += 1">
      + 1
    </button>
  </div>
</template>

<style scoped>
.btn {
  border: 1px solid var(--vp-c-divider);
  border-radius: 4px;
}
</style>
```
:::

::::

Output:

::: demo vue title="Counter" desc="Click the +1 button to increment the counter by 1"

<script setup lang="ts">
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <div class="counter">
    <p>Counter: {{ count }}</p>
    <button type="button" class="btn" @click="count += 1">
      + 1
    </button>
  </div>
</template>

<style scoped>
.btn {
  border: 1px solid var(--vp-c-divider);
  border-radius: 4px;
}
</style>

:::

:::::: warning The Vue demo container syntax also supports embedding demo code using the .js/ts + css approach, but this is not recommended by the theme. Styles cannot be isolated, which may lead to style pollution.

::::: details Reference Example

:::: demo vue title="Title" desc="Description"
::: code-tabs
@tab Counter.ts
```ts
import { defineComponent, ref } from 'vue'

export default defineComponent({
  // code
})
```
@tab Counter.css
```css
/* css code */
```
:::
::::

::::: ::::::

Normal Code Demo

Normal code demos support html, css/less/sass/stylus, and js/ts languages.

They are suitable for relatively simple code demonstrations, such as a style rendering effect, an interaction effect, or a functionality.

Normal code demos also support jumping to CodePen and jsFiddle for viewing.

Additionally, they support importing third-party libraries via external links, such as jQuery or dayjs.

::: warning Overly complex demonstrations are not recommended. :::

Embed Syntax

When using the embed syntax, use .html as the file suffix for the imported demo code file. In the .html file, you can write the demo code as you would an HTML page:

<!-- html code -->
<div id="app">
  Demo Content
<div>

<!-- Script content, use lang attribute to set language, defaults to js -->
<script lang="ts">
</script>

<!-- Style content, use lang attribute to set language, defaults to css -->
<style lang="css">
</style>

<!-- Optional configuration file in json format -->
<script type="config">
{
  "jsLib": [],
  "cssLib": []
}
</script>

Each section is optional. However, note that multiple identical sections are not supported. The order of sections does not matter. Content outside of <script> and <style> is considered HTML code.

You can declare additional dependency resources to load using JSON format within <script type="config"></script>.

For example, loading jQuery and normalize.css:

<div>xxxx</div>

<script type="config">
{
  "jsLib": [
    "https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"
  ],
  "cssLib": [
    "https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.min.css"
  ]
}
</script>

A conventional example:

Input:

@[demo title="Example" desc="This is a conventional demo"](./demo/normal.html)

::: details View ./demo/normal.html Code @code :::

Output:

@demo title="Example" desc="This is a conventional demo"


Example introducing jQuery, dayjs, and normalize.css:

Input:

@[demo title="Example" desc="This is a conventional demo"](./demo/normal-lib.html)

::: details View ./demo/normal-lib.html Code @code :::

Output:

@demo title="Example" desc="This is a conventional demo"

Container Syntax

Using the demo container to wrap demo code in a markdown file allows for quick demo code writing:

:::: details Expand to view full example code

::: demo title="Example" desc="Description" expanded
```json
{
  "jsLib": [],
  "cssLib": []
}
```

```html
<!-- html code -->
```

```js
// js code
```

```css
/* css code */
```
:::

::::

You can also wrap ::: code-tabs within ::: demo for better code block presentation:

::::: details Expand to view full example code

:::: demo title="Example" desc="Description" expanded
```json
{
  "jsLib": [],
  "cssLib": []
}
```
::: code-tabs
@tab HTML
```html
<!-- html code -->
```
@tab Javascript
```js
// js code
```
@tab CSS
```css
/* css code */
```
:::
::::

:::::


A conventional container example:

Input:

::::: details Expand to view full example code

:::: demo title="Conventional Example" desc="A conventional example"
::: code-tabs
@tab HTML
```html
<div id="app">
  <h3>vuepress-theme-plume</h3>
</div>
```
@tab Javascript
```js
const a = 'So Awesome!'
const app = document.querySelector('#app')
app.appendChild(document.createElement('small')).textContent = a
```
@tab CSS
```css
#app {
  font-size: 2em;
  text-align: center;
}
```
:::
::::

:::::

Output:

:::: demo title="Conventional Example" desc="A conventional example"

::: code-tabs @tab HTML

<div id="app">
  <h3>vuepress-theme-plume</h3>
</div>

@tab Javascript

const a = 'So Awesome!'
const app = document.querySelector('#app')
app.appendChild(document.createElement('small')).textContent = a

@tab CSS

#app {
  font-size: 2em;
  text-align: center;
}

::: ::::


Example introducing jQuery, dayjs, and normalize.css:

Input:

::::: details Expand to view full example code

:::: demo title="Conventional Example" desc="A conventional example"
```json
{
  "jsLib": [
    "https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js",
    "https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js"
  ],
  "cssLib": ["https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.min.css"]
}
```
::: code-tabs
@tab HTML
```html
<div id="app">
  <h3>vuepress-theme-plume</h3>
  <p id="message"></p>
  <datetime id="datetime"></datetime>
</div>
```
@tab Javascript
```js
$('#message').text('So Awesome!')
const datetime = $('#datetime')
setInterval(() => {
  datetime.text(dayjs().format('YYYY-MM-DD HH:mm:ss'))
}, 1000)
```
@tab CSS
```css
#app {
  font-size: 2em;
  text-align: center;
}
```
:::
::::

:::::

Output:

:::: demo title="Conventional Example" desc="A conventional example"

{
  "jsLib": [
    "https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js",
    "https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js"
  ],
  "cssLib": ["https://cdn.jsdelivr.net/npm/normalize.css@8.0.1/normalize.min.css"]
}

::: code-tabs @tab HTML

<div id="app">
  <h3>vuepress-theme-plume</h3>
  <p id="message"></p>
  <datetime id="datetime"></datetime>
</div>

@tab Javascript

$('#message').text('So Awesome!')
const datetime = $('#datetime')
setInterval(() => {
  datetime.text(dayjs().format('YYYY-MM-DD HH:mm:ss'))
}, 1000)

@tab CSS

#app {
  font-size: 2em;
  text-align: center;
}

::: ::::

Markdown Demo

Demonstrate markdown source code and rendering results within a page.

Embed Syntax

Input:

@[demo markdown title="Bulletin Board" desc="Bulletin Board Code Example"](/.vuepress/bulletin.md)

::: details Expand to view /.vuepress/bulletin.md Code @code :::

Output:

@demo markdown title="Bulletin Board" desc="Bulletin Board Code Example"

Container Syntax

Input:

:::::: details Expand to view full code

:::: demo markdown title="Bulletin Board" desc="Bulletin Board Code Example"
```md
::: center

**QQ Group:** [792882761](https://qm.qq.com/q/FbPPoOIscE)

![QQ qr_code](/images/qq_qrcode.png){width="618" height="616" style="width: 200px"}

If you encounter any issues during use, please feel free to provide feedback via [issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new/choose). You are also welcome to join our QQ group for discussion.

:::
```
::::

::::::

Output:

:::: demo markdown title="Bulletin Board" desc="Bulletin Board Code Example"

::: center

**QQ Group:** [792882761](https://qm.qq.com/q/FbPPoOIscE)

![QQ qr_code](/images/qq_qrcode.png){width="618" height="616" style="width: 200px"}

If you encounter any issues during use, please feel free to provide feedback via [issue](https://github.com/pengzhanbo/vuepress-theme-plume/issues/new/choose). You are also welcome to join our QQ group for discussion.

:::

::::