valaxy 0.0.2 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1 -1
- package/bin/valaxy.js +11 -0
- package/dist/build-OOT6HK6S.js +1 -0
- package/dist/build-SG32QSQ3.mjs +1 -0
- package/dist/chunk-7JDYOPID.js +1 -0
- package/dist/chunk-JJEBEWGI.mjs +1 -0
- package/dist/chunk-L3EDI35I.js +1 -0
- package/dist/chunk-L5SNNWFJ.js +78 -0
- package/dist/chunk-MVJUGWXR.mjs +1 -0
- package/dist/chunk-QI435Q25.mjs +78 -0
- package/dist/config-d6527c8c.d.ts +174 -0
- package/dist/node/cli.d.ts +3 -0
- package/dist/node/cli.js +6 -0
- package/dist/node/cli.mjs +6 -0
- package/dist/node/index.d.ts +45 -0
- package/dist/node/index.js +1 -0
- package/dist/node/index.mjs +1 -0
- package/dist/types/index.d.ts +110 -0
- package/dist/types/index.js +1 -0
- package/dist/types/index.mjs +1 -0
- package/package.json +75 -3
- package/src/client/App.vue +16 -0
- package/src/client/components/AppLink.vue +20 -0
- package/src/client/components/PostCard.vue +69 -0
- package/src/client/components/PostList.vue +50 -0
- package/src/client/components/README.md +7 -0
- package/src/client/components/ValaxyCopyright.vue +80 -0
- package/src/client/components/ValaxyFooter.vue +53 -0
- package/src/client/components/ValaxyHamburger.vue +21 -0
- package/src/client/components/ValaxyMd.vue +71 -0
- package/src/client/components/ValaxyOverlay.vue +44 -0
- package/src/client/components/ValaxyPagination.vue +122 -0
- package/src/client/components/ValaxyRightSidebar.vue +32 -0
- package/src/client/components/ValaxySidebar.vue +35 -0
- package/src/client/components/ValaxyToc.vue +70 -0
- package/src/client/composables/category.ts +101 -0
- package/src/client/composables/comments/index.ts +1 -0
- package/src/client/composables/comments/waline.ts +60 -0
- package/src/client/composables/common.ts +27 -0
- package/src/client/composables/dark.ts +4 -0
- package/src/client/composables/features/index.ts +1 -0
- package/src/client/composables/features/katex.ts +15 -0
- package/src/client/composables/helper.ts +26 -0
- package/src/client/composables/index.ts +17 -0
- package/src/client/composables/layout.ts +7 -0
- package/src/client/composables/post.ts +96 -0
- package/src/client/composables/search/algolia.ts +114 -0
- package/src/client/composables/search/index.ts +0 -0
- package/src/client/composables/sidebar.ts +128 -0
- package/src/client/composables/tag.ts +70 -0
- package/src/client/composables/widgets/aplayer.ts +23 -0
- package/src/client/composables/widgets/backToTop.ts +28 -0
- package/src/client/composables/widgets/codepen.ts +12 -0
- package/src/client/composables/widgets/index.ts +3 -0
- package/src/client/index.html +24 -0
- package/src/client/layouts/404.vue +25 -0
- package/src/client/layouts/README.md +14 -0
- package/src/client/locales/README.md +7 -0
- package/src/client/locales/en.yml +107 -0
- package/src/client/locales/zh-CN.yml +106 -0
- package/src/client/main.ts +30 -0
- package/src/client/modules/README.md +11 -0
- package/src/client/modules/nprogress.ts +14 -0
- package/src/client/modules/pinia.ts +17 -0
- package/src/client/modules/pwa.ts +12 -0
- package/src/client/modules/valaxy.ts +42 -0
- package/src/client/pages/README.md +20 -0
- package/src/client/pages/[...all].vue +15 -0
- package/src/client/pages/about/index.md +5 -0
- package/src/client/pages/hi/[name].vue +52 -0
- package/src/client/pages/index.vue +3 -0
- package/src/client/pages/page/[page].vue +12 -0
- package/src/client/pages/posts/index.md +5 -0
- package/src/client/public/_headers +3 -0
- package/src/client/public/favicon.svg +21 -0
- package/src/client/public/pwa-192x192.png +0 -0
- package/src/client/public/pwa-512x512.png +0 -0
- package/src/client/public/safari-pinned-tab.svg +41 -0
- package/src/client/shims.d.ts +36 -0
- package/src/client/stores/app.ts +14 -0
- package/src/client/stores/user.ts +35 -0
- package/src/client/styles/common/button.scss +29 -0
- package/src/client/styles/common/code.scss +35 -0
- package/src/client/styles/common/hamburger.scss +56 -0
- package/src/client/styles/common/markdown.scss +43 -0
- package/src/client/styles/common/scrollbar.scss +34 -0
- package/src/client/styles/common/sidebar.scss +30 -0
- package/src/client/styles/common/transition.scss +23 -0
- package/src/client/styles/css-vars/dark.scss +17 -0
- package/src/client/styles/css-vars/index.scss +18 -0
- package/src/client/styles/css-vars/light.scss +9 -0
- package/src/client/styles/global/helper.scss +3 -0
- package/src/client/styles/global/index.scss +38 -0
- package/src/client/styles/global/nprogress.scss +14 -0
- package/src/client/styles/global/reset.scss +20 -0
- package/src/client/styles/index.scss +18 -0
- package/src/client/styles/mixins/config.scss +1 -0
- package/src/client/styles/mixins/index.scss +2 -0
- package/src/client/styles/mixins/size.scss +49 -0
- package/src/client/styles/mixins/variable.scss +30 -0
- package/src/client/styles/palette.scss +61 -0
- package/src/client/styles/vars.scss +39 -0
- package/src/client/styles/widgets/banner.scss +116 -0
- package/src/client/types.ts +3 -0
- package/src/client/utils/helper.ts +30 -0
- package/src/client/utils/index.ts +2 -0
- package/src/client/utils/time.ts +23 -0
- package/src/core/config.ts +51 -0
- package/src/core/index.ts +5 -0
- package/src/core/utils.ts +1 -0
- package/src/index.ts +2 -0
- package/src/node/build.ts +12 -0
- package/src/node/cli.ts +177 -0
- package/src/node/config.ts +43 -0
- package/src/node/index.ts +1 -0
- package/src/node/markdown/headings.ts +24 -0
- package/src/node/markdown/index.ts +74 -0
- package/src/node/markdown/markdown-it-container.ts +53 -0
- package/src/node/markdown/markdown-it-katex.ts +200 -0
- package/src/node/markdown/parseHeader.ts +70 -0
- package/src/node/markdown/slugify.ts +24 -0
- package/src/node/options.ts +90 -0
- package/src/node/plugins/extendConfig.ts +28 -0
- package/src/node/plugins/index.ts +91 -0
- package/src/node/plugins/markdown.ts +62 -0
- package/src/node/plugins/preset.ts +174 -0
- package/src/node/plugins/unocss.ts +106 -0
- package/src/node/plugins/valaxy.ts +1 -0
- package/src/node/server.ts +21 -0
- package/src/node/shims.d.ts +23 -0
- package/src/node/utils/cli.ts +105 -0
- package/src/node/utils/index.ts +26 -0
- package/src/node/vite.ts +83 -0
- package/src/types/config.ts +250 -0
- package/src/types/index.ts +2 -0
- package/src/types/posts.ts +107 -0
- package/tsup.config.ts +17 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
@use "../mixins" as *;
|
|
2
|
+
|
|
3
|
+
$banner-animation-duration: 1s;
|
|
4
|
+
$line-animation-duration: 0.4s;
|
|
5
|
+
$char-animation-duration: 0.4s;
|
|
6
|
+
|
|
7
|
+
#banner {
|
|
8
|
+
position: relative;
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
align-items: center;
|
|
12
|
+
height: 100vh;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.banner-char-container {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-direction: column;
|
|
18
|
+
align-items: center;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.vertical-line {
|
|
22
|
+
&-top, &-bottom {
|
|
23
|
+
display: flex;
|
|
24
|
+
background-color: var(--banner-line-color);
|
|
25
|
+
width: 1px;
|
|
26
|
+
height: 0;
|
|
27
|
+
animation-name: extend-line;
|
|
28
|
+
animation-duration: $line-animation-duration;
|
|
29
|
+
animation-fill-mode: forwards;
|
|
30
|
+
animation-timing-function: ease-in;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&-bottom {
|
|
34
|
+
position: absolute;
|
|
35
|
+
bottom: 0;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@keyframes extend-line {
|
|
40
|
+
from {
|
|
41
|
+
height: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
to {
|
|
45
|
+
height: var(--banner-line-height);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.char {
|
|
50
|
+
font-family: get-css-var('font', 'serif');
|
|
51
|
+
font-size: var(--banner-char-size, 1rem);
|
|
52
|
+
font-weight: get-css-var('font', 'serif-weight');
|
|
53
|
+
background-color: var(--banner-char-bg-color);
|
|
54
|
+
line-height: 1;
|
|
55
|
+
|
|
56
|
+
transition: all 0.3s ease-in-out;
|
|
57
|
+
transition-delay: 0s;
|
|
58
|
+
|
|
59
|
+
&:hover {
|
|
60
|
+
color: var(--banner-char-hover-color);
|
|
61
|
+
background-color: var(--banner-char-color);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
&-left,
|
|
65
|
+
&-right {
|
|
66
|
+
display: flex;
|
|
67
|
+
color: var(--banner-char-color);
|
|
68
|
+
opacity: 0;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
&-left {
|
|
72
|
+
border-left: 1px solid var(--banner-line-color);
|
|
73
|
+
border-right: 0px solid rgba(var(--yun-c-primary-rgb), 0.1);
|
|
74
|
+
border-right-width: 0px;
|
|
75
|
+
animation-name: char-move-left;
|
|
76
|
+
animation-duration: $char-animation-duration;
|
|
77
|
+
animation-delay: $line-animation-duration;
|
|
78
|
+
animation-fill-mode: forwards;
|
|
79
|
+
animation-timing-function: ease-out;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
&-right {
|
|
83
|
+
border-left: 0px solid rgba(var(--yun-c-primary-rgb), 0.1);
|
|
84
|
+
border-right: 1px solid var(--banner-line-color);
|
|
85
|
+
border-left-width: 0px;
|
|
86
|
+
animation-name: char-move-right;
|
|
87
|
+
animation-duration: $char-animation-duration;
|
|
88
|
+
animation-delay: $line-animation-duration;
|
|
89
|
+
animation-fill-mode: forwards;
|
|
90
|
+
animation-timing-function: ease-out;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@keyframes char-move-left {
|
|
95
|
+
from {
|
|
96
|
+
opacity: 0;
|
|
97
|
+
border-right-width: 0;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
to {
|
|
101
|
+
opacity: 1;
|
|
102
|
+
border-right-width: var(--banner-empty-border-size, var(--banner-char-size));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@keyframes char-move-right {
|
|
107
|
+
from {
|
|
108
|
+
opacity: 0;
|
|
109
|
+
border-left-width: 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
to {
|
|
113
|
+
opacity: 1;
|
|
114
|
+
border-left-width: var(--banner-empty-border-size, var(--banner-char-size));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 生成介于 min 与 max 之间的随机数
|
|
3
|
+
* @returns
|
|
4
|
+
*/
|
|
5
|
+
export function random(min: number, max: number) {
|
|
6
|
+
return Math.random() * (max - min) + min
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* wrap node
|
|
11
|
+
* @param className
|
|
12
|
+
*/
|
|
13
|
+
export function wrap(el: HTMLElement, className: string) {
|
|
14
|
+
const wrapper = document.createElement('div')
|
|
15
|
+
wrapper.className = className
|
|
16
|
+
el.parentNode!.insertBefore(wrapper, el)
|
|
17
|
+
el.parentNode!.removeChild(el)
|
|
18
|
+
wrapper.appendChild(el)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 包裹表格,添加 class 以控制 table 样式
|
|
23
|
+
*/
|
|
24
|
+
export const wrapTable = (container: HTMLElement | Document = document) => {
|
|
25
|
+
container.querySelectorAll('table').forEach((el) => {
|
|
26
|
+
const container = document.createElement('div')
|
|
27
|
+
container.className = 'table-container'
|
|
28
|
+
wrap(el, 'table-container')
|
|
29
|
+
})
|
|
30
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import dayjs from 'dayjs'
|
|
2
|
+
import type { Post } from 'valaxy'
|
|
3
|
+
|
|
4
|
+
export function formatDate(date: string | number | Date, template = 'YYYY-MM-DD') {
|
|
5
|
+
const today = dayjs(date)
|
|
6
|
+
return today.format(template)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* sort posts by date
|
|
11
|
+
* @param posts
|
|
12
|
+
* @param desc
|
|
13
|
+
*/
|
|
14
|
+
export function sortByDate(posts: Post[], desc = true) {
|
|
15
|
+
return posts.sort((a, b) => {
|
|
16
|
+
const aDate = +new Date(a.date || '')
|
|
17
|
+
const bDate = +new Date(b.date || '')
|
|
18
|
+
if (desc)
|
|
19
|
+
return bDate - aDate
|
|
20
|
+
else
|
|
21
|
+
return aDate - bDate
|
|
22
|
+
})
|
|
23
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// @ts-expect-error virtual module @valaxyjs/config
|
|
2
|
+
import valaxyConfig from '@valaxyjs/config'
|
|
3
|
+
import type { ComputedRef, InjectionKey } from 'vue'
|
|
4
|
+
import { computed, inject, readonly, shallowRef } from 'vue'
|
|
5
|
+
import type { ThemeConfig } from 'valaxy-theme-yun'
|
|
6
|
+
import type { ValaxyConfig } from '../types'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* parse valaxy config
|
|
10
|
+
* @param data
|
|
11
|
+
* @returns
|
|
12
|
+
*/
|
|
13
|
+
function parse(data: string): ValaxyConfig {
|
|
14
|
+
const parsed = JSON.parse(data)
|
|
15
|
+
return (import.meta.env.DEV ? readonly(parsed) : parsed) as ValaxyConfig
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const valaxyConfigSymbol: InjectionKey<ComputedRef<ValaxyConfig<ThemeConfig>>> = Symbol('valaxy:config')
|
|
19
|
+
export const valaxyConfigRef = shallowRef<ValaxyConfig>(parse(valaxyConfig))
|
|
20
|
+
|
|
21
|
+
// hmr
|
|
22
|
+
if (import.meta.hot) {
|
|
23
|
+
// /@valaxyjs/config must be static string
|
|
24
|
+
import.meta.hot.accept('/@valaxyjs/config', (m) => {
|
|
25
|
+
valaxyConfigRef.value = parse(m.default)
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function initConfig() {
|
|
30
|
+
return computed(() => valaxyConfigRef.value)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/*
|
|
34
|
+
* get Config
|
|
35
|
+
* @returns
|
|
36
|
+
*/
|
|
37
|
+
export function useConfig() {
|
|
38
|
+
const config = inject(valaxyConfigSymbol)
|
|
39
|
+
if (!config)
|
|
40
|
+
throw new Error('[Valaxy] config not properly injected in qpp')
|
|
41
|
+
return config!
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* getThemeConfig
|
|
46
|
+
* @returns
|
|
47
|
+
*/
|
|
48
|
+
export function useThemeConfig() {
|
|
49
|
+
const config = useConfig()
|
|
50
|
+
return computed(() => config!.value.themeConfig)
|
|
51
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const isDev = import.meta.env.DEV === true
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { InlineConfig } from 'vite'
|
|
2
|
+
import { mergeConfig, build as viteBuild } from 'vite'
|
|
3
|
+
import type { ResolvedValaxyOptions } from './options'
|
|
4
|
+
import { createViteConfig } from './vite'
|
|
5
|
+
|
|
6
|
+
export async function build(
|
|
7
|
+
options: ResolvedValaxyOptions,
|
|
8
|
+
viteConfig: InlineConfig = {},
|
|
9
|
+
) {
|
|
10
|
+
const inlineConfig = mergeConfig(viteConfig, createViteConfig(options))
|
|
11
|
+
await viteBuild(inlineConfig)
|
|
12
|
+
}
|
package/src/node/cli.ts
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import path from 'path'
|
|
3
|
+
import { exec } from 'child_process'
|
|
4
|
+
import type { Argv } from 'yargs'
|
|
5
|
+
import yargs from 'yargs'
|
|
6
|
+
import type { InlineConfig, LogLevel } from 'vite'
|
|
7
|
+
import openBrowser from 'open'
|
|
8
|
+
|
|
9
|
+
// @ts-expect-error https://github.com/antfu/vite-ssg/pull/225
|
|
10
|
+
import { build as ssgBuild } from 'vite-ssg/node'
|
|
11
|
+
|
|
12
|
+
import consola from 'consola'
|
|
13
|
+
|
|
14
|
+
import { version } from '../../package.json'
|
|
15
|
+
import { resolveOptions } from './options'
|
|
16
|
+
import { bindShortcut, initServer, printInfo } from './utils/cli'
|
|
17
|
+
|
|
18
|
+
const cli = yargs.scriptName('valaxy')
|
|
19
|
+
.usage('$0 [args]')
|
|
20
|
+
.version(version)
|
|
21
|
+
.showHelpOnFail(false)
|
|
22
|
+
.alias('h', 'help')
|
|
23
|
+
.alias('v', 'version')
|
|
24
|
+
|
|
25
|
+
cli.command(
|
|
26
|
+
'* [root]',
|
|
27
|
+
'Start a local server for Valaxy',
|
|
28
|
+
args =>
|
|
29
|
+
commonOptions(args)
|
|
30
|
+
.option('port', {
|
|
31
|
+
alias: 'p',
|
|
32
|
+
type: 'number',
|
|
33
|
+
describe: 'port',
|
|
34
|
+
})
|
|
35
|
+
.option('open', {
|
|
36
|
+
alias: 'o',
|
|
37
|
+
default: false,
|
|
38
|
+
type: 'boolean',
|
|
39
|
+
describe: 'open in browser',
|
|
40
|
+
})
|
|
41
|
+
.option('remote', {
|
|
42
|
+
default: true,
|
|
43
|
+
type: 'boolean',
|
|
44
|
+
describe: 'listen public host and enable remote control',
|
|
45
|
+
})
|
|
46
|
+
.option('log', {
|
|
47
|
+
default: 'warn',
|
|
48
|
+
type: 'string',
|
|
49
|
+
choices: ['error', 'warn', 'info', 'silent'],
|
|
50
|
+
describe: 'log level',
|
|
51
|
+
})
|
|
52
|
+
.strict()
|
|
53
|
+
.help()
|
|
54
|
+
,
|
|
55
|
+
async({ root, port: userPort, open, remote, log }) => {
|
|
56
|
+
if (!fs.existsSync(path.resolve(root, 'pages')))
|
|
57
|
+
process.exit(0)
|
|
58
|
+
|
|
59
|
+
const port = userPort || 4859
|
|
60
|
+
const options = await resolveOptions({ userRoot: root })
|
|
61
|
+
|
|
62
|
+
const viteConfig: InlineConfig = {
|
|
63
|
+
server: {
|
|
64
|
+
watch: {
|
|
65
|
+
// watch theme updated
|
|
66
|
+
ignored: [`!${options.themeRoot}/**`, `${options.userRoot}/**.md`],
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
port,
|
|
70
|
+
strictPort: true,
|
|
71
|
+
open,
|
|
72
|
+
host: remote ? '0.0.0.0' : 'localhost',
|
|
73
|
+
},
|
|
74
|
+
logLevel: log as LogLevel,
|
|
75
|
+
}
|
|
76
|
+
await initServer(options, viteConfig)
|
|
77
|
+
printInfo(options, port, remote)
|
|
78
|
+
|
|
79
|
+
const SHORTCUTS = [
|
|
80
|
+
{
|
|
81
|
+
name: 'r',
|
|
82
|
+
fullName: 'restart',
|
|
83
|
+
action() {
|
|
84
|
+
initServer(options, viteConfig)
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: 'o',
|
|
89
|
+
fullName: 'open',
|
|
90
|
+
action() {
|
|
91
|
+
openBrowser(`http://localhost:${port}`)
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'e',
|
|
96
|
+
fullName: 'edit',
|
|
97
|
+
action() {
|
|
98
|
+
exec(`code "${root}"`)
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
]
|
|
102
|
+
bindShortcut(SHORTCUTS)
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
cli.command(
|
|
106
|
+
'build [root]',
|
|
107
|
+
'build your blog to static content',
|
|
108
|
+
args => commonOptions(args)
|
|
109
|
+
.option('ssg', {
|
|
110
|
+
alias: 's',
|
|
111
|
+
type: 'boolean',
|
|
112
|
+
// https://github.com/antfu/vite-ssg/pull/219
|
|
113
|
+
// to be true, when vite-ssg export build
|
|
114
|
+
default: false,
|
|
115
|
+
describe: 'static site generate',
|
|
116
|
+
})
|
|
117
|
+
.option('output', {
|
|
118
|
+
alias: 'o',
|
|
119
|
+
type: 'string',
|
|
120
|
+
default: 'dist',
|
|
121
|
+
describe: 'output dir',
|
|
122
|
+
}).option('base', {
|
|
123
|
+
type: 'string',
|
|
124
|
+
describe: 'output base',
|
|
125
|
+
})
|
|
126
|
+
.strict()
|
|
127
|
+
.help(),
|
|
128
|
+
async({ ssg, root, base, output }) => {
|
|
129
|
+
const options = await resolveOptions({ userRoot: root })
|
|
130
|
+
printInfo(options)
|
|
131
|
+
|
|
132
|
+
if (ssg) {
|
|
133
|
+
consola.info('use vite-ssg to do ssg build...')
|
|
134
|
+
try {
|
|
135
|
+
// wait vite-ssg can pass custom options
|
|
136
|
+
// https://github.com/antfu/vite-ssg/issues/226
|
|
137
|
+
await ssgBuild({
|
|
138
|
+
mode: 'production',
|
|
139
|
+
})
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
consola.error('[vite-ssg] An internal error occurred.')
|
|
143
|
+
console.log(e)
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
const { build } = await import('./build')
|
|
148
|
+
|
|
149
|
+
consola.info('use vite do spa build...')
|
|
150
|
+
await build(options, {
|
|
151
|
+
base,
|
|
152
|
+
build: {
|
|
153
|
+
// make out dir empty, https://vitejs.dev/config/#build-emptyoutdir
|
|
154
|
+
emptyOutDir: true,
|
|
155
|
+
outDir: path.resolve(options.userRoot, output),
|
|
156
|
+
},
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* set common options for cli
|
|
164
|
+
* @param args
|
|
165
|
+
* @returns
|
|
166
|
+
*/
|
|
167
|
+
function commonOptions(args: Argv<{}>) {
|
|
168
|
+
return args.positional('root', {
|
|
169
|
+
default: '.',
|
|
170
|
+
type: 'string',
|
|
171
|
+
describe: 'root folder of your source files',
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function run() {
|
|
176
|
+
cli.help().parse()
|
|
177
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// import { loadConfig } from 'c12'
|
|
2
|
+
import { loadConfig } from 'unconfig'
|
|
3
|
+
import defu from 'defu'
|
|
4
|
+
import type { ValaxyConfig } from '../types'
|
|
5
|
+
import { defaultValaxyConfig } from '../types'
|
|
6
|
+
import type { ValaxyEntryOptions } from './options'
|
|
7
|
+
|
|
8
|
+
// for user config
|
|
9
|
+
export async function resolveConfig(options: ValaxyEntryOptions = {}) {
|
|
10
|
+
// c12 merge array twice, so i deprecated it
|
|
11
|
+
// const { config, configFile } = await loadConfig<ValaxyConfig>({
|
|
12
|
+
// name: 'valaxy',
|
|
13
|
+
// defaults: defaultValaxyConfig,
|
|
14
|
+
// })
|
|
15
|
+
|
|
16
|
+
const { config: userConfig, sources } = await loadConfig<ValaxyConfig>({
|
|
17
|
+
sources: [
|
|
18
|
+
{
|
|
19
|
+
files: 'valaxy.config',
|
|
20
|
+
extensions: ['ts', 'js', 'mjs', 'cjs', 'json'],
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
merge: false,
|
|
24
|
+
})
|
|
25
|
+
const configFile = sources[0]
|
|
26
|
+
const config = defu(userConfig, defaultValaxyConfig)
|
|
27
|
+
|
|
28
|
+
const theme = options.theme || config.theme || 'yun'
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const { defaultThemeConfig } = await import(`valaxy-theme-${theme}`)
|
|
32
|
+
config.themeConfig = defu(config.themeConfig, defaultThemeConfig)
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
console.error(`valaxy-theme-${theme} doesn't have default config`)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
config,
|
|
40
|
+
configFile,
|
|
41
|
+
theme,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './server'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// ref vitepress
|
|
2
|
+
import type MarkdownIt from 'markdown-it'
|
|
3
|
+
import type { MarkdownRenderer } from '../markdown'
|
|
4
|
+
import { deeplyParseHeader } from './parseHeader'
|
|
5
|
+
import { slugify } from './slugify'
|
|
6
|
+
|
|
7
|
+
export const headingPlugin = (md: MarkdownIt, include = ['h2', 'h3']) => {
|
|
8
|
+
md.renderer.rules.heading_open = (tokens, i, options, env, self) => {
|
|
9
|
+
const token = tokens[i]
|
|
10
|
+
if (include.includes(token.tag)) {
|
|
11
|
+
const title = tokens[i + 1].content
|
|
12
|
+
const idAttr = token.attrs!.find(([name]) => name === 'id')
|
|
13
|
+
const slug = idAttr && idAttr[1]
|
|
14
|
+
const data = (md as MarkdownRenderer).__data
|
|
15
|
+
const headers = data.headers || (data.headers = [])
|
|
16
|
+
headers.push({
|
|
17
|
+
level: parseInt(token.tag.slice(1), 10),
|
|
18
|
+
title: deeplyParseHeader(title),
|
|
19
|
+
slug: slug || slugify(title),
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
return self.renderToken(tokens, i, options)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type MarkdownIt from 'markdown-it'
|
|
2
|
+
|
|
3
|
+
import Anchor from 'markdown-it-anchor'
|
|
4
|
+
import Emoji from 'markdown-it-emoji'
|
|
5
|
+
import Prism from 'markdown-it-prism'
|
|
6
|
+
import LinkAttributes from 'markdown-it-link-attributes'
|
|
7
|
+
import TOC from 'markdown-it-table-of-contents'
|
|
8
|
+
|
|
9
|
+
import type { KatexOptions } from 'katex'
|
|
10
|
+
import Katex from '../markdown/markdown-it-katex'
|
|
11
|
+
import { containerPlugin } from '../markdown/markdown-it-container'
|
|
12
|
+
import { headingPlugin } from '../markdown/headings'
|
|
13
|
+
import { slugify } from './slugify'
|
|
14
|
+
import { parseHeader } from './parseHeader'
|
|
15
|
+
|
|
16
|
+
export interface Header {
|
|
17
|
+
level: number
|
|
18
|
+
title: string
|
|
19
|
+
slug: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface MarkdownParsedData {
|
|
23
|
+
hoistedTags?: string[]
|
|
24
|
+
links?: string[]
|
|
25
|
+
headers?: Header[]
|
|
26
|
+
}
|
|
27
|
+
export interface MarkdownRenderer extends MarkdownIt {
|
|
28
|
+
__data: MarkdownParsedData
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface MarkdownOptions extends MarkdownIt.Options {
|
|
32
|
+
config?: (md: MarkdownIt) => void
|
|
33
|
+
anchor?: {
|
|
34
|
+
permalink?: Anchor.AnchorOptions['permalink']
|
|
35
|
+
}
|
|
36
|
+
// https://github.com/Oktavilla/markdown-it-table-of-contents
|
|
37
|
+
toc?: any
|
|
38
|
+
katex?: KatexOptions
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function setupMarkdownPlugins(md: MarkdownIt, mdOptions: MarkdownOptions = {}) {
|
|
42
|
+
md
|
|
43
|
+
.use(containerPlugin)
|
|
44
|
+
.use(headingPlugin)
|
|
45
|
+
// https://prismjs.com/
|
|
46
|
+
md.use(Prism)
|
|
47
|
+
md.use(LinkAttributes, {
|
|
48
|
+
matcher: (link: string) => /^https?:\/\//.test(link),
|
|
49
|
+
attrs: {
|
|
50
|
+
target: '_blank',
|
|
51
|
+
rel: 'noopener',
|
|
52
|
+
},
|
|
53
|
+
})
|
|
54
|
+
md.use(Katex, mdOptions.katex)
|
|
55
|
+
.use(Anchor, {
|
|
56
|
+
slugify,
|
|
57
|
+
permalink: Anchor.permalink.ariaHidden({}),
|
|
58
|
+
})
|
|
59
|
+
.use(TOC, {
|
|
60
|
+
slugify,
|
|
61
|
+
includeLevel: [2, 3],
|
|
62
|
+
format: parseHeader,
|
|
63
|
+
...mdOptions.toc,
|
|
64
|
+
})
|
|
65
|
+
.use(Emoji)
|
|
66
|
+
|
|
67
|
+
const originalRender = md.render
|
|
68
|
+
md.render = (...args) => {
|
|
69
|
+
(md as MarkdownRenderer).__data = {}
|
|
70
|
+
return originalRender.call(md, ...args)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return md as MarkdownRenderer
|
|
74
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// ref vitepress
|
|
2
|
+
// src/node/markdown/plugins/containers.ts
|
|
3
|
+
|
|
4
|
+
import type MarkdownIt from 'markdown-it'
|
|
5
|
+
import type Token from 'markdown-it/lib/token'
|
|
6
|
+
import container from 'markdown-it-container'
|
|
7
|
+
|
|
8
|
+
type ContainerArgs = [
|
|
9
|
+
typeof container,
|
|
10
|
+
string,
|
|
11
|
+
{
|
|
12
|
+
render(tokens: Token[], idx: number): string
|
|
13
|
+
},
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
function createContainer(classes: string, defaultTitle: string): ContainerArgs {
|
|
17
|
+
return [
|
|
18
|
+
container,
|
|
19
|
+
classes,
|
|
20
|
+
{
|
|
21
|
+
render(tokens, idx) {
|
|
22
|
+
const token = tokens[idx]
|
|
23
|
+
const info = token.info.trim().slice(classes.length).trim()
|
|
24
|
+
if (token.nesting === 1) {
|
|
25
|
+
if (classes === 'details') {
|
|
26
|
+
return `<details class="${classes} custom-block">${
|
|
27
|
+
info ? `<summary>${info}</summary>` : ''
|
|
28
|
+
}\n`
|
|
29
|
+
}
|
|
30
|
+
return `<div class="${classes} custom-block"><p class="custom-block-title">${
|
|
31
|
+
info || defaultTitle
|
|
32
|
+
}</p>\n`
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
return classes === 'details' ? '</details>\n' : '</div>\n'
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const containerPlugin = (md: MarkdownIt) => {
|
|
43
|
+
md.use(...createContainer('tip', 'TIP'))
|
|
44
|
+
.use(...createContainer('info', 'INFO'))
|
|
45
|
+
.use(...createContainer('warning', 'WARNING'))
|
|
46
|
+
.use(...createContainer('danger', 'WARNING'))
|
|
47
|
+
.use(...createContainer('details', 'Details'))
|
|
48
|
+
// explicitly escape Vue syntax
|
|
49
|
+
.use(container, 'v-pre', {
|
|
50
|
+
render: (tokens: Token[], idx: number) =>
|
|
51
|
+
tokens[idx].nesting === 1 ? '<div v-pre>\n' : '</div>\n',
|
|
52
|
+
})
|
|
53
|
+
}
|