This is an automated email from the ASF dual-hosted git repository.

shenyi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/echarts-handbook.git


The following commit(s) were added to refs/heads/master by this push:
     new ebd55ec  add md-live component
ebd55ec is described below

commit ebd55ece846a880742e70c84d62f14f9f92f94f1
Author: pissang <bm2736...@gmail.com>
AuthorDate: Wed Jun 2 20:45:55 2021 +0800

    add md-live component
---
 components/helper/loadScripts.ts                   |  53 +++++++++
 components/markdown/Live.vue                       | 124 +++++++++++++++++++++
 components/markdown/global.ts                      |   2 +
 .../zh/application/chart-types/line/area-line.md   |   5 +-
 .../zh/application/chart-types/line/basic-line.md  |  25 ++---
 .../zh/application/chart-types/line/smooth-line.md |   5 +-
 .../application/chart-types/line/stacked-line.md   |   8 +-
 .../zh/application/chart-types/line/step-line.md   |   5 +-
 contents/zh/meta/get-started.md                    |  36 +++++-
 layouts/default.vue                                |   3 +
 nuxt.config.js                                     |   2 +
 package-lock.json                                  |   5 +
 package.json                                       |   3 +-
 13 files changed, 246 insertions(+), 30 deletions(-)

diff --git a/components/helper/loadScripts.ts b/components/helper/loadScripts.ts
new file mode 100644
index 0000000..cff54ed
--- /dev/null
+++ b/components/helper/loadScripts.ts
@@ -0,0 +1,53 @@
+const promisesCache = {}
+interface ScriptObj {
+  url: string
+  type: 'css' | 'js'
+}
+export function loadScriptsAsync(scripts: (string | ScriptObj)[]) {
+  return Promise.all(
+    scripts
+      .map(scriptUrl => {
+        if (typeof scriptUrl === 'string') {
+          return {
+            url: scriptUrl,
+            // TODO Not supported type
+            type: scriptUrl.match(/\.css$/) ? 'css' : 'js'
+          }
+        }
+        return scriptUrl
+      })
+      .map(function(scriptUrl) {
+        if (promisesCache[scriptUrl.url]) {
+          return promisesCache[scriptUrl.url]
+        }
+
+        const promise = new Promise((resolve, reject) => {
+          if (scriptUrl.type === 'js') {
+            const script = document.createElement('script')
+            script.src = scriptUrl.url
+            script.async = false
+            script.onload = function() {
+              resolve(null)
+            }
+            script.onerror = function() {
+              reject()
+            }
+            document.body.appendChild(script)
+          } else if (scriptUrl.type === 'css') {
+            const link = document.createElement('link')
+            link.rel = 'stylesheet'
+            link.href = scriptUrl.url
+            link.onload = function() {
+              resolve(null)
+            }
+            link.onerror = function() {
+              reject()
+            }
+            document.body.appendChild(link)
+          }
+        })
+        promisesCache[scriptUrl.url] = promise
+        return promise
+      })
+  )
+}
diff --git a/components/markdown/Live.vue b/components/markdown/Live.vue
new file mode 100644
index 0000000..21b6832
--- /dev/null
+++ b/components/markdown/Live.vue
@@ -0,0 +1,124 @@
+<template>
+  <div class="md-live" v-if="innerCode">
+    <div class="md-live-editor">
+      <prism-editor v-model="innerCode" :highlight="highlighter">
+      </prism-editor>
+      <div class="md-live-tag">live</div>
+    </div>
+    <div class="md-live-preview"></div>
+  </div>
+</template>
+
+<script lang="ts">
+import Vue, { PropType } from 'vue'
+import { PrismEditor } from 'vue-prism-editor'
+import 'vue-prism-editor/dist/prismeditor.min.css'
+import { highlight, languages } from 'prismjs/components/prism-core'
+import 'prismjs/components/prism-clike'
+import 'prismjs/components/prism-javascript'
+import 'prism-themes/themes/prism-material-oceanic.css'
+import { loadScriptsAsync } from '../helper/loadScripts'
+
+function ensureECharts() {
+  if (typeof echarts === 'undefined') {
+    return loadScriptsAsync([
+      'https://cdn.jsdelivr.net/npm/echarts/dist/echarts.js'
+    ]).then(() => {})
+  }
+  return Promise.resolve()
+}
+
+export default Vue.extend({
+  components: {
+    PrismEditor
+  },
+  props: {
+    lang: {
+      type: String,
+      default: 'js'
+    }
+  },
+  data() {
+    return {
+      innerCode: ''
+    }
+  },
+  computed: {},
+  mounted() {
+    this.innerCode = (
+      (this.$slots.default && this.$slots.default[0].text) ||
+      ''
+    ).trim()
+  },
+  methods: {
+    highlighter(code) {
+      return highlight(code, languages[this.lang] || languages.js)
+    }
+  },
+  watch: {
+    innerCode() {
+      ensureECharts().then(() => {
+        // TODO type, resize, throttle
+        if (!this._chartInstance) {
+          this._chartInstance = echarts.init(
+            this.$el.querySelector('.md-live-preview')
+          )
+        }
+        const func = new Function(this.innerCode + '\n return option;')
+        try {
+          const option = func()
+          this._chartInstance.setOption(option)
+        } catch (e) {}
+      })
+    }
+  }
+})
+</script>
+
+<style lang="postcss">
+.md-live {
+  @apply shadow-lg rounded-lg mt-10 mb-20;
+}
+/* required class */
+.md-live-editor {
+  @apply rounded-t-lg;
+  position: relative;
+  /* we dont use `language-` classes anymore so thats why we need to add 
background and text color manually */
+  background: #263238;
+
+  font-size: 13px;
+  padding: 10px;
+
+  pre {
+    color: #c3cee3;
+  }
+
+  .md-live-tag {
+    position: absolute;
+    right: 0;
+    top: 0;
+    text-transform: uppercase;
+    margin-right: 1rem;
+    margin-top: 0.75rem;
+    color: #f7fafc;
+    z-index: 10;
+  }
+}
+
+.md-live-preview {
+  height: 300px;
+  @apply rounded-b-lg;
+}
+
+.prism-editor-wrapper .prism-editor__editor,
+.prism-editor-wrapper .prism-editor__textarea {
+  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
+    'Liberation Mono', 'Courier New', monospace;
+  line-height: 1.5;
+}
+
+/* optional class for removing the outline */
+.prism-editor__textarea:focus {
+  outline: none;
+}
+</style>
diff --git a/components/markdown/global.ts b/components/markdown/global.ts
index f48a156..ada0e5e 100644
--- a/components/markdown/global.ts
+++ b/components/markdown/global.ts
@@ -1,6 +1,8 @@
 import Vue from 'vue'
 import Example from './Example.vue'
 import Alert from './Alert.vue'
