summaryrefslogtreecommitdiff
path: root/public
diff options
context:
space:
mode:
Diffstat (limited to 'public')
-rw-r--r--public/css/index.css18
-rw-r--r--public/js/index.js9
-rw-r--r--public/js/lib/editor/index.js83
-rw-r--r--public/js/lib/editor/toolbar.html48
-rw-r--r--public/js/lib/editor/utils.js113
5 files changed, 250 insertions, 21 deletions
diff --git a/public/css/index.css b/public/css/index.css
index 3f391e27..9cc1766e 100644
--- a/public/css/index.css
+++ b/public/css/index.css
@@ -20,6 +20,24 @@ body.night{
background: #333 !important;
}
+.toolbar {
+ background-color: #1c1c1e;
+ border: 1px solid #343434;
+}
+
+.toolbar > .btn-toolbar > .btn-group > .btn {
+ background-color: #1c1c1e;
+ padding: 5px;
+ font-size: 1em;
+}
+
+.toolbar > .btn-toolbar > .btn-group > .btn:hover {
+ background-color: #383a3e;
+
+ padding: 5px;
+}
+
+
.CodeMirror {
font-family: "Source Code Pro", Consolas, monaco, monospace;
letter-spacing: 0.025em;
diff --git a/public/js/index.js b/public/js/index.js
index c6a4f770..6e13fe9c 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -566,7 +566,10 @@ var previousFocusOnEditor = null
function checkEditorStyle () {
var desireHeight = editorInstance.statusBar ? (ui.area.edit.height() - editorInstance.statusBar.outerHeight()) : ui.area.edit.height()
- // set editor height and min height based on scrollbar style and mode
+ if (editorInstance.toolBar) {
+ desireHeight = desireHeight - editorInstance.toolBar.outerHeight()
+ }
+ // set editor height and min height based on scrollbar style and mode
var scrollbarStyle = editor.getOption('scrollbarStyle')
if (scrollbarStyle === 'overlay' || appState.currentMode === modeType.both) {
ui.area.codemirrorScroll.css('height', desireHeight + 'px')
@@ -804,6 +807,10 @@ function changeMode (type) {
editorInstance.addStatusBar()
editorInstance.updateStatusBar()
}
+ // add and update tool bar
+ if (!editorInstance.toolBar) {
+ editorInstance.addToolBar()
+ }
// work around foldGutter might not init properly
editor.setOption('foldGutter', false)
editor.setOption('foldGutter', true)
diff --git a/public/js/lib/editor/index.js b/public/js/lib/editor/index.js
index bc228b7b..0537e927 100644
--- a/public/js/lib/editor/index.js
+++ b/public/js/lib/editor/index.js
@@ -1,6 +1,7 @@
import * as utils from './utils'
import config from './config'
import statusBarTemplate from './statusbar.html'
+import toolBarTemplate from './toolbar.html'
/* config section */
const isMac = CodeMirror.keyMap.default === CodeMirror.keyMap.macDefault
@@ -136,6 +137,88 @@ export default class Editor {
})
}
+ addToolBar () {
+ this.toolBar = $(toolBarTemplate)
+ this.toolbarPanel = this.editor.addPanel(this.toolBar[0], {
+ position: 'top'
+ })
+
+ var makeBold = $('#makeBold')
+ var makeItalic = $('#makeItalic')
+ var makeStrike = $('#makeStrike')
+ var makeHeader = $('#makeHeader')
+ var makeCode = $('#makeCode')
+ var makeQuote = $('#makeQuote')
+ var makeGenericList = $('#makeGenericList')
+ var makeOrderedList = $('#makeOrderedList')
+ var makeCheckList = $('#makeCheckList')
+ var makeLink = $('#makeLink')
+ var makeImage = $('#makeImage')
+ var makeTable = $('#makeTable')
+ var makeLine = $('#makeLine')
+ var makeComment = $('#makeComment')
+
+ makeBold.click(() => {
+ utils.wrapTextWith(this.editor, this.editor, '**')
+ this.editor.focus()
+ })
+
+ makeItalic.click(() => {
+ utils.wrapTextWith(this.editor, this.editor, '*')
+ this.editor.focus()
+ })
+
+ makeStrike.click(() => {
+ utils.wrapTextWith(this.editor, this.editor, '~~')
+ this.editor.focus()
+ })
+
+ makeHeader.click(() => {
+ utils.insertHeader(this.editor)
+ })
+
+ makeCode.click(() => {
+ utils.wrapTextWith(this.editor, this.editor, '```')
+ this.editor.focus()
+ })
+
+ makeQuote.click(() => {
+ utils.insertOnStartOfLines(this.editor, '> ')
+ })
+
+ makeGenericList.click(() => {
+ utils.insertOnStartOfLines(this.editor, '* ')
+ })
+
+ makeOrderedList.click(() => {
+ utils.insertOnStartOfLines(this.editor, '1. ')
+ })
+
+ makeCheckList.click(() => {
+ utils.insertOnStartOfLines(this.editor, '- [ ] ')
+ })
+
+ makeLink.click(() => {
+ utils.insertLink(this.editor, false)
+ })
+
+ makeImage.click(() => {
+ utils.insertLink(this.editor, true)
+ })
+
+ makeTable.click(() => {
+ utils.insertText(this.editor, '\n\n| Column 1 | Column 2 | Column 3 |\n| -------- | -------- | -------- |\n| Text | Text | Text |\n')
+ })
+
+ makeLine.click(() => {
+ utils.insertText(this.editor, '\n----\n')
+ })
+
+ makeComment.click(() => {
+ utils.insertText(this.editor, '> []')
+ })
+ }
+
addStatusBar () {
this.statusBar = $(statusBarTemplate)
this.statusCursor = this.statusBar.find('.status-cursor > .status-line-column')
diff --git a/public/js/lib/editor/toolbar.html b/public/js/lib/editor/toolbar.html
new file mode 100644
index 00000000..2894eef9
--- /dev/null
+++ b/public/js/lib/editor/toolbar.html
@@ -0,0 +1,48 @@
+<div class="toolbar">
+ <div class="btn-toolbar" role="toolbar" aria-label="Editor toolbar">
+ <div class="btn-group" role="group">
+ <a id="makeBold" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Bold">
+ <i class="fa fa-bold fa-fw"></i>
+ </a>
+ <a id="makeItalic" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Italic">
+ <i class="fa fa-italic fa-fw"></i>
+ </a>
+ <a id="makeStrike" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Strikethrough">
+ <i class="fa fa-strikethrough fa-fw"></i>
+ </a>
+ <a id="makeHeader" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Heading">
+ <i class="fa fa-h1 fa-fw">H</i>
+ </a>
+ <a id="makeCode" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Quote">
+ <i class="fa fa-code fa-fw"></i>
+ </a>
+ <a id="makeQuote" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Quote">
+ <i class="fa fa-quote-right fa-fw"></i>
+ </a>
+ <a id="makeGenericList" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="List">
+ <i class="fa fa-list fa-fw"></i>
+ </a>
+ <a id="makeOrderedList" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Numbered List">
+ <i class="fa fa-list-ol fa-fw"></i>
+ </a>
+ <a id="makeCheckList" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Check List">
+ <i class="fa fa-check-square fa-fw"></i>
+ </a>
+ <a id="makeLink" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Link">
+ <i class="fa fa-link fa-fw"></i>
+ </a>
+ <a id="makeImage" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Image">
+ <i class="fa fa-image fa-fw"></i>
+ </a>
+ <a id="makeTable" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Table">
+ <i class="fa fa-table fa-fw"></i>
+ </a>
+ <a id="makeLine" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Line">
+ <i class="fa fa-minus fa-fw"></i>
+ </a>
+ <a id="makeComment" class="btn btn-sm btn-dark text-uppercase" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" title="Line">
+ <i class="fa fa-comment fa-fw"></i>
+ </a>
+ </div>
+ </div>
+</div>
diff --git a/public/js/lib/editor/utils.js b/public/js/lib/editor/utils.js
index 3702a166..33670884 100644
--- a/public/js/lib/editor/utils.js
+++ b/public/js/lib/editor/utils.js
@@ -3,39 +3,39 @@ export function wrapTextWith (editor, cm, symbol) {
if (!cm.getSelection()) {
return CodeMirror.Pass
} else {
- var ranges = cm.listSelections()
- for (var i = 0; i < ranges.length; i++) {
- var range = ranges[i]
+ let ranges = cm.listSelections()
+ for (let i = 0; i < ranges.length; i++) {
+ let range = ranges[i]
if (!range.empty()) {
const from = range.from()
const to = range.to()
if (symbol !== 'Backspace') {
- cm.replaceRange(symbol, to, to, '+input')
- cm.replaceRange(symbol, from, from, '+input')
- // workaround selection range not correct after add symbol
- var _ranges = cm.listSelections()
- var anchorIndex = editor.indexFromPos(_ranges[i].anchor)
- var headIndex = editor.indexFromPos(_ranges[i].head)
+ let selection = cm.getRange(from, to)
+ let anchorIndex = editor.indexFromPos(ranges[i].anchor)
+ let headIndex = editor.indexFromPos(ranges[i].head)
+ cm.replaceRange(symbol + selection + symbol, from, to, '+input')
if (anchorIndex > headIndex) {
- _ranges[i].anchor.ch--
+ ranges[i].anchor.ch+= symbol.length
+ ranges[i].head.ch+= symbol.length
} else {
- _ranges[i].head.ch--
+ ranges[i].head.ch+= symbol.length
+ ranges[i].anchor.ch+= symbol.length
}
- cm.setSelections(_ranges)
+ cm.setSelections(ranges)
} else {
- var preEndPos = {
+ let preEndPos = {
line: to.line,
- ch: to.ch + 1
+ ch: to.ch + symbol.length
}
- var preText = cm.getRange(to, preEndPos)
- var preIndex = wrapSymbols.indexOf(preText)
- var postEndPos = {
+ let preText = cm.getRange(to, preEndPos)
+ let preIndex = wrapSymbols.indexOf(preText)
+ let postEndPos = {
line: from.line,
- ch: from.ch - 1
+ ch: from.ch - symbol.length
}
- var postText = cm.getRange(postEndPos, from)
- var postIndex = wrapSymbols.indexOf(postText)
+ let postText = cm.getRange(postEndPos, from)
+ let postIndex = wrapSymbols.indexOf(postText)
// check if surround symbol are list in array and matched
if (preIndex > -1 && postIndex > -1 && preIndex === postIndex) {
cm.replaceRange('', to, preEndPos, '+delete')
@@ -46,3 +46,76 @@ export function wrapTextWith (editor, cm, symbol) {
}
}
}
+
+export function insertText (cm, text, cursorEnd = 0) {
+ let cursor = cm.getCursor()
+ cm.replaceSelection(text, cursor, cursor)
+ cm.focus()
+ cm.setCursor({line: cursor.line, ch: cursor.ch + cursorEnd})
+}
+
+export function insertLink(cm, isImage) {
+ let cursor = cm.getCursor()
+ let ranges = cm.listSelections()
+ const linkEnd = '](https://)'
+ const symbol = (isImage) ? '![' : '['
+
+ for (let i = 0; i < ranges.length; i++) {
+ let range = ranges[i]
+ if (!range.empty()) {
+ const from = range.from()
+ const to = range.to()
+ let anchorIndex = editor.indexFromPos(ranges[i].anchor)
+ let headIndex = editor.indexFromPos(ranges[i].head)
+ let selection = cm.getRange(from, to)
+ selection = symbol + selection + linkEnd
+ cm.replaceRange(selection, from, to)
+ if (anchorIndex > headIndex) {
+ ranges[i].anchor.ch+= symbol.length
+ ranges[i].head.ch+= symbol.length
+ } else {
+ ranges[i].head.ch+= symbol.length
+ ranges[i].anchor.ch+= symbol.length
+ }
+ cm.setSelections(ranges)
+ } else {
+ cm.replaceRange(symbol + linkEnd, cursor, cursor)
+ cm.setCursor({line: cursor.line, ch: cursor.ch + symbol.length + linkend.length})
+ }
+ }
+ cm.focus()
+}
+
+export function insertHeader (cm) {
+ let cursor = cm.getCursor()
+ let startOfLine = {line: cursor.line, ch: 0}
+ let startOfLineText = cm.getRange(startOfLine, {line: cursor.line, ch: 1})
+ // See if it is already a header
+ if (startOfLineText === '#') {
+ cm.replaceRange('#', startOfLine, startOfLine)
+ } else {
+ cm.replaceRange('# ', startOfLine, startOfLine)
+ }
+ cm.focus()
+}
+
+export function insertOnStartOfLines (cm, symbol) {
+ let cursor = cm.getCursor()
+ let ranges = cm.listSelections()
+
+ for (let i = 0; i < ranges.length; i++) {
+ let range = ranges[i]
+ if (!range.empty()) {
+ const from = range.from()
+ const to = range.to()
+ let selection = cm.getRange({line: from.line, ch: 0}, to)
+ selection = selection.replace(/\n/g, '\n' + symbol)
+ selection = symbol + selection
+ cm.replaceRange(selection, from, to)
+ } else {
+ cm.replaceRange(symbol, {line: cursor.line, ch: 0}, {line: cursor.line, ch: 0})
+ }
+ }
+ cm.setCursor({line: cursor.line, ch: cursor.ch + symbol.length})
+ cm.focus()
+}