From 057fd4ce9a0e1b9ef1d9978189a6d7f7b18b8d85 Mon Sep 17 00:00:00 2001 From: "Mr.Hope" Date: Wed, 18 Nov 2020 00:35:06 +0800 Subject: [PATCH] feat(md-enhance): support mutiple code block in code-demo --- docs/md-enhance/src/guide/demo.md | 227 +++++++------- docs/md-enhance/src/zh/guide/demo.md | 236 ++++++++------- docs/theme/src/guide/feature/markdown/demo.md | 278 +++++++++-------- .../src/zh/guide/feature/markdown/demo.md | 282 +++++++++-------- .../md-enhance/lib/markdown-it/code-demo.ts | 23 +- packages/md-enhance/package.json | 1 + .../md-enhance/src/demo/{button.ts => dom.ts} | 132 ++++++-- packages/md-enhance/src/demo/index.ts | 140 ++------- packages/md-enhance/src/demo/utils.ts | 286 ++++++++++-------- packages/md-enhance/src/styles/code-demo.styl | 142 +++++---- packages/md-enhance/types/index.d.ts | 31 +- tests/src/guide/markdown.md | 141 ++++----- tests/src/zh/guide/markdown.md | 139 ++++----- yarn.lock | 10 +- 14 files changed, 1067 insertions(+), 1001 deletions(-) rename packages/md-enhance/src/demo/{button.ts => dom.ts} (55%) diff --git a/docs/md-enhance/src/guide/demo.md b/docs/md-enhance/src/guide/demo.md index f375df278611..38b5921c7dd3 100644 --- a/docs/md-enhance/src/guide/demo.md +++ b/docs/md-enhance/src/guide/demo.md @@ -27,14 +27,17 @@ module.exports = { You should use the following syntax: ````md -::: demo [type] +::: demo [type] Optional title text ```html - + + ``` + ```json +// json block is for config { // your config here (optional) } @@ -49,31 +52,39 @@ The json block is optional. The plugin support three types: -- vanilla (default) +- normal (default) - vue - react -### Vanilla +### Normal Syntax: ````md -::: demo +::: demo Optional title text ```html - - - - - + +``` + +```js +// js code +``` + +```css +/* css code */ ``` ```json // config (optional) +{ + "jsLib": [ + ... + ], + "cssLib":[ + ... + ] +} ``` :::: @@ -84,9 +95,10 @@ Syntax: Syntax: ````md -::: demo vue +::: demo [vue] Optional title text -```html +```vue + @@ -112,15 +124,20 @@ Syntax: Syntax: ````md -::: demo react +::: demo [react] Optional title text ```js export default class App extends React.Component { // your react component } -App.__style__ = ` - your styles -`; +``` + +```css +/* your css content */ +``` + +```json +// config (optional) ``` ::: @@ -158,82 +175,88 @@ module.exports = { We also make an enhance: If you import Babel, then Vue and Vanilla script will be parsed to es6 using babel. ::: -### PreProcessor +### Available languages -You can config preprocessor in your demo block. But only jsPreprocessor `'babel'` is supported at runtime when you import babel standalone library. +You can use different language in your demo block. -When you set other proprocessor, since the plugin is not able to resolve them, demo display will be disabled, and only codes can be seen. And the plugin will provide you a button to open it in CodePen. +When you set another language, since the plugin is not able to resolve them, demo display will be disabled, and only codes can be seen. And the plugin will provide you a button to open it in CodePen. -HTML preprocessors: +Available HTML languages: -- `"none"` (default) +- `"html"` (default) - `"slim"` - `"haml"` - `"markdown"` -JS preprocessors: +> You can also use `md` in code block. + +Available JS languages: -- `"none"` (default) +- `"javascript"` (default) - `"coffeescript"` - `"babel"` - `"livescript"` - `"typescript"` -CSS preprocessors: +> You can also use `js`, `ts`, `coffee` and `ls` in code block. -- `"none"` (default) +Available CSS languages: + +- `"css"` (default) - `"less"` - `"scss"` - `"sass"` - `"stylus"` +> You can also use `styl` in code block. + ## Demo -::: demo +::: demo A normal demo ```html -

Mr.Hope

Is very handsome

- - - +``` + +```js +document.querySelector("#very").addEventListener("click", () => { + alert("Very handsome!"); +}); +``` + +```css +span { + color: red; +} ``` ::: ````md -::: demo +::: demo A normal demo ```html -

Mr.Hope

Is very handsome

- - - +``` + +```js +document.querySelector("#very").addEventListener("click", () => { + alert("Very handsome!"); +}); +``` + +```css +span { + color: red; +} ``` ::: ```` -::: demo react +::: demo [react] A react demo ```js export default class App extends React.Component { @@ -249,17 +272,18 @@ export default class App extends React.Component { ); } } -App.__style__ = ` +``` + +```css .box-react span { color: red; } -`; ``` ::: ````md -::: demo react +::: demo [react] A react demo ```js export default class App extends React.Component { @@ -275,19 +299,20 @@ export default class App extends React.Component { ); } } -App.__style__ = ` +``` + +```css .box-react span { color: red; } -`; ``` ::: ```` -::: demo vue +::: demo [vue] A vue demo -```html +```vue @@ -306,9 +331,9 @@ App.__style__ = ` ::: ````md -::: demo vue +::: demo [vue] A vue demo -```html +```vue @@ -327,68 +352,54 @@ App.__style__ = ` ::: ```` -::: demo +::: demo A normal demo -```html - +```md # Title is very handsome. - - - +document.querySelector("h1").innerHTML = message; ``` -```json -{ - "html": "markdown", - "js": "typescript", - "css": "scss" +```scss +h1 { + font-style: italic; + + + p { + color: red; + } } ``` ::: ````md -::: demo +::: demo A normal demo -```html - - # Title is very handsome. - - - +```ts +const message: string = "Mr.Hope"; + +document.querySelector("h1").innerHTML = message; ``` -```json -{ - "html": "markdown", - "js": "typescript", - "css": "scss" +```scss +h1 { + font-style: italic; + + + p { + color: red; + } } ``` diff --git a/docs/md-enhance/src/zh/guide/demo.md b/docs/md-enhance/src/zh/guide/demo.md index f719d54e3c8e..87eae1d26f9e 100644 --- a/docs/md-enhance/src/zh/guide/demo.md +++ b/docs/md-enhance/src/zh/guide/demo.md @@ -27,14 +27,16 @@ module.exports = { 您应该使用以下语法: ````md -::: demo [类型] +::: demo [类型] 可选的标题文字 ```html - + + ``` ```json +// json block 作为插件配置 { // 放置你的配置 (optional) } @@ -44,39 +46,47 @@ module.exports = { ```` ::: tip -json 块是可选的。 +JSON 块是可选的。 ::: 该插件支持三种类型: -- vanilla (默认) +- normal (默认) - vue - react -### Vanilla +### Normal 写法: ````md -::: demo +::: demo 可选的标题文字 ```html - - - - - + +``` + +```js +// js code +``` + +```css +/* css code */ ``` ```json // 配置 (可选) +{ + "jsLib": [ + ... + ], + "cssLib":[ + ... + ] +} ``` -:::: +::: ```` ### Vue @@ -84,9 +94,10 @@ json 块是可选的。 语法: ````md -::: demo vue +::: demo [vue] 可选的标题文字 -```html +```vue + @@ -112,15 +123,20 @@ json 块是可选的。 语法: ````md -::: demo react +::: demo [react] 可选的标题文字 ```js export default class App extends React.Component { // react 组件 } -App.__style__ = ` - your styles -`; +``` + +```css +/* 你的 css 内容 */ +``` + +```json +// 配置 (可选) ``` ::: @@ -158,82 +174,88 @@ module.exports = { 我们还进行了增强: 如果你导入 Babel,则将使用 babel 将脚本解析为 es6,以确保能在浏览器上正常运行。 ::: -### 预处理器 +### 可用的语言 -您可以在演示块中配置预处理器。但是,在运行时仅支持 JS 预处理器 `'babel'`(你还需要手动导入 babel 独立库)。 +您可以在演示块中使用不同语言。 -当您设置其他预处理器时,由于插件无法解析它们,因此演示将被禁用,您只能看到代码。插件将为您提供一个 "在 CodePen 中打开" 按钮。 +当您设置其他语言时,由于插件无法解析它们,因此演示将被禁用,您只能看到代码。插件将为您提供一个 "在 CodePen 中打开" 按钮允许你直接在 CodePen 打开代码。 -HTML 预处理器: +可用的 HTML 语言: -- `"none"` (默认) +- `"html"` (默认) - `"slim"` - `"haml"` - `"markdown"` -JS 预处理器: +> 你也可以在代码块中使用 `md`。 -- `"none"` (默认) +可用的 JS 语言: + +- `"javascript"` (default) - `"coffeescript"` - `"babel"` - `"livescript"` - `"typescript"` -CSS 预处理器: +> 你也可以在代码块中使用 `js`, `ts`, `coffee` 和 `ls`。 + +可用的 CSS 语言: -- `"none"` (默认) +- `"css"` (default) - `"less"` - `"scss"` - `"sass"` - `"stylus"` +> 你也可以在代码块中使用 `styl`。 + ## 演示 -::: demo +::: demo 一个普通 Demo ```html -

