diff --git a/examples/naivebayes/index.vue b/examples/naivebayes/index.vue
index 80e9908..1954d1d 100644
--- a/examples/naivebayes/index.vue
+++ b/examples/naivebayes/index.vue
@@ -26,12 +26,7 @@
-
+
{
editor.value = payload.view
}
+
const editorExtensions = computed(() => {
- return [javascript(), useTheme().theme.value === Theme.Dark ? oneDark : []]
+ return [javascript(), useTheme().currentTheme.value === Theme.Dark ? oneDark : []]
})
const loading = ref(false)
diff --git a/examples/vue-codemirror/index.vue b/examples/vue-codemirror/index.vue
index b9fa6b0..c73d629 100644
--- a/examples/vue-codemirror/index.vue
+++ b/examples/vue-codemirror/index.vue
@@ -26,7 +26,7 @@
import { Theme, useTheme } from '@/composables/theme'
import Loading from '@/components/common/loading.vue'
import languages from './languages'
- import themes from './themes'
+ import * as themes from './themes'
import Toolbar from './toolbar.vue'
import Editor from './editor.vue'
@@ -54,7 +54,7 @@
const langCodeMap = reactive(new Map any }>())
const currentLangCode = computed(() => langCodeMap.get(config.language)!)
const currentTheme = computed(() => {
- return config.theme !== 'default' ? themes[config.theme] : void 0
+ return config.theme !== 'default' ? (themes as any)[config.theme] : void 0
})
const ensureLanguageCode = async (targetLanguage: string) => {
diff --git a/examples/vue-codemirror/lang-code/vue/index.ts b/examples/vue-codemirror/lang-code/vue/index.ts
new file mode 100644
index 0000000..86acbac
--- /dev/null
+++ b/examples/vue-codemirror/lang-code/vue/index.ts
@@ -0,0 +1,7 @@
+import { vue } from '@codemirror/lang-vue'
+import code from './vue.vue?raw'
+
+export default {
+ language: vue,
+ code
+}
diff --git a/examples/vue-codemirror/lang-code/vue/vue.vue b/examples/vue-codemirror/lang-code/vue/vue.vue
new file mode 100644
index 0000000..2fe8800
--- /dev/null
+++ b/examples/vue-codemirror/lang-code/vue/vue.vue
@@ -0,0 +1,27 @@
+
+
+
{{ greeting }}
+
+
+
+
+
+
+
diff --git a/examples/vue-codemirror/themes.ts b/examples/vue-codemirror/themes.ts
index 188787b..5b2bc8f 100644
--- a/examples/vue-codemirror/themes.ts
+++ b/examples/vue-codemirror/themes.ts
@@ -1,5 +1,21 @@
-import { oneDark } from '@codemirror/theme-one-dark'
-
-export default {
- oneDark
-} as Record
+export { oneDark } from '@codemirror/theme-one-dark'
+export { materialDark } from 'cm6-theme-material-dark'
+export { nord } from 'cm6-theme-nord'
+export {
+ amy,
+ ayuLight,
+ barf,
+ bespin,
+ birdsOfParadise,
+ boysAndGirls,
+ clouds,
+ cobalt,
+ coolGlow,
+ dracula,
+ espresso,
+ noctisLilac,
+ rosePineDawn,
+ smoothy,
+ solarizedLight,
+ tomorrow
+} from 'thememirror'
diff --git a/package.json b/package.json
index 428b0dc..a28a0b9 100644
--- a/package.json
+++ b/package.json
@@ -29,6 +29,7 @@
"@codemirror/lang-python": "^6.x",
"@codemirror/lang-rust": "^6.x",
"@codemirror/lang-sql": "^6.x",
+ "@codemirror/lang-vue": "^0.1.2",
"@codemirror/lang-xml": "^6.x",
"@codemirror/language": "^6.x",
"@codemirror/legacy-modes": "^6.x",
@@ -42,6 +43,8 @@
"@videojs-player/vue": "^1.0.0",
"@videojs/themes": "^1.0.1",
"axios": "^1.5.0",
+ "cm6-theme-material-dark": "^0.2.0",
+ "cm6-theme-nord": "^0.2.0",
"codemirror": "^6.x",
"dedent": "^1.5.1",
"flv.js": "^1.6.2",
@@ -55,6 +58,7 @@
"react-dom": "^18.2.0",
"segmentit": "^2.0.3",
"swiper": "^10.2.0",
+ "thememirror": "^2.0.1",
"video.js": "^8.5.2",
"vue": "^3.3.4",
"vue-codemirror": "^6.1.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 80cef64..3affd1e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -44,6 +44,9 @@ dependencies:
'@codemirror/lang-sql':
specifier: ^6.x
version: 6.3.3(@codemirror/view@6.15.3)(@lezer/common@1.0.2)
+ '@codemirror/lang-vue':
+ specifier: ^0.1.2
+ version: 0.1.2
'@codemirror/lang-xml':
specifier: ^6.x
version: 6.0.1(@codemirror/view@6.15.3)
@@ -83,6 +86,12 @@ dependencies:
axios:
specifier: ^1.5.0
version: 1.5.0
+ cm6-theme-material-dark:
+ specifier: ^0.2.0
+ version: 0.2.0(@codemirror/language@6.3.2)(@codemirror/state@6.1.4)(@codemirror/view@6.15.3)(@lezer/highlight@1.1.3)
+ cm6-theme-nord:
+ specifier: ^0.2.0
+ version: 0.2.0(@codemirror/language@6.3.2)(@codemirror/state@6.1.4)(@codemirror/view@6.15.3)(@lezer/highlight@1.1.3)
codemirror:
specifier: ^6.x
version: 6.0.1(@lezer/common@1.0.2)
@@ -122,6 +131,9 @@ dependencies:
swiper:
specifier: ^10.2.0
version: 10.2.0
+ thememirror:
+ specifier: ^2.0.1
+ version: 2.0.1(@codemirror/language@6.3.2)(@codemirror/state@6.1.4)(@codemirror/view@6.15.3)
video.js:
specifier: ^8.5.2
version: 8.5.2
@@ -598,6 +610,17 @@ packages:
- '@lezer/common'
dev: false
+ /@codemirror/lang-vue@0.1.2:
+ resolution: {integrity: sha512-D4YrefiRBAr+CfEIM4S3yvGSbYW+N69mttIfGMEf7diHpRbmygDxS+R/5xSqjgtkY6VO6qmUrre1GkRcWeZa9A==}
+ dependencies:
+ '@codemirror/lang-html': 6.4.0
+ '@codemirror/lang-javascript': 6.1.2
+ '@codemirror/language': 6.3.2
+ '@lezer/common': 1.0.2
+ '@lezer/highlight': 1.1.3
+ '@lezer/lr': 1.3.10
+ dev: false
+
/@codemirror/lang-xml@6.0.1(@codemirror/view@6.15.3):
resolution: {integrity: sha512-0tvycUTElajCcRKgsszhKjWX+uuOogdu5+enpfqYA+j0gnP8ek7LRxujh2/XMPRdXt/hwOML4slJLE7r2eX3yQ==}
dependencies:
@@ -1036,6 +1059,12 @@ packages:
'@lezer/common': 1.0.2
dev: false
+ /@lezer/lr@1.3.10:
+ resolution: {integrity: sha512-BZfVvf7Re5BIwJHlZXbJn9L8lus5EonxQghyn+ih8Wl36XMFBPTXC0KM0IdUtj9w/diPHsKlXVgL+AlX2jYJ0Q==}
+ dependencies:
+ '@lezer/common': 1.0.2
+ dev: false
+
/@lezer/markdown@1.0.2:
resolution: {integrity: sha512-8CY0OoZ6V5EzPjSPeJ4KLVbtXdLBd8V6sRCooN5kHnO28ytreEGTyrtU/zUwo/XLRzGr/e1g44KlzKi3yWGB5A==}
dependencies:
@@ -1566,6 +1595,34 @@ packages:
fsevents: 2.3.2
dev: true
+ /cm6-theme-material-dark@0.2.0(@codemirror/language@6.3.2)(@codemirror/state@6.1.4)(@codemirror/view@6.15.3)(@lezer/highlight@1.1.3):
+ resolution: {integrity: sha512-H09JZihzg4w0mTtOqo5bQdxItkQWw+ergKlk7BSfwYjaR2nOi+wIN0R+ByAo7bON8GbFODvjTxH3EIqdhovFeA==}
+ peerDependencies:
+ '@codemirror/language': ^6.0.0
+ '@codemirror/state': ^6.0.0
+ '@codemirror/view': ^6.0.0
+ '@lezer/highlight': ^1.0.0
+ dependencies:
+ '@codemirror/language': 6.3.2
+ '@codemirror/state': 6.1.4
+ '@codemirror/view': 6.15.3
+ '@lezer/highlight': 1.1.3
+ dev: false
+
+ /cm6-theme-nord@0.2.0(@codemirror/language@6.3.2)(@codemirror/state@6.1.4)(@codemirror/view@6.15.3)(@lezer/highlight@1.1.3):
+ resolution: {integrity: sha512-jTh+5nvl+N/5CtTK7UVcrxDCj2AOStvbNM8uP6tx6amq4QaaLDlapjMw+MNzEkvxcPnHY+YM91tbklS2KNlR2w==}
+ peerDependencies:
+ '@codemirror/language': ^6.0.0
+ '@codemirror/state': ^6.0.0
+ '@codemirror/view': ^6.0.0
+ '@lezer/highlight': ^1.0.0
+ dependencies:
+ '@codemirror/language': 6.3.2
+ '@codemirror/state': 6.1.4
+ '@codemirror/view': 6.15.3
+ '@lezer/highlight': 1.1.3
+ dev: false
+
/codemirror@6.0.1(@lezer/common@1.0.2):
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
dependencies:
@@ -3088,6 +3145,18 @@ packages:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
dev: true
+ /thememirror@2.0.1(@codemirror/language@6.3.2)(@codemirror/state@6.1.4)(@codemirror/view@6.15.3):
+ resolution: {integrity: sha512-d5i6FVvWWPkwrm4cHLI3t9AT1OrkAt7Ig8dtdYSofgF7C/eiyNuq6zQzSTusWTde3jpW9WLvA9J/fzNKMUsd0w==}
+ peerDependencies:
+ '@codemirror/language': ^6.0.0
+ '@codemirror/state': ^6.0.0
+ '@codemirror/view': ^6.0.0
+ dependencies:
+ '@codemirror/language': 6.3.2
+ '@codemirror/state': 6.1.4
+ '@codemirror/view': 6.15.3
+ dev: false
+
/titleize@3.0.0:
resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==}
engines: {node: '>=12'}
diff --git a/src/components/layout/navbar.vue b/src/components/layout/navbar.vue
index afe19b5..a100aaf 100644
--- a/src/components/layout/navbar.vue
+++ b/src/components/layout/navbar.vue
@@ -18,7 +18,7 @@
const toggleTheme = () => {
const currentIndex = THEMES.indexOf(theme.theme.value)
const newIndex = currentIndex === THEMES.length - 1 ? 0 : currentIndex + 1
- theme.set(THEMES[newIndex])
+ theme.setTheme(THEMES[newIndex])
}
const activatedTheme = computed(() => {
diff --git a/src/composables/theme.ts b/src/composables/theme.ts
index cf195fa..aadf8b6 100644
--- a/src/composables/theme.ts
+++ b/src/composables/theme.ts
@@ -1,4 +1,4 @@
-import { App, inject, ref, readonly } from 'vue'
+import { App, inject, ref, computed, readonly } from 'vue'
import storage from '@/services/storage'
export enum Theme {
@@ -38,9 +38,27 @@ const createThemeStore = (defaultTheme: Theme) => {
}
}
+ const systemTheme = ref(defaultTheme)
+ const initOnClient = () => {
+ systemTheme.value = getSystemTheme() || defaultTheme
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', ({ matches }) => {
+ systemTheme.value = matches ? Theme.Dark : Theme.Light
+ })
+ }
+
+ const currentTheme = computed(() => {
+ if (theme.value === Theme.System) {
+ return systemTheme.value
+ } else {
+ return theme.value
+ }
+ })
+
return {
theme: readonly(theme),
- set: setTheme
+ currentTheme,
+ setTheme,
+ initOnClient
}
}
diff --git a/src/csr.ts b/src/csr.ts
index 133df2c..c5805cb 100644
--- a/src/csr.ts
+++ b/src/csr.ts
@@ -8,7 +8,7 @@ import { createUniversalApp } from './main'
import '@/styles/app.scss'
-const { app, router, visitor } = createUniversalApp({
+const { app, router, visitor, theme } = createUniversalApp({
// MARK: use `createApp`, not `createSSRApp`, to avoid hydrate
appCreator: createApp,
routerHistory: createWebHistory(),
@@ -20,6 +20,7 @@ const { app, router, visitor } = createUniversalApp({
app.use(highlight)
app.use(adsense, { ID: GOOGLE_ADSENSE_CLIENT_ID, enabledAutoAD: false })
visitor.resetStateOnClient()
+theme.initOnClient()
router.isReady().finally(() => {
app.mount('#app', true).$nextTick(() => {