You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by ov...@apache.org on 2020/06/17 11:17:06 UTC

[incubator-echarts-handbook] 02/11: feat: router completed

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

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

commit 894cee7ab8eae4e91eed90355a0c700c2035d54a
Author: Ovilia <zw...@gmail.com>
AuthorDate: Wed Apr 1 14:11:05 2020 +0800

    feat: router completed
---
 components/Logo.vue               |  34 --------
 components/partials/Aside.vue     | 159 ++++++++++++++++++++++++++++++++++++++
 components/partials/Navigator.vue |  42 ++++++++++
 contents/en/enPosts.js            |   1 +
 contents/en/line.md               |   0
 contents/zh/line.md               |  20 +++++
 contents/zh/zhPosts.js            |   1 +
 layouts/default.vue               | 153 +++++++++++++++++++++++++++---------
 nuxt.config.js                    |  36 ++++++++-
 package-lock.json                 | 121 +++++++++++++++++++++++++++++
 package.json                      |  11 ++-
 pages/index.vue                   |  79 +++++++++++--------
 pages/zh/_post.vue                |  29 +++++++
 store/index.js                    |  72 +++++++++++++++++
 tsconfig.json                     |   4 +-
 types/nuxt.d.ts                   |  23 ++++++
 16 files changed, 677 insertions(+), 108 deletions(-)

