valaxy 0.1.1 → 0.2.1
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/bin/valaxy.js +1 -1
- package/dist/chunk-B2JVVNA4.js +88 -0
- package/dist/chunk-FH6NMGNX.mjs +88 -0
- package/dist/chunk-TSLYS2VY.js +1 -0
- package/dist/chunk-U4ZDCBEC.mjs +1 -0
- package/dist/config-24b4f209.d.ts +188 -0
- package/dist/index.d.ts +337 -150
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{cli.d.ts → node/cli.d.ts} +0 -0
- package/dist/node/cli.js +45 -0
- package/dist/node/cli.mjs +45 -0
- package/dist/node/index.d.ts +46 -0
- package/dist/node/index.js +1 -0
- package/dist/node/index.mjs +1 -0
- package/package.json +23 -20
- package/src/client/components/PostCard.vue +16 -17
- package/src/client/components/PostList.vue +3 -3
- package/src/client/components/ValaxyCopyright.vue +1 -1
- package/src/client/components/ValaxyFooter.vue +1 -1
- package/src/client/components/ValaxyMd.vue +1 -1
- package/src/client/components/ValaxyOverlay.vue +4 -4
- package/src/client/components/ValaxyPagination.vue +14 -11
- package/src/client/components/ValaxyRightSidebar.vue +2 -2
- package/src/client/components/ValaxySidebar.vue +4 -10
- package/src/client/components/ValaxyToc.vue +12 -10
- package/src/client/composables/category.ts +24 -5
- package/src/client/composables/comments/index.ts +1 -0
- package/src/client/composables/comments/twikoo.ts +37 -0
- package/src/client/composables/comments/waline.ts +8 -5
- package/src/client/composables/common.ts +3 -4
- package/src/client/composables/post.ts +26 -1
- package/src/client/composables/search/algolia.ts +2 -1
- package/src/client/composables/sidebar.ts +2 -2
- package/src/client/composables/tag.ts +9 -2
- package/src/client/composables/widgets/backToTop.ts +10 -4
- package/src/client/index.html +5 -0
- package/src/client/layouts/404.vue +5 -1
- package/src/client/main.ts +2 -9
- package/src/client/modules/valaxy.ts +31 -13
- package/src/client/shims.d.ts +5 -5
- package/src/client/styles/common/button.scss +3 -5
- package/src/client/styles/common/code.scss +181 -9
- package/src/client/styles/common/custom-blocks.scss +84 -0
- package/src/client/styles/common/hamburger.scss +2 -2
- package/src/client/styles/common/markdown.scss +4 -6
- package/src/client/styles/common/sidebar.scss +3 -3
- package/src/client/styles/common/transition.scss +2 -2
- package/src/client/styles/css-vars.scss +39 -0
- package/src/client/styles/global/helper.scss +2 -2
- package/src/client/styles/global/i18n.scss +20 -0
- package/src/client/styles/global/index.scss +1 -1
- package/src/client/styles/global/nprogress.scss +1 -1
- package/src/client/styles/global/reset.scss +1 -1
- package/src/client/styles/index.scss +21 -8
- package/src/client/styles/mixins/config.scss +1 -1
- package/src/client/styles/mixins/index.scss +1 -0
- package/src/client/styles/palette.scss +58 -44
- package/src/client/styles/vars.scss +1 -13
- package/src/client/styles/widgets/banner.scss +2 -2
- package/src/client/utils/index.ts +0 -2
- package/src/node/build.ts +20 -1
- package/src/node/cli.ts +32 -19
- package/src/node/markdown/headings.ts +3 -2
- package/src/node/markdown/highlight.ts +50 -0
- package/src/node/markdown/highlightLines.ts +96 -0
- package/src/node/markdown/index.ts +23 -12
- package/src/node/markdown/markdown-it-container.ts +9 -1
- package/src/node/markdown/markdown-it-katex.ts +20 -10
- package/src/node/markdown/parseHeader.ts +4 -2
- package/src/node/options.ts +3 -1
- package/src/node/plugins/index.ts +53 -24
- package/src/node/plugins/markdown.ts +1 -1
- package/src/node/plugins/preset.ts +46 -10
- package/src/node/plugins/unocss.ts +21 -19
- package/src/node/rss.ts +127 -0
- package/src/node/server.ts +1 -1
- package/src/node/shims.d.ts +15 -0
- package/src/node/utils/cli.ts +0 -1
- package/src/node/vite.ts +7 -15
- package/src/types/config.ts +28 -2
- package/src/types/posts.ts +6 -1
- package/tsup.config.ts +1 -0
- package/dist/build-VGAF4K5S.js +0 -1
- package/dist/build-Y5F7AZ2V.mjs +0 -1
- package/dist/chunk-5KQ3UFYI.js +0 -1
- package/dist/chunk-ESCOXVP6.mjs +0 -83
- package/dist/chunk-JWA76JND.mjs +0 -1
- package/dist/chunk-WYCH73X6.js +0 -83
- package/dist/cli.js +0 -6
- package/dist/cli.mjs +0 -6
- package/src/client/pages/about/index.md +0 -5
- package/src/client/pages/posts/index.md +0 -5
- package/src/client/styles/css-vars/dark.scss +0 -17
- package/src/client/styles/css-vars/index.scss +0 -18
- package/src/client/styles/css-vars/light.scss +0 -9
|
@@ -18,22 +18,10 @@ $font: map.merge((
|
|
|
18
18
|
'serif-weight': 900,
|
|
19
19
|
), $font);
|
|
20
20
|
|
|
21
|
-
$z-index: () !default;
|
|
22
|
-
$z-index: map.merge((
|
|
23
|
-
'cloud': 8,
|
|
24
|
-
'go-down': 9,
|
|
25
|
-
'sidebar': 10,
|
|
26
|
-
'fireworks': 11,
|
|
27
|
-
'menu-btn': 20,
|
|
28
|
-
'go-up-btn': 20,
|
|
29
|
-
'search-popup': 30,
|
|
30
|
-
'search-btn': 31,
|
|
31
|
-
), $z-index);
|
|
32
|
-
|
|
33
21
|
$transition: () !default;
|
|
34
22
|
$transition: map.merge((
|
|
35
23
|
'duration-fast': 0.2s,
|
|
36
24
|
'duration': 0.4s,
|
|
37
25
|
'duration-slow': 0.6s,
|
|
38
|
-
'': all var(--
|
|
26
|
+
'': all var(--va-transition-duration-fast) ease-in-out
|
|
39
27
|
), $transition);
|
|
@@ -70,7 +70,7 @@ $char-animation-duration: 0.4s;
|
|
|
70
70
|
|
|
71
71
|
&-left {
|
|
72
72
|
border-left: 1px solid var(--banner-line-color);
|
|
73
|
-
border-right: 0px solid rgba(var(--
|
|
73
|
+
border-right: 0px solid rgba(var(--va-c-primary-rgb), 0.1);
|
|
74
74
|
border-right-width: 0px;
|
|
75
75
|
animation-name: char-move-left;
|
|
76
76
|
animation-duration: $char-animation-duration;
|
|
@@ -80,7 +80,7 @@ $char-animation-duration: 0.4s;
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
&-right {
|
|
83
|
-
border-left: 0px solid rgba(var(--
|
|
83
|
+
border-left: 0px solid rgba(var(--va-c-primary-rgb), 0.1);
|
|
84
84
|
border-right: 1px solid var(--banner-line-color);
|
|
85
85
|
border-left-width: 0px;
|
|
86
86
|
animation-name: char-move-right;
|
package/src/node/build.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { InlineConfig } from 'vite'
|
|
2
2
|
import { mergeConfig, build as viteBuild } from 'vite'
|
|
3
|
+
import { build as viteSsgBuild } from 'vite-ssg/node'
|
|
4
|
+
import generateSitemap from 'vite-ssg-sitemap'
|
|
5
|
+
|
|
3
6
|
import type { ResolvedValaxyOptions } from './options'
|
|
4
7
|
import { createViteConfig } from './vite'
|
|
5
8
|
|
|
@@ -7,6 +10,22 @@ export async function build(
|
|
|
7
10
|
options: ResolvedValaxyOptions,
|
|
8
11
|
viteConfig: InlineConfig = {},
|
|
9
12
|
) {
|
|
10
|
-
const inlineConfig = mergeConfig(
|
|
13
|
+
const inlineConfig = mergeConfig(await createViteConfig(options), viteConfig)
|
|
11
14
|
await viteBuild(inlineConfig)
|
|
12
15
|
}
|
|
16
|
+
|
|
17
|
+
export async function ssgBuild(
|
|
18
|
+
options: ResolvedValaxyOptions,
|
|
19
|
+
viteConfig: InlineConfig = {},
|
|
20
|
+
) {
|
|
21
|
+
const inlineConfig: InlineConfig = mergeConfig(await createViteConfig(options), viteConfig)
|
|
22
|
+
|
|
23
|
+
// https://github.com/antfu/vite-ssg
|
|
24
|
+
inlineConfig.ssgOptions = {
|
|
25
|
+
script: 'async',
|
|
26
|
+
formatting: 'minify',
|
|
27
|
+
onFinished() { generateSitemap() },
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
await viteSsgBuild({}, inlineConfig)
|
|
31
|
+
}
|
package/src/node/cli.ts
CHANGED
|
@@ -6,15 +6,17 @@ import yargs from 'yargs'
|
|
|
6
6
|
import type { InlineConfig, LogLevel } from 'vite'
|
|
7
7
|
import openBrowser from 'open'
|
|
8
8
|
|
|
9
|
-
// @ts-expect-error https://github.com/antfu/vite-ssg/pull/225
|
|
10
|
-
import { build as ssgBuild } from 'vite-ssg/node'
|
|
11
|
-
|
|
12
9
|
import consola from 'consola'
|
|
13
10
|
|
|
14
11
|
import { version } from '../../package.json'
|
|
15
12
|
import { resolveOptions } from './options'
|
|
16
13
|
import { bindShortcut, initServer, printInfo } from './utils/cli'
|
|
17
14
|
|
|
15
|
+
// build
|
|
16
|
+
import { build, ssgBuild } from './build'
|
|
17
|
+
// rss
|
|
18
|
+
import { build as rssBuild } from './rss'
|
|
19
|
+
|
|
18
20
|
const cli = yargs.scriptName('valaxy')
|
|
19
21
|
.usage('$0 [args]')
|
|
20
22
|
.version(version)
|
|
@@ -121,22 +123,29 @@ cli.command(
|
|
|
121
123
|
describe: 'output dir',
|
|
122
124
|
}).option('base', {
|
|
123
125
|
type: 'string',
|
|
126
|
+
default: '/',
|
|
124
127
|
describe: 'output base',
|
|
125
128
|
})
|
|
126
129
|
.strict()
|
|
127
130
|
.help(),
|
|
128
131
|
async({ ssg, root, base, output }) => {
|
|
129
|
-
const options = await resolveOptions({ userRoot: root })
|
|
132
|
+
const options = await resolveOptions({ userRoot: root }, 'build')
|
|
130
133
|
printInfo(options)
|
|
131
134
|
|
|
135
|
+
const viteConfig = {
|
|
136
|
+
base,
|
|
137
|
+
build: {
|
|
138
|
+
// make out dir empty, https://vitejs.dev/config/#build-emptyoutdir
|
|
139
|
+
emptyOutDir: true,
|
|
140
|
+
outDir: path.resolve(options.userRoot, output),
|
|
141
|
+
},
|
|
142
|
+
}
|
|
143
|
+
|
|
132
144
|
if (ssg) {
|
|
133
145
|
consola.info('use vite-ssg to do ssg build...')
|
|
146
|
+
|
|
134
147
|
try {
|
|
135
|
-
|
|
136
|
-
// https://github.com/antfu/vite-ssg/issues/226
|
|
137
|
-
await ssgBuild({
|
|
138
|
-
mode: 'production',
|
|
139
|
-
})
|
|
148
|
+
await ssgBuild(options, viteConfig)
|
|
140
149
|
}
|
|
141
150
|
catch (e) {
|
|
142
151
|
consola.error('[vite-ssg] An internal error occurred.')
|
|
@@ -144,21 +153,25 @@ cli.command(
|
|
|
144
153
|
}
|
|
145
154
|
}
|
|
146
155
|
else {
|
|
147
|
-
const { build } = await import('./build')
|
|
148
|
-
|
|
149
156
|
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
|
-
})
|
|
157
|
+
await build(options, viteConfig)
|
|
158
158
|
}
|
|
159
159
|
},
|
|
160
160
|
)
|
|
161
161
|
|
|
162
|
+
cli.command(
|
|
163
|
+
'rss [root]',
|
|
164
|
+
'generate rss feed',
|
|
165
|
+
args => commonOptions(args)
|
|
166
|
+
.strict()
|
|
167
|
+
.help(),
|
|
168
|
+
async({ root }) => {
|
|
169
|
+
consola.info('Generate RSS ...')
|
|
170
|
+
const options = await resolveOptions({ userRoot: root }, 'build')
|
|
171
|
+
await rssBuild(options)
|
|
172
|
+
},
|
|
173
|
+
)
|
|
174
|
+
|
|
162
175
|
/**
|
|
163
176
|
* set common options for cli
|
|
164
177
|
* @param args
|
|
@@ -4,10 +4,11 @@ import type { MarkdownRenderer } from '../markdown'
|
|
|
4
4
|
import { deeplyParseHeader } from './parseHeader'
|
|
5
5
|
import { slugify } from './slugify'
|
|
6
6
|
|
|
7
|
-
export const headingPlugin = (md: MarkdownIt, include = [
|
|
7
|
+
export const headingPlugin = (md: MarkdownIt, include = [1, 2, 3, 4]) => {
|
|
8
8
|
md.renderer.rules.heading_open = (tokens, i, options, env, self) => {
|
|
9
9
|
const token = tokens[i]
|
|
10
|
-
|
|
10
|
+
const tags = include.map(item => `h${item}`)
|
|
11
|
+
if (tags.includes(token.tag)) {
|
|
11
12
|
const title = tokens[i + 1].content
|
|
12
13
|
const idAttr = token.attrs!.find(([name]) => name === 'id')
|
|
13
14
|
const slug = idAttr && idAttr[1]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import consola from 'consola'
|
|
2
|
+
import escapeHtml from 'escape-html'
|
|
3
|
+
import prism from 'prismjs'
|
|
4
|
+
|
|
5
|
+
// prism is listed as actual dep so it's ok to require
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
7
|
+
const loadLanguages = require('prismjs/components/index')
|
|
8
|
+
|
|
9
|
+
// required to make embedded highlighting work...
|
|
10
|
+
loadLanguages(['markup', 'css', 'javascript'])
|
|
11
|
+
|
|
12
|
+
function wrap(code: string, lang: string): string {
|
|
13
|
+
if (lang === 'text')
|
|
14
|
+
code = escapeHtml(code)
|
|
15
|
+
|
|
16
|
+
return `<pre v-pre><code>${code}</code></pre>`
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const highlight = (str: string, lang: string) => {
|
|
20
|
+
if (!lang)
|
|
21
|
+
return wrap(str, 'text')
|
|
22
|
+
|
|
23
|
+
lang = lang.toLowerCase()
|
|
24
|
+
const rawLang = lang
|
|
25
|
+
if (lang === 'vue' || lang === 'html')
|
|
26
|
+
lang = 'markup'
|
|
27
|
+
|
|
28
|
+
if (lang === 'md')
|
|
29
|
+
lang = 'markdown'
|
|
30
|
+
|
|
31
|
+
if (lang === 'ts')
|
|
32
|
+
lang = 'typescript'
|
|
33
|
+
|
|
34
|
+
if (lang === 'py')
|
|
35
|
+
lang = 'python'
|
|
36
|
+
|
|
37
|
+
if (!prism.languages[lang]) {
|
|
38
|
+
try {
|
|
39
|
+
loadLanguages([lang])
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
consola.warn(`[valaxy] Syntax highlight for language "${lang}" is not supported.`)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (prism.languages[lang]) {
|
|
46
|
+
const code = prism.highlight(str, prism.languages[lang], lang)
|
|
47
|
+
return wrap(code, rawLang)
|
|
48
|
+
}
|
|
49
|
+
return wrap(str, 'text')
|
|
50
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Modified from https://github.com/egoist/markdown-it-highlight-lines
|
|
2
|
+
import type MarkdownIt from 'markdown-it'
|
|
3
|
+
|
|
4
|
+
const wrapperRE = /^<pre .*?><code>/
|
|
5
|
+
|
|
6
|
+
export const highlightLinePlugin = (md: MarkdownIt) => {
|
|
7
|
+
const fence = md.renderer.rules.fence!
|
|
8
|
+
md.renderer.rules.fence = (...args) => {
|
|
9
|
+
const [tokens, idx, options] = args
|
|
10
|
+
const token = tokens[idx]
|
|
11
|
+
|
|
12
|
+
// due to use of markdown-it-attrs, the {0} syntax would have been converted
|
|
13
|
+
// to attrs on the token
|
|
14
|
+
const attr = token.attrs && token.attrs[0]
|
|
15
|
+
if (!attr)
|
|
16
|
+
return fence(...args)
|
|
17
|
+
|
|
18
|
+
const lines = attr[0]
|
|
19
|
+
if (!lines || !/[\d,-]+/.test(lines))
|
|
20
|
+
return fence(...args)
|
|
21
|
+
|
|
22
|
+
const lineNumbers = lines
|
|
23
|
+
.split(',')
|
|
24
|
+
.map(v => v.split('-').map(v => parseInt(v, 10)))
|
|
25
|
+
|
|
26
|
+
const code = options.highlight
|
|
27
|
+
? options.highlight(token.content, token.info, '')
|
|
28
|
+
: token.content
|
|
29
|
+
|
|
30
|
+
const rawCode = code.replace(wrapperRE, '')
|
|
31
|
+
const highlightLinesCode = rawCode
|
|
32
|
+
.split('\n')
|
|
33
|
+
.map((split, index) => {
|
|
34
|
+
const lineNumber = index + 1
|
|
35
|
+
const inRange = lineNumbers.some(([start, end]) => {
|
|
36
|
+
if (start && end)
|
|
37
|
+
return lineNumber >= start && lineNumber <= end
|
|
38
|
+
|
|
39
|
+
return lineNumber === start
|
|
40
|
+
})
|
|
41
|
+
if (inRange)
|
|
42
|
+
return '<div class="highlighted"> </div>'
|
|
43
|
+
|
|
44
|
+
return '<br>'
|
|
45
|
+
})
|
|
46
|
+
.join('')
|
|
47
|
+
|
|
48
|
+
const highlightLinesWrapperCode = `<div class="highlight-lines">${highlightLinesCode}</div>`
|
|
49
|
+
|
|
50
|
+
return highlightLinesWrapperCode + code
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// markdown-it plugin for wrapping <pre> ... </pre>.
|
|
55
|
+
//
|
|
56
|
+
// If your plugin was chained before preWrapper, you can add additional element directly.
|
|
57
|
+
// If your plugin was chained after preWrapper, you can use these slots:
|
|
58
|
+
// 1. <!--beforebegin-->
|
|
59
|
+
// 2. <!--afterbegin-->
|
|
60
|
+
// 3. <!--beforeend-->
|
|
61
|
+
// 4. <!--afterend-->
|
|
62
|
+
export const preWrapperPlugin = (md: MarkdownIt) => {
|
|
63
|
+
const fence = md.renderer.rules.fence!
|
|
64
|
+
md.renderer.rules.fence = (...args) => {
|
|
65
|
+
const [tokens, idx] = args
|
|
66
|
+
const token = tokens[idx]
|
|
67
|
+
const rawCode = fence(...args)
|
|
68
|
+
return `<div class="language-${token.info.trim()}">${rawCode}</div>`
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// markdown-it plugin for generating line numbers.
|
|
73
|
+
// It depends on preWrapper plugin.
|
|
74
|
+
export const lineNumberPlugin = (md: MarkdownIt) => {
|
|
75
|
+
const fence = md.renderer.rules.fence!
|
|
76
|
+
md.renderer.rules.fence = (...args) => {
|
|
77
|
+
const rawCode = fence(...args)
|
|
78
|
+
const code = rawCode.slice(
|
|
79
|
+
rawCode.indexOf('<code>'),
|
|
80
|
+
rawCode.indexOf('</code>'),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
const lines = code.split('\n')
|
|
84
|
+
const lineNumbersCode = [...Array(lines.length - 1)]
|
|
85
|
+
.map((line, index) => `<span class="line-number">${index + 1}</span><br>`)
|
|
86
|
+
.join('')
|
|
87
|
+
|
|
88
|
+
const lineNumbersWrapperCode = `<div class="line-numbers-wrapper">${lineNumbersCode}</div>`
|
|
89
|
+
|
|
90
|
+
const finalCode = rawCode
|
|
91
|
+
.replace(/<\/div>$/, `${lineNumbersWrapperCode}</div>`)
|
|
92
|
+
.replace(/"(language-\w+)"/, '"$1 line-numbers-mode"')
|
|
93
|
+
|
|
94
|
+
return finalCode
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -2,9 +2,10 @@ import type MarkdownIt from 'markdown-it'
|
|
|
2
2
|
|
|
3
3
|
import Anchor from 'markdown-it-anchor'
|
|
4
4
|
import Emoji from 'markdown-it-emoji'
|
|
5
|
-
import Prism from 'markdown-it-prism'
|
|
6
5
|
import LinkAttributes from 'markdown-it-link-attributes'
|
|
7
6
|
import TOC from 'markdown-it-table-of-contents'
|
|
7
|
+
import TaskLists from 'markdown-it-task-lists'
|
|
8
|
+
import attrs from 'markdown-it-attrs'
|
|
8
9
|
|
|
9
10
|
import type { KatexOptions } from 'katex'
|
|
10
11
|
import Katex from '../markdown/markdown-it-katex'
|
|
@@ -12,6 +13,8 @@ import { containerPlugin } from '../markdown/markdown-it-container'
|
|
|
12
13
|
import { headingPlugin } from '../markdown/headings'
|
|
13
14
|
import { slugify } from './slugify'
|
|
14
15
|
import { parseHeader } from './parseHeader'
|
|
16
|
+
import { highlight } from './highlight'
|
|
17
|
+
import { highlightLinePlugin, preWrapperPlugin } from './highlightLines'
|
|
15
18
|
|
|
16
19
|
export interface Header {
|
|
17
20
|
level: number
|
|
@@ -39,18 +42,25 @@ export interface MarkdownOptions extends MarkdownIt.Options {
|
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
export function setupMarkdownPlugins(md: MarkdownIt, mdOptions: MarkdownOptions = {}) {
|
|
45
|
+
md.set({
|
|
46
|
+
highlight,
|
|
47
|
+
})
|
|
42
48
|
md
|
|
49
|
+
.use(highlightLinePlugin)
|
|
50
|
+
.use(preWrapperPlugin)
|
|
43
51
|
.use(containerPlugin)
|
|
44
|
-
.use(headingPlugin)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
.use(headingPlugin, mdOptions?.toc?.includeLevel)
|
|
53
|
+
// .use(lineNumberPlugin)
|
|
54
|
+
// https://github.com/arve0/markdown-it-attrs
|
|
55
|
+
// add classes
|
|
56
|
+
md.use(attrs)
|
|
57
|
+
.use(LinkAttributes, {
|
|
58
|
+
matcher: (link: string) => /^https?:\/\//.test(link),
|
|
59
|
+
attrs: {
|
|
60
|
+
target: '_blank',
|
|
61
|
+
rel: 'noopener',
|
|
62
|
+
},
|
|
63
|
+
})
|
|
54
64
|
md.use(Katex, mdOptions.katex)
|
|
55
65
|
.use(Anchor, {
|
|
56
66
|
slugify,
|
|
@@ -58,11 +68,12 @@ export function setupMarkdownPlugins(md: MarkdownIt, mdOptions: MarkdownOptions
|
|
|
58
68
|
})
|
|
59
69
|
.use(TOC, {
|
|
60
70
|
slugify,
|
|
61
|
-
includeLevel: [2, 3],
|
|
71
|
+
includeLevel: [2, 3, 4],
|
|
62
72
|
format: parseHeader,
|
|
63
73
|
...mdOptions.toc,
|
|
64
74
|
})
|
|
65
75
|
.use(Emoji)
|
|
76
|
+
.use(TaskLists)
|
|
66
77
|
|
|
67
78
|
const originalRender = md.render
|
|
68
79
|
md.render = (...args) => {
|
|
@@ -24,7 +24,7 @@ function createContainer(classes: string, defaultTitle: string): ContainerArgs {
|
|
|
24
24
|
if (token.nesting === 1) {
|
|
25
25
|
if (classes === 'details') {
|
|
26
26
|
return `<details class="${classes} custom-block">${
|
|
27
|
-
|
|
27
|
+
`<summary>${info}</summary>`
|
|
28
28
|
}\n`
|
|
29
29
|
}
|
|
30
30
|
return `<div class="${classes} custom-block"><p class="custom-block-title">${
|
|
@@ -50,4 +50,12 @@ export const containerPlugin = (md: MarkdownIt) => {
|
|
|
50
50
|
render: (tokens: Token[], idx: number) =>
|
|
51
51
|
tokens[idx].nesting === 1 ? '<div v-pre>\n' : '</div>\n',
|
|
52
52
|
})
|
|
53
|
+
|
|
54
|
+
const languages = ['zh-CN', 'en']
|
|
55
|
+
languages.forEach((lang) => {
|
|
56
|
+
md.use(container, lang, {
|
|
57
|
+
render: (tokens: Token[], idx: number) =>
|
|
58
|
+
tokens[idx].nesting === 1 ? `<div lang="${lang}">\n` : '</div>\n',
|
|
59
|
+
})
|
|
60
|
+
})
|
|
53
61
|
}
|
|
@@ -41,11 +41,13 @@ function isValidDelim(state: any, pos: number) {
|
|
|
41
41
|
function math_inline(state: any, silent: boolean) {
|
|
42
42
|
let match, token, res, pos
|
|
43
43
|
|
|
44
|
-
if (state.src[state.pos] !== '$')
|
|
44
|
+
if (state.src[state.pos] !== '$')
|
|
45
|
+
return false
|
|
45
46
|
|
|
46
47
|
res = isValidDelim(state, state.pos)
|
|
47
48
|
if (!res.can_open) {
|
|
48
|
-
if (!silent)
|
|
49
|
+
if (!silent)
|
|
50
|
+
state.pending += '$'
|
|
49
51
|
state.pos += 1
|
|
50
52
|
return true
|
|
51
53
|
}
|
|
@@ -64,20 +66,23 @@ function math_inline(state: any, silent: boolean) {
|
|
|
64
66
|
while (state.src[pos] === '\\') pos -= 1
|
|
65
67
|
|
|
66
68
|
// Even number of escapes, potential closing delimiter found
|
|
67
|
-
if (((match - pos) % 2) === 1)
|
|
69
|
+
if (((match - pos) % 2) === 1)
|
|
70
|
+
break
|
|
68
71
|
match += 1
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
// No closing delimter found. Consume $ and continue.
|
|
72
75
|
if (match === -1) {
|
|
73
|
-
if (!silent)
|
|
76
|
+
if (!silent)
|
|
77
|
+
state.pending += '$'
|
|
74
78
|
state.pos = start
|
|
75
79
|
return true
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
// Check if we have empty content, ie: $$. Do not parse.
|
|
79
83
|
if (match - start === 0) {
|
|
80
|
-
if (!silent)
|
|
84
|
+
if (!silent)
|
|
85
|
+
state.pending += '$$'
|
|
81
86
|
state.pos = start + 1
|
|
82
87
|
return true
|
|
83
88
|
}
|
|
@@ -85,7 +90,8 @@ function math_inline(state: any, silent: boolean) {
|
|
|
85
90
|
// Check for valid closing delimiter
|
|
86
91
|
res = isValidDelim(state, match)
|
|
87
92
|
if (!res.can_close) {
|
|
88
|
-
if (!silent)
|
|
93
|
+
if (!silent)
|
|
94
|
+
state.pending += '$'
|
|
89
95
|
state.pos = start
|
|
90
96
|
return true
|
|
91
97
|
}
|
|
@@ -106,13 +112,16 @@ function math_block(state: any, start: number, end: number, silent: boolean) {
|
|
|
106
112
|
let pos = state.bMarks[start] + state.tShift[start]
|
|
107
113
|
let max = state.eMarks[start]
|
|
108
114
|
|
|
109
|
-
if (pos + 2 > max)
|
|
110
|
-
|
|
115
|
+
if (pos + 2 > max)
|
|
116
|
+
return false
|
|
117
|
+
if (state.src.slice(pos, pos + 2) !== '$$')
|
|
118
|
+
return false
|
|
111
119
|
|
|
112
120
|
pos += 2
|
|
113
121
|
firstLine = state.src.slice(pos, max)
|
|
114
122
|
|
|
115
|
-
if (silent)
|
|
123
|
+
if (silent)
|
|
124
|
+
return true
|
|
116
125
|
if (firstLine.trim().slice(-2) === '$$') {
|
|
117
126
|
// Single line expression
|
|
118
127
|
firstLine = firstLine.trim().slice(0, -2)
|
|
@@ -122,7 +131,8 @@ function math_block(state: any, start: number, end: number, silent: boolean) {
|
|
|
122
131
|
for (next = start; !found;) {
|
|
123
132
|
next++
|
|
124
133
|
|
|
125
|
-
if (next >= end)
|
|
134
|
+
if (next >= end)
|
|
135
|
+
break
|
|
126
136
|
|
|
127
137
|
pos = state.bMarks[next] + state.tShift[next]
|
|
128
138
|
max = state.eMarks[next]
|
|
@@ -48,8 +48,10 @@ export const removeNonCodeWrappedHTML = (str: string) => {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
const compose = (...processors: ((str: string) => string)[]) => {
|
|
51
|
-
if (processors.length === 0)
|
|
52
|
-
|
|
51
|
+
if (processors.length === 0)
|
|
52
|
+
return (input: string) => input
|
|
53
|
+
if (processors.length === 1)
|
|
54
|
+
return processors[0]
|
|
53
55
|
return processors.reduce((prev, next) => {
|
|
54
56
|
return str => next(prev(str))
|
|
55
57
|
})
|
package/src/node/options.ts
CHANGED
|
@@ -16,6 +16,7 @@ export interface ValaxyEntryOptions {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export interface ResolvedValaxyOptions {
|
|
19
|
+
mode: 'dev' | 'build'
|
|
19
20
|
/**
|
|
20
21
|
* Client root path
|
|
21
22
|
* @default 'valaxy/src/client'
|
|
@@ -69,7 +70,7 @@ export function getThemeRoot(name: string, entry: string) {
|
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
// for cli options
|
|
72
|
-
export async function resolveOptions(options: ValaxyEntryOptions) {
|
|
73
|
+
export async function resolveOptions(options: ValaxyEntryOptions, mode: ResolvedValaxyOptions['mode'] = 'dev') {
|
|
73
74
|
const clientRoot = resolve(resolveImportPath('valaxy/package.json'), 'src/client')
|
|
74
75
|
const userRoot = resolve(options.userRoot || process.cwd())
|
|
75
76
|
|
|
@@ -77,6 +78,7 @@ export async function resolveOptions(options: ValaxyEntryOptions) {
|
|
|
77
78
|
const themeRoot = getThemeRoot(theme, userRoot)
|
|
78
79
|
|
|
79
80
|
const valaxyOptions: ResolvedValaxyOptions = {
|
|
81
|
+
mode,
|
|
80
82
|
clientRoot,
|
|
81
83
|
userRoot,
|
|
82
84
|
themeRoot,
|
|
@@ -8,33 +8,58 @@ import type { ResolvedValaxyOptions, ValaxyServerOptions } from '../options'
|
|
|
8
8
|
import { toAtFS } from '../utils'
|
|
9
9
|
import { VALAXY_CONFIG_ID } from './valaxy'
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
/**
|
|
12
|
+
* for /@valaxyjs/styles
|
|
13
|
+
* @param roots
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
function generateStyles(roots: string[]) {
|
|
17
|
+
const imports: string[] = []
|
|
18
|
+
|
|
19
|
+
for (const root of roots) {
|
|
20
|
+
const styles: string[] = []
|
|
21
|
+
|
|
22
|
+
const autoloadNames = ['index', 'css-vars']
|
|
23
|
+
autoloadNames.forEach((name) => {
|
|
24
|
+
styles.push(join(root, 'styles', `${name}.css`))
|
|
25
|
+
styles.push(join(root, 'styles', `${name}.scss`))
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
for (const style of styles) {
|
|
29
|
+
if (fs.existsSync(style))
|
|
30
|
+
imports.push(`import "${toAtFS(style)}"`)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return imports.join('\n')
|
|
34
|
+
}
|
|
15
35
|
|
|
16
|
-
|
|
36
|
+
function generateLocales(roots: string[]) {
|
|
37
|
+
const imports: string[] = [
|
|
38
|
+
'const messages = { "zh-CN": {}, en: {} }',
|
|
39
|
+
]
|
|
40
|
+
const languages = ['zh-CN', 'en']
|
|
41
|
+
|
|
42
|
+
roots.forEach((root, i) => {
|
|
43
|
+
languages.forEach((lang) => {
|
|
44
|
+
const langYml = `${root}/locales/${lang}.yml`
|
|
45
|
+
if (fs.existsSync(langYml)) {
|
|
46
|
+
const varName = lang.replace('-', '') + i
|
|
47
|
+
imports.push(`import ${varName} from "${langYml}"`)
|
|
48
|
+
imports.push(`Object.assign(messages['${lang}'], ${varName})`)
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
})
|
|
17
52
|
|
|
18
|
-
|
|
19
|
-
|
|
53
|
+
imports.push('export default messages')
|
|
54
|
+
return imports.join('\n')
|
|
55
|
+
}
|
|
20
56
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
join(root, 'styles', 'vars.scss'),
|
|
24
|
-
join(root, 'styles', 'index.css'),
|
|
25
|
-
join(root, 'styles', 'index.scss'),
|
|
26
|
-
]
|
|
57
|
+
export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions: ValaxyServerOptions = {}): Plugin {
|
|
58
|
+
const valaxyPrefix = '/@valaxy'
|
|
27
59
|
|
|
28
|
-
|
|
29
|
-
if (fs.existsSync(style)) {
|
|
30
|
-
imports.push(`import "${toAtFS(style)}"`)
|
|
31
|
-
continue
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
60
|
+
let valaxyConfig = options.config
|
|
35
61
|
|
|
36
|
-
|
|
37
|
-
}
|
|
62
|
+
const roots = [options.clientRoot, options.themeRoot, options.userRoot]
|
|
38
63
|
|
|
39
64
|
return {
|
|
40
65
|
name: 'Valaxy',
|
|
@@ -60,7 +85,10 @@ export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions
|
|
|
60
85
|
|
|
61
86
|
// generate styles
|
|
62
87
|
if (id === '/@valaxyjs/styles')
|
|
63
|
-
return
|
|
88
|
+
return generateStyles(roots)
|
|
89
|
+
|
|
90
|
+
if (id === '/@valaxyjs/locales')
|
|
91
|
+
return generateLocales(roots)
|
|
64
92
|
|
|
65
93
|
if (id.startsWith(valaxyPrefix))
|
|
66
94
|
return ''
|
|
@@ -69,7 +97,8 @@ export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions
|
|
|
69
97
|
async handleHotUpdate(ctx) {
|
|
70
98
|
// handle valaxy.config.ts hmr
|
|
71
99
|
const { file, server } = ctx
|
|
72
|
-
if (file !== options.configFile)
|
|
100
|
+
if (file !== options.configFile)
|
|
101
|
+
return
|
|
73
102
|
|
|
74
103
|
const { config } = await resolveConfig()
|
|
75
104
|
|
|
@@ -47,7 +47,7 @@ export function createMarkdownPlugin(options: ResolvedValaxyOptions): Plugin[] {
|
|
|
47
47
|
handleHotUpdate(ctx) {
|
|
48
48
|
const { file, server } = ctx
|
|
49
49
|
// send headers
|
|
50
|
-
if (file.endsWith('.md')) {
|
|
50
|
+
if (file.endsWith('.md') && _md && _md.__data) {
|
|
51
51
|
server.ws.send({
|
|
52
52
|
type: 'custom',
|
|
53
53
|
event: 'valaxy:pageHeaders',
|