Merge branch 'pr-846'

This commit is contained in:
Sheogorath 2018-06-23 21:19:44 +02:00
commit 49db5bc653
No known key found for this signature in database
GPG key ID: 1F05CC3635CDDFFD
5 changed files with 250 additions and 21 deletions

View file

@ -20,6 +20,24 @@ body.night{
background: #333 !important; 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 { .CodeMirror {
font-family: "Source Code Pro", Consolas, monaco, monospace; font-family: "Source Code Pro", Consolas, monaco, monospace;
letter-spacing: 0.025em; letter-spacing: 0.025em;

View file

@ -566,7 +566,10 @@ var previousFocusOnEditor = null
function checkEditorStyle () { function checkEditorStyle () {
var desireHeight = editorInstance.statusBar ? (ui.area.edit.height() - editorInstance.statusBar.outerHeight()) : ui.area.edit.height() 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') var scrollbarStyle = editor.getOption('scrollbarStyle')
if (scrollbarStyle === 'overlay' || appState.currentMode === modeType.both) { if (scrollbarStyle === 'overlay' || appState.currentMode === modeType.both) {
ui.area.codemirrorScroll.css('height', desireHeight + 'px') ui.area.codemirrorScroll.css('height', desireHeight + 'px')
@ -804,6 +807,10 @@ function changeMode (type) {
editorInstance.addStatusBar() editorInstance.addStatusBar()
editorInstance.updateStatusBar() editorInstance.updateStatusBar()
} }
// add and update tool bar
if (!editorInstance.toolBar) {
editorInstance.addToolBar()
}
// work around foldGutter might not init properly // work around foldGutter might not init properly
editor.setOption('foldGutter', false) editor.setOption('foldGutter', false)
editor.setOption('foldGutter', true) editor.setOption('foldGutter', true)

View file

@ -1,6 +1,7 @@
import * as utils from './utils' import * as utils from './utils'
import config from './config' import config from './config'
import statusBarTemplate from './statusbar.html' import statusBarTemplate from './statusbar.html'
import toolBarTemplate from './toolbar.html'
/* config section */ /* config section */
const isMac = CodeMirror.keyMap.default === CodeMirror.keyMap.macDefault 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 () { addStatusBar () {
this.statusBar = $(statusBarTemplate) this.statusBar = $(statusBarTemplate)
this.statusCursor = this.statusBar.find('.status-cursor > .status-line-column') this.statusCursor = this.statusBar.find('.status-cursor > .status-line-column')

View file

@ -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>

View file

@ -3,39 +3,39 @@ export function wrapTextWith (editor, cm, symbol) {
if (!cm.getSelection()) { if (!cm.getSelection()) {
return CodeMirror.Pass return CodeMirror.Pass
} else { } else {
var ranges = cm.listSelections() let ranges = cm.listSelections()
for (var i = 0; i < ranges.length; i++) { for (let i = 0; i < ranges.length; i++) {
var range = ranges[i] let range = ranges[i]
if (!range.empty()) { if (!range.empty()) {
const from = range.from() const from = range.from()
const to = range.to() const to = range.to()
if (symbol !== 'Backspace') { if (symbol !== 'Backspace') {
cm.replaceRange(symbol, to, to, '+input') let selection = cm.getRange(from, to)
cm.replaceRange(symbol, from, from, '+input') let anchorIndex = editor.indexFromPos(ranges[i].anchor)
// workaround selection range not correct after add symbol let headIndex = editor.indexFromPos(ranges[i].head)
var _ranges = cm.listSelections() cm.replaceRange(symbol + selection + symbol, from, to, '+input')
var anchorIndex = editor.indexFromPos(_ranges[i].anchor)
var headIndex = editor.indexFromPos(_ranges[i].head)
if (anchorIndex > headIndex) { if (anchorIndex > headIndex) {
_ranges[i].anchor.ch-- ranges[i].anchor.ch+= symbol.length
ranges[i].head.ch+= symbol.length
} else { } else {
_ranges[i].head.ch-- ranges[i].head.ch+= symbol.length
ranges[i].anchor.ch+= symbol.length
} }
cm.setSelections(_ranges) cm.setSelections(ranges)
} else { } else {
var preEndPos = { let preEndPos = {
line: to.line, line: to.line,
ch: to.ch + 1 ch: to.ch + symbol.length
} }
var preText = cm.getRange(to, preEndPos) let preText = cm.getRange(to, preEndPos)
var preIndex = wrapSymbols.indexOf(preText) let preIndex = wrapSymbols.indexOf(preText)
var postEndPos = { let postEndPos = {
line: from.line, line: from.line,
ch: from.ch - 1 ch: from.ch - symbol.length
} }
var postText = cm.getRange(postEndPos, from) let postText = cm.getRange(postEndPos, from)
var postIndex = wrapSymbols.indexOf(postText) let postIndex = wrapSymbols.indexOf(postText)
// check if surround symbol are list in array and matched // check if surround symbol are list in array and matched
if (preIndex > -1 && postIndex > -1 && preIndex === postIndex) { if (preIndex > -1 && postIndex > -1 && preIndex === postIndex) {
cm.replaceRange('', to, preEndPos, '+delete') 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()
}