+import Live from './Live.vue'
 
 Vue.component('md-example', Example)
 Vue.component('md-alert', Alert)
+Vue.component('md-live', Live)
diff --git a/contents/zh/application/chart-types/line/area-line.md 
b/contents/zh/application/chart-types/line/area-line.md
index 921fc33..fa8421f 100644
--- a/contents/zh/application/chart-types/line/area-line.md
+++ b/contents/zh/application/chart-types/line/area-line.md
@@ -2,8 +2,7 @@
 
 区域面积折线图将折线到坐标轴的空间设置背景色,用区域面积表达数据。相比普通的折线图,区域面积折线图的视觉效果更加饱满丰富,在系列不多的场景下尤其适用。
 
-<!-- embed -->
-```js
+<md-live>
 option = {
     xAxis: {
         data: ['A', 'B', 'C', 'D', 'E']
@@ -22,6 +21,6 @@ option = {
         }
     }]
 };
-```
+</md-live>
 
 通过 [`areaStyle`](${optionPath}series-line.areaStyle) 设置折线图的填充区域样式,将其设为为 `{}` 
表示使用默认样式,即使用系列的颜色以半透明的方式填充区域。如果想指定特定的样式,可以通过设置 `areaStyle` 
下的配置项覆盖,如第二个系列将填充区域的颜色设为不透明度为 0.5 的黄色。
diff --git a/contents/zh/application/chart-types/line/basic-line.md 
b/contents/zh/application/chart-types/line/basic-line.md
index 2eee0b9..7f24b51 100644
--- a/contents/zh/application/chart-types/line/basic-line.md
+++ b/contents/zh/application/chart-types/line/basic-line.md
@@ -6,8 +6,7 @@
 
 如果我们想建立一个横坐标是类目型(category)、纵坐标是数值型(value)的折线图,我们可以使用这样的方式:
 
-<!-- embed -->
-```js
+<md-live>
 option = {
     xAxis: {
         type: 'category',
@@ -21,7 +20,7 @@ option = {
         type: 'line'
     }]
 };
-```
+</md-live>
 
 在这个例子中,我们通过 `xAxis` 将横坐标设为类目型,并指定了对应的值;通过 `type` 将 `yAxis` 的类型设定为数值型。在 
`series` 中,我们将系列类型设为 `line`,并且通过 `data` 指定了折线图三个点的取值。这样,就能得到一个最简单的折线图了。
 