Mr.Hope

-

Is 十分

- - - +

十分

+``` + +```js +document.querySelector("#very").addEventListener("click", () => { + alert("十分帅"); +}); +``` + +```css +span { + color: red; +} ``` ::: ````md -::: demo +::: demo 一个普通 Demo ```html -

Mr.Hope

-

Is 十分

- - - +

十分

+``` + +```js +document.querySelector("#very").addEventListener("click", () => { + alert("十分帅"); +}); +``` + +```css +span { + color: red; +} ``` ::: ```` -::: demo react +::: demo [react] 一个 React Demo ```js export default class App extends React.Component { @@ -249,17 +271,18 @@ export default class App extends React.Component { ); } } -App.__style__ = ` +``` + +```css .box-react span { color: red; } -`; ``` ::: ````md -::: demo react +::: demo [react] 一个 React Demo ```js export default class App extends React.Component { @@ -275,19 +298,20 @@ export default class App extends React.Component { ); } } -App.__style__ = ` +``` + +```css .box-react span { color: red; } -`; ``` ::: ```` -::: demo vue +::: demo [vue] 一个 Vue Demo -```html +```vue @@ -306,9 +330,9 @@ App.__style__ = ` ::: ````md -::: demo vue +::: demo [vue] 一个 Vue Demo -```html +```vue @@ -327,68 +351,54 @@ App.__style__ = ` ::: ```` -::: demo +::: demo 一个普通 Demo -```html - +```md # 标题 -十分帅! - - - +document.querySelector("h1").innerHTML = message; ``` -```json -{ - "html": "markdown", - "js": "typescript", - "css": "scss" +```scss +h1 { + font-style: italic; + + + p { + color: red; + } } ``` ::: ````md -::: demo +::: demo 一个普通 Demo -```html - - # 标题 十分帅! - - - +```ts +const message: string = "Mr.Hope"; + +document.querySelector("h1").innerHTML = message; ``` -```json -{ - "html": "markdown", - "js": "typescript", - "css": "scss" +```scss +h1 { + font-style: italic; + + + p { + color: red; + } } ``` diff --git a/docs/theme/src/guide/feature/markdown/demo.md b/docs/theme/src/guide/feature/markdown/demo.md index 71a2fa3dca11..2e92c127d0e1 100644 --- a/docs/theme/src/guide/feature/markdown/demo.md +++ b/docs/theme/src/guide/feature/markdown/demo.md @@ -27,14 +27,16 @@ module.exports = { You should use the following syntax: ````md -::: demo [type] +::: demo [type] Optional title text ```html - + + ``` ```json +// json block is for config { // your config here (optional) } @@ -49,31 +51,39 @@ The json block is optional. The plugin support three types: -- vanilla (default) +- normal (default) - vue - react -### Vanilla +### Normal Syntax: ````md -::: demo +::: demo Optional title text ```html - - - - - + +``` + +```js +// js code +``` + +```css +/* css code */ ``` ```json // config (optional) +{ + "jsLib": [ + ... + ], + "cssLib":[ + ... + ] +} ``` :::: @@ -84,19 +94,20 @@ Syntax: Syntax: ````md -::: demo vue +::: demo [vue] Optional title text -```html +```vue + ``` @@ -112,15 +123,20 @@ Syntax: Syntax: ````md -::: demo react +::: demo [react] Optional title text ```js export default class App extends React.Component { // your react component } -App.__style__ = ` - your styles -`; +``` + +```css +/* your css content */ +``` + +```json +// config (optional) ``` ::: @@ -158,82 +174,88 @@ module.exports = { We also make an enhance: If you import Babel, then Vue and Vanilla script will be parsed to es6 using babel. ::: -### PreProcessor +### Available languages -You can config preprocessor in your demo block. But only jsPreprocessor `'babel'` is supported at runtime when you import babel standalone library. +You can use different language in your demo block. -When you set other proprocessor, since the plugin is not able to resolve them, demo display will be disabled, and only codes can be seen. And the plugin will provide you a button to open it in CodePen. +When you set another language, since the plugin is not able to resolve them, demo display will be disabled, and only codes can be seen. And the plugin will provide you a button to open it in CodePen. -HTML preprocessors: +Available HTML languages: -- `"none"` (default) +- `"html"` (default) - `"slim"` - `"haml"` - `"markdown"` -JS preprocessors: +> You can also use `md` in code block. + +Available JS languages: -- `"none"` (default) +- `"javascript"` (default) - `"coffeescript"` - `"babel"` - `"livescript"` - `"typescript"` -CSS preprocessors: +> You can also use `js`, `ts`, `coffee` and `ls` in code block. -- `"none"` (default) +Available CSS languages: + +- `"css"` (default) - `"less"` - `"scss"` - `"sass"` - `"stylus"` +> You can also use `styl` in code block. + ## Demo -::: demo +::: demo A normal demo ```html - -