diff --git a/components/Logo.vue b/components/Logo.vue
deleted file mode 100644
index 58118db..0000000
--- a/components/Logo.vue
+++ /dev/null
@@ -1,34 +0,0 @@
-<template>
-  <svg class="NuxtLogo" width="245" height="180" viewBox="0 0 452 342" xmlns="http://www.w3.org/2000/svg">
-    <g fill="none" fill-rule="evenodd">
-      <path
-        d="M139 330l-1-2c-2-4-2-8-1-13H29L189 31l67 121 22-16-67-121c-1-2-9-14-22-14-6 0-15 2-22 15L5 303c-1 3-8 16-2 27 4 6 10 12 24 12h136c-14 0-21-6-24-12z"
-        fill="#00C58E"
-      />
-      <path
-        d="M447 304L317 70c-2-2-9-15-22-15-6 0-15 3-22 15l-17 28v54l39-67 129 230h-49a23 23 0 0 1-2 14l-1 1c-6 11-21 12-23 12h76c3 0 17-1 24-12 3-5 5-14-2-26z"
-        fill="#108775"
-      />
-      <path
-        d="M376 330v-1l1-2c1-4 2-8 1-12l-4-12-102-178-15-27h-1l-15 27-102 178-4 12a24 24 0 0 0 2 15c4 6 10 12 24 12h190c3 0 18-1 25-12zM256 152l93 163H163l93-163z"
-        fill="#2F495E"
-        fill-rule="nonzero"
-      />
-    </g>
-  </svg>
-</template>
-<style>
-.NuxtLogo {
-  animation: 1s appear;
-  margin: auto;
-}
-
-@keyframes appear {
-  0% {
-    opacity: 0;
-  }
-  100% {
-    opacity: 1;
-  }
-}
-</style>
diff --git a/components/partials/Aside.vue b/components/partials/Aside.vue
new file mode 100644
index 0000000..cb066d7
--- /dev/null
+++ b/components/partials/Aside.vue
@@ -0,0 +1,159 @@
+<template>
+  <aside :class="{ 'opacity-25': $store.state.focusMode }" class="opacity-transition block bg-gray-100 mt-8 -mx-4 lg:bg-transparent lg:mt-0 lg:mx-0 lg:inset-0 z-90 lg:mb-0 lg:static lg:h-auto lg:overflow-y-visible lg:pt-0 lg:w-1/4 lg:block">
+    <div class="h-full overflow-y-auto scrolling-touch text-center lg:text-left lg:h-auto lg:block lg:relative lg:sticky lg:top-24">
+      <a v-if="breadcrumb" class="block text-left p-4 lg:hidden" href="#nav" @click.prevent="showNav = !showNav">
+        <nui-times v-if="showNav" class="float-right mt-1 mr-1 h-5" />
+        <nui-caret-down v-else class="float-right mt-2 mr-1" />
+        <span class="uppercase text-gray-500 ml-1">{{ breadcrumb.group }} :</span> {{ breadcrumb.title }}
+      </a>
+      <nav class="pt-8 lg:overflow-y-auto lg:block lg:pl-0 lg:pr-8 sticky?lg:h-(screen-24)" :class="{ hidden: !showNav }">
+        <p class="uppercase font-bold pb-6">
+          {{ $store.state.lang.text.version }} <span class="text-nuxt-lightgreen">{{ $store.state.docVersion }}</span>
+        </p>
+        <template v-for="(group, index) in list">
+          <h3 :key="`title-${index}`" class="uppercase font-medium text-light-onSurfaceSecondary dark:text-dark-onSurfaceSecondary pb-2 transition-colors duration-300 ease-linear">
+            {{ group.title }}
+          </h3>
+          <ul :key="`list-${index}`" class="pb-8">
+            <li v-for="link in group.links" :key="link.to" class="py-2">
+              <nuxt-link class="text-light-onSurfacePrimary dark:text-dark-onSurfacePrimary hover:text-nuxt-lightgreen dark:hover:text-nuxt-lightgreen transition-colors duration-300 ease-linear" :class="{'current-link': path === menu + link.to}" :to="menu + link.to" exact>
+                {{ link.name }}
+              </nuxt-link>
+              <ul v-if="path === menu + link.to && link.contents" class="pl-2 py-1">
+                <li v-for="(content, i) in link.contents" :key="content.to" class="py-1 text-sm">
+                  <a :href="menu + link.to + content.to" class="text-light-onSurfaceSecondary dark:text-dark-onSurfaceSecondary transition-colors duration-300 ease-linear" :class="{'current-link': current === i}" @click.prevent="scrollTo(content.to)">
+                    {{ content.name }}
+                  </a>
+                </li>
+              </ul>
+            </li>
+          </ul>
+        </template>
+      </nav>
+    </div>
+  </aside>
+</template>
+
+<script>
+import throttle from 'lodash/throttle'
+import nuiCaretDown from '@/components/svg/CaretDown'
+import nuiTimes from '@/components/svg/Times'
+
+export default {
+  components: {
+    nuiCaretDown,
+    nuiTimes
+  },
+  data () {
+    return { current: 0, setInter: null, showNav: false }
+  },
+  computed: {
+    list () {
+      return this.$store.state.menu[this.$route.params.section] || []
+    },
+    visible () { return this.$store.state.visibleAffix },
+    path () { return this.$route.path.slice(-1) === '/' ? this.$route.path.slice(0, -1) : this.$route.path },
+    menu () { return '/' + this.$route.params.section },
+    breadcrumb () {
+      let breadcrumb = null
+      this.list.forEach((group) => {
+        group.links.forEach((link) => {
+          if ((this.$route.params.slug && link.to === '/' + this.$route.params.slug) || (!this.$route.params.slug && (link.to === '' || link.to === '/'))) {
+            breadcrumb = { group: group.title, title: link.name }
+          }
+        })
+      })
+      return breadcrumb
+    },
+    contents () {
+      const c = []
+      this.list.forEach((group) => {
+        if (Array.isArray(group.links) && !c.length) {
+          const l = group.links.find((link) => {
+            return this.path === this.menu + link.to
+          })
+          if (l && l.contents) {
+            l.contents.forEach((content) => {
+              const el = document.getElementById(content.to.slice(1))
+              if (el) {
+                c.push(el.offsetTop)
+              }
+            })
+          }
+        }
+      })
+      return c
+    }
+  },
+  watch: {
+    '$route.fullPath': 'hashChanged'
+  },
+  mounted () {
+    this.$nextTick(() => {
+      window.addEventListener('scroll', throttle(() => this.scrolled(), 100))
+      if (this.$route.hash.length) {
+        this.scrollTo(this.$route.hash)
+      }
+      this.scrolled()
+    })
+  },
+  methods: {
+    hashChanged (toPath, fromPath) {
+      this.showNav = false
+      toPath = toPath.split('#')
+      fromPath = fromPath.split('#')
+      this.$nextTick(() => this.scrollTo(this.$route.hash))
+    },
+    toggle () { this.$store.commit('toggle', 'visibleAffix') },
+    scrolled () {
+      const h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
+      const doc = document.documentElement
+      const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
+      const el = this.contents.find((pos) => {
+        return pos > top + (h / 2)
+      })
+      this.current = (el ? this.contents.indexOf(el) : this.contents.length) - 1
+    },
+    scrollTo (id) {
+      if (this._scrolling) {
+        return
+      }
+      this._scrolling = true
+      if (this.$store.state.visibleAffix) {
+        this.toggle()
+      }
+      if (id !== this.$route.hash) {
+        this.$router.push(this.$route.fullPath.split('#')[0] + id)
+      }
+      this.$nextTick(() => {
+        const el = document.getElementById(id.slice(1))
+        if (!el) {
+          this._scrolling = false
+          return
+        }
+        const to = el.offsetTop - (window.outerWidth < 1024 ? 90 : 120)
+        const doc = document.documentElement
+        let top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
+        const diff = (to > top ? to - top : top - to) / 25
+        let i = 0
+        window.clearInterval(this.setInter)
+        this.setInter = window.setInterval(() => {
+          top = (to > top) ? top + diff : top - diff
+          window.scrollTo(0, top)
+          i++
+          if (i === 25) {
+            this._scrolling = false
+            window.clearInterval(this.setInter)
+          }
+        }, 10)
+      })
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.current-link {
+  color: theme('colors.primary.base');
+}
+</style>
diff --git a/components/partials/Navigator.vue b/components/partials/Navigator.vue
new file mode 100644
index 0000000..426dd0d
--- /dev/null
+++ b/components/partials/Navigator.vue
@@ -0,0 +1,42 @@
+<template>
+    <!-- tmp nav -->
+    <div>
+        <nav>
+            <img src="http://localhost/incubator-echarts-website/zh/images/logo.png">
+
+            <div class="nav-btn">首页</div>
+            <div class="nav-btn">下载</div>
+            <div class="nav-btn">实例</div>
+            <div class="nav-btn">社区</div>
+            <div class="nav-btn">工具</div>
+            <div class="nav-btn">贡献</div>
+            <div class="nav-btn">关于</div>
+        </nav>
+    </div>
+</template>
+<style>
+
+nav {
+    width: 100%;
+    height: 50px;
+    background-color: #293c55;
+}
+
+.nav-btn {
+    color: rgba(255,255,255,0.45);
+    display: inline-block;
+    padding: 13px 20px;
+    margin-left: 5px;
+    font-size: 14px;
+    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+nav img {
+    float: left;
+    height: 50px;
+    padding: 12px 12px;
+    font-size: 18px;
+    line-height: 20px;
+}
+
+</style>
diff --git a/contents/en/enPosts.js b/contents/en/enPosts.js
new file mode 100644
index 0000000..d6d1738
--- /dev/null
+++ b/contents/en/enPosts.js
@@ -0,0 +1 @@
+export default [];
diff --git a/contents/en/line.md b/contents/en/line.md
new file mode 100644
index 0000000..e69de29
diff --git a/contents/zh/line.md b/contents/zh/line.md
new file mode 100644
index 0000000..9ba27d0
--- /dev/null
+++ b/contents/zh/line.md
@@ -0,0 +1,20 @@
+# 柱状图
+
+柱状通过柱形的高度来表现数据的大小,用于有至少一个类目轴或时间轴的直角坐标系上。
+
+## 最简单的柱状图
+
+设置柱状图的方式,是将 `series.name` 设为 `"bar"`。最简单的柱状图可以这样设置:
+
+```js
+option = {
+    xAxis: {
+        data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
+    },
+    yAxis: {},
+    series: [{
+        type: 'bar',
+        data: [23, 24, 18, 25, 27, 28, 25]
+    }]
+};
+```
diff --git a/contents/zh/zhPosts.js b/contents/zh/zhPosts.js
new file mode 100644
index 0000000..8775b96
--- /dev/null
+++ b/contents/zh/zhPosts.js
@@ -0,0 +1 @@
+export default ['line'];
diff --git a/layouts/default.vue b/layouts/default.vue
index 2f45459..347fa81 100644
--- a/layouts/default.vue
+++ b/layouts/default.vue
@@ -1,55 +1,134 @@
 <template>
   <div>
-    <nuxt />
+    <navigator />
+
+    <div class="container-fluid">
+      <div class="row flex-xl-nowrap2">
+        <div class="bd-sidebar border-bottom-0 col-md-3 col-xl-2 col-12">
+          <div class="bd-docs-nav">
+            <div class="bd-toc-item">
+              <a href="#" class="bd-toc-link">开始</a>
+              <ul class="nav bd-sidenav">
+                <li class="nav-item">
+                  <a href="#" class="nav-link">第一个 ECharts 图表</a>
+                </li>
+                <li class="nav-item">
+                  <a href="#" class="nav-link">定制主题样式</a>
+                </li>
+                <li class="nav-item">
+                  <a href="#" class="nav-link">基本概念</a>
+                </li>
+              </ul>
+            </div>
+            <div class="bd-toc-item">
+              <a href="#" class="bd-toc-link nuxt-link-exact-active">图表类型</a>
+              <ul class="nav bd-sidenav">
+                <li class="nav-item">
+                  <a href="#" class="nav-link">折线图</a>
+                </li>
+                <li class="nav-item">
+                  <a href="#" class="nav-link">柱状图</a>
+                </li>
+                <li class="nav-item">
+                  <a href="#" class="nav-link">饼图</a>
+                </li>
+                <li class="nav-item">
+                  <a href="#" class="nav-link">散点图</a>
+                </li>
+                <li class="nav-item">
+                  <a href="#" class="nav-link">涟漪散点图</a>
+                </li>
+                <li class="nav-item">
+                  <a href="#" class="nav-link">雷达图</a>
+                </li>
+                <li class="nav-item">
+                  <a href="#" class="nav-link">树图</a>
+                </li>
+              </ul>
+            </div>
+          </div>
+        </div>
+        <div class="bd-content col-md-9 col-xl-8 col-12 pb-md-3 pl-md-5">
+          <div class="post-content content">
+            <nuxt />
+          </div>
+        </div>
+      </div>
+    </div>
   </div>
 </template>
 
+<script lang="ts">
+import Vue from 'vue';
+import Navigator from '~/components/partials/Navigator.vue';
+
+export default Vue.extend({
+  components: {
+    Navigator
+  }
+})
+</script>
+
 <style>
-html {
-  font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, 'Segoe UI',
-    Roboto, 'Helvetica Neue', Arial, sans-serif;
-  font-size: 16px;
-  word-spacing: 1px;
-  -ms-text-size-adjust: 100%;
-  -webkit-text-size-adjust: 100%;
-  -moz-osx-font-smoothing: grayscale;
-  -webkit-font-smoothing: antialiased;
-  box-sizing: border-box;
+.bd-sidebar {
+  padding: 20px;
+}
+
+.bd-toc-item {
+  margin-bottom: 20px;
+}
+
+.bd-sidenav {
+  margin-top: 10px;
+  display: none;
+}
+
+.nav {
+  display: block;
+}
+
+.bd-toc-link {
+  font-weight: bold;
+  color: #444;
+}
+
+.nav-link {
+  color: #555;
 }
 
-*,
-*:before,
-*:after {
-  box-sizing: border-box;
-  margin: 0;
+  .nav-link:hover {
+    text-decoration: underline;
+  }
+
+
+
+.post-content {
+  margin: 20px 0;
 }
 
-.button--green {
-  display: inline-block;
-  border-radius: 4px;
-  border: 1px solid #3b8070;
-  color: #3b8070;
-  text-decoration: none;
-  padding: 10px 30px;
+h1 {
+  margin-bottom: 20px;
+  font-size: 36px;
 }
 
-.button--green:hover {
-  color: #fff;
-  background-color: #3b8070;
+h2 {
+  margin: 40px 0 20px 0;
+  font-size: 26px;
 }
 
-.button--grey {
-  display: inline-block;
-  border-radius: 4px;
-  border: 1px solid #35495e;
-  color: #35495e;
-  text-decoration: none;
-  padding: 10px 30px;
-  margin-left: 15px;
+h3 {
+  font-size: 22px;
+}
+
+h4 {
+  font-size: 18px;
+}
+
+h5 {
+  font-size: 16px;
 }
 
-.button--grey:hover {
-  color: #fff;
-  background-color: #35495e;
+h6 {
+  font-size: 14px;
 }
 </style>
diff --git a/nuxt.config.js b/nuxt.config.js
index b4ca074..19d82cf 100644
--- a/nuxt.config.js
+++ b/nuxt.config.js
@@ -1,3 +1,5 @@
+import enPosts from './contents/en/enPosts';
+import zhPosts from './contents/zh/zhPosts';
 
 export default {
   mode: 'universal',
@@ -45,7 +47,25 @@ export default {
   */
   modules: [
     // Doc: https://bootstrap-vue.js.org
-    'bootstrap-vue/nuxt'
+    'bootstrap-vue/nuxt',
+    [
+      'nuxt-i18n',
+      {
+        locales: ['en', 'zh'],
+        defaultLocale: 'en',
+        vueI18n: {
+          fallbackLocale: 'en',
+          messages: {
+            en: {
+              greeting: 'Hello world!'
+            },
+            zh: {
+              greeting: '你好!'
+            }
+          }
+        }
+      }
+    ]
   ],
   /*
   ** Build configuration
@@ -55,10 +75,24 @@ export default {
     ** You can extend webpack config here
     */
     extend (config, ctx) {
+      config.module.rules.push({
+        test: /\.md$/,
+        use: ['raw-loader']
+      });
     },
 
     filenames: {
       chunk: 'js/[contenthash].js'
     }
+  },
+  generate: {
+    routes: [
+      '/zh/line'
+    ]
+    // routes: [
+
+    // ]
+    // .concat(zhPosts.map(post => `/zh/${post}`))
+    // .concat(enPosts.map(post => `/en/${post}`))
   }
 }
diff --git a/package-lock.json b/package-lock.json
index e336076..16169e4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -923,6 +923,15 @@
       "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
       "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw=="
     },
+    "@intlify/vue-i18n-loader": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/@intlify/vue-i18n-loader/-/vue-i18n-loader-0.6.1.tgz",
+      "integrity": "sha512-PyBeKrIxNQmnHq/hYGMneVIQAlGTWsFu92SMD5Noyi3GcHJvDpnthWTuRUBAsY4WqQ7RYLCnrngqCrUY5tNZtg==",
+      "requires": {
+        "js-yaml": "^3.13.1",
+        "json5": "^2.1.1"
+      }
+    },
     "@nuxt/babel-preset-app": {
       "version": "2.12.1",
       "resolved": "https://registry.npmjs.org/@nuxt/babel-preset-app/-/babel-preset-app-2.12.1.tgz",
@@ -5569,6 +5578,39 @@
         }
       }
     },
+    "front-matter": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-3.1.0.tgz",
+      "integrity": "sha512-RFEK8N6waWTdwBZOPNEtvwMjZ/hUfpwXkYUYkmmOhQGdhSulXhWrFwiUhdhkduLDiIwbROl/faF1X/PC/GGRMw==",
+      "dev": true,
+      "requires": {
+        "js-yaml": "^3.13.1"
+      }
+    },
+    "frontmatter-markdown-loader": {
+      "version": "3.3.0",
+      "resolved": "https://registry.npmjs.org/frontmatter-markdown-loader/-/frontmatter-markdown-loader-3.3.0.tgz",
+      "integrity": "sha512-aEn0v7XM+pvvCltcnUSrFAjVziH5jgjR0Z+ccVH7QXZDYLN5FjUxj15tUvEVHx6mgV6HVHkmt1YdDQowyOIQxA==",
+      "dev": true,
+      "requires": {
+        "front-matter": "^3.0.1",
+        "loader-utils": "^2.0.0",
+        "markdown-it": "^10.0.0"
+      },
+      "dependencies": {
+        "loader-utils": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+          "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+          "dev": true,
+          "requires": {
+            "big.js": "^5.2.2",
+            "emojis-list": "^3.0.0",
+            "json5": "^2.1.2"
+          }
+        }
+      }
+    },
     "fs-extra": {
       "version": "8.1.0",
       "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@@ -6834,6 +6876,11 @@
         "is-extglob": "^2.1.1"
       }
     },
+    "is-https": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-https/-/is-https-1.0.0.tgz",
+      "integrity": "sha512-1adLLwZT9XEXjzhQhZxd75uxf0l+xI9uTSFaZeSESjL3E1eXSPpO+u5RcgqtzeZ1KCaNvtEwZSTO2P4U5erVqQ=="
+    },
     "is-nan": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz",
@@ -6972,6 +7019,11 @@
         }
       }
     },
