Skip to content

Commit 023161d

Browse files
authored
Merge pull request #1335 from hackmdio/feature/configurable-theme
Configurable editor color scheme (theme)
2 parents e09c16a + 89ff0b6 commit 023161d

File tree

8 files changed

+231
-26
lines changed

8 files changed

+231
-26
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* Based on https://github.com/dempfi/ayu */
2+
3+
.cm-s-ayu-dark.CodeMirror { background: #0a0e14; color: #b3b1ad; }
4+
.cm-s-ayu-dark div.CodeMirror-selected { background: #273747; }
5+
.cm-s-ayu-dark .CodeMirror-line::selection, .cm-s-ayu-dark .CodeMirror-line > span::selection, .cm-s-ayu-dark .CodeMirror-line > span > span::selection { background: rgba(39, 55, 71, 99); }
6+
.cm-s-ayu-dark .CodeMirror-line::-moz-selection, .cm-s-ayu-dark .CodeMirror-line > span::-moz-selection, .cm-s-ayu-dark .CodeMirror-line > span > span::-moz-selection { background: rgba(39, 55, 71, 99); }
7+
.cm-s-ayu-dark .CodeMirror-gutters { background: #0a0e14; border-right: 0px; }
8+
.cm-s-ayu-dark .CodeMirror-guttermarker { color: white; }
9+
.cm-s-ayu-dark .CodeMirror-guttermarker-subtle { color: #3d424d; }
10+
.cm-s-ayu-dark .CodeMirror-linenumber { color: #3d424d; }
11+
.cm-s-ayu-dark .CodeMirror-cursor { border-left: 1px solid #e6b450; }
12+
13+
.cm-s-ayu-dark span.cm-comment { color: #626a73; }
14+
.cm-s-ayu-dark span.cm-atom { color: #ae81ff; }
15+
.cm-s-ayu-dark span.cm-number { color: #e6b450; }
16+
17+
.cm-s-ayu-dark span.cm-comment.cm-attribute { color: #ffb454; }
18+
.cm-s-ayu-dark span.cm-comment.cm-def { color: rgba(57, 186, 230, 80); }
19+
.cm-s-ayu-dark span.cm-comment.cm-tag { color: #39bae6; }
20+
.cm-s-ayu-dark span.cm-comment.cm-type { color: #5998a6; }
21+
22+
.cm-s-ayu-dark span.cm-property, .cm-s-ayu-dark span.cm-attribute { color: #ffb454; }
23+
.cm-s-ayu-dark span.cm-keyword { color: #ff8f40; }
24+
.cm-s-ayu-dark span.cm-builtin { color: #e6b450; }
25+
.cm-s-ayu-dark span.cm-string { color: #c2d94c; }
26+
27+
.cm-s-ayu-dark span.cm-variable { color: #b3b1ad; }
28+
.cm-s-ayu-dark span.cm-variable-2 { color: #f07178; }
29+
.cm-s-ayu-dark span.cm-variable-3 { color: #39bae6; }
30+
.cm-s-ayu-dark span.cm-type { color: #ff8f40; }
31+
.cm-s-ayu-dark span.cm-def { color: #ffee99; }
32+
.cm-s-ayu-dark span.cm-bracket { color: #f8f8f2; }
33+
.cm-s-ayu-dark span.cm-tag { color: rgba(57, 186, 230, 80); }
34+
.cm-s-ayu-dark span.cm-header { color: #c2d94c; }
35+
.cm-s-ayu-dark span.cm-link { color: #39bae6; }
36+
.cm-s-ayu-dark span.cm-error { color: #ff3333; }
37+
38+
.cm-s-ayu-dark .CodeMirror-activeline-background { background: #01060e; }
39+
.cm-s-ayu-dark .CodeMirror-matchingbracket {
40+
text-decoration: underline;
41+
color: white !important;
42+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* Based on https://github.com/dempfi/ayu */
2+
3+
.cm-s-ayu-mirage.CodeMirror { background: #1f2430; color: #cbccc6; }
4+
.cm-s-ayu-mirage div.CodeMirror-selected { background: #34455a; }
5+
.cm-s-ayu-mirage .CodeMirror-line::selection, .cm-s-ayu-mirage .CodeMirror-line > span::selection, .cm-s-ayu-mirage .CodeMirror-line > span > span::selection { background: #34455a; }
6+
.cm-s-ayu-mirage .CodeMirror-line::-moz-selection, .cm-s-ayu-mirage .CodeMirror-line > span::-moz-selection, .cm-s-ayu-mirage .CodeMirror-line > span > span::-moz-selection { background: rgba(25, 30, 42, 99); }
7+
.cm-s-ayu-mirage .CodeMirror-gutters { background: #1f2430; border-right: 0px; }
8+
.cm-s-ayu-mirage .CodeMirror-guttermarker { color: white; }
9+
.cm-s-ayu-mirage .CodeMirror-guttermarker-subtle { color: rgba(112, 122, 140, 66); }
10+
.cm-s-ayu-mirage .CodeMirror-linenumber { color: rgba(61, 66, 77, 99); }
11+
.cm-s-ayu-mirage .CodeMirror-cursor { border-left: 1px solid #ffcc66; }
12+
13+
.cm-s-ayu-mirage span.cm-comment { color: #5c6773; font-style:italic; }
14+
.cm-s-ayu-mirage span.cm-atom { color: #ae81ff; }
15+
.cm-s-ayu-mirage span.cm-number { color: #ffcc66; }
16+
17+
.cm-s-ayu-mirage span.cm-comment.cm-attribute { color: #ffd580; }
18+
.cm-s-ayu-mirage span.cm-comment.cm-def { color: #d4bfff; }
19+
.cm-s-ayu-mirage span.cm-comment.cm-tag { color: #5ccfe6; }
20+
.cm-s-ayu-mirage span.cm-comment.cm-type { color: #5998a6; }
21+
22+
.cm-s-ayu-mirage span.cm-property { color: #f29e74; }
23+
.cm-s-ayu-mirage span.cm-attribute { color: #ffd580; }
24+
.cm-s-ayu-mirage span.cm-keyword { color: #ffa759; }
25+
.cm-s-ayu-mirage span.cm-builtin { color: #ffcc66; }
26+
.cm-s-ayu-mirage span.cm-string { color: #bae67e; }
27+
28+
.cm-s-ayu-mirage span.cm-variable { color: #cbccc6; }
29+
.cm-s-ayu-mirage span.cm-variable-2 { color: #f28779; }
30+
.cm-s-ayu-mirage span.cm-variable-3 { color: #5ccfe6; }
31+
.cm-s-ayu-mirage span.cm-type { color: #ffa759; }
32+
.cm-s-ayu-mirage span.cm-def { color: #ffd580; }
33+
.cm-s-ayu-mirage span.cm-bracket { color: rgba(92, 207, 230, 80); }
34+
.cm-s-ayu-mirage span.cm-tag { color: #5ccfe6; }
35+
.cm-s-ayu-mirage span.cm-header { color: #bae67e; }
36+
.cm-s-ayu-mirage span.cm-link { color: #5ccfe6; }
37+
.cm-s-ayu-mirage span.cm-error { color: #ff3333; }
38+
39+
.cm-s-ayu-mirage .CodeMirror-activeline-background { background: #191e2a; }
40+
.cm-s-ayu-mirage .CodeMirror-matchingbracket {
41+
text-decoration: underline;
42+
color: white !important;
43+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
3+
Name: Tomorrow Night - Bright
4+
Author: Chris Kempson
5+
6+
Port done by Gerard Braad <[email protected]>
7+
8+
*/
9+
10+
.cm-s-tomorrow-night-bright.CodeMirror { background: #000000; color: #eaeaea; }
11+
.cm-s-tomorrow-night-bright div.CodeMirror-selected { background: #424242; }
12+
.cm-s-tomorrow-night-bright .CodeMirror-gutters { background: #000000; border-right: 0px; }
13+
.cm-s-tomorrow-night-bright .CodeMirror-guttermarker { color: #e78c45; }
14+
.cm-s-tomorrow-night-bright .CodeMirror-guttermarker-subtle { color: #777; }
15+
.cm-s-tomorrow-night-bright .CodeMirror-linenumber { color: #424242; }
16+
.cm-s-tomorrow-night-bright .CodeMirror-cursor { border-left: 1px solid #6A6A6A; }
17+
18+
.cm-s-tomorrow-night-bright span.cm-comment { color: #d27b53; }
19+
.cm-s-tomorrow-night-bright span.cm-atom { color: #a16a94; }
20+
.cm-s-tomorrow-night-bright span.cm-number { color: #a16a94; }
21+
22+
.cm-s-tomorrow-night-bright span.cm-property, .cm-s-tomorrow-night-bright span.cm-attribute { color: #99cc99; }
23+
.cm-s-tomorrow-night-bright span.cm-keyword { color: #d54e53; }
24+
.cm-s-tomorrow-night-bright span.cm-string { color: #e7c547; }
25+
26+
.cm-s-tomorrow-night-bright span.cm-variable { color: #b9ca4a; }
27+
.cm-s-tomorrow-night-bright span.cm-variable-2 { color: #7aa6da; }
28+
.cm-s-tomorrow-night-bright span.cm-def { color: #e78c45; }
29+
.cm-s-tomorrow-night-bright span.cm-bracket { color: #eaeaea; }
30+
.cm-s-tomorrow-night-bright span.cm-tag { color: #d54e53; }
31+
.cm-s-tomorrow-night-bright span.cm-link { color: #a16a94; }
32+
.cm-s-tomorrow-night-bright span.cm-error { background: #d54e53; color: #6A6A6A; }
33+
34+
.cm-s-tomorrow-night-bright .CodeMirror-activeline-background { background: #2a2a2a; }
35+
.cm-s-tomorrow-night-bright .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
3+
Name: Tomorrow Night - Eighties
4+
Author: Chris Kempson
5+
6+
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
7+
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
8+
9+
*/
10+
11+
.cm-s-tomorrow-night-eighties.CodeMirror { background: #000000; color: #CCCCCC; }
12+
.cm-s-tomorrow-night-eighties div.CodeMirror-selected { background: #2D2D2D; }
13+
.cm-s-tomorrow-night-eighties .CodeMirror-line::selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span::selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span > span::selection { background: rgba(45, 45, 45, 0.99); }
14+
.cm-s-tomorrow-night-eighties .CodeMirror-line::-moz-selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span::-moz-selection, .cm-s-tomorrow-night-eighties .CodeMirror-line > span > span::-moz-selection { background: rgba(45, 45, 45, 0.99); }
15+
.cm-s-tomorrow-night-eighties .CodeMirror-gutters { background: #000000; border-right: 0px; }
16+
.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker { color: #f2777a; }
17+
.cm-s-tomorrow-night-eighties .CodeMirror-guttermarker-subtle { color: #777; }
18+
.cm-s-tomorrow-night-eighties .CodeMirror-linenumber { color: #515151; }
19+
.cm-s-tomorrow-night-eighties .CodeMirror-cursor { border-left: 1px solid #6A6A6A; }
20+
21+
.cm-s-tomorrow-night-eighties span.cm-comment { color: #d27b53; }
22+
.cm-s-tomorrow-night-eighties span.cm-atom { color: #a16a94; }
23+
.cm-s-tomorrow-night-eighties span.cm-number { color: #a16a94; }
24+
25+
.cm-s-tomorrow-night-eighties span.cm-property, .cm-s-tomorrow-night-eighties span.cm-attribute { color: #99cc99; }
26+
.cm-s-tomorrow-night-eighties span.cm-keyword { color: #f2777a; }
27+
.cm-s-tomorrow-night-eighties span.cm-string { color: #ffcc66; }
28+
29+
.cm-s-tomorrow-night-eighties span.cm-variable { color: #99cc99; }
30+
.cm-s-tomorrow-night-eighties span.cm-variable-2 { color: #6699cc; }
31+
.cm-s-tomorrow-night-eighties span.cm-def { color: #f99157; }
32+
.cm-s-tomorrow-night-eighties span.cm-bracket { color: #CCCCCC; }
33+
.cm-s-tomorrow-night-eighties span.cm-tag { color: #f2777a; }
34+
.cm-s-tomorrow-night-eighties span.cm-link { color: #a16a94; }
35+
.cm-s-tomorrow-night-eighties span.cm-error { background: #f2777a; color: #6A6A6A; }
36+
37+
.cm-s-tomorrow-night-eighties .CodeMirror-activeline-background { background: #343600; }
38+
.cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket { text-decoration: underline; color: white !important; }

public/js/lib/editor/constants.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export const availableThemes = [
2+
{ name: 'Light', value: 'default' },
3+
{ name: 'One Dark (Default)', value: 'one-dark' },
4+
{ name: 'Monokai', value: 'monokai' },
5+
{ name: 'Solarized Dark', value: 'solarized dark' },
6+
{ name: 'Solarized Light', value: 'solarized light' },
7+
{ name: 'Dracula', value: 'dracula' },
8+
{ name: 'Material', value: 'material' },
9+
{ name: 'Nord', value: 'nord' },
10+
{ name: 'Panda', value: 'panda-syntax' },
11+
{ name: 'Ayu Dark', value: 'ayu-dark' },
12+
{ name: 'Ayu Mirage', value: 'ayu-mirage' },
13+
{ name: 'Tomorror Night Bright', value: 'tomorrow-night-bright' },
14+
{ name: 'Tomorror Night Eighties', value: 'tomorrow-night-eighties' }
15+
]

public/js/lib/editor/index.js

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
/* global CodeMirror, $, editor, Cookies */
2+
import { options, Alignment, FormatType } from '@susisu/mte-kernel'
3+
import debounce from 'lodash/debounce'
4+
25
import * as utils from './utils'
36
import config from './config'
47
import statusBarTemplate from './statusbar.html'
58
import toolBarTemplate from './toolbar.html'
69
import './markdown-lint'
710
import { initTableEditor } from './table-editor'
8-
import { options, Alignment, FormatType } from '@susisu/mte-kernel'
11+
import { availableThemes } from './constants'
912

1013
/* config section */
1114
const isMac = CodeMirror.keyMap.default === CodeMirror.keyMap.macDefault
@@ -325,6 +328,8 @@ export default class Editor {
325328
this.setSpellcheck()
326329
this.setLinter()
327330
this.setPreferences()
331+
332+
this.handleStatusBarResize()
328333
}
329334

330335
updateStatusBar () {
@@ -349,6 +354,21 @@ export default class Editor {
349354
}
350355
}
351356

357+
handleStatusBarResize () {
358+
const onResize = debounce(() => {
359+
if (!this.statusBar) {
360+
return
361+
}
362+
363+
const maxHeight = window.innerHeight - this.statusBar.height() - 50 /* navbar height */ - 10 /* spacing */
364+
this.statusBar.find('.status-theme ul.dropdown-menu').css('max-height', `${maxHeight}px`)
365+
}, 300)
366+
367+
$(window).resize(onResize)
368+
369+
onResize()
370+
}
371+
352372
setIndent () {
353373
var cookieIndentType = Cookies.get('indent_type')
354374
var cookieTabSize = parseInt(Cookies.get('tab_size'))
@@ -488,38 +508,37 @@ export default class Editor {
488508
}
489509

490510
setTheme () {
491-
var cookieTheme = Cookies.get('theme')
492-
if (cookieTheme) {
493-
this.editor.setOption('theme', cookieTheme)
494-
}
511+
this.statusIndicators.find('.status-theme ul.dropdown-menu').append(availableThemes.map(theme => {
512+
return $(`<li value="${theme.value}"><a>${theme.name}</a></li>`)
513+
}))
495514

496-
var themeToggle = this.statusTheme.find('.ui-theme-toggle')
497-
498-
const checkTheme = () => {
499-
var theme = this.editor.getOption('theme')
500-
if (theme === 'one-dark') {
501-
themeToggle.removeClass('active')
502-
} else {
503-
themeToggle.addClass('active')
504-
}
515+
const activateThemeListItem = (theme) => {
516+
this.statusIndicators.find('.status-theme li').removeClass('active')
517+
this.statusIndicators.find(`.status-theme li[value="${theme}"]`).addClass('active')
505518
}
506519

507-
themeToggle.click(() => {
508-
var theme = this.editor.getOption('theme')
509-
if (theme === 'one-dark') {
510-
theme = 'default'
511-
} else {
512-
theme = 'one-dark'
513-
}
520+
const setTheme = theme => {
514521
this.editor.setOption('theme', theme)
515522
Cookies.set('theme', theme, {
516523
expires: 365
517524
})
525+
this.statusIndicators.find('.status-theme li').removeClass('active')
526+
this.statusIndicators.find(`.status-theme li[value="${theme}"]`).addClass('active')
527+
}
518528

519-
checkTheme()
520-
})
529+
const cookieTheme = Cookies.get('theme')
530+
if (cookieTheme && availableThemes.find(theme => cookieTheme === theme.value)) {
531+
setTheme(cookieTheme)
532+
activateThemeListItem(cookieTheme)
533+
} else {
534+
activateThemeListItem(this.editor.getOption('theme'))
535+
}
521536

522-
checkTheme()
537+
this.statusIndicators.find('.status-theme li').click(function () {
538+
const theme = $(this).attr('value')
539+
setTheme(theme)
540+
activateThemeListItem(theme)
541+
})
523542
}
524543

525544
setSpellcheck () {

public/js/lib/editor/statusbar.html

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@
3131
<div class="indent-width-label" title="Click to change indentation size">4</div>
3232
<input class="indent-width-input hidden" type="number" min="1" max="10" maxlength="2" size="2">
3333
</div>
34-
<div class="status-theme">
35-
<a class="ui-theme-toggle" title="Toggle editor theme"><i class="fa fa-sun-o fa-fw"></i></a>
34+
<div class="status-theme dropup">
35+
<a id="themeLabel" class="ui-theme-label text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Select theme">
36+
<i class="fa fa-paint-brush fa-fw"></i>
37+
</a>
38+
<ul class="dropdown-menu" aria-labelledby="themeLabel" style="overflow: auto;">
39+
</ul>
3640
</div>
3741
<div class="status-spellcheck">
3842
<a class="ui-spellcheck-toggle" title="Toggle spellcheck"><i class="fa fa-check fa-fw"></i></a>

webpack.common.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,15 @@ module.exports = {
222222
path.join(__dirname, 'node_modules/@hackmd/codemirror/addon/search/matchesonscrollbar.css'),
223223
path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/monokai.css'),
224224
path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/one-dark.css'),
225+
path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/dracula.css'),
226+
path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/material.css'),
227+
path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/nord.css'),
228+
path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/panda-syntax.css'),
229+
path.join(__dirname, 'node_modules/@hackmd/codemirror/theme/solarized.css'),
230+
path.join(__dirname, 'public/css/codemirror-extend/ayu-dark.css'),
231+
path.join(__dirname, 'public/css/codemirror-extend/ayu-mirage.css'),
232+
path.join(__dirname, 'public/css/codemirror-extend/tomorrow-night-bright.css'),
233+
path.join(__dirname, 'public/css/codemirror-extend/tomorrow-night-eighties.css'),
225234
path.join(__dirname, 'node_modules/@hackmd/codemirror/mode/tiddlywiki/tiddlywiki.css'),
226235
path.join(__dirname, 'node_modules/@hackmd/codemirror/mode/mediawiki/mediawiki.css'),
227236
path.join(__dirname, 'public/css/github-extract.css'),

0 commit comments

Comments
 (0)