重新布局,添加教程
This commit is contained in:
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -19,5 +19,6 @@ declare module 'vue' {
|
|||||||
NTag: typeof import('naive-ui')['NTag']
|
NTag: typeof import('naive-ui')['NTag']
|
||||||
NText: typeof import('naive-ui')['NText']
|
NText: typeof import('naive-ui')['NText']
|
||||||
Preview: typeof import('./src/components/Preview.vue')['default']
|
Preview: typeof import('./src/components/Preview.vue')['default']
|
||||||
|
Tutorial: typeof import('./src/components/Tutorial.vue')['default']
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
26
package-lock.json
generated
26
package-lock.json
generated
@@ -13,6 +13,8 @@
|
|||||||
"@codemirror/lang-javascript": "^6.2.3",
|
"@codemirror/lang-javascript": "^6.2.3",
|
||||||
"@vueuse/core": "^12.7.0",
|
"@vueuse/core": "^12.7.0",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
|
"github-markdown-css": "^5.8.1",
|
||||||
|
"marked": "^15.0.7",
|
||||||
"naive-ui": "^2.41.0",
|
"naive-ui": "^2.41.0",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
@@ -1618,6 +1620,18 @@
|
|||||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/github-markdown-css": {
|
||||||
|
"version": "5.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-5.8.1.tgz",
|
||||||
|
"integrity": "sha512-8G+PFvqigBQSWLQjyzgpa2ThD9bo7+kDsriUIidGcRhXgmcaAWUIpCZf8DavJgc+xifjbCG+GvMyWr0XMXmc7g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/glob-parent": {
|
"node_modules/glob-parent": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
@@ -1820,6 +1834,18 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.5.0"
|
"@jridgewell/sourcemap-codec": "^1.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/marked": {
|
||||||
|
"version": "15.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.7.tgz",
|
||||||
|
"integrity": "sha512-dgLIeKGLx5FwziAnsk4ONoGwHwGPJzselimvlVskE9XLN4Orv9u2VA3GWw/lYUqjfA0rUT/6fqKwfZJapP9BEg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"marked": "bin/marked.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/merge-stream": {
|
"node_modules/merge-stream": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
"@codemirror/lang-javascript": "^6.2.3",
|
"@codemirror/lang-javascript": "^6.2.3",
|
||||||
"@vueuse/core": "^12.7.0",
|
"@vueuse/core": "^12.7.0",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
|
"github-markdown-css": "^5.8.1",
|
||||||
|
"marked": "^15.0.7",
|
||||||
"naive-ui": "^2.41.0",
|
"naive-ui": "^2.41.0",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
|
|||||||
27
public/turtorial/01/README.md
Normal file
27
public/turtorial/01/README.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# 测试
|
||||||
|
|
||||||
|
## 什么是 HTML
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div>hello</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
```css
|
||||||
|
.welcome {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 什么是 HTML
|
||||||
|
|
||||||
|
## 什么是 HTML
|
||||||
|
|
||||||
|
## 什么是 HTML
|
||||||
|
|
||||||
|
## 什么是 HTML
|
||||||
|
|
||||||
|
## 什么是 HTML
|
||||||
|
|
||||||
|
## 什么是 HTML
|
||||||
|
|
||||||
|
## 什么是 HTML
|
||||||
1
public/turtorial/02/README.md
Normal file
1
public/turtorial/02/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# 什么是 CSS
|
||||||
0
public/turtorial/03/README.md
Normal file
0
public/turtorial/03/README.md
Normal file
@@ -1,6 +1,5 @@
|
|||||||
import { defineConfig } from "@rsbuild/core"
|
import { defineConfig } from "@rsbuild/core"
|
||||||
import { pluginVue } from "@rsbuild/plugin-vue"
|
import { pluginVue } from "@rsbuild/plugin-vue"
|
||||||
// import AutoImport from "unplugin-auto-import/rspack"
|
|
||||||
import { NaiveUiResolver } from "unplugin-vue-components/resolvers"
|
import { NaiveUiResolver } from "unplugin-vue-components/resolvers"
|
||||||
import Components from "unplugin-vue-components/rspack"
|
import Components from "unplugin-vue-components/rspack"
|
||||||
|
|
||||||
@@ -17,19 +16,6 @@ export default defineConfig({
|
|||||||
tools: {
|
tools: {
|
||||||
rspack: {
|
rspack: {
|
||||||
plugins: [
|
plugins: [
|
||||||
// AutoImport({
|
|
||||||
// imports: [
|
|
||||||
// "vue",
|
|
||||||
// {
|
|
||||||
// "naive-ui": [
|
|
||||||
// "useDialog",
|
|
||||||
// "useMessage",
|
|
||||||
// "useNotification",
|
|
||||||
// "useLoadingBar",
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// }),
|
|
||||||
Components({
|
Components({
|
||||||
resolvers: [NaiveUiResolver()],
|
resolvers: [NaiveUiResolver()],
|
||||||
}),
|
}),
|
||||||
|
|||||||
24
src/App.vue
24
src/App.vue
@@ -2,6 +2,7 @@
|
|||||||
import { dateZhCN, zhCN } from "naive-ui"
|
import { dateZhCN, zhCN } from "naive-ui"
|
||||||
import Editors from "./components/Editors.vue"
|
import Editors from "./components/Editors.vue"
|
||||||
import Preview from "./components/Preview.vue"
|
import Preview from "./components/Preview.vue"
|
||||||
|
import Tutorial from "./components/Tutorial.vue"
|
||||||
import { useMagicKeys, whenever } from "@vueuse/core"
|
import { useMagicKeys, whenever } from "@vueuse/core"
|
||||||
|
|
||||||
const { ctrl_s } = useMagicKeys({
|
const { ctrl_s } = useMagicKeys({
|
||||||
@@ -22,14 +23,25 @@ whenever(ctrl_r, () => {})
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-config-provider :locale="zhCN" :date-locale="dateZhCN">
|
<n-config-provider class="myContainer" :locale="zhCN" :date-locale="dateZhCN" inline-theme-disabled>
|
||||||
<n-split :min="0.25" :max="0.75">
|
<n-split :default-size="1 / 3" min="300px" max="700px">
|
||||||
<template #1>
|
<template #1><Tutorial /></template>
|
||||||
<Editors />
|
|
||||||
</template>
|
|
||||||
<template #2>
|
<template #2>
|
||||||
<Preview />
|
<n-split direction="vertical">
|
||||||
|
<template #1>
|
||||||
|
<Editors />
|
||||||
|
</template>
|
||||||
|
<template #2>
|
||||||
|
<Preview />
|
||||||
|
</template>
|
||||||
|
</n-split>
|
||||||
</template>
|
</template>
|
||||||
</n-split>
|
</n-split>
|
||||||
</n-config-provider>
|
</n-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
<style scoped>
|
||||||
|
.myContainer {
|
||||||
|
height: 100vh;
|
||||||
|
width: 100vw;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<n-tabs
|
<n-tabs
|
||||||
size="large"
|
style="height: 100%"
|
||||||
pane-class="pane"
|
pane-class="pane"
|
||||||
|
size="large"
|
||||||
:default-value="currentTab"
|
:default-value="currentTab"
|
||||||
type="segment"
|
type="segment"
|
||||||
@update:value="changeTab"
|
@update:value="changeTab"
|
||||||
@@ -9,7 +10,7 @@
|
|||||||
<n-tab-pane name="html" tab="HTML">
|
<n-tab-pane name="html" tab="HTML">
|
||||||
<template #tab>
|
<template #tab>
|
||||||
<n-flex align="center">
|
<n-flex align="center">
|
||||||
<Icon icon="skill-icons:html" :width="20" :height="20"></Icon>
|
<Icon icon="skill-icons:html" :width="20"></Icon>
|
||||||
<span>HTML</span>
|
<span>HTML</span>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
@@ -18,7 +19,7 @@
|
|||||||
<n-tab-pane name="css" tab="CSS">
|
<n-tab-pane name="css" tab="CSS">
|
||||||
<template #tab>
|
<template #tab>
|
||||||
<n-flex align="center">
|
<n-flex align="center">
|
||||||
<Icon icon="skill-icons:css" :width="20" :height="20"></Icon>
|
<Icon icon="skill-icons:css" :width="20"></Icon>
|
||||||
<span>CSS</span>
|
<span>CSS</span>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
@@ -27,7 +28,7 @@
|
|||||||
<n-tab-pane name="js" tab="JavaScript">
|
<n-tab-pane name="js" tab="JavaScript">
|
||||||
<template #tab>
|
<template #tab>
|
||||||
<n-flex align="center">
|
<n-flex align="center">
|
||||||
<Icon icon="skill-icons:javascript" :width="20" :height="20"></Icon>
|
<Icon icon="skill-icons:javascript" :width="20"></Icon>
|
||||||
<span>JavaScript</span>
|
<span>JavaScript</span>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
@@ -36,7 +37,7 @@
|
|||||||
<n-tab-pane name="actions" tab="选项">
|
<n-tab-pane name="actions" tab="选项">
|
||||||
<template #tab>
|
<template #tab>
|
||||||
<n-flex align="center">
|
<n-flex align="center">
|
||||||
<Icon icon="solar:settings-bold" :width="20" :height="20"></Icon>
|
<Icon icon="skill-icons:actix-dark" :width="20"></Icon>
|
||||||
<span>选项</span>
|
<span>选项</span>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</template>
|
</template>
|
||||||
@@ -72,7 +73,7 @@
|
|||||||
import { Icon } from "@iconify/vue"
|
import { Icon } from "@iconify/vue"
|
||||||
import Editor from "./Editor.vue"
|
import Editor from "./Editor.vue"
|
||||||
import { useStorage } from "@vueuse/core"
|
import { useStorage } from "@vueuse/core"
|
||||||
import { html, css, js, reset, size, changeSize } from "../store.ts"
|
import { html, css, js, reset, size, changeSize } from "../store"
|
||||||
|
|
||||||
const currentTab = useStorage("web-tab", "html")
|
const currentTab = useStorage("web-tab", "html")
|
||||||
|
|
||||||
@@ -83,7 +84,8 @@ function changeTab(tab: "html" | "css" | "js" | "actions") {
|
|||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.pane {
|
.pane {
|
||||||
height: calc(100vh - 62px);
|
height: 100%;
|
||||||
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
.wrapper {
|
.wrapper {
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<n-flex align="center" justify="space-between" class="pane">
|
<n-flex align="center" justify="space-between" class="title">
|
||||||
<n-text class="preview">预览</n-text>
|
<n-flex align="center">
|
||||||
|
<Icon icon="noto:eyes" :width="20"></Icon>
|
||||||
|
<n-text class="titleText">预览</n-text>
|
||||||
|
</n-flex>
|
||||||
<n-flex>
|
<n-flex>
|
||||||
<n-button>提交</n-button>
|
<!-- <n-button>提交</n-button> -->
|
||||||
</n-flex>
|
</n-flex>
|
||||||
</n-flex>
|
</n-flex>
|
||||||
<iframe class="iframe" ref="iframe"></iframe>
|
<iframe class="iframe" ref="iframe"></iframe>
|
||||||
@@ -10,16 +13,16 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { watchDebounced } from "@vueuse/core"
|
import { watchDebounced } from "@vueuse/core"
|
||||||
import { html, css, js } from "../store.ts"
|
import { html, css, js } from "../store"
|
||||||
import { onMounted, useTemplateRef } from "vue"
|
import { onMounted, useTemplateRef } from "vue"
|
||||||
|
import { Icon } from "@iconify/vue"
|
||||||
|
|
||||||
const iframe = useTemplateRef<HTMLIFrameElement>("iframe")
|
const iframe = useTemplateRef<HTMLIFrameElement>("iframe")
|
||||||
|
|
||||||
function preview() {
|
function preview() {
|
||||||
if (!iframe.value) return
|
if (!iframe.value) return
|
||||||
const doc = iframe.value.contentDocument!
|
const doc = iframe.value.contentDocument!
|
||||||
doc.open()
|
const content = `<!DOCTYPE html>
|
||||||
doc.write(`<!DOCTYPE html>
|
|
||||||
<html lang="zh-Hans-CN">
|
<html lang="zh-Hans-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
@@ -33,19 +36,21 @@ function preview() {
|
|||||||
${html.value}
|
${html.value}
|
||||||
<script type="module">${js.value}<\/script>
|
<script type="module">${js.value}<\/script>
|
||||||
</body>
|
</body>
|
||||||
</html>`)
|
</html>`
|
||||||
|
doc.open()
|
||||||
|
doc.write(content)
|
||||||
doc.close()
|
doc.close()
|
||||||
}
|
}
|
||||||
watchDebounced([html, css, js], preview, { debounce: 500, maxWait: 1000 })
|
watchDebounced([html, css, js], preview, { debounce: 500, maxWait: 1000 })
|
||||||
onMounted(preview)
|
onMounted(preview)
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.pane {
|
.title {
|
||||||
height: 46px;
|
height: 46px;
|
||||||
background-color: rgb(247, 247, 250);
|
background-color: rgb(247, 247, 250);
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
}
|
}
|
||||||
.preview {
|
.titleText {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
.iframe {
|
.iframe {
|
||||||
|
|||||||
61
src/components/Tutorial.vue
Normal file
61
src/components/Tutorial.vue
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<n-flex align="center" class="title">
|
||||||
|
<n-flex align="center">
|
||||||
|
<Icon icon="twemoji:open-book" :width="20"></Icon>
|
||||||
|
<n-text class="preview">教程</n-text>
|
||||||
|
<n-button text @click="prev" :disabled="step === '01'">
|
||||||
|
<Icon :width="24" icon="pepicons-pencil:arrow-left"></Icon>
|
||||||
|
</n-button>
|
||||||
|
<n-button text @click="next" :disabled="end">
|
||||||
|
<Icon :width="24" icon="pepicons-pencil:arrow-right"></Icon>
|
||||||
|
</n-button>
|
||||||
|
</n-flex>
|
||||||
|
</n-flex>
|
||||||
|
<div class="markdown-body" v-html="marked(content)"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { Icon } from "@iconify/vue"
|
||||||
|
import { step, prev, next, content } from "../store"
|
||||||
|
import { onMounted, ref, watch } from "vue"
|
||||||
|
import { marked } from "marked"
|
||||||
|
|
||||||
|
const end = ref(false)
|
||||||
|
|
||||||
|
async function getContent() {
|
||||||
|
const res = await fetch(`/turtorial/${step.value}/README.md`)
|
||||||
|
const data = await res.text()
|
||||||
|
if (!!data) {
|
||||||
|
content.value = data
|
||||||
|
end.value = false
|
||||||
|
} else {
|
||||||
|
end.value = true
|
||||||
|
content.value = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(getContent)
|
||||||
|
watch(step, getContent)
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.title {
|
||||||
|
height: 46px;
|
||||||
|
background-color: rgb(247, 247, 250);
|
||||||
|
padding: 0 20px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.preview {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
.markdown-body {
|
||||||
|
padding: 16px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
0
src/env.d.ts
vendored
Normal file
0
src/env.d.ts
vendored
Normal file
@@ -1,6 +1,7 @@
|
|||||||
import { createApp } from "vue"
|
import { createApp } from "vue"
|
||||||
import { create } from "naive-ui"
|
import { create } from "naive-ui"
|
||||||
import "normalize.css"
|
import "normalize.css"
|
||||||
|
import "github-markdown-css/github-markdown-light.css"
|
||||||
import App from "./App.vue"
|
import App from "./App.vue"
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|||||||
11
src/store.ts
11
src/store.ts
@@ -23,3 +23,14 @@ export const size = useStorage("web-fontsize", 24)
|
|||||||
export function changeSize(num: number) {
|
export function changeSize(num: number) {
|
||||||
size.value = num
|
size.value = num
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const step = useStorage("web-turtorial-step", "01")
|
||||||
|
export const content = useStorage("web-turtorial-content", "")
|
||||||
|
export function prev() {
|
||||||
|
let num = parseInt(step.value) - 1
|
||||||
|
step.value = num.toString().padStart(2, "0")
|
||||||
|
}
|
||||||
|
export function next() {
|
||||||
|
let num = parseInt(step.value) + 1
|
||||||
|
step.value = num.toString().padStart(2, "0")
|
||||||
|
}
|
||||||
|
|||||||
1
src/vite-env.d.ts
vendored
1
src/vite-env.d.ts
vendored
@@ -1 +0,0 @@
|
|||||||
/// <reference types="vite/client" />
|
|
||||||
Reference in New Issue
Block a user