+ `
+ }
+}
diff --git a/docs/.vitepress/plugins/demo-block/style.scss b/docs/.vitepress/plugins/demo-block/style.scss
new file mode 100644
index 00000000..3278cfd4
--- /dev/null
+++ b/docs/.vitepress/plugins/demo-block/style.scss
@@ -0,0 +1,205 @@
+@media (max-width: 1000px) {
+ .vitepress-plugin-demo-block__h_code {
+ display: none;
+ }
+ .vitepress-plugin-demo-block__app {
+ margin-left: auto !important;
+ margin-right: auto !important;
+ }
+}
+
+.vitepress-plugin-demo-block__wrapper {
+ margin-top: 10px;
+ border: 1px solid #ebebeb;
+ border-radius: 4px;
+ transition: all .2s;
+
+ &.vitepress-plugin-demo-block__horizontal {
+ .vitepress-plugin-demo-block__display {
+ height: 400px;
+ display: flex;
+
+ .vitepress-plugin-demo-block__app {
+ width: 300px;
+ border: 1px solid #ebebeb;
+ box-shadow: 1px 1px 3px #ebebeb;
+ margin-right: 5px;
+ overflow: auto;
+ }
+
+ .vitepress-plugin-demo-block__h_code {
+ flex: 1;
+ overflow: auto;
+ height: 100%;
+
+ > pre {
+ overflow: visible;
+ }
+ }
+ }
+ }
+
+ .vitepress-plugin-demo-block__display {
+ max-height: 400px;
+ overflow: auto;
+ input[type=button] {
+ background-color: buttonface;
+ padding-block: 1px;
+ padding-inline: 6px;
+ cursor: pointer;
+ }
+ }
+ div {
+ box-sizing: border-box;
+ }
+
+ &:hover {
+ box-shadow: 0 0 11px rgba(33,33,33,.2);
+ }
+
+ .vitepress-plugin-demo-block__code {
+ overflow: hidden;
+ height: 0;
+ padding: 0 !important;
+ background-color: #282c34;
+ border-radius: 0 !important;
+ transition: height .5s;
+
+ pre {
+ margin: 0 !important;
+ }
+ }
+
+ .vitepress-plugin-demo-block__display {
+ padding: 20px;
+ border-bottom: 1px solid #ebebeb;
+ }
+
+ .vitepress-plugin-demo-block__footer {
+ position: relative;
+ text-align: center;
+
+ &.vitepress-plugin-demo-block__show-link {
+ .vitepress-plugin-demo-block__jsfiddle,
+ .vitepress-plugin-demo-block__codepen {
+ opacity: 1;
+ }
+
+ .vitepress-plugin-demo-block__expand::before {
+ border-top: none;
+ border-right: 6px solid transparent;
+ border-bottom: 6px solid #ccc;
+ border-left: 6px solid transparent;
+ }
+ }
+
+ &:hover {
+ .vitepress-plugin-demo-block__jsfiddle,
+ .vitepress-plugin-demo-block__codepen,
+ .vitepress-plugin-demo-block__expand span,
+ .vitepress-plugin-demo-block__expand {
+ opacity: 1;
+ }
+
+ .vitepress-plugin-demo-block__expand::before {
+ border-top-color: var(--vp-c-brand-1) !important;
+ border-bottom-color: var(--vp-c-brand-1) !important;
+ }
+
+ svg {
+ fill: var(--vp-c-brand-1) !important;
+ }
+ }
+
+ .vitepress-plugin-demo-block__expand-text {
+ transition: all .5s;
+ opacity: 0;
+ }
+
+ form:nth-last-child(2) {
+ right: 50px;
+ }
+
+ form:last-child {
+ right: 10px;
+ }
+
+ .vitepress-plugin-demo-block__button {
+ border-color: transparent;
+ background-color: transparent;
+ font-size: 14px;
+ color: var(--vp-c-brand-1);
+ cursor: pointer;
+ outline: none;
+ margin: 0;
+ width: 46px;
+ position: relative;
+
+ &:hover::before {
+ content: attr(data-tip);
+ white-space: nowrap;
+ position: absolute;
+ top: -30px;
+ left: 50%;
+ color: #eee;
+ line-height: 1;
+ z-index: 1000;
+ border-radius: 4px;
+ padding: 6px;
+ transform: translateX(-50%);
+ background-color: rgba(0, 0, 0, .8)
+ }
+
+ &:hover::after {
+ content: '' !important;
+ display: block;
+ position: absolute;
+ left: 50%;
+ top: -5px;
+ transform: translateX(-50%);
+ border: 5px solid transparent;
+ border-top-color: rgba(0, 0, 0, .8);
+ }
+
+ svg {
+ width: 34px;
+ height: 20px;
+ fill: #ccc;
+ }
+ }
+
+ .vitepress-plugin-demo-block__jsfiddle,
+ .vitepress-plugin-demo-block__codepen {
+ position: absolute;
+ top: 10px;
+ transition: all .5s;
+ }
+
+ .vitepress-plugin-demo-block__expand {
+ position: relative;
+ width: 100px;
+ height: 40px;
+ margin: 0;
+ color: var(--vp-c-brand-1);
+ font-size: 14px;
+ background-color: transparent;
+ border-color: transparent;
+ outline: none;
+ transition: all .5s;
+ cursor: pointer;
+
+ &::before {
+ content: "";
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ width: 0;
+ height: 0;
+ border-top: 6px solid #ccc;
+ border-right: 6px solid transparent;
+ border-left: 6px solid transparent;
+ transform: translate(-50%, -50%);
+ }
+ }
+ }
+}
diff --git a/docs/.vitepress/plugins/flowchart/index.mjs b/docs/.vitepress/plugins/flowchart/index.mjs
new file mode 100644
index 00000000..17bc7bd2
--- /dev/null
+++ b/docs/.vitepress/plugins/flowchart/index.mjs
@@ -0,0 +1,121 @@
+import hash from 'hash-sum'
+
+export const flowchartPlugin = (md, options = {}) => {
+ options = options || {}
+
+ const openMarker = options.openMarker || '@flowstart'
+ const openChar = openMarker.charCodeAt(0)
+ const closeMarker = options.closeMarker || '@flowend'
+ const closeChar = closeMarker.charCodeAt(0)
+
+ function render (tokens, idx, options, env, self) {
+ const token = tokens[idx]
+ const key = `flowchart_${hash(idx)}`
+ const { content, info } = token
+ return `
`
+ }
+
+ function uml (state, startLine, endLine, silent) {
+ let nextLine
+ let i
+ let autoClosed = false
+ let start = state.bMarks[startLine] + state.tShift[startLine]
+ let max = state.eMarks[startLine]
+
+ // Check out the first character quickly,
+ // this should filter out most of non-uml blocks
+ if (openChar !== state.src.charCodeAt(start)) {
+ return false
+ }
+
+ // Check out the rest of the marker string
+ for (i = 0; i < openMarker.length; ++i) {
+ if (openMarker[i] !== state.src[start + i]) {
+ return false
+ }
+ }
+
+ const markup = state.src.slice(start, start + i)
+ const params = state.src.slice(start + i, max)
+
+ // Since start is found, we can report success here in validation mode
+ if (silent) {
+ return true
+ }
+
+ // Search for the end of the block
+ nextLine = startLine
+
+ for (; ;) {
+ nextLine++
+ if (nextLine >= endLine) {
+ // unclosed block should be autoclosed by end of document.
+ // also block seems to be autoclosed by end of parent
+ break
+ }
+
+ start = state.bMarks[nextLine] + state.tShift[nextLine]
+ max = state.eMarks[nextLine]
+
+ if (start < max && state.sCount[nextLine] < state.blkIndent) {
+ // non-empty line with negative indent should stop the list:
+ // - ```
+ // test
+ break
+ }
+
+ if (closeChar !== state.src.charCodeAt(start)) {
+ // didn't find the closing fence
+ continue
+ }
+
+ if (state.sCount[nextLine] > state.sCount[startLine]) {
+ // closing fence should not be indented with respect of opening fence
+ continue
+ }
+
+ let closeMarkerMatched = true
+ for (i = 0; i < closeMarker.length; ++i) {
+ if (closeMarker[i] !== state.src[start + i]) {
+ closeMarkerMatched = false
+ break
+ }
+ }
+
+ if (!closeMarkerMatched) {
+ continue
+ }
+
+ // make sure tail has spaces only
+ if (state.skipSpaces(start + i) < max) {
+ continue
+ }
+
+ // found!
+ autoClosed = true
+ break
+ }
+
+ const contents = state.src
+ .split('\n')
+ .slice(startLine + 1, nextLine)
+ .join('\n')
+
+ const token = state.push('flowchart', 'fence', 0)
+ token.block = true
+ token.info = params
+ token.content = contents
+ token.map = [startLine, nextLine]
+ token.markup = markup
+
+ state.line = nextLine + (autoClosed ? 1 : 0)
+
+ return true
+ }
+
+ md.block.ruler.before('fence', 'flowchart', uml, {
+ alt: ['paragraph', 'reference', 'blockquote', 'list']
+ })
+
+ md.renderer.rules.flowchart = render
+}
diff --git a/docs/.vitepress/plugins/flowchart/presets/ant.mjs b/docs/.vitepress/plugins/flowchart/presets/ant.mjs
new file mode 100644
index 00000000..43200fca
--- /dev/null
+++ b/docs/.vitepress/plugins/flowchart/presets/ant.mjs
@@ -0,0 +1,50 @@
+import base from './base'
+
+export default Object.assign({}, base, {
+ // style symbol types
+ 'symbols': {
+ start: {
+ 'class': 'start-element',
+ 'font-color': 'white',
+ 'fill': '#595959',
+ 'line-width': '0px'
+ },
+ end: {
+ 'class': 'end-element',
+ 'font-color': 'white',
+ 'fill': '#595959',
+ 'line-width': '0px'
+ },
+ operation: {
+ 'class': 'operation-element',
+ 'font-color': 'white',
+ 'fill': '#1890ff',
+ 'line-width': '0px'
+ },
+ inputoutput: {
+ 'class': 'inputoutput-element',
+ 'font-color': 'white',
+ 'fill': '#1890ff',
+ 'line-width': '0px'
+ },
+ subroutine: {
+ 'class': 'subroutine-element',
+ 'font-color': 'white',
+ 'fill': '#FF485E',
+ 'element-color': '#fff',
+ 'line-color': 'red'
+ },
+ condition: {
+ 'class': 'condition-element',
+ 'font-color': 'white',
+ 'fill': '#FF485E',
+ 'line-width': '0px'
+ },
+ parallel: {
+ 'class': 'parallel-element',
+ 'font-color': 'white',
+ 'fill': '#1890ff',
+ 'line-width': '0px'
+ }
+ }
+})
\ No newline at end of file
diff --git a/docs/.vitepress/plugins/flowchart/presets/base.mjs b/docs/.vitepress/plugins/flowchart/presets/base.mjs
new file mode 100644
index 00000000..cd993d6b
--- /dev/null
+++ b/docs/.vitepress/plugins/flowchart/presets/base.mjs
@@ -0,0 +1,16 @@
+export default {
+ 'x': 0,
+ 'y': 0,
+ 'line-width': 2,
+ 'line-length': 50,
+ 'text-margin': 10,
+ 'font-size': 14,
+ 'font-color': '#8DA1AC',
+ 'line-color': '#8DA1AC',
+ 'element-color': 'black',
+ 'fill': 'white',
+ 'yes-text': 'yes',
+ 'no-text': 'no',
+ 'arrow-end': 'block',
+ 'scale': 1
+}
\ No newline at end of file
diff --git a/docs/.vitepress/plugins/flowchart/presets/index.mjs b/docs/.vitepress/plugins/flowchart/presets/index.mjs
new file mode 100644
index 00000000..086db5aa
--- /dev/null
+++ b/docs/.vitepress/plugins/flowchart/presets/index.mjs
@@ -0,0 +1,9 @@
+import ant from './ant'
+import vue from './vue'
+import pia from './pia'
+
+export default {
+ ant,
+ vue,
+ pia,
+}
\ No newline at end of file
diff --git a/docs/.vitepress/plugins/flowchart/presets/pia.mjs b/docs/.vitepress/plugins/flowchart/presets/pia.mjs
new file mode 100644
index 00000000..b021cd9c
--- /dev/null
+++ b/docs/.vitepress/plugins/flowchart/presets/pia.mjs
@@ -0,0 +1,62 @@
+import base from './base'
+
+export default Object.assign({}, base, {
+ // style symbol types
+ 'line-width': 1,
+ 'symbols': {
+ start: {
+ 'class': 'start-element',
+ 'fill': '#ccc',
+ 'line-width': '1px',
+ 'line-color': '#5c6ac4',
+ 'font-color': '#000',
+ },
+ end: {
+ 'class': 'end-element',
+ 'fill': '#ccc',
+ 'line-width': '1px',
+ 'line-color': '#5c6ac4',
+ 'font-color': '#000',
+ },
+ operation: {
+ 'class': 'operation-element',
+ 'font-color': 'white',
+ 'fill': '#f1f1f1',
+ 'line-width': '1px',
+ 'line-color': '#5c6ac4',
+ 'font-color': '#000',
+ },
+ inputoutput: {
+ 'class': 'inputoutput-element',
+ 'font-color': 'white',
+ 'fill': '#f1f1f1',
+ 'line-width': '1px',
+ 'line-color': '#5c6ac4',
+ 'font-color': '#000',
+ },
+ subroutine: {
+ 'class': 'subroutine-element',
+ 'font-color': 'white',
+ 'fill': '#f1f1f1',
+ 'line-width': '1px',
+ 'line-color': '#5c6ac4',
+ 'font-color': '#000',
+ },
+ condition: {
+ 'class': 'condition-element',
+ 'font-color': 'white',
+ 'fill': '#f1f1f1',
+ 'line-width': '1px',
+ 'line-color': '#5c6ac4',
+ 'font-color': '#000',
+ },
+ parallel: {
+ 'class': 'parallel-element',
+ 'font-color': 'white',
+ 'fill': '#f1f1f1',
+ 'line-width': '1px',
+ 'line-color': '#5c6ac4',
+ 'font-color': '#000',
+ }
+ }
+})
\ No newline at end of file
diff --git a/docs/.vitepress/plugins/flowchart/presets/vue.mjs b/docs/.vitepress/plugins/flowchart/presets/vue.mjs
new file mode 100644
index 00000000..a0df2ee0
--- /dev/null
+++ b/docs/.vitepress/plugins/flowchart/presets/vue.mjs
@@ -0,0 +1,52 @@
+import base from './base'
+
+export default Object.assign({}, base, {
+ // style symbol types
+ 'symbols': {
+ start: {
+ 'class': 'start-element',
+ 'font-color': 'white',
+ 'fill': '#2F495F',
+ 'line-width': '0px',
+ 'rx': '10px',
+ 'ry': '10px'
+ },
+ end: {
+ 'class': 'end-element',
+ 'font-color': 'white',
+ 'fill': '#2F495F',
+ 'line-width': '0px'
+ },
+ operation: {
+ 'class': 'operation-element',
+ 'font-color': 'white',
+ 'fill': '#00BC7D',
+ // 'line-width': '0px'
+ },
+ inputoutput: {
+ 'class': 'inputoutput-element',
+ 'font-color': 'white',
+ 'fill': '#EB4D5D',
+ 'line-width': '0px'
+ },
+ subroutine: {
+ 'class': 'subroutine-element',
+ 'font-color': 'white',
+ 'fill': '#937AC4',
+ 'element-color': '#fff',
+ 'line-color': 'red'
+ },
+ condition: {
+ 'class': 'condition-element',
+ 'font-color': 'white',
+ 'fill': '#FFB500',
+ 'line-width': '0px'
+ },
+ parallel: {
+ 'class': 'parallel-element',
+ 'font-color': 'white',
+ 'fill': '#2F495F',
+ 'line-width': '0px'
+ }
+ }
+})
\ No newline at end of file
diff --git a/docs/.vitepress/theme/custom.sass b/docs/.vitepress/theme/custom.sass
new file mode 100644
index 00000000..6febdaf5
--- /dev/null
+++ b/docs/.vitepress/theme/custom.sass
@@ -0,0 +1,31 @@
+// scrollbar 樣式
+::-webkit-scrollbar
+ width: 6px
+ height: 5px
+::-webkit-scrollbar-track
+ margin: 20px
+::-webkit-scrollbar-track-piece
+ background-color: rgba(0,0,0,.2)
+ -webkit-border-radius: 6px
+::-webkit-scrollbar-thumb:vertical
+ height: 5px
+ background-color: hsla(0,0%,49%,.7)
+ -webkit-border-radius: 6px
+::-webkit-scrollbar-thumb:horizontal
+ width: 5px
+ background-color: hsla(0,0%,49%,.7)
+
+// image-figure 元件
+.image-figure
+ text-align: center
+ margin: 15px 0
+.image-figure img
+ margin: auto
+ width: 90%
+.image-figure figurecaption
+ margin: 10px
+
+// 首頁 logo 背景
+:root
+ --vp-home-hero-image-background-image: linear-gradient(135deg, #FFF 10%, #FFF 100%)
+ --vp-home-hero-image-filter: blur(50px)
diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js
new file mode 100644
index 00000000..6dc2f6de
--- /dev/null
+++ b/docs/.vitepress/theme/index.js
@@ -0,0 +1,26 @@
+import DefaultTheme from 'vitepress/theme'
+import googleAnalytics from 'vitepress-plugin-google-analytics'
+import FlowChart from '../components/FlowChart.vue'
+import Mindmap from '../components/Mindmap.vue'
+import PDF from '../components/PDF.vue'
+import Tree from '../components/Tree.vue'
+import ImageFigure from '../components/ImageFigure.vue'
+import $ from 'jquery'
+import './custom.sass'
+
+export default {
+ ...DefaultTheme,
+ enhanceApp({ app, router, siteData }) {
+ googleAnalytics({
+ id: 'G-SV22CZB2YX',
+ }),
+ app.component('FlowChart', FlowChart)
+ app.component('Mindmap', Mindmap)
+ app.component('PDF', PDF)
+ app.component('Tree', Tree)
+ app.component('ImageFigure', ImageFigure)
+ if (!import.meta.env.SSR) {
+ window.$ = $
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/.vuepress/components/List.vue b/docs/.vuepress/components/List.vue
deleted file mode 100644
index 53ac4fd2..00000000
--- a/docs/.vuepress/components/List.vue
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/.vuepress/components/Mindmap.vue b/docs/.vuepress/components/Mindmap.vue
deleted file mode 100644
index e55816d0..00000000
--- a/docs/.vuepress/components/Mindmap.vue
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/.vuepress/components/PDF.vue b/docs/.vuepress/components/PDF.vue
deleted file mode 100644
index 5f286982..00000000
--- a/docs/.vuepress/components/PDF.vue
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/.vuepress/components/Tree.vue b/docs/.vuepress/components/Tree.vue
deleted file mode 100644
index 2e5c975e..00000000
--- a/docs/.vuepress/components/Tree.vue
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
deleted file mode 100644
index e32796de..00000000
--- a/docs/.vuepress/config.js
+++ /dev/null
@@ -1,69 +0,0 @@
-module.exports = {
- plugins: ['cursor-effects', 'ribbon', 'reading-progress', 'demo-block', 'vuepress-plugin-code-copy', 'register-components', 'flowchart', 'vuepress-plugin-smooth-scroll'],
- title: "泰山職訓前端班課程講義",
- base: '/F2E-book/',
- description: "進入 JavaScript 的世界",
- dest: "public",
- head: [
- [
- "link",
- {
- rel: "icon",
- href: "/favicon.ico"
- }
- ],
- [
- "meta",
- {
- name: "viewport",
- content: "width=device-width,initial-scale=1,user-scalable=no"
- }
- ],
- ['script', { src: 'https://code.jquery.com/jquery-3.4.1.min.js' }],
- ],
- themeConfig: {
- postOrder: "name",
- themePicker: true,
- defaultDark: true,
- footerTheme: false,
- footerYear: false,
- footerCustom: "Made with ❤ by Kento",
- GAID: "UA-131804412-12",
- nav: [
- {
- text: "首頁",
- link: "/",
- icon: "reco-home"
- },
- {
- text: "章節",
- link: "/views/",
- icon: "reco-menu"
- },
- {
- text: "標籤",
- link: "/tag/",
- icon: "reco-tag"
- },
- {
- text: "GitHub",
- link: "https://github.com/rogeraabbccdd/F2E-book",
- icon: "reco-github"
- },
- {
- text: "課程報名",
- link: "https://ttms.etraining.gov.tw/eYVTR/YR008/Detail?BCM_SNO=123724",
- icon: "reco-mail"
- }
- ],
- search: true,
- searchMaxSuggestions: 10,
- sidebar: "auto",
- lastUpdated: "Last Updated",
- author: "Kento",
- startYear: "2019"
- },
- markdown: {
- lineNumbers: true
- }
-};
diff --git a/docs/.vuepress/public/hero.png b/docs/.vuepress/public/hero.png
deleted file mode 100644
index dc853a1d..00000000
Binary files a/docs/.vuepress/public/hero.png and /dev/null differ
diff --git a/docs/.vuepress/public/images/ch16/1.gif b/docs/.vuepress/public/images/ch16/1.gif
deleted file mode 100644
index 76e34f7e..00000000
Binary files a/docs/.vuepress/public/images/ch16/1.gif and /dev/null differ
diff --git a/docs/.vuepress/styles/palette.styl b/docs/.vuepress/styles/palette.styl
deleted file mode 100644
index e2004255..00000000
--- a/docs/.vuepress/styles/palette.styl
+++ /dev/null
@@ -1,2 +0,0 @@
-$accentColor = #52c0fd
-$textColor = #232321
\ No newline at end of file
diff --git a/docs/.vuepress/theme/LICENSE b/docs/.vuepress/theme/LICENSE
deleted file mode 100644
index 84b7cce6..00000000
--- a/docs/.vuepress/theme/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2019 reco_luan
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/docs/.vuepress/theme/components/AlgoliaSearchBox.vue b/docs/.vuepress/theme/components/AlgoliaSearchBox.vue
deleted file mode 100644
index 92ea648a..00000000
--- a/docs/.vuepress/theme/components/AlgoliaSearchBox.vue
+++ /dev/null
@@ -1,156 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Background.vue b/docs/.vuepress/theme/components/Background.vue
deleted file mode 100644
index 666d0143..00000000
--- a/docs/.vuepress/theme/components/Background.vue
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Common.vue b/docs/.vuepress/theme/components/Common.vue
deleted file mode 100644
index 0c509c0e..00000000
--- a/docs/.vuepress/theme/components/Common.vue
+++ /dev/null
@@ -1,210 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/DropdownLink.vue b/docs/.vuepress/theme/components/DropdownLink.vue
deleted file mode 100644
index aa55fac7..00000000
--- a/docs/.vuepress/theme/components/DropdownLink.vue
+++ /dev/null
@@ -1,183 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/DropdownTransition.vue b/docs/.vuepress/theme/components/DropdownTransition.vue
deleted file mode 100644
index 8c711a15..00000000
--- a/docs/.vuepress/theme/components/DropdownTransition.vue
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Footer.vue b/docs/.vuepress/theme/components/Footer.vue
deleted file mode 100644
index da63e498..00000000
--- a/docs/.vuepress/theme/components/Footer.vue
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Home.vue b/docs/.vuepress/theme/components/Home.vue
deleted file mode 100644
index fbb0e551..00000000
--- a/docs/.vuepress/theme/components/Home.vue
+++ /dev/null
@@ -1,237 +0,0 @@
-
-
-
-
-
-
{{ data.heroText || $title || '午后南杂' }}
-
-
{{ data.tagline || $description || 'Welcome to your vuePress-theme-reco site' }}
-
-
-
-
-
-
-
-
-
{{ feature.title }}
-
{{ feature.details }}
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/HomeBlog.vue b/docs/.vuepress/theme/components/HomeBlog.vue
deleted file mode 100644
index e4be3f88..00000000
--- a/docs/.vuepress/theme/components/HomeBlog.vue
+++ /dev/null
@@ -1,419 +0,0 @@
-
-
-
-
{{ data.heroText || $title || '午后南杂' }}
-
-
{{ data.tagline || $description || 'Welcome to your vuePress-theme-reco site' }}
-
-
-
-
-
-
-
{{ $themeConfig.author || $site.title }}
-
{{ $themeConfig.intro }}
-
-
-
-
{{getPagesLength}}
- 文章
-
-
-
{{$tags.list.length}}
- 標籤
-
-
-
-
分類
-
- -
-
- {{ item.name }}
- {{ item.pages.length }}
-
-
-
-
-
標籤
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/NavLink.vue b/docs/.vuepress/theme/components/NavLink.vue
deleted file mode 100644
index 6c715775..00000000
--- a/docs/.vuepress/theme/components/NavLink.vue
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
- {{ item.text }}
-
-
-
- {{ item.text }}
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/NavLinks.vue b/docs/.vuepress/theme/components/NavLinks.vue
deleted file mode 100644
index d35569ee..00000000
--- a/docs/.vuepress/theme/components/NavLinks.vue
+++ /dev/null
@@ -1,190 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Navbar.vue b/docs/.vuepress/theme/components/Navbar.vue
deleted file mode 100644
index da74d223..00000000
--- a/docs/.vuepress/theme/components/Navbar.vue
+++ /dev/null
@@ -1,134 +0,0 @@
-
-
-
-
-
-
- {{ $siteTitle }}
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/NoteAbstract.vue b/docs/.vuepress/theme/components/NoteAbstract.vue
deleted file mode 100644
index 82d4b737..00000000
--- a/docs/.vuepress/theme/components/NoteAbstract.vue
+++ /dev/null
@@ -1,79 +0,0 @@
-
-
-
-
- {{item.title}}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Pagation.vue b/docs/.vuepress/theme/components/Pagation.vue
deleted file mode 100644
index 3c096473..00000000
--- a/docs/.vuepress/theme/components/Pagation.vue
+++ /dev/null
@@ -1,165 +0,0 @@
-
-
-
- <
- 1
- ...
- {{num}}
- ...
- {{pages}}
- >
- 跳到:
-
- GO
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Page.vue b/docs/.vuepress/theme/components/Page.vue
deleted file mode 100644
index f9300f91..00000000
--- a/docs/.vuepress/theme/components/Page.vue
+++ /dev/null
@@ -1,286 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
- ←
-
- {{ prev.title || prev.path }}
-
-
-
-
-
- {{ next.title || next.path }}
-
- →
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/PageInfo.vue b/docs/.vuepress/theme/components/PageInfo.vue
deleted file mode 100644
index db957e58..00000000
--- a/docs/.vuepress/theme/components/PageInfo.vue
+++ /dev/null
@@ -1,116 +0,0 @@
-
-
-
- {{ pageInfo.frontmatter.author || $themeConfig.author || $site.title }}
-
-
- {{ pageInfo.frontmatter.date | formatDate }}
-
-
-
-
-
-
- {{subItem}}
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Password.vue b/docs/.vuepress/theme/components/Password.vue
deleted file mode 100644
index 1fabf4e0..00000000
--- a/docs/.vuepress/theme/components/Password.vue
+++ /dev/null
@@ -1,315 +0,0 @@
-
-
-
-
{{isPage ? $frontmatter.title : $site.title}}
-
{{$site.description}}
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Sidebar.vue b/docs/.vuepress/theme/components/Sidebar.vue
deleted file mode 100644
index 62f12863..00000000
--- a/docs/.vuepress/theme/components/Sidebar.vue
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/SidebarButton.vue b/docs/.vuepress/theme/components/SidebarButton.vue
deleted file mode 100644
index b8fb4150..00000000
--- a/docs/.vuepress/theme/components/SidebarButton.vue
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/SidebarGroup.vue b/docs/.vuepress/theme/components/SidebarGroup.vue
deleted file mode 100644
index da7b5e8f..00000000
--- a/docs/.vuepress/theme/components/SidebarGroup.vue
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/SidebarLink.vue b/docs/.vuepress/theme/components/SidebarLink.vue
deleted file mode 100644
index da42b898..00000000
--- a/docs/.vuepress/theme/components/SidebarLink.vue
+++ /dev/null
@@ -1,109 +0,0 @@
-
-
-
diff --git a/docs/.vuepress/theme/components/SidebarLinks.vue b/docs/.vuepress/theme/components/SidebarLinks.vue
deleted file mode 100644
index c60c41f9..00000000
--- a/docs/.vuepress/theme/components/SidebarLinks.vue
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/TagList.vue b/docs/.vuepress/theme/components/TagList.vue
deleted file mode 100644
index 3addd077..00000000
--- a/docs/.vuepress/theme/components/TagList.vue
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
- {{item.name}}
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Theme/ThemeOptions.vue b/docs/.vuepress/theme/components/Theme/ThemeOptions.vue
deleted file mode 100644
index eadf2c22..00000000
--- a/docs/.vuepress/theme/components/Theme/ThemeOptions.vue
+++ /dev/null
@@ -1,119 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/components/Theme/index.vue b/docs/.vuepress/theme/components/Theme/index.vue
deleted file mode 100644
index 321f2325..00000000
--- a/docs/.vuepress/theme/components/Theme/index.vue
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/fonts/Cascadia.ttf b/docs/.vuepress/theme/fonts/Cascadia.ttf
deleted file mode 100644
index 9c702a08..00000000
Binary files a/docs/.vuepress/theme/fonts/Cascadia.ttf and /dev/null differ
diff --git a/docs/.vuepress/theme/fonts/font_1030519_r8dx79ig3q.eot b/docs/.vuepress/theme/fonts/font_1030519_r8dx79ig3q.eot
deleted file mode 100644
index d415061c..00000000
Binary files a/docs/.vuepress/theme/fonts/font_1030519_r8dx79ig3q.eot and /dev/null differ
diff --git a/docs/.vuepress/theme/global-components/Badge.vue b/docs/.vuepress/theme/global-components/Badge.vue
deleted file mode 100644
index b3c1b4ce..00000000
--- a/docs/.vuepress/theme/global-components/Badge.vue
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
diff --git a/docs/.vuepress/theme/images/1.png b/docs/.vuepress/theme/images/1.png
deleted file mode 100644
index ec430f8a..00000000
Binary files a/docs/.vuepress/theme/images/1.png and /dev/null differ
diff --git a/docs/.vuepress/theme/images/2.png b/docs/.vuepress/theme/images/2.png
deleted file mode 100644
index a74e73a7..00000000
Binary files a/docs/.vuepress/theme/images/2.png and /dev/null differ
diff --git a/docs/.vuepress/theme/images/3.png b/docs/.vuepress/theme/images/3.png
deleted file mode 100644
index 22376dba..00000000
Binary files a/docs/.vuepress/theme/images/3.png and /dev/null differ
diff --git a/docs/.vuepress/theme/images/4.png b/docs/.vuepress/theme/images/4.png
deleted file mode 100644
index c5ea8bd8..00000000
Binary files a/docs/.vuepress/theme/images/4.png and /dev/null differ
diff --git a/docs/.vuepress/theme/images/5.png b/docs/.vuepress/theme/images/5.png
deleted file mode 100644
index 80bda650..00000000
Binary files a/docs/.vuepress/theme/images/5.png and /dev/null differ
diff --git a/docs/.vuepress/theme/images/6.png b/docs/.vuepress/theme/images/6.png
deleted file mode 100644
index 054ce412..00000000
Binary files a/docs/.vuepress/theme/images/6.png and /dev/null differ
diff --git a/docs/.vuepress/theme/images/home-bg.jpg b/docs/.vuepress/theme/images/home-bg.jpg
deleted file mode 100644
index 02d4a81b..00000000
Binary files a/docs/.vuepress/theme/images/home-bg.jpg and /dev/null differ
diff --git a/docs/.vuepress/theme/images/home-blog.png b/docs/.vuepress/theme/images/home-blog.png
deleted file mode 100644
index 4bb19d5e..00000000
Binary files a/docs/.vuepress/theme/images/home-blog.png and /dev/null differ
diff --git a/docs/.vuepress/theme/images/home-head.png b/docs/.vuepress/theme/images/home-head.png
deleted file mode 100644
index 72247268..00000000
Binary files a/docs/.vuepress/theme/images/home-head.png and /dev/null differ
diff --git a/docs/.vuepress/theme/images/icon_vuepress_reco.png b/docs/.vuepress/theme/images/icon_vuepress_reco.png
deleted file mode 100644
index ac012529..00000000
Binary files a/docs/.vuepress/theme/images/icon_vuepress_reco.png and /dev/null differ
diff --git a/docs/.vuepress/theme/index.js b/docs/.vuepress/theme/index.js
deleted file mode 100644
index 8cfd6054..00000000
--- a/docs/.vuepress/theme/index.js
+++ /dev/null
@@ -1,76 +0,0 @@
-const path = require('path')
-
-// Theme API.
-module.exports = (options, ctx) => ({
- alias () {
- const { themeConfig, siteConfig } = ctx
- // resolve algolia
- const isAlgoliaSearch = (
- themeConfig.algolia ||
- Object.keys(siteConfig.locales && themeConfig.locales || {})
- .some(base => themeConfig.locales[base].algolia)
- )
- return {
- '@AlgoliaSearchBox': isAlgoliaSearch
- ? path.resolve(__dirname, 'components/AlgoliaSearchBox.vue')
- : path.resolve(__dirname, 'noopModule.js')
- }
- },
-
- plugins: [
- '@vuepress-reco/back-to-top',
- '@vuepress-reco/loading-page',
- '@vuepress-reco/pagation',
- '@vuepress-reco/screenfull',
- '@vuepress-reco/ga',
- '@vuepress-reco/comments',
- '@vuepress/active-header-links',
- '@vuepress/medium-zoom',
- '@vuepress/plugin-nprogress',
- '@vuepress/search',
- ['@vuepress/plugin-blog', {
- permalink: '/:regular',
- frontmatters: [
- {
- id: 'tags',
- keys: ['tags'],
- path: '/tag/',
- layout: 'Tags',
- scopeLayout: 'Tag'
- },
- {
- id: 'categories',
- keys: ['categories'],
- path: '/categories/',
- layout: 'Categories',
- scopeLayout: 'Category'
- },
- {
- id: 'timeline',
- keys: ['timeline'],
- path: '/timeline/',
- layout: 'TimeLines',
- scopeLayout: 'TimeLine'
- }
- ]
- }],
- ['container', {
- type: 'tip',
- defaultTitle: {
- '/zh/': '提示'
- }
- }],
- ['container', {
- type: 'warning',
- defaultTitle: {
- '/zh/': '注意'
- }
- }],
- ['container', {
- type: 'danger',
- defaultTitle: {
- '/zh/': '警告'
- }
- }]
- ]
-})
diff --git a/docs/.vuepress/theme/layouts/404.vue b/docs/.vuepress/theme/layouts/404.vue
deleted file mode 100644
index ed5a3a17..00000000
--- a/docs/.vuepress/theme/layouts/404.vue
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
404
-
{{ getMsg() }}
-
Take me home.
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/layouts/Category.vue b/docs/.vuepress/theme/layouts/Category.vue
deleted file mode 100644
index 20a719e3..00000000
--- a/docs/.vuepress/theme/layouts/Category.vue
+++ /dev/null
@@ -1,175 +0,0 @@
-
-
-
-
-
-
- -
-
- {{ item.name }}
- {{ item.pages.length }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/layouts/Layout.vue b/docs/.vuepress/theme/layouts/Layout.vue
deleted file mode 100644
index 98cdafb2..00000000
--- a/docs/.vuepress/theme/layouts/Layout.vue
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/layouts/Tags.vue b/docs/.vuepress/theme/layouts/Tags.vue
deleted file mode 100644
index 777cc752..00000000
--- a/docs/.vuepress/theme/layouts/Tags.vue
+++ /dev/null
@@ -1,134 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/layouts/TimeLines.vue b/docs/.vuepress/theme/layouts/TimeLines.vue
deleted file mode 100644
index e4652376..00000000
--- a/docs/.vuepress/theme/layouts/TimeLines.vue
+++ /dev/null
@@ -1,196 +0,0 @@
-
-
-
-
- - Yesterday Once More!
- -
-
{{item.year}}
-
- -
- {{dateFormat(subItem.frontmatter.date)}}
- {{subItem.title}}
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/.vuepress/theme/mixins/index.js b/docs/.vuepress/theme/mixins/index.js
deleted file mode 100644
index b1515087..00000000
--- a/docs/.vuepress/theme/mixins/index.js
+++ /dev/null
@@ -1,31 +0,0 @@
-export default {
- methods: {
- _tagColor () {
- // 红、蓝、绿、橙、灰
- const tagColorArr = ['#8bc34a', '#673ab7', '#f47e60', '#ff9800', '#f44336', '#00abc0', '#2196f3', '#67cc86', '#fb9b5f']
- const index = Math.floor(Math.random() * tagColorArr.length)
- return tagColorArr[index]
- },
- _filterPostData (posts) {
- posts = posts.filter(item => {
- const { home, date, publish } = item.frontmatter
- return !(home == true || !item.path.match(/\/views\/.*/g) || publish === false)
- })
- return posts
- },
- _sortPostData (posts) {
- posts.sort((a, b) => {
- return this._getTimeNum(b) - this._getTimeNum(a)
- })
- },
- _sortPostDataName (posts) {
- posts.sort((a, b) => {
- return a.title.localeCompare(b.title, "zh-Hant-TW");
- })
- },
- // 获取时间的数字类型
- _getTimeNum (date) {
- return parseInt(new Date(date.frontmatter.date).getTime())
- }
- }
-}
diff --git a/docs/.vuepress/theme/noopModule.js b/docs/.vuepress/theme/noopModule.js
deleted file mode 100644
index b1c6ea43..00000000
--- a/docs/.vuepress/theme/noopModule.js
+++ /dev/null
@@ -1 +0,0 @@
-export default {}
diff --git a/docs/.vuepress/theme/styles/arrow.styl b/docs/.vuepress/theme/styles/arrow.styl
deleted file mode 100644
index 20bffc0d..00000000
--- a/docs/.vuepress/theme/styles/arrow.styl
+++ /dev/null
@@ -1,22 +0,0 @@
-@require './config'
-
-.arrow
- display inline-block
- width 0
- height 0
- &.up
- border-left 4px solid transparent
- border-right 4px solid transparent
- border-bottom 6px solid $arrowBgColor
- &.down
- border-left 4px solid transparent
- border-right 4px solid transparent
- border-top 6px solid $arrowBgColor
- &.right
- border-top 4px solid transparent
- border-bottom 4px solid transparent
- border-left 6px solid $arrowBgColor
- &.left
- border-top 4px solid transparent
- border-bottom 4px solid transparent
- border-right 6px solid $arrowBgColor
diff --git a/docs/.vuepress/theme/styles/cascadia.css b/docs/.vuepress/theme/styles/cascadia.css
deleted file mode 100644
index befe7495..00000000
--- a/docs/.vuepress/theme/styles/cascadia.css
+++ /dev/null
@@ -1,5 +0,0 @@
-@font-face {
- font-family: "Cascadia Code";
- src: local(Cascadia Code),
- url("../fonts/Cascadia.ttf") format("truetype");
-}
diff --git a/docs/.vuepress/theme/styles/code.styl b/docs/.vuepress/theme/styles/code.styl
deleted file mode 100644
index be5a67db..00000000
--- a/docs/.vuepress/theme/styles/code.styl
+++ /dev/null
@@ -1,135 +0,0 @@
-.content__default
- code
- color lighten($textColor, 20%)
- padding 0.25rem 0.5rem
- margin 0
- font-size 0.85em
- background-color rgba(27,31,35,0.05)
- border-radius 3px
- .token
- &.deleted
- color #EC5975
- &.inserted
- color $accentColor
-
-.content__default
- pre, pre[class*="language-"]
- line-height 1.4
- padding 1.25rem 1.5rem
- margin 0.85rem 0
- background-color $codeBgColor
- border-radius 6px
- overflow auto
- code
- color #fff
- padding 0
- background-color transparent
- border-radius 0
-
-div[class*="language-"]
- position relative
- background-color $codeBgColor
- border-radius 6px
- .highlight-lines
- user-select none
- padding-top 1.3rem
- position absolute
- top 0
- left 0
- width 100%
- line-height 1.4
- .highlighted
- background-color rgba(0, 0, 0, 66%)
- pre, pre[class*="language-"]
- background transparent
- position relative
- z-index 1
- &::before
- position absolute
- z-index 3
- top 0.8em
- right 1em
- font-size 0.75rem
- color rgba(255, 255, 255, 0.4)
- &:not(.line-numbers-mode)
- .line-numbers-wrapper
- display none
- &.line-numbers-mode
- .highlight-lines .highlighted
- position relative
- &:before
- content ' '
- position absolute
- z-index 3
- left 0
- top 0
- display block
- width $lineNumbersWrapperWidth
- height 100%
- background-color rgba(0, 0, 0, 66%)
- pre
- padding-left $lineNumbersWrapperWidth + 1 rem
- vertical-align middle
- .line-numbers-wrapper
- position absolute
- top 0
- width $lineNumbersWrapperWidth
- text-align center
- color rgba(255, 255, 255, 0.3)
- padding 1.25rem 0
- line-height 1.4
- br
- user-select none
- .line-number
- position relative
- z-index 4
- user-select none
- font-size 0.85em
- &::after
- content ''
- position absolute
- z-index 2
- top 0
- left 0
- width $lineNumbersWrapperWidth
- height 100%
- border-radius 6px 0 0 6px
- border-right 1px solid rgba(0, 0, 0, 66%)
- background-color $codeBgColor
-
-
-for lang in $codeLang
- div{'[class~="language-' + lang + '"]'}
- &:before
- content ('' + lang)
-
-div[class~="language-javascript"]
- &:before
- content "js"
-
-div[class~="language-typescript"]
- &:before
- content "ts"
-
-div[class~="language-markup"]
- &:before
- content "html"
-
-div[class~="language-markdown"]
- &:before
- content "md"
-
-div[class~="language-json"]:before
- content "json"
-
-div[class~="language-ruby"]:before
- content "rb"
-
-div[class~="language-python"]:before
- content "py"
-
-div[class~="language-bash"]:before
- content "sh"
-
-div[class~="language-php"]:before
- content "php"
diff --git a/docs/.vuepress/theme/styles/colorMixin.styl b/docs/.vuepress/theme/styles/colorMixin.styl
deleted file mode 100644
index f2903041..00000000
--- a/docs/.vuepress/theme/styles/colorMixin.styl
+++ /dev/null
@@ -1,104 +0,0 @@
-@require './recoConfig.styl'
-
-color-mode(accountColor , colorName)
- .reco-theme-{colorName}
- input
- color accountColor!important;
- a.sidebar-link.active
- border-color: accountColor
- color accountColor!important;
- blockquote
- border-color: accountColor
- .search-box input
- border-color: accountColor!important;
- &:focus
- border-color: accountColor!important;
- .navbar
- box-shadow: $boxShadow
- .nav-links a:hover,
- .nav-links a.router-link-active,
- .nav-links a:hover .iconfont,
- .nav-links a.router-link-active .iconfont
- color accountColor!important;
- .home
- .hero
- .action-button
- background-color accountColor!important;
- color: #fff!important
- .footer
- a
- color accountColor!important;
- .home-blog
- .info-wrapper
- .num
- > div, >div i
- color accountColor!important;
- .abstract-wrapper .abstract-item .title
- a
- color accountColor!important;
- a:after
- background-color accountColor!important;
- .back-to-ceiling i
- color accountColor!important;
- .dropdown-wrapper .nav-dropdown .dropdown-item a.router-link-active::after
- border-left: 5px solid accountColor!important;
- .tags
- .tag-item.active, .tag-item:hover
- color accountColor!important;
- .timeline-wrapper .year-wrapper li:hover
- .title
- color accountColor!important;
- .date::before
- background: accountColor!important;
- .date
- color accountColor!important;
- .categories-wrapper
- .category-wrapper
- .category-item
- &:hover, &.active
- background accountColor!important
- a
- span.post-num
- color accountColor!important
- .color-picker
- .color-button
- .iconfont
- color accountColor!important;
- .fullscreen-wrapper
- .iconfont
- color accountColor!important;
- a
- color accountColor;
- a.sidebar-link, a.nav-link, a.dropdown-title
- color $textColor
- a.sidebar-link:hover
- color accountColor!important;
- .password-shadow
- .inputBox
- background: accountColor!important
- input
- color #fff!important
- &:focus~span
- color accountColor!important
- button
- border 1px solid accountColor!important
- color accountColor!important;
- .showBanNiang
- background-color lighten(accountColor, 50%)!important
- .banniang-container
- .messageBox
- background-color lighten(accountColor, 50%)!important
- .operation
- i:hover
- color lighten(accountColor, 50%)!important
-
- @media (min-width: 765px)
- .nav-item > a:not(.external):hover,
- .nav-item > a:not(.external).router-link-active
- border-color: accountColor!important;
- @media (max-width: 959px)
- .search-box input
- border-color: transparent!important;
-
-for key, value in $themePicker
- color-mode(value, key)
diff --git a/docs/.vuepress/theme/styles/custom-blocks.styl b/docs/.vuepress/theme/styles/custom-blocks.styl
deleted file mode 100644
index 8b7fa0f1..00000000
--- a/docs/.vuepress/theme/styles/custom-blocks.styl
+++ /dev/null
@@ -1,32 +0,0 @@
-.custom-block
- .custom-block-title
- font-weight 600
- margin-bottom -0.4rem
- &.tip, &.warning, &.danger
- padding .1rem 1.5rem
- border-left-width .5rem
- border-left-style solid
- margin 1rem 0
- &.tip
- background-color #f3f5f7
- border-color #67cc86
- &.warning
- background-color #fbf0ea
- border-color #fb9b5f
- // color darken(#ffe564, 70%)
- .custom-block-title
- color darken(#ffe564, 50%)
- a
- color $textColor
- &.danger
- background-color #fceaea
- border-color #f26d6d
- // color darken(red, 70%)
- .custom-block-title
- color darken(red, 40%)
- a
- color $textColor
- tr:nth-child(2n)
- background: transparent !important;
-
-
diff --git a/docs/.vuepress/theme/styles/iconfont.css b/docs/.vuepress/theme/styles/iconfont.css
deleted file mode 100644
index 137596b2..00000000
--- a/docs/.vuepress/theme/styles/iconfont.css
+++ /dev/null
@@ -1,156 +0,0 @@
-@font-face {
- font-family:"iconfont";
- src: url('../fonts/font_1030519_r8dx79ig3q.eot');
- /* IE9 */
- src: url('../fonts/font_1030519_r8dx79ig3q.eot') format('embedded-opentype'),
- /* IE6-IE8 */
- url('data:application/x-font-woff2;charset=utf-8;base64,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') format('woff2'), url('//at.alicdn.com/t/font_1030519_r8dx79ig3q.woff?t=1567267716889') format('woff'), url('//at.alicdn.com/t/font_1030519_r8dx79ig3q.ttf?t=1567267716889') format('truetype'),
- /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
- url('//at.alicdn.com/t/font_1030519_r8dx79ig3q.svg?t=1567267716889#iconfont') format('svg');
- /* iOS 4.1- */
-}
-.iconfont {
- font-family:"iconfont" !important;
- font-size: 16px;
- font-style: normal;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
-}
-.reco-douban:before {
- content:"\e603";
-}
-.reco-wechat:before {
- content:"\e720";
-}
-.reco-color:before {
- content:"\eae9";
-}
-.reco-sf:before {
- content:"\e610";
-}
-.reco-message:before {
- content:"\e634";
-}
-.reco-eye:before {
- content:"\e669";
-}
-.reco-search:before {
- content:"\e611";
-}
-.reco-category:before {
- content:"\e61e";
-}
-.reco-npm:before {
- content:"\e88d";
-}
-.reco-menu:before {
- content:"\e67c";
-}
-.reco-suggestion:before {
- content:"\e608";
-}
-.reco-coding:before {
- content:"\e601";
-}
-.reco-github:before {
- content:"\e628";
-}
-.reco-other:before {
- content:"\e60e";
-}
-.reco-home:before {
- content:"\e65b";
-}
-.reco-document:before {
- content:"\e67a";
-}
-.reco-blog:before {
- content:"\e676";
-}
-.reco-huawei:before {
- content:"\e6b9";
-}
-.reco-up:before {
- content:"\e68b";
-}
-.reco-weibo:before {
- content:"\e612";
-}
-.reco-fullscreen:before {
- content:"\e602";
-}
-.reco-tag:before {
- content:"\e633";
-}
-.reco-date:before {
- content:"\e63b";
-}
-.reco-jianshu:before {
- content:"\e60c";
-}
-.reco-bokeyuan:before {
- content:"\e626";
-}
-.reco-beian:before {
- content:"\e667";
-}
-.reco-copyright:before {
- content:"\ef87";
-}
-.reco-bilibili:before {
- content:"\e630";
-}
-.reco-account:before {
- content:"\e607";
-}
-.reco-qq:before {
- content:"\e67b";
-}
-.reco-theme:before {
- content:"\e7e8";
-}
-.reco-three:before {
- content:"\e644";
-}
-.reco-gitlab:before {
- content:"\e63c";
-}
-.reco-api:before {
- content:"\e662";
-}
-.reco-mayun:before {
- content:"\e6d0";
-}
-.reco-zhihu:before {
- content:"\e605";
-}
-.reco-facebook:before {
- content:"\e606";
-}
-.reco-taobao:before {
- content:"\e6a5";
-}
-.reco-tongzhi:before {
- content:"\e764";
-}
-.reco-douyin:before {
- content:"\e654";
-}
-.reco-v2ex:before {
- content:"\e62a";
-}
-.reco-toutiao:before {
- content:"\e6b7";
-}
-.reco-linkedin:before {
- content:"\e668";
-}
-.reco-twitter:before {
- content:"\e60b";
-}
-.reco-csdn:before {
- content:"\e609";
-}
-.reco-juejin:before {
- content:"\e613";
-}
diff --git a/docs/.vuepress/theme/styles/loadMixin.styl b/docs/.vuepress/theme/styles/loadMixin.styl
deleted file mode 100644
index 960afa07..00000000
--- a/docs/.vuepress/theme/styles/loadMixin.styl
+++ /dev/null
@@ -1,11 +0,0 @@
-load-start(){
- transform:translateY(-20px);
- opacity 0
-}
-
-load-end($delayTime){
- transition:all .25s;
- transform:translateY(0);
- transition-delay: $delayTime
- opacity 1
-}
\ No newline at end of file
diff --git a/docs/.vuepress/theme/styles/mobile.styl b/docs/.vuepress/theme/styles/mobile.styl
deleted file mode 100644
index 929598a7..00000000
--- a/docs/.vuepress/theme/styles/mobile.styl
+++ /dev/null
@@ -1,41 +0,0 @@
-// @require './config'
-
-$mobileSidebarWidth = $sidebarWidth * 0.82
-
-// narrow desktop / iPad
-@media (max-width: $MQNarrow)
- .sidebar
- font-size 15px
- width $mobileSidebarWidth
- .page
- padding-left $mobileSidebarWidth
- .password-shadow
- padding-left $mobileSidebarWidth
-
-// wide mobile
-@media (max-width: $MQMobile)
- .sidebar
- top 0
- padding-top $navbarHeight
- transform translateX(-100%)
- transition transform .2s ease
- .page
- padding-left 0
- .theme-container
- &.sidebar-open
- .sidebar
- transform translateX(0)
- &.no-navbar
- .sidebar
- padding-top: 0
- .password-shadow
- padding-left 0
-
-// narrow mobile
-@media (max-width: $MQMobileNarrow)
- h1
- font-size 1.9rem
- .content__default
- div[class*="language-"]
- margin 0.85rem -1.5rem
- border-radius 0
diff --git a/docs/.vuepress/theme/styles/recoConfig.styl b/docs/.vuepress/theme/styles/recoConfig.styl
deleted file mode 100644
index 4fb6633c..00000000
--- a/docs/.vuepress/theme/styles/recoConfig.styl
+++ /dev/null
@@ -1,11 +0,0 @@
-$boxShadow = 0 1px 6px 0 rgba(0, 0, 0, 0.2)
-$boxShadowHover = 0 2px 16px 0 rgba(0, 0, 0, 0.2)
-$textShadow = 0 2px 4px rgba(0, 0, 0, 0.1);
-$borderRadius = .25rem
-
-$themePicker = {
- red: #f26d6d,
- blue: #2196f3,
- green: #3eaf7c,
- orange: #fb9b5f
-}
diff --git a/docs/.vuepress/theme/styles/theme.styl b/docs/.vuepress/theme/styles/theme.styl
deleted file mode 100644
index d9b40d11..00000000
--- a/docs/.vuepress/theme/styles/theme.styl
+++ /dev/null
@@ -1,392 +0,0 @@
-@require './recoConfig'
-@require './code'
-@require './custom-blocks'
-@require './arrow'
-@require './wrapper'
-@require './toc'
-@require './colorMixin'
-@require './iconfont.css'
-@require './cascadia.css'
-
-html, body
- padding 0
- margin 0
- text-shadow: $textShadow
-body
- font-family Ubuntu, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif, "Microsoft JHengHei", "Microsoft Yahei"
- -webkit-font-smoothing antialiased
- -moz-osx-font-smoothing grayscale
- font-size 16px
- color $textColor
- background-color #fff
-
-.page
- padding-left $sidebarWidth
-
-.navbar
- position fixed
- z-index 20
- top 0
- left 0
- right 0
- height $navbarHeight
- background-color #fff
- box-sizing border-box
-
-.sidebar-mask
- position fixed
- z-index 9
- top 0
- left 0
- width 100vw
- height 100vh
- display none
- background-color: rgba(0,0,0,.65);
-
-.sidebar
- font-size 16px
- background-color #fff
- width $sidebarWidth
- position fixed
- z-index 10
- margin 0
- top $navbarHeight
- left 0
- bottom 0
- box-sizing border-box
- border-right 1px solid $borderColor
- overflow-y auto
-
-.content__default:not(.custom)
- @extend $wrapper
- // > *:first-child
- // margin-top 1.6rem
- a:hover
- text-decoration underline
- p.demo
- padding 1rem 1.5rem
- border 1px solid #ddd
- border-radius 4px
- img
- max-width 100%
-
-.content__default.custom
- padding 0
- margin 0
- img
- max-width 100%
-
-a
- font-weight 500
- color $accentColor
- text-decoration none
-
-p a code
- font-weight 400
- color $accentColor
-
-kbd
- background #eee
- border solid 0.15rem #ddd
- border-bottom solid 0.25rem #ddd
- border-radius 0.15rem
- padding 0 0.15em
-
-blockquote
- font-size .9rem
- color #999
- border-left .25rem solid $accentColor
- margin 0.5rem 0
- padding .25rem 0 .25rem 1rem
- & > p
- margin 0
-
-ul, ol
- padding-left 1.2em
-
-strong
- font-weight 600
-
-h1, h2, h3, h4, h5, h6
- font-weight 500
- line-height 1.25
- .content__default:not(.custom) > &
- margin-top (0.5rem - $navbarHeight)
- padding-top ($navbarHeight + 1rem)
- margin-bottom 0
- &:first-child
- margin-top -3.5rem
- margin-bottom 1rem
- + p, + pre, + .custom-block
- margin-top 2rem
- &:hover .header-anchor
- opacity: 1
-
-h1
- font-size 1.95rem
-
-h2
- font-size 1.65rem
- padding-bottom .3rem
- border-bottom 1px solid $borderColor
-
-h3
- font-size 1.35rem
-
-a.header-anchor
- font-size 0.85em
- float left
- margin-left -0.87em
- padding-right 0.23em
- margin-top 0.125em
- opacity 0
- &:hover
- text-decoration none
-
-code, kbd, .line-number
- font-family "Cascadia Code", source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace, "Microsoft JHengHei", , "Microsoft Yahei"
-
-p, ul, ol
- line-height 1.7
-
-hr
- border 0
- border-top 1px solid $borderColor
-
-table
- border-collapse collapse
- margin 1rem 0
- display: block
- overflow-x: auto
-
-tr
- border-top 1px solid #dfe2e5
- &:nth-child(2n)
- background-color #f6f8fa
-
-th, td
- border 1px solid #dfe2e5
- padding .6em 1em
-
-.theme-container
- &.sidebar-open
- .sidebar-mask
- display: block
- &.no-navbar
- .content__default:not(.custom) > h1, h2, h3, h4, h5, h6
- margin-top 1.5rem
- padding-top 0
- .sidebar
- top 0
-
-@media (min-width: ($MQMobile + 1px))
- .theme-container.no-sidebar
- .sidebar
- display none
- .page
- padding-left 0
-
-@require 'mobile.styl'
-
-.iconfont
- font-size: 0.9rem;
- color: #888;
- // &:not(:first-child)
- // margin-left: 1rem
- // span
- // margin-left: .5rem
-
-.iconfont span
- font-family Ubuntu, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif, "Microsoft JHengHei", "Microsoft Yahei"
-/************** 滚动条 **************/
-::-webkit-scrollbar
- width: 6px;
- height: 5px;
-
-::-webkit-scrollbar-track-piece
- background-color: rgba(0, 0, 0, 0.2);
- -webkit-border-radius: 6px;
-
-::-webkit-scrollbar-thumb:vertical
- height: 5px;
- background-color: rgba(125, 125, 125, 0.7);
- -webkit-border-radius: 6px;
-
-::-webkit-scrollbar-thumb:horizontal
- width: 5px;
- background-color: rgba(125, 125, 125, 0.7);
- -webkit-border-radius: 6px;
-
-/************** 流程图的滚动条 **************/
-.vuepress-flowchart
- overflow: auto
-
-/************** 腾讯 404 公益 **************/
-
-.mod_404 .desc {
- .desc_link {
- display: inline-block
- // margin: 20px 0
- background: #424242!important
- color: #ffffff
- padding: 6px 20px!important
- text-decoration: none!important
- border-radius: 4px
- }
-}
-
-@media screen and (max-width: 720px) {
- .mod_404 .desc {
- margin: 50px 0
- }
-}
-
-/************** 评论功能 **************/
-
-.comments-wrapper
- .valine-wrapper
- #valine.v
- .vwrap
- background: #f0f2f4
- // box-shadow: $boxShadow
- .vcontrol
- .vsubmit
- background: #fff
- .vinfo
- padding-left: .6rem
- .vlist
- padding: 0 .6rem
- border-radius: $borderRadius
- .vcard
- .vimg
- border-radius: $borderRadius
- box-shadow: $boxShadow
- border: none
- .vh
- .vhead
- .vsys
- box-shadow: $boxShadow
- .vmeta
- margin-bottom: 1rem
- .vat
- margin-right: .3rem
- background: #f0f2f4
- box-shadow: $boxShadow
- border-radius: $borderRadius
- padding: 0 .4rem
- color: #313131
- border: 1px solid #ededed
- .vcontent
- background: #f0f2f4
- box-shadow: $boxShadow
- border-radius: $borderRadius
- margin: 0 .3rem
- padding: .1rem .6rem .05rem .6rem
- p .at
- color: #1abc9c
- .info
- padding-right: .6rem
-
-/************** 分页 **************/
-.pagation
- .pagation-list
- .jump, .jumpinp input
- box-shadow: $boxShadow
-
-/************** 搜索框 **************/
-
-.search-box input
- border-radius: $borderRadius
-
-/************** FIX **************/
-a.color-button
- cursor: pointer;
-
-.abstract-item
- background-color: #fff;
- a:hover
- text-decoration: none !important;
-
-/************** Dark **************/
-.reco-theme-dark
- color: #fff;
- background: #121212;
- a.sidebar-link, a.nav-link, a.dropdown-title
- color: #fff;
- .navbar
- box-shadow: none;
- border-bottom: 1px solid #fff;
- .links
- background: #121212;
- .navbar
- color: #fff;
- background: #121212;
- .site-name
- color: #fff;
- .color-picker-menu
- background: #121212;
- .home-blog .home-blog-wrapper .info-wrapper .num > div h3
- color: #fff;
- .dropdown-wrapper .nav-dropdown
- color: #fff;
- background: #121212;
- .sidebar
- color: #fff;
- background: #121212;
- .content__default code
- color: #dd6efd;
- .iconfont
- color: #aaa;
- .footer
- a
- color: #fff;
- a:hover
- color:$accentColor
- .nav-links a:hover, .nav-links a.router-link-active
- color:$accentColor
- .category-item:hover
- .category-name
- color: #000;
- .custom-block.tip
- color: #a0ddc1
- background-color: rgba(66, 185, 131, 0.25)
- .custom-block-title
- color: #66c99c;
- tr:nth-child(2n)
- background: transparent !important;
- .custom-block.warning
- color: #ffefa2
- background-color: rgba(255, 229, 100, 0.25)
- tr:nth-child(2n)
- background: transparent !important;
- .custom-block-title
- color: #ffd91d;
- a
- color: #ffdf41
- .custom-block.danger
- color: #f66;
- background-color: rgba(204, 0, 0, 0.25)
- tr:nth-child(2n)
- background: transparent !important;
- .custom-block-title
- color: #ff2929
- a
- color: #ff0a0a
- .home .feature h2,
- .home .feature p
- color: #fff;
- .home .hero .description
- color: #fff;
- .footer-wrapper
- color: #fff !important;
- tr:nth-child(2n)
- background: #2b2f33;
- blockquote
- color: #ddd;
- .abstract-wrapper
- .abstract-item
- background-color: #222222;
-
-@media (prefers-color-scheme: dark)
- html
- content: "dark"
diff --git a/docs/.vuepress/theme/styles/toc.styl b/docs/.vuepress/theme/styles/toc.styl
deleted file mode 100644
index d3e71069..00000000
--- a/docs/.vuepress/theme/styles/toc.styl
+++ /dev/null
@@ -1,3 +0,0 @@
-.table-of-contents
- .badge
- vertical-align middle
diff --git a/docs/.vuepress/theme/styles/wrapper.styl b/docs/.vuepress/theme/styles/wrapper.styl
deleted file mode 100644
index a99262c7..00000000
--- a/docs/.vuepress/theme/styles/wrapper.styl
+++ /dev/null
@@ -1,9 +0,0 @@
-$wrapper
- max-width $contentWidth
- margin 0 auto
- padding 2rem 2.5rem
- @media (max-width: $MQNarrow)
- padding 2rem
- @media (max-width: $MQMobileNarrow)
- padding 1.5rem
-
diff --git a/docs/.vuepress/theme/util/formatDate.js b/docs/.vuepress/theme/util/formatDate.js
deleted file mode 100644
index 99db245c..00000000
--- a/docs/.vuepress/theme/util/formatDate.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * 时间格式化的方法
- * 创建时间:2019-10-08
- * 作者:刘晓北
- * 邮箱: 15732451723@163.com
-*/
-
-// 将时间格式化成 YYYY/MM/DD HH:mm:SS
-export const fromatDateTime = (time) => {
- const date = new Date(time)
- const Y = date.getFullYear()
- const M = date.getMonth() + 1
- const D = date.getDate()
- let H = date.getHours()
- H = H > 9 ? H : '0' + H
- let m = date.getMinutes()
- m = m > 9 ? m : '0' + m
- let S = date.getSeconds()
- S = S > 9 ? S : '0' + S
- return Y + '/' + M + '/' + D + ' ' + H + ':' + m + ':' + S
-}
\ No newline at end of file
diff --git a/docs/.vuepress/theme/util/index.js b/docs/.vuepress/theme/util/index.js
deleted file mode 100644
index 9913ff7e..00000000
--- a/docs/.vuepress/theme/util/index.js
+++ /dev/null
@@ -1,239 +0,0 @@
-export const hashRE = /#.*$/
-export const extRE = /\.(md|html)$/
-export const endingSlashRE = /\/$/
-export const outboundRE = /^(https?:|mailto:|tel:)/
-
-export function normalize (path) {
- return decodeURI(path)
- .replace(hashRE, '')
- .replace(extRE, '')
-}
-
-export function getHash (path) {
- const match = path.match(hashRE)
- if (match) {
- return match[0]
- }
-}
-
-export function isExternal (path) {
- return outboundRE.test(path)
-}
-
-export function isMailto (path) {
- return /^mailto:/.test(path)
-}
-
-export function isTel (path) {
- return /^tel:/.test(path)
-}
-
-export function ensureExt (path) {
- if (isExternal(path)) {
- return path
- }
- const hashMatch = path.match(hashRE)
- const hash = hashMatch ? hashMatch[0] : ''
- const normalized = normalize(path)
-
- if (endingSlashRE.test(normalized)) {
- return path
- }
- return normalized + '.html' + hash
-}
-
-export function isActive (route, path) {
- const routeHash = route.hash
- const linkHash = getHash(path)
- if (linkHash && routeHash !== linkHash) {
- return false
- }
- const routePath = normalize(route.path)
- const pagePath = normalize(path)
- return routePath === pagePath
-}
-
-export function resolvePage (pages, rawPath, base) {
- if (base) {
- rawPath = resolvePath(rawPath, base)
- }
- const path = normalize(rawPath)
- for (let i = 0; i < pages.length; i++) {
- if (normalize(pages[i].regularPath) === path) {
- return Object.assign({}, pages[i], {
- type: 'page',
- path: ensureExt(pages[i].path)
- })
- }
- }
- console.error(`[vuepress] No matching page found for sidebar item "${rawPath}"`)
- return {}
-}
-
-function resolvePath (relative, base, append) {
- const firstChar = relative.charAt(0)
- if (firstChar === '/') {
- return relative
- }
-
- if (firstChar === '?' || firstChar === '#') {
- return base + relative
- }
-
- const stack = base.split('/')
-
- // remove trailing segment if:
- // - not appending
- // - appending to trailing slash (last segment is empty)
- if (!append || !stack[stack.length - 1]) {
- stack.pop()
- }
-
- // resolve relative path
- const segments = relative.replace(/^\//, '').split('/')
- for (let i = 0; i < segments.length; i++) {
- const segment = segments[i]
- if (segment === '..') {
- stack.pop()
- } else if (segment !== '.') {
- stack.push(segment)
- }
- }
-
- // ensure leading slash
- if (stack[0] !== '') {
- stack.unshift('')
- }
-
- return stack.join('/')
-}
-
-/**
- * @param { Page } page
- * @param { string } regularPath
- * @param { SiteData } site
- * @param { string } localePath
- * @returns { SidebarGroup }
- */
-export function resolveSidebarItems (page, regularPath, site, localePath) {
- const { pages, themeConfig } = site
-
- const localeConfig = localePath && themeConfig.locales
- ? themeConfig.locales[localePath] || themeConfig
- : themeConfig
-
- const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
- if (pageSidebarConfig === 'auto') {
- return resolveHeaders(page)
- }
-
- const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
- if (!sidebarConfig) {
- return []
- } else {
- const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
- return config
- ? config.map(item => resolveItem(item, pages, base))
- : []
- }
-}
-
-/**
- * @param { Page } page
- * @returns { SidebarGroup }
- */
-function resolveHeaders (page) {
- const headers = groupHeaders(page.headers || [])
- return [{
- type: 'group',
- collapsable: false,
- title: page.title,
- path: null,
- children: headers.map(h => ({
- type: 'auto',
- title: h.title,
- basePath: page.path,
- path: page.path + '#' + h.slug,
- children: h.children || []
- }))
- }]
-}
-
-export function groupHeaders (headers) {
- // group h3s under h2
- headers = headers.map(h => Object.assign({}, h))
- let lastH2
- headers.forEach(h => {
- if (h.level === 2) {
- lastH2 = h
- } else if (lastH2) {
- (lastH2.children || (lastH2.children = [])).push(h)
- }
- })
- return headers.filter(h => h.level === 2)
-}
-
-export function resolveNavLinkItem (linkItem) {
- return Object.assign(linkItem, {
- type: linkItem.items && linkItem.items.length ? 'links' : 'link'
- })
-}
-
-/**
- * @param { Route } route
- * @param { Array
| Array | [link: string]: SidebarConfig } config
- * @returns { base: string, config: SidebarConfig }
- */
-export function resolveMatchingConfig (regularPath, config) {
- if (Array.isArray(config)) {
- return {
- base: '/',
- config: config
- }
- }
- for (const base in config) {
- if (ensureEndingSlash(regularPath).indexOf(encodeURI(base)) === 0) {
- return {
- base,
- config: config[base]
- }
- }
- }
- return {}
-}
-
-function ensureEndingSlash (path) {
- return /(\.html|\/)$/.test(path)
- ? path
- : path + '/'
-}
-
-function resolveItem (item, pages, base, groupDepth = 1) {
- if (typeof item === 'string') {
- return resolvePage(pages, item, base)
- } else if (Array.isArray(item)) {
- return Object.assign(resolvePage(pages, item[0], base), {
- title: item[1]
- })
- } else {
- if (groupDepth > 3) {
- console.error(
- '[vuepress] detected a too deep nested sidebar group.'
- )
- }
- const children = item.children || []
- if (children.length === 0 && item.path) {
- return Object.assign(resolvePage(pages, item.path, base), {
- title: item.title
- })
- }
- return {
- type: 'group',
- path: item.path,
- title: item.title,
- sidebarDepth: item.sidebarDepth,
- children: children.map(child => resolveItem(child, pages, base, groupDepth + 1)),
- collapsable: item.collapsable !== false
- }
- }
-}
diff --git a/docs/README.md b/docs/README.md
deleted file mode 100644
index 54ec69c0..00000000
--- a/docs/README.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-home: true
-heroImage: /hero.png
-heroImageStyle: {
- maxWidth: '200px',
- width: '100%',
- display: block,
- margin: '5rem auto 2rem',
- borderRadius: '1rem',
-}
-isShowTitleInHome: true
-actionText: 開始
-actionLink: /views/
-features:
-- title: 網頁前端
- details: 包含基礎 JavaScript 語法、JQuery 函式庫 以及 Vue.js 框架
-- title: 後端伺服器
- details: Node.js 是能夠在伺服器端運行 JavaScript 的跨平台執行環境。
-- title: 資料庫
- details: MongoDB 是文件導向的資料庫系統,為目前最靈活易用的 NoSQL 之一。
----
diff --git a/docs/views/ch19.md b/docs/advanced/advanced.md
similarity index 94%
rename from docs/views/ch19.md
rename to docs/advanced/advanced.md
index 3985e1e1..f0fb0664 100644
--- a/docs/views/ch19.md
+++ b/docs/advanced/advanced.md
@@ -1,12 +1,7 @@
----
-title: Ch.19 進階 JavaScript 語法
-tags:
- - JavaScript
-prev: ./ch18
-next: ./ch20
----
+# 進階 JavaScript 語法
+
try catch、Promise 和 async await
-
+
## try catch
try catch 可以處理程式的錯誤,讓程式不會因為錯誤而影響執行
也可以利用這種寫法進行流程控制
@@ -96,8 +91,8 @@ willGetMoney(true).then(res => {
## async await
將 function 加上 `async`,就可以在 function 內使用等待程式執行完畢的 `await`,變成同步函式
也可以透過 `await` 的幫助,改善 Promise 可讀性
-
-
+
+
:::danger 注意
await 只能加在 async function 內,且 await 只能加在 Promise 函式
diff --git a/docs/views/ch18.md b/docs/advanced/ajax.md
similarity index 95%
rename from docs/views/ch18.md
rename to docs/advanced/ajax.md
index 9ffdfdf1..f3e4651d 100644
--- a/docs/views/ch18.md
+++ b/docs/advanced/ajax.md
@@ -1,17 +1,10 @@
----
-title: Ch.18 HTTP 請求與 AJAX
-tags:
- - JavaScript
- - jQuery
-prev: ./ch17
-next: ./ch19
----
+# HTTP 請求與 AJAX
AJAX 是一種非同步的技術,讓網頁不重新整理就可以跟伺服器交換資料
-
+
## HTTP 請求
以上網瀏覽網頁為例,HTTP 請求如圖
-
+
### Request Line
Request Line 為請求的方式及目標網址
diff --git a/docs/basic/array-object.md b/docs/basic/array-object.md
new file mode 100644
index 00000000..005c85b9
--- /dev/null
+++ b/docs/basic/array-object.md
@@ -0,0 +1,454 @@
+# 陣列與物件
+陣列是多種相似資料的集合
+物件是一個東西的多種不同屬性的集合
+
+## 陣列
+可以想像陣列是一台火車,每節車廂就是一筆資料,火車長度沒有限制
+- 每一節車廂的號碼就是 `索引`,又稱 `index`
+- 每一節車廂的乘客就是 `值`,又稱 `value`
+
+:::tip TIP
+通常在命名陣列時,會用複數名詞,如 `students`、`teachers`、`items` 等
+:::
+
+```js
+// 用陣列前
+const bendon1 = "雞排飯";
+const bendon2 = "排骨飯";
+const bendon3 = "魚排飯";
+
+// 用陣列後
+const bendons = ["雞排飯", "排骨飯", "魚排飯"];
+```
+
+如果把上面的陣列想像成一台火車
+- 火車的名字叫做 `bendons`,有 `3` 節車廂
+- 第 `0` 節車廂的名字叫做 `雞排飯`;
+- 第 `1` 節車廂的名字叫做 `排骨飯`;
+- 第 `2` 節車廂的名字叫做 `魚排飯`;
+- `0`、`1`、`2` 是這個陣列的 `索引`,又稱 `index`
+- `雞排飯`、`排骨飯`、`魚排飯` 是這個陣列的 `值`,又稱 `value`
+
+:::danger 注意
+在程式裡,陣列的索引是從 `0` 開始
+:::
+
+在存取陣列資料時
+- `[]` 可以使用索引取得資料,如果索引不存在會回傳 `undefined`
+- `.length` 可以得到陣列的長度
+
+```js
+const alphabets = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
+
+// .length 取長度
+console.log(`有 ${alphabets.length} 個字母
`)
+
+// [索引] 取指定資料
+console.log(alphabets[0]) // a
+console.log(alphabets[1]) // b
+console.log(alphabets[1000]) // undefined
+
+// 以變數值當索引取資料
+const index = 2
+console.log(alphabets[index]) // c
+
+// 使用迴圈取得所有資料
+for (let i = 0; i < alphabets.length; i++) {
+ document.write(alphabets[i])
+}
+```
+
+## 物件
+物件保存了一個東西的不同種資料
+- 每個資料名稱叫做 `key`
+- 資料的值叫做 `value`
+
+```js
+const person = {
+ name: "王小明",
+ age: 25,
+ number: 24
+}
+```
+
+如果把上面的物件想像成一個人
+- 這個人的 `name` 為 `王小明`
+- 這個人的 `age` 為 `25`
+- 這個人的 `number` 為 `24`
+
+:::danger 注意
+物件無法直接使用 `.length` 取得長度,也不能用 `[第幾個]` 取得資料
+但是可以用 `["索引名"]` 取得某索引的資料
+:::
+
+```js
+const person = {
+ name: "王小明",
+ age: 25,
+ number: 24
+}
+// 用 .key 取值
+console.log(person.name)
+// 用 ["key"] 取值
+console.log(person['name'])
+// 用變數當 key 取值
+const key = 'name'
+console.log(person[key])
+```
+
+## 解構賦值
+解構賦值可以把陣列或物件中的資料解開擷取成為獨立變數
+相當於建立一個新變數,並設定為陣列或物件中的某個值
+在解構時可以使用其餘運算子 `...` 取得剩餘的資料
+
+:::danger 注意
+其餘元素 `...` 必須放在最後一個
+`[a, ...others, c]` 是不正確的語法
+:::
+
+陣列解構範例
+```js
+const array = [1, 2, 3, 4]
+
+// 原始寫法
+const one = array[0]
+const two = array[1]
+const others = [array[2], array[3]]
+console.log(one) // 1
+console.log(two) // 2
+console.log(others) // [3, 4]
+
+// 解構賦值
+// 依照順序取值
+const [one, two, ...apple] = array
+console.log(one) // 1
+console.log(two) // 2
+console.log(apple) // [3, 4]
+```
+
+物件解構範例
+
+```js
+const obj = { a: 1, b: 2, c: 3, d: 4 }
+
+// 原始寫法
+const a = obj.a
+const bbb = obj.b
+const others = { c: obj.c, d: obj.d }
+console.log(a) // 1
+console.log(bbb) // 2
+console.log(others) // { c: 3, d: 4 }
+
+// 解構賦值
+// 依照 key 名稱取值,可用 : 重新命名
+const { a, b: bbb, ...others } = obj
+console.log(a) // 1
+console.log(bbb) // 2
+console.log(banana) // { c: 3, d: 4 }
+```
+
+## 巢狀
+物件和 Array 可以依資料情況組合,儲存更複雜的資料
+
+由物件組成的陣列範例
+```js
+const people = [
+ {
+ name: "小明",
+ age: 25,
+ number: 24
+ },
+ {
+ name: "小美",
+ age: 24,
+ number: 25
+ }
+]
+```
+
+物件內值為陣列範例
+```js
+const restaurant = {
+ name: "好好吃便當店",
+ tel: "02-21345678",
+ foods: ["雞排飯", "排骨飯", "魚排飯"]
+}
+```
+
+二維陣列概念,如 X 班 Y 號同學的成績
+
+三維陣列概念,如 X 年 Y 班 Z 號同學的成績
+
+:::tip TIP
+目前網路上給開發者使用的公開資料大多是物件和陣列的結合
+所以熟悉物件和陣列的組合,對於串接 API 會有很大的幫助
+- [政府資料開放平台](https://data.gov.tw/)
+- [KKTIX 活動資訊 API](https://kktix.com/events.json)
+:::
+
+## 可選串連
+當要存取的陣列索引或物件屬性可能不存在時,使用 `?.` 可以避免出現錯誤
+
+物件範例
+```js
+const user = {
+ name: 'AAA',
+ info: {
+ email: 'aaa@gmail.com'
+ }
+}
+console.log(user.name) // AAA
+console.log(user.info.email) // aaa@gmail.com
+console.log(user.info.address) // undefined
+
+// Uncaught TypeError: Cannot read properties of undefined (reading 'city')
+console.log(user.info.address.city)
+
+console.log(user.info.address?.city) // undefined
+console.log(user.info.address?.city?.postcode) // undefined
+```
+
+陣列範例
+```js
+const restaurant = {
+ name: '好好吃便當店',
+ tel: '02-21345678',
+ menu: []
+}
+
+// Uncaught TypeError: Cannot read properties of undefined (reading 'price')
+console.log(restaurant.menu[0].price)
+
+// undefined
+console.log(restaurant.menu?.[0]?.price)
+```
+
+可選串連搭配短路求值範例,當資料不存在時使用預設值
+```js
+const products = [
+ { name: 'iPhone 15', price: 48900 },
+ {
+ name: 'Nothing Phone(2)',
+ price: 21900,
+ producer: {
+ name: 'Nothing',
+ url: 'https://tw.nothing.tech/'
+ }
+ },
+ {
+ name: 'Nothing Phone(1)',
+ price: 14900,
+ producer: {
+ name: 'Nothing',
+ url: 'https://tw.nothing.tech/'
+ }
+ }
+]
+
+for (let i = 0; i < products.length; i++) {
+ document.write(`
+
+ ${products[i].name},價格為 ${products[i].price}
+ 製造商為
+ ${products[i].producer?.name || '不明'}
+
+ `)
+}
+```
+
+## 迴圈
+可以透過迴圈去取出陣列或物件裡的所有資料
+- `for` 適合固定次數的迴圈,陣列有固定長度,所以可以對陣列使用
+- `for of` 針對陣列的值進行迴圈
+- `for in` 針對物件的 key 或是陣列的 index 進行迴圈
+
+`for` 迴圈範例
+```js
+const bendons = ["雞排飯", "排骨飯", "魚排飯"];
+for(let i = 0; i < bendons.length; i++) {
+ console.log(i, bendons[i])
+}
+```
+
+`for of` 迴圈範例
+```js
+const bendons = ["雞排飯", "排骨飯", "魚排飯"];
+for(const bendon of bendons) {
+ console.log(bendon);
+}
+```
+
+`for in` 陣列迴圈範例
+```js
+const bendons = ["雞排飯", "排骨飯", "魚排飯"];
+for(const i in bendons) {
+ console.log(i, bendons[i]);
+}
+```
+
+`for in` 物件迴圈範例
+```js
+const person = {
+ name: "王小明",
+ age: 25,
+ number: 24
+}
+for(const key in person) {
+ console.log(person[key]);
+}
+```
+
+## 傳值與傳址
+傳值 (Pass by value)
+- 其餘文字、數字、布林等資料型態傳遞方式
+- 複製一份資料,改變其中一個不會影響另一個
+
+```js
+let test1 = 1
+let test2 = test1
+test2 = 100
+console.log(test1) // 1
+console.log(test2) // 100
+```
+
+傳址 (Pass by reference)
+- 物件和陣列的資料傳遞方式
+- 指向同一個記憶體位置,改變其中一個會影響另一個
+
+陣列傳址範例
+```js
+const a = [1, 2, 3]
+const b = a
+b[0] = 100
+console.log(a) // [100, 2, 3]
+console.log(b) // [100, 2, 3]
+console.log(a === b) // true
+```
+
+物件傳址範例
+```js
+const obj1 = {
+ a: 1,
+ b: 2,
+ c: 3
+}
+const obj2 = obj1
+obj1.a = 100
+console.log(obj1) // {a: 100, b: 2, c: 3}
+console.log(obj2) // {a: 100, b: 2, c: 3}
+```
+
+:::danger 注意
+在編寫時,以資料的型態決定是傳值還是傳址
+
+陣列範例
+指向的是陣列內的索引為 0 的值,而不是整個陣列
+索引為 0 的值資料型態不是陣列也不是物件,所以是傳值
+```js
+const a = [4, 5, 6]
+let b = a[0]
+b = 100
+console.log(a) // [4, 5, 6]
+console.log(b) // 100
+```
+
+物件範例
+指向的是物件內的值,而不是整個物件
+物件內的值是一般資料型態,所以是傳值
+```js
+const obj1 = {
+ a: 1,
+ b: 2,
+ c: 3
+}
+const obj2 = {
+ a: obj1.a,
+ b: obj1.b,
+ c: obj1.c
+}
+obj2.a = 100
+console.log(obj1) // {a: 1, b: 2, c: 3}
+console.log(obj2) // {a: 100, b: 2, c: 3}
+```
+:::
+
+## 綜合練習
+:::warning 練習
+宣告一個數字陣列
+```js
+const numbers = [33, 75, 69, 41, 50, 19]
+```
+- 印出陣列 `第 x 個數字為 y`
+- 求 `41` 是第幾個數字
+- 有幾個奇數和幾個偶數
+- 最大數字和最小數字
+:::
+
+:::warning 練習
+某國家發生通貨膨脹
+饅頭第一天 1 元,第二天 2 元,第三天 3 元,以此類推
+小明他從第一天起,連續買了 10 天的饅頭
+每天買的饅頭數依序為 1, 8, 3, 4, 5, 6, 7, 2, 9, 10
+求小明買饅頭花費的總金額
+
+題目修改自 [高中生程式解題系統](https://zerojudge.tw/ShowProblem?problemid=b294)
+:::
+
+:::warning 練習
+假設某一公司有五種產品 A、B、C、D、E
+其單價分別為 12、16、10、14、15 元
+而該公司共有三位銷售員,他們在某個月份的銷售量如下所示
+
+||產品 A|產品 B|產品 C|產品 D|產品 E|
+|---|---|---|---|---|---|
+|銷售員 1|33|32|56|45|33|
+|銷售員 2|77|33|68|45|23|
+|銷售員 3|43|55|43|67|65|
+
+請將上表的內容設定成二維陣列,並依序完成下列各題
+- 每一個銷售員的銷售總金額
+- 每一項產品的銷售總金額
+
+```js
+const data = [
+ [33, 32, 56, 45, 33],
+ [77, 33, 68, 45, 23],
+ [43, 55, 43, 67, 65]
+]
+```
+:::
+
+:::warning 作業
+練習二維陣列
+下表為某地星期一到星期四的時段一、時段二與時段三的氣溫
+
+||星期一|星期二|星期三|星期四|
+|---|---|---|---|---|
+|時段一|18.2|17.3|15.0|13.4|
+|時段二|23.8|25.1|20.6|17.8|
+|時段三|20.6|21.5|18.4|15.7|
+
+請將上表的內容設定成二維陣列,並依序完成下列各題
+
+- 將陣列內容印出成表格
+- 每日的平均溫度
+- 時段一、時段二、時段三的平均氣溫
+- 溫度最高的日子與時段
+- 溫度最低的日子與時段
+
+```js
+const data = [
+ [18.2, 17.3, 15.0, 13.4],
+ [23.8, 25.1, 20.6, 17.8],
+ [20.6, 21.5, 18.4, 15.7]
+]
+```
+:::
diff --git a/docs/basic/class.md b/docs/basic/class.md
new file mode 100644
index 00000000..8fa8946f
--- /dev/null
+++ b/docs/basic/class.md
@@ -0,0 +1,122 @@
+# 物件導向
+物件裡面的值除了可以是一般的文字、數字外,它的值也可以是 function
+如果物件裡面包含 function 的話,就會是 `物件導向` 的程式設計
+
+## 物件中的 function
+- 物件裡面可以用 function 作為值
+- 以 `this` 來代表這個物件,可以用來取得物件裡的其他屬性
+
+```js
+const person = {
+ firstName: '小明',
+ lastName: '王',
+ // 物件內 function 定義方式
+ fullName: function () {
+ return this.firstName + this.lastName
+ },
+ // 物件內 function 定義方式簡寫
+ sayHi () {
+ return '你好,我是' + this.fullName()
+ },
+ // 物件內箭頭函式定義方式
+ // this 會指向 window 而不是物件
+ sayHi2: () => {
+ return '你好,我是' + this.fullName()
+ }
+}
+```
+
+上面的程式碼可以畫成像這樣的心智圖
+
+
+:::tip TIP
+可選串連也可以避免呼叫物件內不存在的 function 時的錯誤
+```js
+person.sayGoodBye?.()
+```
+:::
+
+:::danger 注意
+`this` 在不同地方有不同意思,使用時需要特別注意
+以下為瀏覽器常見的使用情況
+- 在物件的 function 裡,`this` 代表這個物件
+- 在一般 function 裡,`this` 代表 `window`
+- 在箭頭函式裡,`this` 代表 `window`
+:::
+
+## 類別
+類別是物件導向的基本概念,宣告一個模板後,用它來建立物件
+使用 `class` 來宣告類別,並用 `new` 來建立物件
+
+```js
+// 宣告類別
+class Person {
+ // constructor 是物件建立時會執行的 function
+ constructor(firstName, lastName) {
+ this.firstName = firstName
+ this.lastName = lastName
+ }
+ fullName () {
+ return this.firstName + this.lastName
+ }
+ sayHi () {
+ return '你好,我是' + this.fullName()
+ }
+}
+
+// 建立物件
+const Ming = new Person("小明", "王");
+const Mei = new Person("小美", "王");
+
+// 使用建立的物件
+document.write(Ming.sayHi())
+document.write(Mei.sayHi())
+```
+
+
diff --git a/docs/basic/condition.md b/docs/basic/condition.md
new file mode 100644
index 00000000..dea65347
--- /dev/null
+++ b/docs/basic/condition.md
@@ -0,0 +1,456 @@
+# 邏輯判斷式
+
+邏輯判斷式是程式運作不可或缺的部分,它可以讓程式根據不同的情況去執行不同的程式碼
+
+## 認識語法
+當中文句型為
+
+> 如果 ( 條件 ) { 條件成立時的動作 } 否則 { 條件不成立時的動作 }
+
+> 如果 ( 外面下雨 ) { 在家裡待著電影 } 否則 { 出門和爬山 }
+
+翻譯成程式就是
+
+```js
+if (條件) {
+ 條件成立時的程式碼
+} else {
+ 條件不成立時的程式碼
+}
+```
+
+```js
+if (外面下雨) {
+ 在家裡待著電影
+} else {
+ 出門
+ 去爬山
+}
+```
+- `if` 代表如果,後面接判斷式,如果成立,就會裡面的執行程式碼
+- `else` 代表否則,當 `if` 不成立時,就會裡面的執行程式碼
+
+:::tip TIP
+當判斷式後的 `{}` 內只有一行程式碼時,可以省略 `{}`
+```js
+if (條件) 執行程式碼
+else 執行程式碼
+```
+上面的範例可以寫成
+```js
+if (外面下雨) 在家裡待著電影
+else {
+ 出門
+ 去爬山
+}
+```
+:::
+
+`else` 和中文 `否則` 一樣是非必要的
+
+> 如果 ( 可以決定交作業時間 ) { 我希望永遠不必交 }
+
+```js
+if (可以決定交作業時間) {
+ 我希望永遠不必交
+}
+```
+
+## 比較運算子
+比較運算子是用來比較兩個值的大小
+運算的結果會是布林值 `true` 或 `false`
+
+:::danger 注意
+請注意符號的擺放位置,例如 `a >= b` 不能寫成 `a => b`
+`=>` 代表 function 的箭頭函式,不是比較運算子
+:::
+
+| 符號 | 說明 |
+|:---|:---|
+| a == b | a 等於 b |
+| a === b | a 等於 b (資料型態也要相同) |
+| a != b | a 不等於 b |
+| a <> b | a 不等於 b |
+| a !== b | a 不等於 b (資料型態也不相等) |
+| a > b | a 大於 b (數值判斷) |
+| a < b | a 小於 b (數值判斷) |
+| a >= b | a 大於 b 或是 a 等於 b |
+| a <= b | a 小於等於 b 或是 a 等於 b |
+
+數字大小比較範例
+```js
+const a = 10, b = 20
+if (a > b) {
+ console.log('a 大於 b')
+} else {
+ console.log('a 不大於 b')
+}
+```
+
+資料型態比較範例
+
+```js
+const a = 100, b = '100'
+if (a == b) {
+ console.log('a == b')
+} else {
+ console.log('a != b')
+}
+if (a === b) {
+ console.log('a === b')
+} else {
+ console.log('a !== b')
+}
+```
+
+若判斷的是布林值,可以直接用 `if(變數)` 來判斷
+
+```js
+const ok = false
+// if (ok) --> if (ok === true)
+if (ok) {
+ console.log('ok')
+}
+// if (!ok) --> if (ok === false)
+if (!ok) {
+ console.log('not ok')
+}
+```
+
+## 邏輯運算子
+邏輯運算子是用來組合多個比較運算子的結果
+運算的結果會是布林值 `true` 或 `false`
+
+| 符號 | 說明 | 舉例 |
+|:---|:---|:---|
+| a && b | a 與 b ,必須符合兩者 | 如果颱風天沒颳風也沒下雨,我就去看電影 |
+| a || b | a 或 b,符合其中一個 | A: 晚餐吃什麼? B: 便當或麵都可以 |
+| !a | 否定、相反 | A: 你假日想做什麼事? B: 除了練習程式外,其他都可以 |
+
+`&&` 範例
+```js
+const rain = false, wind = true
+if (!rain && !wind) console.log('看電影')
+else console.log('在家發呆')
+```
+`||` 範例
+```js
+const dinner = '便當'
+if (dinner === '炸雞' || dinner === '可樂') {
+ console.log('好耶')
+} else {
+ console.log('不好耶')
+}
+```
+
+相反式範例
+```js
+!(a==b)
+!(a>b)
+!(a>=b)
+!(a三元運算子
+
+語法規則為
+
+> 條件 ? 成立時執行的程式 : 否定時執行的程式
+
+```js
+const like = confirm('你喜歡 JavaScript 嗎')
+
+// 使用三元運算子前
+if (message) {
+ console.log('喜歡')
+} else {
+ console.log('不喜歡')
+}
+
+// 使用三元運算子後,將結果放在變數
+const message = like ? '喜歡' : '不喜歡'
+console.log(message)
+
+// 使用三元運算子後,直接印出結果
+console.log(like ? '喜歡' : '不喜歡')
+```
+
+## 多條件式
+當條件有多筆需要判斷時,你可以用 `()` 組合判斷式
+```js
+const coding = confirm('你會寫 code 嗎')
+const game = confirm('你有玩原神嗎')
+const player = confirm('你是可莉玩家嗎')
+if ((game && player) || coding) {
+ console.log('酷欸')
+} else {
+ console.log('加油')
+}
+```
+
+## 判斷式條件的延伸
+前面的判斷式,都是 2 選 1
+但很多時候,遇到 3 選 1 、4 選 1 或更多的時候,就需要用到 `else if`
+
+@flowstart
+st=>start: 開始
+cond1=>condition: if
+cond2=>condition: else if
+cond3=>condition: else if
+cond4=>condition: else
+e=>end: 結果
+process1=>operation: 執行區塊內程式碼
+process2=>operation: 執行區塊內程式碼
+process3=>operation: 執行區塊內程式碼
+process4=>operation: 執行區塊內程式碼
+
+st->cond1
+cond1(yes)->process1->e
+cond1(no)->cond2
+cond2(yes)->process2->e
+cond2(no)->cond3
+cond3(yes)->process3->e
+cond3(no)->cond4
+cond4(yes)->process4->e
+@flowend
+
+程式寫法範例
+>if( 條件一 ) { 符合時執行程式碼 }
+else if ( 條件二 ) { 符合時執行程式碼 }
+else if ( 條件三 ) { 符合時執行程式碼 }
+else { 以上都不符合時執行程式碼 }
+
+成績標準範例
+>if ( 成績 >= 95 ) { 你的成績是 S 級 }
+else if ( 成績 >= 90 ) { 你的成績是 A 級 }
+else if ( 成績 >= 80 ) { 你的成績是 B 級 }
+else { 你的成績是 C 級 }
+
+年齡分級判斷範例,編寫的時候要注意判斷順序
+
+```js
+const age = prompt('請輸入年齡')
+
+// 錯誤的判斷寫法,永遠都是普遍級
+if (age >= 0) {
+ document.write('普遍級')
+} else if (age >= 6) {
+ document.write('保護級')
+} else if (age >= 12) {
+ document.write('輔12級')
+} else if (age >= 15) {
+ document.write('輔15級')
+} else if (age >= 18) {
+ document.write('限制級')
+}
+
+// 正確寫法
+if (age >= 18) {
+ document.write('限制級')
+} else if (age >= 15) {
+ document.write('輔15級')
+} else if (age >= 12) {
+ document.write('輔12級')
+} else if (age >= 6) {
+ document.write('保護級')
+} else if (age >= 0) {
+ document.write('普遍級')
+}
+```
+
+:::warning 練習
+使用 `prompt()` 製作一個選擇題
+:::
+
+## switch case
+`switch` 是另一種判斷式,可以用來判斷多個條件
+執行時會將 `()` 內的變數值,和 `case` 後面的值做比較
+- 從符合的 `case` 開始往下執行,直到遇到 `break` 為止,順序會影響執行
+- 如果沒有符合的 `case`,就會執行 `default` 的程式碼
+
+語言判斷,使用 `if` 寫法
+```js
+if (lang === 'zh-tw') {
+ document.write('台灣中文')
+} else if (lang === 'ja-jp') {
+ document.write('日本日文')
+} else if (lang === 'en-us' || lang === 'en') {
+ document.write('英文')
+} else {
+ document.write('窩不知道')
+}
+```
+語言判斷,使用三元運算子寫法
+```js
+const message =
+ lang === 'zh-tw' ? '台灣中文' :
+ lang === 'ja-jp' ? '日本日文' :
+ (lang === 'en-us' || lang === 'en') ? '英文' : '窩不知道'
+document.write(message)
+```
+語言判斷,使用 `switch` 寫法
+```js
+switch (lang) {
+ case 'zh-tw':
+ document.write('台灣中文')
+ break
+ case 'jp':
+ document.write('日本')
+ case 'ja-jp':
+ document.write('日本日文')
+ break
+ case 'en-us':
+ case 'en':
+ document.write('英文')
+ break
+ default:
+ document.write('窩不知道')
+ break
+}
+```
+年齡分級判斷範例
+```js
+const age = 18
+// 不能寫 switch (age),只能寫 switch (true)
+// 當寫 switch(age) 時
+// age === (age >= 18)
+// 18 === (18 >= 18)
+// 18 === true
+// false
+switch (true) {
+ case (age >= 18):
+ document.write('限制級')
+ break
+ case (age >= 15):
+ document.write('輔15級')
+ break
+ case (age >= 12):
+ document.write('輔12級')
+ break
+ case (age >= 16):
+ document.write('保護級')
+ break
+ case (age >= 0):
+ document.write('普遍級')
+ break
+}
+```
+
+## 巢狀判斷式
+判斷式裡面還可以再使用判斷式,做更詳細的判斷
+@flowstart
+st=>start: 開始
+cond1=>condition: if
+e=>end: 結果
+process1=>operation: 執行 else 程式碼
+process11=>operation: 判斷式1
+process12=>operation: 判斷式2
+process13=>operation: 判斷式3
+st->cond1
+cond1(yes)->process11->process12->process13->e
+cond1(no)->process1->e
+@flowend
+
+```js
+const weather = 'rain'
+const umbrella = false
+
+if (weather === 'rain') {
+ if (umbrella) {
+ document.write('下雨,有傘,沒事')
+ } else {
+ document.write('下雨,沒傘,有事')
+ }
+} else {
+ document.write('沒下雨,沒差')
+}
+```
+
+## 短路求值
+邏輯運算子也可以用在賦值
+- `||` 取第一個 `Boolean()` 判斷為 true 的值
+- `&&` 取第一個 `Boolean()` 判斷為 false 的值
+- `??` 取第一個不是 `null` 也不是 `undefined` 的值
+
+以下為 `Boolean()` 判斷為 `false` 的狀況
+- `false`
+- `0`
+- `""`
+- `null`
+- `undefined`
+- `NaN`
+
+`||` 使用範例
+```js
+const x = null || 0 || undefined || 123 || 'abc' || 'dfgd' || false
+console.log(x)
+```
+`&&` 使用範例
+```js
+const y = 'abc' && 123 && 456 && false && 'def' && undefined
+console.log(y)
+```
+`??` 使用範例
+```js
+const z = undefined ?? null ?? false ?? 'abc' ?? 123 ?? 456 ?? false ?? 'def'
+console.log(z)
+```
+實際應用範例
+```js
+// 使用短路求值前,需要判斷變數是否有值
+let name = prompt('請輸入名字')
+if (name === '' || name === null) {
+ name = '路人'
+}
+
+// 使用短路求值後
+const name = prompt('請輸入名字') || '路人'
+console.log(name)
+```
+
+## 綜合練習
+使用判斷式製作問答題
+```js
+let score = 0
+
+const ans1 = confirm('鳳梨是食物嗎')
+if (ans1) {
+ score += 10
+ alert('答對了')
+} else {
+ alert('答錯了')
+}
+
+const ans2 = confirm('披薩是食物嗎')
+if (ans2) {
+ score += 10
+ alert('答對了')
+} else {
+ alert('答錯了')
+}
+
+const ans3 = confirm('鳳梨披薩是食物嗎')
+if (ans3) {
+ score = 0
+ document.write('你輸了')
+} else {
+ score += 10
+ document.write(`恭喜過關,你得了 ${score} 分`)
+}
+```
+
+:::warning 練習
+製作一個星座判斷器,進入網頁時出現三個輸入視窗,分別是姓名、出生月份和出生日期
+輸入完成後跳出訊息,格式為 `OOO 你好,你的星座是 OOO 座`
+:::
+
+:::warning 作業
+自己設計 5 道題目問答題或選擇題,遊戲結束後會顯示得分
+:::
diff --git a/docs/basic/data-array.md b/docs/basic/data-array.md
new file mode 100644
index 00000000..c39dff38
--- /dev/null
+++ b/docs/basic/data-array.md
@@ -0,0 +1,249 @@
+# 資料處理 - 陣列
+一些常用的陣列處理函式
+
+## 基本處理
+- `.forEach(function)` 迴圈陣列,每個東西都執行提供的 function,有三個參數可以使用
+ - `value` 現在在執行 function 的東西值
+ - `index` 現在在執行 function 的東西索引
+ - `array` 陣列本身
+- `.join(連接文字)` 將陣列用連接文字串成文字
+- `.push(資料1, 資料2...)` 把資料放進陣列後面
+- `.unshift(資料1, 資料2...)` 把資料放進陣列前面
+- `.pop()` 移除最後一個並回傳
+- `.shift()` 移除第一個並回傳
+- `.splice(開始位置, 刪除數量, 插入資料1, 插入資料2...)` 插入、刪除、取代陣列中的元素
+- `.slice(開始位置, 結束位置)` 切割陣列,產生新陣列,**不會修改原始陣列**
+- `.concat(陣列)` 連接陣列,**不會修改原始陣列**
+- `.reverse()` 顛倒陣列
+
+:::danger 注意
+當參數為 function 時,需要注意變數型態
+```js
+const func = (value) => {
+ console.log(value)
+}
+
+// 正確,func 是 function
+array.forEach(func)
+// 錯誤,func() 是 function 的回傳值
+// 會立即執行 func(),並將回傳值放入 setTimeout
+// 但 func() 沒有回傳值,所以會放入 undefined
+array.forEach(func())
+```
+:::
+
+`.forEach()` 範例
+```js
+const numbers = [1, 2, 3, 4, 5]
+
+// .forEach() 使用匿名函式
+numbers.forEach((value, index, array) => {
+ console.log(value, index, array)
+})
+
+// .forEach() 使用已定義的函式
+const each = (value, index, array) => {
+ console.log(value, index, array)
+}
+numbers.forEach(each)
+```
+
+`.join()` 範例
+```js
+const numbers = [1, 2, 3, 4, 5]
+console.log(numbers.join('-')) // 1-2-3-4-5
+```
+
+增加、刪除範例
+```js
+const fruits = ['蘋果', '香蕉', '西瓜']
+
+fruits.push('橘子')
+// ['蘋果', '香蕉', '西瓜', '橘子']
+console.log(fruits)
+
+fruits.push('葡萄', '藍莓')
+// ['蘋果', '香蕉', '西瓜', '橘子', '葡萄', '藍莓']
+console.log(fruits)
+
+const fruits2 = ['草莓', '芭樂', '柳丁']
+fruits.push(...fruits2)
+// ['蘋果', '香蕉', '西瓜', '橘子', '葡萄', '藍莓', '草莓', '芭樂', '柳丁']
+console.log(fruits)
+
+fruits.unshift('榴槤')
+// ['榴槤', '蘋果', '香蕉', '西瓜', '橘子', '葡萄', '藍莓', '草莓', '芭樂', '柳丁']
+console.log(fruits)
+
+const lastFruit = fruits.pop()
+console.log(lastFruit) // 柳丁
+// ['榴槤', '蘋果', '香蕉', '西瓜', '橘子', '葡萄', '藍莓', '草莓', '芭樂']
+console.log(fruits)
+
+const firstFruit = fruits.shift()
+console.log(firstFruit) // 榴槤
+// ['蘋果', '香蕉', '西瓜', '橘子', '葡萄', '藍莓', '草莓', '芭樂']
+console.log(fruits)
+
+const otherFruits = ['櫻桃', '火龍果']
+fruits.splice(1, 2, ...otherFruits)
+// ['蘋果', '櫻桃', '火龍果', '橘子', '葡萄', '藍莓', '草莓', '芭樂']
+console.log(otherFruits)
+
+const newFruits = phones.slice(1, 5)
+// newFruits = ['櫻桃', '火龍果', '橘子', '葡萄']
+// fruits = ['蘋果', '櫻桃', '火龍果', '橘子', '葡萄', '藍莓', '草莓', '芭樂']
+console.log(newFruits, fruits)
+
+const concatFruits = fruits.concat(['荔枝', '龍眼'])
+// concatFruits = ['蘋果', '櫻桃', '火龍果', '橘子', '葡萄', '藍莓', '草莓', '芭樂', '荔枝', '龍眼']
+// fruits = ['蘋果', '櫻桃', '火龍果', '橘子', '葡萄', '藍莓', '草莓', '芭樂']
+console.log(concatFruits, fruits)
+
+fruits.reverse()
+// ['芭樂', '草莓', '藍莓', '葡萄', '橘子', '火龍果', '櫻桃', '蘋果']
+console.log(fruits)
+```
+
+## 尋找與取代
+- `.includes(搜尋內容)`
+ - 尋找陣列是否有東西符合搜尋內容,回傳 boolean
+- `.indexOf(搜尋內容, 從第幾個開始往後)`
+ - 尋找陣列是否有東西符合搜尋內容,回傳第一個符合的索引,`-1` 代表找不到 (從前面開始往後找)
+ - 第二個參數是選填,預設是 `0`
+- `.lastIndexOf(搜尋內容, 從第幾個開始往前)`
+ - 尋找陣列是否有東西符合搜尋內容,回傳最後一個符合的索引,`-1` 代表找不到 (從後面開始往前找)
+ - 第二個參數是選填,預設是 `array.length - 1`
+- `.some(function)`
+ - 迴圈陣列,每個東西都執行提供的 function
+ - 判斷陣列有沒有東西執行 function 後 return true,回傳 boolean
+- `.every(function)`
+ - 迴圈陣列,每個東西都執行提供的 function
+ - 判斷陣列所有東西執行 function 後 return true,回傳 boolean
+- `.find(function)`
+ - 迴圈陣列,每個東西都執行提供的 function
+ - 回傳第一個執行 function 結果為 true 的值
+- `.findLast(function)`
+ - 迴圈陣列,每個東西都執行提供的 function
+ - 回傳最後一個執行 function 結果為 true 的值
+- `.findIndex(function)`
+ - 迴圈陣列,每個東西都執行提供的 function
+ - 回傳第一個執行 function 結果為 true 的索引
+- `.findLastIndex(function)`
+ - 迴圈陣列,每個東西都執行提供的 function
+ - 回傳最後一個執行 function 結果為 true 的索引
+- `.filter(function)`
+ - 迴圈陣列,每個東西都執行提供的 function
+ - 將所有執行結果為 true 的值產生為新陣列
+
+:::danger 注意
+
+```js
+const arr = [{ a: 1 }]
+console.log(arr.includes({ a: 1 })) // false
+const obj = { b: 2 }
+const arr2 = [obj]
+console.log(arr2.includes(obj)) // true
+```
+:::
+
+```js
+const numbers = [100, 200, 300, 400, 500]
+console.log(numbers.includes(200)) // true
+console.log(numbers.indexOf(100, 2)) // -1
+console.log(numbers.lastIndexOf(100, 2)) // 0
+
+const some = numbers.some((value) => {
+ return value > 300
+})
+console.log(some) // true
+
+const every = numbers.every((value) => {
+ return value > 300
+})
+console.log('every', every) // false
+
+const find = numbers.find((value) => {
+ return value > 300
+})
+console.log('find', find) // 400
+
+const findLast = numbers.findLast((value) => {
+ return value > 300
+})
+console.log('findLast', findLast) // 500
+
+const findIndex = numbers.findIndex((value) => {
+ return value > 300
+})
+console.log('findIndex', findIndex) // 3
+
+const findLastIndex = numbers.findLastIndex((value) => {
+ return value > 300
+})
+console.log('findLastIndex', findLastIndex) // 4
+
+const filter = numbers.filter((value) => {
+ return value > 300
+})
+console.log(filter) // [400, 500]
+```
+
+## 其他
+- `.map(function)`
+ - 迴圈陣列,每個東西都執行提供的 function
+ - 將每個東西執行 function 的 return 值變成新的陣列
+- `.reduce(function, 初始值)`
+ - 迴圈陣列,每個東西都執行提供的 function
+ - 將每個東西執行 function 的 return 值累加
+ - 初始值可不設,預設是陣列第一個值
+- `.sort(function)`
+ - 兩兩比較,a 代表後面的值,b 代表前面的值
+ - `return 0` 順序不變
+ - `return < 0` a 在前
+ - `return > 0` b 在前
+ - `return a - b` 正序
+ - `return b - a` 倒序
+ - 搭配 `a.localeCompare(b)` 依照字元編碼排序文字
+- 其他陣列處理套件
+ - [lodash](https://lodash.com/)
+ - [underscore.js](https://underscorejs.org/)
+
+```js
+const numbers1 = [100, 200, 300]
+const numbers1Double = numbers1.map(value => {
+ return value * 2
+})
+console.log(numbers1Double) // [200, 400, 600]
+
+const numbers2 = [100, 200, 300, 400, 500]
+const numbers2Total = numbers2.reduce((total, value) => {
+ console.log(total, value)
+ return total + value
+})
+console.log(numbers2Total) // 1500
+
+const numbers3 = [100, 1561, 154613, 1231, 564635, 15641310]
+numbers3.sort((a, b) => {
+ console.log(a, b)
+ return a - b
+})
+console.log(numbers3) // [100, 1231, 1561, 154613, 564635, 15641310]
+
+const cn = ['零', '一', '二', '三', '四', '五']
+cn.sort((a, b) => a.localeCompare(b))
+console.log(cn) // ['一', '三', '二', '五', '四', '零']
+
+const en = ['aaa', 'bbb', 'zzz', 'ccc', 'fff', 'ddd']
+en.sort((a, b) => a.localeCompare(b))
+console.log(en) // ['aaa', 'bbb', 'ccc', 'ddd', 'fff', 'zzz']
+```
+
+## 綜合練習
+:::warning 練習
+將 `prompt()` 輸入的文字移除前後空白後倒過來後顯示在網頁上
+:::
+
+:::warning 挑戰
+將 `prompt()` 輸入的英文文字大寫轉小寫,小寫轉大寫後顯示在網頁上
+:::
\ No newline at end of file
diff --git a/docs/basic/data-number.md b/docs/basic/data-number.md
new file mode 100644
index 00000000..d022d067
--- /dev/null
+++ b/docs/basic/data-number.md
@@ -0,0 +1,105 @@
+# 資料處理 - 數字
+數字處理相關語法
+
+## 語法
+數字處理使用 `Math` 語法,提供了許多數學運算功能
+
+- `Math.round(數字)` 四捨五入到整數
+- `Math.ceil(數字)` 無條件進位
+- `Math.floor(數字)` 無條件捨去
+- `Math.pow(數字, 次方)` 次方
+- `Math.sqrt(數字)` 平方根
+- `Math.sign(數字)` 正負數判斷,負數為 -1,0 為 0,正數為 1
+- `Math.abs(數字)` 絕對值
+- `Math.min(數字1, 數字2, 數字3...)` 取最小值
+- `Math.max(數字1, 數字2, 數字3...)` 取最大值
+- `Math.random()` 從 0 到 1 隨機取小數,包含 0,不包含1
+```js
+Math.round(4.7) // 5
+
+Math.ceil(4.4) // 5
+
+Math.floor(4.8) // 4
+
+Math.pow(8, 2) // 64
+
+Math.sqrt(64) // 8
+
+Math.sign(-100) // -1
+
+Math.abs(-5) // 5
+
+Math.min(0, 150, 30, 20, -8, -200) // -200
+
+Math.max(0, 150, 30, 20, -8, -200) // 150
+
+Math.random() // 0.123456789
+```
+
+:::tip TIP
+取陣列的最大值與最小值可以利用 `...` 展開運算子
+```js
+const arr = [0, 150, 30, 20, -8, -200]
+Math.min(...arr) // -200
+Math.max(...arr) // 150
+```
+:::
+
+## 綜合練習
+:::warning 練習
+從 0 到 100 隨機取一個整數
+:::
+
+:::warning 練習
+製作隨機數字 function,提供最小整數和最大整數,回傳一個區間內的隨機整數
+```js
+const rand = (min, max) => {
+ // 程式碼...
+}
+```
+:::
+
+:::warning 作業
+用上面練習完成的 function 製作威力彩號碼產生器
+將隨機出的數字用 `document.write()` 顯示在網頁上
+威力彩規則
+- A 區 1~38 取 6 個數字
+- B 區 1~8 取 1 個數字
+:::
+
+:::warning 練習
+請寫一個 function,判斷傳入的數字是不是質數
+並使用該 function 列出 1 ~ 100 間的所有質數
+質數特性
+- 不能被大於 2 且小於自身平方根的數整除
+- 只能被 1 和自身整除,不能被 2 到 (num-1) 整除
+:::
+
+:::warning 挑戰
+文文記性不太好,常常會忘東忘西。他也常忘記提款卡密碼,每次忘記密碼都得帶著身份證、存摺、印章親自到銀行去重設密碼,還得繳交 50 元的手續費,很是麻煩。後來他決定把密碼寫在提款卡上免得忘記,但是這樣一來,萬一提款卡掉了,存款就會被盜領。因此他決定以一個只有他看得懂的方式把密碼寫下來。
+
+他的密碼有 6 位數,所以他寫下了 7 個大寫字母,相鄰的每兩個字母間的「距離」就依序代表密碼中的一位數。所謂「距離」指的是從較「小」的字母要數幾個字母才能數到較「大」字母。字母的大小則是依其順序而定,越後面的字母越「大」。
+
+假設文文所寫的 7 個字母是 POKEMON,那麼密碼的第一位數就是字母 P 和 O 的「距離」,由於 P 就是 O 的下一個字母,因此,從 O 開始只要往下數一個字母就是 P 了,所以密碼的第一位數就是 1。密碼的第二位數則是字母 O 和 K 的「距離」,從 K 開始,往下數 4 個字母 (L, M, N, O) 就到了 O,所以第二位數是 4,以此類推。因此,POKEMON 所代表的密碼便是 146821。
+
+噓!你千萬別把這個密秘告訴別人哦,要不然文文的存款就不保了。
+
+文文可以透過 prompt 輸入文字
+輸入文字後就將解密後的密碼回傳
+```js
+const decrypt = (text) => {
+ // ... 在此寫你的程式碼
+}
+
+const input = prompt('輸入文字')
+console.log(decrypt(input))
+```
+
+測試資料
+|輸入|輸出|
+|---|---|
+|POKEMON|146821|
+|TYPHOON|598701|
+
+題目修改自 [高中生程式解題系統](https://zerojudge.tw/ShowProblem?problemid=a065)
+:::
diff --git a/docs/basic/data-string.md b/docs/basic/data-string.md
new file mode 100644
index 00000000..06a07077
--- /dev/null
+++ b/docs/basic/data-string.md
@@ -0,0 +1,205 @@
+# 資料處理 - 文字
+
+各種處理文字的語法
+
+## 基本處理
+- `.trim()` 移除前後空白
+- `.toUpperCase()` 轉大寫
+- `.toLowerCase()` 轉小寫
+
+:::tip TIP
+JavaScript 可以串連多個語法
+```js
+const text = ' 123 Abc Def GHI Jkl '
+const result = text.trim().toUpperCase().toLowerCase()
+console.log(result) // '123 abc def ghi jkl'
+```
+
+:::
+```js
+let text = ' 123 Abc Def GHI Jkl '
+console.log(text) // ' 123 Abc Def GHI Jkl '
+
+text = text.trim()
+console.log(text) // '123 Abc Def GHI Jkl'
+
+text = text.toUpperCase()
+console.log(text) // '123 ABC DEF GHI JKL'
+
+text = text.toLowerCase()
+console.log(text) // '123 abc def ghi jkl'
+```
+
+## 尋找與取代
+- `.includes(尋找文字, 從第幾個字開始)`
+ - 檢查是否有包含尋找文字,回傳 boolean
+ - 第二個參數是選填,預設是 `0`
+- `.indexOf(尋找文字, 從第幾個字開始往後)`
+ - 尋找陣列是否有東西符合尋找文字,回傳第一個符合的索引,`-1` 代表找不到
+ - 第二個參數是選填,預設是 `0`
+- `.lastIndexOf(尋找文字, 從第幾個字開始往前)`
+ - 尋找陣列是否有東西符合尋找文字,回傳最後一個符合的索引,`-1` 代表找不到
+ - 第二個參數是選填,預設是 `string.length - 1`
+- `.match(正則表達式Regex)`
+ - 符合的結果用陣列回傳
+ - 沒找到回傳 `null`
+- `.matchAll(正則表達式Regex)`
+ - 符合的結果用 `RegExpStringIterator` 回傳
+ - 只能用迴圈取資料
+- `.replace(搜尋文字或 Regex, 取代文字)`
+ - 搜尋文字只會取代找到的第一個
+ - 正則表達式有設定 `g` 會取代全部找到的
+ - 正則表達式的取代文字可以使用 `$1`, `$2`... 或 `$<群組名稱>` 代表找到的東西
+
+正則表達式語法參考:
+- [Learn Regex](https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md)
+- [Regexr](https://regexr.com/)
+- [Regex101](https://regex101.com/)
+
+:::danger 注意
+- `includes()` 只能放文字,不能放正則表達式,如果要用正則表達式的話要用
+- `match()`、`matchAll()` 只能放正則表達式,不能放文字
+- `replace()` 取代文字只會取代找到的第一個,如果要全部取代的話可以用迴圈或正則表達式
+:::
+
+```js
+const curry = '外賣 咖哩拌飯 咖哩烏冬'
+
+const includesCurry1 = text2.includes('咖哩')
+console.log(includesCurry) // true
+const includesCurry2 = text2.includes('咖哩', 3)
+console.log(includesCurry2) // false
+
+const indexCurry = text2.indexOf('咖哩')
+console.log(indexCurry) // 3
+
+const lastIndexCurry = text2.lastIndexOf('咖哩')
+console.log(lastIndexCurry) // 9
+
+const matchCurry = text2.match(/咖哩/g)
+console.log(matchCurry) // [ '咖哩', '咖哩' ]
+
+const matchAllCurry = text2.matchAll(/咖哩/g)
+console.log(matchAllCurry) // RegExpStringIterator
+for (const match of matchAllCurry) {
+ // [
+ // '咖哩',
+ // index: 3,
+ // input: '外賣 咖哩拌飯 咖哩烏冬',
+ // groups: undefined
+ // ]
+ console.log(match)
+}
+
+const replaceCurry1 = text2.replace('咖哩', '三色豆')
+console.log(replaceCurry1) // '外賣 三色豆拌飯 咖哩烏冬'
+
+const replaceCurry2 = text2.replace(/咖哩/g, '三色豆')
+console.log(replaceCurry2) // '外賣 三色豆拌飯 三色豆烏冬'
+
+const email = 'aaaa@gmail.com'
+const emailMatch = email.match(/^[0-9a-z]+@[0-9a-z]+\.[0-9a-z]+$/g)
+console.log(emailMatch) // ['aaaa@gmail.com']
+
+const emailRegexGroup = /^([0-9a-z]+)@([0-9a-z]+)\.([0-9a-z]+)$/g
+const emailMatchAllGroup = email.matchAll(emailRegexGroup)
+for (const match of emailMatchAllGroup) {
+ // 0: "aaaa@gmail.com"
+ // 1: "aaaa"
+ // 2: "gmail"
+ // 3: "com"
+ // groups: undefined
+ // index: 0
+ console.log(match)
+}
+
+const emailReplaceGroup = email.replace(emailRegexGroup, '帳號是 $1,網域是 $2.$3')
+console.log(emailReplaceGroup) // '帳號是 aaaa,網域是 gmail.com'
+
+const emailRegexGroup2 = /^(?[0-9a-z]+)@(?[0-9a-z]+)\.(?[0-9a-z]+)$/g
+const emailMatchAllGroup2 = email.matchAll(emailRegexGroup2)
+for (const match of emailMatchAllGroup2) {
+ // 0: "aaaa@gmail.com"
+ // 1: "aaaa"
+ // 2: "gmail"
+ // 3: "com"
+ // groups: {
+ // account: "aaa",
+ // domain: "gmail",
+ // tld: "com"
+ // }
+ // index: 0
+ console.log(match)
+}
+
+const emailReplaceGroup2 = email.replace(emailRegexGroup2, '帳號是 $,網域是 $.$')
+console.log(emailReplaceGroup2) // '帳號是 aaaa,網域是 gmail.com'
+```
+
+## 切割
+- `.substr(開始位置, 長度)`
+ - 從開始位置取指定長度的文字
+ - 位置可以放負數,代表倒數,`-1` 是倒數第一個字
+ - 長度不寫會直接取到結尾
+- `.substring(開始位置, 結束位置)`
+ - 從開始位置取到結束位置,**不包含結束位置**
+ - 結束位置不寫會直接取到結尾
+- `.slice(開始位置, 結束位置)`
+ - 從開始位置取到結束位置,**不包含結束位置**
+ - 結束位置不寫會直接取到結尾
+ - 位置可以放負數
+
+```js
+const text3 = 'abcdefg'
+
+console.log(text3.substr(3, 1)) // d
+
+console.log(text3.substr(3)) // defg
+
+// text3.substr(-3, 2)
+// text3.length = 7
+// -3 => 7 - 3 => 4
+// text3.substr(4, 2)
+console.log(text3.substr(-3, 2)) // ef
+
+console.log(text3.substring(2, 6)) // cdef
+
+console.log(text3.slice(2, 6)) // cdef
+
+// text3.slice(-4, -2)
+// text3.length = 7
+// -4 => 7 - 4 => 3
+// -2 => 7 - 2 => 5
+// text3.slice(3, 5)
+console.log(text3.slice(-4, -2)) // de
+
+```
+
+## 資料型態轉換
+
+## 綜合練習
+:::warning 練習
+將兩個 `prompt()` 輸入的數字相加顯示在網頁上,如果輸入的不是數字,跳出錯誤訊息
+:::
+
+:::warning 挑戰
+製作凱薩密碼 (Caesar Cipher) 加密工具
+使用者先輸入英文明文,再輸入數字密鑰
+請編寫一個 function 處理資料
+將明文和密鑰傳入,回傳處理完後的密文
+最後在網頁上顯示出來
+
+範例:
+```
+密鑰: 3
+明文: meet me after the toga party
+密文: PHHW PH DIWHU WKH WRJD SDUWB
+```
+
+提示:
+- `字串.charCodeAt(索引)` 可取得指定文字的字元數字編號
+- `String.fromCharCode(數字)` 可將字元編號轉回文字
+- 英文大寫 A-Z 的是連續的,小寫 A-Z 也是,但是英文大小寫編號間有其他字
+- 需考慮密鑰超過 26 的情況
+:::
+
diff --git a/docs/basic/function.md b/docs/basic/function.md
new file mode 100644
index 00000000..5ec0f703
--- /dev/null
+++ b/docs/basic/function.md
@@ -0,0 +1,398 @@
+# function
+
+function 可以將一段程式碼包裝起來,可以重複使用,也方便維護,寫成物件更可以將程式碼分類。
+
+## 語法
+function 由下列幾個部分組成
+- `名稱` 跟變數宣告一樣,給這個 function 一個名稱,建議以程式碼的功能命名
+- `()` 放傳入 function 的值
+- `{}` 則是要執行的程式碼
+- 執行 function 時只要使用 `名稱` 和 `()` 就能執行
+- 宣告時可以使用 `function declartaion` 或 `function expression` 兩種方式
+
+:::tip TIP
+使用 function expression 宣告時通常會使用 `const` 以避免 function 被覆寫
+:::
+
+```js
+// 使用 function declartaion 宣告 function
+function GoodMorning () {
+ document.write('早上好,現在我有冰淇淋')
+}
+
+// 使用 function expression 宣告 function
+const GoodMorning = function () {
+ document.write('早上好,現在我有冰淇淋')
+}
+
+// 執行 function
+GoodMorning()
+```
+
+## 傳入資料
+將資料傳入 function 可以讓 function 有更多的彈性
+- 傳入的資料叫做 `參數`,放在 `()` 內
+- 參數是 function 內的變數,只能在 function 內使用
+- 參數可以有多個,用 `,` 隔開
+- 能以 `arguments` 得到所有傳入參數的陣列
+
+:::danger 注意
+function 處理資料時盡量不要使用外部的變數,只針對傳入的資料做處理
+這種不會影響到外部的資料的 function 叫做 `Pure Function`
+:::
+
+```js
+function GoodMorning (time, item) {
+ console.log(arguments)
+ document.write(`${time}好,現在我有${item}`)
+}
+GoodMorning('早上', '冰淇淋')
+GoodMorning('中午', '桂格超大便當')
+GoodMorning('晚上')
+```
+
+參數可以設定預設值,當參數沒有收到傳入值時,就會使用預設值
+```js
+function GoodMorning (time = '早上', item = '冰淇淋') {
+ document.write(`${time}好,現在我有${item}`)
+}
+GoodMorning('早上', '冰淇淋')
+GoodMorning('中午', '桂格超大便當')
+GoodMorning('晚上')
+GoodMorning(undefined, '炸雞排')
+```
+
+## return
+`return` 可以將程式處理完畢的結果傳出,讓 function 更有彈性
+
+:::danger 注意
+- 一個 function 只能有一個 `return`
+- `return` 下面的程式碼不會執行
+:::
+
+```js
+function GoodMorning (time = '早上', item = '冰淇淋') {
+ return `${time}好,現在我有${item}`
+ // return 下面的程式碼不會執行
+ console.log(123)
+}
+
+const text = GoodMorning('早上', '冰淇淋')
+console.log(text)
+
+document.write(GoodMorning('中午', '桂格超大便當'))
+alert(GoodMorning('晚上', '雞排珍奶'))
+```
+
+## 箭頭函式
+箭頭函式可以將 function 的宣告寫得比較簡短
+
+```js
+const GoodMorning = (time = '早上', item = '冰淇淋') => {
+ return `${time}好,現在我有${item}`
+}
+```
+:::tip TIP
+- 箭頭函式只有一個參數時,可以省略 `()`
+- 箭頭函式只有一行時,可以省略 `{}` 和 `return`
+- 只有一行簡寫時,如果要回傳物件,要用 `()` 包起來
+
+簡寫範例
+```js
+// 簡寫前
+const squre = (number) => {
+ return number * number
+}
+
+// 簡寫後
+const squre = number => number * number
+```
+物件回傳簡寫範例
+```js
+// 簡寫前
+const getUserData = () => {
+ return { name: 'John', age: 18 }
+}
+
+// 簡寫後
+const getUserData = () => ({ name: 'John', age: 18 })
+```
+:::
+
+:::danger 注意
+箭頭函式無法使用 `arguments` 取得所有傳入的參數
+```js
+const GoodMorning = (time = '早上', item = '冰淇淋') => {
+ // Uncaught ReferenceError: arguments is not defined
+ console.log(arguments)
+}
+
+```
+:::
+
+## jsDoc
+使用 [jsDoc](https://jsdoc.app/) 格式編寫的 function 註解會有編輯器提示
+
+```js
+/**
+ * 早安
+ */
+const GoodMorning = () => {}
+
+/**
+ * 早安
+ * @param time 時間
+ * @param item 物品
+ */
+const GoodMorning = (time, item) => {}
+
+/**
+ * 早安
+ * @param time {string} 時間
+ * @param item {string} 物品
+ */
+const GoodMorning = (time, item) => {}
+
+/**
+ * 早安
+ * @param [time=早上] {string} 時間
+ * @param [item=冰淇淋] {string} 物品
+ */
+const GoodMorning = (time = '早上', item = '冰淇淋') => {}
+
+/**
+ * 早安
+ * @param [time=早上] {string} 時間
+ * @param [item=冰淇淋] {string} 物品
+ * @returns {string} 組合完成的訊息
+ */
+const GoodMorning = (time = '早上', item = '冰淇淋') => {}
+```
+
+## 綜合練習
+:::warning 練習
+編寫一個 function,可以判斷傳入的數字是不是偶數,是的話回傳 `true`,不是則回傳 `false`
+:::
+
+:::warning 練習
+小明喜歡數數
+某天媽媽請他從 n 開始數,下一個數字是 n+1,再下一個數字是 n+2,以此類推
+媽媽想知道,小明數了多少個數字後,數過的數字總和會超過 m
+
+請寫一個程式,使用者可以用 `prompt` 輸入 n 和 m
+請將兩個數字傳入 function 計算後將結果回傳
+
+```js
+const calculate = (n, m) => {
+ // ... 在此寫你的程式碼
+}
+
+const number1 = parseInt(prompt('n'))
+const number2 = parseInt(prompt('m'))
+console.log(calculate(number1, number2))
+```
+
+測試資料
+|n|m|輸出|
+|---|---|---|
+|1|5|3|
+|5|10|2|
+|100|1000|10|
+
+題目修改自 [高中生程式解題系統](https://zerojudge.tw/ShowProblem?problemid=a215)
+:::
+
+:::warning 練習
+製作易經數字卦占卜程式
+使用者輸入三個數字後,將數字以陣列方式傳進 function
+並將處理後的上卦名、下卦名、變爻用陣列回傳
+
+數字卦占卜方式:
+- 輸入三個三位數數字
+- 將前兩個數字各除以 8,最後一個除以 6
+- 如果整除,則餘數即為除數 8 或 6
+- 各數字算完的餘數照八卦的順序選取卦
+- 八卦順序為乾一、兌二、離三、震四、巽五、坎六、艮七、坤八
+- 乾為天、兌為澤、離為火、震為雷、巽為風、坎為水、艮為山、坤為地
+
+範例:
+- 取三個數字 435 692 734
+- 下卦為 435 除以 8 的餘數,為 3,離卦
+- 上卦為 692 除以 8 的餘數,為 4,震卦
+- 變爻為 734 除以 6 的餘數,為 2,第二爻
+- 卜問出來的卦即是離下震上的雷火豐卦,可參考[易學網解卦](https://www.eee-learning.com/book/neweee55)
+
+範例程式碼
+```js
+const gua = (array) => {
+ // ... 在此寫你的程式碼
+}
+
+const number1 = parseInt(prompt('第一個數字'))
+const number2 = parseInt(prompt('第二個數字'))
+const number3 = parseInt(prompt('第三個數字'))
+const numbers = [number1, number2, number3]
+const result = gua(numbers)
+console.log(result[0]) // 輸出 離
+console.log(result[1]) // 輸出 震
+console.log(result[2]) // 輸出 2
+```
+:::
+
+:::warning 練習
+請寫一個 function 判斷輸入的文字是不是正著讀和反著讀都一樣的迴文
+`for`、`for of` 和 `for in` 可以迴圈文字
+
+```js
+const isPalindrome = (text) => {
+ // ... 在此寫你的程式碼
+}
+const result = isPalindrome(prompt('輸入文字'))
+console.log(result)
+```
+
+測試資料
+|文字|輸出|
+|---|---|
+|abba|true|
+|abcd|false|
+|abcba|true|
+:::
+
+:::warning 練習
+請寫一個 function 判斷輸入的文字括號是否閉合
+
+```js
+const isClose = (text) => {
+ // ... 在此寫你的程式碼
+}
+const result = isClose(prompt('輸入文字'))
+console.log(result)
+```
+
+測試資料
+|文字|輸出|
+|---|---|
+|(()|false|
+|()|true|
+|(())|true|
+|(()))|false|
+|)()()|false|
+:::
+
+## 遞迴
+使用遞迴函式是在函式中呼叫函式自己來重複執行動作
+
+累加範例,求 `1 + 2 + 3 + ... + n` 的總和
+```js
+// n = 5
+// sum(5) = 5 + sum(5 - 1) = 5 + sum(4) = 5 + 4 + 3 + 2 + 1 = 15
+// sum(4) = 4 + sum(4 - 1) = 4 + sum(3) = 4 + 3 + 2 + 1
+// sum(3) = 3 + sum(3 - 1) = 3 + sum(2) = 3 + 2 + 1
+// sum(2) = 2 + sum(2 - 1) = 2 + sum(1) = 2 + 1
+// sum(1) = 1
+const sum = n => {
+ if (n === 1) {
+ return 1
+ } else {
+ return n + sum(n - 1)
+ }
+ // return n === 1 ? 1 : n + sum(n - 1)
+}
+console.log(sum(5))
+```
+
+計算費氏數列的第 `n` 個數字
+`0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233`
+```js
+const fibonacci = (n) => {
+ if (n < 2) {
+ return n
+ } else {
+ return fibonacci(n - 1) + fibonacci(n - 2)
+ }
+}
+// n = 0 1 2 3 4 5 6
+// 數字 = 0 1 1 2 3 5 8
+// fib(3) = fib(3 - 1) + fib(3 - 2) = fib(2) + fib(1) = 1 + 1 = 2
+// fib(2) = fib(2 - 1) + fib(2 - 2) = fib(1) + fib(0) = 1 + 0 = 1
+// fib(1) = 1
+// fib(0) = 0
+console.log(fibonacci(3))
+```
+
+以輾轉相除法求最大公因數
+```js
+const gcd = (a, b) => {
+ if (a % b === 0) {
+ return b
+ } else {
+ return gcd(b, a % b)
+ }
+}
+// gcd(2002, 847) => a % b = 2002 % 847 = 308 => 308 != 0 => gcd(847, 308)
+// gcd(847, 308) => a % b = 847 % 308 = 231 => 231 != 0 => gcd(308, 231)
+// gcd(308, 231) => a % b = 308 % 231 = 77 => 77 != 0 => gcd(231, 77)
+// gcd(231, 77) => a % b = 231 % 77 = 0 => 77
+console.log(gcd(2002, 847))
+```
+
+
+
+## var 區域
+`var` 其實是以 function 為區域的區域變數
+```js
+var a = 1
+a = 100
+var a = 2
+console.log(a) // 2
+
+var b = 1
+function func () {
+ var b = 2
+ console.log('in', b) // 2
+}
+func()
+console.log('out', b) // 1
+```
+
+## 提升
+`var` 和 `function` 有提升的特性,宣告的變數會被提升到最上面,可以先使用再宣告變數
+
+直接使用一個未宣告也未賦值的變數會出現錯誤
+```js
+// Uncaught ReferenceError: text is not defined
+console.log(text)
+```
+
+在宣告 `let` 和 `const` 變數前使用變數會出現錯誤
+```js
+// Uncaught ReferenceError: Cannot access 'text' before initialization
+console.log(text)
+const text = 'abc'
+```
+
+`var` 宣告的變數會被提升到最上面,但是不會賦值,所以會是 `undefined`
+```js
+console.log(text) // undefined
+var text = 'abc'
+```
+
+`function declartaion` 會被提升
+```js
+hi('AAA')
+function hi (name) {
+ console.log('hi, ' + name)
+}
+```
+
+使用 `var` 的 `function expression` 會被提升,但是不會賦值,所以會是 `undefined`
+```js
+// function expression
+console.log(hi) // undefined
+// Uncaught TypeError: hi2 is not a function
+// hi('BBB')
+var hi = function (name) {
+ console.log('hi, ' + name)
+}
+```
diff --git a/docs/basic/intro.md b/docs/basic/intro.md
new file mode 100644
index 00000000..850cd71f
--- /dev/null
+++ b/docs/basic/intro.md
@@ -0,0 +1,129 @@
+# 認識 JavaScript
+
+JavaScript 是網頁開發者必學的三種語言之一,也是最流行的腳本語言
+
+## 前端功能
+- 能夠改變 HTML 內容
+- 能夠改變 HTML 屬性
+- 能夠改變 CSS 樣式
+- 能夠偵測使用者對網頁的操作 (滑鼠點擊、鍵盤按鍵等)
+
+改變 HTML 內容範例
+::: demo [vanilla]
+```html
+
+ 我是一段文字
+
+
+
+```
+:::
+
+改變 HTML 屬性範例
+::: demo [vanilla]
+```html
+
+ 點我去 Google
+
+
+
+```
+:::
+
+改變 CSS 樣式範例
+::: demo [vanilla]
+```html
+
+ 我是一段文字
+
+
+
+```
+:::
+
+偵測使用者操作範例
+::: demo [vanilla]
+```html
+
+
+ 點擊燈泡來開關這盞燈
+
+
+```
+:::
+
+## 後端功能
+- 能以 `Node.js` 開發網頁後端
+- 能使用和前端一樣的語言進行開發
+- `Node.js` 以 Google 的 V8 引擎打造,非常快速
+- 有相當多的套件可以使用,擴充性高
+
+## 其他功能
+- 能以 [Electron](https://electronjs.org/) 開發跨平台應用程式
+- 能以 [UserScript](https://greasyfork.org/zh-TW) 修改網頁
+
+## 缺點
+- 在網頁前端以明碼顯示,安全性不高
+- 規範標準不一,有 `CommonJS` 和 `ECMAScript` 等
+- JavaScript 程式結尾可以不加 `;`,程式在執行時會自動補上,但是會發生補錯位置的情況
+- `+` 號不只可以做數學運算,還可以連接文字
+- 以 Node.js 開發的專案套件佔了空間一大半
+- 語法更新頻繁,需要透過 [Babel](https://babeljs.io/) 等工具將新語法轉換成舊瀏覽器支援的語法
+- 弱型別語言,所以才會有 [TypeScript](https://www.typescriptlang.org/) 出現
+
+## 前端的使用方式
+網頁上的 JavaScript 程式碼必須要搭配 `
+