+    "js-cookie": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz",
+      "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="
+    },
     "js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -7083,6 +7135,15 @@
       "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=",
       "dev": true
     },
+    "linkify-it": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz",
+      "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==",
+      "dev": true,
+      "requires": {
+        "uc.micro": "^1.0.1"
+      }
+    },
     "load-json-file": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
@@ -7343,6 +7404,19 @@
         "object-visit": "^1.0.0"
       }
     },
+    "markdown-it": {
+      "version": "10.0.0",
+      "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-10.0.0.tgz",
+      "integrity": "sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==",
+      "dev": true,
+      "requires": {
+        "argparse": "^1.0.7",
+        "entities": "~2.0.0",
+        "linkify-it": "^2.0.0",
+        "mdurl": "^1.0.1",
+        "uc.micro": "^1.0.5"
+      }
+    },
     "md5.js": {
       "version": "1.3.5",
       "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@@ -7358,6 +7432,12 @@
       "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
       "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA=="
     },
+    "mdurl": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
+      "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=",
+      "dev": true
+    },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -7874,6 +7954,21 @@
         "@nuxt/webpack": "2.12.1"
       }
     },
+    "nuxt-i18n": {
+      "version": "6.7.2",
+      "resolved": "https://registry.npmjs.org/nuxt-i18n/-/nuxt-i18n-6.7.2.tgz",
+      "integrity": "sha512-A1olNJuumr8r6o5C8hV9hgJO7KG4AEx9m2Cn/8dKNi1VHQCCx0DcGlTS6B9mgenpqmpBBbB09OWcOrrA9wJI9Q==",
+      "requires": {
+        "@babel/parser": "^7.5.5",
+        "@babel/traverse": "^7.5.5",
+        "@intlify/vue-i18n-loader": "^0.6.1",
+        "cookie": "^0.4.0",
+        "is-https": "^1.0.0",
+        "js-cookie": "^2.2.1",
+        "vue-i18n": "^8.12.0",
+        "vue-i18n-extensions": "^0.2.1"
+      }
+    },
     "object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -9455,6 +9550,16 @@
         "unpipe": "1.0.0"
       }
     },
