aboutsummaryrefslogtreecommitdiff
path: root/node_modules/vuepress/lib
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/vuepress/lib')
-rw-r--r--node_modules/vuepress/lib/app/.temp/enhanceApp.js1
-rw-r--r--node_modules/vuepress/lib/app/.temp/override.styl1
-rw-r--r--node_modules/vuepress/lib/app/.temp/routes.js178
-rw-r--r--node_modules/vuepress/lib/app/.temp/siteData.js634
-rw-r--r--node_modules/vuepress/lib/app/.temp/style.styl1
-rw-r--r--node_modules/vuepress/lib/app/.temp/themeEnhanceApp.js1
-rw-r--r--node_modules/vuepress/lib/app/SWUpdateEvent.js43
-rw-r--r--node_modules/vuepress/lib/app/app.js102
-rw-r--r--node_modules/vuepress/lib/app/clientEntry.js74
-rw-r--r--node_modules/vuepress/lib/app/components/Badge.vue46
-rw-r--r--node_modules/vuepress/lib/app/components/ClientOnly.js12
-rw-r--r--node_modules/vuepress/lib/app/components/Content.js17
-rw-r--r--node_modules/vuepress/lib/app/components/OutboundLink.vue12
-rw-r--r--node_modules/vuepress/lib/app/dataMixin.js90
-rw-r--r--node_modules/vuepress/lib/app/index.dev.html11
-rw-r--r--node_modules/vuepress/lib/app/index.ssr.html17
-rw-r--r--node_modules/vuepress/lib/app/root-mixins/activeHeaderLinks.js47
-rw-r--r--node_modules/vuepress/lib/app/root-mixins/index.js7
-rw-r--r--node_modules/vuepress/lib/app/root-mixins/updateMeta.js59
-rw-r--r--node_modules/vuepress/lib/app/serverEntry.js14
-rw-r--r--node_modules/vuepress/lib/app/store.js7
-rw-r--r--node_modules/vuepress/lib/app/util.js19
-rw-r--r--node_modules/vuepress/lib/build.js200
-rw-r--r--node_modules/vuepress/lib/default-theme/AlgoliaSearchBox.vue156
-rw-r--r--node_modules/vuepress/lib/default-theme/DropdownLink.vue181
-rw-r--r--node_modules/vuepress/lib/default-theme/DropdownTransition.vue33
-rw-r--r--node_modules/vuepress/lib/default-theme/Home.vue162
-rw-r--r--node_modules/vuepress/lib/default-theme/Layout.vue183
-rw-r--r--node_modules/vuepress/lib/default-theme/NavLink.vue49
-rw-r--r--node_modules/vuepress/lib/default-theme/NavLinks.vue151
-rw-r--r--node_modules/vuepress/lib/default-theme/Navbar.vue133
-rw-r--r--node_modules/vuepress/lib/default-theme/NotFound.vue26
-rw-r--r--node_modules/vuepress/lib/default-theme/Page.vue246
-rw-r--r--node_modules/vuepress/lib/default-theme/SWUpdatePopup.vue85
-rw-r--r--node_modules/vuepress/lib/default-theme/SearchBox.vue238
-rw-r--r--node_modules/vuepress/lib/default-theme/Sidebar.vue113
-rw-r--r--node_modules/vuepress/lib/default-theme/SidebarButton.vue28
-rw-r--r--node_modules/vuepress/lib/default-theme/SidebarGroup.vue77
-rw-r--r--node_modules/vuepress/lib/default-theme/SidebarLink.vue91
-rw-r--r--node_modules/vuepress/lib/default-theme/search.svg1
-rw-r--r--node_modules/vuepress/lib/default-theme/styles/arrow.styl22
-rw-r--r--node_modules/vuepress/lib/default-theme/styles/code.styl129
-rw-r--r--node_modules/vuepress/lib/default-theme/styles/config.styl22
-rw-r--r--node_modules/vuepress/lib/default-theme/styles/custom-blocks.styl28
-rw-r--r--node_modules/vuepress/lib/default-theme/styles/mobile.styl37
-rw-r--r--node_modules/vuepress/lib/default-theme/styles/nprogress.styl48
-rw-r--r--node_modules/vuepress/lib/default-theme/styles/theme.styl190
-rw-r--r--node_modules/vuepress/lib/default-theme/styles/toc.styl3
-rw-r--r--node_modules/vuepress/lib/default-theme/styles/wrapper.styl9
-rw-r--r--node_modules/vuepress/lib/default-theme/util.js216
-rw-r--r--node_modules/vuepress/lib/dev.js149
-rw-r--r--node_modules/vuepress/lib/eject.js16
-rw-r--r--node_modules/vuepress/lib/index.js4
-rw-r--r--node_modules/vuepress/lib/markdown/component.js81
-rw-r--r--node_modules/vuepress/lib/markdown/containers.js28
-rw-r--r--node_modules/vuepress/lib/markdown/highlight.js47
-rw-r--r--node_modules/vuepress/lib/markdown/highlightLines.js49
-rw-r--r--node_modules/vuepress/lib/markdown/hoist.js14
-rw-r--r--node_modules/vuepress/lib/markdown/index.js78
-rw-r--r--node_modules/vuepress/lib/markdown/lineNumbers.js26
-rw-r--r--node_modules/vuepress/lib/markdown/link.js91
-rw-r--r--node_modules/vuepress/lib/markdown/preWrapper.js19
-rw-r--r--node_modules/vuepress/lib/markdown/slugify.js22
-rw-r--r--node_modules/vuepress/lib/markdown/snippet.js43
-rw-r--r--node_modules/vuepress/lib/prepare/codegen.js74
-rw-r--r--node_modules/vuepress/lib/prepare/index.js51
-rw-r--r--node_modules/vuepress/lib/prepare/loadConfig.js56
-rw-r--r--node_modules/vuepress/lib/prepare/resolveOptions.js194
-rw-r--r--node_modules/vuepress/lib/prepare/util.js80
-rw-r--r--node_modules/vuepress/lib/service-worker/skip-waiting.js12
-rw-r--r--node_modules/vuepress/lib/util/index.js83
-rw-r--r--node_modules/vuepress/lib/util/logger.js47
-rw-r--r--node_modules/vuepress/lib/util/parseHeaders.js56
-rw-r--r--node_modules/vuepress/lib/util/shared.js7
-rw-r--r--node_modules/vuepress/lib/webpack/ClientPlugin.js87
-rw-r--r--node_modules/vuepress/lib/webpack/DevLogPlugin.js38
-rw-r--r--node_modules/vuepress/lib/webpack/HeadPlugin.js22
-rw-r--r--node_modules/vuepress/lib/webpack/createBaseConfig.js315
-rw-r--r--node_modules/vuepress/lib/webpack/createClientConfig.js69
-rw-r--r--node_modules/vuepress/lib/webpack/createServerConfig.js58
-rw-r--r--node_modules/vuepress/lib/webpack/markdownLoader.js101
-rw-r--r--node_modules/vuepress/lib/webpack/noopModule.js1
82 files changed, 6268 insertions, 0 deletions
diff --git a/node_modules/vuepress/lib/app/.temp/enhanceApp.js b/node_modules/vuepress/lib/app/.temp/enhanceApp.js
new file mode 100644
index 00000000..16a79b36
--- /dev/null
+++ b/node_modules/vuepress/lib/app/.temp/enhanceApp.js
@@ -0,0 +1 @@
+export { default } from "/Users/ruki/projects/personal/xmake-docs/src/.vuepress/enhanceApp.js" \ No newline at end of file
diff --git a/node_modules/vuepress/lib/app/.temp/override.styl b/node_modules/vuepress/lib/app/.temp/override.styl
new file mode 100644
index 00000000..c7969f18
--- /dev/null
+++ b/node_modules/vuepress/lib/app/.temp/override.styl
@@ -0,0 +1 @@
+@import("/Users/ruki/projects/personal/xmake-docs/src/.vuepress/override.styl") \ No newline at end of file
diff --git a/node_modules/vuepress/lib/app/.temp/routes.js b/node_modules/vuepress/lib/app/.temp/routes.js
new file mode 100644
index 00000000..625e7fb6
--- /dev/null
+++ b/node_modules/vuepress/lib/app/.temp/routes.js
@@ -0,0 +1,178 @@
+import Vue from 'vue'
+
+import ThemeLayout from '@themeLayout'
+import ThemeNotFound from '@themeNotFound'
+import { injectMixins } from '@app/util'
+import rootMixins from '@app/root-mixins'
+
+injectMixins(ThemeLayout, rootMixins)
+injectMixins(ThemeNotFound, rootMixins)
+
+export const routes = [
+ {
+ name: "v-ddf4be195b958",
+ path: "/",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/README.md").then(comp => {
+ Vue.component("v-ddf4be195b958", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ path: "/index.html",
+ redirect: "/"
+ },
+ {
+ name: "v-8644851cf91dd",
+ path: "/api/introduction.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/api/introduction.md").then(comp => {
+ Vue.component("v-8644851cf91dd", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-b6ee77db64501",
+ path: "/guide/faq.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/guide/faq.md").then(comp => {
+ Vue.component("v-b6ee77db64501", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-fcba2a8896d43",
+ path: "/guide/getting-started.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/guide/getting-started.md").then(comp => {
+ Vue.component("v-fcba2a8896d43", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-cda17500cdb0c",
+ path: "/guide/introduction.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/guide/introduction.md").then(comp => {
+ Vue.component("v-cda17500cdb0c", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-745d22bfe3ef4",
+ path: "/guide/sponsors.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/guide/sponsors.md").then(comp => {
+ Vue.component("v-745d22bfe3ef4", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-360e42fea8e33",
+ path: "/plugin/introduction.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/plugin/introduction.md").then(comp => {
+ Vue.component("v-360e42fea8e33", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-1856b116362c7",
+ path: "/zh/",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/zh/README.md").then(comp => {
+ Vue.component("v-1856b116362c7", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ path: "/zh/index.html",
+ redirect: "/zh/"
+ },
+ {
+ name: "v-6812df0250aa3",
+ path: "/zh/api/introduction.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/zh/api/introduction.md").then(comp => {
+ Vue.component("v-6812df0250aa3", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-d3636509f8935",
+ path: "/zh/guide/faq.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/zh/guide/faq.md").then(comp => {
+ Vue.component("v-d3636509f8935", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-53a48e3593d7c",
+ path: "/zh/guide/getting-started.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/zh/guide/getting-started.md").then(comp => {
+ Vue.component("v-53a48e3593d7c", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-cd45bc6f8fdb",
+ path: "/zh/guide/introduction.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/zh/guide/introduction.md").then(comp => {
+ Vue.component("v-cd45bc6f8fdb", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-bef402580c1cc",
+ path: "/zh/guide/sponsors.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/zh/guide/sponsors.md").then(comp => {
+ Vue.component("v-bef402580c1cc", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ name: "v-faf113f1b77ae",
+ path: "/zh/plugin/introduction.html",
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import("/Users/ruki/projects/personal/xmake-docs/src/zh/plugin/introduction.md").then(comp => {
+ Vue.component("v-faf113f1b77ae", comp.default)
+ next()
+ })
+ }
+ },
+ {
+ path: '*',
+ component: ThemeNotFound
+ }
+] \ No newline at end of file
diff --git a/node_modules/vuepress/lib/app/.temp/siteData.js b/node_modules/vuepress/lib/app/.temp/siteData.js
new file mode 100644
index 00000000..9af62f7a
--- /dev/null
+++ b/node_modules/vuepress/lib/app/.temp/siteData.js
@@ -0,0 +1,634 @@
+export const siteData = {
+ "title": "",
+ "description": "",
+ "base": "/",
+ "pages": [
+ {
+ "key": "v-ddf4be195b958",
+ "path": "/",
+ "lastUpdated": null,
+ "title": "Home",
+ "headers": [
+ {
+ "level": 2,
+ "title": "Simple description",
+ "slug": "simple-description"
+ },
+ {
+ "level": 2,
+ "title": "Package dependences",
+ "slug": "package-dependences"
+ },
+ {
+ "level": 2,
+ "title": "Build project",
+ "slug": "build-project"
+ },
+ {
+ "level": 2,
+ "title": "Run target",
+ "slug": "run-target"
+ },
+ {
+ "level": 2,
+ "title": "Debug target",
+ "slug": "debug-target"
+ },
+ {
+ "level": 2,
+ "title": "Configure platform",
+ "slug": "configure-platform"
+ },
+ {
+ "level": 2,
+ "title": "Menu configuration",
+ "slug": "menu-configuration"
+ },
+ {
+ "level": 2,
+ "title": "Package management",
+ "slug": "package-management"
+ },
+ {
+ "level": 2,
+ "title": "Supported platforms",
+ "slug": "supported-platforms"
+ },
+ {
+ "level": 2,
+ "title": "Supported Languages",
+ "slug": "supported-languages"
+ },
+ {
+ "level": 2,
+ "title": "Supported Projects",
+ "slug": "supported-projects"
+ },
+ {
+ "level": 2,
+ "title": "Builtin Plugins",
+ "slug": "builtin-plugins"
+ },
+ {
+ "level": 2,
+ "title": "More Plugins",
+ "slug": "more-plugins"
+ },
+ {
+ "level": 2,
+ "title": "IDE/Editor Integration",
+ "slug": "ide-editor-integration"
+ },
+ {
+ "level": 2,
+ "title": "More Examples",
+ "slug": "more-examples"
+ },
+ {
+ "level": 2,
+ "title": "Project Examples",
+ "slug": "project-examples"
+ },
+ {
+ "level": 2,
+ "title": "Example Video",
+ "slug": "example-video"
+ },
+ {
+ "level": 2,
+ "title": "Contacts",
+ "slug": "contacts"
+ }
+ ],
+ "frontmatter": {
+ "home": true,
+ "heroImage": "/hero.png",
+ "actionText": "Get Started →",
+ "actionLink": "/guide/getting-started",
+ "features": [
+ {
+ "title": "Why",
+ "details": "Making development and building easier, so that any developer can quickly pick it up and enjoy the productivity boost when developing and building project."
+ },
+ {
+ "title": "Powerful",
+ "details": "Provides lots of features (e.g. package, install, plugin, macro, action, option, task and etc)."
+ },
+ {
+ "title": "Cross-platform",
+ "details": "Supports windows, macOS, linux, android, ios."
+ }
+ ],
+ "footer": "Apache-2.0 Licensed | Copyright © 2015-present tboox.org"
+ }
+ },
+ {
+ "key": "v-8644851cf91dd",
+ "path": "/api/introduction.html",
+ "lastUpdated": null,
+ "title": "Title1",
+ "headers": [
+ {
+ "level": 2,
+ "title": "Title2",
+ "slug": "title2"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3-2"
+ },
+ {
+ "level": 2,
+ "title": "Title2",
+ "slug": "title2-2"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3-3"
+ }
+ ]
+ },
+ {
+ "key": "v-b6ee77db64501",
+ "path": "/guide/faq.html",
+ "lastUpdated": null,
+ "title": "FAQ",
+ "headers": [
+ {
+ "level": 2,
+ "title": "How to get verbose command-line arguments info?",
+ "slug": "how-to-get-verbose-command-line-arguments-info"
+ },
+ {
+ "level": 2,
+ "title": "How to suppress all output info?",
+ "slug": "how-to-suppress-all-output-info"
+ },
+ {
+ "level": 2,
+ "title": "How to do if xmake fails?",
+ "slug": "how-to-do-if-xmake-fails"
+ },
+ {
+ "level": 2,
+ "title": "How to see verbose compiling warnings?",
+ "slug": "how-to-see-verbose-compiling-warnings"
+ },
+ {
+ "level": 2,
+ "title": "How to scan source code and generate xmake.lua automaticlly",
+ "slug": "how-to-scan-source-code-and-generate-xmake-lua-automaticlly"
+ }
+ ]
+ },
+ {
+ "key": "v-fcba2a8896d43",
+ "path": "/guide/getting-started.html",
+ "lastUpdated": null,
+ "title": "Getting Started",
+ "headers": [
+ {
+ "level": 2,
+ "title": "Installation",
+ "slug": "installation"
+ },
+ {
+ "level": 2,
+ "title": "Quick Start",
+ "slug": "quick-start"
+ },
+ {
+ "level": 2,
+ "title": "Project Examples",
+ "slug": "project-examples"
+ },
+ {
+ "level": 2,
+ "title": "Configuration",
+ "slug": "configuration"
+ },
+ {
+ "level": 2,
+ "title": "Dependency Package Management",
+ "slug": "dependency-package-management"
+ }
+ ]
+ },
+ {
+ "key": "v-cda17500cdb0c",
+ "path": "/guide/introduction.html",
+ "lastUpdated": null,
+ "title": "Introduction",
+ "headers": [
+ {
+ "level": 2,
+ "title": "Introduction",
+ "slug": "introduction"
+ }
+ ]
+ },
+ {
+ "key": "v-745d22bfe3ef4",
+ "path": "/guide/sponsors.html",
+ "lastUpdated": null,
+ "title": "Sponsors"
+ },
+ {
+ "key": "v-360e42fea8e33",
+ "path": "/plugin/introduction.html",
+ "lastUpdated": null,
+ "title": "Title1",
+ "headers": [
+ {
+ "level": 2,
+ "title": "Title2",
+ "slug": "title2"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3-2"
+ },
+ {
+ "level": 2,
+ "title": "Title2",
+ "slug": "title2-2"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3-3"
+ }
+ ]
+ },
+ {
+ "key": "v-1856b116362c7",
+ "path": "/zh/",
+ "lastUpdated": null,
+ "title": "Home",
+ "headers": [
+ {
+ "level": 2,
+ "title": "简单的工程描述",
+ "slug": "简单的工程描述"
+ },
+ {
+ "level": 2,
+ "title": "包依赖描述",
+ "slug": "包依赖描述"
+ },
+ {
+ "level": 2,
+ "title": "构建工程",
+ "slug": "构建工程"
+ },
+ {
+ "level": 2,
+ "title": "运行目标",
+ "slug": "运行目标"
+ },
+ {
+ "level": 2,
+ "title": "调试程序",
+ "slug": "调试程序"
+ },
+ {
+ "level": 2,
+ "title": "配置平台",
+ "slug": "配置平台"
+ },
+ {
+ "level": 2,
+ "title": "图形化菜单配置",
+ "slug": "图形化菜单配置"
+ },
+ {
+ "level": 2,
+ "title": "包依赖管理",
+ "slug": "包依赖管理"
+ },
+ {
+ "level": 2,
+ "title": "支持平台",
+ "slug": "支持平台"
+ },
+ {
+ "level": 2,
+ "title": "支持语言",
+ "slug": "支持语言"
+ },
+ {
+ "level": 2,
+ "title": "工程类型",
+ "slug": "工程类型"
+ },
+ {
+ "level": 2,
+ "title": "内置插件",
+ "slug": "内置插件"
+ },
+ {
+ "level": 2,
+ "title": "更多插件",
+ "slug": "更多插件"
+ },
+ {
+ "level": 2,
+ "title": "IDE和编辑器插件",
+ "slug": "ide和编辑器插件"
+ },
+ {
+ "level": 2,
+ "title": "更多例子",
+ "slug": "更多例子"
+ },
+ {
+ "level": 2,
+ "title": "项目例子",
+ "slug": "项目例子"
+ },
+ {
+ "level": 2,
+ "title": "演示视频",
+ "slug": "演示视频"
+ },
+ {
+ "level": 2,
+ "title": "联系方式",
+ "slug": "联系方式"
+ }
+ ],
+ "frontmatter": {
+ "home": true,
+ "heroImage": "/hero.png",
+ "actionText": "快速上手 →",
+ "actionLink": "/zh/guide/getting-started",
+ "features": [
+ {
+ "title": "为什么使用",
+ "details": "让开发者更加关注于项目本身开发,简化项目的描述和构建,并且提供平台无关性,使得一次编写,随处构建"
+ },
+ {
+ "title": "强大",
+ "details": "提供大量的实用特性(例如:插件扩展、脚本宏记录、批量打包、自动文档生成等常用插件)"
+ },
+ {
+ "title": "跨平台",
+ "details": "支持windows, macOS, linux, android, ios"
+ }
+ ],
+ "footer": "Apache-2.0 Licensed | Copyright © 2015-present tboox.org"
+ }
+ },
+ {
+ "key": "v-6812df0250aa3",
+ "path": "/zh/api/introduction.html",
+ "lastUpdated": null,
+ "title": "Title1",
+ "headers": [
+ {
+ "level": 2,
+ "title": "Title2",
+ "slug": "title2"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3-2"
+ },
+ {
+ "level": 2,
+ "title": "Title2",
+ "slug": "title2-2"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3-3"
+ }
+ ]
+ },
+ {
+ "key": "v-d3636509f8935",
+ "path": "/zh/guide/faq.html",
+ "lastUpdated": null
+ },
+ {
+ "key": "v-53a48e3593d7c",
+ "path": "/zh/guide/getting-started.html",
+ "lastUpdated": null,
+ "title": "快速开始",
+ "headers": [
+ {
+ "level": 2,
+ "title": "编译",
+ "slug": "编译"
+ },
+ {
+ "level": 2,
+ "title": "例子",
+ "slug": "例子"
+ }
+ ]
+ },
+ {
+ "key": "v-cd45bc6f8fdb",
+ "path": "/zh/guide/introduction.html",
+ "lastUpdated": null,
+ "title": "简介",
+ "headers": [
+ {
+ "level": 2,
+ "title": "特性",
+ "slug": "特性"
+ },
+ {
+ "level": 2,
+ "title": "项目例子",
+ "slug": "项目例子"
+ },
+ {
+ "level": 2,
+ "title": "联系方式",
+ "slug": "联系方式"
+ }
+ ]
+ },
+ {
+ "key": "v-bef402580c1cc",
+ "path": "/zh/guide/sponsors.html",
+ "lastUpdated": null
+ },
+ {
+ "key": "v-faf113f1b77ae",
+ "path": "/zh/plugin/introduction.html",
+ "lastUpdated": null,
+ "title": "Title1",
+ "headers": [
+ {
+ "level": 2,
+ "title": "Title2",
+ "slug": "title2"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3-2"
+ },
+ {
+ "level": 2,
+ "title": "Title2",
+ "slug": "title2-2"
+ },
+ {
+ "level": 3,
+ "title": "Title3",
+ "slug": "title3-3"
+ }
+ ]
+ }
+ ],
+ "themeConfig": {
+ "repo": "tboox/xmake",
+ "docsRepo": "tboox/xmake-docs",
+ "docsDir": "src",
+ "editLinks": true,
+ "sidebarDepth": 2,
+ "locales": {
+ "/": {
+ "label": "English",
+ "selectText": "Languages",
+ "editLinkText": "Edit this page on GitHub",
+ "lastUpdated": "Last Updated",
+ "nav": [
+ {
+ "text": "Guide",
+ "link": "/guide/introduction"
+ },
+ {
+ "text": "Plugin",
+ "link": "/plugin/introduction"
+ },
+ {
+ "text": "API",
+ "link": "/api/introduction"
+ },
+ {
+ "text": "Articles",
+ "link": "http://www.tboox.org/category/#xmake"
+ },
+ {
+ "text": "Feedback",
+ "link": "https://github.com/tboox/xmake/issues"
+ },
+ {
+ "text": "Community",
+ "link": "https://www.reddit.com/r/tboox/"
+ },
+ {
+ "text": "Donation",
+ "link": "http://tboox.org/cn/donation/"
+ }
+ ],
+ "sidebar": {
+ "/guide/": [
+ "introduction",
+ "getting-started",
+ "faq",
+ "sponsors"
+ ],
+ "/plugin/": [
+ "introduction"
+ ],
+ "/api/": [
+ "introduction"
+ ]
+ }
+ },
+ "/zh/": {
+ "label": "简体中文",
+ "selectText": "选择语言",
+ "editLinkText": "在 GitHub 上编辑此页",
+ "lastUpdated": "上次更新",
+ "nav": [
+ {
+ "text": "指南",
+ "link": "/zh/guide/introduction"
+ },
+ {
+ "text": "插件",
+ "link": "/zh/plugin/introduction"
+ },
+ {
+ "text": "接口",
+ "link": "/zh/api/introduction"
+ },
+ {
+ "text": "文章",
+ "link": "http://www.tboox.org/cn/category/#xmake"
+ },
+ {
+ "text": "反馈",
+ "link": "https://github.com/tboox/xmake/issues"
+ },
+ {
+ "text": "社区",
+ "link": "https://www.reddit.com/r/tboox/"
+ },
+ {
+ "text": "捐助",
+ "link": "http://tboox.org/cn/donation/"
+ }
+ ],
+ "sidebar": {
+ "/zh/guide/": [
+ "introduction",
+ "getting-started",
+ "faq",
+ "sponsors"
+ ],
+ "/zh/plugin/": [
+ "introduction"
+ ],
+ "/zh/api/": [
+ "introduction"
+ ]
+ }
+ }
+ }
+ },
+ "locales": {
+ "/": {
+ "lang": "en-US",
+ "title": "xmake",
+ "description": "A cross-platform build utility based on Lua"
+ },
+ "/zh/": {
+ "lang": "zh-CN",
+ "title": "xmake",
+ "description": "一个基于Lua的轻量级跨平台自动构建工具"
+ }
+ }
+} \ No newline at end of file
diff --git a/node_modules/vuepress/lib/app/.temp/style.styl b/node_modules/vuepress/lib/app/.temp/style.styl
new file mode 100644
index 00000000..b3deab99
--- /dev/null
+++ b/node_modules/vuepress/lib/app/.temp/style.styl
@@ -0,0 +1 @@
+@import("/Users/ruki/projects/personal/xmake-docs/src/.vuepress/style.styl") \ No newline at end of file
diff --git a/node_modules/vuepress/lib/app/.temp/themeEnhanceApp.js b/node_modules/vuepress/lib/app/.temp/themeEnhanceApp.js
new file mode 100644
index 00000000..03c095d5
--- /dev/null
+++ b/node_modules/vuepress/lib/app/.temp/themeEnhanceApp.js
@@ -0,0 +1 @@
+export default function () {} \ No newline at end of file
diff --git a/node_modules/vuepress/lib/app/SWUpdateEvent.js b/node_modules/vuepress/lib/app/SWUpdateEvent.js
new file mode 100644
index 00000000..fe6ab31c
--- /dev/null
+++ b/node_modules/vuepress/lib/app/SWUpdateEvent.js
@@ -0,0 +1,43 @@
+export default class SWUpdateEvent {
+ constructor (registration) {
+ Object.defineProperty(this, 'registration', {
+ value: registration,
+ configurable: true,
+ writable: true
+ })
+ }
+
+ /**
+ * Check if the new service worker exists or not.
+ */
+ update () {
+ return this.registration.update()
+ }
+
+ /**
+ * Activate new service worker to work 'location.reload()' with new data.
+ */
+ skipWaiting () {
+ const worker = this.registration.waiting
+ if (!worker) {
+ return Promise.resolve()
+ }
+
+ console.log('[vuepress:sw] Doing worker.skipWaiting().')
+ return new Promise((resolve, reject) => {
+ const channel = new MessageChannel()
+
+ channel.port1.onmessage = (event) => {
+ console.log('[vuepress:sw] Done worker.skipWaiting().')
+ if (event.data.error) {
+ reject(event.data.error)
+ } else {
+ resolve(event.data)
+ }
+ }
+
+ worker.postMessage({ type: 'skip-waiting' }, [channel.port2])
+ })
+ }
+}
+
diff --git a/node_modules/vuepress/lib/app/app.js b/node_modules/vuepress/lib/app/app.js
new file mode 100644
index 00000000..511abbd4
--- /dev/null
+++ b/node_modules/vuepress/lib/app/app.js
@@ -0,0 +1,102 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+import dataMixin from './dataMixin'
+import store from './store'
+import { routes } from '@temp/routes'
+import { siteData } from '@temp/siteData'
+import enhanceApp from '@temp/enhanceApp'
+import themeEnhanceApp from '@temp/themeEnhanceApp'
+
+// generated from user config
+import('@temp/style.styl')
+
+// built-in components
+import Content from './components/Content'
+import OutboundLink from './components/OutboundLink.vue'
+import ClientOnly from './components/ClientOnly'
+
+// suggest dev server restart on base change
+if (module.hot) {
+ const prevBase = siteData.base
+ module.hot.accept('./.temp/siteData', () => {
+ if (siteData.base !== prevBase) {
+ window.alert(
+ `[vuepress] Site base has changed. ` +
+ `Please restart dev server to ensure correct asset paths.`
+ )
+ }
+ })
+}
+
+Vue.config.productionTip = false
+Vue.use(Router)
+// mixin for exposing $site and $page
+Vue.mixin(dataMixin(siteData))
+// component for rendering markdown content and setting title etc.
+Vue.component('Content', Content)
+Vue.component('OutboundLink', OutboundLink)
+Vue.component('Badge', () => import('./components/Badge.vue'))
+// component for client-only content
+Vue.component('ClientOnly', ClientOnly)
+
+// global helper for adding base path to absolute urls
+Vue.prototype.$withBase = function (path) {
+ const base = this.$site.base
+ if (path.charAt(0) === '/') {
+ return base + path.slice(1)
+ } else {
+ return path
+ }
+}
+
+export function createApp () {
+ const router = new Router({
+ base: siteData.base,
+ mode: 'history',
+ fallback: false,
+ routes,
+ scrollBehavior: (to, from, saved) => {
+ if (saved) {
+ return saved
+ } else if (to.hash) {
+ if (store.disableScrollBehavior) {
+ return false
+ }
+ return {
+ selector: to.hash
+ }
+ } else {
+ return { x: 0, y: 0 }
+ }
+ }
+ })
+
+ // redirect /foo to /foo/
+ router.beforeEach((to, from, next) => {
+ if (!/(\/|\.html)$/.test(to.path)) {
+ next(Object.assign({}, to, {
+ path: to.path + '/'
+ }))
+ } else {
+ next()
+ }
+ })
+
+ const options = {}
+
+ themeEnhanceApp({ Vue, options, router, siteData })
+ enhanceApp({ Vue, options, router, siteData })
+
+ const app = new Vue(
+ Object.assign(options, {
+ router,
+ render (h) {
+ return h('div', { attrs: { id: 'app' }}, [
+ h('router-view', { ref: 'layout' })
+ ])
+ }
+ })
+ )
+
+ return { app, router }
+}
diff --git a/node_modules/vuepress/lib/app/clientEntry.js b/node_modules/vuepress/lib/app/clientEntry.js
new file mode 100644
index 00000000..dc86314a
--- /dev/null
+++ b/node_modules/vuepress/lib/app/clientEntry.js
@@ -0,0 +1,74 @@
+/* global BASE_URL, GA_ID, ga, SW_ENABLED, VUEPRESS_VERSION, LAST_COMMIT_HASH*/
+
+import { createApp } from './app'
+import SWUpdateEvent from './SWUpdateEvent'
+import { register } from 'register-service-worker'
+
+const { app, router } = createApp()
+
+window.__VUEPRESS_VERSION__ = {
+ version: VUEPRESS_VERSION,
+ hash: LAST_COMMIT_HASH
+}
+
+// Google analytics integration
+if (process.env.NODE_ENV === 'production' && GA_ID) {
+ (function (i, s, o, g, r, a, m) {
+ i['GoogleAnalyticsObject'] = r
+ i[r] = i[r] || function () {
+ (i[r].q = i[r].q || []).push(arguments)
+ }
+ i[r].l = 1 * new Date()
+ a = s.createElement(o)
+ m = s.getElementsByTagName(o)[0]
+ a.async = 1
+ a.src = g
+ m.parentNode.insertBefore(a, m)
+ })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga')
+
+ ga('create', GA_ID, 'auto')
+ ga('send', 'pageview')
+
+ router.afterEach(function (to) {
+ ga('set', 'page', app.$withBase(to.fullPath))
+ ga('send', 'pageview')
+ })
+}
+
+router.onReady(() => {
+ app.$mount('#app')
+
+ // Register service worker
+ if (process.env.NODE_ENV === 'production' &&
+ SW_ENABLED &&
+ window.location.protocol === 'https:') {
+ register(`${BASE_URL}service-worker.js`, {
+ ready () {
+ console.log('[vuepress:sw] Service worker is active.')
+ app.$refs.layout.$emit('sw-ready')
+ },
+ cached (registration) {
+ console.log('[vuepress:sw] Content has been cached for offline use.')
+ app.$refs.layout.$emit('sw-cached', new SWUpdateEvent(registration))
+ },
+ updated (registration) {
+ console.log('[vuepress:sw] Content updated.')
+ app.$refs.layout.$emit('sw-updated', new SWUpdateEvent(registration))
+ },
+ offline () {
+ console.log('[vuepress:sw] No internet connection found. App is running in offline mode.')
+ app.$refs.layout.$emit('sw-offline')
+ },
+ error (err) {
+ console.error('[vuepress:sw] Error during service worker registration:', err)
+ app.$refs.layout.$emit('sw-error', err)
+ if (GA_ID) {
+ ga('send', 'exception', {
+ exDescription: err.message,
+ exFatal: false
+ })
+ }
+ }
+ })
+ }
+})
diff --git a/node_modules/vuepress/lib/app/components/Badge.vue b/node_modules/vuepress/lib/app/components/Badge.vue
new file mode 100644
index 00000000..17e6ba6e
--- /dev/null
+++ b/node_modules/vuepress/lib/app/components/Badge.vue
@@ -0,0 +1,46 @@
+<script>
+export default {
+ functional: true,
+ props: {
+ type: {
+ type: String,
+ default: 'tip'
+ },
+ text: String,
+ vertical: {
+ type: String,
+ default: 'top'
+ }
+ },
+ render (h, { props, slots }) {
+ return h('span', {
+ class: ['badge', props.type, props.vertical]
+ }, props.text || slots().default)
+ }
+}
+</script>
+
+<style lang="stylus" scoped>
+@import '../../default-theme/styles/config.styl'
+
+.badge
+ display inline-block
+ font-size 14px
+ height 18px
+ line-height 18px
+ border-radius 3px
+ padding 0 6px
+ color white
+ margin-right 5px
+ background-color #42b983
+ &.middle
+ vertical-align middle
+ &.top
+ vertical-align top
+ &.tip, &.green
+ background-color #42b983
+ &.error
+ background-color #DA5961 //#f66
+ &.warning, &.warn, &.yellow
+ background-color darken(#ffe564, 35%)
+</style>
diff --git a/node_modules/vuepress/lib/app/components/ClientOnly.js b/node_modules/vuepress/lib/app/components/ClientOnly.js
new file mode 100644
index 00000000..c786d1af
--- /dev/null
+++ b/node_modules/vuepress/lib/app/components/ClientOnly.js
@@ -0,0 +1,12 @@
+export default {
+ functional: true,
+ render (h, { parent, children }) {
+ if (parent._isMounted) {
+ return children
+ } else {
+ parent.$once('hook:mounted', () => {
+ parent.$forceUpdate()
+ })
+ }
+ }
+}
diff --git a/node_modules/vuepress/lib/app/components/Content.js b/node_modules/vuepress/lib/app/components/Content.js
new file mode 100644
index 00000000..46628195
--- /dev/null
+++ b/node_modules/vuepress/lib/app/components/Content.js
@@ -0,0 +1,17 @@
+export default {
+ functional: true,
+
+ props: {
+ custom: {
+ type: Boolean,
+ default: true
+ }
+ },
+
+ render (h, { parent, props, data }) {
+ return h(parent.$page.key, {
+ class: [props.custom ? 'custom' : '', data.class, data.staticClass],
+ style: data.style
+ })
+ }
+}
diff --git a/node_modules/vuepress/lib/app/components/OutboundLink.vue b/node_modules/vuepress/lib/app/components/OutboundLink.vue
new file mode 100644
index 00000000..a3aa7f2d
--- /dev/null
+++ b/node_modules/vuepress/lib/app/components/OutboundLink.vue
@@ -0,0 +1,12 @@
+<template functional>
+ <svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15">
+ <path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
+ <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
+ </svg>
+</template>
+
+<style lang="stylus">
+.icon.outbound
+ color #aaa
+ display inline-block
+</style>
diff --git a/node_modules/vuepress/lib/app/dataMixin.js b/node_modules/vuepress/lib/app/dataMixin.js
new file mode 100644
index 00000000..fd003d92
--- /dev/null
+++ b/node_modules/vuepress/lib/app/dataMixin.js
@@ -0,0 +1,90 @@
+import Vue from 'vue'
+import { findPageForPath } from './util'
+
+export default function dataMixin (siteData) {
+ prepare(siteData)
+ const store = new Vue({
+ data: { siteData }
+ })
+
+ if (module.hot) {
+ module.hot.accept('./.temp/siteData', () => {
+ prepare(siteData)
+ store.siteData = siteData
+ })
+ }
+
+ return {
+ computed: {
+ $site () {
+ return store.siteData
+ },
+ $localeConfig () {
+ const { locales = {}} = this.$site
+ let targetLang
+ let defaultLang
+ for (const path in locales) {
+ if (path === '/') {
+ defaultLang = locales[path]
+ } else if (this.$page.path.indexOf(path) === 0) {
+ targetLang = locales[path]
+ }
+ }
+ return targetLang || defaultLang || {}
+ },
+ $siteTitle () {
+ return this.$localeConfig.title || this.$site.title || ''
+ },
+ $title () {
+ const page = this.$page
+ const siteTitle = this.$siteTitle
+ const selfTitle = page.frontmatter.home ? null : (
+ page.frontmatter.title || // explicit title
+ page.title // inferred title
+ )
+ return siteTitle
+ ? selfTitle
+ ? (selfTitle + ' | ' + siteTitle)
+ : siteTitle
+ : selfTitle || 'VuePress'
+ },
+ $description () {
+ // #565 hoist description from meta
+ if (this.$page.frontmatter.meta) {
+ const descriptionMeta = this.$page.frontmatter.meta.filter(item => item.name === 'description')[0]
+ if (descriptionMeta) return descriptionMeta.content
+ }
+ return this.$page.frontmatter.description || this.$localeConfig.description || this.$site.description || ''
+ },
+ $lang () {
+ return this.$page.frontmatter.lang || this.$localeConfig.lang || 'en-US'
+ },
+ $localePath () {
+ return this.$localeConfig.path || '/'
+ },
+ $themeLocaleConfig () {
+ return (this.$site.themeConfig.locales || {})[this.$localePath] || {}
+ },
+ $page () {
+ return findPageForPath(
+ this.$site.pages,
+ this.$route.path
+ )
+ }
+ }
+ }
+}
+
+function prepare (siteData) {
+ siteData.pages.forEach(page => {
+ if (!page.frontmatter) {
+ page.frontmatter = {}
+ }
+ })
+ if (siteData.locales) {
+ Object.keys(siteData.locales).forEach(path => {
+ siteData.locales[path].path = path
+ })
+ }
+ Object.freeze(siteData)
+}
diff --git a/node_modules/vuepress/lib/app/index.dev.html b/node_modules/vuepress/lib/app/index.dev.html
new file mode 100644
index 00000000..06f743c5
--- /dev/null
+++ b/node_modules/vuepress/lib/app/index.dev.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width,initial-scale=1">
+ <title></title>
+ </head>
+ <body>
+ <div id="app"></div>
+ </body>
+</html>
diff --git a/node_modules/vuepress/lib/app/index.ssr.html b/node_modules/vuepress/lib/app/index.ssr.html
new file mode 100644
index 00000000..32d310a9
--- /dev/null
+++ b/node_modules/vuepress/lib/app/index.ssr.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="{{ lang }}">
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width,initial-scale=1">
+ <title>{{ title }}</title>
+ <meta name="description" content="{{ description }}">
+ {{{ userHeadTags }}}
+ {{{ pageMeta }}}
+ {{{ renderResourceHints() }}}
+ {{{ renderStyles() }}}
+ </head>
+ <body>
+ <!--vue-ssr-outlet-->
+ {{{ renderScripts() }}}
+ </body>
+</html>
diff --git a/node_modules/vuepress/lib/app/root-mixins/activeHeaderLinks.js b/node_modules/vuepress/lib/app/root-mixins/activeHeaderLinks.js
new file mode 100644
index 00000000..6cad69d5
--- /dev/null
+++ b/node_modules/vuepress/lib/app/root-mixins/activeHeaderLinks.js
@@ -0,0 +1,47 @@
+import store from '@app/store'
+import throttle from 'lodash.throttle'
+
+export default {
+ mounted () {
+ window.addEventListener('scroll', this.onScroll)
+ },
+ methods: {
+ onScroll: throttle(function () {
+ this.setActiveHash()
+ }, 300),
+ setActiveHash () {
+ const sidebarLinks = [].slice.call(document.querySelectorAll('.sidebar-link'))
+ const anchors = [].slice.call(document.querySelectorAll('.header-anchor'))
+ .filter(anchor => sidebarLinks.some(sidebarLink => sidebarLink.hash === anchor.hash))
+
+ const scrollTop = Math.max(
+ window.pageYOffset,
+ document.documentElement.scrollTop,
+ document.body.scrollTop
+ )
+
+ for (let i = 0; i < anchors.length; i++) {
+ const anchor = anchors[i]
+ const nextAnchor = anchors[i + 1]
+
+ const isActive = i === 0 && scrollTop === 0 ||
+ (scrollTop >= anchor.parentElement.offsetTop + 10 &&
+ (!nextAnchor || scrollTop < nextAnchor.parentElement.offsetTop - 10))
+
+ if (isActive && decodeURIComponent(this.$route.hash) !== decodeURIComponent(anchor.hash)) {
+ store.disableScrollBehavior = true
+ this.$router.replace(decodeURIComponent(anchor.hash), () => {
+ // execute after scrollBehavior handler.
+ this.$nextTick(() => {
+ store.disableScrollBehavior = false
+ })
+ })
+ return
+ }
+ }
+ }
+ },
+ beforeDestroy () {
+ window.removeEventListener('scroll', this.onScroll)
+ }
+}
diff --git a/node_modules/vuepress/lib/app/root-mixins/index.js b/node_modules/vuepress/lib/app/root-mixins/index.js
new file mode 100644
index 00000000..fd966f39
--- /dev/null
+++ b/node_modules/vuepress/lib/app/root-mixins/index.js
@@ -0,0 +1,7 @@
+import updateMeta from './updateMeta'
+import activeHeaderLinks from '@activeHeaderLinks'
+
+export default [
+ updateMeta, // required
+ activeHeaderLinks // optional
+]
diff --git a/node_modules/vuepress/lib/app/root-mixins/updateMeta.js b/node_modules/vuepress/lib/app/root-mixins/updateMeta.js
new file mode 100644
index 00000000..ff2703ac
--- /dev/null
+++ b/node_modules/vuepress/lib/app/root-mixins/updateMeta.js
@@ -0,0 +1,59 @@
+export default {
+ created () {
+ if (this.$ssrContext) {
+ this.$ssrContext.title = this.$title
+ this.$ssrContext.lang = this.$lang
+ this.$ssrContext.description = this.$page.description || this.$description
+ }
+ },
+
+ mounted () {
+ // update title / meta tags
+ this.currentMetaTags = new Set()
+
+ const updateMeta = () => {
+ document.title = this.$title
+ document.documentElement.lang = this.$lang
+ const userMeta = this.$page.frontmatter.meta || []
+ const meta = userMeta.slice(0)
+ const useGlobalDescription = userMeta.filter(m => m.name === 'description').length === 0
+
+ // #665 Avoid duplicate description meta at runtime.
+ if (useGlobalDescription) {
+ meta.push({ name: 'description', content: this.$description })
+ }
+
+ // Including description meta coming from SSR.
+ const descriptionMetas = document.querySelectorAll('meta[name="description"]')
+ if (descriptionMetas.length) {
+ descriptionMetas.forEach(m => this.currentMetaTags.add(m))
+ }
+
+ this.currentMetaTags = new Set(updateMetaTags(meta, this.currentMetaTags))
+ }
+ this.$watch('$page', updateMeta)
+ updateMeta()
+ },
+
+ beforeDestroy () {
+ updateMetaTags(null, this.currentMetaTags)
+ }
+}
+
+function updateMetaTags (meta, current) {
+ if (current) {
+ [...current].forEach(c => {
+ document.head.removeChild(c)
+ })
+ }
+ if (meta) {
+ return meta.map(m => {
+ const tag = document.createElement('meta')
+ Object.keys(m).forEach(key => {
+ tag.setAttribute(key, m[key])
+ })
+ document.head.appendChild(tag)
+ return tag
+ })
+ }
+}
diff --git a/node_modules/vuepress/lib/app/serverEntry.js b/node_modules/vuepress/lib/app/serverEntry.js
new file mode 100644
index 00000000..715fc956
--- /dev/null
+++ b/node_modules/vuepress/lib/app/serverEntry.js
@@ -0,0 +1,14 @@
+import { createApp } from './app'
+
+export default context => new Promise((resolve, reject) => {
+ const { app, router } = createApp()
+ const { url } = context
+ const { fullPath } = router.resolve(url).route
+
+ if (fullPath !== url) {
+ return reject({ url: fullPath })
+ }
+
+ router.push(url)
+ router.onReady(() => resolve(app))
+})
diff --git a/node_modules/vuepress/lib/app/store.js b/node_modules/vuepress/lib/app/store.js
new file mode 100644
index 00000000..115fe0b9
--- /dev/null
+++ b/node_modules/vuepress/lib/app/store.js
@@ -0,0 +1,7 @@
+// It is not yet time to use Vuex to manage the global state
+// singleton object as a global store.
+const state = {
+ disableScrollBehavior: false
+}
+
+export default state
diff --git a/node_modules/vuepress/lib/app/util.js b/node_modules/vuepress/lib/app/util.js
new file mode 100644
index 00000000..c1117224
--- /dev/null
+++ b/node_modules/vuepress/lib/app/util.js
@@ -0,0 +1,19 @@
+export function injectMixins (options, mixins) {
+ if (!options.mixins) {
+ options.mixins = []
+ }
+ options.mixins.push(...mixins)
+}
+
+export function findPageForPath (pages, path) {
+ for (let i = 0; i < pages.length; i++) {
+ const page = pages[i]
+ if (page.path === path) {
+ return page
+ }
+ }
+ return {
+ path: '',
+ frontmatter: {}
+ }
+}
diff --git a/node_modules/vuepress/lib/build.js b/node_modules/vuepress/lib/build.js
new file mode 100644
index 00000000..f7efb49b
--- /dev/null
+++ b/node_modules/vuepress/lib/build.js
@@ -0,0 +1,200 @@
+module.exports = async function build (sourceDir, cliOptions = {}) {
+ process.env.NODE_ENV = 'production'
+
+ const fs = require('fs-extra')
+ const path = require('path')
+ const chalk = require('chalk')
+ const webpack = require('webpack')
+ const readline = require('readline')
+ const escape = require('escape-html')
+
+ const logger = require('./util/logger')
+ const prepare = require('./prepare')
+ const createClientConfig = require('./webpack/createClientConfig')
+ const createServerConfig = require('./webpack/createServerConfig')
+ const { createBundleRenderer } = require('vue-server-renderer')
+ const { normalizeHeadTag, applyUserWebpackConfig } = require('./util')
+
+ logger.wait('\nExtracting site metadata...')
+ const options = await prepare(sourceDir)
+ if (cliOptions.outDir) {
+ options.outDir = cliOptions.outDir
+ }
+
+ const { outDir } = options
+ if (path.resolve() === outDir) {
+ return console.error(logger.error(chalk.red('Unexpected option: outDir cannot be set to the current working directory.\n'), false))
+ }
+ await fs.remove(outDir)
+
+ let clientConfig = createClientConfig(options, cliOptions).toConfig()
+ let serverConfig = createServerConfig(options, cliOptions).toConfig()
+
+ // apply user config...
+ const userConfig = options.siteConfig.configureWebpack
+ if (userConfig) {
+ clientConfig = applyUserWebpackConfig(userConfig, clientConfig, false)
+ serverConfig = applyUserWebpackConfig(userConfig, serverConfig, true)
+ }
+
+ // compile!
+ const stats = await compile([clientConfig, serverConfig])
+
+ const serverBundle = require(path.resolve(outDir, 'manifest/server.json'))
+ const clientManifest = require(path.resolve(outDir, 'manifest/client.json'))
+
+ // remove manifests after loading them.
+ await fs.remove(path.resolve(outDir, 'manifest'))
+
+ // find and remove empty style chunk caused by
+ // https://github.com/webpack-contrib/mini-css-extract-plugin/issues/85
+ // TODO remove when it's fixed
+ await workaroundEmptyStyleChunk()
+
+ // create server renderer using built manifests
+ const renderer = createBundleRenderer(serverBundle, {
+ clientManifest,
+ runInNewContext: false,
+ inject: false,
+ shouldPrefetch: options.siteConfig.shouldPrefetch || (() => true),
+ template: await fs.readFile(path.resolve(__dirname, 'app/index.ssr.html'), 'utf-8')
+ })
+
+ // pre-render head tags from user config
+ const userHeadTags = (options.siteConfig.head || [])
+ .map(renderHeadTag)
+ .join('\n ')
+
+ // render pages
+ logger.wait('Rendering static HTML...')
+ for (const page of options.siteData.pages) {
+ await renderPage(page)
+ }
+
+ // if the user does not have a custom 404.md, generate the theme's default
+ if (!options.siteData.pages.some(p => p.path === '/404.html')) {
+ await renderPage({ path: '/404.html' })
+ }
+
+ readline.clearLine(process.stdout, 0)
+ readline.cursorTo(process.stdout, 0)
+
+ if (options.siteConfig.serviceWorker) {
+ logger.wait('\nGenerating service worker...')
+ const wbb = require('workbox-build')
+ await wbb.generateSW({
+ swDest: path.resolve(outDir, 'service-worker.js'),
+ globDirectory: outDir,
+ globPatterns: ['**\/*.{js,css,html,png,jpg,jpeg,gif,svg,woff,woff2,eot,ttf,otf}']
+ })
+ await fs.writeFile(
+ path.resolve(outDir, 'service-worker.js'),
+ await fs.readFile(path.resolve(__dirname, 'service-worker/skip-waiting.js'), 'utf8'),
+ { flag: 'a' }
+ )
+ }
+
+ // DONE.
+ const relativeDir = path.relative(process.cwd(), outDir)
+ logger.success(`\n${chalk.green('Success!')} Generated static files in ${chalk.cyan(relativeDir)}.\n`)
+
+ // --- helpers ---
+
+ function compile (config) {
+ return new Promise((resolve, reject) => {
+ webpack(config, (err, stats) => {
+ if (err) {
+ return reject(err)
+ }
+ if (stats.hasErrors()) {
+ stats.toJson().errors.forEach(err => {
+ console.error(err)
+ })
+ reject(new Error(`Failed to compile with errors.`))
+ return
+ }
+ if (cliOptions.debug && stats.hasWarnings()) {
+ stats.toJson().warnings.forEach(warning => {
+ console.warn(warning)
+ })
+ }
+ resolve(stats.toJson({ modules: false }))
+ })
+ })
+ }
+
+ function renderHeadTag (tag) {
+ const { tagName, attributes, innerHTML, closeTag } = normalizeHeadTag(tag)
+ return `<${tagName}${renderAttrs(attributes)}>${innerHTML}${closeTag ? `</${tagName}>` : ``}`
+ }
+
+ function renderAttrs (attrs = {}) {
+ const keys = Object.keys(attrs)
+ if (keys.length) {
+ return ' ' + keys.map(name => `${name}="${escape(attrs[name])}"`).join(' ')
+ } else {
+ return ''
+ }
+ }
+
+ async function renderPage (page) {
+ const pagePath = page.path
+ readline.clearLine(process.stdout, 0)
+ readline.cursorTo(process.stdout, 0)
+ process.stdout.write(`Rendering page: ${pagePath}`)
+
+ // #565 Avoid duplicate description meta at SSR.
+ const meta = (page.frontmatter && page.frontmatter.meta || []).filter(item => item.name !== 'description')
+ const pageMeta = renderPageMeta(meta)
+
+ const context = {
+ url: pagePath,
+ userHeadTags,
+ pageMeta,
+ title: 'VuePress',
+ lang: 'en',
+ description: ''
+ }
+
+ let html
+ try {
+ html = await renderer.renderToString(context)
+ } catch (e) {
+ console.error(logger.error(chalk.red(`Error rendering ${pagePath}:`), false))
+ throw e
+ }
+ const filename = decodeURIComponent(pagePath.replace(/\/$/, '/index.html').replace(/^\//, ''))
+ const filePath = path.resolve(outDir, filename)
+ await fs.ensureDir(path.dirname(filePath))
+ await fs.writeFile(filePath, html)
+ }
+
+ function renderPageMeta (meta) {
+ if (!meta) return ''
+ return meta.map(m => {
+ let res = `<meta`
+ Object.keys(m).forEach(key => {
+ res += ` ${key}="${escape(m[key])}"`
+ })
+ return res + `>`
+ }).join('')
+ }
+
+ async function workaroundEmptyStyleChunk () {
+ const styleChunk = stats.children[0].assets.find(a => {
+ return /styles\.\w{8}\.js$/.test(a.name)
+ })
+ if (!styleChunk) return
+ const styleChunkPath = path.resolve(outDir, styleChunk.name)
+ const styleChunkContent = await fs.readFile(styleChunkPath, 'utf-8')
+ await fs.remove(styleChunkPath)
+ // prepend it to app.js.
+ // this is necessary for the webpack runtime to work properly.
+ const appChunk = stats.children[0].assets.find(a => {
+ return /app\.\w{8}\.js$/.test(a.name)
+ })
+ const appChunkPath = path.resolve(outDir, appChunk.name)
+ const appChunkContent = await fs.readFile(appChunkPath, 'utf-8')
+ await fs.writeFile(appChunkPath, styleChunkContent + appChunkContent)
+ }
+}
diff --git a/node_modules/vuepress/lib/default-theme/AlgoliaSearchBox.vue b/node_modules/vuepress/lib/default-theme/AlgoliaSearchBox.vue
new file mode 100644
index 00000000..0334ae0b
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/AlgoliaSearchBox.vue
@@ -0,0 +1,156 @@
+<template>
+ <form
+ id="search-form"
+ class="algolia-search-wrapper search-box"
+ >
+ <input
+ id="algolia-search-input"
+ class="search-query"
+ >
+ </form>
+</template>
+
+<script>
+export default {
+ props: ['options'],
+
+ mounted () {
+ this.initialize(this.options, this.$lang)
+ },
+
+ methods: {
+ initialize (userOptions, lang) {
+ Promise.all([
+ import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.js'),
+ import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.css')
+ ]).then(([docsearch]) => {
+ docsearch = docsearch.default
+ const { algoliaOptions = {}} = userOptions
+ docsearch(Object.assign(
+ {},
+ userOptions,
+ {
+ inputSelector: '#algolia-search-input',
+ // #697 Make docsearch work well at i18n mode.
+ algoliaOptions: Object.assign({
+ 'facetFilters': [`lang:${lang}`].concat(algoliaOptions.facetFilters || [])
+ }, algoliaOptions)
+ }
+ ))
+ })
+ },
+
+ update (options, lang) {
+ this.$el.innerHTML = '<input id="algolia-search-input" class="search-query">'
+ this.initialize(options, lang)
+ }
+ },
+
+ watch: {
+ $lang (newValue) {
+ this.update(this.options, newValue)
+ },
+
+ options (newValue) {
+ this.update(newValue, this.$lang)
+ }
+ }
+}
+</script>
+
+<style lang="stylus">
+@import './styles/config.styl'
+
+.algolia-search-wrapper
+ & > span
+ vertical-align middle
+ .algolia-autocomplete
+ line-height normal
+ .ds-dropdown-menu
+ background-color #fff
+ border 1px solid #999
+ border-radius 4px
+ font-size 16px
+ margin 6px 0 0
+ padding 4px
+ text-align left
+ &:before
+ border-color #999
+ [class*=ds-dataset-]
+ border none
+ padding 0
+ .ds-suggestions
+ margin-top 0
+ .ds-suggestion
+ border-bottom 1px solid $borderColor
+ .algolia-docsearch-suggestion--highlight
+ color #2c815b
+ .algolia-docsearch-suggestion
+ border-color $borderColor
+ padding 0
+ .algolia-docsearch-suggestion--category-header
+ padding 5px 10px
+ margin-top 0
+ background $accentColor
+ color #fff
+ font-weight 600
+ .algolia-docsearch-suggestion--highlight
+ background rgba(255, 255, 255, 0.6)
+ .algolia-docsearch-suggestion--wrapper
+ padding 0
+ .algolia-docsearch-suggestion--title
+ font-weight 600
+ margin-bottom 0
+ color $textColor
+ .algolia-docsearch-suggestion--subcategory-column
+ vertical-align top
+ padding 5px 7px 5px 5px
+ border-color $borderColor
+ background #f1f3f5
+ &:after
+ display none
+ .algolia-docsearch-suggestion--subcategory-column-text
+ color #555
+ .algolia-docsearch-footer
+ border-color $borderColor
+ .ds-cursor .algolia-docsearch-suggestion--content
+ background-color #e7edf3 !important
+ color $textColor
+
+@media (min-width: $MQMobile)
+ .algolia-search-wrapper
+ .algolia-autocomplete
+ .algolia-docsearch-suggestion
+ .algolia-docsearch-suggestion--subcategory-column
+ float none
+ width 150px
+ min-width 150px
+ display table-cell
+ .algolia-docsearch-suggestion--content
+ float none
+ display table-cell
+ width 100%
+ vertical-align top
+ .ds-dropdown-menu
+ min-width 515px !important
+
+@media (max-width: $MQMobile)
+ .algolia-search-wrapper
+ .ds-dropdown-menu
+ min-width calc(100vw - 4rem) !important
+ max-width calc(100vw - 4rem) !important
+ .algolia-docsearch-suggestion--wrapper
+ padding 5px 7px 5px 5px !important
+ .algolia-docsearch-suggestion--subcategory-column
+ padding 0 !important
+ background white !important
+ .algolia-docsearch-suggestion--subcategory-column-text:after
+ content " > "
+ font-size 10px
+ line-height 14.4px
+ display inline-block
+ width 5px
+ margin -3px 3px 0
+ vertical-align middle
+
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/DropdownLink.vue b/node_modules/vuepress/lib/default-theme/DropdownLink.vue
new file mode 100644
index 00000000..e6000a60
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/DropdownLink.vue
@@ -0,0 +1,181 @@
+<template>
+ <div
+ class="dropdown-wrapper"
+ :class="{ open }"
+ >
+ <a
+ class="dropdown-title"
+ @click="toggle"
+ >
+ <span class="title">{{ item.text }}</span>
+ <span
+ class="arrow"
+ :class="open ? 'down' : 'right'"
+ ></span>
+ </a>
+
+ <DropdownTransition>
+ <ul
+ class="nav-dropdown"
+ v-show="open"
+ >
+ <li
+ class="dropdown-item"
+ :key="subItem.link || index"
+ v-for="(subItem, index) in item.items"
+ >
+ <h4 v-if="subItem.type === 'links'">{{ subItem.text }}</h4>
+
+ <ul
+ class="dropdown-subitem-wrapper"
+ v-if="subItem.type === 'links'"
+ >
+ <li
+ class="dropdown-subitem"
+ :key="childSubItem.link"
+ v-for="childSubItem in subItem.items"
+ >
+ <NavLink :item="childSubItem"/>
+ </li>
+ </ul>
+
+ <NavLink
+ v-else
+ :item="subItem"
+ />
+ </li>
+ </ul>
+ </DropdownTransition>
+ </div>
+</template>
+
+<script>
+import NavLink from './NavLink.vue'
+import DropdownTransition from './DropdownTransition.vue'
+
+export default {
+ components: { NavLink, DropdownTransition },
+
+ data () {
+ return {
+ open: false
+ }
+ },
+
+ props: {
+ item: {
+ required: true
+ }
+ },
+
+ methods: {
+ toggle () {
+ this.open = !this.open
+ }
+ }
+}
+</script>
+
+<style lang="stylus">
+@import './styles/config.styl'
+
+.dropdown-wrapper
+ cursor pointer
+ .dropdown-title
+ display block
+ &:hover
+ border-color transparent
+ .arrow
+ vertical-align middle
+ margin-top -1px
+ margin-left 0.4rem
+ .nav-dropdown
+ .dropdown-item
+ color inherit
+ line-height 1.7rem
+ h4
+ margin 0.45rem 0 0
+ border-top 1px solid #eee
+ padding 0.45rem 1.5rem 0 1.25rem
+ .dropdown-subitem-wrapper
+ padding 0
+ list-style none
+ .dropdown-subitem
+ font-size 0.9em
+ a
+ display block
+ line-height 1.7rem
+ position relative
+ border-bottom none
+ font-weight 400
+ margin-bottom 0
+ padding 0 1.5rem 0 1.25rem
+ &:hover
+ color $accentColor
+ &.router-link-active
+ color $accentColor
+ &::after
+ content ""
+ width 0
+ height 0
+ border-left 5px solid $accentColor
+ border-top 3px solid transparent
+ border-bottom 3px solid transparent
+ position absolute
+ top calc(50% - 2px)
+ left 9px
+ &:first-child h4
+ margin-top 0
+ padding-top 0
+ border-top 0
+
+@media (max-width: $MQMobile)
+ .dropdown-wrapper
+ &.open .dropdown-title
+ margin-bottom 0.5rem
+ .nav-dropdown
+ transition height .1s ease-out
+ overflow hidden
+ .dropdown-item
+ h4
+ border-top 0
+ margin-top 0
+ padding-top 0
+ h4, & > a
+ font-size 15px
+ line-height 2rem
+ .dropdown-subitem
+ font-size 14px
+ padding-left 1rem
+
+@media (min-width: $MQMobile)
+ .dropdown-wrapper
+ height 1.8rem
+ &:hover .nav-dropdown
+ // override the inline style.
+ display block !important
+ .dropdown-title .arrow
+ // make the arrow always down at desktop
+ border-left 4px solid transparent
+ border-right 4px solid transparent
+ border-top 6px solid $arrowBgColor
+ border-bottom 0
+ .nav-dropdown
+ display none
+ // Avoid height shaked by clicking
+ height auto !important
+ box-sizing border-box;
+ max-height calc(100vh - 2.7rem)
+ overflow-y auto
+ position absolute
+ top 100%
+ right 0
+ background-color #fff
+ padding 0.6rem 0
+ border 1px solid #ddd
+ border-bottom-color #ccc
+ text-align left
+ border-radius 0.25rem
+ white-space nowrap
+ margin 0
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/DropdownTransition.vue b/node_modules/vuepress/lib/default-theme/DropdownTransition.vue
new file mode 100644
index 00000000..8c711a15
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/DropdownTransition.vue
@@ -0,0 +1,33 @@
+<template>
+ <transition
+ name="dropdown"
+ @enter="setHeight"
+ @after-enter="unsetHeight"
+ @before-leave="setHeight"
+ >
+ <slot/>
+ </transition>
+</template>
+
+<script>
+export default {
+ name: 'DropdownTransition',
+
+ methods: {
+ setHeight (items) {
+ // explicitly set height so that it can be transitioned
+ items.style.height = items.scrollHeight + 'px'
+ },
+
+ unsetHeight (items) {
+ items.style.height = ''
+ }
+ }
+}
+</script>
+
+<style lang="stylus">
+.dropdown-enter, .dropdown-leave-to
+ height 0 !important
+
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/Home.vue b/node_modules/vuepress/lib/default-theme/Home.vue
new file mode 100644
index 00000000..a172eb9b
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/Home.vue
@@ -0,0 +1,162 @@
+<template>
+ <div class="home">
+ <div class="hero">
+ <img
+ v-if="data.heroImage"
+ :src="$withBase(data.heroImage)"
+ alt="hero"
+ >
+
+ <h1>{{ data.heroText || $title || 'Hello' }}</h1>
+
+ <p class="description">
+ {{ data.tagline || $description || 'Welcome to your VuePress site' }}
+ </p>
+
+ <p
+ class="action"
+ v-if="data.actionText && data.actionLink"
+ >
+ <NavLink
+ class="action-button"
+ :item="actionLink"
+ />
+ </p>
+ </div>
+
+ <div
+ class="features"
+ v-if="data.features && data.features.length"
+ >
+ <div
+ class="feature"
+ v-for="(feature, index) in data.features"
+ :key="index"
+ >
+ <h2>{{ feature.title }}</h2>
+ <p>{{ feature.details }}</p>
+ </div>
+ </div>
+
+ <Content custom/>
+
+ <div
+ class="footer"
+ v-if="data.footer"
+ >
+ {{ data.footer }}
+ </div>
+ </div>
+</template>
+
+<script>
+import NavLink from './NavLink.vue'
+
+export default {
+ components: { NavLink },
+
+ computed: {
+ data () {
+ return this.$page.frontmatter
+ },
+
+ actionLink () {
+ return {
+ link: this.data.actionLink,
+ text: this.data.actionText
+ }
+ }
+ }
+}
+</script>
+
+<style lang="stylus">
+@import './styles/config.styl'
+
+.home
+ padding $navbarHeight 2rem 0
+ max-width 960px
+ margin 0px auto
+ .hero
+ text-align center
+ img
+ max-height 280px
+ display block
+ margin 3rem auto 1.5rem
+ h1
+ font-size 3rem
+ h1, .description, .action
+ margin 1.8rem auto
+ .description
+ max-width 35rem
+ font-size 1.6rem
+ line-height 1.3
+ color lighten($textColor, 40%)
+ .action-button
+ display inline-block
+ font-size 1.2rem
+ color #fff
+ background-color $accentColor
+ padding 0.8rem 1.6rem
+ border-radius 4px
+ transition background-color .1s ease
+ box-sizing border-box
+ border-bottom 1px solid darken($accentColor, 10%)
+ &:hover
+ background-color lighten($accentColor, 10%)
+ .features
+ border-top 1px solid $borderColor
+ padding 1.2rem 0
+ margin-top 2.5rem
+ display flex
+ flex-wrap wrap
+ align-items flex-start
+ align-content stretch
+ justify-content space-between
+ .feature
+ flex-grow 1
+ flex-basis 30%
+ max-width 30%
+ h2
+ font-size 1.4rem
+ font-weight 500
+ border-bottom none
+ padding-bottom 0
+ color lighten($textColor, 10%)
+ p
+ color lighten($textColor, 25%)
+ .footer
+ padding 2.5rem
+ border-top 1px solid $borderColor
+ text-align center
+ color lighten($textColor, 25%)
+
+@media (max-width: $MQMobile)
+ .home
+ .features
+ flex-direction column
+ .feature
+ max-width 100%
+ padding 0 2.5rem
+
+@media (max-width: $MQMobileNarrow)
+ .home
+ padding-left 1.5rem
+ padding-right 1.5rem
+ .hero
+ img
+ max-height 210px
+ margin 2rem auto 1.2rem
+ h1
+ font-size 2rem
+ h1, .description, .action
+ margin 1.2rem auto
+ .description
+ font-size 1.2rem
+ .action-button
+ font-size 1rem
+ padding 0.6rem 1.2rem
+ .feature
+ h2
+ font-size 1.25rem
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/Layout.vue b/node_modules/vuepress/lib/default-theme/Layout.vue
new file mode 100644
index 00000000..ee2e6abe
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/Layout.vue
@@ -0,0 +1,183 @@
+<template>
+ <div
+ class="theme-container"
+ :class="pageClasses"
+ @touchstart="onTouchStart"
+ @touchend="onTouchEnd"
+ >
+ <Navbar
+ v-if="shouldShowNavbar"
+ @toggle-sidebar="toggleSidebar"
+ />
+
+ <div
+ class="sidebar-mask"
+ @click="toggleSidebar(false)"
+ ></div>
+
+ <Sidebar
+ :items="sidebarItems"
+ @toggle-sidebar="toggleSidebar"
+ >
+ <slot
+ name="sidebar-top"
+ slot="top"
+ />
+ <slot
+ name="sidebar-bottom"
+ slot="bottom"
+ />
+ </Sidebar>
+
+ <div
+ class="custom-layout"
+ v-if="$page.frontmatter.layout"
+ >
+ <component :is="$page.frontmatter.layout"/>
+ </div>
+
+ <Home v-else-if="$page.frontmatter.home"/>
+
+ <Page
+ v-else
+ :sidebar-items="sidebarItems"
+ >
+ <slot
+ name="page-top"
+ slot="top"
+ />
+ <slot
+ name="page-bottom"
+ slot="bottom"
+ />
+ </Page>
+
+ <SWUpdatePopup :updateEvent="swUpdateEvent"/>
+ </div>
+</template>
+
+<script>
+import Vue from 'vue'
+import nprogress from 'nprogress'
+import Home from './Home.vue'
+import Navbar from './Navbar.vue'
+import Page from './Page.vue'
+import Sidebar from './Sidebar.vue'
+import SWUpdatePopup from './SWUpdatePopup.vue'
+import { resolveSidebarItems } from './util'
+
+export default {
+ components: { Home, Page, Sidebar, Navbar, SWUpdatePopup },
+
+ data () {
+ return {
+ isSidebarOpen: false,
+ swUpdateEvent: null
+ }
+ },
+
+ computed: {
+ shouldShowNavbar () {
+ const { themeConfig } = this.$site
+ const { frontmatter } = this.$page
+ if (
+ frontmatter.navbar === false ||
+ themeConfig.navbar === false) {
+ return false
+ }
+ return (
+ this.$title ||
+ themeConfig.logo ||
+ themeConfig.repo ||
+ themeConfig.nav ||
+ this.$themeLocaleConfig.nav
+ )
+ },
+
+ shouldShowSidebar () {
+ const { frontmatter } = this.$page
+ return (
+ !frontmatter.layout &&
+ !frontmatter.home &&
+ frontmatter.sidebar !== false &&
+ this.sidebarItems.length
+ )
+ },
+
+ sidebarItems () {
+ return resolveSidebarItems(
+ this.$page,
+ this.$route,
+ this.$site,
+ this.$localePath
+ )
+ },
+
+ pageClasses () {
+ const userPageClass = this.$page.frontmatter.pageClass
+ return [
+ {
+ 'no-navbar': !this.shouldShowNavbar,
+ 'sidebar-open': this.isSidebarOpen,
+ 'no-sidebar': !this.shouldShowSidebar
+ },
+ userPageClass
+ ]
+ }
+ },
+
+ mounted () {
+ window.addEventListener('scroll', this.onScroll)
+
+ // configure progress bar
+ nprogress.configure({ showSpinner: false })
+
+ this.$router.beforeEach((to, from, next) => {
+ if (to.path !== from.path && !Vue.component(to.name)) {
+ nprogress.start()
+ }
+ next()
+ })
+
+ this.$router.afterEach(() => {
+ nprogress.done()
+ this.isSidebarOpen = false
+ })
+
+ this.$on('sw-updated', this.onSWUpdated)
+ },
+
+ methods: {
+ toggleSidebar (to) {
+ this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
+ },
+
+ // side swipe
+ onTouchStart (e) {
+ this.touchStart = {
+ x: e.changedTouches[0].clientX,
+ y: e.changedTouches[0].clientY
+ }
+ },
+
+ onTouchEnd (e) {
+ const dx = e.changedTouches[0].clientX - this.touchStart.x
+ const dy = e.changedTouches[0].clientY - this.touchStart.y
+ if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
+ if (dx > 0 && this.touchStart.x <= 80) {
+ this.toggleSidebar(true)
+ } else {
+ this.toggleSidebar(false)
+ }
+ }
+ },
+
+ onSWUpdated (e) {
+ this.swUpdateEvent = e
+ }
+ }
+}
+</script>
+
+<style src="prismjs/themes/prism-tomorrow.css"></style>
+<style src="./styles/theme.styl" lang="stylus"></style>
diff --git a/node_modules/vuepress/lib/default-theme/NavLink.vue b/node_modules/vuepress/lib/default-theme/NavLink.vue
new file mode 100644
index 00000000..d9fa4886
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/NavLink.vue
@@ -0,0 +1,49 @@
+<template>
+ <router-link
+ class="nav-link"
+ :to="link"
+ v-if="!isExternal(link)"
+ :exact="exact"
+ >{{ item.text }}</router-link>
+ <a
+ v-else
+ :href="link"
+ class="nav-link external"
+ :target="isMailto(link) || isTel(link) ? null : '_blank'"
+ :rel="isMailto(link) || isTel(link) ? null : 'noopener noreferrer'"
+ >
+ {{ item.text }}
+ <OutboundLink/>
+ </a>
+</template>
+
+<script>
+import { isExternal, isMailto, isTel, ensureExt } from './util'
+
+export default {
+ props: {
+ item: {
+ required: true
+ }
+ },
+
+ computed: {
+ link () {
+ return ensureExt(this.item.link)
+ },
+
+ exact () {
+ if (this.$site.locales) {
+ return Object.keys(this.$site.locales).some(rootLink => rootLink === this.link)
+ }
+ return this.link === '/'
+ }
+ },
+
+ methods: {
+ isExternal,
+ isMailto,
+ isTel
+ }
+}
+</script>
diff --git a/node_modules/vuepress/lib/default-theme/NavLinks.vue b/node_modules/vuepress/lib/default-theme/NavLinks.vue
new file mode 100644
index 00000000..4037f288
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/NavLinks.vue
@@ -0,0 +1,151 @@
+<template>
+ <nav
+ class="nav-links"
+ v-if="userLinks.length || repoLink"
+ >
+ <!-- user links -->
+ <div
+ class="nav-item"
+ v-for="item in userLinks"
+ :key="item.link"
+ >
+ <DropdownLink
+ v-if="item.type === 'links'"
+ :item="item"
+ />
+ <NavLink
+ v-else
+ :item="item"
+ />
+ </div>
+
+ <!-- repo link -->
+ <a
+ v-if="repoLink"
+ :href="repoLink"
+ class="repo-link"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ {{ repoLabel }}
+ <OutboundLink/>
+ </a>
+ </nav>
+</template>
+
+<script>
+import DropdownLink from './DropdownLink.vue'
+import { resolveNavLinkItem } from './util'
+import NavLink from './NavLink.vue'
+
+export default {
+ components: { NavLink, DropdownLink },
+
+ computed: {
+ userNav () {
+ return this.$themeLocaleConfig.nav || this.$site.themeConfig.nav || []
+ },
+
+ nav () {
+ const { locales } = this.$site
+ if (locales && Object.keys(locales).length > 1) {
+ const currentLink = this.$page.path
+ const routes = this.$router.options.routes
+ const themeLocales = this.$site.themeConfig.locales || {}
+ const languageDropdown = {
+ text: this.$themeLocaleConfig.selectText || 'Languages',
+ items: Object.keys(locales).map(path => {
+ const locale = locales[path]
+ const text = themeLocales[path] && themeLocales[path].label || locale.lang
+ let link
+ // Stay on the current page
+ if (locale.lang === this.$lang) {
+ link = currentLink
+ } else {
+ // Try to stay on the same page
+ link = currentLink.replace(this.$localeConfig.path, path)
+ // fallback to homepage
+ if (!routes.some(route => route.path === link)) {
+ link = path
+ }
+ }
+ return { text, link }
+ })
+ }
+ return [...this.userNav, languageDropdown]
+ }
+ return this.userNav
+ },
+
+ userLinks () {
+ return (this.nav || []).map(link => {
+ return Object.assign(resolveNavLinkItem(link), {
+ items: (link.items || []).map(resolveNavLinkItem)
+ })
+ })
+ },
+
+ repoLink () {
+ const { repo } = this.$site.themeConfig
+ if (repo) {
+ return /^https?:/.test(repo)
+ ? repo
+ : `https://github.com/${repo}`
+ }
+ },
+
+ repoLabel () {
+ if (!this.repoLink) return
+ if (this.$site.themeConfig.repoLabel) {
+ return this.$site.themeConfig.repoLabel
+ }
+
+ const repoHost = this.repoLink.match(/^https?:\/\/[^/]+/)[0]
+ const platforms = ['GitHub', 'GitLab', 'Bitbucket']
+ for (let i = 0; i < platforms.length; i++) {
+ const platform = platforms[i]
+ if (new RegExp(platform, 'i').test(repoHost)) {
+ return platform
+ }
+ }
+
+ return 'Source'
+ }
+ }
+}
+</script>
+
+<style lang="stylus">
+@import './styles/config.styl'
+
+.nav-links
+ display inline-block
+ a
+ line-height 1.4rem
+ color inherit
+ &:hover, &.router-link-active
+ color $accentColor
+ .nav-item
+ position relative
+ display inline-block
+ margin-left 1.5rem
+ line-height 2rem
+ &:first-child
+ margin-left 0
+ .repo-link
+ margin-left 1.5rem
+
+@media (max-width: $MQMobile)
+ .nav-links
+ .nav-item, .repo-link
+ margin-left 0
+
+@media (min-width: $MQMobile)
+ .nav-links a
+ &:hover, &.router-link-active
+ color $textColor
+ .nav-item > a:not(.external)
+ &:hover, &.router-link-active
+ margin-bottom -2px
+ border-bottom 2px solid lighten($accentColor, 8%)
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/Navbar.vue b/node_modules/vuepress/lib/default-theme/Navbar.vue
new file mode 100644
index 00000000..12795665
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/Navbar.vue
@@ -0,0 +1,133 @@
+<template>
+ <header class="navbar">
+ <SidebarButton @toggle-sidebar="$emit('toggle-sidebar')"/>
+
+ <router-link
+ :to="$localePath"
+ class="home-link"
+ >
+ <img
+ class="logo"
+ v-if="$site.themeConfig.logo"
+ :src="$withBase($site.themeConfig.logo)"
+ :alt="$siteTitle"
+ >
+ <span
+ ref="siteName"
+ class="site-name"
+ v-if="$siteTitle"
+ :class="{ 'can-hide': $site.themeConfig.logo }"
+ >{{ $siteTitle }}</span>
+ </router-link>
+
+ <div
+ class="links"
+ :style="{
+ 'max-width': linksWrapMaxWidth + 'px'
+ }"
+ >
+ <AlgoliaSearchBox
+ v-if="isAlgoliaSearch"
+ :options="algolia"
+ />
+ <SearchBox v-else-if="$site.themeConfig.search !== false"/>
+ <NavLinks class="can-hide"/>
+ </div>
+ </header>
+</template>
+
+<script>
+import SidebarButton from './SidebarButton.vue'
+import AlgoliaSearchBox from '@AlgoliaSearchBox'
+import SearchBox from './SearchBox.vue'
+import NavLinks from './NavLinks.vue'
+
+export default {
+ components: { SidebarButton, NavLinks, SearchBox, AlgoliaSearchBox },
+
+ data () {
+ return {
+ linksWrapMaxWidth: null
+ }
+ },
+
+ mounted () {
+ const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
+ const NAVBAR_VERTICAL_PADDING = parseInt(css(this.$el, 'paddingLeft')) + parseInt(css(this.$el, 'paddingRight'))
+ const handleLinksWrapWidth = () => {
+ if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
+ this.linksWrapMaxWidth = null
+ } else {
+ this.linksWrapMaxWidth = this.$el.offsetWidth - NAVBAR_VERTICAL_PADDING -
+ (this.$refs.siteName && this.$refs.siteName.offsetWidth || 0)
+ }
+ }
+ handleLinksWrapWidth()
+ window.addEventListener('resize', handleLinksWrapWidth, false)
+ },
+
+ computed: {
+ algolia () {
+ return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
+ },
+
+ isAlgoliaSearch () {
+ return this.algolia && this.algolia.apiKey && this.algolia.indexName
+ }
+ }
+}
+
+function css (el, property) {
+ // NOTE: Known bug, will return 'auto' if style value is 'auto'
+ const win = el.ownerDocument.defaultView
+ // null means not to return pseudo styles
+ return win.getComputedStyle(el, null)[property]
+}
+</script>
+
+<style lang="stylus">
+@import './styles/config.styl'
+
+$navbar-vertical-padding = 0.7rem
+$navbar-horizontal-padding = 1.5rem
+
+.navbar
+ padding $navbar-vertical-padding $navbar-horizontal-padding
+ line-height $navbarHeight - 1.4rem
+ position relative
+ a, span, img
+ display inline-block
+ .logo
+ height $navbarHeight - 1.4rem
+ min-width $navbarHeight - 1.4rem
+ margin-right 0.8rem
+ vertical-align top
+ .site-name
+ font-size 1.3rem
+ font-weight 600
+ color $textColor
+ position relative
+ .links
+ padding-left 1.5rem
+ box-sizing border-box
+ background-color white
+ white-space nowrap
+ font-size 0.9rem
+ position absolute
+ right $navbar-horizontal-padding
+ top $navbar-vertical-padding
+ display flex
+ .search-box
+ flex: 0 0 auto
+ vertical-align top
+ .nav-links
+ flex 1
+
+@media (max-width: $MQMobile)
+ .navbar
+ padding-left 4rem
+ .can-hide
+ display none
+ .links
+ padding-left 1.5rem
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/NotFound.vue b/node_modules/vuepress/lib/default-theme/NotFound.vue
new file mode 100644
index 00000000..6aefe797
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/NotFound.vue
@@ -0,0 +1,26 @@
+<template>
+ <div class="theme-container">
+ <div class="content">
+ <h1>404</h1>
+ <blockquote>{{ getMsg() }}</blockquote>
+ <router-link to="/">Take me home.</router-link>
+ </div>
+ </div>
+</template>
+
+<script>
+const msgs = [
+ `There's nothing here.`,
+ `How did we get here?`,
+ `That's a Four-Oh-Four.`,
+ `Looks like we've got some broken links.`
+]
+
+export default {
+ methods: {
+ getMsg () {
+ return msgs[Math.floor(Math.random() * msgs.length)]
+ }
+ }
+}
+</script>
diff --git a/node_modules/vuepress/lib/default-theme/Page.vue b/node_modules/vuepress/lib/default-theme/Page.vue
new file mode 100644
index 00000000..37d65b41
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/Page.vue
@@ -0,0 +1,246 @@
+<template>
+ <div class="page">
+ <slot name="top"/>
+
+ <Content :custom="false"/>
+
+ <div class="page-edit">
+ <div
+ class="edit-link"
+ v-if="editLink"
+ >
+ <a
+ :href="editLink"
+ target="_blank"
+ rel="noopener noreferrer"
+ >{{ editLinkText }}</a>
+ <OutboundLink/>
+ </div>
+
+ <div
+ class="last-updated"
+ v-if="lastUpdated"
+ >
+ <span class="prefix">{{ lastUpdatedText }}: </span>
+ <span class="time">{{ lastUpdated }}</span>
+ </div>
+ </div>
+
+ <div class="page-nav" v-if="prev || next">
+ <p class="inner">
+ <span
+ v-if="prev"
+ class="prev"
+ >
+ ←
+ <router-link
+ v-if="prev"
+ class="prev"
+ :to="prev.path"
+ >
+ {{ prev.title || prev.path }}
+ </router-link>
+ </span>
+
+ <span
+ v-if="next"
+ class="next"
+ >
+ <router-link
+ v-if="next"
+ :to="next.path"
+ >
+ {{ next.title || next.path }}
+ </router-link>
+ →
+ </span>
+ </p>
+ </div>
+
+ <slot name="bottom"/>
+ </div>
+</template>
+
+<script>
+import { resolvePage, normalize, outboundRE, endingSlashRE } from './util'
+
+export default {
+ props: ['sidebarItems'],
+
+ computed: {
+ lastUpdated () {
+ if (this.$page.lastUpdated) {
+ return new Date(this.$page.lastUpdated).toLocaleString(this.$lang)
+ }
+ },
+
+ lastUpdatedText () {
+ if (typeof this.$themeLocaleConfig.lastUpdated === 'string') {
+ return this.$themeLocaleConfig.lastUpdated
+ }
+ if (typeof this.$site.themeConfig.lastUpdated === 'string') {
+ return this.$site.themeConfig.lastUpdated
+ }
+ return 'Last Updated'
+ },
+
+ prev () {
+ const prev = this.$page.frontmatter.prev
+ if (prev === false) {
+ return
+ } else if (prev) {
+ return resolvePage(this.$site.pages, prev, this.$route.path)
+ } else {
+ return resolvePrev(this.$page, this.sidebarItems)
+ }
+ },
+
+ next () {
+ const next = this.$page.frontmatter.next
+ if (next === false) {
+ return
+ } else if (next) {
+ return resolvePage(this.$site.pages, next, this.$route.path)
+ } else {
+ return resolveNext(this.$page, this.sidebarItems)
+ }
+ },
+
+ editLink () {
+ if (this.$page.frontmatter.editLink === false) {
+ return
+ }
+ const {
+ repo,
+ editLinks,
+ docsDir = '',
+ docsBranch = 'master',
+ docsRepo = repo
+ } = this.$site.themeConfig
+
+ let path = normalize(this.$page.path)
+ if (endingSlashRE.test(path)) {
+ path += 'README.md'
+ } else {
+ path += '.md'
+ }
+ if (docsRepo && editLinks) {
+ return this.createEditLink(repo, docsRepo, docsDir, docsBranch, path)
+ }
+ },
+
+ editLinkText () {
+ return (
+ this.$themeLocaleConfig.editLinkText ||
+ this.$site.themeConfig.editLinkText ||
+ `Edit this page`
+ )
+ }
+ },
+
+ methods: {
+ createEditLink (repo, docsRepo, docsDir, docsBranch, path) {
+ const bitbucket = /bitbucket.org/
+ if (bitbucket.test(repo)) {
+ const base = outboundRE.test(docsRepo)
+ ? docsRepo
+ : repo
+ return (
+ base.replace(endingSlashRE, '') +
+ `/${docsBranch}` +
+ (docsDir ? '/' + docsDir.replace(endingSlashRE, '') : '') +
+ path +
+ `?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default`
+ )
+ }
+
+ const base = outboundRE.test(docsRepo)
+ ? docsRepo
+ : `https://github.com/${docsRepo}`
+
+ return (
+ base.replace(endingSlashRE, '') +
+ `/edit/${docsBranch}` +
+ (docsDir ? '/' + docsDir.replace(endingSlashRE, '') : '') +
+ path
+ )
+ }
+ }
+}
+
+function resolvePrev (page, items) {
+ return find(page, items, -1)
+}
+
+function resolveNext (page, items) {
+ return find(page, items, 1)
+}
+
+function find (page, items, offset) {
+ const res = []
+ items.forEach(item => {
+ if (item.type === 'group') {
+ res.push(...item.children || [])
+ } else {
+ res.push(item)
+ }
+ })
+ for (let i = 0; i < res.length; i++) {
+ const cur = res[i]
+ if (cur.type === 'page' && cur.path === page.path) {
+ return res[i + offset]
+ }
+ }
+}
+</script>
+
+<style lang="stylus">
+@import './styles/config.styl'
+@require './styles/wrapper.styl'
+
+.page
+ padding-bottom 2rem
+
+.page-edit
+ @extend $wrapper
+ padding-top 1rem
+ padding-bottom 1rem
+ overflow auto
+ .edit-link
+ display inline-block
+ a
+ color lighten($textColor, 25%)
+ margin-right 0.25rem
+ .last-updated
+ float right
+ font-size 0.9em
+ .prefix
+ font-weight 500
+ color lighten($textColor, 25%)
+ .time
+ font-weight 400
+ color #aaa
+
+.page-nav
+ @extend $wrapper
+ padding-top 1rem
+ padding-bottom 0
+ .inner
+ min-height 2rem
+ margin-top 0
+ border-top 1px solid $borderColor
+ padding-top 1rem
+ overflow auto // clear float
+ .next
+ float right
+
+@media (max-width: $MQMobile)
+ .page-edit
+ .edit-link
+ margin-bottom .5rem
+ .last-updated
+ font-size .8em
+ float none
+ text-align left
+
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/SWUpdatePopup.vue b/node_modules/vuepress/lib/default-theme/SWUpdatePopup.vue
new file mode 100644
index 00000000..b224db31
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/SWUpdatePopup.vue
@@ -0,0 +1,85 @@
+<template>
+ <transition name="sw-update-popup">
+ <div
+ v-if="enabled"
+ class="sw-update-popup"
+ >
+ {{message}}<br>
+ <button @click="reload">{{buttonText}}</button>
+ </div>
+ </transition>
+</template>
+
+<script>
+export default {
+ props: {
+ updateEvent: {
+ type: Object,
+ default: null
+ }
+ },
+
+ computed: {
+ popupConfig () {
+ for (const config of [this.$themeLocaleConfig, this.$site.themeConfig]) {
+ const sw = config.serviceWorker
+ if (sw && sw.updatePopup) {
+ return typeof sw.updatePopup === 'object' ? sw.updatePopup : {}
+ }
+ }
+ return null
+ },
+
+ enabled () {
+ return Boolean(this.popupConfig && this.updateEvent)
+ },
+
+ message () {
+ const c = this.popupConfig
+ return (c && c.message) || 'New content is available.'
+ },
+
+ buttonText () {
+ const c = this.popupConfig
+ return (c && c.buttonText) || 'Refresh'
+ }
+ },
+
+ methods: {
+ reload () {
+ if (this.updateEvent) {
+ this.updateEvent.skipWaiting().then(() => {
+ location.reload(true)
+ })
+ this.updateEvent = null
+ }
+ }
+ }
+}
+</script>
+
+<style lang="stylus">
+@import './styles/config.styl'
+
+.sw-update-popup
+ position fixed
+ right 1em
+ bottom 1em
+ padding 1em
+ border 1px solid $accentColor
+ border-radius 3px
+ background #fff
+ box-shadow 0 4px 16px rgba(0, 0, 0, 0.5)
+ text-align center
+
+ button
+ margin-top 0.5em
+ padding 0.25em 2em
+
+.sw-update-popup-enter-active, .sw-update-popup-leave-active
+ transition opacity 0.3s, transform 0.3s
+
+.sw-update-popup-enter, .sw-update-popup-leave-to
+ opacity 0
+ transform translate(0, 50%) scale(0.5)
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/SearchBox.vue b/node_modules/vuepress/lib/default-theme/SearchBox.vue
new file mode 100644
index 00000000..98608552
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/SearchBox.vue
@@ -0,0 +1,238 @@
+<template>
+ <div class="search-box">
+ <input
+ @input="query = $event.target.value"
+ aria-label="Search"
+ :value="query"
+ :class="{ 'focused': focused }"
+ autocomplete="off"
+ spellcheck="false"
+ @focus="focused = true"
+ @blur="focused = false"
+ @keyup.enter="go(focusIndex)"
+ @keyup.up="onUp"
+ @keyup.down="onDown"
+ >
+ <ul
+ class="suggestions"
+ v-if="showSuggestions"
+ :class="{ 'align-right': alignRight }"
+ @mouseleave="unfocus"
+ >
+ <li
+ class="suggestion"
+ v-for="(s, i) in suggestions"
+ :class="{ focused: i === focusIndex }"
+ @mousedown="go(i)"
+ @mouseenter="focus(i)"
+ >
+ <a :href="s.path" @click.prevent>
+ <span class="page-title">{{ s.title || s.path }}</span>
+ <span v-if="s.header" class="header">&gt; {{ s.header.title }}</span>
+ </a>
+ </li>
+ </ul>
+ </div>
+</template>
+
+<script>
+export default {
+ data () {
+ return {
+ query: '',
+ focused: false,
+ focusIndex: 0
+ }
+ },
+
+ computed: {
+ showSuggestions () {
+ return (
+ this.focused &&
+ this.suggestions &&
+ this.suggestions.length
+ )
+ },
+
+ suggestions () {
+ const query = this.query.trim().toLowerCase()
+ if (!query) {
+ return
+ }
+
+ const { pages, themeConfig } = this.$site
+ const max = themeConfig.searchMaxSuggestions || 5
+ const localePath = this.$localePath
+ const matches = item => (
+ item.title &&
+ item.title.toLowerCase().indexOf(query) > -1
+ )
+ const res = []
+ for (let i = 0; i < pages.length; i++) {
+ if (res.length >= max) break
+ const p = pages[i]
+ // filter out results that do not match current locale
+ if (this.getPageLocalePath(p) !== localePath) {
+ continue
+ }
+ if (matches(p)) {
+ res.push(p)
+ } else if (p.headers) {
+ for (let j = 0; j < p.headers.length; j++) {
+ if (res.length >= max) break
+ const h = p.headers[j]
+ if (matches(h)) {
+ res.push(Object.assign({}, p, {
+ path: p.path + '#' + h.slug,
+ header: h
+ }))
+ }
+ }
+ }
+ }
+ return res
+ },
+
+ // make suggestions align right when there are not enough items
+ alignRight () {
+ const navCount = (this.$site.themeConfig.nav || []).length
+ const repo = this.$site.repo ? 1 : 0
+ return navCount + repo <= 2
+ }
+ },
+
+ methods: {
+ getPageLocalePath (page) {
+ for (const localePath in this.$site.locales || {}) {
+ if (localePath !== '/' && page.path.indexOf(localePath) === 0) {
+ return localePath
+ }
+ }
+ return '/'
+ },
+
+ onUp () {
+ if (this.showSuggestions) {
+ if (this.focusIndex > 0) {
+ this.focusIndex--
+ } else {
+ this.focusIndex = this.suggestions.length - 1
+ }
+ }
+ },
+
+ onDown () {
+ if (this.showSuggestions) {
+ if (this.focusIndex < this.suggestions.length - 1) {
+ this.focusIndex++
+ } else {
+ this.focusIndex = 0
+ }
+ }
+ },
+
+ go (i) {
+ if (!this.showSuggestions) {
+ return
+ }
+ this.$router.push(this.suggestions[i].path)
+ this.query = ''
+ this.focusIndex = 0
+ },
+
+ focus (i) {
+ this.focusIndex = i
+ },
+
+ unfocus () {
+ this.focusIndex = -1
+ }
+ }
+}
+</script>
+
+<style lang="stylus">
+@import './styles/config.styl'
+
+.search-box
+ display inline-block
+ position relative
+ margin-right 1rem
+ input
+ cursor text
+ width 10rem
+ color lighten($textColor, 25%)
+ display inline-block
+ border 1px solid darken($borderColor, 10%)
+ border-radius 2rem
+ font-size 0.9rem
+ line-height 2rem
+ padding 0 0.5rem 0 2rem
+ outline none
+ transition all .2s ease
+ background #fff url(./search.svg) 0.6rem 0.5rem no-repeat
+ background-size 1rem
+ &:focus
+ cursor auto
+ border-color $accentColor
+ .suggestions
+ background #fff
+ width 20rem
+ position absolute
+ top 1.5rem
+ border 1px solid darken($borderColor, 10%)
+ border-radius 6px
+ padding 0.4rem
+ list-style-type none
+ &.align-right
+ right 0
+ .suggestion
+ line-height 1.4
+ padding 0.4rem 0.6rem
+ border-radius 4px
+ cursor pointer
+ a
+ white-space normal
+ color lighten($textColor, 35%)
+ .page-title
+ font-weight 600
+ .header
+ font-size 0.9em
+ margin-left 0.25em
+ &.focused
+ background-color #f3f4f5
+ a
+ color $accentColor
+
+@media (max-width: $MQNarrow)
+ .search-box
+ input
+ cursor pointer
+ width 0
+ border-color transparent
+ position relative
+ &:focus
+ cursor text
+ left 0
+ width 10rem
+
+@media (max-width: $MQNarrow) and (min-width: $MQMobile)
+ .search-box
+ .suggestions
+ left 0
+
+@media (max-width: $MQMobile)
+ .search-box
+ margin-right 0
+ input
+ left 1rem
+ .suggestions
+ right 0
+
+@media (max-width: $MQMobileNarrow)
+ .search-box
+ .suggestions
+ width calc(100vw - 4rem)
+ input:focus
+ width 8rem
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/Sidebar.vue b/node_modules/vuepress/lib/default-theme/Sidebar.vue
new file mode 100644
index 00000000..7bcf0059
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/Sidebar.vue
@@ -0,0 +1,113 @@
+<template>
+ <div class="sidebar">
+ <NavLinks/>
+ <slot name="top"/>
+ <ul class="sidebar-links" v-if="items.length">
+ <li v-for="(item, i) in items" :key="i">
+ <SidebarGroup
+ v-if="item.type === 'group'"
+ :item="item"
+ :first="i === 0"
+ :open="i === openGroupIndex"
+ :collapsable="item.collapsable || item.collapsible"
+ @toggle="toggleGroup(i)"
+ />
+ <SidebarLink v-else :item="item"/>
+ </li>
+ </ul>
+ <slot name="bottom"/>
+ </div>
+</template>
+
+<script>
+import SidebarGroup from './SidebarGroup.vue'
+import SidebarLink from './SidebarLink.vue'
+import NavLinks from './NavLinks.vue'
+import { isActive } from './util'
+
+export default {
+ components: { SidebarGroup, SidebarLink, NavLinks },
+
+ props: ['items'],
+
+ data () {
+ return {
+ openGroupIndex: 0
+ }
+ },
+
+ created () {
+ this.refreshIndex()
+ },
+
+ watch: {
+ '$route' () {
+ this.refreshIndex()
+ }
+ },
+
+ methods: {
+ refreshIndex () {
+ const index = resolveOpenGroupIndex(
+ this.$route,
+ this.items
+ )
+ if (index > -1) {
+ this.openGroupIndex = index
+ }
+ },
+
+ toggleGroup (index) {
+ this.openGroupIndex = index === this.openGroupIndex ? -1 : index
+ },
+
+ isActive (page) {
+ return isActive(this.$route, page.path)
+ }
+ }
+}
+
+function resolveOpenGroupIndex (route, items) {
+ for (let i = 0; i < items.length; i++) {
+ const item = items[i]
+ if (item.type === 'group' && item.children.some(c => isActive(route, c.path))) {
+ return i
+ }
+ }
+ return -1
+}
+</script>
+
+<style lang="stylus">
+@import './styles/config.styl'
+
+.sidebar
+ ul
+ padding 0
+ margin 0
+ list-style-type none
+ a
+ display inline-block
+ .nav-links
+ display none
+ border-bottom 1px solid $borderColor
+ padding 0.5rem 0 0.75rem 0
+ a
+ font-weight 600
+ .nav-item, .repo-link
+ display block
+ line-height 1.25rem
+ font-size 1.1em
+ padding 0.5rem 0 0.5rem 1.5rem
+ .sidebar-links
+ padding 1.5rem 0
+
+@media (max-width: $MQMobile)
+ .sidebar
+ .nav-links
+ display block
+ .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
+ top calc(1rem - 2px)
+ .sidebar-links
+ padding 1rem 0
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/SidebarButton.vue b/node_modules/vuepress/lib/default-theme/SidebarButton.vue
new file mode 100644
index 00000000..0a222434
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/SidebarButton.vue
@@ -0,0 +1,28 @@
+<template>
+ <div class="sidebar-button" @click="$emit('toggle-sidebar')">
+ <svg class="icon" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512">
+ <path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z" class=""></path>
+ </svg>
+ </div>
+</template>
+
+<style lang="stylus">
+@import './styles/config.styl'
+
+.sidebar-button
+ display none
+ width 1.25rem
+ height 1.25rem
+ position absolute
+ padding 0.6rem
+ top 0.6rem
+ left 1rem
+ .icon
+ display block
+ width 1.25rem
+ height 1.25rem
+
+@media (max-width: $MQMobile)
+ .sidebar-button
+ display block
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/SidebarGroup.vue b/node_modules/vuepress/lib/default-theme/SidebarGroup.vue
new file mode 100644
index 00000000..119dfa14
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/SidebarGroup.vue
@@ -0,0 +1,77 @@
+<template>
+ <div
+ class="sidebar-group"
+ :class="{ first, collapsable }"
+ >
+ <p
+ class="sidebar-heading"
+ :class="{ open }"
+ @click="$emit('toggle')"
+ >
+ <span>{{ item.title }}</span>
+ <span
+ class="arrow"
+ v-if="collapsable"
+ :class="open ? 'down' : 'right'">
+ </span>
+ </p>
+
+ <DropdownTransition>
+ <ul
+ ref="items"
+ class="sidebar-group-items"
+ v-if="open || !collapsable"
+ >
+ <li v-for="child in item.children">
+ <SidebarLink :item="child"/>
+ </li>
+ </ul>
+ </DropdownTransition>
+ </div>
+</template>
+
+<script>
+import SidebarLink from './SidebarLink.vue'
+import DropdownTransition from './DropdownTransition.vue'
+
+export default {
+ name: 'SidebarGroup',
+ props: ['item', 'first', 'open', 'collapsable'],
+ components: { SidebarLink, DropdownTransition }
+}
+</script>
+
+<style lang="stylus">
+.sidebar-group
+ &:not(.first)
+ margin-top 1em
+ .sidebar-group
+ padding-left 0.5em
+ &:not(.collapsable)
+ .sidebar-heading
+ cursor auto
+ color inherit
+
+.sidebar-heading
+ color #999
+ transition color .15s ease
+ cursor pointer
+ font-size 1.1em
+ font-weight bold
+ // text-transform uppercase
+ padding 0 1.5rem
+ margin-top 0
+ margin-bottom 0.5rem
+ &.open, &:hover
+ color inherit
+ .arrow
+ position relative
+ top -0.12em
+ left 0.5em
+ &:.open .arrow
+ top -0.18em
+
+.sidebar-group-items
+ transition height .1s ease-out
+ overflow hidden
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/SidebarLink.vue b/node_modules/vuepress/lib/default-theme/SidebarLink.vue
new file mode 100644
index 00000000..8288bf96
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/SidebarLink.vue
@@ -0,0 +1,91 @@
+<script>
+import { isActive, hashRE, groupHeaders } from './util'
+
+export default {
+ functional: true,
+
+ props: ['item'],
+
+ render (h, { parent: { $page, $site, $route }, props: { item }}) {
+ // use custom active class matching logic
+ // due to edge case of paths ending with / + hash
+ const selfActive = isActive($route, item.path)
+ // for sidebar: auto pages, a hash link should be active if one of its child
+ // matches
+ const active = item.type === 'auto'
+ ? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug))
+ : selfActive
+ const link = renderLink(h, item.path, item.title || item.path, active)
+ const configDepth = $page.frontmatter.sidebarDepth != null
+ ? $page.frontmatter.sidebarDepth
+ : $site.themeConfig.sidebarDepth
+ const maxDepth = configDepth == null ? 1 : configDepth
+ const displayAllHeaders = !!$site.themeConfig.displayAllHeaders
+ if (item.type === 'auto') {
+ return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)]
+ } else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) {
+ const children = groupHeaders(item.headers)
+ return [link, renderChildren(h, children, item.path, $route, maxDepth)]
+ } else {
+ return link
+ }
+ }
+}
+
+function renderLink (h, to, text, active) {
+ return h('router-link', {
+ props: {
+ to,
+ activeClass: '',
+ exactActiveClass: ''
+ },
+ class: {
+ active,
+ 'sidebar-link': true
+ }
+ }, text)
+}
+
+function renderChildren (h, children, path, route, maxDepth, depth = 1) {
+ if (!children || depth > maxDepth) return null
+ return h('ul', { class: 'sidebar-sub-headers' }, children.map(c => {
+ const active = isActive(route, path + '#' + c.slug)
+ return h('li', { class: 'sidebar-sub-header' }, [
+ renderLink(h, path + '#' + c.slug, c.title, active),
+ renderChildren(h, c.children, path, route, maxDepth, depth + 1)
+ ])
+ }))
+}
+</script>
+
+<style lang="stylus">
+@import './styles/config.styl'
+
+.sidebar .sidebar-sub-headers
+ padding-left 1rem
+ font-size 0.95em
+
+a.sidebar-link
+ font-weight 400
+ display inline-block
+ color $textColor
+ border-left 0.25rem solid transparent
+ padding 0.35rem 1rem 0.35rem 1.25rem
+ line-height 1.4
+ width: 100%
+ box-sizing: border-box
+ &:hover
+ color $accentColor
+ &.active
+ font-weight 600
+ color $accentColor
+ border-left-color $accentColor
+ .sidebar-group &
+ padding-left 2rem
+ .sidebar-sub-headers &
+ padding-top 0.25rem
+ padding-bottom 0.25rem
+ border-left none
+ &.active
+ font-weight 500
+</style>
diff --git a/node_modules/vuepress/lib/default-theme/search.svg b/node_modules/vuepress/lib/default-theme/search.svg
new file mode 100644
index 00000000..03d83913
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/search.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="13"><g stroke-width="2" stroke="#aaa" fill="none"><path d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg>
diff --git a/node_modules/vuepress/lib/default-theme/styles/arrow.styl b/node_modules/vuepress/lib/default-theme/styles/arrow.styl
new file mode 100644
index 00000000..20bffc0d
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/styles/arrow.styl
@@ -0,0 +1,22 @@
+@require './config'
+
+.arrow
+ display inline-block
+ width 0
+ height 0
+ &.up
+ border-left 4px solid transparent
+ border-right 4px solid transparent
+ border-bottom 6px solid $arrowBgColor
+ &.down
+ border-left 4px solid transparent
+ border-right 4px solid transparent
+ border-top 6px solid $arrowBgColor
+ &.right
+ border-top 4px solid transparent
+ border-bottom 4px solid transparent
+ border-left 6px solid $arrowBgColor
+ &.left
+ border-top 4px solid transparent
+ border-bottom 4px solid transparent
+ border-right 6px solid $arrowBgColor
diff --git a/node_modules/vuepress/lib/default-theme/styles/code.styl b/node_modules/vuepress/lib/default-theme/styles/code.styl
new file mode 100644
index 00000000..8383c6e3
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/styles/code.styl
@@ -0,0 +1,129 @@
+@require './config'
+
+.content
+ code
+ color lighten($textColor, 20%)
+ padding 0.25rem 0.5rem
+ margin 0
+ font-size 0.85em
+ background-color rgba(27,31,35,0.05)
+ border-radius 3px
+
+.content
+ pre, pre[class*="language-"]
+ line-height 1.4
+ padding 1.25rem 1.5rem
+ margin 0.85rem 0
+ background-color $codeBgColor
+ border-radius 6px
+ overflow auto
+ code
+ color #fff
+ padding 0
+ background-color transparent
+ border-radius 0
+
+div[class*="language-"]
+ position relative
+ background-color $codeBgColor
+ border-radius 6px
+ .highlight-lines
+ user-select none
+ padding-top 1.3rem
+ position absolute
+ top 0
+ left 0
+ width 100%
+ line-height 1.4
+ .highlighted
+ background-color rgba(0, 0, 0, 66%)
+ pre, pre[class*="language-"]
+ background transparent
+ position relative
+ z-index 1
+ &::before
+ position absolute
+ z-index 3
+ top 0.8em
+ right 1em
+ font-size 0.75rem
+ color rgba(255, 255, 255, 0.4)
+ &:not(.line-numbers-mode)
+ .line-numbers-wrapper
+ display none
+ &.line-numbers-mode
+ .highlight-lines .highlighted
+ position relative
+ &:before
+ content ' '
+ position absolute
+ z-index 3
+ left 0
+ top 0
+ display block
+ width $lineNumbersWrapperWidth
+ height 100%
+ background-color rgba(0, 0, 0, 66%)
+ pre
+ padding-left $lineNumbersWrapperWidth + 1 rem
+ vertical-align middle
+ .line-numbers-wrapper
+ position absolute
+ top 0
+ width $lineNumbersWrapperWidth
+ text-align center
+ color rgba(255, 255, 255, 0.3)
+ padding 1.25rem 0
+ line-height 1.4
+ br
+ user-select none
+ .line-number
+ position relative
+ z-index 4
+ user-select none
+ font-size 0.85em
+ &::after
+ content ''
+ position absolute
+ z-index 2
+ top 0
+ left 0
+ width $lineNumbersWrapperWidth
+ height 100%
+ border-radius 6px 0 0 6px
+ border-right 1px solid rgba(0, 0, 0, 66%)
+ background-color $codeBgColor
+
+
+for lang in $codeLang
+ div{'[class~="language-' + lang + '"]'}
+ &:before
+ content ('' + lang)
+
+div[class~="language-javascript"]
+ &:before
+ content "js"
+
+div[class~="language-typescript"]
+ &:before
+ content "ts"
+
+div[class~="language-markup"]
+ &:before
+ content "html"
+
+div[class~="language-markdown"]
+ &:before
+ content "md"
+
+div[class~="language-json"]:before
+ content "json"
+
+div[class~="language-ruby"]:before
+ content "rb"
+
+div[class~="language-python"]:before
+ content "py"
+
+div[class~="language-bash"]:before
+ content "sh"
diff --git a/node_modules/vuepress/lib/default-theme/styles/config.styl b/node_modules/vuepress/lib/default-theme/styles/config.styl
new file mode 100644
index 00000000..a57d4484
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/styles/config.styl
@@ -0,0 +1,22 @@
+// colors
+$accentColor = #3eaf7c
+$textColor = #2c3e50
+$borderColor = #eaecef
+$codeBgColor = #282c34
+$arrowBgColor = #ccc
+
+// layout
+$navbarHeight = 3.6rem
+$sidebarWidth = 20rem
+$contentWidth = 740px
+
+// responsive breakpoints
+$MQNarrow = 959px
+$MQMobile = 719px
+$MQMobileNarrow = 419px
+
+// code
+$lineNumbersWrapperWidth = 3.5rem
+$codeLang = js ts html md vue css sass scss less stylus go java c sh yaml py
+
+@import '~@temp/override.styl'
diff --git a/node_modules/vuepress/lib/default-theme/styles/custom-blocks.styl b/node_modules/vuepress/lib/default-theme/styles/custom-blocks.styl
new file mode 100644
index 00000000..3ccc2df2
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/styles/custom-blocks.styl
@@ -0,0 +1,28 @@
+.custom-block
+ .custom-block-title
+ font-weight 600
+ margin-bottom -0.4rem
+ &.tip, &.warning, &.danger
+ padding .1rem 1.5rem
+ border-left-width .5rem
+ border-left-style solid
+ margin 1rem 0
+ &.tip
+ background-color #f3f5f7
+ border-color #42b983
+ &.warning
+ background-color rgba(255,229,100,.3)
+ border-color darken(#ffe564, 35%)
+ color darken(#ffe564, 70%)
+ .custom-block-title
+ color darken(#ffe564, 50%)
+ a
+ color $textColor
+ &.danger
+ background-color #ffe6e6
+ border-color darken(red, 20%)
+ color darken(red, 70%)
+ .custom-block-title
+ color darken(red, 40%)
+ a
+ color $textColor
diff --git a/node_modules/vuepress/lib/default-theme/styles/mobile.styl b/node_modules/vuepress/lib/default-theme/styles/mobile.styl
new file mode 100644
index 00000000..b35e59c5
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/styles/mobile.styl
@@ -0,0 +1,37 @@
+@require './config'
+
+$mobileSidebarWidth = $sidebarWidth * 0.82
+
+// narrow desktop / iPad
+@media (max-width: $MQNarrow)
+ .sidebar
+ font-size 15px
+ width $mobileSidebarWidth
+ .page
+ padding-left $mobileSidebarWidth
+
+// wide mobile
+@media (max-width: $MQMobile)
+ .sidebar
+ top 0
+ padding-top $navbarHeight
+ transform translateX(-100%)
+ transition transform .2s ease
+ .page
+ padding-left 0
+ .theme-container
+ &.sidebar-open
+ .sidebar
+ transform translateX(0)
+ &.no-navbar
+ .sidebar
+ padding-top: 0
+
+// narrow mobile
+@media (max-width: $MQMobileNarrow)
+ h1
+ font-size 1.9rem
+ .content
+ div[class*="language-"]
+ margin 0.85rem -1.5rem
+ border-radius 0
diff --git a/node_modules/vuepress/lib/default-theme/styles/nprogress.styl b/node_modules/vuepress/lib/default-theme/styles/nprogress.styl
new file mode 100644
index 00000000..f186a67e
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/styles/nprogress.styl
@@ -0,0 +1,48 @@
+#nprogress
+ pointer-events none
+ .bar
+ background $accentColor
+ position fixed
+ z-index 1031
+ top 0
+ left 0
+ width 100%
+ height 2px
+ .peg
+ display block
+ position absolute
+ right 0px
+ width 100px
+ height 100%
+ box-shadow 0 0 10px $accentColor, 0 0 5px $accentColor
+ opacity 1.0
+ transform rotate(3deg) translate(0px, -4px)
+ .spinner
+ display block
+ position fixed
+ z-index 1031
+ top 15px
+ right 15px
+ .spinner-icon
+ width 18px
+ height 18px
+ box-sizing border-box
+ border solid 2px transparent
+ border-top-color $accentColor
+ border-left-color $accentColor
+ border-radius 50%
+ animation nprogress-spinner 400ms linear infinite
+
+.nprogress-custom-parent
+ overflow hidden
+ position relative
+
+.nprogress-custom-parent #nprogress .spinner,
+.nprogress-custom-parent #nprogress .bar
+ position absolute
+
+@keyframes nprogress-spinner
+ 0%
+ transform rotate(0deg)
+ 100%
+ transform rotate(360deg)
diff --git a/node_modules/vuepress/lib/default-theme/styles/theme.styl b/node_modules/vuepress/lib/default-theme/styles/theme.styl
new file mode 100644
index 00000000..a733861f
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/styles/theme.styl
@@ -0,0 +1,190 @@
+@require './config'
+@require './nprogress'
+@require './code'
+@require './custom-blocks'
+@require './arrow'
+@require './wrapper'
+@require './toc'
+
+html, body
+ padding 0
+ margin 0
+
+body
+ font-family -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif
+ -webkit-font-smoothing antialiased
+ -moz-osx-font-smoothing grayscale
+ font-size 16px
+ color $textColor
+
+.page
+ padding-left $sidebarWidth
+
+.navbar
+ position fixed
+ z-index 20
+ top 0
+ left 0
+ right 0
+ height $navbarHeight
+ background-color #fff
+ box-sizing border-box
+ border-bottom 1px solid $borderColor
+
+.sidebar-mask
+ position fixed
+ z-index 9
+ top 0
+ left 0
+ width 100vw
+ height 100vh
+ display none
+
+.sidebar
+ font-size 15px
+ background-color #fff
+ width $sidebarWidth
+ position fixed
+ z-index 10
+ margin 0
+ top $navbarHeight
+ left 0
+ bottom 0
+ box-sizing border-box
+ border-right 1px solid $borderColor
+ overflow-y auto
+
+.content:not(.custom)
+ @extend $wrapper
+ > *:first-child
+ margin-top $navbarHeight
+ a:hover
+ text-decoration underline
+ p.demo
+ padding 1rem 1.5rem
+ border 1px solid #ddd
+ border-radius 4px
+ img
+ max-width 100%
+
+.content.custom
+ padding 0
+ margin 0
+ img
+ max-width 100%
+
+a
+ font-weight 500
+ color $accentColor
+ text-decoration none
+
+p a code
+ font-weight 400
+ color $accentColor
+
+kbd
+ background #eee
+ border solid 0.15rem #ddd
+ border-bottom solid 0.25rem #ddd
+ border-radius 0.15rem
+ padding 0 0.15em
+
+blockquote
+ font-size 1.2rem
+ color #999
+ border-left .25rem solid #dfe2e5
+ margin-left 0
+ padding-left 1rem
+
+ul, ol
+ padding-left 1.2em
+
+strong
+ font-weight 600
+
+h1, h2, h3, h4, h5, h6
+ font-weight 600
+ line-height 1.25
+ .content:not(.custom) > &
+ margin-top (0.5rem - $navbarHeight)
+ padding-top ($navbarHeight + 1rem)
+ margin-bottom 0
+ &:first-child
+ margin-top -1.5rem
+ margin-bottom 1rem
+ + p, + pre, + .custom-block
+ margin-top 2rem
+ &:hover .header-anchor
+ opacity: 1
+
+h1
+ font-size 2.2rem
+
+h2
+ font-size 1.65rem
+ padding-bottom .3rem
+ border-bottom 1px solid $borderColor
+
+h3
+ font-size 1.35rem
+
+a.header-anchor
+ font-size 0.85em
+ float left
+ margin-left -0.87em
+ padding-right 0.23em
+ margin-top 0.125em
+ opacity 0
+ &:hover
+ text-decoration none
+
+code, kbd, .line-number
+ font-family source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace
+
+p, ul, ol
+ line-height 1.7
+
+hr
+ border 0
+ border-top 1px solid $borderColor
+
+table
+ border-collapse collapse
+ margin 1rem 0
+ display: block
+ overflow-x: auto
+
+tr
+ border-top 1px solid #dfe2e5
+ &:nth-child(2n)
+ background-color #f6f8fa
+
+th, td
+ border 1px solid #dfe2e5
+ padding .6em 1em
+
+.custom-layout
+ padding-top $navbarHeight
+
+.theme-container
+ &.sidebar-open
+ .sidebar-mask
+ display: block
+ &.no-navbar
+ .content:not(.custom) > h1, h2, h3, h4, h5, h6
+ margin-top 1.5rem
+ padding-top 0
+ .sidebar
+ top 0
+ .custom-layout
+ padding-top 0
+
+
+@media (min-width: ($MQMobile + 1px))
+ .theme-container.no-sidebar
+ .sidebar
+ display none
+ .page
+ padding-left 0
+
+@require './mobile.styl'
diff --git a/node_modules/vuepress/lib/default-theme/styles/toc.styl b/node_modules/vuepress/lib/default-theme/styles/toc.styl
new file mode 100644
index 00000000..d3e71069
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/styles/toc.styl
@@ -0,0 +1,3 @@
+.table-of-contents
+ .badge
+ vertical-align middle
diff --git a/node_modules/vuepress/lib/default-theme/styles/wrapper.styl b/node_modules/vuepress/lib/default-theme/styles/wrapper.styl
new file mode 100644
index 00000000..a99262c7
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/styles/wrapper.styl
@@ -0,0 +1,9 @@
+$wrapper
+ max-width $contentWidth
+ margin 0 auto
+ padding 2rem 2.5rem
+ @media (max-width: $MQNarrow)
+ padding 2rem
+ @media (max-width: $MQMobileNarrow)
+ padding 1.5rem
+
diff --git a/node_modules/vuepress/lib/default-theme/util.js b/node_modules/vuepress/lib/default-theme/util.js
new file mode 100644
index 00000000..ef95bea5
--- /dev/null
+++ b/node_modules/vuepress/lib/default-theme/util.js
@@ -0,0 +1,216 @@
+export const hashRE = /#.*$/
+export const extRE = /\.(md|html)$/
+export const endingSlashRE = /\/$/
+export const outboundRE = /^(https?:|mailto:|tel:)/
+
+export function normalize (path) {
+ return decodeURI(path)
+ .replace(hashRE, '')
+ .replace(extRE, '')
+}
+
+export function getHash (path) {
+ const match = path.match(hashRE)
+ if (match) {
+ return match[0]
+ }
+}
+
+export function isExternal (path) {
+ return outboundRE.test(path)
+}
+
+export function isMailto (path) {
+ return /^mailto:/.test(path)
+}
+
+export function isTel (path) {
+ return /^tel:/.test(path)
+}
+
+export function ensureExt (path) {
+ if (isExternal(path)) {
+ return path
+ }
+ const hashMatch = path.match(hashRE)
+ const hash = hashMatch ? hashMatch[0] : ''
+ const normalized = normalize(path)
+
+ if (endingSlashRE.test(normalized)) {
+ return path
+ }
+ return normalized + '.html' + hash
+}
+
+export function isActive (route, path) {
+ const routeHash = route.hash
+ const linkHash = getHash(path)
+ if (linkHash && routeHash !== linkHash) {
+ return false
+ }
+ const routePath = normalize(route.path)
+ const pagePath = normalize(path)
+ return routePath === pagePath
+}
+
+export function resolvePage (pages, rawPath, base) {
+ if (base) {
+ rawPath = resolvePath(rawPath, base)
+ }
+ const path = normalize(rawPath)
+ for (let i = 0; i < pages.length; i++) {
+ if (normalize(pages[i].path) === path) {
+ return Object.assign({}, pages[i], {
+ type: 'page',
+ path: ensureExt(rawPath)
+ })
+ }
+ }
+ console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`)
+ return {}
+}
+
+function resolvePath (relative, base, append) {
+ const firstChar = relative.charAt(0)
+ if (firstChar === '/') {
+ return relative
+ }
+
+ if (firstChar === '?' || firstChar === '#') {
+ return base + relative
+ }
+
+ const stack = base.split('/')
+
+ // remove trailing segment if:
+ // - not appending
+ // - appending to trailing slash (last segment is empty)
+ if (!append || !stack[stack.length - 1]) {
+ stack.pop()
+ }
+
+ // resolve relative path
+ const segments = relative.replace(/^\//, '').split('/')
+ for (let i = 0; i < segments.length; i++) {
+ const segment = segments[i]
+ if (segment === '..') {
+ stack.pop()
+ } else if (segment !== '.') {
+ stack.push(segment)
+ }
+ }
+
+ // ensure leading slash
+ if (stack[0] !== '') {
+ stack.unshift('')
+ }
+
+ return stack.join('/')
+}
+
+export function resolveSidebarItems (page, route, site, localePath) {
+ const { pages, themeConfig } = site
+
+ const localeConfig = localePath && themeConfig.locales
+ ? themeConfig.locales[localePath] || themeConfig
+ : themeConfig
+
+ const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
+ if (pageSidebarConfig === 'auto') {
+ return resolveHeaders(page)
+ }
+
+ const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
+ if (!sidebarConfig) {
+ return []
+ } else {
+ const { base, config } = resolveMatchingConfig(route, sidebarConfig)
+ return config
+ ? config.map(item => resolveItem(item, pages, base))
+ : []
+ }
+}
+
+function resolveHeaders (page) {
+ const headers = groupHeaders(page.headers || [])
+ return [{
+ type: 'group',
+ collapsable: false,
+ title: page.title,
+ children: headers.map(h => ({
+ type: 'auto',
+ title: h.title,
+ basePath: page.path,
+ path: page.path + '#' + h.slug,
+ children: h.children || []
+ }))
+ }]
+}
+
+export function groupHeaders (headers) {
+ // group h3s under h2
+ headers = headers.map(h => Object.assign({}, h))
+ let lastH2
+ headers.forEach(h => {
+ if (h.level === 2) {
+ lastH2 = h
+ } else if (lastH2) {
+ (lastH2.children || (lastH2.children = [])).push(h)
+ }
+ })
+ return headers.filter(h => h.level === 2)
+}
+
+export function resolveNavLinkItem (linkItem) {
+ return Object.assign(linkItem, {
+ type: linkItem.items && linkItem.items.length ? 'links' : 'link'
+ })
+}
+
+export function resolveMatchingConfig (route, config) {
+ if (Array.isArray(config)) {
+ return {
+ base: '/',
+ config: config
+ }
+ }
+ for (const base in config) {
+ if (ensureEndingSlash(route.path).indexOf(base) === 0) {
+ return {
+ base,
+ config: config[base]
+ }
+ }
+ }
+ return {}
+}
+
+function ensureEndingSlash (path) {
+ return /(\.html|\/)$/.test(path)
+ ? path
+ : path + '/'
+}
+
+function resolveItem (item, pages, base, isNested) {
+ if (typeof item === 'string') {
+ return resolvePage(pages, item, base)
+ } else if (Array.isArray(item)) {
+ return Object.assign(resolvePage(pages, item[0], base), {
+ title: item[1]
+ })
+ } else {
+ if (isNested) {
+ console.error(
+ '[vuepress] Nested sidebar groups are not supported. ' +
+ 'Consider using navbar + categories instead.'
+ )
+ }
+ const children = item.children || []
+ return {
+ type: 'group',
+ title: item.title,
+ children: children.map(child => resolveItem(child, pages, base, true)),
+ collapsable: item.collapsable !== false
+ }
+ }
+}
diff --git a/node_modules/vuepress/lib/dev.js b/node_modules/vuepress/lib/dev.js
new file mode 100644
index 00000000..ba909d99
--- /dev/null
+++ b/node_modules/vuepress/lib/dev.js
@@ -0,0 +1,149 @@
+module.exports = async function dev (sourceDir, cliOptions = {}) {
+ const fs = require('fs')
+ const path = require('path')
+ const chalk = require('chalk')
+ const webpack = require('webpack')
+ const chokidar = require('chokidar')
+ const serve = require('webpack-serve')
+ const convert = require('koa-connect')
+ const mount = require('koa-mount')
+ const range = require('koa-range')
+ const serveStatic = require('koa-static')
+ const history = require('connect-history-api-fallback')
+
+ const prepare = require('./prepare')
+ const logger = require('./util/logger')
+ const HeadPlugin = require('./webpack/HeadPlugin')
+ const DevLogPlugin = require('./webpack/DevLogPlugin')
+ const createClientConfig = require('./webpack/createClientConfig')
+ const { applyUserWebpackConfig } = require('./util')
+ const { frontmatterEmitter } = require('./webpack/markdownLoader')
+
+ logger.wait('\nExtracting site metadata...')
+ const options = await prepare(sourceDir)
+
+ // setup watchers to update options and dynamically generated files
+ const update = () => {
+ prepare(sourceDir).catch(err => {
+ console.error(logger.error(chalk.red(err.stack), false))
+ })
+ }
+
+ // watch add/remove of files
+ const pagesWatcher = chokidar.watch([
+ '**/*.md',
+ '.vuepress/components/**/*.vue'
+ ], {
+ cwd: sourceDir,
+ ignored: '.vuepress/**/*.md',
+ ignoreInitial: true
+ })
+ pagesWatcher.on('add', update)
+ pagesWatcher.on('unlink', update)
+ pagesWatcher.on('addDir', update)
+ pagesWatcher.on('unlinkDir', update)
+
+ // watch config file
+ const configWatcher = chokidar.watch([
+ '.vuepress/config.js',
+ '.vuepress/config.yml',
+ '.vuepress/config.toml'
+ ], {
+ cwd: sourceDir,
+ ignoreInitial: true
+ })
+ configWatcher.on('change', update)
+
+ // also listen for frontmatter changes from markdown files
+ frontmatterEmitter.on('update', update)
+
+ // resolve webpack config
+ let config = createClientConfig(options, cliOptions)
+
+ config
+ .plugin('html')
+ // using a fork of html-webpack-plugin to avoid it requiring webpack
+ // internals from an incompatible version.
+ .use(require('vuepress-html-webpack-plugin'), [{
+ template: path.resolve(__dirname, 'app/index.dev.html')
+ }])
+
+ config
+ .plugin('site-data')
+ .use(HeadPlugin, [{
+ tags: options.siteConfig.head || []
+ }])
+
+ const port = await resolvePort(cliOptions.port || options.siteConfig.port)
+ const { host, displayHost } = await resolveHost(cliOptions.host || options.siteConfig.host)
+
+ config
+ .plugin('vuepress-log')
+ .use(DevLogPlugin, [{
+ port,
+ displayHost,
+ publicPath: options.publicPath
+ }])
+
+ config = config.toConfig()
+ const userConfig = options.siteConfig.configureWebpack
+ if (userConfig) {
+ config = applyUserWebpackConfig(userConfig, config, false /* isServer */)
+ }
+
+ const compiler = webpack(config)
+
+ const nonExistentDir = path.resolve(__dirname, 'non-existent')
+ await serve({
+ // avoid project cwd from being served. Otherwise if the user has index.html
+ // in cwd it would break the server
+ content: [nonExistentDir],
+ compiler,
+ host,
+ dev: { logLevel: 'warn' },
+ hot: {
+ port: port + 1,
+ logLevel: 'error'
+ },
+ logLevel: 'error',
+ port,
+ add: app => {
+ const userPublic = path.resolve(sourceDir, '.vuepress/public')
+
+ // enable range request
+ app.use(range)
+
+ // respect base when serving static files...
+ if (fs.existsSync(userPublic)) {
+ app.use(mount(options.publicPath, serveStatic(userPublic)))
+ }
+
+ app.use(convert(history({
+ rewrites: [
+ { from: /\.html$/, to: '/' }
+ ]
+ })))
+ }
+ })
+}
+
+function resolveHost (host) {
+ // webpack-serve hot updates doesn't work properly over 0.0.0.0 on Windows,
+ // but localhost does not allow visiting over network :/
+ const defaultHost = process.platform === 'win32' ? 'localhost' : '0.0.0.0'
+ host = host || defaultHost
+ const displayHost = host === defaultHost && process.platform !== 'win32'
+ ? 'localhost'
+ : host
+ return {
+ displayHost,
+ host
+ }
+}
+
+async function resolvePort (port) {
+ const portfinder = require('portfinder')
+ portfinder.basePort = parseInt(port) || 8080
+ port = await portfinder.getPortPromise()
+ return port
+}
diff --git a/node_modules/vuepress/lib/eject.js b/node_modules/vuepress/lib/eject.js
new file mode 100644
index 00000000..e96b00fd
--- /dev/null
+++ b/node_modules/vuepress/lib/eject.js
@@ -0,0 +1,16 @@
+const fs = require('fs-extra')
+const path = require('path')
+const chalk = require('chalk')
+const logger = require('./util/logger')
+
+module.exports = async (dir) => {
+ const source = path.resolve(__dirname, 'default-theme')
+ const target = path.resolve(dir, '.vuepress/theme')
+ await fs.copy(source, target)
+ // remove the import to default theme override
+ const styleConfig = path.resolve(target, 'styles/config.styl')
+ const content = await fs.readFile(styleConfig, 'utf-8')
+ const transformed = content.split('\n').slice(0, -2).join('\n')
+ await fs.writeFile(styleConfig, transformed)
+ logger.success(`\nCopied default theme into ${chalk.cyan(target)}.\n`)
+}
diff --git a/node_modules/vuepress/lib/index.js b/node_modules/vuepress/lib/index.js
new file mode 100644
index 00000000..8e4d4a19
--- /dev/null
+++ b/node_modules/vuepress/lib/index.js
@@ -0,0 +1,4 @@
+exports.dev = require('./dev')
+exports.build = require('./build')
+exports.eject = require('./eject')
+Object.assign(exports, require('./util'))
diff --git a/node_modules/vuepress/lib/markdown/component.js b/node_modules/vuepress/lib/markdown/component.js
new file mode 100644
index 00000000..1aab66e8
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/component.js
@@ -0,0 +1,81 @@
+// Replacing the default htmlBlock rule to allow using custom components at
+// root level
+
+const blockNames = require('markdown-it/lib/common/html_blocks')
+const HTML_OPEN_CLOSE_TAG_RE = require('markdown-it/lib/common/html_re').HTML_OPEN_CLOSE_TAG_RE
+
+// An array of opening and corresponding closing sequences for html tags,
+// last argument defines whether it can terminate a paragraph or not
+const HTML_SEQUENCES = [
+ [/^<(script|pre|style)(?=(\s|>|$))/i, /<\/(script|pre|style)>/i, true],
+ [/^<!--/, /-->/, true],
+ [/^<\?/, /\?>/, true],
+ [/^<![A-Z]/, />/, true],
+ [/^<!\[CDATA\[/, /\]\]>/, true],
+ // PascalCase Components
+ [/^<[A-Z]/, />/, true],
+ // custom elements with hyphens
+ [/^<\w+\-/, />/, true],
+ [new RegExp('^</?(' + blockNames.join('|') + ')(?=(\\s|/?>|$))', 'i'), /^$/, true],
+ [new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false]
+]
+
+module.exports = md => {
+ md.block.ruler.at('html_block', htmlBlock)
+}
+
+function htmlBlock (state, startLine, endLine, silent) {
+ let i, nextLine, lineText
+ let pos = state.bMarks[startLine] + state.tShift[startLine]
+ let max = state.eMarks[startLine]
+
+ // if it's indented more than 3 spaces, it should be a code block
+ if (state.sCount[startLine] - state.blkIndent >= 4) { return false }
+
+ if (!state.md.options.html) { return false }
+
+ if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false }
+
+ lineText = state.src.slice(pos, max)
+
+ for (i = 0; i < HTML_SEQUENCES.length; i++) {
+ if (HTML_SEQUENCES[i][0].test(lineText)) { break }
+ }
+
+ if (i === HTML_SEQUENCES.length) {
+ console.log(lineText)
+ return false
+ }
+
+ if (silent) {
+ // true if this sequence can be a terminator, false otherwise
+ return HTML_SEQUENCES[i][2]
+ }
+
+ nextLine = startLine + 1
+
+ // If we are here - we detected HTML block.
+ // Let's roll down till block end.
+ if (!HTML_SEQUENCES[i][1].test(lineText)) {
+ for (; nextLine < endLine; nextLine++) {
+ if (state.sCount[nextLine] < state.blkIndent) { break }
+
+ pos = state.bMarks[nextLine] + state.tShift[nextLine]
+ max = state.eMarks[nextLine]
+ lineText = state.src.slice(pos, max)
+
+ if (HTML_SEQUENCES[i][1].test(lineText)) {
+ if (lineText.length !== 0) { nextLine++ }
+ break
+ }
+ }
+ }
+
+ state.line = nextLine
+
+ const token = state.push('html_block', '', 0)
+ token.map = [startLine, nextLine]
+ token.content = state.getLines(startLine, nextLine, state.blkIndent, true)
+
+ return true
+}
diff --git a/node_modules/vuepress/lib/markdown/containers.js b/node_modules/vuepress/lib/markdown/containers.js
new file mode 100644
index 00000000..215c4534
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/containers.js
@@ -0,0 +1,28 @@
+const container = require('markdown-it-container')
+
+module.exports = md => {
+ md
+ .use(...createContainer('tip', 'TIP'))
+ .use(...createContainer('warning', 'WARNING'))
+ .use(...createContainer('danger', 'WARNING'))
+ // explicitly escape Vue syntax
+ .use(container, 'v-pre', {
+ render: (tokens, idx) => tokens[idx].nesting === 1
+ ? `<div v-pre>\n`
+ : `</div>\n`
+ })
+}
+
+function createContainer (klass, defaultTitle) {
+ return [container, klass, {
+ render (tokens, idx) {
+ const token = tokens[idx]
+ const info = token.info.trim().slice(klass.length).trim()
+ if (token.nesting === 1) {
+ return `<div class="${klass} custom-block"><p class="custom-block-title">${info || defaultTitle}</p>\n`
+ } else {
+ return `</div>\n`
+ }
+ }
+ }]
+}
diff --git a/node_modules/vuepress/lib/markdown/highlight.js b/node_modules/vuepress/lib/markdown/highlight.js
new file mode 100644
index 00000000..02d5e3ff
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/highlight.js
@@ -0,0 +1,47 @@
+const chalk = require('chalk')
+const prism = require('prismjs')
+const loadLanguages = require('prismjs/components/index')
+const escapeHtml = require('escape-html')
+const logger = require('../util/logger')
+
+// required to make embedded highlighting work...
+loadLanguages(['markup', 'css', 'javascript'])
+
+function wrap (code, lang) {
+ if (lang === 'text') {
+ code = escapeHtml(code)
+ }
+ return `<pre v-pre class="language-${lang}"><code>${code}</code></pre>`
+}
+
+module.exports = (str, lang) => {
+ if (!lang) {
+ return wrap(str, 'text')
+ }
+ lang = lang.toLowerCase()
+ const rawLang = lang
+ if (lang === 'vue' || lang === 'html') {
+ lang = 'markup'
+ }
+ if (lang === 'md') {
+ lang = 'markdown'
+ }
+ if (lang === 'ts') {
+ lang = 'typescript'
+ }
+ if (lang === 'py') {
+ lang = 'python'
+ }
+ if (!prism.languages[lang]) {
+ try {
+ loadLanguages([lang])
+ } catch (e) {
+ logger.warn(chalk.yellow(`[vuepress] Syntax highlight for language "${lang}" is not supported.`))
+ }
+ }
+ if (prism.languages[lang]) {
+ const code = prism.highlight(str, prism.languages[lang], lang)
+ return wrap(code, rawLang)
+ }
+ return wrap(str, 'text')
+}
diff --git a/node_modules/vuepress/lib/markdown/highlightLines.js b/node_modules/vuepress/lib/markdown/highlightLines.js
new file mode 100644
index 00000000..dd833432
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/highlightLines.js
@@ -0,0 +1,49 @@
+// Modified from https://github.com/egoist/markdown-it-highlight-lines
+
+const RE = /{([\d,-]+)}/
+const wrapperRE = /^<pre .*?><code>/
+
+module.exports = md => {
+ const fence = md.renderer.rules.fence
+ md.renderer.rules.fence = (...args) => {
+ const [tokens, idx, options] = args
+ const token = tokens[idx]
+
+ const rawInfo = token.info
+ if (!rawInfo || !RE.test(rawInfo)) {
+ return fence(...args)
+ }
+
+ const langName = rawInfo.replace(RE, '').trim()
+ // ensure the next plugin get the correct lang.
+ token.info = langName
+
+ const lineNumbers = RE.exec(rawInfo)[1]
+ .split(',')
+ .map(v => v.split('-').map(v => parseInt(v, 10)))
+
+ const code = options.highlight
+ ? options.highlight(token.content, langName)
+ : token.content
+
+ const rawCode = code.replace(wrapperRE, '')
+ const highlightLinesCode = rawCode.split('\n').map((split, index) => {
+ const lineNumber = index + 1
+ const inRange = lineNumbers.some(([start, end]) => {
+ if (start && end) {
+ return lineNumber >= start && lineNumber <= end
+ }
+ return lineNumber === start
+ })
+ if (inRange) {
+ return `<div class="highlighted">&nbsp;</div>`
+ }
+ return '<br>'
+ }).join('')
+
+ const highlightLinesWrapperCode =
+ `<div class="highlight-lines">${highlightLinesCode}</div>`
+
+ return highlightLinesWrapperCode + code
+ }
+}
diff --git a/node_modules/vuepress/lib/markdown/hoist.js b/node_modules/vuepress/lib/markdown/hoist.js
new file mode 100644
index 00000000..a6383398
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/hoist.js
@@ -0,0 +1,14 @@
+module.exports = md => {
+ const RE = /^<(script|style)(?=(\s|>|$))/i
+
+ md.renderer.rules.html_block = (tokens, idx) => {
+ const content = tokens[idx].content
+ const hoistedTags = md.__data.hoistedTags || (md.__data.hoistedTags = [])
+ if (RE.test(content.trim())) {
+ hoistedTags.push(content)
+ return ''
+ } else {
+ return content
+ }
+ }
+}
diff --git a/node_modules/vuepress/lib/markdown/index.js b/node_modules/vuepress/lib/markdown/index.js
new file mode 100644
index 00000000..f4942f6c
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/index.js
@@ -0,0 +1,78 @@
+const highlight = require('./highlight')
+const highlightLines = require('./highlightLines')
+const preWrapper = require('./preWrapper')
+const lineNumbers = require('./lineNumbers')
+const component = require('./component')
+const hoistScriptStyle = require('./hoist')
+const convertRouterLink = require('./link')
+const containers = require('./containers')
+const snippet = require('./snippet')
+const emoji = require('markdown-it-emoji')
+const anchor = require('markdown-it-anchor')
+const toc = require('markdown-it-table-of-contents')
+const _slugify = require('./slugify')
+const { parseHeaders } = require('../util/parseHeaders')
+
+module.exports = ({ markdown = {}} = {}) => {
+ // allow user config slugify
+ const slugify = markdown.slugify || _slugify
+
+ const md = require('markdown-it')({
+ html: true,
+ highlight
+ })
+ // custom plugins
+ .use(component)
+ .use(highlightLines)
+ .use(preWrapper)
+ .use(snippet)
+ .use(convertRouterLink, Object.assign({
+ target: '_blank',
+ rel: 'noopener noreferrer'
+ }, markdown.externalLinks))
+ .use(hoistScriptStyle)
+ .use(containers)
+
+ // 3rd party plugins
+ .use(emoji)
+ .use(anchor, Object.assign({
+ slugify,
+ permalink: true,
+ permalinkBefore: true,
+ permalinkSymbol: '#'
+ }, markdown.anchor))
+ .use(toc, Object.assign({
+ slugify,
+ includeLevel: [2, 3],
+ format: parseHeaders
+ }, markdown.toc))
+
+ // apply user config
+ if (markdown.config) {
+ markdown.config(md)
+ }
+
+ if (markdown.lineNumbers) {
+ md.use(lineNumbers)
+ }
+
+ module.exports.dataReturnable(md)
+
+ // expose slugify
+ md.slugify = slugify
+
+ return md
+}
+
+module.exports.dataReturnable = function dataReturnable (md) {
+ // override render to allow custom plugins return data
+ const render = md.render
+ md.render = (...args) => {
+ md.__data = {}
+ const html = render.call(md, ...args)
+ return {
+ html,
+ data: md.__data
+ }
+ }
+}
diff --git a/node_modules/vuepress/lib/markdown/lineNumbers.js b/node_modules/vuepress/lib/markdown/lineNumbers.js
new file mode 100644
index 00000000..bc95d2b0
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/lineNumbers.js
@@ -0,0 +1,26 @@
+// markdown-it plugin for generating line numbers.
+// It depends on preWrapper plugin.
+
+module.exports = md => {
+ const fence = md.renderer.rules.fence
+ md.renderer.rules.fence = (...args) => {
+ const rawCode = fence(...args)
+ const code = rawCode.slice(
+ rawCode.indexOf('<code>'),
+ rawCode.indexOf('</code>')
+ )
+
+ const lines = code.split('\n')
+ const lineNumbersCode = [...Array(lines.length - 1)]
+ .map((line, index) => `<span class="line-number">${index + 1}</span><br>`).join('')
+
+ const lineNumbersWrapperCode =
+ `<div class="line-numbers-wrapper">${lineNumbersCode}</div>`
+
+ const finalCode = rawCode
+ .replace('<!--beforeend-->', `${lineNumbersWrapperCode}<!--beforeend-->`)
+ .replace('extra-class', 'line-numbers-mode')
+
+ return finalCode
+ }
+}
diff --git a/node_modules/vuepress/lib/markdown/link.js b/node_modules/vuepress/lib/markdown/link.js
new file mode 100644
index 00000000..bbe9550d
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/link.js
@@ -0,0 +1,91 @@
+// markdown-it plugin for:
+// 1. adding target="_blank" to external links
+// 2. converting internal links to <router-link>
+
+const indexRE = /(.*)(index|readme).md(#?.*)$/i
+
+module.exports = (md, externalAttrs) => {
+ let hasOpenRouterLink = false
+ let hasOpenExternalLink = false
+
+ md.renderer.rules.link_open = (tokens, idx, options, env, self) => {
+ const token = tokens[idx]
+ const hrefIndex = token.attrIndex('href')
+ if (hrefIndex >= 0) {
+ const link = token.attrs[hrefIndex]
+ const href = link[1]
+ const isExternal = /^https?:/.test(href)
+ const isSourceLink = /(\/|\.md|\.html)(#.*)?$/.test(href)
+ if (isExternal) {
+ Object.entries(externalAttrs).forEach(([key, val]) => {
+ token.attrSet(key, val)
+ })
+ if (/_blank/i.test(externalAttrs['target'])) {
+ hasOpenExternalLink = true
+ }
+ } else if (isSourceLink) {
+ hasOpenRouterLink = true
+ tokens[idx] = toRouterLink(token, link)
+ }
+ }
+ return self.renderToken(tokens, idx, options)
+ }
+
+ function toRouterLink (token, link) {
+ link[0] = 'to'
+ let to = link[1]
+
+ // convert link to filename and export it for existence check
+ const links = md.__data.links || (md.__data.links = [])
+ links.push(to)
+
+ const indexMatch = to.match(indexRE)
+ if (indexMatch) {
+ const [, path, , hash] = indexMatch
+ to = path + hash
+ } else {
+ to = to
+ .replace(/\.md$/, '.html')
+ .replace(/\.md(#.*)$/, '.html$1')
+ }
+
+ // relative path usage.
+ if (!to.startsWith('/')) {
+ to = ensureBeginningDotSlash(to)
+ }
+
+ // markdown-it encodes the uri
+ link[1] = decodeURI(to)
+
+ // export the router links for testing
+ const routerLinks = md.__data.routerLinks || (md.__data.routerLinks = [])
+ routerLinks.push(to)
+
+ return Object.assign({}, token, {
+ tag: 'router-link'
+ })
+ }
+
+ md.renderer.rules.link_close = (tokens, idx, options, env, self) => {
+ const token = tokens[idx]
+ if (hasOpenRouterLink) {
+ token.tag = 'router-link'
+ hasOpenRouterLink = false
+ }
+ if (hasOpenExternalLink) {
+ hasOpenExternalLink = false
+ // add OutBoundLink to the beforeend of this link if it opens in _blank.
+ return '<OutboundLink/>' + self.renderToken(tokens, idx, options)
+ }
+ return self.renderToken(tokens, idx, options)
+ }
+}
+
+const beginningSlashRE = /^\.\//
+
+function ensureBeginningDotSlash (path) {
+ if (beginningSlashRE.test(path)) {
+ return path
+ }
+ return './' + path
+}
diff --git a/node_modules/vuepress/lib/markdown/preWrapper.js b/node_modules/vuepress/lib/markdown/preWrapper.js
new file mode 100644
index 00000000..8f1b1d73
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/preWrapper.js
@@ -0,0 +1,19 @@
+// markdown-it plugin for wrapping <pre> ... </pre>.
+//
+// If your plugin was chained before preWrapper, you can add additional eleemnt directly.
+// If your plugin was chained after preWrapper, you can use these slots:
+// 1. <!--beforebegin-->
+// 2. <!--afterbegin-->
+// 3. <!--beforeend-->
+// 4. <!--afterend-->
+
+module.exports = md => {
+ const fence = md.renderer.rules.fence
+ md.renderer.rules.fence = (...args) => {
+ const [tokens, idx] = args
+ const token = tokens[idx]
+ const rawCode = fence(...args)
+ return `<!--beforebegin--><div class="language-${token.info.trim()} extra-class">` +
+ `<!--afterbegin-->${rawCode}<!--beforeend--></div><!--afterend-->`
+ }
+}
diff --git a/node_modules/vuepress/lib/markdown/slugify.js b/node_modules/vuepress/lib/markdown/slugify.js
new file mode 100644
index 00000000..47a9d6e9
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/slugify.js
@@ -0,0 +1,22 @@
+// string.js slugify drops non ascii chars so we have to
+// use a custom implementation here
+const removeDiacritics = require('diacritics').remove
+// eslint-disable-next-line no-control-regex
+const rControl = /[\u0000-\u001f]/g
+const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'<>,.?/]+/g
+
+module.exports = function slugify (str) {
+ return removeDiacritics(str)
+ // Remove control characters
+ .replace(rControl, '')
+ // Replace special characters
+ .replace(rSpecial, '-')
+ // Remove continous separators
+ .replace(/\-{2,}/g, '-')
+ // Remove prefixing and trailing separtors
+ .replace(/^\-+|\-+$/g, '')
+ // ensure it doesn't start with a number (#121)
+ .replace(/^(\d)/, '_$1')
+ // lowercase
+ .toLowerCase()
+}
diff --git a/node_modules/vuepress/lib/markdown/snippet.js b/node_modules/vuepress/lib/markdown/snippet.js
new file mode 100644
index 00000000..a677e12f
--- /dev/null
+++ b/node_modules/vuepress/lib/markdown/snippet.js
@@ -0,0 +1,43 @@
+const fs = require('fs')
+
+module.exports = function snippet (md, options = {}) {
+ const root = options.root || process.cwd()
+ function parser (state, startLine, endLine, silent) {
+ const CH = '<'.charCodeAt(0)
+ const pos = state.bMarks[startLine] + state.tShift[startLine]
+ const max = state.eMarks[startLine]
+
+ // if it's indented more than 3 spaces, it should be a code block
+ if (state.sCount[startLine] - state.blkIndent >= 4) {
+ return false
+ }
+
+ for (let i = 0; i < 3; ++i) {
+ const ch = state.src.charCodeAt(pos + i)
+ if (ch !== CH || pos + i >= max) return false
+ }
+
+ if (silent) {
+ return true
+ }
+
+ const start = pos + 3
+ const end = state.skipSpacesBack(max, pos)
+ const rawPath = state.src.slice(start, end).trim().replace(/^@/, root)
+ const filename = rawPath.split(/[{:\s]/).shift()
+ const content = fs.existsSync(filename) ? fs.readFileSync(filename).toString() : 'Not found: ' + filename
+ const meta = rawPath.replace(filename, '')
+
+ state.line = startLine + 1
+
+ const token = state.push('fence', 'code', 0)
+ token.info = filename.split('.').pop() + meta
+ token.content = content
+ token.markup = '```'
+ token.map = [startLine, startLine + 1]
+
+ return true
+ }
+
+ md.block.ruler.before('fence', 'snippet', parser)
+}
diff --git a/node_modules/vuepress/lib/prepare/codegen.js b/node_modules/vuepress/lib/prepare/codegen.js
new file mode 100644
index 00000000..52e85355
--- /dev/null
+++ b/node_modules/vuepress/lib/prepare/codegen.js
@@ -0,0 +1,74 @@
+const path = require('path')
+const { fileToComponentName, resolveComponents } = require('./util')
+
+exports.genRoutesFile = async function ({
+ siteData: { pages },
+ sourceDir,
+ pageFiles
+}) {
+ function genRoute ({ path: pagePath, key: componentName }, index) {
+ const file = pageFiles[index]
+ const filePath = path.resolve(sourceDir, file)
+ let code = `
+ {
+ name: ${JSON.stringify(componentName)},
+ path: ${JSON.stringify(pagePath)},
+ component: ThemeLayout,
+ beforeEnter: (to, from, next) => {
+ import(${JSON.stringify(filePath)}).then(comp => {
+ Vue.component(${JSON.stringify(componentName)}, comp.default)
+ next()
+ })
+ }
+ }`
+
+ const dncodedPath = decodeURIComponent(pagePath)
+ if (dncodedPath !== pagePath) {
+ code += `,
+ {
+ path: ${JSON.stringify(dncodedPath)},
+ redirect: ${JSON.stringify(pagePath)}
+ }`
+ }
+
+ if (/\/$/.test(pagePath)) {
+ code += `,
+ {
+ path: ${JSON.stringify(pagePath + 'index.html')},
+ redirect: ${JSON.stringify(pagePath)}
+ }`
+ }
+
+ return code
+ }
+
+ const notFoundRoute = `,
+ {
+ path: '*',
+ component: ThemeNotFound
+ }`
+
+ return (
+ `import ThemeLayout from '@themeLayout'\n` +
+ `import ThemeNotFound from '@themeNotFound'\n` +
+ `import { injectMixins } from '@app/util'\n` +
+ `import rootMixins from '@app/root-mixins'\n\n` +
+ `injectMixins(ThemeLayout, rootMixins)\n` +
+ `injectMixins(ThemeNotFound, rootMixins)\n\n` +
+ `export const routes = [${pages.map(genRoute).join(',')}${notFoundRoute}\n]`
+ )
+}
+
+exports.genComponentRegistrationFile = async function ({ sourceDir }) {
+ function genImport (file) {
+ const name = fileToComponentName(file)
+ const baseDir = path.resolve(sourceDir, '.vuepress/components')
+ const absolutePath = path.resolve(baseDir, file)
+ const code = `Vue.component(${JSON.stringify(name)}, () => import(${JSON.stringify(absolutePath)}))`
+ return code
+ }
+
+ const components = (await resolveComponents(sourceDir)) || []
+ return `import Vue from 'vue'\n` + components.map(genImport).join('\n')
+}
+
diff --git a/node_modules/vuepress/lib/prepare/index.js b/node_modules/vuepress/lib/prepare/index.js
new file mode 100644
index 00000000..7561f791
--- /dev/null
+++ b/node_modules/vuepress/lib/prepare/index.js
@@ -0,0 +1,51 @@
+const path = require('path')
+const fs = require('fs-extra')
+const resolveOptions = require('./resolveOptions')
+const { genRoutesFile, genComponentRegistrationFile } = require('./codegen')
+const { writeTemp, writeEnhanceTemp } = require('./util')
+const logger = require('../util/logger')
+const chalk = require('chalk')
+
+module.exports = async function prepare (sourceDir) {
+ // 1. load options
+ const options = await resolveOptions(sourceDir)
+
+ // 2. generate routes & user components registration code
+ const routesCode = await genRoutesFile(options)
+ const componentCode = await genComponentRegistrationFile(options)
+
+ await writeTemp('routes.js', [
+ componentCode,
+ routesCode
+ ].join('\n'))
+
+ // 3. generate siteData
+ const dataCode = `export const siteData = ${JSON.stringify(options.siteData, null, 2)}`
+ await writeTemp('siteData.js', dataCode)
+
+ // 4. handle user override
+ const overridePath = path.resolve(sourceDir, '.vuepress/override.styl').replace(/[\\]+/g, '/')
+ const hasUserOverride = fs.existsSync(overridePath)
+ await writeTemp('override.styl', hasUserOverride ? `@import(${JSON.stringify(overridePath)})` : ``)
+
+ const stylePath = path.resolve(sourceDir, '.vuepress/style.styl').replace(/[\\]+/g, '/')
+ const hasUserStyle = fs.existsSync(stylePath)
+ await writeTemp('style.styl', hasUserStyle ? `@import(${JSON.stringify(stylePath)})` : ``)
+
+ // Temporary tip, will be removed at next release.
+ if (hasUserOverride && !hasUserStyle) {
+ logger.tip(
+ `${chalk.magenta('override.styl')} has been split into 2 APIs, we recommend you upgrade to continue.\n` +
+ ` See: ${chalk.magenta('https://vuepress.vuejs.org/default-theme-config/#simple-css-override')}`
+ )
+ }
+
+ // 5. handle enhanceApp.js
+ const enhanceAppPath = path.resolve(sourceDir, '.vuepress/enhanceApp.js')
+ await writeEnhanceTemp('enhanceApp.js', enhanceAppPath)
+
+ // 6. handle the theme enhanceApp.js
+ await writeEnhanceTemp('themeEnhanceApp.js', options.themeEnhanceAppPath)
+
+ return options
+}
diff --git a/node_modules/vuepress/lib/prepare/loadConfig.js b/node_modules/vuepress/lib/prepare/loadConfig.js
new file mode 100644
index 00000000..aa913ba0
--- /dev/null
+++ b/node_modules/vuepress/lib/prepare/loadConfig.js
@@ -0,0 +1,56 @@
+const fs = require('fs-extra')
+const path = require('path')
+const yamlParser = require('js-yaml')
+const tomlParser = require('toml')
+
+module.exports = function loadConfig (vuepressDir, bustCache = true) {
+ const configPath = path.resolve(vuepressDir, 'config.js')
+ const configYmlPath = path.resolve(vuepressDir, 'config.yml')
+ const configTomlPath = path.resolve(vuepressDir, 'config.toml')
+
+ if (bustCache) {
+ delete require.cache[configPath]
+ }
+
+ // resolve siteConfig
+ let siteConfig = {}
+ if (fs.existsSync(configYmlPath)) {
+ siteConfig = parseConfig(configYmlPath)
+ } else if (fs.existsSync(configTomlPath)) {
+ siteConfig = parseConfig(configTomlPath)
+ } else if (fs.existsSync(configPath)) {
+ siteConfig = require(configPath)
+ }
+
+ return siteConfig
+}
+
+function parseConfig (file) {
+ const content = fs.readFileSync(file, 'utf-8')
+ const [extension] = /.\w+$/.exec(file)
+ let data
+
+ switch (extension) {
+ case '.yml':
+ case '.yaml':
+ data = yamlParser.safeLoad(content)
+ break
+
+ case '.toml':
+ data = tomlParser.parse(content)
+ // reformat to match config since TOML does not allow different data type
+ // https://github.com/toml-lang/toml#array
+ const format = []
+ if (data.head) {
+ Object.keys(data.head).forEach(meta => {
+ data.head[meta].forEach(values => {
+ format.push([meta, values])
+ })
+ })
+ }
+ data.head = format
+ break
+ }
+
+ return data || {}
+}
diff --git a/node_modules/vuepress/lib/prepare/resolveOptions.js b/node_modules/vuepress/lib/prepare/resolveOptions.js
new file mode 100644
index 00000000..9b97ca8e
--- /dev/null
+++ b/node_modules/vuepress/lib/prepare/resolveOptions.js
@@ -0,0 +1,194 @@
+const fs = require('fs-extra')
+const path = require('path')
+const globby = require('globby')
+const createMarkdown = require('../markdown')
+const loadConfig = require('./loadConfig')
+const { encodePath, fileToPath, sort, getGitLastUpdatedTimeStamp } = require('./util')
+const {
+ inferTitle,
+ extractHeaders,
+ parseFrontmatter
+} = require('../util/index')
+
+module.exports = async function resolveOptions (sourceDir) {
+ const vuepressDir = path.resolve(sourceDir, '.vuepress')
+ const siteConfig = loadConfig(vuepressDir)
+
+ // normalize head tag urls for base
+ const base = siteConfig.base || '/'
+ if (base !== '/' && siteConfig.head) {
+ siteConfig.head.forEach(tag => {
+ const attrs = tag[1]
+ if (attrs) {
+ for (const name in attrs) {
+ if (name === 'src' || name === 'href') {
+ const value = attrs[name]
+ if (value.charAt(0) === '/') {
+ attrs[name] = base + value.slice(1)
+ }
+ }
+ }
+ }
+ })
+ }
+
+ // resolve outDir
+ const outDir = siteConfig.dest
+ ? path.resolve(siteConfig.dest)
+ : path.resolve(sourceDir, '.vuepress/dist')
+
+ // resolve theme
+ const useDefaultTheme = (
+ !siteConfig.theme &&
+ !fs.existsSync(path.resolve(vuepressDir, 'theme'))
+ )
+ const defaultThemePath = path.resolve(__dirname, '../default-theme')
+ let themePath = null
+ let themeLayoutPath = null
+ let themeNotFoundPath = null
+ let themeEnhanceAppPath = null
+
+ if (useDefaultTheme) {
+ // use default theme
+ themePath = defaultThemePath
+ themeLayoutPath = path.resolve(defaultThemePath, 'Layout.vue')
+ themeNotFoundPath = path.resolve(defaultThemePath, 'NotFound.vue')
+ } else {
+ // resolve theme Layout
+ if (siteConfig.theme) {
+ // use external theme
+ try {
+ themeLayoutPath = require.resolve(`vuepress-theme-${siteConfig.theme}/Layout.vue`, {
+ paths: [
+ path.resolve(__dirname, '../../node_modules'),
+ path.resolve(sourceDir)
+ ]
+ })
+ themePath = path.dirname(themeLayoutPath)
+ } catch (e) {
+ throw new Error(`[vuepress] Failed to load custom theme "${
+ siteConfig.theme
+ }". File vuepress-theme-${siteConfig.theme}/Layout.vue does not exist.`)
+ }
+ } else {
+ // use custom theme
+ themePath = path.resolve(vuepressDir, 'theme')
+ themeLayoutPath = path.resolve(themePath, 'Layout.vue')
+ if (!fs.existsSync(themeLayoutPath)) {
+ throw new Error(`[vuepress] Cannot resolve Layout.vue file in .vuepress/theme.`)
+ }
+ }
+
+ // resolve theme NotFound
+ themeNotFoundPath = path.resolve(themePath, 'NotFound.vue')
+ if (!fs.existsSync(themeNotFoundPath)) {
+ themeNotFoundPath = path.resolve(defaultThemePath, 'NotFound.vue')
+ }
+
+ // resolve theme enhanceApp
+ themeEnhanceAppPath = path.resolve(themePath, 'enhanceApp.js')
+ if (!fs.existsSync(themeEnhanceAppPath)) {
+ themeEnhanceAppPath = null
+ }
+ }
+
+ // resolve theme config
+ const themeConfig = siteConfig.themeConfig || {}
+
+ // resolve algolia
+ const isAlgoliaSearch = (
+ themeConfig.algolia ||
+ Object.keys(siteConfig.locales && themeConfig.locales || {})
+ .some(base => themeConfig.locales[base].algolia)
+ )
+
+ // resolve markdown
+ const markdown = createMarkdown(siteConfig)
+
+ // resolve pageFiles
+ const patterns = ['**/*.md', '!.vuepress', '!node_modules']
+ if (siteConfig.dest) {
+ // #654 exclude dest folder when dest dir was set in
+ // sourceDir but not in '.vuepress'
+ const outDirRelative = path.relative(sourceDir, outDir)
+ if (!outDirRelative.includes('..')) {
+ patterns.push('!' + outDirRelative)
+ }
+ }
+ const pageFiles = sort(await globby(patterns, { cwd: sourceDir }))
+
+ // resolve lastUpdated
+ const shouldResolveLastUpdated = (
+ themeConfig.lastUpdated ||
+ Object.keys(siteConfig.locales && themeConfig.locales || {})
+ .some(base => themeConfig.locales[base].lastUpdated)
+ )
+
+ // resolve pagesData
+ const pagesData = await Promise.all(pageFiles.map(async (file) => {
+ const filepath = path.resolve(sourceDir, file)
+ const key = 'v-' + Math.random().toString(16).slice(2)
+ const data = {
+ key,
+ path: encodePath(fileToPath(file))
+ }
+
+ if (shouldResolveLastUpdated) {
+ data.lastUpdated = getGitLastUpdatedTimeStamp(filepath)
+ }
+
+ // extract yaml frontmatter
+ const content = await fs.readFile(filepath, 'utf-8')
+ const frontmatter = parseFrontmatter(content)
+ // infer title
+ const title = inferTitle(frontmatter)
+ if (title) {
+ data.title = title
+ }
+ const headers = extractHeaders(
+ frontmatter.content,
+ ['h2', 'h3'],
+ markdown
+ )
+ if (headers.length) {
+ data.headers = headers
+ }
+ if (Object.keys(frontmatter.data).length) {
+ data.frontmatter = frontmatter.data
+ }
+ if (frontmatter.excerpt) {
+ const { html } = markdown.render(frontmatter.excerpt)
+ data.excerpt = html
+ }
+ return data
+ }))
+
+ // resolve site data
+ const siteData = {
+ title: siteConfig.title || '',
+ description: siteConfig.description || '',
+ base,
+ pages: pagesData,
+ themeConfig,
+ locales: siteConfig.locales
+ }
+
+ const options = {
+ siteConfig,
+ siteData,
+ sourceDir,
+ outDir,
+ publicPath: base,
+ pageFiles,
+ pagesData,
+ themePath,
+ themeLayoutPath,
+ themeNotFoundPath,
+ themeEnhanceAppPath,
+ useDefaultTheme,
+ isAlgoliaSearch,
+ markdown
+ }
+
+ return options
+}
diff --git a/node_modules/vuepress/lib/prepare/util.js b/node_modules/vuepress/lib/prepare/util.js
new file mode 100644
index 00000000..efa96cc9
--- /dev/null
+++ b/node_modules/vuepress/lib/prepare/util.js
@@ -0,0 +1,80 @@
+const path = require('path')
+const spawn = require('cross-spawn')
+const fs = require('fs-extra')
+const globby = require('globby')
+
+const tempPath = path.resolve(__dirname, '../app/.temp')
+fs.ensureDirSync(tempPath)
+
+const tempCache = new Map()
+exports.writeTemp = async function (file, content) {
+ // cache write to avoid hitting the dist if it didn't change
+ const cached = tempCache.get(file)
+ if (cached !== content) {
+ await fs.writeFile(path.join(tempPath, file), content)
+ tempCache.set(file, content)
+ }
+}
+
+exports.writeEnhanceTemp = async function (destName, srcPath) {
+ await exports.writeTemp(
+ destName,
+ fs.existsSync(srcPath)
+ ? `export { default } from ${JSON.stringify(srcPath)}`
+ : `export default function () {}`
+ )
+}
+
+const indexRE = /(^|.*\/)(index|readme)\.md$/i
+const extRE = /\.(vue|md)$/
+
+exports.fileToPath = function (file) {
+ if (exports.isIndexFile(file)) {
+ // README.md -> /
+ // foo/README.md -> /foo/
+ return file.replace(indexRE, '/$1')
+ } else {
+ // foo.md -> /foo.html
+ // foo/bar.md -> /foo/bar.html
+ return `/${file.replace(extRE, '').replace(/\\/g, '/')}.html`
+ }
+}
+
+exports.fileToComponentName = function (file) {
+ let normalizedName = file
+ .replace(/\/|\\/g, '-')
+ .replace(extRE, '')
+ if (exports.isIndexFile(file)) {
+ normalizedName = normalizedName.replace(/readme$/i, 'index')
+ }
+ const pagePrefix = /\.md$/.test(file) ? `page-` : ``
+ return `${pagePrefix}${normalizedName}`
+}
+
+exports.isIndexFile = function (file) {
+ return indexRE.test(file)
+}
+
+exports.resolveComponents = async function (sourceDir) {
+ const componentDir = path.resolve(sourceDir, '.vuepress/components')
+ if (!fs.existsSync(componentDir)) {
+ return
+ }
+ return exports.sort(await globby(['**/*.vue'], { cwd: componentDir }))
+}
+
+exports.sort = function (arr) {
+ return arr.sort((a, b) => {
+ if (a < b) return -1
+ if (a > b) return 1
+ return 0
+ })
+}
+
+exports.encodePath = function (userpath) {
+ return userpath.split('/').map(item => encodeURIComponent(item)).join('/')
+}
+
+exports.getGitLastUpdatedTimeStamp = function (filepath) {
+ return parseInt(spawn.sync('git', ['log', '-1', '--format=%ct', filepath]).stdout.toString('utf-8')) * 1000
+}
diff --git a/node_modules/vuepress/lib/service-worker/skip-waiting.js b/node_modules/vuepress/lib/service-worker/skip-waiting.js
new file mode 100644
index 00000000..54fd8d37
--- /dev/null
+++ b/node_modules/vuepress/lib/service-worker/skip-waiting.js
@@ -0,0 +1,12 @@
+addEventListener('message', event => {
+ const replyPort = event.ports[0]
+ const message = event.data
+ if (replyPort && message && message.type === 'skip-waiting') {
+ event.waitUntil(
+ self.skipWaiting().then(
+ () => replyPort.postMessage({ error: null }),
+ error => replyPort.postMessage({ error })
+ )
+ )
+ }
+})
diff --git a/node_modules/vuepress/lib/util/index.js b/node_modules/vuepress/lib/util/index.js
new file mode 100644
index 00000000..52044a8f
--- /dev/null
+++ b/node_modules/vuepress/lib/util/index.js
@@ -0,0 +1,83 @@
+const { deeplyParseHeaders } = require('./parseHeaders')
+
+exports.normalizeHeadTag = function (tag) {
+ if (typeof tag === 'string') {
+ tag = [tag]
+ }
+ const tagName = tag[0]
+ return {
+ tagName,
+ attributes: tag[1] || {},
+ innerHTML: tag[2] || '',
+ closeTag: !(tagName === 'meta' || tagName === 'link')
+ }
+}
+
+exports.applyUserWebpackConfig = function (userConfig, config, isServer) {
+ const merge = require('webpack-merge')
+ if (typeof userConfig === 'object') {
+ return merge(config, userConfig)
+ }
+ if (typeof userConfig === 'function') {
+ const res = userConfig(config, isServer)
+ if (res && typeof res === 'object') {
+ return merge(config, res)
+ }
+ }
+ return config
+}
+
+exports.inferTitle = function (frontmatter) {
+ if (frontmatter.data.home) {
+ return 'Home'
+ }
+ if (frontmatter.data.title) {
+ return deeplyParseHeaders(frontmatter.data.title)
+ }
+ const match = frontmatter.content.trim().match(/^#+\s+(.*)/m)
+ if (match) {
+ return deeplyParseHeaders(match[1])
+ }
+}
+
+exports.parseFrontmatter = function (content) {
+ const matter = require('gray-matter')
+ const toml = require('toml')
+
+ return matter(content, {
+ excerpt_separator: '<!-- more -->',
+ engines: {
+ toml: toml.parse.bind(toml),
+ excerpt: false
+ }
+ })
+}
+
+const LRU = require('lru-cache')
+const cache = LRU({ max: 1000 })
+
+exports.extractHeaders = function (content, include = [], md) {
+ const key = content + include.join(',')
+ const hit = cache.get(key)
+ if (hit) {
+ return hit
+ }
+
+ const tokens = md.parse(content, {})
+
+ const res = []
+ tokens.forEach((t, i) => {
+ if (t.type === 'heading_open' && include.includes(t.tag)) {
+ const title = tokens[i + 1].content
+ const slug = t.attrs.find(([name]) => name === 'id')[1]
+ res.push({
+ level: parseInt(t.tag.slice(1), 10),
+ title: deeplyParseHeaders(title),
+ slug: slug || md.slugify(title)
+ })
+ }
+ })
+
+ cache.set(key, res)
+ return res
+}
diff --git a/node_modules/vuepress/lib/util/logger.js b/node_modules/vuepress/lib/util/logger.js
new file mode 100644
index 00000000..84e07e86
--- /dev/null
+++ b/node_modules/vuepress/lib/util/logger.js
@@ -0,0 +1,47 @@
+const chalk = require('chalk')
+
+const logger = {}
+
+const logTypes = {
+ success: {
+ color: 'green',
+ label: 'DONE'
+ },
+ error: {
+ color: 'red',
+ label: 'FAIL'
+ },
+ warn: {
+ color: 'yellow',
+ label: 'WARN'
+ },
+ tip: {
+ color: 'cyan',
+ label: 'TIP'
+ },
+ wait: {
+ color: 'blue',
+ label: 'WAIT'
+ }
+}
+
+const getLoggerFn = (color, label) => (msg, log = true) => {
+ let newLine = false
+ if (msg.startsWith('\n')) {
+ if (log) msg = msg.slice(1)
+ newLine = true
+ }
+ msg = chalk.reset.inverse.bold[color](` ${label} `) + ' ' + msg
+ if (log) {
+ console.log(newLine ? '\n' + msg : msg)
+ } else {
+ return msg
+ }
+}
+
+for (const type in logTypes) {
+ const { color, label } = logTypes[type]
+ logger[type] = getLoggerFn(color, label)
+}
+
+module.exports = logger
diff --git a/node_modules/vuepress/lib/util/parseHeaders.js b/node_modules/vuepress/lib/util/parseHeaders.js
new file mode 100644
index 00000000..2c9fe641
--- /dev/null
+++ b/node_modules/vuepress/lib/util/parseHeaders.js
@@ -0,0 +1,56 @@
+// Since VuePress needs to extract the header from the markdown source
+// file and display it in the sidebar or title (#238), this file simply
+// removes some unnecessary elements to make header displays well at
+// sidebar or title.
+//
+// But header's parsing in the markdown content is done by the markdown
+// loader based on markdown-it. markdown-it parser will will always keep
+// HTML in headers, so in VuePress, after being parsed by the markdiwn
+// loader, the raw HTML in headers will finally be parsed by Vue-loader.
+// so that we can write HTML/Vue in the header. One exception is the HTML
+// wrapped by <code>(markdown token: '`') tag.
+
+const { compose } = require('./shared')
+
+const parseEmojis = str => {
+ const emojiData = require('markdown-it-emoji/lib/data/full.json')
+ return String(str).replace(/:(.+?):/g, (placeholder, key) => emojiData[key] || placeholder)
+}
+
+const unescapeHtml = html => String(html)
+ .replace(/&quot;/g, '"')
+ .replace(/&#39;/g, '\'')
+ .replace(/&#x3A;/g, ':')
+ .replace(/&lt;/g, '<')
+ .replace(/&gt;/g, '>')
+
+const removeMarkdownTokens = str => String(str)
+ .replace(/\[(.*)\]\(.*\)/, '$1') // []()
+ .replace(/(`|\*{1,3}|_)(.*?[^\\])\1/g, '$2') // `{t}` | *{t}* | **{t}** | ***{t}*** | _{t}_
+ .replace(/(\\)(\*|_|`|\!)/g, '$2') // remove escape char '\'
+
+const trim = str => str.trim()
+
+// This method remove the raw HTML but reserve the HTML wrapped by `<code>`.
+// e.g.
+// Input: "<a> b", Output: "b"
+// Input: "`<a>` b", Output: "`<a>` b"
+exports.removeNonCodeWrappedHTML = (str) => {
+ return String(str).replace(/(^|[^><`])<.*>([^><`]|$)/g, '$1$2')
+}
+
+// Unescape html, parse emojis and remove some md tokens.
+exports.parseHeaders = compose(
+ unescapeHtml,
+ parseEmojis,
+ removeMarkdownTokens,
+ trim
+)
+
+// Also clean the html that isn't wrapped by code.
+// Because we want to support using VUE components in headers.
+// e.g. https://vuepress.vuejs.org/guide/using-vue.html#badge
+exports.deeplyParseHeaders = compose(
+ exports.removeNonCodeWrappedHTML,
+ exports.parseHeaders,
+)
diff --git a/node_modules/vuepress/lib/util/shared.js b/node_modules/vuepress/lib/util/shared.js
new file mode 100644
index 00000000..023f63bd
--- /dev/null
+++ b/node_modules/vuepress/lib/util/shared.js
@@ -0,0 +1,7 @@
+exports.compose = (...processors) => {
+ if (processors.length === 0) return input => input
+ if (processors.length === 1) return processors[0]
+ return processors.reduce((prev, next) => {
+ return (...args) => next(prev(...args))
+ })
+}
diff --git a/node_modules/vuepress/lib/webpack/ClientPlugin.js b/node_modules/vuepress/lib/webpack/ClientPlugin.js
new file mode 100644
index 00000000..82028475
--- /dev/null
+++ b/node_modules/vuepress/lib/webpack/ClientPlugin.js
@@ -0,0 +1,87 @@
+// Temporarily hacked dev build
+
+var isJS = function (file) { return /\.js(\?[^.]+)?$/.test(file) }
+
+var isCSS = function (file) { return /\.css(\?[^.]+)?$/.test(file) }
+
+var onEmit = function (compiler, name, hook) {
+ if (compiler.hooks) {
+ // Webpack >= 4.0.0
+ compiler.hooks.emit.tapAsync(name, hook)
+ } else {
+ // Webpack < 4.0.0
+ compiler.plugin('emit', hook)
+ }
+}
+
+var hash = require('hash-sum')
+var uniq = require('lodash.uniq')
+var VueSSRClientPlugin = function VueSSRClientPlugin (options) {
+ if (options === void 0) options = {}
+
+ this.options = Object.assign({
+ filename: 'vue-ssr-client-manifest.json'
+ }, options)
+}
+
+VueSSRClientPlugin.prototype.apply = function apply (compiler) {
+ var this$1 = this
+
+ onEmit(compiler, 'vue-client-plugin', function (compilation, cb) {
+ var stats = compilation.getStats().toJson()
+
+ var allFiles = uniq(stats.assets
+ .map(function (a) { return a.name }))
+ // Avoid preloading / injecting the style chunk
+ .filter(file => !/styles\.\w{8}\.js$/.test(file))
+
+ var initialFiles = uniq(Object.keys(stats.entrypoints)
+ .map(function (name) { return stats.entrypoints[name].assets })
+ .reduce(function (assets, all) { return all.concat(assets) }, [])
+ .filter(function (file) { return isJS(file) || isCSS(file) }))
+ // Avoid preloading / injecting the style chunk
+ .filter(file => !/styles\.\w{8}\.js$/.test(file))
+
+ var asyncFiles = allFiles
+ .filter(function (file) { return isJS(file) || isCSS(file) })
+ .filter(function (file) { return initialFiles.indexOf(file) < 0 })
+
+ var manifest = {
+ publicPath: stats.publicPath,
+ all: allFiles,
+ initial: initialFiles,
+ async: asyncFiles,
+ modules: { /* [identifier: string]: Array<index: number> */ }
+ }
+
+ var assetModules = stats.modules.filter(function (m) { return m.assets.length })
+ var fileToIndex = function (file) { return manifest.all.indexOf(file) }
+ stats.modules.forEach(function (m) {
+ // ignore modules duplicated in multiple chunks
+ if (m.chunks.length === 1) {
+ var cid = m.chunks[0]
+ var chunk = stats.chunks.find(function (c) { return c.id === cid })
+ if (!chunk || !chunk.files) {
+ return
+ }
+ var id = m.identifier.replace(/\s\w+$/, '') // remove appended hash
+ var files = manifest.modules[hash(id)] = chunk.files.map(fileToIndex)
+ // find all asset modules associated with the same chunk
+ assetModules.forEach(function (m) {
+ if (m.chunks.some(function (id) { return id === cid })) {
+ files.push.apply(files, m.assets.map(fileToIndex))
+ }
+ })
+ }
+ })
+
+ var json = JSON.stringify(manifest, null, 2)
+ compilation.assets[this$1.options.filename] = {
+ source: function () { return json },
+ size: function () { return json.length }
+ }
+ cb()
+ })
+}
+
+module.exports = VueSSRClientPlugin
diff --git a/node_modules/vuepress/lib/webpack/DevLogPlugin.js b/node_modules/vuepress/lib/webpack/DevLogPlugin.js
new file mode 100644
index 00000000..8fd18d4a
--- /dev/null
+++ b/node_modules/vuepress/lib/webpack/DevLogPlugin.js
@@ -0,0 +1,38 @@
+const chalk = require('chalk')
+const logger = require('../util/logger')
+
+module.exports = class DevLogPlugin {
+ constructor (options) {
+ this.options = options
+ }
+
+ apply (compiler) {
+ let isFirst = true
+ compiler.hooks.done.tap('vuepress-log', stats => {
+ clearScreen()
+
+ const { displayHost, port, publicPath } = this.options
+ const time = new Date().toTimeString().match(/^[\d:]+/)[0]
+ const displayUrl = `http://${displayHost}:${port}${publicPath}`
+
+ logger.success(
+ `\n${chalk.gray(`[${time}]`)} Build ${chalk.italic(stats.hash.slice(0, 6))} ` +
+ `finished in ${stats.endTime - stats.startTime} ms! ` +
+ (
+ isFirst
+ ? ''
+ : `${chalk.gray(`(${displayUrl})`)}`
+ )
+ )
+ if (isFirst) {
+ isFirst = false
+ console.log(`\n${chalk.gray('>')} VuePress dev server listening at ${chalk.cyan(displayUrl)}`)
+ }
+ })
+ compiler.hooks.invalid.tap('vuepress-log', clearScreen)
+ }
+}
+
+function clearScreen () {
+ process.stdout.write('\x1Bc')
+}
diff --git a/node_modules/vuepress/lib/webpack/HeadPlugin.js b/node_modules/vuepress/lib/webpack/HeadPlugin.js
new file mode 100644
index 00000000..2ccb46e0
--- /dev/null
+++ b/node_modules/vuepress/lib/webpack/HeadPlugin.js
@@ -0,0 +1,22 @@
+const { normalizeHeadTag } = require('../util')
+
+module.exports = class SiteDataPlugin {
+ constructor ({ tags }) {
+ this.tags = tags
+ }
+
+ apply (compiler) {
+ compiler.hooks.compilation.tap('vuepress-site-data', compilation => {
+ compilation.hooks.htmlWebpackPluginAlterAssetTags.tapAsync('vuepress-site-data', (data, cb) => {
+ try {
+ this.tags.forEach(tag => {
+ data.head.push(normalizeHeadTag(tag))
+ })
+ } catch (e) {
+ return cb(e)
+ }
+ cb(null, data)
+ })
+ })
+ }
+}
diff --git a/node_modules/vuepress/lib/webpack/createBaseConfig.js b/node_modules/vuepress/lib/webpack/createBaseConfig.js
new file mode 100644
index 00000000..dcf7fab3
--- /dev/null
+++ b/node_modules/vuepress/lib/webpack/createBaseConfig.js
@@ -0,0 +1,315 @@
+const path = require('path')
+
+module.exports = function createBaseConfig ({
+ siteConfig,
+ siteData,
+ sourceDir,
+ outDir,
+ publicPath,
+ themePath,
+ themeLayoutPath,
+ themeNotFoundPath,
+ isAlgoliaSearch,
+ markdown
+}, { debug } = {}, isServer) {
+ const Config = require('webpack-chain')
+ const { VueLoaderPlugin } = require('vue-loader')
+ const CSSExtractPlugin = require('mini-css-extract-plugin')
+
+ const isProd = process.env.NODE_ENV === 'production'
+ const inlineLimit = 10000
+
+ const config = new Config()
+
+ config
+ .mode(isProd && !debug ? 'production' : 'development')
+ .output
+ .path(outDir)
+ .filename(isProd ? 'assets/js/[name].[chunkhash:8].js' : 'assets/js/[name].js')
+ .publicPath(isProd ? publicPath : '/')
+
+ if (debug) {
+ config.devtool('source-map')
+ } else if (!isProd) {
+ config.devtool('cheap-module-eval-source-map')
+ }
+
+ config.resolve
+ .set('symlinks', true)
+ .alias
+ .set('@theme', themePath)
+ .set('@themeLayout', themeLayoutPath)
+ .set('@themeNotFound', themeNotFoundPath)
+ .set('@source', sourceDir)
+ .set('@app', path.resolve(__dirname, '../app'))
+ .set('@temp', path.resolve(__dirname, '../app/.temp'))
+ .set('@default-theme', path.resolve(__dirname, '../default-theme'))
+ .set('@AlgoliaSearchBox', isAlgoliaSearch
+ ? path.resolve(__dirname, '../default-theme/AlgoliaSearchBox.vue')
+ : path.resolve(__dirname, './noopModule.js'))
+ .end()
+ .extensions
+ .merge(['.js', '.jsx', '.vue', '.json', '.styl'])
+ .end()
+ .modules
+ // prioritize our own
+ .add(path.resolve(__dirname, '../../node_modules'))
+ .add(path.resolve(__dirname, '../../../'))
+ .add('node_modules')
+
+ // Load extra root mixins on demand.
+ const { activeHeaderLinks = true } = siteData.themeConfig
+ const rootMixinsLoadingConfig = { activeHeaderLinks }
+ for (const mixinName in rootMixinsLoadingConfig) {
+ const enabled = rootMixinsLoadingConfig[mixinName]
+ config.resolve
+ .alias.set(`@${mixinName}`, enabled
+ ? path.resolve(__dirname, `../app/root-mixins/${mixinName}.js`)
+ : path.resolve(__dirname, './noopModule.js')
+ )
+ }
+
+ config.resolveLoader
+ .set('symlinks', true)
+ .modules
+ // prioritize our own
+ .add(path.resolve(__dirname, '../../node_modules'))
+ .add(path.resolve(__dirname, '../../../'))
+ .add('node_modules')
+
+ config.module
+ .noParse(/^(vue|vue-router|vuex|vuex-router-sync)$/)
+
+ const cacheDirectory = path.resolve(__dirname, '../../node_modules/.cache/vuepress')
+ const cacheIdentifier = JSON.stringify({
+ vuepress: require('../../package.json').version,
+ 'cache-loader': require('cache-loader').version,
+ 'vue-loader': require('vue-loader').version,
+ isProd,
+ isServer,
+ config: (
+ (siteConfig.markdown ? JSON.stringify(siteConfig.markdown) : '') +
+ (siteConfig.chainWebpack || '').toString() +
+ (siteConfig.configureWebpack || '').toString()
+ )
+ })
+
+ function applyVuePipeline (rule) {
+ rule
+ .use('cache-loader')
+ .loader('cache-loader')
+ .options({
+ cacheDirectory,
+ cacheIdentifier
+ })
+
+ rule
+ .use('vue-loader')
+ .loader('vue-loader')
+ .options({
+ compilerOptions: {
+ preserveWhitespace: true
+ },
+ cacheDirectory,
+ cacheIdentifier
+ })
+ }
+
+ const vueRule = config.module
+ .rule('vue')
+ .test(/\.vue$/)
+
+ applyVuePipeline(vueRule)
+
+ const mdRule = config.module
+ .rule('markdown')
+ .test(/\.md$/)
+
+ applyVuePipeline(mdRule)
+
+ mdRule
+ .use('markdown-loader')
+ .loader(require.resolve('./markdownLoader'))
+ .options({ sourceDir, markdown })
+
+ config.module
+ .rule('pug')
+ .test(/\.pug$/)
+ .use('pug-plain-loader')
+ .loader('pug-plain-loader')
+ .end()
+
+ if (!siteConfig.evergreen) {
+ const libDir = path.join(__dirname, '..')
+ config.module
+ .rule('js')
+ .test(/\.js$/)
+ .exclude.add(filepath => {
+ // Always transpile lib directory
+ if (filepath.startsWith(libDir)) {
+ return false
+ }
+ // always transpile js in vue files
+ if (/\.vue\.js$/.test(filepath)) {
+ return false
+ }
+ // Don't transpile node_modules
+ return /node_modules/.test(filepath)
+ }).end()
+ .use('cache-loader')
+ .loader('cache-loader')
+ .options({
+ cacheDirectory,
+ cacheIdentifier
+ })
+ .end()
+ .use('babel-loader')
+ .loader('babel-loader')
+ .options({
+ // do not pick local project babel config (.babelrc)
+ babelrc: false,
+ // do not pick local project babel config (babel.config.js)
+ // ref: http://babeljs.io/docs/en/config-files
+ configFile: false,
+ presets: [
+ require.resolve('@vue/babel-preset-app')
+ ]
+ })
+ }
+
+ config.module
+ .rule('images')
+ .test(/\.(png|jpe?g|gif)(\?.*)?$/)
+ .use('url-loader')
+ .loader('url-loader')
+ .options({
+ limit: inlineLimit,
+ name: `assets/img/[name].[hash:8].[ext]`
+ })
+
+ // do not base64-inline SVGs.
+ // https://github.com/facebookincubator/create-react-app/pull/1180
+ config.module
+ .rule('svg')
+ .test(/\.(svg)(\?.*)?$/)
+ .use('file-loader')
+ .loader('file-loader')
+ .options({
+ name: `assets/img/[name].[hash:8].[ext]`
+ })
+
+ config.module
+ .rule('media')
+ .test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/)
+ .use('url-loader')
+ .loader('url-loader')
+ .options({
+ limit: inlineLimit,
+ name: `assets/media/[name].[hash:8].[ext]`
+ })
+
+ config.module
+ .rule('fonts')
+ .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i)
+ .use('url-loader')
+ .loader('url-loader')
+ .options({
+ limit: inlineLimit,
+ name: `assets/fonts/[name].[hash:8].[ext]`
+ })
+
+ function createCSSRule (lang, test, loader, options) {
+ const baseRule = config.module.rule(lang).test(test)
+ const modulesRule = baseRule.oneOf('modules').resourceQuery(/module/)
+ const normalRule = baseRule.oneOf('normal')
+
+ applyLoaders(modulesRule, true)
+ applyLoaders(normalRule, false)
+
+ function applyLoaders (rule, modules) {
+ if (!isServer) {
+ if (isProd) {
+ rule.use('extract-css-loader').loader(CSSExtractPlugin.loader)
+ } else {
+ rule.use('vue-style-loader').loader('vue-style-loader')
+ }
+ }
+
+ rule.use('css-loader')
+ .loader(isServer ? 'css-loader/locals' : 'css-loader')
+ .options({
+ modules,
+ localIdentName: `[local]_[hash:base64:8]`,
+ importLoaders: 1,
+ sourceMap: !isProd
+ })
+
+ rule.use('postcss-loader').loader('postcss-loader').options(Object.assign({
+ plugins: [require('autoprefixer')],
+ sourceMap: !isProd
+ }, siteConfig.postcss))
+
+ if (loader) {
+ rule.use(loader).loader(loader).options(options)
+ }
+ }
+ }
+
+ createCSSRule('css', /\.css$/)
+ createCSSRule('postcss', /\.p(ost)?css$/)
+ createCSSRule('scss', /\.scss$/, 'sass-loader', siteConfig.scss)
+ createCSSRule('sass', /\.sass$/, 'sass-loader', Object.assign({ indentedSyntax: true }, siteConfig.sass))
+ createCSSRule('less', /\.less$/, 'less-loader', siteConfig.less)
+ createCSSRule('stylus', /\.styl(us)?$/, 'stylus-loader', Object.assign({
+ preferPathResolver: 'webpack'
+ }, siteConfig.stylus))
+
+ config
+ .plugin('vue-loader')
+ .use(VueLoaderPlugin)
+
+ if (isProd && !isServer) {
+ config
+ .plugin('extract-css')
+ .use(CSSExtractPlugin, [{
+ filename: 'assets/css/styles.[chunkhash:8].css'
+ }])
+
+ // ensure all css are extracted together.
+ // since most of the CSS will be from the theme and very little
+ // CSS will be from async chunks
+ config.optimization.splitChunks({
+ cacheGroups: {
+ styles: {
+ name: 'styles',
+ // necessary to ensure async chunks are also extracted
+ test: m => /css-extract/.test(m.type),
+ chunks: 'all',
+ enforce: true
+ }
+ }
+ })
+ }
+
+ // inject constants
+ config
+ .plugin('injections')
+ .use(require('webpack/lib/DefinePlugin'), [{
+ BASE_URL: JSON.stringify(siteConfig.base || '/'),
+ GA_ID: siteConfig.ga ? JSON.stringify(siteConfig.ga) : false,
+ SW_ENABLED: !!siteConfig.serviceWorker,
+ VUEPRESS_VERSION: JSON.stringify(require('../../package.json').version),
+ LAST_COMMIT_HASH: JSON.stringify(getLastCommitHash())
+ }])
+
+ return config
+}
+
+function getLastCommitHash () {
+ const spawn = require('cross-spawn')
+ let hash
+ try {
+ hash = spawn.sync('git', ['log', '-1', '--format=%h']).stdout.toString('utf-8').trim()
+ } catch (error) {}
+ return hash
+}
diff --git a/node_modules/vuepress/lib/webpack/createClientConfig.js b/node_modules/vuepress/lib/webpack/createClientConfig.js
new file mode 100644
index 00000000..8c276633
--- /dev/null
+++ b/node_modules/vuepress/lib/webpack/createClientConfig.js
@@ -0,0 +1,69 @@
+module.exports = function createClientConfig (options, cliOptions) {
+ const path = require('path')
+ const WebpackBar = require('webpackbar')
+ const createBaseConfig = require('./createBaseConfig')
+
+ const config = createBaseConfig(options, cliOptions)
+
+ config
+ .entry('app')
+ .add(path.resolve(__dirname, '../app/clientEntry.js'))
+
+ config.node
+ .merge({
+ // prevent webpack from injecting useless setImmediate polyfill because Vue
+ // source contains it (although only uses it if it's native).
+ setImmediate: false,
+ global: false,
+ process: false,
+ // prevent webpack from injecting mocks to Node native modules
+ // that does not make sense for the client
+ dgram: 'empty',
+ fs: 'empty',
+ net: 'empty',
+ tls: 'empty',
+ child_process: 'empty'
+ })
+
+ // generate client manifest only during build
+ if (process.env.NODE_ENV === 'production') {
+ // This is a temp build of vue-server-renderer/client-plugin.
+ // TODO Switch back to original after problems are resolved.
+ // Fixes two things:
+ // 1. Include CSS in preload files
+ // 2. filter out useless styles.xxxxx.js chunk from mini-css-extract-plugin
+ // https://github.com/webpack-contrib/mini-css-extract-plugin/issues/85
+ config
+ .plugin('ssr-client')
+ .use(require('./ClientPlugin'), [{
+ filename: 'manifest/client.json'
+ }])
+
+ config
+ .plugin('optimize-css')
+ .use(require('optimize-css-assets-webpack-plugin'), [{
+ canPrint: false,
+ cssProcessorOptions: {
+ safe: true,
+ autoprefixer: { disable: true },
+ mergeLonghand: false
+ }
+ }])
+ }
+
+ if (!cliOptions.debug) {
+ config
+ .plugin('bar')
+ .use(WebpackBar, [{
+ name: 'Client',
+ color: '#41b883',
+ compiledIn: false
+ }])
+ }
+
+ if (options.siteConfig.chainWebpack) {
+ options.siteConfig.chainWebpack(config, false /* isServer */)
+ }
+
+ return config
+}
diff --git a/node_modules/vuepress/lib/webpack/createServerConfig.js b/node_modules/vuepress/lib/webpack/createServerConfig.js
new file mode 100644
index 00000000..e9f09835
--- /dev/null
+++ b/node_modules/vuepress/lib/webpack/createServerConfig.js
@@ -0,0 +1,58 @@
+module.exports = function createServerConfig (options, cliOptions) {
+ const fs = require('fs')
+ const path = require('path')
+ const WebpackBar = require('webpackbar')
+ const createBaseConfig = require('./createBaseConfig')
+ const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')
+ const CopyPlugin = require('copy-webpack-plugin')
+
+ const config = createBaseConfig(options, cliOptions, true /* isServer */)
+ const { sourceDir, outDir } = options
+
+ config
+ .target('node')
+ .externals([/^vue|vue-router$/])
+ .devtool('source-map')
+
+ // no need to minimize server build
+ config.optimization.minimize(false)
+
+ config
+ .entry('app')
+ .add(path.resolve(__dirname, '../app/serverEntry.js'))
+
+ config.output
+ .filename('server-bundle.js')
+ .libraryTarget('commonjs2')
+
+ config
+ .plugin('ssr-server')
+ .use(VueSSRServerPlugin, [{
+ filename: 'manifest/server.json'
+ }])
+
+ const publicDir = path.resolve(sourceDir, '.vuepress/public')
+ if (fs.existsSync(publicDir)) {
+ config
+ .plugin('copy')
+ .use(CopyPlugin, [[
+ { from: publicDir, to: outDir }
+ ]])
+ }
+
+ if (!cliOptions.debug) {
+ config
+ .plugin('bar')
+ .use(WebpackBar, [{
+ name: 'Server',
+ color: 'blue',
+ compiledIn: false
+ }])
+ }
+
+ if (options.siteConfig.chainWebpack) {
+ options.siteConfig.chainWebpack(config, true /* isServer */)
+ }
+
+ return config
+}
diff --git a/node_modules/vuepress/lib/webpack/markdownLoader.js b/node_modules/vuepress/lib/webpack/markdownLoader.js
new file mode 100644
index 00000000..3c49b747
--- /dev/null
+++ b/node_modules/vuepress/lib/webpack/markdownLoader.js
@@ -0,0 +1,101 @@
+const fs = require('fs')
+const path = require('path')
+const hash = require('hash-sum')
+const { EventEmitter } = require('events')
+const { getOptions } = require('loader-utils')
+const { inferTitle, extractHeaders, parseFrontmatter } = require('../util')
+const LRU = require('lru-cache')
+
+const cache = LRU({ max: 1000 })
+const devCache = LRU({ max: 1000 })
+
+module.exports = function (src) {
+ const isProd = process.env.NODE_ENV === 'production'
+ const isServer = this.target === 'node'
+ const { markdown, sourceDir } = getOptions(this)
+
+ // we implement a manual cache here because this loader is chained before
+ // vue-loader, and will be applied on the same file multiple times when
+ // selecting the individual blocks.
+ const file = this.resourcePath
+ const key = hash(file + src)
+ const cached = cache.get(key)
+ if (cached && (isProd || /\?vue/.test(this.resourceQuery))) {
+ return cached
+ }
+
+ const frontmatter = parseFrontmatter(src)
+ const content = frontmatter.content
+
+ if (!isProd && !isServer) {
+ const inferredTitle = inferTitle(frontmatter)
+ const headers = extractHeaders(content, ['h2', 'h3'], markdown)
+ delete frontmatter.content
+
+ // diff frontmatter and title, since they are not going to be part of the
+ // returned component, changes in frontmatter do not trigger proper updates
+ const cachedData = devCache.get(file)
+ if (cachedData && (
+ cachedData.inferredTitle !== inferredTitle ||
+ JSON.stringify(cachedData.frontmatter) !== JSON.stringify(frontmatter) ||
+ headersChanged(cachedData.headers, headers)
+ )) {
+ // frontmatter changed... need to do a full reload
+ module.exports.frontmatterEmitter.emit('update')
+ }
+
+ devCache.set(file, {
+ headers,
+ frontmatter,
+ inferredTitle
+ })
+ }
+
+ // the render method has been augmented to allow plugins to
+ // register data during render
+ const { html, data: { hoistedTags, links }} = markdown.render(content)
+
+ // check if relative links are valid
+ links && links.forEach(link => {
+ link = decodeURIComponent(link)
+ const shortname = link
+ .replace(/#.*$/, '')
+ .replace(/\.html$/, '.md')
+ const filename = shortname
+ .replace(/\/$/, '/README.md')
+ .replace(/^\//, sourceDir + '/')
+ const altname = shortname
+ .replace(/\/$/, '/index.md')
+ .replace(/^\//, sourceDir + '/')
+ const dir = path.dirname(this.resourcePath)
+ const file = path.resolve(dir, filename)
+ const altfile = altname !== filename ? path.resolve(dir, altname) : null
+ if (!fs.existsSync(file) && (!altfile || !fs.existsSync(altfile))) {
+ this.emitWarning(
+ new Error(
+ `\nFile for relative link "${link}" does not exist.\n` +
+ `(Resolved file: ${file})\n`
+ )
+ )
+ }
+ })
+
+ const res = (
+ `<template>\n` +
+ `<div class="content">${html}</div>\n` +
+ `</template>\n` +
+ (hoistedTags || []).join('\n')
+ )
+ cache.set(key, res)
+ return res
+}
+
+function headersChanged (a, b) {
+ if (a.length !== b.length) return true
+ return a.some((h, i) => (
+ h.title !== b[i].title ||
+ h.level !== b[i].level
+ ))
+}
+
+module.exports.frontmatterEmitter = new EventEmitter()
diff --git a/node_modules/vuepress/lib/webpack/noopModule.js b/node_modules/vuepress/lib/webpack/noopModule.js
new file mode 100644
index 00000000..b1c6ea43
--- /dev/null
+++ b/node_modules/vuepress/lib/webpack/noopModule.js
@@ -0,0 +1 @@
+export default {}