aboutsummaryrefslogtreecommitdiff
path: root/doc/docs
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2021-04-19 23:41:33 +0800
committerLi Jin <dragon-fly@qq.com>2021-04-19 23:41:33 +0800
commit5d3b07801456d16dcc2c75dcccd48d508a6b60cc (patch)
tree2df1a154bf58d93f2475df02afbd15f1a8ba2963 /doc/docs
parentea82666506b57d6e905b7f2e5fe78498fe5a7abd (diff)
downloadyuescript-5d3b07801456d16dcc2c75dcccd48d508a6b60cc.tar.gz
yuescript-5d3b07801456d16dcc2c75dcccd48d508a6b60cc.tar.bz2
yuescript-5d3b07801456d16dcc2c75dcccd48d508a6b60cc.zip
first commit for Yuescript document site.
Diffstat (limited to 'doc/docs')
-rwxr-xr-xdoc/docs/.vuepress/components/CompilerModal.vue32
-rwxr-xr-xdoc/docs/.vuepress/components/YueCompiler.vue383
-rwxr-xr-xdoc/docs/.vuepress/components/YueDisplay.vue49
-rwxr-xr-xdoc/docs/.vuepress/config.js77
-rwxr-xr-xdoc/docs/.vuepress/enhanceApp.js14
-rw-r--r--doc/docs/.vuepress/public/image/yuescript.svg53
-rwxr-xr-xdoc/docs/.vuepress/styles/index.styl9
-rwxr-xr-xdoc/docs/.vuepress/styles/palette.styl12
-rw-r--r--doc/docs/.vuepress/theme/LICENSE21
-rw-r--r--doc/docs/.vuepress/theme/README.md11
-rw-r--r--doc/docs/.vuepress/theme/components/AlgoliaSearchBox.vue172
-rw-r--r--doc/docs/.vuepress/theme/components/DropdownLink.vue252
-rw-r--r--doc/docs/.vuepress/theme/components/DropdownTransition.vue33
-rw-r--r--doc/docs/.vuepress/theme/components/Home.vue175
-rw-r--r--doc/docs/.vuepress/theme/components/NavLink.vue90
-rw-r--r--doc/docs/.vuepress/theme/components/NavLinks.vue156
-rw-r--r--doc/docs/.vuepress/theme/components/Navbar.vue140
-rw-r--r--doc/docs/.vuepress/theme/components/Page.vue31
-rw-r--r--doc/docs/.vuepress/theme/components/PageEdit.vue155
-rw-r--r--doc/docs/.vuepress/theme/components/PageNav.vue163
-rw-r--r--doc/docs/.vuepress/theme/components/Sidebar.vue64
-rw-r--r--doc/docs/.vuepress/theme/components/SidebarButton.vue40
-rw-r--r--doc/docs/.vuepress/theme/components/SidebarGroup.vue141
-rw-r--r--doc/docs/.vuepress/theme/components/SidebarLink.vue133
-rw-r--r--doc/docs/.vuepress/theme/components/SidebarLinks.vue106
-rw-r--r--doc/docs/.vuepress/theme/global-components/Badge.vue44
-rw-r--r--doc/docs/.vuepress/theme/global-components/CodeBlock.vue41
-rw-r--r--doc/docs/.vuepress/theme/global-components/CodeGroup.vue120
-rw-r--r--doc/docs/.vuepress/theme/index.js59
-rw-r--r--doc/docs/.vuepress/theme/layouts/404.vue30
-rw-r--r--doc/docs/.vuepress/theme/layouts/Layout.vue151
-rw-r--r--doc/docs/.vuepress/theme/noopModule.js1
-rw-r--r--doc/docs/.vuepress/theme/package.json44
-rw-r--r--doc/docs/.vuepress/theme/styles/arrow.styl22
-rw-r--r--doc/docs/.vuepress/theme/styles/code.styl176
-rw-r--r--doc/docs/.vuepress/theme/styles/config.styl1
-rw-r--r--doc/docs/.vuepress/theme/styles/custom-blocks.styl44
-rw-r--r--doc/docs/.vuepress/theme/styles/index.styl202
-rw-r--r--doc/docs/.vuepress/theme/styles/mobile.styl37
-rw-r--r--doc/docs/.vuepress/theme/styles/toc.styl3
-rw-r--r--doc/docs/.vuepress/theme/styles/wrapper.styl9
-rw-r--r--doc/docs/.vuepress/theme/util/index.js244
-rwxr-xr-xdoc/docs/README.md8
-rwxr-xr-xdoc/docs/doc/README.md594
-rwxr-xr-xdoc/docs/try/README.md6
45 files changed, 4348 insertions, 0 deletions
diff --git a/doc/docs/.vuepress/components/CompilerModal.vue b/doc/docs/.vuepress/components/CompilerModal.vue
new file mode 100755
index 0000000..65ae9b0
--- /dev/null
+++ b/doc/docs/.vuepress/components/CompilerModal.vue
@@ -0,0 +1,32 @@
1<template>
2 <modal name="compiler" @before-open="prepare()" height="auto" width="80%" scrollable>
3 <yue-compiler :text="content" compileronly displayonly/>
4 </modal>
5</template>
6
7<script>
8 import Vue from 'vue';
9 import VModal from 'vue-js-modal/dist/ssr.nocss';
10 import 'vue-js-modal/dist/styles.css';
11 Vue.use(VModal);
12 import YueCompiler from './YueCompiler.vue';
13
14 export default {
15 components: {
16 YueCompiler,
17 },
18 mounted () {
19 },
20 data() {
21 return {
22 content: "",
23 };
24 },
25 methods: {
26 prepare() {
27 this.$data.content = window.yueCodes;
28 },
29 },
30 }
31</script>
32
diff --git a/doc/docs/.vuepress/components/YueCompiler.vue b/doc/docs/.vuepress/components/YueCompiler.vue
new file mode 100755
index 0000000..4d72b92
--- /dev/null
+++ b/doc/docs/.vuepress/components/YueCompiler.vue
@@ -0,0 +1,383 @@
1<template>
2 <div style="width: 100%; height: auto;">
3 <div class="parent" style="background-color: #f5f7ff;">
4 <div class="childL" style="height: 2.5em;">
5 <div class="childTitle">Yuescript {{ info }}</div>
6 </div>
7 <div class="childR" style="height: 2.5em;">
8 <div class="childTitle">Lua</div>
9 </div>
10 <div class="childL" ref='yueEditor' style="height: 30em;">
11 <ClientOnly>
12 <prism-editor class="my-editor" v-model="code" :highlight="highlighter" @input="codeChanged($event)" line-numbers :readonly="readonly"></prism-editor>
13 </ClientOnly>
14 </div>
15 <div class="childR" style="height: 30em;">
16 <ClientOnly>
17 <prism-editor class="my-editor" v-model="compiled" :highlight="highlighter" @input="codeChanged($event)" readonly></prism-editor>
18 </ClientOnly>
19 </div>
20 </div>
21 <div v-if="!compileronly">
22 <button class="button" @click="runCode()">Run!</button>
23 <textarea class="resultArea" readonly>{{ result }}</textarea>
24 </div>
25 </div>
26</template>
27
28<script>
29 import { PrismEditor } from 'vue-prism-editor';
30 import 'vue-prism-editor/dist/prismeditor.min.css';
31 import { highlight, languages } from 'prismjs/components/prism-core';
32 import 'prismjs/components/prism-moonscript';
33 import 'prismjs/components/prism-lua';
34
35 export default {
36 props: {
37 compileronly: {
38 type: Boolean,
39 default: false,
40 },
41 displayonly: {
42 type: Boolean,
43 default: false,
44 },
45 text: {
46 type: String,
47 default: '',
48 },
49 },
50 components: {
51 PrismEditor,
52 },
53 data() {
54 return {
55 info: 'Loading',
56 readonly: true,
57 code: '',
58 compiled: '',
59 result: '',
60 };
61 },
62 mounted () {
63 if (this.text !== '') {
64 this.$data.code = this.text;
65 this.codeChanged(this.text);
66 }
67 const check = ((self)=> {
68 return ()=> {
69 if (window.yue) {
70 self.$data.info = window.yue.version();
71 self.$data.readonly = false;
72 const editor = self.$refs.yueEditor;
73 if (editor.children.length === 0) {
74 setTimeout(check, 100);
75 return;
76 }
77 const textArea = editor.children[0].children[1].children[0];
78 textArea.focus();
79 } else {
80 setTimeout(check, 100);
81 }
82 }
83 })(this);
84 check();
85 },
86 methods: {
87 runCode() {
88 if (window.yue && this.$data.compiled !== '') {
89 let res = '';
90 try {
91 res = window.yue.exec(this.$data.code);
92 } catch (err) {
93 res = err;
94 }
95 this.$data.result = res;
96 }
97 },
98 highlighter(code) {
99 return highlight(code, languages.moon);
100 },
101 codeChanged(text) {
102 if (window.yue) {
103 let res = ['','compiler error, and please help opening an issue for this. Thanks a lot!'];
104 try {
105 res = window.yue.tolua(text, true, !this.displayonly, true);
106 if (res[0] !== '') {
107 this.$data.compiled = res[0];
108 } else {
109 this.$data.compiled = res[1];
110 }
111 } catch (error) {
112 this.$data.compiled = res[1];
113 }
114 }
115 },
116 }
117 }
118</script>
119
120<style scoped>
121 .resultArea {
122 float: left;
123 margin-right: 1em;
124 overflow: scroll;
125 overflow-wrap: break-word;
126 width: calc(100% - 120px);
127 height: 55px;
128 border-color: #b7ae8f;
129 outline: none;
130 resize: none;
131 margin-top: 5px;
132 }
133 .childL {
134 float: left;
135 width: 50%;
136 box-sizing: border-box;
137 background-clip: content-box;
138 background: #f5f7ff;
139 }
140 .childR {
141 float: left;
142 width: 50%;
143 box-sizing: border-box;
144 background-clip: content-box;
145 background: #f5f7ff;
146 }
147 .childTitle {
148 width: 100%;
149 font-size: 1.5em;
150 color: #b7ae8f;
151 text-align: center;
152 padding: 0.2em;
153 }
154 .button {
155 float: right;
156 border: none;
157 display: inline-block;
158 font-size: 1.2rem;
159 color: #fff;
160 background-color: #b7ae8f;
161 text-decoration: none;
162 padding: .8rem 1.6rem;
163 border-radius: 4px;
164 transition: background-color .1s ease;
165 box-sizing: border-box;
166 border-bottom: 1px solid #aaa07b;
167 margin-top: 10px;
168 margin-right: 5px;
169 }
170 .button:hover {
171 background-color: #beb69a;
172 }
173 .button:focus,
174 .button:active:focus,
175 .button.active:focus,
176 .button.focus,
177 .button:active.focus {
178 outline: none;
179 }
180
181 .my-editor {
182 font-family: Consolas, Menlo, Monaco, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, monospace;
183 line-height: 1.375;
184 direction: ltr;
185 text-align: left;
186 white-space: pre;
187 word-spacing: normal;
188 word-break: normal;
189 -moz-tab-size: 4;
190 -o-tab-size: 4;
191 tab-size: 4;
192 -webkit-hyphens: none;
193 -moz-hyphens: none;
194 -ms-hyphens: none;
195 hyphens: none;
196 background: #f5f7ff;
197 color: #5e6687;
198 font-size: 1em;
199 overflow: scroll;
200 }
201
202 .my-editor >>> .prism-editor__textarea:focus {
203 outline: none;
204 }
205
206 /*
207 Name: Base16 Atelier Sulphurpool Light
208 Author: Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool)
209
210 Prism template by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/prism/)
211 Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
212
213 */
214 code[class*="language-"],
215 pre[class*="language-"] {
216 font-family: Consolas, Menlo, Monaco, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, monospace;
217 font-size: 1em;
218 line-height: 1.375;
219 direction: ltr;
220 text-align: left;
221 white-space: pre;
222 word-spacing: normal;
223 word-break: normal;
224 -moz-tab-size: 4;
225 -o-tab-size: 4;
226 tab-size: 4;
227 -webkit-hyphens: none;
228 -moz-hyphens: none;
229 -ms-hyphens: none;
230 hyphens: none;
231 background: #f5f7ff;
232 color: #5e6687;
233 }
234
235 pre > code[class*="language-"] {
236 font-size: 1em;
237 }
238
239 pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
240 code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
241 text-shadow: none;
242 background: #dfe2f1;
243 }
244
245 pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
246 code[class*="language-"]::selection, code[class*="language-"] ::selection {
247 text-shadow: none;
248 background: #dfe2f1;
249 }
250
251 /* Code blocks */
252 pre[class*="language-"] {
253 padding: 1em;
254 margin: .5em 0;
255 overflow: auto;
256 }
257
258 /* Inline code */
259 :not(pre) > code[class*="language-"] {
260 padding: .1em;
261 border-radius: .3em;
262 }
263
264 .token.comment,
265 .token.prolog,
266 .token.doctype,
267 .token.cdata {
268 color: #898ea4;
269 }
270
271 .token.punctuation {
272 color: #5e6687;
273 }
274
275 .token.namespace {
276 opacity: .7;
277 }
278
279 .token.operator,
280 .token.boolean,
281 .token.number {
282 color: #c76b29;
283 }
284
285 .token.property {
286 color: #c08b30;
287 }
288
289 .token.tag {
290 color: #3d8fd1;
291 }
292
293 .token.string {
294 color: #22a2c9;
295 }
296
297 .token.selector {
298 color: #6679cc;
299 }
300
301 .token.attr-name {
302 color: #c76b29;
303 }
304
305 .token.entity,
306 .token.url,
307 .language-css .token.string,
308 .style .token.string {
309 color: #22a2c9;
310 }
311
312 .token.attr-value,
313 .token.keyword,
314 .token.control,
315 .token.directive,
316 .token.unit {
317 color: #ac9739;
318 }
319
320 .token.statement,
321 .token.regex,
322 .token.atrule {
323 color: #22a2c9;
324 }
325
326 .token.placeholder,
327 .token.variable {
328 color: #3d8fd1;
329 }
330
331 .token.deleted {
332 text-decoration: line-through;
333 }
334
335 .token.inserted {
336 border-bottom: 1px dotted #202746;
337 text-decoration: none;
338 }
339
340 .token.italic {
341 font-style: italic;
342 }
343
344 .token.important,
345 .token.bold {
346 font-weight: bold;
347 }
348
349 .token.important {
350 color: #c94922;
351 }
352
353 .token.entity {
354 cursor: help;
355 }
356
357 pre > code.highlight {
358 outline: 0.4em solid #c94922;
359 outline-offset: .4em;
360 }
361
362 /* overrides color-values for the Line Numbers plugin
363 * http://prismjs.com/plugins/line-numbers/
364 */
365 .line-numbers .line-numbers-rows {
366 border-right-color: #dfe2f1;
367 }
368
369 .line-numbers-rows > span:before {
370 color: #979db4;
371 }
372
373 /* overrides color-values for the Line Highlight plugin
374 * http://prismjs.com/plugins/line-highlight/
375 */
376 .line-highlight {
377 background: rgba(107, 115, 148, 0.2);
378 background: -webkit-linear-gradient(left, rgba(107, 115, 148, 0.2) 70%, rgba(107, 115, 148, 0));
379 background: linear-gradient(to right, rgba(107, 115, 148, 0.2) 70%, rgba(107, 115, 148, 0));
380 }
381
382</style>
383
diff --git a/doc/docs/.vuepress/components/YueDisplay.vue b/doc/docs/.vuepress/components/YueDisplay.vue
new file mode 100755
index 0000000..b89805b
--- /dev/null
+++ b/doc/docs/.vuepress/components/YueDisplay.vue
@@ -0,0 +1,49 @@
1<template>
2 <div>
3 <button class="button" @click="compile()">Compile</button>
4 <div style="display: none;">
5 <slot></slot>
6 </div>
7 </div>
8</template>
9
10<script>
11 export default {
12 methods: {
13 compile() {
14 const node = this.$el.children[1];
15 const code = node.innerText;
16 window.yueCodes = code;
17 this.$modal.show('compiler');
18 },
19 },
20 }
21</script>
22
23<style scoped>
24 .button {
25 border: none;
26 display: inline-block;
27 font-size: 16px;
28 color: #fff;
29 background-color: #b7ae8f;
30 text-decoration: none;
31 padding: .4rem 0.8rem;
32 border-radius: 4px;
33 transition: background-color .1s ease;
34 box-sizing: border-box;
35 border-bottom: 1px solid #aaa07b;
36 margin-bottom: 1em;
37 }
38 .button:hover {
39 background-color: #beb69a;
40 }
41 .button:focus,
42 .button:active:focus,
43 .button.active:focus,
44 .button.focus,
45 .button:active.focus {
46 outline: none;
47 }
48</style>
49
diff --git a/doc/docs/.vuepress/config.js b/doc/docs/.vuepress/config.js
new file mode 100755
index 0000000..fe34c46
--- /dev/null
+++ b/doc/docs/.vuepress/config.js
@@ -0,0 +1,77 @@
1const { description } = require('../../package')
2
3module.exports = {
4 /**
5 * Ref:https://v1.vuepress.vuejs.org/config/#title
6 */
7 title: 'Yuescript',
8 /**
9 * Ref:https://v1.vuepress.vuejs.org/config/#description
10 */
11 description: description,
12
13 /**
14 * Extra tags to be injected to the page HTML `<head>`
15 *
16 * ref:https://v1.vuepress.vuejs.org/config/#head
17 */
18 head: [
19 ['meta', { name: 'theme-color', content: '#3eaf7c' }],
20 ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }],
21 ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }],
22 ['script', {}, `window.global = window;`],
23 ['script', {}, `
24 var Module = {
25 onRuntimeInitialized: function() {
26 window.yue = Module;
27 window.Vue.$data.readonly = false;
28 window.Vue.$data.info = Module.version();
29 }
30 };
31 `],
32 ['script', {}, `
33 var Module = {
34 onRuntimeInitialized: function() {
35 window.yue = Module;
36 }
37 };
38 `],
39 ['script', { src: '/js/yuescript.js' }],
40 ],
41
42 /**
43 * Theme configuration, here is the default theme configuration for VuePress.
44 *
45 * ref:https://v1.vuepress.vuejs.org/theme/default-theme-config.html
46 */
47 themeConfig: {
48 repo: '',
49 editLinks: false,
50 docsDir: '',
51 editLinkText: '',
52 lastUpdated: false,
53 nav: [
54 {
55 text: 'Document',
56 link: '/doc/'
57 },
58 {
59 text: 'Try yue!',
60 link: '/try/',
61 },
62 {
63 text: 'Github',
64 link: 'https://github.com/pigpigyyy/Yuescript'
65 }
66 ],
67 },
68
69 /**
70 * Apply plugins,ref:https://v1.vuepress.vuejs.org/zh/plugin/
71 */
72 plugins: [
73 '@vuepress/plugin-back-to-top',
74 '@vuepress/plugin-medium-zoom',
75 '~plugins/vue-js-modal.js',
76 ]
77}
diff --git a/doc/docs/.vuepress/enhanceApp.js b/doc/docs/.vuepress/enhanceApp.js
new file mode 100755
index 0000000..8452a86
--- /dev/null
+++ b/doc/docs/.vuepress/enhanceApp.js
@@ -0,0 +1,14 @@
1/**
2 * Client app enhancement file.
3 *
4 * https://v1.vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements
5 */
6
7export default ({
8 Vue, // the version of Vue being used in the VuePress app
9 options, // the options for the root Vue instance
10 router, // the router instance for the app
11 siteData // site metadata
12}) => {
13 // ...apply enhancements for the site.
14}
diff --git a/doc/docs/.vuepress/public/image/yuescript.svg b/doc/docs/.vuepress/public/image/yuescript.svg
new file mode 100644
index 0000000..b7e5884
--- /dev/null
+++ b/doc/docs/.vuepress/public/image/yuescript.svg
@@ -0,0 +1,53 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Generator: Adobe Illustrator 22.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
3<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
4 <!ENTITY ns_extend "http://ns.adobe.com/Extensibility/1.0/">
5 <!ENTITY ns_ai "http://ns.adobe.com/AdobeIllustrator/10.0/">
6 <!ENTITY ns_graphs "http://ns.adobe.com/Graphs/1.0/">
7 <!ENTITY ns_vars "http://ns.adobe.com/Variables/1.0/">
8 <!ENTITY ns_imrep "http://ns.adobe.com/ImageReplacement/1.0/">
9 <!ENTITY ns_sfw "http://ns.adobe.com/SaveForWeb/1.0/">
10 <!ENTITY ns_custom "http://ns.adobe.com/GenericCustomNamespace/1.0/">
11 <!ENTITY ns_adobe_xpath "http://ns.adobe.com/XPath/1.0/">
12]>
13<svg version="1.1" id="图层_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
14 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="" viewBox="250 200 95.3 441.9" xml:space="preserve">
15 <g>
16 <g>
17 <path fill="#B4AC8F" d="M209.8,522.5c-3.7,0.8-8.1,1.6-11.7,2.3c0.5-2,1.9-7.8,2.9-11.5l-2.8-2.9l-3.3,14.5c0,0.2-0.1,0.4-0.3,0.6
18 l-6,5.7l2.4,2.6l6.1-5.8c0.2-0.2,0.3-0.3,0.5-0.3l14.7-2.5L209.8,522.5z"/>
19 <path fill="#B4AC8F" d="M225.4,551.7c-1.9,2.7-4.2,3.9-7.8,1.5c-3.6-2.5-3.4-5.2-1.6-7.8l7.7-11.2l-2.9-2l-7.8,11.4
20 c-2.8,4-2.3,7.9,3.2,11.7c5.9,4,9.7,2.4,12.2-1.3l7.7-11.3l-3-2L225.4,551.7z"/>
21 <polygon fill="#B4AC8F" points="241.1,569.1 255.5,574.8 256.9,572.7 245.3,568 248,561.2 258.6,565.4 259.5,563 249,558.8
22 251.4,552.9 262.4,557.3 263.3,555 249.1,549.3 "/>
23 <path fill="#B4AC8F" d="M283.6,559.6c-4.7-0.8-8.2,0.8-8.8,4.2c-0.5,3,1.2,4.9,6.3,7.2c4,1.8,5.2,3,4.8,5.3
24 c-0.4,2.2-2.4,3.1-5.4,2.6c-2.9-0.5-4.7-2.2-4.8-4.8l-3.5-0.6c-0.3,3.9,2.4,6.8,7.6,7.8c5.7,1,9-1.1,9.6-4.6
25 c0.5-2.9-0.7-5.2-6.6-7.9c-3.7-1.7-4.9-2.6-4.6-4.5c0.3-1.8,1.9-2.7,4.7-2.2c3,0.5,4.1,2.1,4.1,4.2l3.4,0.6
26 C291,563.6,289.1,560.6,283.6,559.6z"/>
27 <path fill="#B4AC8F" d="M315.3,581.1c-5.2,0.2-7-4-7.1-8.4c-0.2-4.4,1.6-8.4,6.4-8.6c3.7-0.1,5.2,1.6,5.9,3.9l3.5-0.1
28 c-0.6-3.5-3.4-6.5-9.4-6.3c-7.2,0.3-10.3,5.5-10.1,11.2c0.2,6.3,3.2,11,10.8,10.7c6.1-0.2,8.6-3.5,9.2-7l-3.5,0.1
29 C320.4,579,319,581,315.3,581.1z"/>
30 <path fill="#B4AC8F" d="M356.7,570.7c-0.7-2.8-2.2-4.2-4.9-4.2c1.8-1.1,3.5-2.9,2.7-5.9c-0.9-3.5-4.5-4.6-8.9-3.4l-8.9,2.3l5.3,20.6
31 l3.4-0.9L343,570l4.1-1.1c3.9-1,5.4-0.2,6.1,2.6l0.1,0.4c0.6,2.2,1.1,4,1.7,4.8l3.4-0.9c-0.6-1.1-1.1-2.9-1.6-4.8L356.7,570.7z
32 M346.8,566.5l-4.4,1.1l-1.7-6.7l5.1-1.3c2.8-0.7,4.8-0.1,5.3,2C351.8,564.5,349.8,565.8,346.8,566.5z"/>
33
34 <rect x="370.4" y="548.3" transform="matrix(0.9105 -0.4136 0.4136 0.9105 -197.8473 203.9409)" fill="#B4AC8F" width="3.5" height="21.3"/>
35 <path fill="#B4AC8F" d="M390,536.6l-7.2,4.9l12,17.6l2.9-2l-5.1-7.4l3.9-2.7c4.3-2.9,6.1-6.7,3.7-10.2
36 C398.1,533.6,393.9,533.9,390,536.6z M395.1,545.1l-3.7,2.6l-4.2-6.2l3.8-2.6c2.6-1.8,5-2,6.4,0
37 C399,541.3,397.7,543.3,395.1,545.1z"/>
38 <polygon fill="#B4AC8F" points="419.6,513.4 417.7,511.6 405.1,524.8 407,526.5 412,521.2 425.6,534.2 428.1,531.6 414.5,518.7
39 "/>
40 <path fill="#B4AC8F" d="M334.2,260.2c-2.1-0.3-4.2-0.6-6.3-0.9v14.4v0.5c22.4,24.2,36.9,55.9,39,90.9H228.7c0,0-14,0.7-14,12.3
41 c0,12.1,11.1,14.1,13.9,14.1s69.4,0,69.4,0s8.7-0.5,8.7,6.1c0,6.3-6.4,6-8.6,6H156.6c11-74.3,69.2-133.2,143.1-145.3
42 c-79.7,4.2-144.2,66.5-151.9,145.3h-41.1c0,0-15.3-1.8-15.3,11.5c0,13.3,11.5,12.8,14.7,12.8c0.6,0,19.5,0,41.1,0
43 c1.5,28.3,10.4,54.8,24.7,77.4l0.1-0.1c-8.8-17.9-14.5-37.6-16.6-58.4c31.5,0,73,0,75.3,0c3.6,0,13.7-0.5,13.7-12.2
44 c0-11.6-12.4-11.9-12.4-11.9l-101.8,0c0,0-8.9,0.7-8.9-6.4s5.8-7.4,8.4-7.4c0.6,0,190.5,0,190.5,0s14.6,1.6,14.6-11.9
45 c0-12-12.8-11.5-17.5-11.5c-4.7,0-65.1,0-65.1,0s-9.7,0.4-9.7-6.9c0-7.3,8.2-6.9,9.6-6.9c0.7,0,59.7,0,114.7,0c0,0.7,0,1.5,0,2.2
46 c0,38.5-14.9,73.6-39.3,99.8v0c-21.6,23.3-50.7,39.6-83.5,45.1c6.3,3.9,12.9,7.3,19.8,10.2c23.9-6.8,45.6-19,63.6-35.2v0
47 c14.7-13.2,27-29.2,36.1-47h71.1v-6.7h-67.9c9.1-20.2,14.2-42.6,14.2-66.2c0-0.7,0-1.5,0-2.2c26.9,0,51.4,0,65.9,0
48 c5.1,14.9,7.9,30.8,7.9,47.4c0,27.5-7.6,53.3-20.9,75.4l11.2,9.1c15.2-24.6,24-53.5,24-84.5C469.4,339.2,410.8,272.6,334.2,260.2
49 z M216.9,435.3c0,6.5-6.3,6.9-6.3,6.9s-27,0-55.4,0c-0.3-4.3-0.5-8.6-0.5-12.9c0-0.5,0-0.9,0-1.4c27.4,0,56.2,0,56.5,0
50 C212.2,428,216.9,428.8,216.9,435.3z M381.2,365.1c-1.8-32.4-13.1-62.2-31.3-86.7c43.3,12.8,78.4,45.1,95,86.7H381.2z"/>
51 </g>
52 </g>
53</svg>
diff --git a/doc/docs/.vuepress/styles/index.styl b/doc/docs/.vuepress/styles/index.styl
new file mode 100755
index 0000000..69327fd
--- /dev/null
+++ b/doc/docs/.vuepress/styles/index.styl
@@ -0,0 +1,9 @@
1/**
2 * Custom Styles here.
3 *
4 * ref:https://v1.vuepress.vuejs.org/config/#index-styl
5 */
6
7.home .hero img
8 max-width 450px!important
9
diff --git a/doc/docs/.vuepress/styles/palette.styl b/doc/docs/.vuepress/styles/palette.styl
new file mode 100755
index 0000000..389aa76
--- /dev/null
+++ b/doc/docs/.vuepress/styles/palette.styl
@@ -0,0 +1,12 @@
1/**
2 * Custom palette here.
3 *
4 * ref:https://v1.vuepress.vuejs.org/zh/config/#palette-styl
5 */
6
7$accentColor = #b7ae8f
8$textColor = #2c3e50
9$borderColor = #eaecef
10$codeBgColor = #f5f7ff
11
12$contentWidth = 900px
diff --git a/doc/docs/.vuepress/theme/LICENSE b/doc/docs/.vuepress/theme/LICENSE
new file mode 100644
index 0000000..15f1f7e
--- /dev/null
+++ b/doc/docs/.vuepress/theme/LICENSE
@@ -0,0 +1,21 @@
1The MIT License (MIT)
2
3Copyright (c) 2018-present, Yuxi (Evan) You
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21THE SOFTWARE.
diff --git a/doc/docs/.vuepress/theme/README.md b/doc/docs/.vuepress/theme/README.md
new file mode 100644
index 0000000..fc49626
--- /dev/null
+++ b/doc/docs/.vuepress/theme/README.md
@@ -0,0 +1,11 @@
1# @vuepress/theme-default
2
3> theme-default for VuePress
4
5## Plugins
6
7The default theme has the following plugin built in:
8
9- [@vuepress/plugin-active-header-links](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/plugin-active-header-links)
10- [@vuepress/plugin-google-analytics](https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/plugin-google-analytics)
11- [@vuepress/plugin-search](https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/plugin-search)
diff --git a/doc/docs/.vuepress/theme/components/AlgoliaSearchBox.vue b/doc/docs/.vuepress/theme/components/AlgoliaSearchBox.vue
new file mode 100644
index 0000000..7071fb8
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/AlgoliaSearchBox.vue
@@ -0,0 +1,172 @@
1<template>
2 <form
3 id="search-form"
4 class="algolia-search-wrapper search-box"
5 role="search"
6 >
7 <input
8 id="algolia-search-input"
9 class="search-query"
10 :placeholder="placeholder"
11 >
12 </form>
13</template>
14
15<script>
16export default {
17 name: 'AlgoliaSearchBox',
18
19 props: ['options'],
20
21 data () {
22 return {
23 placeholder: undefined
24 }
25 },
26
27 watch: {
28 $lang (newValue) {
29 this.update(this.options, newValue)
30 },
31
32 options (newValue) {
33 this.update(newValue, this.$lang)
34 }
35 },
36
37 mounted () {
38 this.initialize(this.options, this.$lang)
39 this.placeholder = this.$site.themeConfig.searchPlaceholder || ''
40 },
41
42 methods: {
43 initialize (userOptions, lang) {
44 Promise.all([
45 import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.js'),
46 import(/* webpackChunkName: "docsearch" */ 'docsearch.js/dist/cdn/docsearch.min.css')
47 ]).then(([docsearch]) => {
48 docsearch = docsearch.default
49 const { algoliaOptions = {}} = userOptions
50 docsearch(Object.assign(
51 {},
52 userOptions,
53 {
54 inputSelector: '#algolia-search-input',
55 // #697 Make docsearch work well at i18n mode.
56 algoliaOptions: {
57 ...algoliaOptions,
58 facetFilters: [`lang:${lang}`].concat(algoliaOptions.facetFilters || [])
59 },
60 handleSelected: (input, event, suggestion) => {
61 const { pathname, hash } = new URL(suggestion.url)
62 const routepath = pathname.replace(this.$site.base, '/')
63 const _hash = decodeURIComponent(hash)
64 this.$router.push(`${routepath}${_hash}`)
65 }
66 }
67 ))
68 })
69 },
70
71 update (options, lang) {
72 this.$el.innerHTML = '<input id="algolia-search-input" class="search-query">'
73 this.initialize(options, lang)
74 }
75 }
76}
77</script>
78
79<style lang="stylus">
80.algolia-search-wrapper
81 & > span
82 vertical-align middle
83 .algolia-autocomplete
84 line-height normal
85 .ds-dropdown-menu
86 background-color #fff
87 border 1px solid #999
88 border-radius 4px
89 font-size 16px
90 margin 6px 0 0
91 padding 4px
92 text-align left
93 &:before
94 border-color #999
95 [class*=ds-dataset-]
96 border none
97 padding 0
98 .ds-suggestions
99 margin-top 0
100 .ds-suggestion
101 border-bottom 1px solid $borderColor
102 .algolia-docsearch-suggestion--highlight
103 color #2c815b
104 .algolia-docsearch-suggestion
105 border-color $borderColor
106 padding 0
107 .algolia-docsearch-suggestion--category-header
108 padding 5px 10px
109 margin-top 0
110 background $accentColor
111 color #fff
112 font-weight 600
113 .algolia-docsearch-suggestion--highlight
114 background rgba(255, 255, 255, 0.6)
115 .algolia-docsearch-suggestion--wrapper
116 padding 0
117 .algolia-docsearch-suggestion--title
118 font-weight 600
119 margin-bottom 0
120 color $textColor
121 .algolia-docsearch-suggestion--subcategory-column
122 vertical-align top
123 padding 5px 7px 5px 5px
124 border-color $borderColor
125 background #f1f3f5
126 &:after
127 display none
128 .algolia-docsearch-suggestion--subcategory-column-text
129 color #555
130 .algolia-docsearch-footer
131 border-color $borderColor
132 .ds-cursor .algolia-docsearch-suggestion--content
133 background-color #e7edf3 !important
134 color $textColor
135
136@media (min-width: $MQMobile)
137 .algolia-search-wrapper
138 .algolia-autocomplete
139 .algolia-docsearch-suggestion
140 .algolia-docsearch-suggestion--subcategory-column
141 float none
142 width 150px
143 min-width 150px
144 display table-cell
145 .algolia-docsearch-suggestion--content
146 float none
147 display table-cell
148 width 100%
149 vertical-align top
150 .ds-dropdown-menu
151 min-width 515px !important
152
153@media (max-width: $MQMobile)
154 .algolia-search-wrapper
155 .ds-dropdown-menu
156 min-width calc(100vw - 4rem) !important
157 max-width calc(100vw - 4rem) !important
158 .algolia-docsearch-suggestion--wrapper
159 padding 5px 7px 5px 5px !important
160 .algolia-docsearch-suggestion--subcategory-column
161 padding 0 !important
162 background white !important
163 .algolia-docsearch-suggestion--subcategory-column-text:after
164 content " > "
165 font-size 10px
166 line-height 14.4px
167 display inline-block
168 width 5px
169 margin -3px 3px 0
170 vertical-align middle
171
172</style>
diff --git a/doc/docs/.vuepress/theme/components/DropdownLink.vue b/doc/docs/.vuepress/theme/components/DropdownLink.vue
new file mode 100644
index 0000000..be6563f
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/DropdownLink.vue
@@ -0,0 +1,252 @@
1<template>
2 <div
3 class="dropdown-wrapper"
4 :class="{ open }"
5 >
6 <button
7 class="dropdown-title"
8 type="button"
9 :aria-label="dropdownAriaLabel"
10 @click="handleDropdown"
11 >
12 <span class="title">{{ item.text }}</span>
13 <span
14 class="arrow down"
15 />
16 </button>
17 <button
18 class="mobile-dropdown-title"
19 type="button"
20 :aria-label="dropdownAriaLabel"
21 @click="setOpen(!open)"
22 >
23 <span class="title">{{ item.text }}</span>
24 <span
25 class="arrow"
26 :class="open ? 'down' : 'right'"
27 />
28 </button>
29
30 <DropdownTransition>
31 <ul
32 v-show="open"
33 class="nav-dropdown"
34 >
35 <li
36 v-for="(subItem, index) in item.items"
37 :key="subItem.link || index"
38 class="dropdown-item"
39 >
40 <h4 v-if="subItem.type === 'links'">
41 {{ subItem.text }}
42 </h4>
43
44 <ul
45 v-if="subItem.type === 'links'"
46 class="dropdown-subitem-wrapper"
47 >
48 <li
49 v-for="childSubItem in subItem.items"
50 :key="childSubItem.link"
51 class="dropdown-subitem"
52 >
53 <NavLink
54 :item="childSubItem"
55 @focusout="
56 isLastItemOfArray(childSubItem, subItem.items) &&
57 isLastItemOfArray(subItem, item.items) &&
58 setOpen(false)
59 "
60 />
61 </li>
62 </ul>
63
64 <NavLink
65 v-else
66 :item="subItem"
67 @focusout="isLastItemOfArray(subItem, item.items) && setOpen(false)"
68 />
69 </li>
70 </ul>
71 </DropdownTransition>
72 </div>
73</template>
74
75<script>
76import NavLink from '@theme/components/NavLink.vue'
77import DropdownTransition from '@theme/components/DropdownTransition.vue'
78import last from 'lodash/last'
79
80export default {
81 name: 'DropdownLink',
82
83 components: {
84 NavLink,
85 DropdownTransition
86 },
87
88 props: {
89 item: {
90 required: true
91 }
92 },
93
94 data () {
95 return {
96 open: false
97 }
98 },
99
100 computed: {
101 dropdownAriaLabel () {
102 return this.item.ariaLabel || this.item.text
103 }
104 },
105
106 watch: {
107 $route () {
108 this.open = false
109 }
110 },
111
112 methods: {
113 setOpen (value) {
114 this.open = value
115 },
116
117 isLastItemOfArray (item, array) {
118 return last(array) === item
119 },
120
121 /**
122 * Open the dropdown when user tab and click from keyboard.
123 *
124 * Use event.detail to detect tab and click from keyboard. Ref: https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/detail
125 * The Tab + Click is UIEvent > KeyboardEvent, so the detail is 0.
126 */
127 handleDropdown () {
128 const isTriggerByTab = event.detail === 0
129 if (isTriggerByTab) this.setOpen(!this.open)
130 }
131 }
132}
133</script>
134
135<style lang="stylus">
136.dropdown-wrapper
137 cursor pointer
138 .dropdown-title
139 display block
140 font-size 0.9rem
141 font-family inherit
142 cursor inherit
143 padding inherit
144 line-height 1.4rem
145 background transparent
146 border none
147 font-weight 500
148 color $textColor
149 &:hover
150 border-color transparent
151 .arrow
152 vertical-align middle
153 margin-top -1px
154 margin-left 0.4rem
155 .mobile-dropdown-title
156 @extends .dropdown-title
157 display none
158 font-weight 600
159 font-size inherit
160 &:hover
161 color $accentColor
162 .nav-dropdown
163 .dropdown-item
164 color inherit
165 line-height 1.7rem
166 h4
167 margin 0.45rem 0 0
168 border-top 1px solid #eee
169 padding 1rem 1.5rem 0.45rem 1.25rem
170 .dropdown-subitem-wrapper
171 padding 0
172 list-style none
173 .dropdown-subitem
174 font-size 0.9em
175 a
176 display block
177 line-height 1.7rem
178 position relative
179 border-bottom none
180 font-weight 400
181 margin-bottom 0
182 padding 0 1.5rem 0 1.25rem
183 &:hover
184 color $accentColor
185 &.router-link-active
186 color $accentColor
187 &::after
188 content ""
189 width 0
190 height 0
191 border-left 5px solid $accentColor
192 border-top 3px solid transparent
193 border-bottom 3px solid transparent
194 position absolute
195 top calc(50% - 2px)
196 left 9px
197 &:first-child h4
198 margin-top 0
199 padding-top 0
200 border-top 0
201
202@media (max-width: $MQMobile)
203 .dropdown-wrapper
204 &.open .dropdown-title
205 margin-bottom 0.5rem
206 .dropdown-title
207 display: none
208 .mobile-dropdown-title
209 display: block
210 .nav-dropdown
211 transition height .1s ease-out
212 overflow hidden
213 .dropdown-item
214 h4
215 border-top 0
216 margin-top 0
217 padding-top 0
218 h4, & > a
219 font-size 15px
220 line-height 2rem
221 .dropdown-subitem
222 font-size 14px
223 padding-left 1rem
224
225@media (min-width: $MQMobile)
226 .dropdown-wrapper
227 height 1.8rem
228 &:hover .nav-dropdown,
229 &.open .nav-dropdown
230 // override the inline style.
231 display block !important
232 &.open:blur
233 display none
234 .nav-dropdown
235 display none
236 // Avoid height shaked by clicking
237 height auto !important
238 box-sizing border-box;
239 max-height calc(100vh - 2.7rem)
240 overflow-y auto
241 position absolute
242 top 100%
243 right 0
244 background-color #fff
245 padding 0.6rem 0
246 border 1px solid #ddd
247 border-bottom-color #ccc
248 text-align left
249 border-radius 0.25rem
250 white-space nowrap
251 margin 0
252</style>
diff --git a/doc/docs/.vuepress/theme/components/DropdownTransition.vue b/doc/docs/.vuepress/theme/components/DropdownTransition.vue
new file mode 100644
index 0000000..eeaf12b
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/DropdownTransition.vue
@@ -0,0 +1,33 @@
1<template>
2 <transition
3 name="dropdown"
4 @enter="setHeight"
5 @after-enter="unsetHeight"
6 @before-leave="setHeight"
7 >
8 <slot />
9 </transition>
10</template>
11
12<script>
13export default {
14 name: 'DropdownTransition',
15
16 methods: {
17 setHeight (items) {
18 // explicitly set height so that it can be transitioned
19 items.style.height = items.scrollHeight + 'px'
20 },
21
22 unsetHeight (items) {
23 items.style.height = ''
24 }
25 }
26}
27</script>
28
29<style lang="stylus">
30.dropdown-enter, .dropdown-leave-to
31 height 0 !important
32
33</style>
diff --git a/doc/docs/.vuepress/theme/components/Home.vue b/doc/docs/.vuepress/theme/components/Home.vue
new file mode 100644
index 0000000..acd8744
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/Home.vue
@@ -0,0 +1,175 @@
1<template>
2 <main
3 class="home"
4 :aria-labelledby="data.heroText !== null ? 'main-title' : null"
5 >
6 <header class="hero">
7 <img
8 v-if="data.heroImage"
9 :src="$withBase(data.heroImage)"
10 :alt="data.heroAlt || 'hero'"
11 >
12
13 <h1
14 v-if="data.heroText !== null"
15 id="main-title"
16 >
17 {{ data.heroText || $title || 'Hello' }}
18 </h1>
19
20 <p
21 v-if="data.tagline !== null"
22 class="description"
23 >
24 {{ data.tagline || $description || 'Welcome to your VuePress site' }}
25 </p>
26
27 <p
28 v-if="data.actionText && data.actionLink"
29 class="action"
30 >
31 <NavLink
32 class="action-button"
33 :item="actionLink"
34 />
35 </p>
36 </header>
37
38 <div
39 v-if="data.features && data.features.length"
40 class="features"
41 >
42 <div
43 v-for="(feature, index) in data.features"
44 :key="index"
45 class="feature"
46 >
47 <h2>{{ feature.title }}</h2>
48 <p>{{ feature.details }}</p>
49 </div>
50 </div>
51
52 <Content class="theme-default-content custom" />
53
54 <div
55 v-if="data.footer"
56 class="footer"
57 >
58 {{ data.footer }}
59 </div>
60 </main>
61</template>
62
63<script>
64import NavLink from '@theme/components/NavLink.vue'
65
66export default {
67 name: 'Home',
68
69 components: { NavLink },
70
71 computed: {
72 data () {
73 return this.$page.frontmatter
74 },
75
76 actionLink () {
77 return {
78 link: this.data.actionLink,
79 text: this.data.actionText
80 }
81 }
82 }
83}
84</script>
85
86<style lang="stylus">
87.home
88 padding $navbarHeight 2rem 0
89 max-width $homePageWidth
90 margin 0px auto
91 display block
92 .hero
93 text-align center
94 img
95 max-width: 100%
96 max-height 280px
97 display block
98 margin 3rem auto 1.5rem
99 h1
100 font-size 3rem
101 h1, .description, .action
102 margin 1.8rem auto
103 .description
104 max-width 35rem
105 font-size 1.6rem
106 line-height 1.3
107 color lighten($textColor, 40%)
108 .action-button
109 display inline-block
110 font-size 1.2rem
111 color #fff
112 background-color $accentColor
113 padding 0.8rem 1.6rem
114 border-radius 4px
115 transition background-color .1s ease
116 box-sizing border-box
117 border-bottom 1px solid darken($accentColor, 10%)
118 &:hover
119 background-color lighten($accentColor, 10%)
120 .features
121 border-top 1px solid $borderColor
122 padding 1.2rem 0
123 margin-top 2.5rem
124 display flex
125 flex-wrap wrap
126 align-items flex-start
127 align-content stretch
128 justify-content space-between
129 .feature
130 flex-grow 1
131 flex-basis 30%
132 max-width 30%
133 h2
134 font-size 1.4rem
135 font-weight 500
136 border-bottom none
137 padding-bottom 0
138 color lighten($textColor, 10%)
139 p
140 color lighten($textColor, 25%)
141 .footer
142 padding 2.5rem
143 border-top 1px solid $borderColor
144 text-align center
145 color lighten($textColor, 25%)
146
147@media (max-width: $MQMobile)
148 .home
149 .features
150 flex-direction column
151 .feature
152 max-width 100%
153 padding 0 2.5rem
154
155@media (max-width: $MQMobileNarrow)
156 .home
157 padding-left 1.5rem
158 padding-right 1.5rem
159 .hero
160 img
161 max-height 210px
162 margin 2rem auto 1.2rem
163 h1
164 font-size 2rem
165 h1, .description, .action
166 margin 1.2rem auto
167 .description
168 font-size 1.2rem
169 .action-button
170 font-size 1rem
171 padding 0.6rem 1.2rem
172 .feature
173 h2
174 font-size 1.25rem
175</style>
diff --git a/doc/docs/.vuepress/theme/components/NavLink.vue b/doc/docs/.vuepress/theme/components/NavLink.vue
new file mode 100644
index 0000000..f7e65a4
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/NavLink.vue
@@ -0,0 +1,90 @@
1<template>
2 <RouterLink
3 v-if="isInternal"
4 class="nav-link"
5 :to="link"
6 :exact="exact"
7 @focusout.native="focusoutAction"
8 >
9 {{ item.text }}
10 </RouterLink>
11 <a
12 v-else
13 :href="link"
14 class="nav-link external"
15 :target="target"
16 :rel="rel"
17 @focusout="focusoutAction"
18 >
19 {{ item.text }}
20 <OutboundLink v-if="isBlankTarget" />
21 </a>
22</template>
23
24<script>
25import { isExternal, isMailto, isTel, ensureExt } from '../util'
26
27export default {
28 name: 'NavLink',
29
30 props: {
31 item: {
32 required: true
33 }
34 },
35
36 computed: {
37 link () {
38 return ensureExt(this.item.link)
39 },
40
41 exact () {
42 if (this.$site.locales) {
43 return Object.keys(this.$site.locales).some(rootLink => rootLink === this.link)
44 }
45 return this.link === '/'
46 },
47
48 isNonHttpURI () {
49 return isMailto(this.link) || isTel(this.link)
50 },
51
52 isBlankTarget () {
53 return this.target === '_blank'
54 },
55
56 isInternal () {
57 return !isExternal(this.link) && !this.isBlankTarget
58 },
59
60 target () {
61 if (this.isNonHttpURI) {
62 return null
63 }
64 if (this.item.target) {
65 return this.item.target
66 }
67 return isExternal(this.link) ? '_blank' : ''
68 },
69
70 rel () {
71 if (this.isNonHttpURI) {
72 return null
73 }
74 if (this.item.rel === false) {
75 return null
76 }
77 if (this.item.rel) {
78 return this.item.rel
79 }
80 return this.isBlankTarget ? 'noopener noreferrer' : null
81 }
82 },
83
84 methods: {
85 focusoutAction () {
86 this.$emit('focusout')
87 }
88 }
89}
90</script>
diff --git a/doc/docs/.vuepress/theme/components/NavLinks.vue b/doc/docs/.vuepress/theme/components/NavLinks.vue
new file mode 100644
index 0000000..2656ae2
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/NavLinks.vue
@@ -0,0 +1,156 @@
1<template>
2 <nav
3 v-if="userLinks.length || repoLink"
4 class="nav-links"
5 >
6 <!-- user links -->
7 <div
8 v-for="item in userLinks"
9 :key="item.link"
10 class="nav-item"
11 >
12 <DropdownLink
13 v-if="item.type === 'links'"
14 :item="item"
15 />
16 <NavLink
17 v-else
18 :item="item"
19 />
20 </div>
21
22 <!-- repo link -->
23 <a
24 v-if="repoLink"
25 :href="repoLink"
26 class="repo-link"
27 target="_blank"
28 rel="noopener noreferrer"
29 >
30 {{ repoLabel }}
31 <OutboundLink />
32 </a>
33 </nav>
34</template>
35
36<script>
37import DropdownLink from '@theme/components/DropdownLink.vue'
38import { resolveNavLinkItem } from '../util'
39import NavLink from '@theme/components/NavLink.vue'
40
41export default {
42 name: 'NavLinks',
43
44 components: {
45 NavLink,
46 DropdownLink
47 },
48
49 computed: {
50 userNav () {
51 return this.$themeLocaleConfig.nav || this.$site.themeConfig.nav || []
52 },
53
54 nav () {
55 const { locales } = this.$site
56 if (locales && Object.keys(locales).length > 1) {
57 const currentLink = this.$page.path
58 const routes = this.$router.options.routes
59 const themeLocales = this.$site.themeConfig.locales || {}
60 const languageDropdown = {
61 text: this.$themeLocaleConfig.selectText || 'Languages',
62 ariaLabel: this.$themeLocaleConfig.ariaLabel || 'Select language',
63 items: Object.keys(locales).map(path => {
64 const locale = locales[path]
65 const text = themeLocales[path] && themeLocales[path].label || locale.lang
66 let link
67 // Stay on the current page
68 if (locale.lang === this.$lang) {
69 link = currentLink
70 } else {
71 // Try to stay on the same page
72 link = currentLink.replace(this.$localeConfig.path, path)
73 // fallback to homepage
74 if (!routes.some(route => route.path === link)) {
75 link = path
76 }
77 }
78 return { text, link }
79 })
80 }
81 return [...this.userNav, languageDropdown]
82 }
83 return this.userNav
84 },
85
86 userLinks () {
87 return (this.nav || []).map(link => {
88 return Object.assign(resolveNavLinkItem(link), {
89 items: (link.items || []).map(resolveNavLinkItem)
90 })
91 })
92 },
93
94 repoLink () {
95 const { repo } = this.$site.themeConfig
96 if (repo) {
97 return /^https?:/.test(repo)
98 ? repo
99 : `https://github.com/${repo}`
100 }
101 return null
102 },
103
104 repoLabel () {
105 if (!this.repoLink) return
106 if (this.$site.themeConfig.repoLabel) {
107 return this.$site.themeConfig.repoLabel
108 }
109
110 const repoHost = this.repoLink.match(/^https?:\/\/[^/]+/)[0]
111 const platforms = ['GitHub', 'GitLab', 'Bitbucket']
112 for (let i = 0; i < platforms.length; i++) {
113 const platform = platforms[i]
114 if (new RegExp(platform, 'i').test(repoHost)) {
115 return platform
116 }
117 }
118
119 return 'Source'
120 }
121 }
122}
123</script>
124
125<style lang="stylus">
126.nav-links
127 display inline-block
128 a
129 line-height 1.4rem
130 color inherit
131 &:hover, &.router-link-active
132 color $accentColor
133 .nav-item
134 position relative
135 display inline-block
136 margin-left 1.5rem
137 line-height 2rem
138 &:first-child
139 margin-left 0
140 .repo-link
141 margin-left 1.5rem
142
143@media (max-width: $MQMobile)
144 .nav-links
145 .nav-item, .repo-link
146 margin-left 0
147
148@media (min-width: $MQMobile)
149 .nav-links a
150 &:hover, &.router-link-active
151 color $textColor
152 .nav-item > a:not(.external)
153 &:hover, &.router-link-active
154 margin-bottom -2px
155 border-bottom 2px solid lighten($accentColor, 8%)
156</style>
diff --git a/doc/docs/.vuepress/theme/components/Navbar.vue b/doc/docs/.vuepress/theme/components/Navbar.vue
new file mode 100644
index 0000000..f8dd49c
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/Navbar.vue
@@ -0,0 +1,140 @@
1<template>
2 <header class="navbar">
3 <SidebarButton @toggle-sidebar="$emit('toggle-sidebar')" />
4
5 <RouterLink
6 :to="$localePath"
7 class="home-link"
8 >
9 <img
10 v-if="$site.themeConfig.logo"
11 class="logo"
12 :src="$withBase($site.themeConfig.logo)"
13 :alt="$siteTitle"
14 >
15 <span
16 v-if="$siteTitle"
17 ref="siteName"
18 class="site-name"
19 :class="{ 'can-hide': $site.themeConfig.logo }"
20 >{{ $siteTitle }}</span>
21 </RouterLink>
22
23 <div
24 class="links"
25 :style="linksWrapMaxWidth ? {
26 'max-width': linksWrapMaxWidth + 'px'
27 } : {}"
28 >
29 <AlgoliaSearchBox
30 v-if="isAlgoliaSearch"
31 :options="algolia"
32 />
33 <SearchBox v-else-if="$site.themeConfig.search !== false && $page.frontmatter.search !== false" />
34 <NavLinks class="can-hide" />
35 </div>
36 </header>
37</template>
38
39<script>
40import AlgoliaSearchBox from '@AlgoliaSearchBox'
41import SearchBox from '@SearchBox'
42import SidebarButton from '@theme/components/SidebarButton.vue'
43import NavLinks from '@theme/components/NavLinks.vue'
44
45export default {
46 name: 'Navbar',
47
48 components: {
49 SidebarButton,
50 NavLinks,
51 SearchBox,
52 AlgoliaSearchBox
53 },
54
55 data () {
56 return {
57 linksWrapMaxWidth: null
58 }
59 },
60
61 computed: {
62 algolia () {
63 return this.$themeLocaleConfig.algolia || this.$site.themeConfig.algolia || {}
64 },
65
66 isAlgoliaSearch () {
67 return this.algolia && this.algolia.apiKey && this.algolia.indexName
68 }
69 },
70
71 mounted () {
72 const MOBILE_DESKTOP_BREAKPOINT = 719 // refer to config.styl
73 const NAVBAR_VERTICAL_PADDING = parseInt(css(this.$el, 'paddingLeft')) + parseInt(css(this.$el, 'paddingRight'))
74 const handleLinksWrapWidth = () => {
75 if (document.documentElement.clientWidth < MOBILE_DESKTOP_BREAKPOINT) {
76 this.linksWrapMaxWidth = null
77 } else {
78 this.linksWrapMaxWidth = this.$el.offsetWidth - NAVBAR_VERTICAL_PADDING
79 - (this.$refs.siteName && this.$refs.siteName.offsetWidth || 0)
80 }
81 }
82 handleLinksWrapWidth()
83 window.addEventListener('resize', handleLinksWrapWidth, false)
84 }
85}
86
87function css (el, property) {
88 // NOTE: Known bug, will return 'auto' if style value is 'auto'
89 const win = el.ownerDocument.defaultView
90 // null means not to return pseudo styles
91 return win.getComputedStyle(el, null)[property]
92}
93</script>
94
95<style lang="stylus">
96$navbar-vertical-padding = 0.7rem
97$navbar-horizontal-padding = 1.5rem
98
99.navbar
100 padding $navbar-vertical-padding $navbar-horizontal-padding
101 line-height $navbarHeight - 1.4rem
102 a, span, img
103 display inline-block
104 .logo
105 height $navbarHeight - 1.4rem
106 min-width $navbarHeight - 1.4rem
107 margin-right 0.8rem
108 vertical-align top
109 .site-name
110 font-size 1.3rem
111 font-weight 600
112 color $textColor
113 position relative
114 .links
115 padding-left 1.5rem
116 box-sizing border-box
117 background-color white
118 white-space nowrap
119 font-size 0.9rem
120 position absolute
121 right $navbar-horizontal-padding
122 top $navbar-vertical-padding
123 display flex
124 .search-box
125 flex: 0 0 auto
126 vertical-align top
127
128@media (max-width: $MQMobile)
129 .navbar
130 padding-left 4rem
131 .can-hide
132 display none
133 .links
134 padding-left 1.5rem
135 .site-name
136 width calc(100vw - 9.4rem)
137 overflow hidden
138 white-space nowrap
139 text-overflow ellipsis
140</style>
diff --git a/doc/docs/.vuepress/theme/components/Page.vue b/doc/docs/.vuepress/theme/components/Page.vue
new file mode 100644
index 0000000..04ec7cb
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/Page.vue
@@ -0,0 +1,31 @@
1<template>
2 <main class="page">
3 <slot name="top" />
4
5 <Content class="theme-default-content" />
6 <PageEdit />
7
8 <PageNav v-bind="{ sidebarItems }" />
9
10 <slot name="bottom" />
11 </main>
12</template>
13
14<script>
15import PageEdit from '@theme/components/PageEdit.vue'
16import PageNav from '@theme/components/PageNav.vue'
17
18export default {
19 components: { PageEdit, PageNav },
20 props: ['sidebarItems']
21}
22</script>
23
24<style lang="stylus">
25@require '../styles/wrapper.styl'
26
27.page
28 padding-bottom 2rem
29 display block
30
31</style>
diff --git a/doc/docs/.vuepress/theme/components/PageEdit.vue b/doc/docs/.vuepress/theme/components/PageEdit.vue
new file mode 100644
index 0000000..cf9b2d2
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/PageEdit.vue
@@ -0,0 +1,155 @@
1<template>
2 <footer class="page-edit">
3 <div
4 v-if="editLink"
5 class="edit-link"
6 >
7 <a
8 :href="editLink"
9 target="_blank"
10 rel="noopener noreferrer"
11 >{{ editLinkText }}</a>
12 <OutboundLink />
13 </div>
14
15 <div
16 v-if="lastUpdated"
17 class="last-updated"
18 >
19 <span class="prefix">{{ lastUpdatedText }}:</span>
20 <span class="time">{{ lastUpdated }}</span>
21 </div>
22 </footer>
23</template>
24
25<script>
26import isNil from 'lodash/isNil'
27import { endingSlashRE, outboundRE } from '../util'
28
29export default {
30 name: 'PageEdit',
31
32 computed: {
33 lastUpdated () {
34 return this.$page.lastUpdated
35 },
36
37 lastUpdatedText () {
38 if (typeof this.$themeLocaleConfig.lastUpdated === 'string') {
39 return this.$themeLocaleConfig.lastUpdated
40 }
41 if (typeof this.$site.themeConfig.lastUpdated === 'string') {
42 return this.$site.themeConfig.lastUpdated
43 }
44 return 'Last Updated'
45 },
46
47 editLink () {
48 const showEditLink = isNil(this.$page.frontmatter.editLink)
49 ? this.$site.themeConfig.editLinks
50 : this.$page.frontmatter.editLink
51
52 const {
53 repo,
54 docsDir = '',
55 docsBranch = 'master',
56 docsRepo = repo
57 } = this.$site.themeConfig
58
59 if (showEditLink && docsRepo && this.$page.relativePath) {
60 return this.createEditLink(
61 repo,
62 docsRepo,
63 docsDir,
64 docsBranch,
65 this.$page.relativePath
66 )
67 }
68 return null
69 },
70
71 editLinkText () {
72 return (
73 this.$themeLocaleConfig.editLinkText
74 || this.$site.themeConfig.editLinkText
75 || `Edit this page`
76 )
77 }
78 },
79
80 methods: {
81 createEditLink (repo, docsRepo, docsDir, docsBranch, path) {
82 const bitbucket = /bitbucket.org/
83 if (bitbucket.test(docsRepo)) {
84 const base = docsRepo
85 return (
86 base.replace(endingSlashRE, '')
87 + `/src`
88 + `/${docsBranch}/`
89 + (docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '')
90 + path
91 + `?mode=edit&spa=0&at=${docsBranch}&fileviewer=file-view-default`
92 )
93 }
94
95 const gitlab = /gitlab.com/
96 if (gitlab.test(docsRepo)) {
97 const base = docsRepo
98 return (
99 base.replace(endingSlashRE, '')
100 + `/-/edit`
101 + `/${docsBranch}/`
102 + (docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '')
103 + path
104 )
105 }
106
107 const base = outboundRE.test(docsRepo)
108 ? docsRepo
109 : `https://github.com/${docsRepo}`
110 return (
111 base.replace(endingSlashRE, '')
112 + '/edit'
113 + `/${docsBranch}/`
114 + (docsDir ? docsDir.replace(endingSlashRE, '') + '/' : '')
115 + path
116 )
117 }
118 }
119}
120</script>
121
122<style lang="stylus">
123@require '../styles/wrapper.styl'
124
125.page-edit
126 @extend $wrapper
127 padding-top 1rem
128 padding-bottom 1rem
129 overflow auto
130
131 .edit-link
132 display inline-block
133 a
134 color lighten($textColor, 25%)
135 margin-right 0.25rem
136 .last-updated
137 float right
138 font-size 0.9em
139 .prefix
140 font-weight 500
141 color lighten($textColor, 25%)
142 .time
143 font-weight 400
144 color #767676
145
146@media (max-width: $MQMobile)
147 .page-edit
148 .edit-link
149 margin-bottom 0.5rem
150 .last-updated
151 font-size 0.8em
152 float none
153 text-align left
154
155</style>
diff --git a/doc/docs/.vuepress/theme/components/PageNav.vue b/doc/docs/.vuepress/theme/components/PageNav.vue
new file mode 100644
index 0000000..4c19aae
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/PageNav.vue
@@ -0,0 +1,163 @@
1<template>
2 <div
3 v-if="prev || next"
4 class="page-nav"
5 >
6 <p class="inner">
7 <span
8 v-if="prev"
9 class="prev"
10 >
11
12 <a
13 v-if="prev.type === 'external'"
14 class="prev"
15 :href="prev.path"
16 target="_blank"
17 rel="noopener noreferrer"
18 >
19 {{ prev.title || prev.path }}
20
21 <OutboundLink />
22 </a>
23
24 <RouterLink
25 v-else
26 class="prev"
27 :to="prev.path"
28 >
29 {{ prev.title || prev.path }}
30 </RouterLink>
31 </span>
32
33 <span
34 v-if="next"
35 class="next"
36 >
37 <a
38 v-if="next.type === 'external'"
39 :href="next.path"
40 target="_blank"
41 rel="noopener noreferrer"
42 >
43 {{ next.title || next.path }}
44
45 <OutboundLink />
46 </a>
47
48 <RouterLink
49 v-else
50 :to="next.path"
51 >
52 {{ next.title || next.path }}
53 </RouterLink>
54
55 </span>
56 </p>
57 </div>
58</template>
59
60<script>
61import { resolvePage } from '../util'
62import isString from 'lodash/isString'
63import isNil from 'lodash/isNil'
64
65export default {
66 name: 'PageNav',
67
68 props: ['sidebarItems'],
69
70 computed: {
71 prev () {
72 return resolvePageLink(LINK_TYPES.PREV, this)
73 },
74
75 next () {
76 return resolvePageLink(LINK_TYPES.NEXT, this)
77 }
78 }
79}
80
81function resolvePrev (page, items) {
82 return find(page, items, -1)
83}
84
85function resolveNext (page, items) {
86 return find(page, items, 1)
87}
88
89const LINK_TYPES = {
90 NEXT: {
91 resolveLink: resolveNext,
92 getThemeLinkConfig: ({ nextLinks }) => nextLinks,
93 getPageLinkConfig: ({ frontmatter }) => frontmatter.next
94 },
95 PREV: {
96 resolveLink: resolvePrev,
97 getThemeLinkConfig: ({ prevLinks }) => prevLinks,
98 getPageLinkConfig: ({ frontmatter }) => frontmatter.prev
99 }
100}
101
102function resolvePageLink (
103 linkType,
104 { $themeConfig, $page, $route, $site, sidebarItems }
105) {
106 const { resolveLink, getThemeLinkConfig, getPageLinkConfig } = linkType
107
108 // Get link config from theme
109 const themeLinkConfig = getThemeLinkConfig($themeConfig)
110
111 // Get link config from current page
112 const pageLinkConfig = getPageLinkConfig($page)
113
114 // Page link config will overwrite global theme link config if defined
115 const link = isNil(pageLinkConfig) ? themeLinkConfig : pageLinkConfig
116
117 if (link === false) {
118 return
119 } else if (isString(link)) {
120 return resolvePage($site.pages, link, $route.path)
121 } else {
122 return resolveLink($page, sidebarItems)
123 }
124}
125
126function find (page, items, offset) {
127 const res = []
128 flatten(items, res)
129 for (let i = 0; i < res.length; i++) {
130 const cur = res[i]
131 if (cur.type === 'page' && cur.path === decodeURIComponent(page.path)) {
132 return res[i + offset]
133 }
134 }
135}
136
137function flatten (items, res) {
138 for (let i = 0, l = items.length; i < l; i++) {
139 if (items[i].type === 'group') {
140 flatten(items[i].children || [], res)
141 } else {
142 res.push(items[i])
143 }
144 }
145}
146</script>
147
148<style lang="stylus">
149@require '../styles/wrapper.styl'
150
151.page-nav
152 @extend $wrapper
153 padding-top 1rem
154 padding-bottom 0
155 .inner
156 min-height 2rem
157 margin-top 0
158 border-top 1px solid $borderColor
159 padding-top 1rem
160 overflow auto // clear float
161 .next
162 float right
163</style>
diff --git a/doc/docs/.vuepress/theme/components/Sidebar.vue b/doc/docs/.vuepress/theme/components/Sidebar.vue
new file mode 100644
index 0000000..e70e333
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/Sidebar.vue
@@ -0,0 +1,64 @@
1<template>
2 <aside class="sidebar">
3 <NavLinks />
4
5 <slot name="top" />
6
7 <SidebarLinks
8 :depth="0"
9 :items="items"
10 />
11 <slot name="bottom" />
12 </aside>
13</template>
14
15<script>
16import SidebarLinks from '@theme/components/SidebarLinks.vue'
17import NavLinks from '@theme/components/NavLinks.vue'
18
19export default {
20 name: 'Sidebar',
21
22 components: { SidebarLinks, NavLinks },
23
24 props: ['items']
25}
26</script>
27
28<style lang="stylus">
29.sidebar
30 ul
31 padding 0
32 margin 0
33 list-style-type none
34 a
35 display inline-block
36 .nav-links
37 display none
38 border-bottom 1px solid $borderColor
39 padding 0.5rem 0 0.75rem 0
40 a
41 font-weight 600
42 .nav-item, .repo-link
43 display block
44 line-height 1.25rem
45 font-size 1.1em
46 padding 0.5rem 0 0.5rem 1.5rem
47 & > .sidebar-links
48 padding 1.5rem 0
49 & > li > a.sidebar-link
50 font-size 1.1em
51 line-height 1.7
52 font-weight bold
53 & > li:not(:first-child)
54 margin-top .75rem
55
56@media (max-width: $MQMobile)
57 .sidebar
58 .nav-links
59 display block
60 .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
61 top calc(1rem - 2px)
62 & > .sidebar-links
63 padding 1rem 0
64</style>
diff --git a/doc/docs/.vuepress/theme/components/SidebarButton.vue b/doc/docs/.vuepress/theme/components/SidebarButton.vue
new file mode 100644
index 0000000..3f54afd
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/SidebarButton.vue
@@ -0,0 +1,40 @@
1<template>
2 <div
3 class="sidebar-button"
4 @click="$emit('toggle-sidebar')"
5 >
6 <svg
7 class="icon"
8 xmlns="http://www.w3.org/2000/svg"
9 aria-hidden="true"
10 role="img"
11 viewBox="0 0 448 512"
12 >
13 <path
14 fill="currentColor"
15 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"
16 class=""
17 />
18 </svg>
19 </div>
20</template>
21
22<style lang="stylus">
23.sidebar-button
24 cursor pointer
25 display none
26 width 1.25rem
27 height 1.25rem
28 position absolute
29 padding 0.6rem
30 top 0.6rem
31 left 1rem
32 .icon
33 display block
34 width 1.25rem
35 height 1.25rem
36
37@media (max-width: $MQMobile)
38 .sidebar-button
39 display block
40</style>
diff --git a/doc/docs/.vuepress/theme/components/SidebarGroup.vue b/doc/docs/.vuepress/theme/components/SidebarGroup.vue
new file mode 100644
index 0000000..d7f1929
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/SidebarGroup.vue
@@ -0,0 +1,141 @@
1<template>
2 <section
3 class="sidebar-group"
4 :class="[
5 {
6 collapsable,
7 'is-sub-group': depth !== 0
8 },
9 `depth-${depth}`
10 ]"
11 >
12 <RouterLink
13 v-if="item.path"
14 class="sidebar-heading clickable"
15 :class="{
16 open,
17 'active': isActive($route, item.path)
18 }"
19 :to="item.path"
20 @click.native="$emit('toggle')"
21 >
22 <span>{{ item.title }}</span>
23 <span
24 v-if="collapsable"
25 class="arrow"
26 :class="open ? 'down' : 'right'"
27 />
28 </RouterLink>
29
30 <p
31 v-else
32 class="sidebar-heading"
33 :class="{ open }"
34 @click="$emit('toggle')"
35 >
36 <span>{{ item.title }}</span>
37 <span
38 v-if="collapsable"
39 class="arrow"
40 :class="open ? 'down' : 'right'"
41 />
42 </p>
43
44 <DropdownTransition>
45 <SidebarLinks
46 v-if="open || !collapsable"
47 class="sidebar-group-items"
48 :items="item.children"
49 :sidebar-depth="item.sidebarDepth"
50 :initial-open-group-index="item.initialOpenGroupIndex"
51 :depth="depth + 1"
52 />
53 </DropdownTransition>
54 </section>
55</template>
56
57<script>
58import { isActive } from '../util'
59import DropdownTransition from '@theme/components/DropdownTransition.vue'
60
61export default {
62 name: 'SidebarGroup',
63
64 components: {
65 DropdownTransition
66 },
67
68 props: [
69 'item',
70 'open',
71 'collapsable',
72 'depth'
73 ],
74
75 // ref: https://vuejs.org/v2/guide/components-edge-cases.html#Circular-References-Between-Components
76 beforeCreate () {
77 this.$options.components.SidebarLinks = require('@theme/components/SidebarLinks.vue').default
78 },
79
80 methods: { isActive }
81}
82</script>
83
84<style lang="stylus">
85.sidebar-group
86 .sidebar-group
87 padding-left 0.5em
88 &:not(.collapsable)
89 .sidebar-heading:not(.clickable)
90 cursor auto
91 color inherit
92 // refine styles of nested sidebar groups
93 &.is-sub-group
94 padding-left 0
95 & > .sidebar-heading
96 font-size 0.95em
97 line-height 1.4
98 font-weight normal
99 padding-left 2rem
100 &:not(.clickable)
101 opacity 0.5
102 & > .sidebar-group-items
103 padding-left 1rem
104 & > li > .sidebar-link
105 font-size: 0.95em;
106 border-left none
107 &.depth-2
108 & > .sidebar-heading
109 border-left none
110
111.sidebar-heading
112 color $textColor
113 transition color .15s ease
114 cursor pointer
115 font-size 1.1em
116 font-weight bold
117 // text-transform uppercase
118 padding 0.35rem 1.5rem 0.35rem 1.25rem
119 width 100%
120 box-sizing border-box
121 margin 0
122 border-left 0.25rem solid transparent
123 &.open, &:hover
124 color inherit
125 .arrow
126 position relative
127 top -0.12em
128 left 0.5em
129 &.clickable
130 &.active
131 font-weight 600
132 color $accentColor
133 border-left-color $accentColor
134 &:hover
135 color $accentColor
136
137.sidebar-group-items
138 transition height .1s ease-out
139 font-size 0.95em
140 overflow hidden
141</style>
diff --git a/doc/docs/.vuepress/theme/components/SidebarLink.vue b/doc/docs/.vuepress/theme/components/SidebarLink.vue
new file mode 100644
index 0000000..4cd7665
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/SidebarLink.vue
@@ -0,0 +1,133 @@
1<script>
2import { isActive, hashRE, groupHeaders } from '../util'
3
4export default {
5 functional: true,
6
7 props: ['item', 'sidebarDepth'],
8
9 render (h,
10 {
11 parent: {
12 $page,
13 $site,
14 $route,
15 $themeConfig,
16 $themeLocaleConfig
17 },
18 props: {
19 item,
20 sidebarDepth
21 }
22 }) {
23 // use custom active class matching logic
24 // due to edge case of paths ending with / + hash
25 const selfActive = isActive($route, item.path)
26 // for sidebar: auto pages, a hash link should be active if one of its child
27 // matches
28 const active = item.type === 'auto'
29 ? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug))
30 : selfActive
31 const link = item.type === 'external'
32 ? renderExternal(h, item.path, item.title || item.path)
33 : renderLink(h, item.path, item.title || item.path, active)
34
35 const maxDepth = [
36 $page.frontmatter.sidebarDepth,
37 sidebarDepth,
38 $themeLocaleConfig.sidebarDepth,
39 $themeConfig.sidebarDepth,
40 1
41 ].find(depth => depth !== undefined)
42
43 const displayAllHeaders = $themeLocaleConfig.displayAllHeaders
44 || $themeConfig.displayAllHeaders
45
46 if (item.type === 'auto') {
47 return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)]
48 } else if ((active || displayAllHeaders) && item.headers && !hashRE.test(item.path)) {
49 const children = groupHeaders(item.headers)
50 return [link, renderChildren(h, children, item.path, $route, maxDepth)]
51 } else {
52 return link
53 }
54 }
55}
56
57function renderLink (h, to, text, active, level) {
58 const component = {
59 props: {
60 to,
61 activeClass: '',
62 exactActiveClass: ''
63 },
64 class: {
65 active,
66 'sidebar-link': true
67 }
68 }
69
70 if (level > 2) {
71 component.style = {
72 'padding-left': level + 'rem'
73 }
74 }
75
76 return h('RouterLink', component, text)
77}
78
79function renderChildren (h, children, path, route, maxDepth, depth = 1) {
80 if (!children || depth > maxDepth) return null
81 return h('ul', { class: 'sidebar-sub-headers' }, children.map(c => {
82 const active = isActive(route, path + '#' + c.slug)
83 return h('li', { class: 'sidebar-sub-header' }, [
84 renderLink(h, path + '#' + c.slug, c.title, active, c.level - 1),
85 renderChildren(h, c.children, path, route, maxDepth, depth + 1)
86 ])
87 }))
88}
89
90function renderExternal (h, to, text) {
91 return h('a', {
92 attrs: {
93 href: to,
94 target: '_blank',
95 rel: 'noopener noreferrer'
96 },
97 class: {
98 'sidebar-link': true
99 }
100 }, [text, h('OutboundLink')])
101}
102</script>
103
104<style lang="stylus">
105.sidebar .sidebar-sub-headers
106 padding-left 1rem
107 font-size 0.95em
108
109a.sidebar-link
110 font-size 1em
111 font-weight 400
112 display inline-block
113 color $textColor
114 border-left 0.25rem solid transparent
115 padding 0.35rem 1rem 0.35rem 1.25rem
116 line-height 1.4
117 width: 100%
118 box-sizing: border-box
119 &:hover
120 color $accentColor
121 &.active
122 font-weight 600
123 color $accentColor
124 border-left-color $accentColor
125 .sidebar-group &
126 padding-left 2rem
127 .sidebar-sub-headers &
128 padding-top 0.25rem
129 padding-bottom 0.25rem
130 border-left none
131 &.active
132 font-weight 500
133</style>
diff --git a/doc/docs/.vuepress/theme/components/SidebarLinks.vue b/doc/docs/.vuepress/theme/components/SidebarLinks.vue
new file mode 100644
index 0000000..55e6288
--- /dev/null
+++ b/doc/docs/.vuepress/theme/components/SidebarLinks.vue
@@ -0,0 +1,106 @@
1<template>
2 <ul
3 v-if="items.length"
4 class="sidebar-links"
5 >
6 <li
7 v-for="(item, i) in items"
8 :key="i"
9 >
10 <SidebarGroup
11 v-if="item.type === 'group'"
12 :item="item"
13 :open="i === openGroupIndex"
14 :collapsable="item.collapsable || item.collapsible"
15 :depth="depth"
16 @toggle="toggleGroup(i)"
17 />
18 <SidebarLink
19 v-else
20 :sidebar-depth="sidebarDepth"
21 :item="item"
22 />
23 </li>
24 </ul>
25</template>
26
27<script>
28import SidebarGroup from '@theme/components/SidebarGroup.vue'
29import SidebarLink from '@theme/components/SidebarLink.vue'
30import { isActive } from '../util'
31
32export default {
33 name: 'SidebarLinks',
34
35 components: { SidebarGroup, SidebarLink },
36
37 props: [
38 'items',
39 'depth', // depth of current sidebar links
40 'sidebarDepth', // depth of headers to be extracted
41 'initialOpenGroupIndex'
42 ],
43
44 data () {
45 return {
46 openGroupIndex: this.initialOpenGroupIndex || 0
47 }
48 },
49
50 watch: {
51 '$route' () {
52 this.refreshIndex()
53 }
54 },
55
56 created () {
57 this.refreshIndex()
58 },
59
60 methods: {
61 refreshIndex () {
62 const index = resolveOpenGroupIndex(
63 this.$route,
64 this.items
65 )
66 if (index > -1) {
67 this.openGroupIndex = index
68 }
69 },
70
71 toggleGroup (index) {
72 this.openGroupIndex = index === this.openGroupIndex ? -1 : index
73 },
74
75 isActive (page) {
76 return isActive(this.$route, page.regularPath)
77 }
78 }
79}
80
81function resolveOpenGroupIndex (route, items) {
82 for (let i = 0; i < items.length; i++) {
83 const item = items[i]
84 if (descendantIsActive(route, item)) {
85 return i
86 }
87 }
88 return -1
89}
90
91function descendantIsActive (route, item) {
92 if (item.type === 'group') {
93 const childIsActive = item.path && isActive(route, item.path)
94 const grandChildIsActive = item.children.some(child => {
95 if (child.type === 'group') {
96 return descendantIsActive(route, child)
97 } else {
98 return child.type === 'page' && isActive(route, child.path)
99 }
100 })
101
102 return childIsActive || grandChildIsActive
103 }
104 return false
105}
106</script>
diff --git a/doc/docs/.vuepress/theme/global-components/Badge.vue b/doc/docs/.vuepress/theme/global-components/Badge.vue
new file mode 100644
index 0000000..53951f9
--- /dev/null
+++ b/doc/docs/.vuepress/theme/global-components/Badge.vue
@@ -0,0 +1,44 @@
1<script>
2export default {
3 functional: true,
4 props: {
5 type: {
6 type: String,
7 default: 'tip'
8 },
9 text: String,
10 vertical: {
11 type: String,
12 default: 'top'
13 }
14 },
15 render (h, { props, slots }) {
16 return h('span', {
17 class: ['badge', props.type],
18 style: {
19 verticalAlign: props.vertical
20 }
21 }, props.text || slots().default)
22 }
23}
24</script>
25
26<style lang="stylus" scoped>
27.badge
28 display inline-block
29 font-size 14px
30 height 18px
31 line-height 18px
32 border-radius 3px
33 padding 0 6px
34 color white
35 background-color #42b983
36 &.tip, &.green
37 background-color $badgeTipColor
38 &.error
39 background-color $badgeErrorColor
40 &.warning, &.warn, &.yellow
41 background-color $badgeWarningColor
42 & + &
43 margin-left 5px
44</style>
diff --git a/doc/docs/.vuepress/theme/global-components/CodeBlock.vue b/doc/docs/.vuepress/theme/global-components/CodeBlock.vue
new file mode 100644
index 0000000..d59d85b
--- /dev/null
+++ b/doc/docs/.vuepress/theme/global-components/CodeBlock.vue
@@ -0,0 +1,41 @@
1<template>
2 <div
3 class="theme-code-block"
4 :class="{ 'theme-code-block__active': active }"
5 >
6 <slot />
7 </div>
8</template>
9
10<script>
11export default {
12 name: 'CodeBlock',
13 props: {
14 title: {
15 type: String,
16 required: true
17 },
18 active: {
19 type: Boolean,
20 default: false
21 }
22 },
23 mounted () {
24 if (this.$parent && this.$parent.loadTabs) {
25 this.$parent.loadTabs()
26 }
27 }
28}
29</script>
30
31<style scoped>
32 .theme-code-block {
33 display: none;
34 }
35 .theme-code-block__active {
36 display: block;
37 }
38 .theme-code-block > pre {
39 background-color: orange;
40 }
41</style>
diff --git a/doc/docs/.vuepress/theme/global-components/CodeGroup.vue b/doc/docs/.vuepress/theme/global-components/CodeGroup.vue
new file mode 100644
index 0000000..ac6ec55
--- /dev/null
+++ b/doc/docs/.vuepress/theme/global-components/CodeGroup.vue
@@ -0,0 +1,120 @@
1<template>
2 <ClientOnly>
3 <div class="theme-code-group">
4 <div class="theme-code-group__nav">
5 <ul class="theme-code-group__ul">
6 <li
7 v-for="(tab, i) in codeTabs"
8 :key="tab.title"
9 class="theme-code-group__li"
10 >
11 <button
12 class="theme-code-group__nav-tab"
13 :class="{
14 'theme-code-group__nav-tab-active': i === activeCodeTabIndex,
15 }"
16 @click="changeCodeTab(i)"
17 >
18 {{ tab.title }}
19 </button>
20 </li>
21 </ul>
22 </div>
23 <slot />
24 <pre
25 v-if="codeTabs.length < 1"
26 class="pre-blank"
27 >// Make sure to add code blocks to your code group</pre>
28 </div>
29 </ClientOnly>
30</template>
31
32<script>
33export default {
34 name: 'CodeGroup',
35 data () {
36 return {
37 codeTabs: [],
38 activeCodeTabIndex: -1
39 }
40 },
41 watch: {
42 activeCodeTabIndex (index) {
43 this.activateCodeTab(index)
44 }
45 },
46 mounted () {
47 this.loadTabs()
48 },
49 methods: {
50 changeCodeTab (index) {
51 this.activeCodeTabIndex = index
52 },
53 loadTabs () {
54 this.codeTabs = (this.$slots.default || []).filter(slot => Boolean(slot.componentOptions)).map((slot, index) => {
55 if (slot.componentOptions.propsData.active === '') {
56 this.activeCodeTabIndex = index
57 }
58
59 return {
60 title: slot.componentOptions.propsData.title,
61 elm: slot.elm
62 }
63 })
64
65 if (this.activeCodeTabIndex === -1 && this.codeTabs.length > 0) {
66 this.activeCodeTabIndex = 0
67 }
68
69 this.activateCodeTab(0)
70 },
71 activateCodeTab (index) {
72 this.codeTabs.forEach(tab => {
73 if (tab.elm) {
74 tab.elm.classList.remove('theme-code-block__active')
75 }
76 })
77
78 if (this.codeTabs[index].elm) {
79 this.codeTabs[index].elm.classList.add('theme-code-block__active')
80 }
81 }
82 }
83}
84</script>
85
86<style lang="stylus" scoped>
87 .theme-code-group {}
88 .theme-code-group__nav {
89 margin-bottom: -35px;
90 background-color: $codeBgColor;
91 padding-bottom: 22px;
92 border-top-left-radius: 6px;
93 border-top-right-radius: 6px;
94 padding-left: 10px;
95 padding-top: 10px;
96 }
97 .theme-code-group__ul {
98 margin: auto 0;
99 padding-left: 0;
100 display: inline-flex;
101 list-style: none;
102 }
103 .theme-code-group__li {}
104 .theme-code-group__nav-tab {
105 border: 0;
106 padding: 5px;
107 cursor: pointer;
108 background-color: transparent;
109 font-size: 0.85em;
110 line-height: 1.4;
111 color: rgba(255, 255, 255, 0.9);
112 font-weight: 600;
113 }
114 .theme-code-group__nav-tab-active {
115 border-bottom: #42b983 1px solid;
116 }
117 .pre-blank {
118 color: #42b983;
119 }
120</style>
diff --git a/doc/docs/.vuepress/theme/index.js b/doc/docs/.vuepress/theme/index.js
new file mode 100644
index 0000000..baaf102
--- /dev/null
+++ b/doc/docs/.vuepress/theme/index.js
@@ -0,0 +1,59 @@
1const path = require('path')
2
3// Theme API.
4module.exports = (options, ctx) => {
5 const { themeConfig, siteConfig } = ctx
6
7 // resolve algolia
8 const isAlgoliaSearch = (
9 themeConfig.algolia
10 || Object
11 .keys(siteConfig.locales && themeConfig.locales || {})
12 .some(base => themeConfig.locales[base].algolia)
13 )
14
15 const enableSmoothScroll = themeConfig.smoothScroll === true
16
17 return {
18 alias () {
19 return {
20 '@AlgoliaSearchBox': isAlgoliaSearch
21 ? path.resolve(__dirname, 'components/AlgoliaSearchBox.vue')
22 : path.resolve(__dirname, 'noopModule.js')
23 }
24 },
25
26 plugins: [
27 ['@vuepress/active-header-links', options.activeHeaderLinks],
28 '@vuepress/search',
29 '@vuepress/plugin-nprogress',
30 ['container', {
31 type: 'tip',
32 defaultTitle: {
33 '/': 'TIP',
34 '/zh/': '提示'
35 }
36 }],
37 ['container', {
38 type: 'warning',
39 defaultTitle: {
40 '/': 'WARNING',
41 '/zh/': '注意'
42 }
43 }],
44 ['container', {
45 type: 'danger',
46 defaultTitle: {
47 '/': 'WARNING',
48 '/zh/': '警告'
49 }
50 }],
51 ['container', {
52 type: 'details',
53 before: info => `<details class="custom-block details">${info ? `<summary>${info}</summary>` : ''}\n`,
54 after: () => '</details>\n'
55 }],
56 ['smooth-scroll', enableSmoothScroll]
57 ]
58 }
59}
diff --git a/doc/docs/.vuepress/theme/layouts/404.vue b/doc/docs/.vuepress/theme/layouts/404.vue
new file mode 100644
index 0000000..2cbfa0f
--- /dev/null
+++ b/doc/docs/.vuepress/theme/layouts/404.vue
@@ -0,0 +1,30 @@
1<template>
2 <div class="theme-container">
3 <div class="theme-default-content">
4 <h1>404</h1>
5
6 <blockquote>{{ getMsg() }}</blockquote>
7
8 <RouterLink to="/">
9 Take me home.
10 </RouterLink>
11 </div>
12 </div>
13</template>
14
15<script>
16const msgs = [
17 `There's nothing here.`,
18 `How did we get here?`,
19 `That's a Four-Oh-Four.`,
20 `Looks like we've got some broken links.`
21]
22
23export default {
24 methods: {
25 getMsg () {
26 return msgs[Math.floor(Math.random() * msgs.length)]
27 }
28 }
29}
30</script>
diff --git a/doc/docs/.vuepress/theme/layouts/Layout.vue b/doc/docs/.vuepress/theme/layouts/Layout.vue
new file mode 100644
index 0000000..3298070
--- /dev/null
+++ b/doc/docs/.vuepress/theme/layouts/Layout.vue
@@ -0,0 +1,151 @@
1<template>
2 <div
3 class="theme-container"
4 :class="pageClasses"
5 @touchstart="onTouchStart"
6 @touchend="onTouchEnd"
7 >
8 <Navbar
9 v-if="shouldShowNavbar"
10 @toggle-sidebar="toggleSidebar"
11 />
12
13 <div
14 class="sidebar-mask"
15 @click="toggleSidebar(false)"
16 />
17
18 <Sidebar
19 :items="sidebarItems"
20 @toggle-sidebar="toggleSidebar"
21 >
22 <template #top>
23 <slot name="sidebar-top" />
24 </template>
25 <template #bottom>
26 <slot name="sidebar-bottom" />
27 </template>
28 </Sidebar>
29
30 <Home v-if="$page.frontmatter.home" />
31
32 <Page
33 v-else
34 :sidebar-items="sidebarItems"
35 >
36 <template #top>
37 <slot name="page-top" />
38 </template>
39 <template #bottom>
40 <slot name="page-bottom" />
41 </template>
42 </Page>
43 </div>
44</template>
45
46<script>
47import Home from '@theme/components/Home.vue'
48import Navbar from '@theme/components/Navbar.vue'
49import Page from '@theme/components/Page.vue'
50import Sidebar from '@theme/components/Sidebar.vue'
51import { resolveSidebarItems } from '../util'
52
53export default {
54 name: 'Layout',
55
56 components: {
57 Home,
58 Page,
59 Sidebar,
60 Navbar
61 },
62
63 data () {
64 return {
65 isSidebarOpen: false
66 }
67 },
68
69 computed: {
70 shouldShowNavbar () {
71 const { themeConfig } = this.$site
72 const { frontmatter } = this.$page
73 if (
74 frontmatter.navbar === false
75 || themeConfig.navbar === false) {
76 return false
77 }
78 return (
79 this.$title
80 || themeConfig.logo
81 || themeConfig.repo
82 || themeConfig.nav
83 || this.$themeLocaleConfig.nav
84 )
85 },
86
87 shouldShowSidebar () {
88 const { frontmatter } = this.$page
89 return (
90 !frontmatter.home
91 && frontmatter.sidebar !== false
92 && this.sidebarItems.length
93 )
94 },
95
96 sidebarItems () {
97 return resolveSidebarItems(
98 this.$page,
99 this.$page.regularPath,
100 this.$site,
101 this.$localePath
102 )
103 },
104
105 pageClasses () {
106 const userPageClass = this.$page.frontmatter.pageClass
107 return [
108 {
109 'no-navbar': !this.shouldShowNavbar,
110 'sidebar-open': this.isSidebarOpen,
111 'no-sidebar': !this.shouldShowSidebar
112 },
113 userPageClass
114 ]
115 }
116 },
117
118 mounted () {
119 this.$router.afterEach(() => {
120 this.isSidebarOpen = false
121 })
122 },
123
124 methods: {
125 toggleSidebar (to) {
126 this.isSidebarOpen = typeof to === 'boolean' ? to : !this.isSidebarOpen
127 this.$emit('toggle-sidebar', this.isSidebarOpen)
128 },
129
130 // side swipe
131 onTouchStart (e) {
132 this.touchStart = {
133 x: e.changedTouches[0].clientX,
134 y: e.changedTouches[0].clientY
135 }
136 },
137
138 onTouchEnd (e) {
139 const dx = e.changedTouches[0].clientX - this.touchStart.x
140 const dy = e.changedTouches[0].clientY - this.touchStart.y
141 if (Math.abs(dx) > Math.abs(dy) && Math.abs(dx) > 40) {
142 if (dx > 0 && this.touchStart.x <= 80) {
143 this.toggleSidebar(true)
144 } else {
145 this.toggleSidebar(false)
146 }
147 }
148 }
149 }
150}
151</script>
diff --git a/doc/docs/.vuepress/theme/noopModule.js b/doc/docs/.vuepress/theme/noopModule.js
new file mode 100644
index 0000000..b1c6ea4
--- /dev/null
+++ b/doc/docs/.vuepress/theme/noopModule.js
@@ -0,0 +1 @@
export default {}
diff --git a/doc/docs/.vuepress/theme/package.json b/doc/docs/.vuepress/theme/package.json
new file mode 100644
index 0000000..d5dfc26
--- /dev/null
+++ b/doc/docs/.vuepress/theme/package.json
@@ -0,0 +1,44 @@
1{
2 "name": "@vuepress/theme-default",
3 "version": "1.8.2",
4 "description": "Default theme for VuePress",
5 "keywords": [
6 "documentation",
7 "generator",
8 "vue",
9 "vuepress"
10 ],
11 "homepage": "https://github.com/vuejs/vuepress/blob/master/packages/@vuepress/theme-default#readme",
12 "bugs": {
13 "url": "https://github.com/vuejs/vuepress/issues"
14 },
15 "repository": {
16 "type": "git",
17 "url": "git+https://github.com/vuejs/vuepress.git",
18 "directory": "packages/@vuepress/theme-default"
19 },
20 "license": "MIT",
21 "author": "Evan You",
22 "main": "index.js",
23 "dependencies": {
24 "@vuepress/plugin-active-header-links": "1.8.2",
25 "@vuepress/plugin-nprogress": "1.8.2",
26 "@vuepress/plugin-search": "1.8.2",
27 "docsearch.js": "^2.5.2",
28 "lodash": "^4.17.15",
29 "stylus": "^0.54.8",
30 "stylus-loader": "^3.0.2",
31 "vuepress-plugin-container": "^2.0.2",
32 "vuepress-plugin-smooth-scroll": "^0.0.3"
33 },
34 "publishConfig": {
35 "access": "public"
36 },
37 "maintainers": [
38 {
39 "name": "ULIVZ",
40 "email": "chl814@foxmail.com"
41 }
42 ],
43 "gitHead": "11eed0f0f105b97a7324cfa8e59d7d27bb966842"
44}
diff --git a/doc/docs/.vuepress/theme/styles/arrow.styl b/doc/docs/.vuepress/theme/styles/arrow.styl
new file mode 100644
index 0000000..20bffc0
--- /dev/null
+++ b/doc/docs/.vuepress/theme/styles/arrow.styl
@@ -0,0 +1,22 @@
1@require './config'
2
3.arrow
4 display inline-block
5 width 0
6 height 0
7 &.up
8 border-left 4px solid transparent
9 border-right 4px solid transparent
10 border-bottom 6px solid $arrowBgColor
11 &.down
12 border-left 4px solid transparent
13 border-right 4px solid transparent
14 border-top 6px solid $arrowBgColor
15 &.right
16 border-top 4px solid transparent
17 border-bottom 4px solid transparent
18 border-left 6px solid $arrowBgColor
19 &.left
20 border-top 4px solid transparent
21 border-bottom 4px solid transparent
22 border-right 6px solid $arrowBgColor
diff --git a/doc/docs/.vuepress/theme/styles/code.styl b/doc/docs/.vuepress/theme/styles/code.styl
new file mode 100644
index 0000000..0cb4081
--- /dev/null
+++ b/doc/docs/.vuepress/theme/styles/code.styl
@@ -0,0 +1,176 @@
1/*
2
3Name: Base16 Atelier Sulphurpool Light
4Author: Bram de Haan (http://atelierbram.github.io/syntax-highlighting/atelier-schemes/sulphurpool)
5
6Prism template by Bram de Haan (http://atelierbram.github.io/syntax-highlighting/prism/)
7Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8
9*/
10code[class*="language-"],
11pre[class*="language-"] {
12 font-family: Consolas, Menlo, Monaco, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, monospace;
13 font-size: 1em;
14 line-height: 1.375;
15 direction: ltr;
16 text-align: left;
17 white-space: pre;
18 word-spacing: normal;
19 word-break: normal;
20 -moz-tab-size: 4;
21 -o-tab-size: 4;
22 tab-size: 4;
23 -webkit-hyphens: none;
24 -moz-hyphens: none;
25 -ms-hyphens: none;
26 hyphens: none;
27 background: #f5f7ff;
28 color: #5e6687;
29}
30
31pre > code[class*="language-"] {
32 font-size: 1em;
33}
34
35pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
36code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
37 text-shadow: none;
38 background: #dfe2f1;
39}
40
41pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
42code[class*="language-"]::selection, code[class*="language-"] ::selection {
43 text-shadow: none;
44 background: #dfe2f1;
45}
46
47/* Code blocks */
48pre[class*="language-"] {
49 padding: 1em;
50 margin: .5em 0;
51 overflow: auto;
52}
53
54/* Inline code */
55:not(pre) > code[class*="language-"] {
56 padding: .1em;
57 border-radius: .3em;
58}
59
60.token.comment,
61.token.prolog,
62.token.doctype,
63.token.cdata {
64 color: #898ea4;
65}
66
67.token.punctuation {
68 color: #5e6687;
69}
70
71.token.namespace {
72 opacity: .7;
73}
74
75.token.operator,
76.token.boolean,
77.token.number {
78 color: #c76b29;
79}
80
81.token.property {
82 color: #c08b30;
83}
84
85.token.tag {
86 color: #3d8fd1;
87}
88
89.token.string {
90 color: #22a2c9;
91}
92
93.token.selector {
94 color: #6679cc;
95}
96
97.token.attr-name {
98 color: #c76b29;
99}
100
101.token.entity,
102.token.url,
103.language-css .token.string,
104.style .token.string {
105 color: #22a2c9;
106}
107
108.token.attr-value,
109.token.keyword,
110.token.control,
111.token.directive,
112.token.unit {
113 color: #ac9739;
114}
115
116.token.statement,
117.token.regex,
118.token.atrule {
119 color: #22a2c9;
120}
121
122.token.placeholder,
123.token.variable {
124 color: #3d8fd1;
125}
126
127.token.deleted {
128 text-decoration: line-through;
129}
130
131.token.inserted {
132 border-bottom: 1px dotted #202746;
133 text-decoration: none;
134}
135
136.token.italic {
137 font-style: italic;
138}
139
140.token.important,
141.token.bold {
142 font-weight: bold;
143}
144
145.token.important {
146 color: #c94922;
147}
148
149.token.entity {
150 cursor: help;
151}
152
153pre > code.highlight {
154 outline: 0.4em solid #c94922;
155 outline-offset: .4em;
156}
157
158/* overrides color-values for the Line Numbers plugin
159 * http://prismjs.com/plugins/line-numbers/
160 */
161.line-numbers .line-numbers-rows {
162 border-right-color: #dfe2f1;
163}
164
165.line-numbers-rows > span:before {
166 color: #979db4;
167}
168
169/* overrides color-values for the Line Highlight plugin
170 * http://prismjs.com/plugins/line-highlight/
171 */
172.line-highlight {
173 background: rgba(107, 115, 148, 0.2);
174 background: -webkit-linear-gradient(left, rgba(107, 115, 148, 0.2) 70%, rgba(107, 115, 148, 0));
175 background: linear-gradient(to right, rgba(107, 115, 148, 0.2) 70%, rgba(107, 115, 148, 0));
176}
diff --git a/doc/docs/.vuepress/theme/styles/config.styl b/doc/docs/.vuepress/theme/styles/config.styl
new file mode 100644
index 0000000..9e40321
--- /dev/null
+++ b/doc/docs/.vuepress/theme/styles/config.styl
@@ -0,0 +1 @@
$contentClass = '.theme-default-content'
diff --git a/doc/docs/.vuepress/theme/styles/custom-blocks.styl b/doc/docs/.vuepress/theme/styles/custom-blocks.styl
new file mode 100644
index 0000000..5b86816
--- /dev/null
+++ b/doc/docs/.vuepress/theme/styles/custom-blocks.styl
@@ -0,0 +1,44 @@
1.custom-block
2 .custom-block-title
3 font-weight 600
4 margin-bottom -0.4rem
5 &.tip, &.warning, &.danger
6 padding .1rem 1.5rem
7 border-left-width .5rem
8 border-left-style solid
9 margin 1rem 0
10 &.tip
11 background-color #f3f5f7
12 border-color #42b983
13 &.warning
14 background-color rgba(255,229,100,.3)
15 border-color darken(#ffe564, 35%)
16 color darken(#ffe564, 70%)
17 .custom-block-title
18 color darken(#ffe564, 50%)
19 a
20 color $textColor
21 &.danger
22 background-color #ffe6e6
23 border-color darken(red, 20%)
24 color darken(red, 70%)
25 .custom-block-title
26 color darken(red, 40%)
27 a
28 color $textColor
29 &.details
30 display block
31 position relative
32 border-radius 2px
33 margin 1.6em 0
34 padding 1.6em
35 background-color #eee
36 h4
37 margin-top 0
38 figure, p
39 &:last-child
40 margin-bottom 0
41 padding-bottom 0
42 summary
43 outline none
44 cursor pointer
diff --git a/doc/docs/.vuepress/theme/styles/index.styl b/doc/docs/.vuepress/theme/styles/index.styl
new file mode 100644
index 0000000..ecef658
--- /dev/null
+++ b/doc/docs/.vuepress/theme/styles/index.styl
@@ -0,0 +1,202 @@
1@require './config'
2@require './code'
3@require './custom-blocks'
4@require './arrow'
5@require './wrapper'
6@require './toc'
7
8html, body
9 padding 0
10 margin 0
11 background-color #fff
12
13body
14 font-family -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif
15 -webkit-font-smoothing antialiased
16 -moz-osx-font-smoothing grayscale
17 font-size 16px
18 color $textColor
19
20.page
21 padding-left $sidebarWidth
22
23.navbar
24 position fixed
25 z-index 20
26 top 0
27 left 0
28 right 0
29 height $navbarHeight
30 background-color #fff
31 box-sizing border-box
32 border-bottom 1px solid $borderColor
33
34.sidebar-mask
35 position fixed
36 z-index 9
37 top 0
38 left 0
39 width 100vw
40 height 100vh
41 display none
42
43.sidebar
44 font-size 16px
45 background-color #fff
46 width $sidebarWidth
47 position fixed
48 z-index 10
49 margin 0
50 top $navbarHeight
51 left 0
52 bottom 0
53 box-sizing border-box
54 border-right 1px solid $borderColor
55 overflow-y auto
56
57{$contentClass}:not(.custom)
58 @extend $wrapper
59 > *:first-child
60 margin-top $navbarHeight
61
62 a:hover
63 text-decoration underline
64
65 p.demo
66 padding 1rem 1.5rem
67 border 1px solid #ddd
68 border-radius 4px
69
70 img
71 max-width 100%
72
73{$contentClass}.custom
74 padding 0
75 margin 0
76
77 img
78 max-width 100%
79
80a
81 font-weight 500
82 color $accentColor
83 text-decoration none
84
85p a code
86 font-weight 400
87 color $accentColor
88
89kbd
90 background #eee
91 border solid 0.15rem #ddd
92 border-bottom solid 0.25rem #ddd
93 border-radius 0.15rem
94 padding 0 0.15em
95
96blockquote
97 font-size 1rem
98 color #999;
99 border-left .2rem solid #dfe2e5
100 margin 1rem 0
101 padding .25rem 0 .25rem 1rem
102
103 & > p
104 margin 0
105
106ul, ol
107 padding-left 1.2em
108
109strong
110 font-weight 600
111
112h1, h2, h3, h4, h5, h6
113 font-weight 600
114 line-height 1.25
115
116 {$contentClass}:not(.custom) > &
117 margin-top (0.5rem - $navbarHeight)
118 padding-top ($navbarHeight + 1rem)
119 margin-bottom 0
120
121 &:first-child
122 margin-top -1.5rem
123 margin-bottom 1rem
124
125 + p, + pre, + .custom-block
126 margin-top 2rem
127
128 &:focus .header-anchor,
129 &:hover .header-anchor
130 opacity: 1
131
132h1
133 font-size 2.2rem
134
135h2
136 font-size 1.65rem
137 padding-bottom .3rem
138 border-bottom 1px solid $borderColor
139
140h3
141 font-size 1.35rem
142
143a.header-anchor
144 font-size 0.85em
145 float left
146 margin-left -0.87em
147 padding-right 0.23em
148 margin-top 0.125em
149 opacity 0
150
151 &:focus,
152 &:hover
153 text-decoration none
154
155code, kbd, .line-number
156 font-family Consolas, Menlo, Monaco, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", "Courier New", Courier, monospace
157
158p, ul, ol
159 line-height 1.7
160
161hr
162 border 0
163 border-top 1px solid $borderColor
164
165table
166 border-collapse collapse
167 margin 1rem 0
168 display: block
169 overflow-x: auto
170
171tr
172 border-top 1px solid #dfe2e5
173
174 &:nth-child(2n)
175 background-color #f6f8fa
176
177th, td
178 border 1px solid #dfe2e5
179 padding .6em 1em
180
181.theme-container
182 &.sidebar-open
183 .sidebar-mask
184 display: block
185
186 &.no-navbar
187 {$contentClass}:not(.custom) > h1, h2, h3, h4, h5, h6
188 margin-top 1.5rem
189 padding-top 0
190
191 .sidebar
192 top 0
193
194@media (min-width: ($MQMobile + 1px))
195 .theme-container.no-sidebar
196 .sidebar
197 display none
198
199 .page
200 padding-left 0
201
202@require 'mobile.styl'
diff --git a/doc/docs/.vuepress/theme/styles/mobile.styl b/doc/docs/.vuepress/theme/styles/mobile.styl
new file mode 100644
index 0000000..f5bd327
--- /dev/null
+++ b/doc/docs/.vuepress/theme/styles/mobile.styl
@@ -0,0 +1,37 @@
1@require './config'
2
3$mobileSidebarWidth = $sidebarWidth * 0.82
4
5// narrow desktop / iPad
6@media (max-width: $MQNarrow)
7 .sidebar
8 font-size 15px
9 width $mobileSidebarWidth
10 .page
11 padding-left $mobileSidebarWidth
12
13// wide mobile
14@media (max-width: $MQMobile)
15 .sidebar
16 top 0
17 padding-top $navbarHeight
18 transform translateX(-100%)
19 transition transform .2s ease
20 .page
21 padding-left 0
22 .theme-container
23 &.sidebar-open
24 .sidebar
25 transform translateX(0)
26 &.no-navbar
27 .sidebar
28 padding-top: 0
29
30// narrow mobile
31@media (max-width: $MQMobileNarrow)
32 h1
33 font-size 1.9rem
34 {$contentClass}
35 div[class*="language-"]
36 margin 0.85rem -1.5rem
37 border-radius 0
diff --git a/doc/docs/.vuepress/theme/styles/toc.styl b/doc/docs/.vuepress/theme/styles/toc.styl
new file mode 100644
index 0000000..d3e7106
--- /dev/null
+++ b/doc/docs/.vuepress/theme/styles/toc.styl
@@ -0,0 +1,3 @@
1.table-of-contents
2 .badge
3 vertical-align middle
diff --git a/doc/docs/.vuepress/theme/styles/wrapper.styl b/doc/docs/.vuepress/theme/styles/wrapper.styl
new file mode 100644
index 0000000..a99262c
--- /dev/null
+++ b/doc/docs/.vuepress/theme/styles/wrapper.styl
@@ -0,0 +1,9 @@
1$wrapper
2 max-width $contentWidth
3 margin 0 auto
4 padding 2rem 2.5rem
5 @media (max-width: $MQNarrow)
6 padding 2rem
7 @media (max-width: $MQMobileNarrow)
8 padding 1.5rem
9
diff --git a/doc/docs/.vuepress/theme/util/index.js b/doc/docs/.vuepress/theme/util/index.js
new file mode 100644
index 0000000..92fcd3b
--- /dev/null
+++ b/doc/docs/.vuepress/theme/util/index.js
@@ -0,0 +1,244 @@
1export const hashRE = /#.*$/
2export const extRE = /\.(md|html)$/
3export const endingSlashRE = /\/$/
4export const outboundRE = /^[a-z]+:/i
5
6export function normalize (path) {
7 return decodeURI(path)
8 .replace(hashRE, '')
9 .replace(extRE, '')
10}
11
12export function getHash (path) {
13 const match = path.match(hashRE)
14 if (match) {
15 return match[0]
16 }
17}
18
19export function isExternal (path) {
20 return outboundRE.test(path)
21}
22
23export function isMailto (path) {
24 return /^mailto:/.test(path)
25}
26
27export function isTel (path) {
28 return /^tel:/.test(path)
29}
30
31export function ensureExt (path) {
32 if (isExternal(path)) {
33 return path
34 }
35 const hashMatch = path.match(hashRE)
36 const hash = hashMatch ? hashMatch[0] : ''
37 const normalized = normalize(path)
38
39 if (endingSlashRE.test(normalized)) {
40 return path
41 }
42 return normalized + '.html' + hash
43}
44
45export function isActive (route, path) {
46 const routeHash = decodeURIComponent(route.hash)
47 const linkHash = getHash(path)
48 if (linkHash && routeHash !== linkHash) {
49 return false
50 }
51 const routePath = normalize(route.path)
52 const pagePath = normalize(path)
53 return routePath === pagePath
54}
55
56export function resolvePage (pages, rawPath, base) {
57 if (isExternal(rawPath)) {
58 return {
59 type: 'external',
60 path: rawPath
61 }
62 }
63 if (base) {
64 rawPath = resolvePath(rawPath, base)
65 }
66 const path = normalize(rawPath)
67 for (let i = 0; i < pages.length; i++) {
68 if (normalize(pages[i].regularPath) === path) {
69 return Object.assign({}, pages[i], {
70 type: 'page',
71 path: ensureExt(pages[i].path)
72 })
73 }
74 }
75 console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`)
76 return {}
77}
78
79function resolvePath (relative, base, append) {
80 const firstChar = relative.charAt(0)
81 if (firstChar === '/') {
82 return relative
83 }
84
85 if (firstChar === '?' || firstChar === '#') {
86 return base + relative
87 }
88
89 const stack = base.split('/')
90
91 // remove trailing segment if:
92 // - not appending
93 // - appending to trailing slash (last segment is empty)
94 if (!append || !stack[stack.length - 1]) {
95 stack.pop()
96 }
97
98 // resolve relative path
99 const segments = relative.replace(/^\//, '').split('/')
100 for (let i = 0; i < segments.length; i++) {
101 const segment = segments[i]
102 if (segment === '..') {
103 stack.pop()
104 } else if (segment !== '.') {
105 stack.push(segment)
106 }
107 }
108
109 // ensure leading slash
110 if (stack[0] !== '') {
111 stack.unshift('')
112 }
113
114 return stack.join('/')
115}
116
117/**
118 * @param { Page } page
119 * @param { string } regularPath
120 * @param { SiteData } site
121 * @param { string } localePath
122 * @returns { SidebarGroup }
123 */
124export function resolveSidebarItems (page, regularPath, site, localePath) {
125 const { pages, themeConfig } = site
126
127 const localeConfig = localePath && themeConfig.locales
128 ? themeConfig.locales[localePath] || themeConfig
129 : themeConfig
130
131 const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
132 if (pageSidebarConfig === 'auto') {
133 return resolveHeaders(page)
134 }
135
136 const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
137 if (!sidebarConfig) {
138 return []
139 } else {
140 const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
141 if (config === 'auto') {
142 return resolveHeaders(page)
143 }
144 return config
145 ? config.map(item => resolveItem(item, pages, base))
146 : []
147 }
148}
149
150/**
151 * @param { Page } page
152 * @returns { SidebarGroup }
153 */
154function resolveHeaders (page) {
155 const headers = groupHeaders(page.headers || [])
156 return [{
157 type: 'group',
158 collapsable: false,
159 title: page.title,
160 path: null,
161 children: headers.map(h => ({
162 type: 'auto',
163 title: h.title,
164 basePath: page.path,
165 path: page.path + '#' + h.slug,
166 children: h.children || []
167 }))
168 }]
169}
170
171export function groupHeaders (headers) {
172 // group h3s under h2
173 headers = headers.map(h => Object.assign({}, h))
174 let lastH2
175 headers.forEach(h => {
176 if (h.level === 2) {
177 lastH2 = h
178 } else if (lastH2) {
179 (lastH2.children || (lastH2.children = [])).push(h)
180 }
181 })
182 return headers.filter(h => h.level === 2)
183}
184
185export function resolveNavLinkItem (linkItem) {
186 return Object.assign(linkItem, {
187 type: linkItem.items && linkItem.items.length ? 'links' : 'link'
188 })
189}
190
191/**
192 * @param { Route } route
193 * @param { Array<string|string[]> | Array<SidebarGroup> | [link: string]: SidebarConfig } config
194 * @returns { base: string, config: SidebarConfig }
195 */
196export function resolveMatchingConfig (regularPath, config) {
197 if (Array.isArray(config)) {
198 return {
199 base: '/',
200 config: config
201 }
202 }
203 for (const base in config) {
204 if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) {
205 return {
206 base,
207 config: config[base]
208 }
209 }
210 }
211 return {}
212}
213
214function ensureEndingSlash (path) {
215 return /(\.html|\/)$/.test(path)
216 ? path
217 : path + '/'
218}
219
220function resolveItem (item, pages, base, groupDepth = 1) {
221 if (typeof item === 'string') {
222 return resolvePage(pages, item, base)
223 } else if (Array.isArray(item)) {
224 return Object.assign(resolvePage(pages, item[0], base), {
225 title: item[1]
226 })
227 } else {
228 const children = item.children || []
229 if (children.length === 0 && item.path) {
230 return Object.assign(resolvePage(pages, item.path, base), {
231 title: item.title
232 })
233 }
234 return {
235 type: 'group',
236 path: item.path,
237 title: item.title,
238 sidebarDepth: item.sidebarDepth,
239 initialOpenGroupIndex: item.initialOpenGroupIndex,
240 children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)),
241 collapsable: item.collapsable !== false
242 }
243 }
244}
diff --git a/doc/docs/README.md b/doc/docs/README.md
new file mode 100755
index 0000000..dfc01d1
--- /dev/null
+++ b/doc/docs/README.md
@@ -0,0 +1,8 @@
1---
2home: true
3heroImage: ./image/yuescript.svg
4tagline: A language that compiles to Lua
5actionText: Quick Start →
6actionLink: /doc/
7footer: Made by Jin with ❤️
8---
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md
new file mode 100755
index 0000000..0d43d04
--- /dev/null
+++ b/doc/docs/doc/README.md
@@ -0,0 +1,594 @@
1---
2sidebar: auto
3---
4
5<CompilerModal />
6
7# Yuescript
8<img src="/image/yuescript.svg" width="300" height="300" alt="logo"/>
9
10## Introduction
11
12Yuescript is a dynamic language that compiles to Lua. The codes written in Yuescript are expressive and extremely concise. And it is suitable for writing some changing application logic with more maintainable codes and runs in a Lua embeded environment such as games or website servers.
13
14Yue (月) is the name of moon in Chinese and it's pronounced as [jyɛ].
15
16### An Overview of Yuescript
17```moonscript
18-- import syntax
19import "yue" as :p, :to_lua
20
21-- implicit objects
22inventory =
23 equipment:
24 * "sword"
25 * "shield"
26 items:
27 * name: "potion"
28 count: 10
29 * name: "bread"
30 count: 3
31
32-- backcall
33{1, 2, 3}
34 |> map (x)-> x * 2
35 |> filter (x)-> x > 4
36 |> reduce 0, (a, b)-> a + b
37 |> print
38
39-- metatable manipulation
40apple =
41 size: 15
42 index#: {color: 0x00ffff}
43p apple.color, apple.#?, apple.index#
44
45-- js-like export syntax
46export yuescript = "月之脚本"
47```
48<YueDisplay>
49<pre>
50-- import syntax
51import "yue" as :p, :to_lua
52
53-- implicit objects
54inventory =
55 equipment:
56 * "sword"
57 * "shield"
58 items:
59 * name: "potion"
60 count: 10
61 * name: "bread"
62 count: 3
63
64-- backcall
65{1, 2, 3}
66 |> map (x)-> x * 2
67 |> filter (x)-> x > 4
68 |> reduce 0, (a, b)-> a + b
69 |> print
70
71-- metatable manipulation
72apple =
73 size: 15
74 index#: {color: 0x00ffff}
75p apple.color, apple.#?, apple.index#
76
77-- js-like export syntax
78export yuescript = "月之脚本"
79</pre>
80</YueDisplay>
81
82## Installation
83
84* **Lua Module**
85
86&emsp;&emsp;Install [luarocks](https://luarocks.org), a package manager for Lua modules. Then install it as a Lua module and executable with:
87
88```
89> luarocks install yuescript
90```
91
92&emsp;&emsp;Or you can build `yue.so` file with:
93
94```
95> make shared LUAI=/usr/local/include/lua LUAL=/usr/local/lib/lua
96```
97
98&emsp;&emsp;Then get the binary file from path **bin/shared/yue.so**.
99
100* **Binary Tool**
101
102&emsp;&emsp;Clone this repo, then build and install executable with:
103```
104> make install
105```
106
107&emsp;&emsp;Build Yuescript tool without macro feature:
108```
109> make install NO_MACRO=true
110```
111
112&emsp;&emsp;Build Yuescript tool without built-in Lua binary:
113```
114> make install NO_LUA=true
115```
116
117## Usage
118
119&emsp;&emsp;Require the Yuescript module in Lua:
120```Lua
121-- require `main.yue` in Lua
122require("yue")("main")
123
124-- use the Yuescript compiler in Lua
125local yue = require("yue")
126local codes, err, globals = yue.to_lua([[
127f = ->
128 print "hello world"
129f!
130]],{
131 implicit_return_root = true,
132 reserve_line_number = true,
133 lint_global = true
134})
135```
136&emsp;&emsp;Use Yuescript tool with:
137```
138> yue -h
139Usage: yue [options|files|directories] ...
140
141 -h Print this message
142 -e str Execute a file or raw codes
143 -t path Specify where to place compiled files
144 -o file Write output to file
145 -s Use spaces in generated codes instead of tabs
146 -m Generate minified codes
147 -p Write output to standard out
148 -b Dump compile time (doesn't write output)
149 -l Write line numbers from source codes
150 -v Print version
151 -- Read from standard in, print to standard out
152 (Must be first and only argument)
153
154 Execute without options to enter REPL, type symbol '$'
155 in a single line to start/stop multi-line mode
156```
157&emsp;&emsp;Use cases:
158&emsp;&emsp;Recursively compile every Yuescript file with extension **.yue** under current path: **yue .**
159&emsp;&emsp;Compile and save results to a target path: **yue -t /target/path/ .**
160&emsp;&emsp;Compile and reserve debug info: **yue -l .**
161&emsp;&emsp;Compile and generate minified codes: **yue -m .**
162&emsp;&emsp;Execute raw codes: **yue -e 'print 123'**
163&emsp;&emsp;Execute a Yuescript file: **yue -e main.yue**
164
165## Macro
166
167### Common Usage
168Macro function is used for evaluating a string in the compile time and insert the generated codes into final compilation.
169
170```moonscript
171macro config = (debugging)->
172 global debugMode = debugging == "true"
173 ""
174
175macro asserts = (cond)->
176 debugMode and "assert #{cond}" or ""
177
178macro assert = (cond)->
179 debugMode and "assert #{cond}" or "#{cond}"
180
181$config true
182$asserts item ~= nil
183
184$config false
185value = $assert item
186
187-- the passed expressions are treated as strings
188macro and = (...)-> "#{ table.concat {...}, ' and ' }"
189if $and f1!, f2!, f3!
190 print "OK"
191```
192<YueDisplay>
193<pre>
194macro config = (debugging)->
195 global debugMode = debugging == "true"
196 ""
197
198macro asserts = (cond)->
199 debugMode and "assert #{cond}" or ""
200
201macro assert = (cond)->
202 debugMode and "assert #{cond}" or "#{cond}"
203
204$config true
205$asserts item ~= nil
206
207$config false
208value = $assert item
209
210-- the passed expressions are treated as strings
211macro and = (...)-> "#{ table.concat {...}, ' and ' }"
212if $and f1!, f2!, f3!
213 print "OK"
214</pre>
215</YueDisplay>
216
217### Insert Raw Codes
218
219A macro function can either return a Yuescript string or a config table containing Lua codes.
220```moonscript
221macro yueFunc = (var)-> "local #{var} = ->"
222$yueFunc funcA
223funcA = -> "assign the Yue defined variable"
224
225-- take care and let Yuescript know the
226-- local variables you declared in Lua code
227macro luaFunc = (var)-> {
228 codes: "local function #{var}() end"
229 type: "lua"
230 locals: {var}
231}
232$luaFunc funcB
233funcB = -> "assign the Lua defined variable"
234
235macro lua = (code)-> {
236 :code
237 type: "lua"
238}
239
240-- the raw string leading and ending symbols are auto trimed
241$lua[==[
242-- raw Lua codes insertion
243if cond then
244 print("output")
245end
246]==]
247```
248<YueDisplay>
249<pre>
250macro yueFunc = (var)-> "local #{var} = ->"
251$yueFunc funcA
252funcA = -> "assign the Yue defined variable"
253
254-- take care and let Yuescript know the
255-- local variables you declared in Lua codes
256macro luaFunc = (var)-> {
257 codes: "local function #{var}() end"
258 type: "lua"
259 locals: {var}
260}
261$luaFunc funcB
262funcB = -> "assign the Lua defined variable"
263
264macro lua = (code)-> {
265 :code
266 type: "lua"
267}
268
269-- the raw string leading and ending symbols are auto trimed
270$lua[==[
271-- raw Lua codes insertion
272if cond then
273 print("output")
274end
275]==]
276</pre>
277</YueDisplay>
278
279### Export Macro
280
281Macro functions can be exported from a module and get imported in another module. It is recommanded to export macro functions in a single file to speed up compilation.
282```moonscript
283-- file: utils.yue
284export macro map = (items, action)-> "[#{action} for _ in *#{items}]"
285export macro filter = (items, action)-> "[_ for _ in *#{items} when #{action}]"
286export macro foreach = (items, action)-> "for _ in *#{items}
287 #{action}"
288
289-- file main.yue
290import "utils" as {
291 $, -- symbol to import all macros
292 $foreach: $each -- rename macro $foreach to $each
293}
294{1, 2, 3} |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
295```
296<YueDisplay>
297<pre>
298-- file: utils.yue
299export macro map = (items, action)-> "[#{action} for _ in *#{items}]"
300export macro filter = (items, action)-> "[_ for _ in *#{items} when #{action}]"
301export macro foreach = (items, action)-> "for _ in *#{items}
302 #{action}"
303
304-- file main.yue
305-- import function is not available in browser, try it in a real environment
306--[[
307import "utils" as {
308 $, -- symbol to import all macros
309 $foreach: $each -- rename macro $foreach to $each
310}
311{1, 2, 3} |> $map(_ * 2) |> $filter(_ > 4) |> $each print _
312]]
313</pre>
314</YueDisplay>
315
316## Special Operator
317
318### Metatable
319
320The **#** operator can be used as a shortcut for metatable manipulation.
321
322* **Metatable Creation**
323Create normal table with key **#** or metamethod key that ends with **#**.
324
325```moonscript
326mt = {}
327add = (right)=> #: mt, value: @value + right.value
328mt.__add = add
329
330a = #: mt, value: 1
331 -- set field with variable of the same name
332b = :add#, value: 2
333c = add#: mt.__add, value: 3
334
335d = a + b + c
336print d.value
337
338close _ = close#: -> print "out of scope"
339```
340<YueDisplay>
341<pre>
342mt = {}
343add = (right)=> #: mt, value: @value + right.value
344mt.__add = add
345
346a = #: mt, value: 1
347 -- set field with variable of the same name
348b = :add#, value: 2
349c = add#: mt.__add, value: 3
350
351d = a + b + c
352print d.value
353
354close _ = close#: -> print "out of scope"
355</pre>
356</YueDisplay>
357
358* **Metatable Accessing**
359Accessing metatable with key **#** or metamethod key that ends with **#**.
360
361```moonscript
362-- create with metatable containing field "value"
363tb = ["value"]#: 123
364tb.index# = tb.#
365print tb.value
366
367tb.# = __index: {item: "hello"}
368print tb.item
369```
370<YueDisplay>
371<pre>
372-- create with metatable containing field "value"
373tb = ["value"]#: 123
374tb.index# = tb.#
375print tb.value
376
377tb.# = __index: {item: "hello"}
378print tb.item
379</pre>
380</YueDisplay>
381
382* **Metatable Destructure**
383Destruct metatable with metamethod key that ends with **#**.
384
385```moonscript
386{item, :new, :close#, index#: getter} = tb
387print item, new, close, getter
388```
389<YueDisplay>
390<pre>
391{item, :new, :close#, index#: getter} = tb
392print item, new, close, getter
393</pre>
394</YueDisplay>
395
396### Existence
397
398The **?** operator can be used in a variety of contexts to check for existence.
399
400```moonscript
401func?!
402print abc?["hello world"]?.xyz
403
404x = tab?.value
405len = utf8?.len or string?.len or (o)-> #o
406
407if print and x?
408 print x
409
410with? io.open "test.txt", "w"
411 \write "hello"
412 \close!
413```
414<YueDisplay>
415<pre>
416func?!
417print abc?["hello world"]?.xyz
418
419x = tab?.value
420len = utf8?.len or string?.len or (o)-> #o
421
422if print and x?
423 print x
424
425with? io.open "test.txt", "w"
426 \write "hello"
427 \close!
428</pre>
429</YueDisplay>
430
431### Piping
432
433Instead of a series of nested function calls, you can pipe values with operator **|>**.
434```moonscript
435"hello" |> print
4361 |> print 2 -- insert pipe item as the first argument
4372 |> print 1, _, 3 -- pipe with a placeholder
438
439-- pipe expression in multiline
440readFile "example.txt"
441 |> extract language, {}
442 |> parse language
443 |> emit
444 |> render
445 |> print
446```
447<YueDisplay>
448<pre>
449"hello" |> print
4501 |> print 2 -- insert pipe item as the first argument
4512 |> print 1, _, 3 -- pipe with a placeholder
452
453-- pipe expression in multiline
454readFile "example.txt"
455 |> extract language, {}
456 |> parse language
457 |> emit
458 |> render
459 |> print
460</pre>
461</YueDisplay>
462
463## Module
464
465### Import
466
467The import statement is a syntax sugar for requiring a module or help extracting items from an imported module.
468
469```moonscript
470-- used as table destructure
471do
472 import C, Ct, Cmt from require "lpeg"
473 import insert, concat from table
474
475-- shortcut for requring a module
476do
477 import 'module'
478 import 'module_x'
479 import "d-a-s-h-e-s"
480 import "module.part"
481
482-- requring module with aliasing or table destruction
483do
484 import "player" as PlayerModule
485 import "lpeg" as :C, :Ct, :Cmt
486 import "export" as {one, two, Something:{umm:{ch}}}
487```
488<YueDisplay>
489<pre>
490-- used as table destruction
491do
492 import C, Ct, Cmt from require "lpeg"
493 import insert, concat from table
494
495-- shortcut for requring a module
496do
497 import 'module'
498 import 'module_x'
499 import "d-a-s-h-e-s"
500 import "module.part"
501
502-- requring module with aliasing or table destruction
503do
504 import "player" as PlayerModule
505 import "lpeg" as :C, :Ct, :Cmt
506 import "export" as {one, two, Something:{umm:{ch}}}
507</pre>
508</YueDisplay>
509
510### Export
511
512The export statement offers a concise way to define modules.
513
514* **Named Export**
515Named export will define a local variable as well as adding a field in the exported table.
516
517```moonscript
518export a, b, c = 1, 2, 3
519export cool = "cat"
520
521export What = if this
522 "abc"
523else
524 "def"
525
526export y = ->
527 hallo = 3434
528
529export class Something
530 umm: "cool"
531```
532<YueDisplay>
533<pre>
534export a, b, c = 1, 2, 3
535export cool = "cat"
536
537export What = if this
538 "abc"
539else
540 "def"
541
542export y = ->
543 hallo = 3434
544
545export class Something
546 umm: "cool"
547</pre>
548</YueDisplay>
549
550* **Unnamed Export**
551Unnamed export will add the target item into the array part of the exported table.
552
553```moonscript
554d, e, f = 3, 2, 1
555export d, e, f
556
557export if this
558 123
559else
560 456
561
562export with tmp
563 j = 2000
564```
565<YueDisplay>
566<pre>
567d, e, f = 3, 2, 1
568export d, e, f
569
570export if this
571 123
572else
573 456
574
575export with tmp
576 j = 2000
577</pre>
578</YueDisplay>
579
580* **Default Export**
581Using the **default** keyword in export statement to replace the exported table with any thing.
582
583```moonscript
584export default ->
585 print "hello"
586 123
587```
588<YueDisplay>
589<pre>
590export default ->
591 print "hello"
592 123
593</pre>
594</YueDisplay> \ No newline at end of file
diff --git a/doc/docs/try/README.md b/doc/docs/try/README.md
new file mode 100755
index 0000000..d6ba5dd
--- /dev/null
+++ b/doc/docs/try/README.md
@@ -0,0 +1,6 @@
1# Yuescript Online Compiler
2---
3
4Try Yuescript in the browser with WASM.
5
6<YueCompiler />