支持编辑区自定义主题/添加编辑区主题

This commit is contained in:
xiaoqi.cxq 2022-10-07 15:17:06 +08:00
parent ee9bd1ab5a
commit 545f8da3cb
10 changed files with 394 additions and 11 deletions

View File

@ -7,11 +7,12 @@ import Prism from 'prismjs';
import cledit from '../services/editor/cledit';
export default {
props: ['value', 'lang', 'disabled'],
props: ['value', 'lang', 'disabled', 'scrollClass'],
mounted() {
const preElt = this.$el;
let scrollElt = preElt;
while (scrollElt && !scrollElt.classList.contains('modal')) {
const scrollCls = this.scrollClass || 'modal';
while (scrollElt && !scrollElt.classList.contains(scrollCls)) {
scrollElt = scrollElt.parentNode;
}
if (scrollElt) {

View File

@ -63,6 +63,15 @@ export default {
}, {
name: '日光白',
value: 'solarized_light',
}, {
name: '咖啡黑',
value: 'espresso_libre',
}, {
name: '薰衣草黑',
value: 'lavender',
}, {
name: '耀斑黑',
value: 'solarflare',
}, {
name: 'Clouds白',
value: 'clouds',
@ -72,11 +81,15 @@ export default {
}, {
name: 'GitHub白',
value: 'github',
}, {
name: '自定义',
value: 'custom',
}],
}),
computed: {
...mapGetters('theme', [
'currEditTheme',
'customEditThemeStyle',
]),
selectedTheme() {
return {
@ -103,7 +116,12 @@ export default {
});
},
async changeTheme(item) {
store.dispatch('theme/setEditTheme', item.value);
await store.dispatch('theme/setEditTheme', item.value);
//
if (item.value === 'custom' && !this.customEditThemeStyle) {
this.toggleSideBar(true);
store.dispatch('data/setSideBarPanel', 'editTheme');
}
},
showHelp() {
this.toggleSideBar(true);

View File

@ -23,6 +23,7 @@
<div v-else-if="panel === 'help'" class="side-bar__panel side-bar__panel--help">
<pre class="markdown-highlighting" v-html="markdownSample"></pre>
</div>
<edit-theme-menu v-else-if="panel === 'editTheme'"></edit-theme-menu>
<div class="side-bar__panel side-bar__panel--toc" :class="{'side-bar__panel--hidden': panel !== 'toc'}">
<toc>
</toc>
@ -41,6 +42,7 @@ import PublishMenu from './menus/PublishMenu';
import HistoryMenu from './menus/HistoryMenu';
import ImportExportMenu from './menus/ImportExportMenu';
import WorkspaceBackupMenu from './menus/WorkspaceBackupMenu';
import EditThemeMenu from './menus/EditThemeMenu';
import markdownSample from '../data/markdownSample.md';
import markdownConversionSvc from '../services/markdownConversionSvc';
import store from '../store';
@ -55,6 +57,7 @@ const panelNames = {
history: '文件历史',
importExport: '导入/导出',
workspaceBackups: '文档空间备份',
editTheme: '编辑区主题',
};
export default {
@ -67,6 +70,7 @@ export default {
HistoryMenu,
ImportExportMenu,
WorkspaceBackupMenu,
EditThemeMenu,
},
data: () => ({
markdownSample: markdownConversionSvc.highlight(markdownSample),

View File

@ -81,6 +81,8 @@
right: 0;
float: left;
min-width: 160px;
max-height: 450px;
overflow-y: scroll;
padding: 5px 0;
margin: 2px 0 0;
list-style: none;
@ -95,6 +97,7 @@
li {
width: 100%;
display: list-item;
margin: 0;
text-align: -webkit-match-parent;
a {

View File

@ -0,0 +1,116 @@
<template>
<div class="edit-theme side-bar__panel side-bar__panel--menu">
<div class="side-bar__info">
<div class="menu-entry menu-entry--info flex flex--row flex--align-center">
<span v-if="currEditTheme==='custom'">
下面的自定义主题样式可编辑可参考其他主题样式填入自己喜欢的编辑样式<br>
主题class为edit-theme-custom
</span>
<span v-else>
下面的主题样式不可编辑
</span>
</div>
</div>
<div class="side-bar__content">
<template v-if="currEditTheme === 'default'">
默认主题无额外样式请选择其他主题
</template>
<template v-else>
<code-editor v-for="(value, index) in styleEles" :key="index"
v-if="value.id === `edit-theme-${currEditTheme}`" lang="css" :value="value.innerHTML"
:disabled="value.id!=='edit-theme-custom'" @changed="changeText" scrollClass="side-bar__inner"></code-editor>
</template>
</div>
<div class="flex flex--row flex--end" v-if="currEditTheme==='custom'">
<button class="edit-theme__button button" @click="saveStyleText">保存</button>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import MenuEntry from './common/MenuEntry';
import CodeEditor from '../CodeEditor';
import store from '../../store';
export default {
components: {
MenuEntry,
CodeEditor,
},
data: () => ({
themeStyleText: '',
styleEles: [],
}),
computed: {
...mapGetters('theme', [
'currEditTheme',
]),
},
methods: {
saveStyleText() {
const typeEle = this.findByTheme(this.currEditTheme);
if (!typeEle || !this.themeStyleText) {
return;
}
typeEle.innerHTML = this.themeStyleText;
store.dispatch('theme/setCustomEditThemeStyle', this.themeStyleText);
store.dispatch('notification/info', '保存自定义主题样式成功!');
},
findByTheme(theme) {
const findEles = this.styleEles.filter(it => it.id === `edit-theme-${theme}`);
return findEles.length ? findEles[0] : null;
},
changeText(text) {
this.themeStyleText = text;
},
close() {
store.dispatch('data/setSideBarPanel', 'menu');
},
initStyle(theme) {
if (theme === 'default') {
return;
}
const value = theme || this.currEditTheme;
if (this.findByTheme(value)) {
return;
}
const styleId = `edit-theme-${value}`;
const styleEle = document.getElementById(styleId);
if (!styleEle) {
setTimeout(() => this.initStyle(value), 1000);
return;
}
this.styleEles.push(styleEle);
},
},
watch: {
currEditTheme: {
immediate: true,
handler(val) {
this.initStyle(val);
},
},
},
created() {
this.initStyle();
},
};
</script>
<style lang="scss">
.side-bar__panel--menu {
.side-bar__content {
.code-editor {
min-height: 400px !important;
max-height: 100%;
}
}
.edit-theme__button {
font-size: 14px;
margin-top: 0.5em;
}
}
</style>

View File

@ -105,6 +105,11 @@
<div><div class="menu-entry__label menu-entry__label--count">{{templateCount}}</div> 模板</div>
<span>为您的导出配置 Handlebars 模板</span>
</menu-entry>
<menu-entry @click.native="setPanel('editTheme')">
<icon-select-theme slot="icon"></icon-select-theme>
编辑区主题
<span>编辑区主题样式(自定义主题可编辑)</span>
</menu-entry>
<menu-entry @click.native="settings">
<icon-settings slot="icon"></icon-settings>
<div>配置</div>

View File

@ -1,35 +1,49 @@
const localKey = 'theme/currEditTheme';
const customEditThemeKey = 'theme/customEditThemeStyle';
export default {
namespaced: true,
state: {
// 当前编辑主题
currEditTheme: null,
initEditTheme: false,
currEditTheme: '',
customEditThemeStyle: null,
},
mutations: {
setEditTheme: (state, value) => {
state.currEditTheme = value;
},
setInitEditTheme: (state, value) => {
state.initEditTheme = value;
setCustomEditThemeStyle: (state, value) => {
state.customEditThemeStyle = value;
},
},
getters: {
currEditTheme: state => state.currEditTheme,
initEditTheme: state => state.initEditTheme,
customEditThemeStyle: state => state.customEditThemeStyle,
},
actions: {
async setEditTheme({ commit }, theme) {
commit('setEditTheme', theme);
commit('setInitEditTheme', true);
localStorage.setItem(localKey, theme);
// 如果不是default 则加载样式
if (!theme || theme === 'default') {
commit('setEditTheme', theme);
localStorage.setItem(localKey, theme);
return;
}
const themeStyle = document.getElementById(`edit-theme-${theme}`);
if (themeStyle) {
commit('setEditTheme', theme);
localStorage.setItem(localKey, theme);
return;
}
// 如果是自定义则直接追加
if (theme === 'custom') {
const styleEle = document.createElement('style');
styleEle.id = `edit-theme-${theme}`;
styleEle.type = 'text/css';
styleEle.innerHTML = localStorage.getItem(customEditThemeKey) || '';
commit('setCustomEditThemeStyle', styleEle.innerHTML);
document.head.appendChild(styleEle);
commit('setEditTheme', theme);
localStorage.setItem(localKey, theme);
return;
}
const script = document.createElement('script');
@ -42,6 +56,8 @@ export default {
try {
document.head.appendChild(script);
timeout = setTimeout(reject, 30);
commit('setEditTheme', theme);
localStorage.setItem(localKey, theme);
} catch (e) {
reject(e);
}
@ -51,5 +67,9 @@ export default {
document.head.removeChild(script);
}
},
setCustomEditThemeStyle({ commit }, value) {
commit('setCustomEditThemeStyle', value);
localStorage.setItem(customEditThemeKey, value);
},
},
};

View File

@ -0,0 +1,72 @@
function init_edit_theme_espresso_libre() {
const style = document.createElement('style');
style.id = 'edit-theme-espresso_libre';
style.type = 'text/css';
style.innerHTML = "/* 默认字体颜色、光标颜色、背景颜色*/\n\
.edit-theme--espresso_libre .editor__inner {\n\
color: #BDAE9D;\n\
caret-color: #BDAE9D;\n\
}\n\
.edit-theme--espresso_libre .editor {\n\
background-color: #2A211C;\n\
}\n\
/* 标题颜色 */\n\
.edit-theme--espresso_libre .editor__inner .cn-head,\n\
.edit-theme--espresso_libre .editor-in-page-buttons .icon {\n\
color: #44AA43;\n\
}\n\
/* 加粗颜色 */\n\
.edit-theme--espresso_libre .editor__inner .cn-strong {\n\
color: #43A8ED;\n\
}\n\
/* 信息块颜色 */\n\
.edit-theme--espresso_libre .editor__inner .blockquote {\n\
color: #52708b;\n\
}\n\
/* 源信息、md标记符号等非关键信息的颜色 */\n\
.edit-theme--espresso_libre .editor__inner .cl,\n\
.edit-theme--espresso_libre .editor__inner .hr,\n\
.edit-theme--espresso_libre .editor__inner .link,\n\
.edit-theme--espresso_libre .editor__inner .linkref, \n\
.edit-theme--espresso_libre .editor__inner .linkdef .url {\n\
color: rgba(139,158,177,0.8);\n\
}\n\
.edit-theme--espresso_libre .editor__inner .cn-toc, \n\
.edit-theme--espresso_libre .editor__inner .code,\n\
.edit-theme--espresso_libre .editor__inner .img,\n\
.edit-theme--espresso_libre .editor__inner .img-wrapper,\n\
.edit-theme--espresso_libre .editor__inner .imgref,\n\
.edit-theme--espresso_libre .editor__inner .cl-toc {\n\
color: rgba(139,158,177,0.8);\n\
background-color: rgba(0,0,0,0.33);\n\
}\n\
/* 代码块颜色 */\n\
.edit-theme--espresso_libre .editor__inner .cn-code {\n\
color: #7290D9;\n\
}\n\
/* 链接颜色 */\n\
.edit-theme--espresso_libre .editor__inner .img .cl-underlined-text,\n\
.edit-theme--espresso_libre .editor__inner .imgref .cl-underlined-text,\n\
.edit-theme--espresso_libre .editor__inner .link .cl-underlined-text,\n\
.edit-theme--espresso_libre .editor__inner .linkref .cl-underlined-text {\n\
color: #049B0A;\n\
}\n\
/* 图片原始链接背景颜色 */\n\
.edit-theme--espresso_libre .editor__inner .img-wrapper .img {\n\
background-color: transparent;\n\
}\n\
.edit-theme--espresso_libre .editor__inner .keyword {\n\
color: #47596b;\n\
}\n\
.edit-theme--espresso_libre .editor__inner .email,\n\
.edit-theme--espresso_libre .editor__inner .cl-title,\n\
.edit-theme--espresso_libre .editor__inner .tag,\n\
.edit-theme--espresso_libre .editor__inner .latex,\n\
.edit-theme--espresso_libre .editor__inner .math,\n\
.edit-theme--espresso_libre .editor__inner .entity,\n\
.edit-theme--espresso_libre .editor__inner .pre [class*='language-'] {\n\
color: #BDAE9D;\n\
}";
document.head.appendChild(style);
}
init_edit_theme_espresso_libre();

View File

@ -0,0 +1,72 @@
function init_edit_theme_lavender() {
const style = document.createElement('style');
style.id = 'edit-theme-lavender';
style.type = 'text/css';
style.innerHTML = "/* 默认字体颜色、光标颜色、背景颜色*/\n\
.edit-theme--lavender .editor__inner {\n\
color: #E0CEED;\n\
caret-color: #E0CEED;\n\
}\n\
.edit-theme--lavender .editor {\n\
background-color: #29222E;\n\
}\n\
/* 标题颜色 */\n\
.edit-theme--lavender .editor__inner .cn-head,\n\
.edit-theme--lavender .editor-in-page-buttons .icon {\n\
color: #F25AE6;\n\
}\n\
/* 加粗颜色 */\n\
.edit-theme--lavender .editor__inner .cn-strong {\n\
color: #8E6DA6;\n\
}\n\
/* 信息块颜色 */\n\
.edit-theme--lavender .editor__inner .blockquote {\n\
color: #B657FF;\n\
}\n\
/* 源信息、md标记符号等非关键信息的颜色 */\n\
.edit-theme--lavender .editor__inner .cl,\n\
.edit-theme--lavender .editor__inner .hr,\n\
.edit-theme--lavender .editor__inner .link,\n\
.edit-theme--lavender .editor__inner .linkref, \n\
.edit-theme--lavender .editor__inner .linkdef .url {\n\
color: rgba(139,158,177,0.8);\n\
}\n\
.edit-theme--lavender .editor__inner .cn-toc, \n\
.edit-theme--lavender .editor__inner .code,\n\
.edit-theme--lavender .editor__inner .img,\n\
.edit-theme--lavender .editor__inner .img-wrapper,\n\
.edit-theme--lavender .editor__inner .imgref,\n\
.edit-theme--lavender .editor__inner .cl-toc {\n\
color: rgba(139,158,177,0.8);\n\
background-color: rgba(0,0,0,0.33);\n\
}\n\
/* 代码块颜色 */\n\
.edit-theme--lavender .editor__inner .cn-code {\n\
color: #8E69C9;\n\
}\n\
/* 链接颜色 */\n\
.edit-theme--lavender .editor__inner .img .cl-underlined-text,\n\
.edit-theme--lavender .editor__inner .imgref .cl-underlined-text,\n\
.edit-theme--lavender .editor__inner .link .cl-underlined-text,\n\
.edit-theme--lavender .editor__inner .linkref .cl-underlined-text {\n\
color: #F5B0EF;\n\
}\n\
/* 图片原始链接背景颜色 */\n\
.edit-theme--lavender .editor__inner .img-wrapper .img {\n\
background-color: transparent;\n\
}\n\
.edit-theme--lavender .editor__inner .keyword {\n\
color: #47596b;\n\
}\n\
.edit-theme--lavender .editor__inner .email,\n\
.edit-theme--lavender .editor__inner .cl-title,\n\
.edit-theme--lavender .editor__inner .tag,\n\
.edit-theme--lavender .editor__inner .latex,\n\
.edit-theme--lavender .editor__inner .math,\n\
.edit-theme--lavender .editor__inner .entity,\n\
.edit-theme--lavender .editor__inner .pre [class*='language-'] {\n\
color: #E0CEED;\n\
}";
document.head.appendChild(style);
}
init_edit_theme_lavender();

View File

@ -0,0 +1,72 @@
function init_edit_theme_solarflare() {
const style = document.createElement('style');
style.id = 'edit-theme-solarflare';
style.type = 'text/css';
style.innerHTML = "/* 默认字体颜色、光标颜色、背景颜色*/\n\
.edit-theme--solarflare .editor__inner {\n\
color: #e3e2e0;\n\
caret-color: #e3e2e0;\n\
}\n\
.edit-theme--solarflare .editor {\n\
background-color: #292D30;\n\
}\n\
/* 标题颜色 */\n\
.edit-theme--solarflare .editor__inner .cn-head,\n\
.edit-theme--solarflare .editor-in-page-buttons .icon {\n\
color: #FF4E50;\n\
}\n\
/* 加粗颜色 */\n\
.edit-theme--solarflare .editor__inner .cn-strong {\n\
color: #FF4E50;\n\
}\n\
/* 信息块颜色 */\n\
.edit-theme--solarflare .editor__inner .blockquote {\n\
color: #FF4E50;\n\
}\n\
/* 源信息、md标记符号等非关键信息的颜色 */\n\
.edit-theme--solarflare .editor__inner .cl,\n\
.edit-theme--solarflare .editor__inner .hr,\n\
.edit-theme--solarflare .editor__inner .link,\n\
.edit-theme--solarflare .editor__inner .linkref, \n\
.edit-theme--solarflare .editor__inner .linkdef .url {\n\
color: rgba(139,158,177,0.8);\n\
}\n\
.edit-theme--solarflare .editor__inner .cn-toc, \n\
.edit-theme--solarflare .editor__inner .code,\n\
.edit-theme--solarflare .editor__inner .img,\n\
.edit-theme--solarflare .editor__inner .img-wrapper,\n\
.edit-theme--solarflare .editor__inner .imgref,\n\
.edit-theme--solarflare .editor__inner .cl-toc {\n\
color: rgba(139,158,177,0.8);\n\
background-color: rgba(0,0,0,0.33);\n\
}\n\
/* 代码块颜色 */\n\
.edit-theme--solarflare .editor__inner .cn-code {\n\
color: #FC913A;\n\
}\n\
/* 链接颜色 */\n\
.edit-theme--solarflare .editor__inner .img .cl-underlined-text,\n\
.edit-theme--solarflare .editor__inner .imgref .cl-underlined-text,\n\
.edit-theme--solarflare .editor__inner .link .cl-underlined-text,\n\
.edit-theme--solarflare .editor__inner .linkref .cl-underlined-text {\n\
color: #EDE574;\n\
}\n\
/* 图片原始链接背景颜色 */\n\
.edit-theme--solarflare .editor__inner .img-wrapper .img {\n\
background-color: transparent;\n\
}\n\
.edit-theme--solarflare .editor__inner .keyword {\n\
color: #47596b;\n\
}\n\
.edit-theme--solarflare .editor__inner .email,\n\
.edit-theme--solarflare .editor__inner .cl-title,\n\
.edit-theme--solarflare .editor__inner .tag,\n\
.edit-theme--solarflare .editor__inner .latex,\n\
.edit-theme--solarflare .editor__inner .math,\n\
.edit-theme--solarflare .editor__inner .entity,\n\
.edit-theme--solarflare .editor__inner .pre [class*='language-'] {\n\
color: #e3e2e0;\n\
}";
document.head.appendChild(style);
}
init_edit_theme_solarflare();