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.
Files changed (138) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -1
  3. package/bin/valaxy.js +11 -0
  4. package/dist/build-OOT6HK6S.js +1 -0
  5. package/dist/build-SG32QSQ3.mjs +1 -0
  6. package/dist/chunk-7JDYOPID.js +1 -0
  7. package/dist/chunk-JJEBEWGI.mjs +1 -0
  8. package/dist/chunk-L3EDI35I.js +1 -0
  9. package/dist/chunk-L5SNNWFJ.js +78 -0
  10. package/dist/chunk-MVJUGWXR.mjs +1 -0
  11. package/dist/chunk-QI435Q25.mjs +78 -0
  12. package/dist/config-d6527c8c.d.ts +174 -0
  13. package/dist/node/cli.d.ts +3 -0
  14. package/dist/node/cli.js +6 -0
  15. package/dist/node/cli.mjs +6 -0
  16. package/dist/node/index.d.ts +45 -0
  17. package/dist/node/index.js +1 -0
  18. package/dist/node/index.mjs +1 -0
  19. package/dist/types/index.d.ts +110 -0
  20. package/dist/types/index.js +1 -0
  21. package/dist/types/index.mjs +1 -0
  22. package/package.json +75 -3
  23. package/src/client/App.vue +16 -0
  24. package/src/client/components/AppLink.vue +20 -0
  25. package/src/client/components/PostCard.vue +69 -0
  26. package/src/client/components/PostList.vue +50 -0
  27. package/src/client/components/README.md +7 -0
  28. package/src/client/components/ValaxyCopyright.vue +80 -0
  29. package/src/client/components/ValaxyFooter.vue +53 -0
  30. package/src/client/components/ValaxyHamburger.vue +21 -0
  31. package/src/client/components/ValaxyMd.vue +71 -0
  32. package/src/client/components/ValaxyOverlay.vue +44 -0
  33. package/src/client/components/ValaxyPagination.vue +122 -0
  34. package/src/client/components/ValaxyRightSidebar.vue +32 -0
  35. package/src/client/components/ValaxySidebar.vue +35 -0
  36. package/src/client/components/ValaxyToc.vue +70 -0
  37. package/src/client/composables/category.ts +101 -0
  38. package/src/client/composables/comments/index.ts +1 -0
  39. package/src/client/composables/comments/waline.ts +60 -0
  40. package/src/client/composables/common.ts +27 -0
  41. package/src/client/composables/dark.ts +4 -0
  42. package/src/client/composables/features/index.ts +1 -0
  43. package/src/client/composables/features/katex.ts +15 -0
  44. package/src/client/composables/helper.ts +26 -0
  45. package/src/client/composables/index.ts +17 -0
  46. package/src/client/composables/layout.ts +7 -0
  47. package/src/client/composables/post.ts +96 -0
  48. package/src/client/composables/search/algolia.ts +114 -0
  49. package/src/client/composables/search/index.ts +0 -0
  50. package/src/client/composables/sidebar.ts +128 -0
  51. package/src/client/composables/tag.ts +70 -0
  52. package/src/client/composables/widgets/aplayer.ts +23 -0
  53. package/src/client/composables/widgets/backToTop.ts +28 -0
  54. package/src/client/composables/widgets/codepen.ts +12 -0
  55. package/src/client/composables/widgets/index.ts +3 -0
  56. package/src/client/index.html +24 -0
  57. package/src/client/layouts/404.vue +25 -0
  58. package/src/client/layouts/README.md +14 -0
  59. package/src/client/locales/README.md +7 -0
  60. package/src/client/locales/en.yml +107 -0
  61. package/src/client/locales/zh-CN.yml +106 -0
  62. package/src/client/main.ts +30 -0
  63. package/src/client/modules/README.md +11 -0
  64. package/src/client/modules/nprogress.ts +14 -0
  65. package/src/client/modules/pinia.ts +17 -0
  66. package/src/client/modules/pwa.ts +12 -0
  67. package/src/client/modules/valaxy.ts +42 -0
  68. package/src/client/pages/README.md +20 -0
  69. package/src/client/pages/[...all].vue +15 -0
  70. package/src/client/pages/about/index.md +5 -0
  71. package/src/client/pages/hi/[name].vue +52 -0
  72. package/src/client/pages/index.vue +3 -0
  73. package/src/client/pages/page/[page].vue +12 -0
  74. package/src/client/pages/posts/index.md +5 -0
  75. package/src/client/public/_headers +3 -0
  76. package/src/client/public/favicon.svg +21 -0
  77. package/src/client/public/pwa-192x192.png +0 -0
  78. package/src/client/public/pwa-512x512.png +0 -0
  79. package/src/client/public/safari-pinned-tab.svg +41 -0
  80. package/src/client/shims.d.ts +36 -0
  81. package/src/client/stores/app.ts +14 -0
  82. package/src/client/stores/user.ts +35 -0
  83. package/src/client/styles/common/button.scss +29 -0
  84. package/src/client/styles/common/code.scss +35 -0
  85. package/src/client/styles/common/hamburger.scss +56 -0
  86. package/src/client/styles/common/markdown.scss +43 -0
  87. package/src/client/styles/common/scrollbar.scss +34 -0
  88. package/src/client/styles/common/sidebar.scss +30 -0
  89. package/src/client/styles/common/transition.scss +23 -0
  90. package/src/client/styles/css-vars/dark.scss +17 -0
  91. package/src/client/styles/css-vars/index.scss +18 -0
  92. package/src/client/styles/css-vars/light.scss +9 -0
  93. package/src/client/styles/global/helper.scss +3 -0
  94. package/src/client/styles/global/index.scss +38 -0
  95. package/src/client/styles/global/nprogress.scss +14 -0
  96. package/src/client/styles/global/reset.scss +20 -0
  97. package/src/client/styles/index.scss +18 -0
  98. package/src/client/styles/mixins/config.scss +1 -0
  99. package/src/client/styles/mixins/index.scss +2 -0
  100. package/src/client/styles/mixins/size.scss +49 -0
  101. package/src/client/styles/mixins/variable.scss +30 -0
  102. package/src/client/styles/palette.scss +61 -0
  103. package/src/client/styles/vars.scss +39 -0
  104. package/src/client/styles/widgets/banner.scss +116 -0
  105. package/src/client/types.ts +3 -0
  106. package/src/client/utils/helper.ts +30 -0
  107. package/src/client/utils/index.ts +2 -0
  108. package/src/client/utils/time.ts +23 -0
  109. package/src/core/config.ts +51 -0
  110. package/src/core/index.ts +5 -0
  111. package/src/core/utils.ts +1 -0
  112. package/src/index.ts +2 -0
  113. package/src/node/build.ts +12 -0
  114. package/src/node/cli.ts +177 -0
  115. package/src/node/config.ts +43 -0
  116. package/src/node/index.ts +1 -0
  117. package/src/node/markdown/headings.ts +24 -0
  118. package/src/node/markdown/index.ts +74 -0
  119. package/src/node/markdown/markdown-it-container.ts +53 -0
  120. package/src/node/markdown/markdown-it-katex.ts +200 -0
  121. package/src/node/markdown/parseHeader.ts +70 -0
  122. package/src/node/markdown/slugify.ts +24 -0
  123. package/src/node/options.ts +90 -0
  124. package/src/node/plugins/extendConfig.ts +28 -0
  125. package/src/node/plugins/index.ts +91 -0
  126. package/src/node/plugins/markdown.ts +62 -0
  127. package/src/node/plugins/preset.ts +174 -0
  128. package/src/node/plugins/unocss.ts +106 -0
  129. package/src/node/plugins/valaxy.ts +1 -0
  130. package/src/node/server.ts +21 -0
  131. package/src/node/shims.d.ts +23 -0
  132. package/src/node/utils/cli.ts +105 -0
  133. package/src/node/utils/index.ts +26 -0
  134. package/src/node/vite.ts +83 -0
  135. package/src/types/config.ts +250 -0
  136. package/src/types/index.ts +2 -0
  137. package/src/types/posts.ts +107 -0
  138. package/tsup.config.ts +17 -0