+    "raw-loader": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.0.tgz",
+      "integrity": "sha512-iINUOYvl1cGEmfoaLjnZXt4bKfT2LJnZZib5N/LLyAphC+Dd11vNP9CNVb38j+SAJpFI1uo8j9frmih53ASy7Q==",
+      "dev": true,
+      "requires": {
+        "loader-utils": "^1.2.3",
+        "schema-utils": "^2.5.0"
+      }
+    },
     "read-cache": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -10941,6 +11046,12 @@
       "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz",
       "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ=="
     },
+    "uc.micro": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
+      "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==",
+      "dev": true
+    },
     "uglify-js": {
       "version": "3.4.10",
       "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
@@ -11252,6 +11363,16 @@
       "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
       "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog=="
     },
+    "vue-i18n": {
+      "version": "8.16.0",
+      "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.16.0.tgz",
+      "integrity": "sha512-cp9JOsx4ETzlCsnD22FE8ZhAmD8kcyNLRKV0DPsS7bBNTCdIlOKuyTGonWKYcGCUtNMtwemDWRBevRm8eevBVg=="
+    },
+    "vue-i18n-extensions": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/vue-i18n-extensions/-/vue-i18n-extensions-0.2.1.tgz",
+      "integrity": "sha512-xBrItI7bEwBnG7eAlnyUARP41JYYn2+ABMR8q1Yh5FM9hHCbs4XPZwG+4+FPeIZ6b5gYk4YUP//m+fWiuU9z9A=="
+    },
     "vue-loader": {
       "version": "15.9.1",
       "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.1.tgz",
diff --git a/package.json b/package.json
index 7486315..9080abc 100644
--- a/package.json
+++ b/package.json
@@ -12,9 +12,10 @@
     "lint": "eslint --ext .js,.vue --ignore-path .gitignore ."
   },
   "dependencies": {
-    "nuxt": "^2.0.0",
+    "bootstrap": "^4.1.3",
     "bootstrap-vue": "^2.0.0",
-    "bootstrap": "^4.1.3"
+    "nuxt": "^2.0.0",
+    "nuxt-i18n": "^6.7.2"
   },
   "devDependencies": {
     "@nuxt/typescript-build": "^0.6.0",
@@ -22,6 +23,10 @@
     "@nuxtjs/eslint-module": "^1.0.0",
     "babel-eslint": "^10.0.1",
     "eslint": "^6.1.0",
-    "eslint-plugin-nuxt": ">=0.4.2"
+    "eslint-plugin-nuxt": ">=0.4.2",
+    "front-matter": "^3.1.0",
+    "frontmatter-markdown-loader": "^3.3.0",
+    "markdown-it": "^10.0.0",
+    "raw-loader": "^4.0.0"
   }
 }