@@ -32,8 +31,7 @@ option = {
 
 如果我们希望折线图在横坐标和纵坐标上都是连续的,即在笛卡尔坐标系中,应该如何实现呢?答案也很简单,只要把 `series` 的 `data` 
每个数据用一个包含两个元素的数组表示就行了。
 
-<!-- embed -->
-```js
+<md-live>
 option = {
     xAxis: {},
     yAxis: {},
@@ -42,7 +40,7 @@ option = {
         type: 'line'
     }]
 };
-```
+</md-live>
 
 
 ## 折线图样式设置
@@ -51,8 +49,7 @@ option = {
 
 折线图中折线的样式可以通过 `lineStyle` 设置。可以为其指定颜色、线宽、折线类型、阴影、不透明度等等,具体的可以参考配置项手册 
[`series.lineStyle`](${optionPath}series-line.lineStyle) 
了解。这里,我们以设置颜色(color)、线宽(width)和折线类型(type)为例说明。
 
-<!-- embed -->
-```js
+<md-live>
 option = {
     xAxis: {
         data: ['A', 'B', 'C', 'D', 'E']
@@ -70,7 +67,7 @@ option = {
         }
     }]
 };
-```
+</md-live>
 
 这里设置折线宽度时,数据点描边的宽度是不会跟着改变的,而应该在数据点的配置项中另外设置。
 
@@ -83,8 +80,7 @@ option = {
 
 在系列中,这数据点的标签通过 [`series.label`](${optionPath}series-line.label) 属性指定。如果将 
`label` 下的 `show` 指定为`true`,则表示该数值默认时就显示;如果为 `false`,而 
[`series.emphasis.label.show`](${optionPath}series-line.emphasis.label.show) 为 
`true`,则表示只有在鼠标移动到该数据时,才显示数值。
 
-<!-- embed -->
-```js
+<md-live>
 option = {
     xAxis: {
         data: ['A', 'B', 'C', 'D', 'E']
@@ -102,7 +98,7 @@ option = {
         }
     }]
 };
-```
+</md-live>
 
 
 ## 空数据
@@ -111,8 +107,7 @@ option = {
 
 在 ECharts 中,我们使用字符串 `'-'` 表示空数据,这对其他系列的数据也是适用的。
 
-<!-- embed -->
-```js
+<md-live>
 option = {
     xAxis: {
         data: ['A', 'B', 'C', 'D', 'E']
@@ -123,6 +118,6 @@ option = {
         type: 'line'
     }]
 };
-```
+</md-live>
 
 > 注意区别这个例子中,“空”数据与取值为 0 的数据。
diff --git a/contents/zh/application/chart-types/line/smooth-line.md 
b/contents/zh/application/chart-types/line/smooth-line.md
index 387cefc..c29f6cc 100644
--- a/contents/zh/application/chart-types/line/smooth-line.md
+++ b/contents/zh/application/chart-types/line/smooth-line.md
@@ -2,8 +2,7 @@
 
 平滑曲线图也是折线图的一种变形,这种更柔和的样式也是一种不错的视觉选择。使用时,只需要将折线图系列的 `smooth` 属性设置为 `true` 即可。
 
-<!-- embed -->
-```js
+<md-live>
 option = {
     xAxis: {
         data: ['A', 'B', 'C', 'D', 'E']
@@ -15,4 +14,4 @@ option = {
         smooth: true
     }]
 };
-```
+</md-live>
diff --git a/contents/zh/application/chart-types/line/stacked-line.md 
b/contents/zh/application/chart-types/line/stacked-line.md
index b022056..843f45f 100644
--- a/contents/zh/application/chart-types/line/stacked-line.md
+++ b/contents/zh/application/chart-types/line/stacked-line.md
@@ -3,7 +3,7 @@
 与[堆叠柱状图](./zh/application_chart-types_bar_stacked-bar)类似,堆叠折线图也是用系列的 `stack` 
设置哪些系列堆叠在一起。
 
 <!-- embed -->
-```js
+<md-live>
 option = {
     xAxis: {
         data: ['A', 'B', 'C', 'D', 'E']
@@ -19,12 +19,12 @@ option = {
         stack: 'x'
     }]
 };
-```
+</md-live>
 
 但是不同的是,如果不加说明的话,我们很难判断出这是一个堆叠折线图,还是一个普通的折线图。所以,对于堆叠折线图而言,一般建议使用区域填充色以表明堆叠的情况。
 
 <!-- embed -->
-```js
+<md-live>
 option = {
     xAxis: {
         data: ['A', 'B', 'C', 'D', 'E']
@@ -42,4 +42,4 @@ option = {
         areaStyle: {}
     }]
 };
-```
+</md-live>
diff --git a/contents/zh/application/chart-types/line/step-line.md 
b/contents/zh/application/chart-types/line/step-line.md
index d271602..ad73928 100644
--- a/contents/zh/application/chart-types/line/step-line.md
+++ b/contents/zh/application/chart-types/line/step-line.md
@@ -4,8 +4,7 @@
 
 在 ECharts 中,系列的 `step` 属性用来表征阶梯线图的连接类型,它共有三种取值:`'start'`、`'middle'` 和 
`'end'`,分别表示在当前点,当前点与下个点的中间点,下个点拐弯。
 
-<!-- embed -->
-```js
+<md-live>
 option = {
     xAxis: {
         type: 'category',
@@ -33,6 +32,6 @@ option = {
         data: [450, 432, 401, 454, 590, 530, 510]
     }]
 };
-```
+</md-live>
 
 > 请注意这个例子中不同的 `step` 取值对应的数据点和连线的区别。
diff --git a/contents/zh/meta/get-started.md b/contents/zh/meta/get-started.md
index 95d27a3..d70a4d4 100644
--- a/contents/zh/meta/get-started.md
+++ b/contents/zh/meta/get-started.md
@@ -88,6 +88,8 @@ option = {
 
 ### md-alert
 
+提示组件
+
 ```markdown
 <md-alert type="info">
 This is an info alert.
@@ -114,4 +116,36 @@ This is an warning alert.
 </md-alert>
 <md-alert type="danger">
 This is an danger alert.
-</md-alert>
\ No newline at end of file
+</md-alert>
+
+
+### md-live
+
+实时代码预览组件
+```markdown
+<md-live>
+option = {
+    xAxis: {
+        data: ['A', 'B', 'C', 'D', 'E']
+    },
+    yAxis: {},
+    series: [{
+        data: [0, 22, '-', 23, 19],
+        type: 'line'
+    }]
+};
+</md-live>
+```
+
+<md-live>
+option = {
+    xAxis: {
+        data: ['A', 'B', 'C', 'D', 'E']
+    },
+    yAxis: {},
+    series: [{
+        data: [0, 22, '-', 23, 19],
+        type: 'line'
+    }]
+};
+</md-live>
\ No newline at end of file
diff --git a/layouts/default.vue b/layouts/default.vue
index 02ea4d5..43b69a9 100644
--- a/layouts/default.vue
+++ b/layouts/default.vue
@@ -129,6 +129,9 @@ export default {
 
     @apply bg-blue-100 border-blue-400 rounded-lg;
 
+    code {
+      @apply bg-blue-200 shadow-none border-0 text-current;
+    }
     :first-child {
       margin-top: 0;
     }
diff --git a/nuxt.config.js b/nuxt.config.js
index 3df2268..38ba4cc 100644
--- a/nuxt.config.js
+++ b/nuxt.config.js
@@ -3,6 +3,8 @@ import zhPosts from './contents/zh/posts'
 import config from './configs/config'
 
 export default {
+  ssr: false,
+
   target: 'static',
 
   router: {
diff --git a/package-lock.json b/package-lock.json
index ae4ecd0..3336c4d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -20668,6 +20668,11 @@
       "resolved": 
"https://registry.npmjs.org/vue-no-ssr/-/vue-no-ssr-1.1.1.tgz";,
       "integrity": 
"sha512-ZMjqRpWabMPqPc7gIrG0Nw6vRf1+itwf0Itft7LbMXs2g3Zs/NFmevjZGN1x7K3Q95GmIjWbQZTVerxiBxI+0g=="
     },
+    "vue-prism-editor": {
+      "version": "1.2.2",
+      "resolved": 
"https://registry.npmjs.org/vue-prism-editor/-/vue-prism-editor-1.2.2.tgz";,
+      "integrity": 
"sha512-Lq2VgVygTx3Whn/tC8gD4m1ajA4lzSyCTqPLZA1Dq/ErbBaZA93FWRblwCoDR7AD2nXhGWuiTzb5ih3guzB7DA=="
+    },
     "vue-router": {
       "version": "3.5.1",
       "resolved": 
"https://registry.npmjs.org/vue-router/-/vue-router-3.5.1.tgz";,
diff --git a/package.json b/package.json
index 8bad855..fec488d 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,8 @@
     "markdown-it-table-of-contents": "^0.5.2",
     "nuxt": "^2.15.6",
     "nuxt-i18n": "^6.27.0",
-    "scroll-into-view": "^1.15.0"
+    "scroll-into-view": "^1.15.0",
+    "vue-prism-editor": "^1.2.2"
   },
   "devDependencies": {
     "@nuxt/content": "^1.14.0",

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@echarts.apache.org
For additional commands, e-mail: commits-h...@echarts.apache.org

Reply via email to