chore: migrate from Vuex to Pinia (#236)

This commit is contained in:
YangQi 2023-07-29 19:59:34 +08:00 committed by GitHub
parent ae9f654d81
commit 8e2669788b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 284 additions and 233 deletions

69
package-lock.json generated
View File

@ -21,17 +21,15 @@
"marked": "^4.0.18",
"minio": "7.0.33",
"node-fetch": "^3.2.10",
"pinia": "^2.1.6",
"prettify": "^0.1.7",
"qiniu-js": "^3.4.1",
"uuid": "^8.3.2",
"vue": "^2.7.14",
"vuex": "^3.6.2"
"vue": "^2.7.14"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.19",
"@vue/cli-plugin-eslint": "^4.5.19",
"@vue/cli-plugin-router": "^4.5.19",
"@vue/cli-plugin-vuex": "^4.5.12",
"@vue/cli-service": "^4.5.15",
"@vue/eslint-config-prettier": "^6.0.0",
"async-validator": "^4.0.7",
@ -3881,6 +3879,11 @@
"integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
"dev": true
},
"node_modules/@vue/devtools-api": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz",
"integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q=="
},
"node_modules/@vue/eslint-config-prettier": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-6.0.0.tgz",
@ -21901,6 +21904,56 @@
"node": ">=6"
}
},
"node_modules/pinia": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.6.tgz",
"integrity": "sha512-bIU6QuE5qZviMmct5XwCesXelb5VavdOWKWaB17ggk++NUwQWWbP5YnsONTk3b752QkW9sACiR81rorpeOMSvQ==",
"dependencies": {
"@vue/devtools-api": "^6.5.0",
"vue-demi": ">=0.14.5"
},
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"@vue/composition-api": "^1.4.0",
"typescript": ">=4.4.4",
"vue": "^2.6.14 || ^3.3.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
},
"typescript": {
"optional": true
}
}
},
"node_modules/pinia/node_modules/vue-demi": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz",
"integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==",
"hasInstallScript": true,
"bin": {
"vue-demi-fix": "bin/vue-demi-fix.js",
"vue-demi-switch": "bin/vue-demi-switch.js"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@vue/composition-api": "^1.0.0-rc.1",
"vue": "^3.0.0-0 || ^2.6.0"
},
"peerDependenciesMeta": {
"@vue/composition-api": {
"optional": true
}
}
},
"node_modules/pinkie": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
@ -27019,14 +27072,6 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/vuex": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
"integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==",
"peerDependencies": {
"vue": "^2.0.0"
}
},
"node_modules/watchpack": {
"version": "1.7.5",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",

View File

@ -26,17 +26,15 @@
"marked": "^4.0.18",
"minio": "7.0.33",
"node-fetch": "^3.2.10",
"pinia": "^2.1.6",
"prettify": "^0.1.7",
"qiniu-js": "^3.4.1",
"uuid": "^8.3.2",
"vue": "^2.7.14",
"vuex": "^3.6.2"
"vue": "^2.7.14"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.5.19",
"@vue/cli-plugin-eslint": "^4.5.19",
"@vue/cli-plugin-router": "^4.5.19",
"@vue/cli-plugin-vuex": "^4.5.12",
"@vue/cli-service": "^4.5.15",
"@vue/eslint-config-prettier": "^6.0.0",
"async-validator": "^4.0.7",

View File

@ -19,7 +19,8 @@
</template>
<script>
import { mapState } from 'vuex'
import { mapState } from 'pinia'
import { useStore } from '@/stores'
export default {
props: {
@ -32,7 +33,7 @@ export default {
btnType() {
return this.nightMode ? `default` : `primary`
},
...mapState({
...mapState(useStore, {
nightMode: (state) => state.nightMode,
}),
},

View File

@ -170,6 +170,9 @@
</template>
<script>
import { mapState, mapActions } from 'pinia'
import { useStore } from '@/stores'
import { setFontSize, setColorWithCustomTemplate } from '@/assets/scripts/util'
import { solveWeChatImage, mergeCss } from '@/assets/scripts/converter'
import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt'
@ -177,7 +180,6 @@ import config from '@/assets/scripts/config'
import ResetDialog from './ResetDialog'
import StyleOptionMenu from './StyleOptionMenu'
import PostInfoDialog from './PostInfoDialog'
import { mapState, mapMutations } from 'vuex'
export default {
name: `editor-header`,
@ -236,7 +238,7 @@ export default {
btnType() {
return this.nightMode ? `default` : `primary`
},
...mapState({
...mapState(useStore, {
output: (state) => state.output,
editor: (state) => state.editor,
cssEditor: (state) => state.cssEditor,
@ -408,7 +410,7 @@ export default {
this.showResetConfirm = false
this.editor.focus()
},
...mapMutations([
...mapActions(useStore, [
`setCurrentColor`,
`setCiteStatus`,
`themeChanged`,

View File

@ -53,9 +53,11 @@
</template>
<script>
import { mapState, mapActions } from 'pinia'
import { useStore } from '@/stores'
import config from '@/assets/scripts/config'
import { createTable } from '@/assets/scripts/util'
import { mapState, mapMutations } from 'vuex'
export default {
props: {
@ -76,7 +78,7 @@ export default {
btnType() {
return this.nightMode ? `default` : `primary`
},
...mapState({
...mapState(useStore, {
nightMode: (state) => state.nightMode,
editor: (state) => state.editor,
}),
@ -98,7 +100,7 @@ export default {
this.$emit(`close`)
this.editorRefresh()
},
...mapMutations([`editorRefresh`]),
...mapActions(useStore, [`editorRefresh`]),
},
}
</script>

View File

@ -12,7 +12,8 @@
</template>
<script>
import { mapState } from 'vuex'
import { mapState } from 'pinia'
import { useStore } from '@/stores'
export default {
name: `RunLoading`,
@ -27,7 +28,7 @@ export default {
}, 100)
},
computed: {
...mapState({
...mapState(useStore, {
nightMode: ({ nightMode }) => nightMode,
}),
},

View File

@ -1,27 +1,30 @@
import Vue from 'vue'
import App from './App'
import store from './store'
import ElementUI from 'element-ui'
import { createPinia, PiniaVuePlugin } from 'pinia'
import 'element-ui/lib/theme-chalk/index.css'
import './plugins/element'
import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/xq-light.css'
import 'codemirror/mode/css/css'
import 'codemirror/mode/markdown/markdown'
import 'codemirror/addon/edit/closebrackets'
import 'codemirror/addon/edit/matchbrackets'
import 'codemirror/addon/selection/active-line'
import 'codemirror/addon/hint/show-hint.js'
import 'codemirror/addon/hint/css-hint.js'
import 'codemirror/addon/hint/show-hint'
import 'codemirror/addon/hint/css-hint'
Vue.use(ElementUI)
import './plugins/element'
import App from './App'
Vue.use(ElementUI).use(PiniaVuePlugin)
Vue.config.productionTip = false
App.mpType = `app`
const app = new Vue({
store,
new Vue({
...App,
})
app.$mount(`#app`)
pinia: createPinia(),
}).$mount(`#app`)

View File

@ -1,194 +0,0 @@
import Vue from 'vue'
import Vuex from 'vuex'
import config from '../assets/scripts/config'
import WxRenderer from '../assets/scripts/renderers/wx-renderer'
import { marked } from 'marked'
import CodeMirror from 'codemirror/lib/codemirror'
import DEFAULT_CONTENT from '@/assets/example/markdown.md'
import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt'
import { setColor, formatDoc, formatCss } from '@/assets/scripts/util'
Vue.use(Vuex)
const state = {
wxRenderer: null,
output: ``,
html: ``,
editor: null,
cssEditor: null,
currentFont: ``,
currentSize: ``,
currentColor: ``,
citeStatus: false,
nightMode: false,
codeTheme: config.codeThemeOption[2].value,
isMacCodeBlock: true,
}
const mutations = {
setEditorValue(state, data) {
state.editor.setValue(data)
},
setCssEditorValue(state, data) {
state.cssEditor.setValue(data)
},
setWxRendererOptions(state, data) {
state.wxRenderer.setOptions(data)
},
setCiteStatus(state, data) {
state.citeStatus = data
localStorage.setItem(`citeStatus`, data)
},
setCurrentFont(state, data) {
state.currentFont = data
localStorage.setItem(`fonts`, data)
},
setCurrentSize(state, data) {
state.currentSize = data
localStorage.setItem(`size`, data)
},
setCurrentColor(state, data) {
state.currentColor = data
localStorage.setItem(`color`, data)
},
setCurrentCodeTheme(state, data) {
state.codeTheme = data
localStorage.setItem(`codeTheme`, data)
},
setIsMacCodeBlock(state, data) {
state.isMacCodeBlock = data
localStorage.setItem(`isMacCodeBlock`, data)
},
themeChanged(state) {
state.nightMode = !state.nightMode
localStorage.setItem(`nightMode`, state.nightMode)
},
initEditorState(state) {
state.currentFont =
localStorage.getItem(`fonts`) || config.builtinFonts[0].value
state.currentColor =
localStorage.getItem(`color`) || config.colorOption[0].value
state.currentSize =
localStorage.getItem(`size`) || config.sizeOption[2].value
state.codeTheme =
localStorage.getItem(`codeTheme`) || config.codeThemeOption[2].value
state.citeStatus = localStorage.getItem(`citeStatus`) === `true`
state.nightMode = localStorage.getItem(`nightMode`) === `true`
state.isMacCodeBlock = !(localStorage.getItem(`isMacCodeBlock`) === `false`)
state.wxRenderer = new WxRenderer({
theme: setColor(state.currentColor),
fonts: state.currentFont,
size: state.currentSize,
})
},
initEditorEntity(state) {
const editorDom = document.getElementById(`editor`)
if (!editorDom.value) {
editorDom.value =
localStorage.getItem(`__editor_content`) || formatDoc(DEFAULT_CONTENT)
}
state.editor = CodeMirror.fromTextArea(editorDom, {
mode: `text/x-markdown`,
theme: `xq-light`,
lineNumbers: false,
lineWrapping: true,
styleActiveLine: true,
autoCloseBrackets: true,
extraKeys: {
'Ctrl-F': function autoFormat(editor) {
const doc = formatDoc(editor.getValue(0))
localStorage.setItem(`__editor_content`, doc)
editor.setValue(doc)
},
'Ctrl-S': function save(editor) {},
'Ctrl-B': function bold(editor) {
const selected = editor.getSelection()
editor.replaceSelection(`**${selected}**`)
},
'Ctrl-D': function del(editor) {
const selected = editor.getSelection()
editor.replaceSelection(`~~${selected}~~`)
},
'Ctrl-I': function italic(editor) {
const selected = editor.getSelection()
editor.replaceSelection(`*${selected}*`)
},
},
})
},
initCssEditorEntity(state) {
const cssEditorDom = document.getElementById(`cssEditor`)
if (!cssEditorDom.value) {
cssEditorDom.value =
localStorage.getItem(`__css_content`) || DEFAULT_CSS_CONTENT
}
state.cssEditor = CodeMirror.fromTextArea(cssEditorDom, {
mode: `css`,
theme: `style-mirror`,
lineNumbers: false,
lineWrapping: true,
matchBrackets: true,
autofocus: true,
extraKeys: {
'Ctrl-F': function autoFormat(editor) {
const doc = formatCss(editor.getValue(0))
localStorage.setItem(`__css_content`, doc)
editor.setValue(doc)
},
'Ctrl-S': function save(editor) {},
},
})
},
editorRefresh(state) {
const renderer = state.wxRenderer.getRenderer(state.citeStatus)
marked.setOptions({ renderer })
let output = marked.parse(state.editor.getValue(0))
// 去除第一行的 margin-top
output = output.replace(/(style=".*?)"/, `$1;margin-top: 0"`)
if (state.citeStatus) {
// 引用脚注
output += state.wxRenderer.buildFootnotes()
// 附加的一些 style
output += state.wxRenderer.buildAddition()
}
if (state.isMacCodeBlock) {
output += `
<style>
.hljs.code__pre::before {
position: initial;
padding: initial;
content: '';
display: block;
height: 25px;
background-color: transparent;
background-image: url("https://doocs.oss-cn-shenzhen.aliyuncs.com/img/123.svg");
background-position: 14px 10px;
background-repeat: no-repeat;
background-size: 40px;
}
.hljs.code__pre {
padding: 0!important;
}
.hljs.code__pre code {
display: -webkit-box;
padding: 0.5em 1em 1em;
overflow-x: auto;
text-indent: 0;
}
</style>
`
}
state.output = output
},
}
export default new Vuex.Store({
state,
mutations,
actions: {},
})

190
src/stores/index.js Normal file
View File

@ -0,0 +1,190 @@
import { defineStore } from 'pinia'
import { marked } from 'marked'
import CodeMirror from 'codemirror/lib/codemirror'
import config from '../assets/scripts/config'
import WxRenderer from '../assets/scripts/renderers/wx-renderer'
import DEFAULT_CONTENT from '@/assets/example/markdown.md'
import DEFAULT_CSS_CONTENT from '@/assets/example/theme-css.txt'
import { setColor, formatDoc, formatCss } from '@/assets/scripts/util'
export const useStore = defineStore(`store`, {
state: () => ({
wxRenderer: null,
output: ``,
html: ``,
editor: null,
cssEditor: null,
currentFont: ``,
currentSize: ``,
currentColor: ``,
citeStatus: false,
nightMode: false,
codeTheme: config.codeThemeOption[2].value,
isMacCodeBlock: true,
}),
actions: {
setEditorValue(data) {
this.editor.setValue(data)
},
setCssEditorValue(data) {
this.cssEditor.setValue(data)
},
setWxRendererOptions(data) {
this.wxRenderer.setOptions(data)
},
setCiteStatus(data) {
this.citeStatus = data
localStorage.setItem(`citeStatus`, data)
},
setCurrentFont(data) {
this.currentFont = data
localStorage.setItem(`fonts`, data)
},
setCurrentSize(data) {
this.currentSize = data
localStorage.setItem(`size`, data)
},
setCurrentColor(data) {
this.currentColor = data
localStorage.setItem(`color`, data)
},
setCurrentCodeTheme(data) {
this.codeTheme = data
localStorage.setItem(`codeTheme`, data)
},
setIsMacCodeBlock(data) {
this.isMacCodeBlock = data
localStorage.setItem(`isMacCodeBlock`, data)
},
themeChanged() {
this.nightMode = !this.nightMode
localStorage.setItem(`nightMode`, this.nightMode)
},
initEditorState() {
this.currentFont =
localStorage.getItem(`fonts`) || config.builtinFonts[0].value
this.currentColor =
localStorage.getItem(`color`) || config.colorOption[0].value
this.currentSize =
localStorage.getItem(`size`) || config.sizeOption[2].value
this.codeTheme =
localStorage.getItem(`codeTheme`) || config.codeThemeOption[2].value
this.citeStatus = localStorage.getItem(`citeStatus`) === `true`
this.nightMode = localStorage.getItem(`nightMode`) === `true`
this.isMacCodeBlock = !(
localStorage.getItem(`isMacCodeBlock`) === `false`
)
this.wxRenderer = new WxRenderer({
theme: setColor(this.currentColor),
fonts: this.currentFont,
size: this.currentSize,
})
},
initEditorEntity() {
const editorDom = document.getElementById(`editor`)
if (!editorDom.value) {
editorDom.value =
localStorage.getItem(`__editor_content`) || formatDoc(DEFAULT_CONTENT)
}
this.editor = CodeMirror.fromTextArea(editorDom, {
mode: `text/x-markdown`,
theme: `xq-light`,
lineNumbers: false,
lineWrapping: true,
styleActiveLine: true,
autoCloseBrackets: true,
extraKeys: {
'Ctrl-F': function autoFormat(editor) {
const doc = formatDoc(editor.getValue(0))
localStorage.setItem(`__editor_content`, doc)
editor.setValue(doc)
},
'Ctrl-S': function save(editor) {},
'Ctrl-B': function bold(editor) {
const selected = editor.getSelection()
editor.replaceSelection(`**${selected}**`)
},
'Ctrl-D': function del(editor) {
const selected = editor.getSelection()
editor.replaceSelection(`~~${selected}~~`)
},
'Ctrl-I': function italic(editor) {
const selected = editor.getSelection()
editor.replaceSelection(`*${selected}*`)
},
},
})
},
initCssEditorEntity() {
const cssEditorDom = document.getElementById(`cssEditor`)
if (!cssEditorDom.value) {
cssEditorDom.value =
localStorage.getItem(`__css_content`) || DEFAULT_CSS_CONTENT
}
this.cssEditor = CodeMirror.fromTextArea(cssEditorDom, {
mode: `css`,
theme: `style-mirror`,
lineNumbers: false,
lineWrapping: true,
matchBrackets: true,
autofocus: true,
extraKeys: {
'Ctrl-F': function autoFormat(editor) {
const doc = formatCss(editor.getValue(0))
localStorage.setItem(`__css_content`, doc)
editor.setValue(doc)
},
'Ctrl-S': function save(editor) {},
},
})
},
editorRefresh() {
const renderer = this.wxRenderer.getRenderer(this.citeStatus)
marked.setOptions({ renderer })
let output = marked.parse(this.editor.getValue(0))
// 去除第一行的 margin-top
output = output.replace(/(style=".*?)"/, `$1;margin-top: 0"`)
if (this.citeStatus) {
// 引用脚注
output += this.wxRenderer.buildFootnotes()
// 附加的一些 style
output += this.wxRenderer.buildAddition()
}
if (this.isMacCodeBlock) {
output += `
<style>
.hljs.code__pre::before {
position: initial;
padding: initial;
content: '';
display: block;
height: 25px;
background-color: transparent;
background-image: url("https://doocs.oss-cn-shenzhen.aliyuncs.com/img/123.svg");
background-position: 14px 10px;
background-repeat: no-repeat;
background-size: 40px;
}
.hljs.code__pre {
padding: 0!important;
}
.hljs.code__pre code {
display: -webkit-box;
padding: 0.5em 1em 1em;
overflow-x: auto;
text-indent: 0;
}
</style>
`
}
this.output = output
},
},
})

View File

@ -94,7 +94,11 @@
<run-loading></run-loading>
</div>
</template>
<script>
import { mapState, mapActions } from 'pinia'
import { useStore } from '@/stores'
import EditorHeader from '@/components/CodemirrorEditor/EditorHeader/index'
import AboutDialog from '@/components/CodemirrorEditor/AboutDialog'
import InsertFormDialog from '@/components/CodemirrorEditor/InsertFormDialog'
@ -115,7 +119,6 @@ import {
toBase64,
} from '@/assets/scripts/util'
import fileApi from '../api/file'
import { mapState, mapMutations } from 'vuex'
require(`codemirror/mode/javascript/javascript`)
@ -147,7 +150,7 @@ export default {
UploadImgDialog,
},
computed: {
...mapState({
...mapState(useStore, {
wxRenderer: (state) => state.wxRenderer,
output: (state) => state.output,
editor: (state) => state.editor,
@ -598,7 +601,7 @@ export default {
break
}
},
...mapMutations([
...mapActions(useStore, [
`initEditorState`,
`initEditorEntity`,
`setWxRendererOptions`,