diff --git a/pages/index.vue b/pages/index.vue
index 50a6b85..148b8cc 100644
--- a/pages/index.vue
+++ b/pages/index.vue
@@ -1,42 +1,57 @@
 <template>
-  <div class="container">
-    <div>
-      <logo />
-      <h1 class="title">
-        echarts-booklet
-      </h1>
-      <h2 class="subtitle">
-        ECharts booklet
-      </h2>
-      <div class="links">
-        <a
-          href="https://nuxtjs.org/"
-          target="_blank"
-          class="button--green"
-        >
-          Documentation
-        </a>
-        <a
-          href="https://github.com/nuxt/nuxt.js"
-          target="_blank"
-          class="button--grey"
-        >
-          GitHub
-        </a>
-      </div>
-    </div>
+  <div>
+    this is index
   </div>
 </template>
 
 <script lang="ts">
-import Vue from 'vue'
-import Logo from '~/components/Logo.vue'
+// const fm = require("front-matter");
+// var md = require("markdown-it")({
+//   html: true,
+//   typographer: true
+// });
+import fm from 'front-matter';
+import md from 'markdown-it';
 
-export default Vue.extend({
-  components: {
-    Logo
+export default {
+  async asyncData(data) {
+    console.log(data);
+    // const fileContent = await import(`~/contents/${data.params.post}.md`);
+    // let res = fm(fileContent.default);
+    // return {
+    //   // attributes will be an object containing the markdown metadata
+    //   attributes: res.attributes,
+    //   // content will contain the body of the markdown file,
+    //   // rendered in HTML via the `markdownit` class
+    //   content: md.render(res.body)
+    // };
   }
-})
+}
+
+// import Vue from 'vue';
+
+// export default Vue.extend({
+//   components: {
+//   },
+//   async asyncData(value) {
+//     console.log(value.params);
+//     // ${app.i18n.locale}
+//     // const fileContent = await import(`~/contents/zh/${value.params.slug}.md`)
+//     // const attr = fileContent.attributes
+//     // return {
+//     //   colors: attr.colors,
+//     //   date: attr.date,
+//     //   description: attr.description,
+//     //   id: attr.id,
+//     //   name: value.params.slug,
+//     //   related: attr.related,
+//     //   renderFunc: fileContent.vue.render,
+//     //   staticRenderFuncs: fileContent.vue.staticRenderFns,
+//     //   title: attr.title,
+//     //   urlTranslation: attr.urlTranslation
+//     // }
+//   }
+// })
 </script>
 
 <style>
diff --git a/pages/zh/_post.vue b/pages/zh/_post.vue
new file mode 100644
index 0000000..c37b973
--- /dev/null
+++ b/pages/zh/_post.vue
@@ -0,0 +1,29 @@
+<template>
+  <div v-html="content" class="post-inner"></div>
+</template>
+
+<script lang="ts">
+import fm from 'front-matter';
+import MarkdownIt from 'markdown-it';
+import Vue from 'vue';
+
+const md = new MarkdownIt();
+console.log(typeof md.render);
+
+export default Vue.extend({
+  components: {
+  },
+  async asyncData({params}) {
+    const fileContent = await import(`~/contents/zh/${params.post}.md`);
+    const res = fm(fileContent.default);
+    return {
+      attributes: res.attributes,
+      content: md.render(res.body)
+    };
+  }
+});
+
+</script>
+
+<style>
+</style>
diff --git a/store/index.js b/store/index.js
new file mode 100644
index 0000000..fd0dcb1
--- /dev/null
+++ b/store/index.js
@@ -0,0 +1,72 @@
+export const state = () => ({
+  filled: false,
+  docVersion: '',
+  ghVersion: '',
+  visibleAffix: false,
+  locale: 'en',
+  lang: {},
+  menu: {},
+  homepage: {},
+  adBlocked: false,
+  focusMode: false
+})
+
+export const mutations = {
+  toggle (state, key) {
+    state[key] = !state[key]
+  },
+  setDocVersion (state, docVersion) {
+    state.docVersion = docVersion
+  },
+  setGhVersion (state, ghVersion) {
+    state.ghVersion = ghVersion
+  },
+  setLocale (state, locale) {
+    state.locale = locale
+  },
+  setLang (state, lang) {
+    state.lang = lang
+  },
+  setMenu (state, menu) {
+    state.menu = menu
+  },
+  setHomepage (state, homepage) {
+    state.homepage = homepage
+  },
+  setFilled (state) {
+    state.filled = true
+  },
+  setAdBlocked (state, value) {
+    state.adBlocked = value
+  },
+  setFocusMode (state, value) {
+    state.focusMode = value
+  }
+}
+
+let _focusTimeout = null
+
+export const actions = {
+  async getLangData ({ commit }, locale) {
+    const lang = await this.$docs.get('/lang/' + locale)
+    commit('setLang', lang)
+    commit('setDocVersion', lang.docVersion)
+    const menu = await this.$docs.get('/menu/' + locale)
+    commit('setMenu', menu)
+    const homepage = await this.$docs.get('/homepage/' + locale)
+    commit('setHomepage', homepage)
+  },
+  focusMode ({ commit }) {
+    if (_focusTimeout) {
+      return
+    }
+    _focusTimeout = setTimeout(() => commit('setFocusMode', true), 1300)
+  },
+  clearFocusMode ({ commit }) {
+    if (_focusTimeout) {
+      clearTimeout(_focusTimeout)
+      _focusTimeout = null
+    }
+    commit('setFocusMode', false)
+  }
+}
diff --git a/tsconfig.json b/tsconfig.json
index 3537b80..2bf1c8e 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -13,6 +13,7 @@
     "sourceMap": true,
     "strict": true,
     "noEmit": true,
+    "noImplicitAny": false,
     "experimentalDecorators": true,
     "baseUrl": ".",
     "paths": {
@@ -25,7 +26,8 @@
     },
     "types": [
       "@types/node",
-      "@nuxt/types"
+      "@nuxt/types",
+      "./types/nuxt.d.ts"
     ]
   },
   "exclude": [
diff --git a/types/nuxt.d.ts b/types/nuxt.d.ts
new file mode 100644
index 0000000..3e4548e
--- /dev/null
+++ b/types/nuxt.d.ts
@@ -0,0 +1,23 @@
+import Vue from 'vue'
+import { Store } from 'vuex'
+
+// ComponentOptions is declared in types/options.d.ts
+declare module 'vue/types/options' {
+
+  interface NuxtContext<V extends Vue> {
+    app: V,
+    isClient: boolean,
+    isServer: boolean,
+    isStatic: boolean,
+    isDev: boolean,
+    store: Store<any>, // Consider vuex-typex in future
+    env: object,
+    params: object,
+    query: object
+  }
+
+  interface ComponentOptions<V extends Vue> {
+    asyncData?(context: NuxtContext<V>): Promise<object> | object
+    fetch?(context: NuxtContext<V>): Promise<object> | object
+  }
+}


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