@@ -0,0 +1,200 @@
1
+ // copy from https://github.com/slidevjs/slidev/blob/main/packages/slidev/node/plugins/markdown-it-katex.ts
2
+ // Ported from https://github.com/waylonflinn/markdown-it-katex
3
+
4
+ /* Process inline math */
5
+ /*
6
+ Like markdown-it-simplemath, this is a stripped down, simplified version of:
7
+ https://github.com/runarberg/markdown-it-math
8
+
9
+ It differs in that it takes (a subset of) LaTeX as input and relies on KaTeX
10
+ for rendering output.
11
+ */
12
+
13
+ import type { KatexOptions } from 'katex'
14
+ import katex from 'katex'
15
+
16
+ // Test if potential opening or closing delimieter
17
+ // Assumes that there is a "$" at state.src[pos]
18
+ function isValidDelim(state: any, pos: number) {
19
+ const max = state.posMax
20
+ let can_open = true
21
+ let can_close = true
22
+
23
+ const prevChar = pos > 0 ? state.src.charCodeAt(pos - 1) : -1
24
+ const nextChar = pos + 1 <= max ? state.src.charCodeAt(pos + 1) : -1
25
+
26
+ // Check non-whitespace conditions for opening and closing, and
27
+ // check that closing delimeter isn't followed by a number
28
+ if (prevChar === 0x20/* " " */ || prevChar === 0x09
29
+ ||/* \t */ (nextChar >= 0x30/* "0" */ && nextChar <= 0x39/* "9" */))
30
+ can_close = false
31
+
32
+ if (nextChar === 0x20/* " " */ || nextChar === 0x09/* \t */)
33
+ can_open = false
34
+
35
+ return {
36
+ can_open,
37
+ can_close,
38
+ }
39
+ }
40
+
41
+ function math_inline(state: any, silent: boolean) {
42
+ let match, token, res, pos
43
+
44
+ if (state.src[state.pos] !== '$') return false
45
+
46
+ res = isValidDelim(state, state.pos)
47
+ if (!res.can_open) {
48
+ if (!silent) state.pending += '$'
49
+ state.pos += 1
50
+ return true
51
+ }
52
+
53
+ // First check for and bypass all properly escaped delimieters
54
+ // This loop will assume that the first leading backtick can not
55
+ // be the first character in state.src, which is known since
56
+ // we have found an opening delimieter already.
57
+ const start = state.pos + 1
58
+ match = start
59
+ // eslint-disable-next-line no-cond-assign
60
+ while ((match = state.src.indexOf('$', match)) !== -1) {
61
+ // Found potential $, look for escapes, pos will point to
62
+ // first non escape when complete
63
+ pos = match - 1
64
+ while (state.src[pos] === '\\') pos -= 1
65
+
66
+ // Even number of escapes, potential closing delimiter found
67
+ if (((match - pos) % 2) === 1) break
68
+ match += 1
69
+ }
70
+
71
+ // No closing delimter found. Consume $ and continue.
72
+ if (match === -1) {
73
+ if (!silent) state.pending += '$'
74
+ state.pos = start
75
+ return true
76
+ }
77
+
78
+ // Check if we have empty content, ie: $$. Do not parse.
79
+ if (match - start === 0) {
80
+ if (!silent) state.pending += '$$'
81
+ state.pos = start + 1
82
+ return true
83
+ }
84
+
85
+ // Check for valid closing delimiter
86
+ res = isValidDelim(state, match)
87
+ if (!res.can_close) {
88
+ if (!silent) state.pending += '$'
89
+ state.pos = start
90
+ return true
91
+ }
92
+
93
+ if (!silent) {
94
+ token = state.push('math_inline', 'math', 0)
95
+ token.markup = '$'
96
+ token.content = state.src.slice(start, match)
97
+ }
98
+
99
+ state.pos = match + 1
100
+ return true
101
+ }
102
+
103
+ function math_block(state: any, start: number, end: number, silent: boolean) {
104
+ let firstLine; let lastLine; let next; let lastPos
105
+ let found = false
106
+ let pos = state.bMarks[start] + state.tShift[start]
107
+ let max = state.eMarks[start]
108
+
109
+ if (pos + 2 > max) return false
110
+ if (state.src.slice(pos, pos + 2) !== '$$') return false
111
+
112
+ pos += 2
113
+ firstLine = state.src.slice(pos, max)
114
+
115
+ if (silent) return true
116
+ if (firstLine.trim().slice(-2) === '$$') {
117
+ // Single line expression
118
+ firstLine = firstLine.trim().slice(0, -2)
119
+ found = true
120
+ }
121
+
122
+ for (next = start; !found;) {
123
+ next++
124
+
125
+ if (next >= end) break
126
+
127
+ pos = state.bMarks[next] + state.tShift[next]
128
+ max = state.eMarks[next]
129
+
130
+ if (pos < max && state.tShift[next] < state.blkIndent) {
131
+ // non-empty line with negative indent should stop the list:
132
+ break
133
+ }
134
+
135
+ if (state.src.slice(pos, max).trim().slice(-2) === '$$') {
136
+ lastPos = state.src.slice(0, max).lastIndexOf('$$')
137
+ lastLine = state.src.slice(pos, lastPos)
138
+ found = true
139
+ }
140
+ }
141
+
142
+ state.line = next + 1
143
+
144
+ const token = state.push('math_block', 'math', 0)
145
+ token.block = true
146
+ token.content = (firstLine && firstLine.trim() ? `${firstLine}\n` : '')
147
+ + state.getLines(start + 1, next, state.tShift[start], true)
148
+ + (lastLine && lastLine.trim() ? lastLine : '')
149
+ token.map = [start, state.line]
150
+ token.markup = '$$'
151
+ return true
152
+ }
153
+
154
+ export default function math_plugin(md: any, options: KatexOptions) {
155
+ // Default options
156
+
157
+ options = options || {}
158
+
159
+ // set KaTeX as the renderer for markdown-it-simplemath
160
+ const katexInline = function(latex: string) {
161
+ options.displayMode = false
162
+ try {
163
+ return katex.renderToString(latex, options)
164
+ }
165
+ catch (error) {
166
+ if (options.throwOnError)
167
+ // eslint-disable-next-line no-console
168
+ console.warn(error)
169
+ return latex
170
+ }
171
+ }
172
+
173
+ const inlineRenderer = function(tokens: any, idx: number) {
174
+ return katexInline(tokens[idx].content)
175
+ }
176
+
177
+ const katexBlock = function(latex: string) {
178
+ options.displayMode = true
179
+ try {
180
+ return `<p>${katex.renderToString(latex, options)}</p>`
181
+ }
182
+ catch (error) {
183
+ if (options.throwOnError)
184
+ // eslint-disable-next-line no-console
185
+ console.warn(error)
186
+ return latex
187
+ }
188
+ }
189
+
190
+ const blockRenderer = function(tokens: any, idx: number) {
191
+ return `${katexBlock(tokens[idx].content)}\n`
192
+ }
193
+
194
+ md.inline.ruler.after('escape', 'math_inline', math_inline)
195
+ md.block.ruler.after('blockquote', 'math_block', math_block, {
196
+ alt: ['paragraph', 'reference', 'blockquote', 'list'],
197
+ })
198
+ md.renderer.rules.math_inline = inlineRenderer
199
+ md.renderer.rules.math_block = blockRenderer
200
+ }
@@ -0,0 +1,70 @@
1
+ // ref vitepress
2
+
3
+ // Since VuePress needs to extract the header from the markdown source
4
+ // file and display it in the sidebar or title (#238), this file simply
5
+ // removes some unnecessary elements to make header displays well at
6
+ // sidebar or title.
7
+ //
8
+ // But header's parsing in the markdown content is done by the markdown
9
+ // loader based on markdown-it. markdown-it parser will will always keep
10
+ // HTML in headers, so in VuePress, after being parsed by the markdown
11
+ // loader, the raw HTML in headers will finally be parsed by Vue-loader.
12
+ // so that we can write HTML/Vue in the header. One exception is the HTML
13
+ // wrapped by <code>(markdown token: '`') tag.
14
+ import emojiData from 'markdown-it-emoji/lib/data/full.json'
15
+
16
+ const parseEmojis = (str: string) => {
17
+ return str.replace(
18
+ /:(.+?):/g,
19
+ (placeholder, key) => (emojiData as any)[key] || placeholder,
20
+ )
21
+ }
22
+
23
+ const unescapeHtml = (html: string) =>
24
+ html
25
+ .replace(/&quot;/g, '"')
26
+ .replace(/&#39;/g, '\'')
27
+ .replace(/&#x3A;/g, ':')
28
+ .replace(/&lt;/g, '<')
29
+ .replace(/&gt;/g, '>')
30
+
31
+ const removeMarkdownTokens = (str: string) =>
32
+ str
33
+ .replace(/(\[(.[^\]]+)\]\((.[^)]+)\))/g, '$2') // []()
34
+ .replace(/(`|\*{1,3}|_)(.*?[^\\])\1/g, '$2') // `{t}` | *{t}* | **{t}** | ***{t}*** | _{t}_
35
+ .replace(/(\\)(\*|_|`|\!|<|\$)/g, '$2') // remove escape char '\'
36
+
37
+ const remvoeCustomAnchor = (str: string) =>
38
+ str.replace(/\{#([a-z0-9\-_]+?)\}\s*$/, '') // {#custom-header}
39
+
40
+ const trim = (str: string) => str.trim()
41
+
42
+ // This method remove the raw HTML but reserve the HTML wrapped by `<code>`.
43
+ // e.g.
44
+ // Input: "<a> b", Output: "b"
45
+ // Input: "`<a>` b", Output: "`<a>` b"
46
+ export const removeNonCodeWrappedHTML = (str: string) => {
47
+ return String(str).replace(/(^|[^><`\\])<.*>([^><`]|$)/g, '$1$2')
48
+ }
49
+
50
+ const compose = (...processors: ((str: string) => string)[]) => {
51
+ if (processors.length === 0) return (input: string) => input
52
+ if (processors.length === 1) return processors[0]
53
+ return processors.reduce((prev, next) => {
54
+ return str => next(prev(str))
55
+ })
56
+ }
57
+
58
+ // Unescape html, parse emojis and remove some md tokens.
59
+ export const parseHeader = compose(
60
+ unescapeHtml,
61
+ parseEmojis,
62
+ remvoeCustomAnchor,
63
+ removeMarkdownTokens,
64
+ trim,
65
+ )
66
+
67
+ // Also clean the html that isn't wrapped by code.
68
+ // Because we want to support using VUE components in headers.
69
+ // e.g. https://vuepress.vuejs.org/guide/using-vue.html#badge
70
+ export const deeplyParseHeader = compose(removeNonCodeWrappedHTML, parseHeader)
@@ -0,0 +1,24 @@
1
+ // ref vitepress
2
+ import { remove as removeDiacritics } from 'diacritics'
3
+ // eslint-disable-next-line no-control-regex
4
+ const rControl = /[\u0000-\u001F]/g
5
+ // add '…'
6
+ const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'<>,.…?/]+/g
7
+
8
+ export const slugify = (str: string): string => {
9
+ return (
10
+ removeDiacritics(str)
11
+ // Remove control characters
12
+ .replace(rControl, '')
13
+ // Replace special characters
14
+ .replace(rSpecial, '-')
15
+ // Remove continuous separators
16
+ .replace(/\-{2,}/g, '-')
17
+ // Remove prefixing and trailing separators
18
+ .replace(/^\-+|\-+$/g, '')
19
+ // ensure it doesn't start with a number (#121)
20
+ .replace(/^(\d)/, '_$1')
21
+ // lowercase
22
+ .toLowerCase()
23
+ )
24
+ }
@@ -0,0 +1,90 @@
1
+ import { dirname, resolve } from 'path'
2
+ import _debug from 'debug'
3
+ import type { ValaxyConfig } from '../types'
4
+ import { resolveConfig } from './config'
5
+ import { resolveImportPath } from './utils'
6
+
7
+ const debug = _debug('valaxy:options')
8
+
9
+ // for cli entry
10
+ export interface ValaxyEntryOptions {
11
+ /**
12
+ * theme name
13
+ */
14
+ theme?: string
15
+ userRoot?: string
16
+ }
17
+
18
+ export interface ResolvedValaxyOptions {
19
+ /**
20
+ * Client root path
21
+ * @default 'valaxy/src/client'
22
+ */
23
+ clientRoot: string
24
+ /**
25
+ * User root path
26
+ * @default process.cwd()
27
+ */
28
+ userRoot: string
29
+ /**
30
+ * Theme root path
31
+ */
32
+ themeRoot: string
33
+ /**
34
+ * Theme name
35
+ */
36
+ theme: string
37
+ /**
38
+ * Valaxy Config
39
+ */
40
+ config: ValaxyConfig
41
+ /**
42
+ * config file path
43
+ */
44
+ configFile: string
45
+ }
46
+
47
+ export interface ValaxyServerOptions {
48
+ onConfigReload?: (newConfig: ValaxyConfig, config: ValaxyConfig) => void
49
+ }
50
+
51
+ export function isPath(name: string) {
52
+ return name.startsWith('/') || /^\.\.?[\/\\]/.test(name)
53
+ }
54
+
55
+ /**
56
+ * get theme roots
57
+ * @param name
58
+ * @param entry
59
+ * @returns
60
+ */
61
+ export function getThemeRoot(name: string, entry: string) {
62
+ if (!name)
63
+ return ''
64
+
65
+ if (isPath(name))
66
+ return resolve(dirname(entry), name)
67
+ else
68
+ return resolveImportPath(`valaxy-theme-${name}/package.json`)
69
+ }
70
+
71
+ // for cli options
72
+ export async function resolveOptions(options: ValaxyEntryOptions) {
73
+ const clientRoot = resolve(resolveImportPath('valaxy/package.json'), 'src/client')
74
+ const userRoot = resolve(options.userRoot || process.cwd())
75
+
76
+ const { config: valaxyConfig, configFile, theme } = await resolveConfig(options)
77
+ const themeRoot = getThemeRoot(theme, userRoot)
78
+
79
+ const valaxyOptions: ResolvedValaxyOptions = {
80
+ clientRoot,
81
+ userRoot,
82
+ themeRoot,
83
+ theme,
84
+ config: valaxyConfig,
85
+ configFile: configFile || '',
86
+ }
87
+ debug(valaxyOptions)
88
+
89
+ return valaxyOptions
90
+ }
@@ -0,0 +1,28 @@
1
+ import { resolve } from 'path'
2
+ import type { InlineConfig, Plugin } from 'vite'
3
+ import { mergeConfig } from 'vite'
4
+ import type { ResolvedValaxyOptions } from '../options'
5
+ import { toAtFS } from '../utils'
6
+
7
+ export function createConfigPlugin(options: ResolvedValaxyOptions): Plugin {
8
+ return {
9
+ name: 'valaxy:config',
10
+ config(config) {
11
+ const injection: InlineConfig = {
12
+ resolve: {
13
+ alias: {
14
+ '@/': `${toAtFS(options.userRoot)}/`,
15
+ '~/': `${toAtFS(options.clientRoot)}/`,
16
+ '@valaxyjs/client': `${toAtFS(options.clientRoot)}/`,
17
+ '@valaxyjs/config': '/@valaxyjs/config',
18
+ 'valaxy/package.json': toAtFS(resolve(options.clientRoot, '../../package.json')),
19
+ 'valaxy': toAtFS(resolve(options.clientRoot, '..')),
20
+ '@valaxyjs/core': toAtFS(resolve(options.clientRoot, '../core')),
21
+ [`valaxy-theme-${options.theme}`]: `${toAtFS(resolve(options.themeRoot))}/`,
22
+ },
23
+ },
24
+ }
25
+ return mergeConfig(config, injection)
26
+ },
27
+ }
28
+ }
@@ -0,0 +1,91 @@
1
+ import fs from 'fs'
2
+
3
+ import { join } from 'path'
4
+ import type { Plugin } from 'vite'
5
+ // import consola from 'consola'
6
+ import { resolveConfig } from '../config'
7
+ import type { ResolvedValaxyOptions, ValaxyServerOptions } from '../options'
8
+ import { toAtFS } from '../utils'
9
+ import { VALAXY_CONFIG_ID } from './valaxy'
10
+
11
+ export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions: ValaxyServerOptions = {}): Plugin {
12
+ const valaxyPrefix = '/@valaxy'
13
+
14
+ let valaxyConfig = options.config
15
+
16
+ const roots = [options.userRoot, options.themeRoot]
17
+
18
+ function generateUserStyles() {
19
+ const imports: string[] = []
20
+
21
+ for (const root of roots) {
22
+ const styles = [
23
+ join(root, 'styles', 'vars.scss'),
24
+ join(root, 'styles', 'index.css'),
25
+ join(root, 'styles', 'index.scss'),
26
+ ]
27
+
28
+ for (const style of styles) {
29
+ if (fs.existsSync(style)) {
30
+ imports.push(`import "${toAtFS(style)}"`)
31
+ continue
32
+ }
33
+ }
34
+ }
35
+
36
+ return imports.join('\n')
37
+ }
38
+
39
+ return {
40
+ name: 'Valaxy',
41
+
42
+ configureServer(server) {
43
+ server.watcher.add([
44
+ options.configFile,
45
+ options.userRoot,
46
+ options.themeRoot,
47
+ ])
48
+ },
49
+
50
+ resolveId(id) {
51
+ if (id.startsWith(valaxyPrefix))
52
+ return id
53
+ return null
54
+ },
55
+
56
+ load(id) {
57
+ if (id === `/${VALAXY_CONFIG_ID}`)
58
+ // stringify twice for \"
59
+ return `export default ${JSON.stringify(JSON.stringify(valaxyConfig))}`
60
+
61
+ // generate styles
62
+ if (id === '/@valaxyjs/styles')
63
+ return generateUserStyles()
64
+
65
+ if (id.startsWith(valaxyPrefix))
66
+ return ''
67
+ },
68
+
69
+ async handleHotUpdate(ctx) {
70
+ // handle valaxy.config.ts hmr
71
+ const { file, server } = ctx
72
+ if (file !== options.configFile) return
73
+
74
+ const { config } = await resolveConfig()
75
+
76
+ serverOptions.onConfigReload?.(config, options.config)
77
+ Object.assign(options.config, config)
78
+
79
+ // if (config.base !== options.config.base)
80
+ // consola.warn('[valaxy]: config.base has changed. Please restart the dev server.')
81
+ valaxyConfig = config
82
+
83
+ const moduleIds = [`/${VALAXY_CONFIG_ID}`]
84
+ const moduleEntries = [
85
+ ...Array.from(moduleIds).map(id => server.moduleGraph.getModuleById(id)),
86
+ ].filter(<T>(item: T): item is NonNullable<T> => !!item)
87
+
88
+ return moduleEntries
89
+ },
90
+ }
91
+ }
@@ -0,0 +1,62 @@
1
+ import path from 'path'
2
+ import Markdown from 'vite-plugin-md'
3
+
4
+ import type { Plugin } from 'vite'
5
+ import type { ResolvedValaxyOptions } from '../options'
6
+
7
+ import type { MarkdownRenderer } from '../markdown'
8
+ import { setupMarkdownPlugins } from '../markdown'
9
+ import { slash } from '../utils'
10
+ // import { useRoute } from 'vue-router'
11
+
12
+ export type ViteMdOptions = Parameters<typeof Markdown>[0]
13
+
14
+ export const excerpt_separator = '<!-- more -->'
15
+
16
+ // https://github.com/antfu/vite-plugin-md
17
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
18
+ export function createMarkdownPlugin(options: ResolvedValaxyOptions): Plugin[] {
19
+ let _md: MarkdownRenderer
20
+
21
+ const mdOptions = options.config.markdownIt
22
+
23
+ const defaultOptions: ViteMdOptions = {
24
+ wrapperComponent: 'ValaxyMd',
25
+
26
+ headEnabled: true,
27
+ frontmatter: true,
28
+
29
+ excerpt: excerpt_separator,
30
+
31
+ builders: [
32
+ // avoid conflict with markdown-it-anchor link
33
+ // link(),
34
+ // seems bug, override frontmatter
35
+ // meta(),
36
+ ],
37
+
38
+ markdownItSetup(md) {
39
+ if (mdOptions.config)
40
+ mdOptions.config(md)
41
+
42
+ _md = setupMarkdownPlugins(md, mdOptions)
43
+ },
44
+ }
45
+ return [Markdown(Object.assign(defaultOptions, options.config.markdown)), {
46
+ name: 'valaxy:md',
47
+ handleHotUpdate(ctx) {
48
+ const { file, server } = ctx
49
+ // send headers
50
+ if (file.endsWith('.md')) {
51
+ server.ws.send({
52
+ type: 'custom',
53
+ event: 'valaxy:pageHeaders',
54
+ data: {
55
+ path: `/${slash(path.relative(`${options.userRoot}/pages`, file))}`,
56
+ pageHeaders: _md.__data.headers,
57
+ },
58
+ })
59
+ }
60
+ },
61
+ }]
62
+ }