Mr.Hope

-

Is very handsome

- - - +

Mr.Hope

+

Is very handsome

+``` + +```js +document.querySelector("#very").addEventListener("click", () => { + alert("Very handsome!"); +}); +``` + +```css +span { + color: red; +} ``` ::: ````md -::: demo +::: demo A normal demo ```html - -

Mr.Hope

-

Is very handsome

- - - +

Mr.Hope

+

Is very handsome

+``` + +```js +document.querySelector("#very").addEventListener("click", () => { + alert("Very handsome!"); +}); +``` + +```css +span { + color: red; +} ``` ::: ```` -::: demo react +::: demo [react] A react demo ```js export default class App extends React.Component { @@ -249,17 +271,18 @@ export default class App extends React.Component { ); } } -App.__style__ = ` +``` + +```css .box-react span { color: red; } -`; ``` ::: ````md -::: demo react +::: demo [react] A react demo ```js export default class App extends React.Component { @@ -275,118 +298,111 @@ export default class App extends React.Component { ); } } -App.__style__ = ` +``` + +```css .box-react span { color: red; } -`; ``` ::: ```` -::: demo vue +::: demo [vue] A vue demo -```html +```vue ``` ::: ````md -::: demo vue +::: demo [vue] A vue demo -```html +```vue ``` ::: ```` -::: demo +::: demo A normal demo -```html - - # Title is very handsome. - - - +```ts +const message: string = "Mr.Hope"; + +document.querySelector("h1").innerHTML = message; ``` -```json -{ - "html": "markdown", - "js": "typescript", - "css": "scss" +```scss +h1 { + font-style: italic; + + + p { + color: red; + } } ``` ::: ````md -::: demo +::: demo A normal demo -```html - - # Title is very handsome. - - - +```ts +const message: string = "Mr.Hope"; + +document.querySelector("h1").innerHTML = message; ``` -```json -{ - "html": "markdown", - "js": "typescript", - "css": "scss" +```scss +h1 { + font-style: italic; + + + p { + color: red; + } } ``` diff --git a/docs/theme/src/zh/guide/feature/markdown/demo.md b/docs/theme/src/zh/guide/feature/markdown/demo.md index 91b5ed038d99..cb73a29af579 100644 --- a/docs/theme/src/zh/guide/feature/markdown/demo.md +++ b/docs/theme/src/zh/guide/feature/markdown/demo.md @@ -23,14 +23,16 @@ module.exports = { 您应该使用以下语法: ````md -::: demo [类型] +::: demo [类型] 可选的标题文字 ```html - + + ``` ```json +// json block 作为插件配置 { // 放置你的配置 (optional) } @@ -40,39 +42,47 @@ module.exports = { ```` ::: tip -json 块是可选的。 +JSON 块是可选的。 ::: 该插件支持三种类型: -- vanilla (默认) +- normal (默认) - vue - react -### Vanilla +### Normal 写法: ````md -::: demo +::: demo 可选的标题文字 ```html - - - - - + +``` + +```js +// js code +``` + +```css +/* css code */ ``` ```json // 配置 (可选) +{ + "jsLib": [ + ... + ], + "cssLib":[ + ... + ] +} ``` -:::: +::: ```` ### Vue @@ -80,19 +90,20 @@ json 块是可选的。 语法: ````md -::: demo vue +::: demo [vue] 可选的标题文字 -```html +```vue + ``` @@ -108,15 +119,20 @@ json 块是可选的。 语法: ````md -::: demo react +::: demo [react] 可选的标题文字 ```js export default class App extends React.Component { // react 组件 } -App.__style__ = ` - your styles -`; +``` + +```css +/* 你的 css 内容 */ +``` + +```json +// 配置 (可选) ``` ::: @@ -154,82 +170,88 @@ module.exports = { 我们还进行了增强: 如果你导入 Babel,则将使用 babel 将脚本解析为 es6,以确保能在浏览器上正常运行。 ::: -### 预处理器 +### 可用的语言 -您可以在演示块中配置预处理器。但是,在运行时仅支持 JS 预处理器 `'babel'`(你还需要手动导入 babel 独立库)。 +您可以在演示块中使用不同语言。 -当您设置其他预处理器时,由于插件无法解析它们,因此演示将被禁用,您只能看到代码。插件将为您提供一个 "在 CodePen 中打开" 按钮。 +当您设置其他语言时,由于插件无法解析它们,因此演示将被禁用,您只能看到代码。插件将为您提供一个 "在 CodePen 中打开" 按钮允许你直接在 CodePen 打开代码。 -HTML 预处理器: +可用的 HTML 语言: -- `"none"` (默认) +- `"html"` (默认) - `"slim"` - `"haml"` - `"markdown"` -JS 预处理器: +> 你也可以在代码块中使用 `md`。 -- `"none"` (默认) +可用的 JS 语言: + +- `"javascript"` (default) - `"coffeescript"` - `"babel"` - `"livescript"` - `"typescript"` -CSS 预处理器: +> 你也可以在代码块中使用 `js`, `ts`, `coffee` 和 `ls`。 + +可用的 CSS 语言: -- `"none"` (默认) +- `"css"` (default) - `"less"` - `"scss"` - `"sass"` - `"stylus"` +> 你也可以在代码块中使用 `styl`。 + ## 演示 -::: demo +::: demo 一个普通 Demo ```html - -

Mr.Hope

-

Is 十分

- - - +

Mr.Hope

+

十分

+``` + +```js +document.querySelector("#very").addEventListener("click", () => { + alert("十分帅"); +}); +``` + +```css +span { + color: red; +} ``` ::: ````md -::: demo +::: demo 一个普通 Demo ```html - -

Mr.Hope

-

Is 十分

- - - +

Mr.Hope

+

十分

+``` + +```js +document.querySelector("#very").addEventListener("click", () => { + alert("十分帅"); +}); +``` + +```css +span { + color: red; +} ``` ::: ```` -::: demo react +::: demo [react] 一个 React Demo ```js export default class App extends React.Component { @@ -245,17 +267,18 @@ export default class App extends React.Component { ); } } -App.__style__ = ` +``` + +```css .box-react span { color: red; } -`; ``` ::: ````md -::: demo react +::: demo [react] 一个 React Demo ```js export default class App extends React.Component { @@ -271,118 +294,111 @@ export default class App extends React.Component { ); } } -App.__style__ = ` +``` + +```css .box-react span { color: red; } -`; ``` ::: ```` -::: demo vue +::: demo [vue] 一个 Vue Demo -```html +```vue ``` ::: ````md -::: demo vue +::: demo [vue] 一个 Vue Demo -```html +```vue ``` ::: ```` -::: demo +::: demo 一个普通 Demo -```html - - # 标题 十分帅! - - - +```ts +const message: string = "Mr.Hope"; + +document.querySelector("h1").innerHTML = message; ``` -```json -{ - "html": "markdown", - "js": "typescript", - "css": "scss" +```scss +h1 { + font-style: italic; + + + p { + color: red; + } } ``` ::: ````md -::: demo +::: demo 一个普通 Demo -```html - - # 标题 十分帅! - - - +```ts +const message: string = "Mr.Hope"; + +document.querySelector("h1").innerHTML = message; ``` -```json -{ - "html": "markdown", - "js": "typescript", - "css": "scss" +```scss +h1 { + font-style: italic; + + + p { + color: red; + } } ``` diff --git a/packages/md-enhance/lib/markdown-it/code-demo.ts b/packages/md-enhance/lib/markdown-it/code-demo.ts index ac83480f3aa4..25dfa8c9924b 100644 --- a/packages/md-enhance/lib/markdown-it/code-demo.ts +++ b/packages/md-enhance/lib/markdown-it/code-demo.ts @@ -3,7 +3,8 @@ import Token = require("markdown-it/lib/token"); export const codeDemoRender = (tokens: Token[], idx: number): string => { const { nesting, info } = tokens[idx]; - + const type = /\[(.*)\]/u.exec(info); + const title = /^ demo\s*(?:\[.*?\])?\s*(.*)\s*$/u.exec(info); if (nesting === -1) return ` @@ -11,27 +12,29 @@ export const codeDemoRender = (tokens: Token[], idx: number): string => { `; - let codeStr = ""; - let configStr = ""; + let config = ""; + const code: Record = {}; for (let i = idx; i < tokens.length; i++) { const { type, content, info } = tokens[i]; if (type === "container_demo_close") break; if (!content) continue; if (type === "fence") { - if (info === "json") configStr = encodeURIComponent(content); - else codeStr = encodeURIComponent(content); + if (info === "json") config = encodeURIComponent(content); + else code[info] = content; } } return `