+const TodoListPercentage = ({ percentageOfTodo, onClearCheckboxClick }) => (
+
)
diff --git a/browser/components/TodoListPercentage.styl b/browser/components/TodoListPercentage.styl
index 5a0f3257..4a0081cd 100644
--- a/browser/components/TodoListPercentage.styl
+++ b/browser/components/TodoListPercentage.styl
@@ -54,7 +54,7 @@ body[data-theme="dark"]
.percentageText
color $ui-dark-text-color
-
+
.todoClearText
color $ui-dark-text-color
@@ -71,25 +71,19 @@ body[data-theme="solarized-dark"]
.todoClearText
color #fdf6e3
-body[data-theme="monokai"]
- .percentageBar
- background-color: $ui-monokai-borderColor
+apply-theme(theme)
+ body[data-theme={theme}]
+ .percentageBar
+ background-color: get-theme-var(theme, 'borderColor')
- .progressBar
- background-color $ui-monokai-active-color
+ .progressBar
+ background-color get-theme-var(theme, 'active-color')
- .percentageText
- color $ui-monokai-text-color
+ .percentageText
+ color get-theme-var(theme, 'text-color')
-body[data-theme="dracula"]
- .percentageBar
- background-color $ui-dracula-borderColor
+for theme in 'dracula'
+ apply-theme(theme)
- .progressBar
- background-color: $ui-dracula-active-color
-
- .percentageText
- color $ui-dracula-text-color
-
- .percentageText
- color $ui-dracula-text-color
+for theme in $themes
+ apply-theme(theme)
\ No newline at end of file
diff --git a/browser/components/TodoProcess.js b/browser/components/TodoProcess.js
index 9d1f93cf..6dc46e65 100644
--- a/browser/components/TodoProcess.js
+++ b/browser/components/TodoProcess.js
@@ -8,18 +8,21 @@ import CSSModules from 'browser/lib/CSSModules'
import styles from './TodoProcess.styl'
const TodoProcess = ({
- todoStatus: {
- total: totalTodo,
- completed: completedTodo
- }
+ todoStatus: { total: totalTodo, completed: completedTodo }
}) => (
-
0 ? '' : 'none'}}>
+
0 ? '' : 'none' }}
+ >
{completedTodo} of {totalTodo}
)
diff --git a/browser/components/markdown.styl b/browser/components/markdown.styl
index 4921b531..8ad50e39 100644
--- a/browser/components/markdown.styl
+++ b/browser/components/markdown.styl
@@ -124,40 +124,34 @@ hr
border-bottom solid 1px borderColor
margin 15px 0
h1, h2, h3, h4, h5, h6
+ margin 1em 0 1.5em
+ line-height 1.4
font-weight bold
word-wrap break-word
+ padding .2em 0 .2em
h1
font-size 2.55em
- padding-bottom 0.3em
- line-height 1.2em
+ line-height 1.2
border-bottom solid 1px borderColor
- margin 1em 0 0.44em
&:first-child
margin-top 0
h2
font-size 1.75em
- padding-bottom 0.3em
- line-height 1.225em
+ line-height 1.225
border-bottom solid 1px borderColor
- margin 1em 0 0.57em
&:first-child
margin-top 0
h3
font-size 1.5em
- line-height 1.43em
- margin 1em 0 0.66em
+ line-height 1.43
h4
font-size 1.25em
- line-height 1.4em
- margin 1em 0 0.8em
+ line-height 1.4
h5
font-size 1em
- line-height 1.4em
- margin 1em 0 1em
+ line-height 1.1
h6
font-size 1em
- line-height 1.4em
- margin 1em 0 1em
color #777
p
line-height 1.6em
@@ -363,7 +357,10 @@ admonition_types = {
danger: {color: #c2185b, icon: "block"},
caution: {color: #ffa726, icon: "warning"},
error: {color: #d32f2f, icon: "error_outline"},
- attention: {color: #455a64, icon: "priority_high"}
+ question: {color: #64dd17, icon: "help_outline"},
+ quote: {color: #9e9e9e, icon: "format_quote"},
+ abstract: {color: #00b0ff, icon: "subject"},
+ attention: {color: #455a64, icon: "priority_high"},
}
for name, val in admonition_types
@@ -424,6 +421,9 @@ pre.fence
canvas, svg
max-width 100% !important
+ svg[ratio]
+ width 100%
+
.gallery
width 100%
height 50vh
@@ -444,6 +444,44 @@ pre.fence
color $ui-text-color
background-color $ui-tag-backgroundColor
+.markdownIt-TOC-wrapper
+ list-style none
+ position fixed
+ right 0
+ top 0
+ margin-left 15px
+ z-index 1000
+ transition transform .2s ease-in-out
+ transform translateX(100%)
+
+ .markdownIt-TOC
+ display block
+ max-height 90vh
+ overflow-y auto
+ padding 25px
+ padding-left 38px
+
+ &,
+ &:before
+ background-color $ui-dark-backgroundColor
+ color: $ui-dark-text-color
+
+ &:hover
+ transform translateX(-15px)
+
+ &:before
+ content 'TOC'
+ position absolute
+ width 60px
+ height 30px
+ top 60px
+ left -29px
+ display flex
+ align-items center
+ justify-content center
+ transform-origin top left
+ transform rotate(-90deg)
+
themeDarkBackground = darken(#21252B, 10%)
themeDarkText = #f9f9f9
themeDarkBorder = lighten(themeDarkBackground, 20%)
@@ -511,137 +549,63 @@ body[data-theme="dark"]
color $ui-dark-text-color
background-color $ui-dark-tag-backgroundColor
-themeSolarizedDarkTableOdd = $ui-solarized-dark-noteDetail-backgroundColor
-themeSolarizedDarkTableEven = darken($ui-solarized-dark-noteDetail-backgroundColor, 10%)
-themeSolarizedDarkTableHead = themeSolarizedDarkTableEven
-themeSolarizedDarkTableBorder = themeDarkBorder
+ .markdownIt-TOC-wrapper
+ &,
+ &:before
+ background-color darken(themeDarkBackground, 5%)
+ color themeDarkText
-body[data-theme="solarized-dark"]
- color $ui-solarized-dark-text-color
- border-color themeDarkBorder
- background-color $ui-solarized-dark-noteDetail-backgroundColor
- table
- thead
- tr
- background-color themeSolarizedDarkTableHead
- th
- border-color themeSolarizedDarkTableBorder
- &:last-child
- border-right solid 1px themeSolarizedDarkTableBorder
- tbody
- tr:nth-child(2n + 1)
- background-color themeSolarizedDarkTableOdd
- tr:nth-child(2n)
- background-color themeSolarizedDarkTableEven
- td
- border-color themeSolarizedDarkTableBorder
- &:last-child
- border-right solid 1px themeSolarizedDarkTableBorder
- dl
+apply-theme(theme)
+ body[data-theme={theme}]
+ color get-theme-var(theme, 'text-color')
border-color themeDarkBorder
- background-color themeSolarizedDarkTableHead
- dt
- border-color themeDarkBorder
- dd
- border-color themeDarkBorder
- background-color $ui-solarized-dark-noteDetail-backgroundColor
+ background-color get-theme-var(theme, 'noteDetail-backgroundColor')
+ table
+ thead
+ tr
+ background-color get-theme-var(theme, 'table-head-backgroundColor')
+ th
+ border-color get-theme-var(theme, 'table-borderColor')
+ &:last-child
+ border-right solid 1px get-theme-var(theme, 'table-borderColor')
+ tbody
+ tr:nth-child(2n + 1)
+ background-color get-theme-var(theme, 'table-odd-backgroundColor')
+ tr:nth-child(2n)
+ background-color get-theme-var(theme, 'table-even-backgroundColor')
+ td
+ border-color get-theme-var(theme, 'table-borderColor')
+ &:last-child
+ border-right solid 1px get-theme-var(theme, 'table-borderColor')
+ kbd
+ background-color get-theme-var(theme, 'kbd-backgroundColor')
+ color get-theme-var(theme, 'kbd-color')
- pre.fence
- .gallery
- .carousel-main, .carousel-footer
- background-color $ui-solarized-dark-noteDetail-backgroundColor
- .prev, .next
- color $ui-solarized-dark-button--active-color
- background-color $ui-solarized-dark-button-backgroundColor
+ dl
+ border-color themeDarkBorder
+ background-color get-theme-var(theme, 'table-head-backgroundColor')
+ dt
+ border-color themeDarkBorder
+ dd
+ border-color themeDarkBorder
+ background-color get-theme-var(theme, 'noteDetail-backgroundColor')
-themeMonokaiTableOdd = $ui-monokai-noteDetail-backgroundColor
-themeMonokaiTableEven = darken($ui-monokai-noteDetail-backgroundColor, 10%)
-themeMonokaiTableHead = themeMonokaiTableEven
-themeMonokaiTableBorder = themeDarkBorder
+ pre.fence
+ .gallery
+ .carousel-main, .carousel-footer
+ background-color get-theme-var(theme, 'noteDetail-backgroundColor')
+ .prev, .next
+ color get-theme-var(theme, 'button--active-color')
+ background-color get-theme-var(theme, 'button-backgroundColor')
-body[data-theme="monokai"]
- color $ui-monokai-text-color
- border-color themeDarkBorder
- background-color $ui-monokai-noteDetail-backgroundColor
- table
- thead
- tr
- background-color themeMonokaiTableHead
- th
- border-color themeMonokaiTableBorder
- &:last-child
- border-right solid 1px themeMonokaiTableBorder
- tbody
- tr:nth-child(2n + 1)
- background-color themeMonokaiTableOdd
- tr:nth-child(2n)
- background-color themeMonokaiTableEven
- td
- border-color themeMonokaiTableBorder
- &:last-child
- border-right solid 1px themeMonokaiTableBorder
- kbd
- background-color themeDarkBackground
+ .markdownIt-TOC-wrapper
+ &,
+ &:before
+ background-color darken(get-theme-var(theme, 'noteDetail-backgroundColor'), 15%)
+ color themeDarkText
- dl
- border-color themeDarkBorder
- background-color themeMonokaiTableHead
- dt
- border-color themeDarkBorder
- dd
- border-color themeDarkBorder
- background-color $ui-monokai-noteDetail-backgroundColor
+for theme in 'solarized-dark' 'dracula'
+ apply-theme(theme)
- pre.fence
- .gallery
- .carousel-main, .carousel-footer
- background-color $ui-monokai-noteDetail-backgroundColor
- .prev, .next
- color $ui-monokai-button--active-color
- background-color $ui-monokai-button-backgroundColor
-
-themeDraculaTableOdd = $ui-dracula-noteDetail-backgroundColor
-themeDraculaTableEven = darken($ui-dracula-noteDetail-backgroundColor, 10%)
-themeDraculaTableHead = themeDraculaTableEven
-themeDraculaTableBorder = themeDarkBorder
-
-body[data-theme="dracula"]
- color $ui-dracula-text-color
- border-color themeDarkBorder
- background-color $ui-dracula-noteDetail-backgroundColor
- table
- thead
- tr
- background-color themeDraculaTableHead
- th
- border-color themeDraculaTableBorder
- &:last-child
- border-right solid 1px themeDraculaTableBorder
- tbody
- tr:nth-child(2n + 1)
- background-color themeDraculaTableOdd
- tr:nth-child(2n)
- background-color themeDraculaTableEven
- td
- border-color themeDraculaTableBorder
- &:last-child
- border-right solid 1px themeDraculaTableBorder
- kbd
- background-color themeDarkBackground
-
- dl
- border-color themeDarkBorder
- background-color themeDraculaTableHead
- dt
- border-color themeDarkBorder
- dd
- border-color themeDarkBorder
- background-color $ui-dracula-noteDetail-backgroundColor
-
- pre.fence
- .gallery
- .carousel-main, .carousel-footer
- background-color $ui-dracula-noteDetail-backgroundColor
- .prev, .next
- color $ui-dracula-button--active-color
- background-color $ui-dracula-button-backgroundColor
+for theme in $themes
+ apply-theme(theme)
diff --git a/browser/components/render/MermaidRender.js b/browser/components/render/MermaidRender.js
index d9ea549b..d397d03b 100644
--- a/browser/components/render/MermaidRender.js
+++ b/browser/components/render/MermaidRender.js
@@ -1,4 +1,5 @@
import mermaidAPI from 'mermaid'
+import uiThemes from 'browser/lib/ui-themes'
// fixes bad styling in the mermaid dark theme
const darkThemeStyling = `
@@ -6,11 +7,11 @@ const darkThemeStyling = `
fill: white;
}`
-function getRandomInt (min, max) {
+function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min
}
-function getId () {
+function getId() {
const pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
let id = 'm-'
for (let i = 0; i < 7; i++) {
@@ -19,21 +20,49 @@ function getId () {
return id
}
-function render (element, content, theme, enableHTMLLabel) {
+function render(element, content, theme, enableHTMLLabel) {
try {
const height = element.attributes.getNamedItem('data-height')
- if (height && height.value !== 'undefined') {
+ const isPredefined = height && height.value !== 'undefined'
+
+ if (isPredefined) {
element.style.height = height.value + 'vh'
}
- const isDarkTheme = theme === 'dark' || theme === 'solarized-dark' || theme === 'monokai' || theme === 'dracula'
+
+ const isDarkTheme = uiThemes.some(
+ item => item.name === theme && item.isDark
+ )
+
mermaidAPI.initialize({
theme: isDarkTheme ? 'dark' : 'default',
themeCSS: isDarkTheme ? darkThemeStyling : '',
- useMaxWidth: false,
- flowchart: { htmlLabels: enableHTMLLabel }
+ flowchart: {
+ htmlLabels: enableHTMLLabel
+ },
+ gantt: {
+ useWidth: element.clientWidth
+ }
})
- mermaidAPI.render(getId(), content, (svgGraph) => {
+
+ mermaidAPI.render(getId(), content, svgGraph => {
element.innerHTML = svgGraph
+
+ if (!isPredefined) {
+ const el = element.firstChild
+ const viewBox = el.getAttribute('viewBox').split(' ')
+
+ let ratio = viewBox[2] / viewBox[3]
+
+ if (el.style.maxWidth) {
+ const maxWidth = parseFloat(el.style.maxWidth)
+
+ ratio *= el.parentNode.clientWidth / maxWidth
+ }
+
+ el.setAttribute('ratio', ratio)
+ el.setAttribute('height', el.parentNode.clientWidth / ratio)
+ console.log(el)
+ }
})
} catch (e) {
element.className = 'mermaid-error'
diff --git a/browser/finder/NoteDetail.js b/browser/finder/NoteDetail.js
deleted file mode 100644
index e69de29b..00000000
diff --git a/browser/lib/CSSModules.js b/browser/lib/CSSModules.js
index 691b44d2..c05a56f0 100644
--- a/browser/lib/CSSModules.js
+++ b/browser/lib/CSSModules.js
@@ -1,5 +1,5 @@
import CSSModules from 'react-css-modules'
-export default function (component, styles) {
- return CSSModules(component, styles, {handleNotFoundStyleName: 'log'})
+export default function(component, styles) {
+ return CSSModules(component, styles, { handleNotFoundStyleName: 'log' })
}
diff --git a/browser/lib/Languages.js b/browser/lib/Languages.js
index 435747a9..6367bec4 100644
--- a/browser/lib/Languages.js
+++ b/browser/lib/Languages.js
@@ -11,6 +11,10 @@ const languages = [
name: 'Chinese (zh-TW)',
locale: 'zh-TW'
},
+ {
+ name: 'Czech',
+ locale: 'cs'
+ },
{
name: 'Danish',
locale: 'da'
@@ -74,13 +78,13 @@ const languages = [
]
module.exports = {
- getLocales () {
- return languages.reduce(function (localeList, locale) {
+ getLocales() {
+ return languages.reduce(function(localeList, locale) {
localeList.push(locale.locale)
return localeList
}, [])
},
- getLanguages () {
+ getLanguages() {
return languages
}
}
diff --git a/browser/lib/Mutable.js b/browser/lib/Mutable.js
index 0ae2d9cf..7c376ef1 100644
--- a/browser/lib/Mutable.js
+++ b/browser/lib/Mutable.js
@@ -1,43 +1,43 @@
class MutableMap {
- constructor (iterable) {
+ constructor(iterable) {
this._map = new Map(iterable)
Object.defineProperty(this, 'size', {
get: () => this._map.size,
- set: function (value) {
+ set: function(value) {
this['size'] = value
}
})
}
- get (...args) {
+ get(...args) {
return this._map.get(...args)
}
- set (...args) {
+ set(...args) {
return this._map.set(...args)
}
- delete (...args) {
+ delete(...args) {
return this._map.delete(...args)
}
- has (...args) {
+ has(...args) {
return this._map.has(...args)
}
- clear (...args) {
+ clear(...args) {
return this._map.clear(...args)
}
- forEach (...args) {
+ forEach(...args) {
return this._map.forEach(...args)
}
- [Symbol.iterator] () {
+ [Symbol.iterator]() {
return this._map[Symbol.iterator]()
}
- map (cb) {
+ map(cb) {
const result = []
for (const [key, value] of this._map) {
result.push(cb(value, key))
@@ -45,7 +45,7 @@ class MutableMap {
return result
}
- toJS () {
+ toJS() {
const result = {}
for (let [key, value] of this._map) {
if (value instanceof MutableSet || value instanceof MutableMap) {
@@ -58,42 +58,42 @@ class MutableMap {
}
class MutableSet {
- constructor (iterable) {
+ constructor(iterable) {
this._set = new Set(iterable)
Object.defineProperty(this, 'size', {
get: () => this._set.size,
- set: function (value) {
+ set: function(value) {
this['size'] = value
}
})
}
- add (...args) {
+ add(...args) {
return this._set.add(...args)
}
- delete (...args) {
+ delete(...args) {
return this._set.delete(...args)
}
- forEach (...args) {
+ forEach(...args) {
return this._set.forEach(...args)
}
- [Symbol.iterator] () {
+ [Symbol.iterator]() {
return this._set[Symbol.iterator]()
}
- map (cb) {
+ map(cb) {
const result = []
- this._set.forEach(function (value, key) {
+ this._set.forEach(function(value, key) {
result.push(cb(value, key))
})
return result
}
- toJS () {
+ toJS() {
return Array.from(this._set)
}
}
diff --git a/browser/lib/RcParser.js b/browser/lib/RcParser.js
index 0df59476..e8eb90c4 100644
--- a/browser/lib/RcParser.js
+++ b/browser/lib/RcParser.js
@@ -5,13 +5,13 @@ const BOOSTNOTERC = '.boostnoterc'
const homePath = global.process.env.HOME || global.process.env.USERPROFILE
const _boostnotercPath = path.join(homePath, BOOSTNOTERC)
-export function parse (boostnotercPath = _boostnotercPath) {
+export function parse(boostnotercPath = _boostnotercPath) {
if (!sander.existsSync(boostnotercPath)) return {}
try {
return JSON.parse(sander.readFileSync(boostnotercPath).toString())
} catch (e) {
console.warn(e)
- console.warn('Your .boostnoterc is broken so it\'s not used.')
+ console.warn("Your .boostnoterc is broken so it's not used.")
return {}
}
}
diff --git a/browser/lib/SnippetManager.js b/browser/lib/SnippetManager.js
index 70f9b400..a167f1e0 100644
--- a/browser/lib/SnippetManager.js
+++ b/browser/lib/SnippetManager.js
@@ -3,13 +3,14 @@ import fs from 'fs'
import consts from './consts'
class SnippetManager {
- constructor () {
+ constructor() {
this.defaultSnippet = [
{
id: crypto.randomBytes(16).toString('hex'),
name: 'Dummy text',
prefix: ['lorem', 'ipsum'],
- content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
+ content:
+ 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
}
]
this.snippets = []
@@ -18,7 +19,7 @@ class SnippetManager {
this.assignSnippets = this.assignSnippets.bind(this)
}
- init () {
+ init() {
if (fs.existsSync(consts.SNIPPET_FILE)) {
try {
this.snippets = JSON.parse(
@@ -37,11 +38,11 @@ class SnippetManager {
this.snippets = this.defaultSnippet
}
- assignSnippets (snippets) {
+ assignSnippets(snippets) {
this.snippets = snippets
}
- expandSnippet (wordBeforeCursor, cursor, cm) {
+ expandSnippet(wordBeforeCursor, cursor, cm) {
const templateCursorString = ':{}'
for (let i = 0; i < this.snippets.length; i++) {
if (this.snippets[i].prefix.indexOf(wordBeforeCursor.text) === -1) {
diff --git a/browser/lib/TextEditorInterface.js b/browser/lib/TextEditorInterface.js
index 55f2c29d..18795197 100644
--- a/browser/lib/TextEditorInterface.js
+++ b/browser/lib/TextEditorInterface.js
@@ -1,44 +1,44 @@
import { Point } from '@susisu/mte-kernel'
export default class TextEditorInterface {
- constructor (editor) {
+ constructor(editor) {
this.editor = editor
this.doc = editor.getDoc()
this.transaction = false
}
- getCursorPosition () {
+ getCursorPosition() {
const { line, ch } = this.doc.getCursor()
return new Point(line, ch)
}
- setCursorPosition (pos) {
+ setCursorPosition(pos) {
this.doc.setCursor({
line: pos.row,
ch: pos.column
})
}
- setSelectionRange (range) {
+ setSelectionRange(range) {
this.doc.setSelection(
{ line: range.start.row, ch: range.start.column },
{ line: range.end.row, ch: range.end.column }
)
}
- getLastRow () {
+ getLastRow() {
return this.doc.lineCount() - 1
}
- acceptsTableEdit () {
+ acceptsTableEdit() {
return true
}
- getLine (row) {
+ getLine(row) {
return this.doc.getLine(row)
}
- insertLine (row, line) {
+ insertLine(row, line) {
const lastRow = this.getLastRow()
if (row > lastRow) {
const lastLine = this.getLine(lastRow)
@@ -56,7 +56,7 @@ export default class TextEditorInterface {
}
}
- deleteLine (row) {
+ deleteLine(row) {
const lastRow = this.getLastRow()
if (row >= lastRow) {
if (lastRow > 0) {
@@ -76,15 +76,11 @@ export default class TextEditorInterface {
)
}
} else {
- this.doc.replaceRange(
- '',
- { line: row, ch: 0 },
- { line: row + 1, ch: 0 }
- )
+ this.doc.replaceRange('', { line: row, ch: 0 }, { line: row + 1, ch: 0 })
}
}
- replaceLines (startRow, endRow, lines) {
+ replaceLines(startRow, endRow, lines) {
const lastRow = this.getLastRow()
if (endRow > lastRow) {
const lastLine = this.getLine(lastRow)
@@ -102,7 +98,7 @@ export default class TextEditorInterface {
}
}
- transact (func) {
+ transact(func) {
this.transaction = true
func()
this.transaction = false
diff --git a/browser/lib/confirmDeleteNote.js b/browser/lib/confirmDeleteNote.js
index 80d1ffc7..c9400daa 100644
--- a/browser/lib/confirmDeleteNote.js
+++ b/browser/lib/confirmDeleteNote.js
@@ -3,17 +3,18 @@ import i18n from 'browser/lib/i18n'
const { remote } = electron
const { dialog } = remote
-export function confirmDeleteNote (confirmDeletion, permanent) {
+export function confirmDeleteNote(confirmDeletion, permanent) {
if (confirmDeletion || permanent) {
const alertConfig = {
- ype: 'warning',
+ type: 'warning',
message: i18n.__('Confirm note deletion'),
detail: i18n.__('This will permanently remove this note.'),
buttons: [i18n.__('Confirm'), i18n.__('Cancel')]
}
const dialogButtonIndex = dialog.showMessageBox(
- remote.getCurrentWindow(), alertConfig
+ remote.getCurrentWindow(),
+ alertConfig
)
return dialogButtonIndex === 0
diff --git a/browser/lib/consts.js b/browser/lib/consts.js
index ed497376..07c81b03 100644
--- a/browser/lib/consts.js
+++ b/browser/lib/consts.js
@@ -9,41 +9,53 @@ const CODEMIRROR_EXTRA_THEME_PATH = 'extra_scripts/codemirror/theme'
const isProduction = process.env.NODE_ENV === 'production'
const paths = [
- isProduction ? path.join(app.getAppPath(), CODEMIRROR_THEME_PATH) : path.resolve(CODEMIRROR_THEME_PATH),
- isProduction ? path.join(app.getAppPath(), CODEMIRROR_EXTRA_THEME_PATH) : path.resolve(CODEMIRROR_EXTRA_THEME_PATH)
+ isProduction
+ ? path.join(app.getAppPath(), CODEMIRROR_THEME_PATH)
+ : path.resolve(CODEMIRROR_THEME_PATH),
+ isProduction
+ ? path.join(app.getAppPath(), CODEMIRROR_EXTRA_THEME_PATH)
+ : path.resolve(CODEMIRROR_EXTRA_THEME_PATH)
]
const themes = paths
- .map(directory => fs.readdirSync(directory).map(file => {
- const name = file.substring(0, file.lastIndexOf('.'))
+ .map(directory =>
+ fs.readdirSync(directory).map(file => {
+ const name = file.substring(0, file.lastIndexOf('.'))
- return {
- name,
- path: path.join(directory, file),
- className: `cm-s-${name}`
- }
- }))
+ return {
+ name,
+ path: path.join(directory, file),
+ className: `cm-s-${name}`
+ }
+ })
+ )
.reduce((accumulator, value) => accumulator.concat(value), [])
.sort((a, b) => a.name.localeCompare(b.name))
-themes.splice(themes.findIndex(({ name }) => name === 'solarized'), 1, {
- name: 'solarized dark',
- path: path.join(paths[0], 'solarized.css'),
- className: `cm-s-solarized cm-s-dark`
-}, {
- name: 'solarized light',
- path: path.join(paths[0], 'solarized.css'),
- className: `cm-s-solarized cm-s-light`
-})
+themes.splice(
+ themes.findIndex(({ name }) => name === 'solarized'),
+ 1,
+ {
+ name: 'solarized dark',
+ path: path.join(paths[0], 'solarized.css'),
+ className: `cm-s-solarized cm-s-dark`
+ },
+ {
+ name: 'solarized light',
+ path: path.join(paths[0], 'solarized.css'),
+ className: `cm-s-solarized cm-s-light`
+ }
+)
themes.splice(0, 0, {
name: 'default',
path: path.join(paths[0], 'elegant.css'),
className: `cm-s-default`
})
-const snippetFile = process.env.NODE_ENV !== 'test'
- ? path.join(app.getPath('userData'), 'snippets.json')
- : '' // return nothing as we specified different path to snippets.json in test
+const snippetFile =
+ process.env.NODE_ENV !== 'test'
+ ? path.join(app.getPath('userData'), 'snippets.json')
+ : '' // return nothing as we specified different path to snippets.json in test
const consts = {
FOLDER_COLORS: [
diff --git a/browser/lib/context.js b/browser/lib/context.js
index 6c82e6a2..a89628e5 100644
--- a/browser/lib/context.js
+++ b/browser/lib/context.js
@@ -1,9 +1,9 @@
const { remote } = require('electron')
const { Menu, MenuItem } = remote
-function popup (templates) {
+function popup(templates) {
const menu = new Menu()
- templates.forEach((item) => {
+ templates.forEach(item => {
menu.append(new MenuItem(item))
})
menu.popup(remote.getCurrentWindow())
diff --git a/browser/lib/contextMenuBuilder.js b/browser/lib/contextMenuBuilder.js
index ff3349eb..6eee85da 100644
--- a/browser/lib/contextMenuBuilder.js
+++ b/browser/lib/contextMenuBuilder.js
@@ -1,10 +1,10 @@
import i18n from 'browser/lib/i18n'
import fs from 'fs'
-const {remote} = require('electron')
-const {Menu} = remote.require('electron')
-const {clipboard} = remote.require('electron')
-const {shell} = remote.require('electron')
+const { remote } = require('electron')
+const { Menu } = remote.require('electron')
+const { clipboard } = remote.require('electron')
+const { shell } = remote.require('electron')
const spellcheck = require('./spellcheck')
const uri2path = require('file-uri-to-path')
@@ -16,11 +16,16 @@ const uri2path = require('file-uri-to-path')
* @param {MouseEvent} event that has triggered the creation of the context menu
* @returns {Electron.Menu} The created electron context menu
*/
-const buildEditorContextMenu = function (editor, event) {
- if (editor == null || event == null || event.pageX == null || event.pageY == null) {
+const buildEditorContextMenu = function(editor, event) {
+ if (
+ editor == null ||
+ event == null ||
+ event.pageX == null ||
+ event.pageY == null
+ ) {
return null
}
- const cursor = editor.coordsChar({left: event.pageX, top: event.pageY})
+ const cursor = editor.coordsChar({ left: event.pageX, top: event.pageY })
const wordRange = editor.findWordAt(cursor)
const word = editor.getRange(wordRange.anchor, wordRange.head)
const existingMarks = editor.findMarks(wordRange.anchor, wordRange.head) || []
@@ -40,30 +45,44 @@ const buildEditorContextMenu = function (editor, event) {
isMisspelled: isMisspelled,
spellingSuggestions: suggestion
}
- const template = [{
- role: 'cut'
- }, {
- role: 'copy'
- }, {
- role: 'paste'
- }, {
- role: 'selectall'
- }]
+ const template = [
+ {
+ role: 'cut'
+ },
+ {
+ role: 'copy'
+ },
+ {
+ role: 'paste'
+ },
+ {
+ role: 'selectall'
+ }
+ ]
if (selection.isMisspelled) {
const suggestions = selection.spellingSuggestions
- template.unshift.apply(template, suggestions.map(function (suggestion) {
- return {
- label: suggestion,
- click: function (suggestion) {
- if (editor != null) {
- editor.replaceRange(suggestion.label, wordRange.anchor, wordRange.head)
+ template.unshift.apply(
+ template,
+ suggestions
+ .map(function(suggestion) {
+ return {
+ label: suggestion,
+ click: function(suggestion) {
+ if (editor != null) {
+ editor.replaceRange(
+ suggestion.label,
+ wordRange.anchor,
+ wordRange.head
+ )
+ }
+ }
}
- }
- }
- }).concat({
- type: 'separator'
- }))
+ })
+ .concat({
+ type: 'separator'
+ })
+ )
}
return Menu.buildFromTemplate(template)
}
@@ -74,19 +93,30 @@ const buildEditorContextMenu = function (editor, event) {
* @param {MouseEvent} event that has triggered the creation of the context menu
* @returns {Electron.Menu} The created electron context menu
*/
-const buildMarkdownPreviewContextMenu = function (markdownPreview, event) {
- if (markdownPreview == null || event == null || event.pageX == null || event.pageY == null) {
+const buildMarkdownPreviewContextMenu = function(markdownPreview, event) {
+ if (
+ markdownPreview == null ||
+ event == null ||
+ event.pageX == null ||
+ event.pageY == null
+ ) {
return null
}
// Default context menu inclusions
- const template = [{
- role: 'copy'
- }, {
- role: 'selectall'
- }]
+ const template = [
+ {
+ role: 'copy'
+ },
+ {
+ role: 'selectall'
+ }
+ ]
- if (event.target.tagName.toLowerCase() === 'a' && event.target.getAttribute('href')) {
+ if (
+ event.target.tagName.toLowerCase() === 'a' &&
+ event.target.getAttribute('href')
+ ) {
// Link opener for files on the local system pointed to by href
const href = event.target.href
const isLocalFile = href.startsWith('file:')
@@ -94,31 +124,29 @@ const buildMarkdownPreviewContextMenu = function (markdownPreview, event) {
const absPath = uri2path(href)
try {
if (fs.lstatSync(absPath).isFile()) {
- template.push(
- {
- label: i18n.__('Show in explorer'),
- click: (e) => shell.showItemInFolder(absPath)
- }
- )
+ template.push({
+ label: i18n.__('Show in explorer'),
+ click: e => shell.showItemInFolder(absPath)
+ })
}
} catch (e) {
- console.log('Error while evaluating if the file is locally available', e)
+ console.log(
+ 'Error while evaluating if the file is locally available',
+ e
+ )
}
}
// Add option to context menu to copy url
- template.push(
- {
- label: i18n.__('Copy Url'),
- click: (e) => clipboard.writeText(href)
- }
- )
+ template.push({
+ label: i18n.__('Copy Url'),
+ click: e => clipboard.writeText(href)
+ })
}
return Menu.buildFromTemplate(template)
}
-module.exports =
-{
+module.exports = {
buildEditorContextMenu: buildEditorContextMenu,
buildMarkdownPreviewContextMenu: buildMarkdownPreviewContextMenu
}
diff --git a/browser/lib/convertModeName.js b/browser/lib/convertModeName.js
index b0431059..a0a31f76 100644
--- a/browser/lib/convertModeName.js
+++ b/browser/lib/convertModeName.js
@@ -1,4 +1,4 @@
-export default function convertModeName (name) {
+export default function convertModeName(name) {
switch (name) {
case 'ejs':
return 'Embedded Javascript'
diff --git a/browser/lib/customMeta.js b/browser/lib/customMeta.js
index b890cf55..33296471 100644
--- a/browser/lib/customMeta.js
+++ b/browser/lib/customMeta.js
@@ -3,8 +3,19 @@ import 'codemirror-mode-elixir'
const stylusCodeInfo = CodeMirror.modeInfo.find(info => info.name === 'Stylus')
if (stylusCodeInfo == null) {
- CodeMirror.modeInfo.push({name: 'Stylus', mime: 'text/x-styl', mode: 'stylus', ext: ['styl'], alias: ['styl']})
+ CodeMirror.modeInfo.push({
+ name: 'Stylus',
+ mime: 'text/x-styl',
+ mode: 'stylus',
+ ext: ['styl'],
+ alias: ['styl']
+ })
} else {
stylusCodeInfo.alias = ['styl']
}
-CodeMirror.modeInfo.push({name: 'Elixir', mime: 'text/x-elixir', mode: 'elixir', ext: ['ex']})
+CodeMirror.modeInfo.push({
+ name: 'Elixir',
+ mime: 'text/x-elixir',
+ mode: 'elixir',
+ ext: ['ex']
+})
diff --git a/browser/lib/date-formatter.js b/browser/lib/date-formatter.js
index 8f74fe4d..0ced141a 100644
--- a/browser/lib/date-formatter.js
+++ b/browser/lib/date-formatter.js
@@ -8,7 +8,7 @@ import moment from 'moment'
* @param {mixed}
* @return {string}
*/
-export function formatDate (date) {
+export function formatDate(date) {
const m = moment(date)
if (!m.isValid()) {
throw Error('Invalid argument.')
diff --git a/browser/lib/findNoteTitle.js b/browser/lib/findNoteTitle.js
index 912c3bdd..01ef56d1 100644
--- a/browser/lib/findNoteTitle.js
+++ b/browser/lib/findNoteTitle.js
@@ -1,4 +1,8 @@
-export function findNoteTitle (value, enableFrontMatterTitle, frontMatterTitleField = 'title') {
+export function findNoteTitle(
+ value,
+ enableFrontMatterTitle,
+ frontMatterTitleField = 'title'
+) {
const splitted = value.split('\n')
let title = null
let isInsideCodeBlock = false
@@ -6,8 +10,13 @@ export function findNoteTitle (value, enableFrontMatterTitle, frontMatterTitleFi
if (splitted[0] === '---') {
let line = 0
while (++line < splitted.length) {
- if (enableFrontMatterTitle && splitted[line].startsWith(frontMatterTitleField + ':')) {
- title = splitted[line].substring(frontMatterTitleField.length + 1).trim()
+ if (
+ enableFrontMatterTitle &&
+ splitted[line].startsWith(frontMatterTitleField + ':')
+ ) {
+ title = splitted[line]
+ .substring(frontMatterTitleField.length + 1)
+ .trim()
break
}
@@ -22,11 +31,15 @@ export function findNoteTitle (value, enableFrontMatterTitle, frontMatterTitleFi
if (title === null) {
splitted.some((line, index) => {
const trimmedLine = line.trim()
- const trimmedNextLine = splitted[index + 1] === undefined ? '' : splitted[index + 1].trim()
+ const trimmedNextLine =
+ splitted[index + 1] === undefined ? '' : splitted[index + 1].trim()
if (trimmedLine.match('```')) {
isInsideCodeBlock = !isInsideCodeBlock
}
- if (isInsideCodeBlock === false && (trimmedLine.match(/^# +/) || trimmedNextLine.match(/^=+$/))) {
+ if (
+ isInsideCodeBlock === false &&
+ (trimmedLine.match(/^# +/) || trimmedNextLine.match(/^=+$/))
+ ) {
title = trimmedLine
return true
}
@@ -35,7 +48,7 @@ export function findNoteTitle (value, enableFrontMatterTitle, frontMatterTitleFi
if (title === null) {
title = ''
- splitted.some((line) => {
+ splitted.some(line => {
if (line.trim().length > 0) {
title = line.trim()
return true
diff --git a/browser/lib/findStorage.js b/browser/lib/findStorage.js
index 98d48236..7753dc87 100644
--- a/browser/lib/findStorage.js
+++ b/browser/lib/findStorage.js
@@ -1,10 +1,11 @@
const _ = require('lodash')
-export function findStorage (storageKey) {
+export function findStorage(storageKey) {
const cachedStorageList = JSON.parse(localStorage.getItem('storages'))
- if (!_.isArray(cachedStorageList)) throw new Error('Target storage doesn\'t exist.')
- const storage = _.find(cachedStorageList, {key: storageKey})
- if (storage === undefined) throw new Error('Target storage doesn\'t exist.')
+ if (!_.isArray(cachedStorageList))
+ throw new Error("Target storage doesn't exist.")
+ const storage = _.find(cachedStorageList, { key: storageKey })
+ if (storage === undefined) throw new Error("Target storage doesn't exist.")
return storage
}
diff --git a/browser/lib/getTodoStatus.js b/browser/lib/getTodoStatus.js
index 8b552109..2522a16a 100644
--- a/browser/lib/getTodoStatus.js
+++ b/browser/lib/getTodoStatus.js
@@ -1,9 +1,9 @@
-export function getTodoStatus (content) {
+export function getTodoStatus(content) {
const splitted = content.split('\n')
let numberOfTodo = 0
let numberOfCompletedTodo = 0
- splitted.forEach((line) => {
+ splitted.forEach(line => {
const trimmedLine = line.trim().replace(/^(>\s*)*/, '')
if (trimmedLine.match(/^[+\-*] \[(\s|x)] ./i)) {
numberOfTodo++
@@ -19,7 +19,7 @@ export function getTodoStatus (content) {
}
}
-export function getTodoPercentageOfCompleted (content) {
+export function getTodoPercentageOfCompleted(content) {
const state = getTodoStatus(content)
- return Math.floor(state.completed / state.total * 100)
+ return Math.floor((state.completed / state.total) * 100)
}
diff --git a/browser/lib/htmlTextHelper.js b/browser/lib/htmlTextHelper.js
index ccc545e3..e3e0c0e3 100644
--- a/browser/lib/htmlTextHelper.js
+++ b/browser/lib/htmlTextHelper.js
@@ -7,9 +7,9 @@
* @return {string}
*/
-export function decodeEntities (text) {
+export function decodeEntities(text) {
var entities = [
- ['apos', '\''],
+ ['apos', "'"],
['amp', '&'],
['lt', '<'],
['gt', '>'],
@@ -24,16 +24,16 @@ export function decodeEntities (text) {
return text
}
-export function encodeEntities (text) {
+export function encodeEntities(text) {
const entities = [
- ['\'', 'apos'],
+ ["'", 'apos'],
['<', 'lt'],
['>', 'gt'],
['\\?', '#63'],
['\\$', '#36']
]
- entities.forEach((entity) => {
+ entities.forEach(entity => {
text = text.replace(new RegExp(entity[0], 'g'), `&${entity[1]};`)
})
return text
diff --git a/browser/lib/i18n.js b/browser/lib/i18n.js
index e12e2aa6..ad59cc23 100644
--- a/browser/lib/i18n.js
+++ b/browser/lib/i18n.js
@@ -8,9 +8,10 @@ const i18n = new (require('i18n-2'))({
// setup some locales - other locales default to the first locale
locales: getLocales(),
extension: '.json',
- directory: process.env.NODE_ENV === 'production'
- ? path.join(app.getAppPath(), './locales')
- : path.resolve('./locales'),
+ directory:
+ process.env.NODE_ENV === 'production'
+ ? path.join(app.getAppPath(), './locales')
+ : path.resolve('./locales'),
devMode: false
})
diff --git a/browser/lib/keygen.js b/browser/lib/keygen.js
index 557a8a40..81c8a868 100644
--- a/browser/lib/keygen.js
+++ b/browser/lib/keygen.js
@@ -1,7 +1,7 @@
const crypto = require('crypto')
const uuidv4 = require('uuid/v4')
-module.exports = function (uuid) {
+module.exports = function(uuid) {
if (typeof uuid === typeof true && uuid) {
return uuidv4()
}
diff --git a/browser/lib/markdown-it-deflist.js b/browser/lib/markdown-it-deflist.js
index db14c636..a6b30f48 100644
--- a/browser/lib/markdown-it-deflist.js
+++ b/browser/lib/markdown-it-deflist.js
@@ -1,35 +1,44 @@
'use strict'
-module.exports = function definitionListPlugin (md) {
+module.exports = function definitionListPlugin(md) {
var isSpace = md.utils.isSpace
// Search `[:~][\n ]`, returns next pos after marker on success
// or -1 on fail.
- function skipMarker (state, line) {
+ function skipMarker(state, line) {
let start = state.bMarks[line] + state.tShift[line]
const max = state.eMarks[line]
- if (start >= max) { return -1 }
+ if (start >= max) {
+ return -1
+ }
// Check bullet
const marker = state.src.charCodeAt(start++)
- if (marker !== 0x7E/* ~ */ && marker !== 0x3A/* : */) { return -1 }
+ if (marker !== 0x7e /* ~ */ && marker !== 0x3a /* : */) {
+ return -1
+ }
const pos = state.skipSpaces(start)
// require space after ":"
- if (start === pos) { return -1 }
+ if (start === pos) {
+ return -1
+ }
return start
}
- function markTightParagraphs (state, idx) {
+ function markTightParagraphs(state, idx) {
const level = state.level + 2
let i
let l
for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {
- if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {
+ if (
+ state.tokens[i].level === level &&
+ state.tokens[i].type === 'paragraph_open'
+ ) {
state.tokens[i + 2].hidden = true
state.tokens[i].hidden = true
i += 2
@@ -37,7 +46,7 @@ module.exports = function definitionListPlugin (md) {
}
}
- function deflist (state, startLine, endLine, silent) {
+ function deflist(state, startLine, endLine, silent) {
var ch,
contentStart,
ddLine,
@@ -63,28 +72,38 @@ module.exports = function definitionListPlugin (md) {
if (silent) {
// quirk: validation mode validates a dd block only, not a whole deflist
- if (state.ddIndent < 0) { return false }
+ if (state.ddIndent < 0) {
+ return false
+ }
return skipMarker(state, startLine) >= 0
}
nextLine = startLine + 1
- if (nextLine >= endLine) { return false }
+ if (nextLine >= endLine) {
+ return false
+ }
if (state.isEmpty(nextLine)) {
nextLine++
- if (nextLine >= endLine) { return false }
+ if (nextLine >= endLine) {
+ return false
+ }
}
- if (state.sCount[nextLine] < state.blkIndent) { return false }
+ if (state.sCount[nextLine] < state.blkIndent) {
+ return false
+ }
contentStart = skipMarker(state, nextLine)
- if (contentStart < 0) { return false }
+ if (contentStart < 0) {
+ return false
+ }
// Start list
listTokIdx = state.tokens.length
tight = true
token = state.push('dl_open', 'dl', 1)
- token.map = listLines = [ startLine, 0 ]
+ token.map = listLines = [startLine, 0]
//
// Iterate list items
@@ -100,34 +119,38 @@ module.exports = function definitionListPlugin (md) {
// needed to break out of the second one
//
/* eslint no-labels:0,block-scoped-var:0 */
- OUTER:
- for (;;) {
+ OUTER: for (;;) {
prevEmptyEnd = false
token = state.push('dt_open', 'dt', 1)
- token.map = [ dtLine, dtLine ]
+ token.map = [dtLine, dtLine]
token = state.push('inline', '', 0)
- token.map = [ dtLine, dtLine ]
- token.content = state.getLines(dtLine, dtLine + 1, state.blkIndent, false).trim()
+ token.map = [dtLine, dtLine]
+ token.content = state
+ .getLines(dtLine, dtLine + 1, state.blkIndent, false)
+ .trim()
token.children = []
token = state.push('dt_close', 'dt', -1)
for (;;) {
token = state.push('dd_open', 'dd', 1)
- token.map = itemLines = [ ddLine, 0 ]
+ token.map = itemLines = [ddLine, 0]
pos = contentStart
max = state.eMarks[ddLine]
- offset = state.sCount[ddLine] + contentStart - (state.bMarks[ddLine] + state.tShift[ddLine])
+ offset =
+ state.sCount[ddLine] +
+ contentStart -
+ (state.bMarks[ddLine] + state.tShift[ddLine])
while (pos < max) {
ch = state.src.charCodeAt(pos)
if (isSpace(ch)) {
if (ch === 0x09) {
- offset += 4 - offset % 4
+ offset += 4 - (offset % 4)
} else {
offset++
}
@@ -153,8 +176,11 @@ module.exports = function definitionListPlugin (md) {
state.parentType = 'deflist'
newEndLine = ddLine
- while (++newEndLine < endLine && (state.sCount[newEndLine] >= state.sCount[ddLine] || state.isEmpty(newEndLine))) {
- }
+ while (
+ ++newEndLine < endLine &&
+ (state.sCount[newEndLine] >= state.sCount[ddLine] ||
+ state.isEmpty(newEndLine))
+ ) {}
oldLineMax = state.lineMax
state.lineMax = newEndLine
@@ -169,7 +195,7 @@ module.exports = function definitionListPlugin (md) {
}
// Item become loose if finish with empty line,
// but we should filter last element, because it means list finish
- prevEmptyEnd = (state.line - ddLine) > 1 && state.isEmpty(state.line - 1)
+ prevEmptyEnd = state.line - ddLine > 1 && state.isEmpty(state.line - 1)
state.tShift[ddLine] = oldTShift
state.sCount[ddLine] = oldSCount
@@ -182,11 +208,17 @@ module.exports = function definitionListPlugin (md) {
itemLines[1] = nextLine = state.line
- if (nextLine >= endLine) { break OUTER }
+ if (nextLine >= endLine) {
+ break OUTER
+ }
- if (state.sCount[nextLine] < state.blkIndent) { break OUTER }
+ if (state.sCount[nextLine] < state.blkIndent) {
+ break OUTER
+ }
contentStart = skipMarker(state, nextLine)
- if (contentStart < 0) { break }
+ if (contentStart < 0) {
+ break
+ }
ddLine = nextLine
@@ -194,20 +226,36 @@ module.exports = function definitionListPlugin (md) {
// insert DD tag and repeat checking
}
- if (nextLine >= endLine) { break }
+ if (nextLine >= endLine) {
+ break
+ }
dtLine = nextLine
- if (state.isEmpty(dtLine)) { break }
- if (state.sCount[dtLine] < state.blkIndent) { break }
+ if (state.isEmpty(dtLine)) {
+ break
+ }
+ if (state.sCount[dtLine] < state.blkIndent) {
+ break
+ }
ddLine = dtLine + 1
- if (ddLine >= endLine) { break }
- if (state.isEmpty(ddLine)) { ddLine++ }
- if (ddLine >= endLine) { break }
+ if (ddLine >= endLine) {
+ break
+ }
+ if (state.isEmpty(ddLine)) {
+ ddLine++
+ }
+ if (ddLine >= endLine) {
+ break
+ }
- if (state.sCount[ddLine] < state.blkIndent) { break }
+ if (state.sCount[ddLine] < state.blkIndent) {
+ break
+ }
contentStart = skipMarker(state, ddLine)
- if (contentStart < 0) { break }
+ if (contentStart < 0) {
+ break
+ }
// go to the next loop iteration:
// insert DT and DD tags and repeat checking
@@ -228,5 +276,7 @@ module.exports = function definitionListPlugin (md) {
return true
}
- md.block.ruler.before('paragraph', 'deflist', deflist, { alt: [ 'paragraph', 'reference' ] })
+ md.block.ruler.before('paragraph', 'deflist', deflist, {
+ alt: ['paragraph', 'reference']
+ })
}
diff --git a/browser/lib/markdown-it-fence.js b/browser/lib/markdown-it-fence.js
index f2f7e999..1346a122 100644
--- a/browser/lib/markdown-it-fence.js
+++ b/browser/lib/markdown-it-fence.js
@@ -1,9 +1,9 @@
'use strict'
-module.exports = function (md, renderers, defaultRenderer) {
+module.exports = function(md, renderers, defaultRenderer) {
const paramsRE = /^[ \t]*([\w+#-]+)?(?:\(((?:\s*\w[-\w]*(?:=(?:'(?:.*?[^\\])?'|"(?:.*?[^\\])?"|(?:[^'"][^\s]*)))?)*)\))?(?::([^:]*)(?::(\d+))?)?\s*$/
- function fence (state, startLine, endLine, silent) {
+ function fence(state, startLine, endLine, silent) {
let pos = state.bMarks[startLine] + state.tShift[startLine]
let max = state.eMarks[startLine]
@@ -12,7 +12,7 @@ module.exports = function (md, renderers, defaultRenderer) {
}
const marker = state.src.charCodeAt(pos)
- if (marker !== 0x7E/* ~ */ && marker !== 0x60 /* ` */) {
+ if (marker !== 0x7e /* ~ */ && marker !== 0x60 /* ` */) {
return false
}
@@ -46,7 +46,10 @@ module.exports = function (md, renderers, defaultRenderer) {
if (pos < max && state.sCount[nextLine] < state.blkIndent) {
break
}
- if (state.src.charCodeAt(pos) !== marker || state.sCount[nextLine] - state.blkIndent >= 4) {
+ if (
+ state.src.charCodeAt(pos) !== marker ||
+ state.sCount[nextLine] - state.blkIndent >= 4
+ ) {
continue
}
@@ -127,10 +130,12 @@ module.exports = function (md, renderers, defaultRenderer) {
})
for (const name in renderers) {
- md.renderer.rules[`${name}_fence`] = (tokens, index) => renderers[name](tokens[index])
+ md.renderer.rules[`${name}_fence`] = (tokens, index) =>
+ renderers[name](tokens[index])
}
if (defaultRenderer) {
- md.renderer.rules['_fence'] = (tokens, index) => defaultRenderer(tokens[index])
+ md.renderer.rules['_fence'] = (tokens, index) =>
+ defaultRenderer(tokens[index])
}
}
diff --git a/browser/lib/markdown-it-frontmatter.js b/browser/lib/markdown-it-frontmatter.js
index 66d8ce89..f101dd73 100644
--- a/browser/lib/markdown-it-frontmatter.js
+++ b/browser/lib/markdown-it-frontmatter.js
@@ -1,14 +1,19 @@
'use strict'
-module.exports = function frontMatterPlugin (md) {
- function frontmatter (state, startLine, endLine, silent) {
- if (startLine !== 0 || state.src.substr(startLine, state.eMarks[0]) !== '---') {
+module.exports = function frontMatterPlugin(md) {
+ function frontmatter(state, startLine, endLine, silent) {
+ if (
+ startLine !== 0 ||
+ state.src.substr(startLine, state.eMarks[0]) !== '---'
+ ) {
return false
}
let line = 0
while (++line < state.lineMax) {
- if (state.src.substring(state.bMarks[line], state.eMarks[line]) === '---') {
+ if (
+ state.src.substring(state.bMarks[line], state.eMarks[line]) === '---'
+ ) {
state.line = line + 1
return true
@@ -19,6 +24,6 @@ module.exports = function frontMatterPlugin (md) {
}
md.block.ruler.before('table', 'frontmatter', frontmatter, {
- alt: [ 'paragraph', 'reference', 'blockquote', 'list' ]
+ alt: ['paragraph', 'reference', 'blockquote', 'list']
})
}
diff --git a/browser/lib/markdown-it-sanitize-html.js b/browser/lib/markdown-it-sanitize-html.js
index 641216e3..b93e866f 100644
--- a/browser/lib/markdown-it-sanitize-html.js
+++ b/browser/lib/markdown-it-sanitize-html.js
@@ -4,7 +4,7 @@ import sanitizeHtml from 'sanitize-html'
import { escapeHtmlCharacters } from './utils'
import url from 'url'
-module.exports = function sanitizePlugin (md, options) {
+module.exports = function sanitizePlugin(md, options) {
options = options || {}
md.core.ruler.after('linkify', 'sanitize_inline', state => {
@@ -38,15 +38,20 @@ module.exports = function sanitizePlugin (md, options) {
}
const tagRegex = /<([A-Z][A-Z0-9]*)\s*((?:\s*[A-Z][A-Z0-9]*(?:=("|')(?:[^\3]+?)\3)?)*)\s*\/?>|<\/([A-Z][A-Z0-9]*)\s*>/i
-const attributesRegex = /([A-Z][A-Z0-9]*)(?:=("|')([^\2]+?)\2)?/ig
+const attributesRegex = /([A-Z][A-Z0-9]*)(?:=("|')([^\2]+?)\2)?/gi
-function sanitizeInline (html, options) {
+function sanitizeInline(html, options) {
let match = tagRegex.exec(html)
if (!match) {
return ''
}
- const { allowedTags, allowedAttributes, selfClosing, allowedSchemesAppliedToAttributes } = options
+ const {
+ allowedTags,
+ allowedAttributes,
+ selfClosing,
+ allowedSchemesAppliedToAttributes
+ } = options
if (match[1] !== undefined) {
// opening tag
@@ -65,9 +70,17 @@ function sanitizeInline (html, options) {
name = match[1].toLowerCase()
value = match[3]
- if (allowedAttributes['*'].indexOf(name) !== -1 || (allowedAttributes[tag] && allowedAttributes[tag].indexOf(name) !== -1)) {
+ if (
+ allowedAttributes['*'].indexOf(name) !== -1 ||
+ (allowedAttributes[tag] && allowedAttributes[tag].indexOf(name) !== -1)
+ ) {
if (allowedSchemesAppliedToAttributes.indexOf(name) !== -1) {
- if (naughtyHRef(value, options) || (tag === 'iframe' && name === 'src' && naughtyIFrame(value, options))) {
+ if (
+ naughtyHRef(value, options) ||
+ (tag === 'iframe' &&
+ name === 'src' &&
+ naughtyIFrame(value, options))
+ ) {
continue
}
}
@@ -94,7 +107,7 @@ function sanitizeInline (html, options) {
}
}
-function naughtyHRef (href, options) {
+function naughtyHRef(href, options) {
// href = href.replace(/[\x00-\x20]+/g, '')
if (!href) {
// No href
@@ -117,7 +130,7 @@ function naughtyHRef (href, options) {
return options.allowedSchemes.indexOf(scheme) === -1
}
-function naughtyIFrame (src, options) {
+function naughtyIFrame(src, options) {
try {
const parsed = url.parse(src, false, true)
diff --git a/browser/lib/markdown-toc-generator.js b/browser/lib/markdown-toc-generator.js
index 7c76c1f3..900aef18 100644
--- a/browser/lib/markdown-toc-generator.js
+++ b/browser/lib/markdown-toc-generator.js
@@ -12,7 +12,7 @@ const hasProp = Object.prototype.hasOwnProperty
/**
* From @enyaxu/markdown-it-anchor
*/
-function uniqueSlug (slug, slugs, opts) {
+function uniqueSlug(slug, slugs, opts) {
let uniq = slug
let i = opts.uniqueSlugStartIndex
while (hasProp.call(slugs, uniq)) uniq = `${slug}-${i++}`
@@ -20,7 +20,7 @@ function uniqueSlug (slug, slugs, opts) {
return uniq
}
-function linkify (token) {
+function linkify(token) {
token.content = mdlink(token.content, `#${decodeURI(token.slug)}`)
return token
}
@@ -36,8 +36,8 @@ const tocRegex = new RegExp(`${TOC_MARKER_START}[\\s\\S]*?${TOC_MARKER_END}`)
* Otherwise,TOC is updated in place.
* @param editor CodeMirror editor to be updated with TOC
*/
-export function generateInEditor (editor) {
- function updateExistingToc () {
+export function generateInEditor(editor) {
+ function updateExistingToc() {
const toc = generate(editor.getValue())
const search = editor.getSearchCursor(tocRegex)
while (search.findNext()) {
@@ -45,8 +45,10 @@ export function generateInEditor (editor) {
}
}
- function addTocAtCursorPosition () {
- const toc = generate(editor.getRange(editor.getCursor(), {line: Infinity}))
+ function addTocAtCursorPosition() {
+ const toc = generate(
+ editor.getRange(editor.getCursor(), { line: Infinity })
+ )
editor.replaceRange(wrapTocWithEol(toc, editor), editor.getCursor())
}
@@ -57,7 +59,7 @@ export function generateInEditor (editor) {
}
}
-export function tocExistsInEditor (editor) {
+export function tocExistsInEditor(editor) {
return tocRegex.test(editor.getValue())
}
@@ -66,7 +68,7 @@ export function tocExistsInEditor (editor) {
* @param markdownText MD document
* @returns generatedTOC String containing generated TOC
*/
-export function generate (markdownText) {
+export function generate(markdownText) {
const slugs = {}
const opts = {
uniqueSlugStartIndex: 1
@@ -86,9 +88,12 @@ export function generate (markdownText) {
return TOC_MARKER_START + EOL + EOL + md + EOL + EOL + TOC_MARKER_END
}
-function wrapTocWithEol (toc, editor) {
+function wrapTocWithEol(toc, editor) {
const leftWrap = editor.getCursor().ch === 0 ? '' : EOL
- const rightWrap = editor.getLine(editor.getCursor().line).length === editor.getCursor().ch ? '' : EOL
+ const rightWrap =
+ editor.getLine(editor.getCursor().line).length === editor.getCursor().ch
+ ? ''
+ : EOL
return leftWrap + toc + rightWrap
}
diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js
index 49183442..29a3b70b 100644
--- a/browser/lib/markdown.js
+++ b/browser/lib/markdown.js
@@ -4,23 +4,26 @@ import emoji from 'markdown-it-emoji'
import math from '@rokt33r/markdown-it-math'
import mdurl from 'mdurl'
import smartArrows from 'markdown-it-smartarrows'
+import markdownItTocAndAnchor from '@hikerpig/markdown-it-toc-and-anchor'
import _ from 'lodash'
import ConfigManager from 'browser/main/lib/ConfigManager'
import katex from 'katex'
import { lastFindInArray } from './utils'
-function createGutter (str, firstLineNumber) {
+function createGutter(str, firstLineNumber) {
if (Number.isNaN(firstLineNumber)) firstLineNumber = 1
const lastLineNumber = (str.match(/\n/g) || []).length + firstLineNumber - 1
const lines = []
for (let i = firstLineNumber; i <= lastLineNumber; i++) {
lines.push('
' + i + '')
}
- return '
' + lines.join('') + ''
+ return (
+ '
' + lines.join('') + ''
+ )
}
class Markdown {
- constructor (options = {}) {
+ constructor(options = {}) {
const config = ConfigManager.get()
const defaultOptions = {
typographer: config.preview.smartQuotes,
@@ -36,29 +39,129 @@ class Markdown {
this.md.linkify.set({ fuzzyLink: false })
if (updatedOptions.sanitize !== 'NONE') {
- const allowedTags = ['iframe', 'input', 'b',
- 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7', 'h8', 'br', 'b', 'i', 'strong', 'em', 'a', 'pre', 'code', 'img', 'tt',
- 'div', 'ins', 'del', 'sup', 'sub', 'p', 'ol', 'ul', 'table', 'thead', 'tbody', 'tfoot', 'blockquote',
- 'dl', 'dt', 'dd', 'kbd', 'q', 'samp', 'var', 'hr', 'ruby', 'rt', 'rp', 'li', 'tr', 'td', 'th', 's', 'strike', 'summary', 'details'
+ const allowedTags = [
+ 'iframe',
+ 'input',
+ 'b',
+ 'h1',
+ 'h2',
+ 'h3',
+ 'h4',
+ 'h5',
+ 'h6',
+ 'h7',
+ 'h8',
+ 'br',
+ 'b',
+ 'i',
+ 'strong',
+ 'em',
+ 'a',
+ 'pre',
+ 'code',
+ 'img',
+ 'tt',
+ 'div',
+ 'ins',
+ 'del',
+ 'sup',
+ 'sub',
+ 'p',
+ 'ol',
+ 'ul',
+ 'table',
+ 'thead',
+ 'tbody',
+ 'tfoot',
+ 'blockquote',
+ 'dl',
+ 'dt',
+ 'dd',
+ 'kbd',
+ 'q',
+ 'samp',
+ 'var',
+ 'hr',
+ 'ruby',
+ 'rt',
+ 'rp',
+ 'li',
+ 'tr',
+ 'td',
+ 'th',
+ 's',
+ 'strike',
+ 'summary',
+ 'details'
]
const allowedAttributes = [
- 'abbr', 'accept', 'accept-charset',
- 'accesskey', 'action', 'align', 'alt', 'axis',
- 'border', 'cellpadding', 'cellspacing', 'char',
- 'charoff', 'charset', 'checked',
- 'clear', 'cols', 'colspan', 'color',
- 'compact', 'coords', 'datetime', 'dir',
- 'disabled', 'enctype', 'for', 'frame',
- 'headers', 'height', 'hreflang',
- 'hspace', 'ismap', 'label', 'lang',
- 'maxlength', 'media', 'method',
- 'multiple', 'name', 'nohref', 'noshade',
- 'nowrap', 'open', 'prompt', 'readonly', 'rel', 'rev',
- 'rows', 'rowspan', 'rules', 'scope',
- 'selected', 'shape', 'size', 'span',
- 'start', 'summary', 'tabindex', 'target',
- 'title', 'type', 'usemap', 'valign', 'value',
- 'vspace', 'width', 'itemprop'
+ 'abbr',
+ 'accept',
+ 'accept-charset',
+ 'accesskey',
+ 'action',
+ 'align',
+ 'alt',
+ 'axis',
+ 'border',
+ 'cellpadding',
+ 'cellspacing',
+ 'char',
+ 'charoff',
+ 'charset',
+ 'checked',
+ 'clear',
+ 'cols',
+ 'colspan',
+ 'color',
+ 'compact',
+ 'coords',
+ 'datetime',
+ 'dir',
+ 'disabled',
+ 'enctype',
+ 'for',
+ 'frame',
+ 'headers',
+ 'height',
+ 'hreflang',
+ 'hspace',
+ 'ismap',
+ 'label',
+ 'lang',
+ 'maxlength',
+ 'media',
+ 'method',
+ 'multiple',
+ 'name',
+ 'nohref',
+ 'noshade',
+ 'nowrap',
+ 'open',
+ 'prompt',
+ 'readonly',
+ 'rel',
+ 'rev',
+ 'rows',
+ 'rowspan',
+ 'rules',
+ 'scope',
+ 'selected',
+ 'shape',
+ 'size',
+ 'span',
+ 'start',
+ 'summary',
+ 'tabindex',
+ 'target',
+ 'title',
+ 'type',
+ 'usemap',
+ 'valign',
+ 'value',
+ 'vspace',
+ 'width',
+ 'itemprop'
]
if (updatedOptions.sanitize === 'ALLOW_STYLES') {
@@ -71,20 +174,20 @@ class Markdown {
allowedTags,
allowedAttributes: {
'*': allowedAttributes,
- 'a': ['href'],
- 'div': ['itemscope', 'itemtype'],
- 'blockquote': ['cite'],
- 'del': ['cite'],
- 'ins': ['cite'],
- 'q': ['cite'],
- 'img': ['src', 'width', 'height'],
- 'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen'],
- 'input': ['type', 'id', 'checked']
+ a: ['href'],
+ div: ['itemscope', 'itemtype'],
+ blockquote: ['cite'],
+ del: ['cite'],
+ ins: ['cite'],
+ q: ['cite'],
+ img: ['src', 'width', 'height'],
+ iframe: ['src', 'width', 'height', 'frameborder', 'allowfullscreen'],
+ input: ['type', 'id', 'checked']
},
allowedIframeHostnames: ['www.youtube.com'],
- selfClosing: [ 'img', 'br', 'hr', 'input' ],
- allowedSchemes: [ 'http', 'https', 'ftp', 'mailto' ],
- allowedSchemesAppliedToAttributes: [ 'href', 'src', 'cite' ],
+ selfClosing: ['img', 'br', 'hr', 'input'],
+ allowedSchemes: ['http', 'https', 'ftp', 'mailto'],
+ allowedSchemesAppliedToAttributes: ['href', 'src', 'cite'],
allowProtocolRelative: true
})
}
@@ -97,7 +200,7 @@ class Markdown {
inlineClose: config.preview.latexInlineClose,
blockOpen: config.preview.latexBlockOpen,
blockClose: config.preview.latexBlockClose,
- inlineRenderer: function (str) {
+ inlineRenderer: function(str) {
let output = ''
try {
output = katex.renderToString(str.trim())
@@ -106,7 +209,7 @@ class Markdown {
}
return output
},
- blockRenderer: function (str) {
+ blockRenderer: function(str) {
let output = ''
try {
output = katex.renderToString(str.trim(), { displayMode: true })
@@ -123,96 +226,167 @@ class Markdown {
slugify: require('./slugify')
})
this.md.use(require('markdown-it-kbd'))
- this.md.use(require('markdown-it-admonition'), {types: ['note', 'hint', 'attention', 'caution', 'danger', 'error']})
+ this.md.use(require('markdown-it-admonition'), {
+ types: [
+ 'note',
+ 'hint',
+ 'attention',
+ 'caution',
+ 'danger',
+ 'error',
+ 'quote',
+ 'abstract',
+ 'question'
+ ]
+ })
this.md.use(require('markdown-it-abbr'))
this.md.use(require('markdown-it-sub'))
this.md.use(require('markdown-it-sup'))
+
+ this.md.use(md => {
+ markdownItTocAndAnchor(md, {
+ toc: true,
+ tocPattern: /\[TOC\]/i,
+ anchorLink: false,
+ appendIdToHeading: false
+ })
+
+ md.renderer.rules.toc_open = () => '
'
+ md.renderer.rules.toc_close = () => '
'
+ })
+
this.md.use(require('./markdown-it-deflist'))
this.md.use(require('./markdown-it-frontmatter'))
- this.md.use(require('./markdown-it-fence'), {
- chart: token => {
- if (token.parameters.hasOwnProperty('yaml')) {
- token.parameters.format = 'yaml'
- }
-
- return `
- ${token.fileName}
- ${token.content}
- `
- },
- flowchart: token => {
- return `
- ${token.fileName}
- ${token.content}
- `
- },
- gallery: token => {
- const content = token.content.split('\n').slice(0, -1).map(line => {
- const match = /!\[[^\]]*]\(([^\)]*)\)/.exec(line)
- if (match) {
- return mdurl.encode(match[1])
- } else {
- return mdurl.encode(line)
+ this.md.use(
+ require('./markdown-it-fence'),
+ {
+ chart: token => {
+ if (token.parameters.hasOwnProperty('yaml')) {
+ token.parameters.format = 'yaml'
}
- }).join('\n')
- return `
+ return `
${token.fileName}
- ${content}
+ ${
+ token.content
+ }
`
+ },
+ flowchart: token => {
+ return `
+ ${token.fileName}
+ ${
+ token.content
+ }
+ `
+ },
+ gallery: token => {
+ const content = token.content
+ .split('\n')
+ .slice(0, -1)
+ .map(line => {
+ const match = /!\[[^\]]*]\(([^\)]*)\)/.exec(line)
+ if (match) {
+ return mdurl.encode(match[1])
+ } else {
+ return mdurl.encode(line)
+ }
+ })
+ .join('\n')
+
+ return `
+ ${token.fileName}
+ ${content}
+ `
+ },
+ mermaid: token => {
+ return `
+ ${token.fileName}
+ ${
+ token.content
+ }
+ `
+ },
+ sequence: token => {
+ return `
+ ${token.fileName}
+ ${
+ token.content
+ }
+ `
+ }
},
- mermaid: token => {
- return `
- ${token.fileName}
- ${token.content}
- `
- },
- sequence: token => {
- return `
- ${token.fileName}
- ${token.content}
- `
- }
- }, token => {
- return `
+ token => {
+ return `
${token.fileName}
${createGutter(token.content, token.firstLineNumber)}
${token.content}
`
- })
+ }
+ )
const deflate = require('markdown-it-plantuml/lib/deflate')
- this.md.use(require('markdown-it-plantuml'), {
- generateSource: function (umlCode) {
- const stripTrailingSlash = (url) => url.endsWith('/') ? url.slice(0, -1) : url
- const serverAddress = stripTrailingSlash(config.preview.plantUMLServerAddress) + '/svg'
- const s = unescape(encodeURIComponent(umlCode))
- const zippedCode = deflate.encode64(
- deflate.zip_deflate(`@startuml\n${s}\n@enduml`, 9)
- )
- return `${serverAddress}/${zippedCode}`
- }
+ const plantuml = require('markdown-it-plantuml')
+ const plantUmlStripTrailingSlash = url =>
+ url.endsWith('/') ? url.slice(0, -1) : url
+ const plantUmlServerAddress = plantUmlStripTrailingSlash(
+ config.preview.plantUMLServerAddress
+ )
+ const parsePlantUml = function(umlCode, openMarker, closeMarker, type) {
+ const s = unescape(encodeURIComponent(umlCode))
+ const zippedCode = deflate.encode64(
+ deflate.zip_deflate(`${openMarker}\n${s}\n${closeMarker}`, 9)
+ )
+ return `${plantUmlServerAddress}/${type}/${zippedCode}`
+ }
+
+ this.md.use(plantuml, {
+ generateSource: umlCode =>
+ parsePlantUml(umlCode, '@startuml', '@enduml', 'svg')
})
- // Ditaa support
- this.md.use(require('markdown-it-plantuml'), {
+ // Ditaa support. PlantUML server doesn't support Ditaa in SVG, so we set the format as PNG at the moment.
+ this.md.use(plantuml, {
openMarker: '@startditaa',
closeMarker: '@endditaa',
- generateSource: function (umlCode) {
- const stripTrailingSlash = (url) => url.endsWith('/') ? url.slice(0, -1) : url
- // Currently PlantUML server doesn't support Ditaa in SVG, so we set the format as PNG at the moment.
- const serverAddress = stripTrailingSlash(config.preview.plantUMLServerAddress) + '/png'
- const s = unescape(encodeURIComponent(umlCode))
- const zippedCode = deflate.encode64(
- deflate.zip_deflate(`@startditaa\n${s}\n@endditaa`, 9)
- )
- return `${serverAddress}/${zippedCode}`
- }
+ generateSource: umlCode =>
+ parsePlantUml(umlCode, '@startditaa', '@endditaa', 'png')
+ })
+
+ // Mindmap support
+ this.md.use(plantuml, {
+ openMarker: '@startmindmap',
+ closeMarker: '@endmindmap',
+ generateSource: umlCode =>
+ parsePlantUml(umlCode, '@startmindmap', '@endmindmap', 'svg')
+ })
+
+ // WBS support
+ this.md.use(plantuml, {
+ openMarker: '@startwbs',
+ closeMarker: '@endwbs',
+ generateSource: umlCode =>
+ parsePlantUml(umlCode, '@startwbs', '@endwbs', 'svg')
+ })
+
+ // Gantt support
+ this.md.use(plantuml, {
+ openMarker: '@startgantt',
+ closeMarker: '@endgantt',
+ generateSource: umlCode =>
+ parsePlantUml(umlCode, '@startgantt', '@endgantt', 'svg')
})
// Override task item
- this.md.block.ruler.at('paragraph', function (state, startLine/*, endLine */) {
+ this.md.block.ruler.at('paragraph', function(
+ state,
+ startLine /*, endLine */
+ ) {
let content, terminate, i, l, token
let nextLine = startLine + 1
const terminatorRules = state.md.block.ruler.getRules('paragraph')
@@ -222,10 +396,14 @@ class Markdown {
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
// this would be a code block normally, but after paragraph
// it's considered a lazy continuation regardless of what's there
- if (state.sCount[nextLine] - state.blkIndent > 3) { continue }
+ if (state.sCount[nextLine] - state.blkIndent > 3) {
+ continue
+ }
// quirk for blockquotes, this line should already be checked by that rule
- if (state.sCount[nextLine] < 0) { continue }
+ if (state.sCount[nextLine] < 0) {
+ continue
+ }
// Some tags can terminate paragraph without empty line.
terminate = false
@@ -235,10 +413,14 @@ class Markdown {
break
}
}
- if (terminate) { break }
+ if (terminate) {
+ break
+ }
}
- content = state.getLines(startLine, nextLine, state.blkIndent, false).trim()
+ content = state
+ .getLines(startLine, nextLine, state.blkIndent, false)
+ .trim()
state.line = nextLine
@@ -248,18 +430,31 @@ class Markdown {
if (state.parentType === 'list') {
const match = content.match(/^\[( |x)\] ?(.+)/i)
if (match) {
- const liToken = lastFindInArray(state.tokens, token => token.type === 'list_item_open')
+ const liToken = lastFindInArray(
+ state.tokens,
+ token => token.type === 'list_item_open'
+ )
if (liToken) {
if (!liToken.attrs) {
liToken.attrs = []
}
if (config.preview.lineThroughCheckbox) {
- liToken.attrs.push(['class', `taskListItem${match[1] !== ' ' ? ' checked' : ''}`])
+ liToken.attrs.push([
+ 'class',
+ `taskListItem${match[1] !== ' ' ? ' checked' : ''}`
+ ])
} else {
liToken.attrs.push(['class', 'taskListItem'])
}
}
- content = ``
+ content = ``
}
}
@@ -280,7 +475,7 @@ class Markdown {
// Add line number attribute for scrolling
const originalRender = this.md.renderer.render
this.md.renderer.render = (tokens, options, env) => {
- tokens.forEach((token) => {
+ tokens.forEach(token => {
switch (token.type) {
case 'blockquote_open':
case 'dd_open':
@@ -301,7 +496,7 @@ class Markdown {
window.md = this.md
}
- render (content) {
+ render(content) {
if (!_.isString(content)) content = ''
return this.md.render(content)
}
diff --git a/browser/lib/markdownTextHelper.js b/browser/lib/markdownTextHelper.js
index 1657efd9..bb2ed938 100644
--- a/browser/lib/markdownTextHelper.js
+++ b/browser/lib/markdownTextHelper.js
@@ -6,7 +6,7 @@
* @param {string} input
* @return {string}
*/
-export function strip (input) {
+export function strip(input) {
let output = input
try {
output = output
diff --git a/browser/lib/newNote.js b/browser/lib/newNote.js
index 4eec24f1..024ae21b 100644
--- a/browser/lib/newNote.js
+++ b/browser/lib/newNote.js
@@ -4,12 +4,22 @@ import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
import queryString from 'query-string'
import { push } from 'connected-react-router'
-export function createMarkdownNote (storage, folder, dispatch, location, params, config) {
+export function createMarkdownNote(
+ storage,
+ folder,
+ dispatch,
+ location,
+ params,
+ config
+) {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_MARKDOWN')
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
let tags = []
- if (config.ui.tagNewNoteWithFilteringTags && location.pathname.match(/\/tags/)) {
+ if (
+ config.ui.tagNewNoteWithFilteringTags &&
+ location.pathname.match(/\/tags/)
+ ) {
tags = params.tagname.split(' ')
}
@@ -29,25 +39,40 @@ export function createMarkdownNote (storage, folder, dispatch, location, params,
note: note
})
- dispatch(push({
- pathname: location.pathname,
- search: queryString.stringify({ key: noteHash })
- }))
+ dispatch(
+ push({
+ pathname: location.pathname,
+ search: queryString.stringify({ key: noteHash })
+ })
+ )
ee.emit('list:jump', noteHash)
ee.emit('detail:focus')
})
}
-export function createSnippetNote (storage, folder, dispatch, location, params, config) {
+export function createSnippetNote(
+ storage,
+ folder,
+ dispatch,
+ location,
+ params,
+ config
+) {
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_SNIPPET')
AwsMobileAnalyticsConfig.recordDynamicCustomEvent('ADD_ALLNOTE')
let tags = []
- if (config.ui.tagNewNoteWithFilteringTags && location.pathname.match(/\/tags/)) {
+ if (
+ config.ui.tagNewNoteWithFilteringTags &&
+ location.pathname.match(/\/tags/)
+ ) {
tags = params.tagname.split(' ')
}
- const defaultLanguage = config.editor.snippetDefaultLanguage === 'Auto Detect' ? null : config.editor.snippetDefaultLanguage
+ const defaultLanguage =
+ config.editor.snippetDefaultLanguage === 'Auto Detect'
+ ? null
+ : config.editor.snippetDefaultLanguage
return dataApi
.createNote(storage, {
@@ -71,10 +96,12 @@ export function createSnippetNote (storage, folder, dispatch, location, params,
type: 'UPDATE_NOTE',
note: note
})
- dispatch(push({
- pathname: location.pathname,
- search: queryString.stringify({ key: noteHash })
- }))
+ dispatch(
+ push({
+ pathname: location.pathname,
+ search: queryString.stringify({ key: noteHash })
+ })
+ )
ee.emit('list:jump', noteHash)
ee.emit('detail:focus')
})
diff --git a/browser/lib/normalizeEditorFontFamily.js b/browser/lib/normalizeEditorFontFamily.js
index a2a2ec31..21ded4ac 100644
--- a/browser/lib/normalizeEditorFontFamily.js
+++ b/browser/lib/normalizeEditorFontFamily.js
@@ -1,7 +1,7 @@
import consts from 'browser/lib/consts'
import isString from 'lodash/isString'
-export default function normalizeEditorFontFamily (fontFamily) {
+export default function normalizeEditorFontFamily(fontFamily) {
const defaultEditorFontFamily = consts.DEFAULT_EDITOR_FONT_FAMILY
return isString(fontFamily) && fontFamily.length > 0
? [fontFamily].concat(defaultEditorFontFamily).join(', ')
diff --git a/browser/lib/search.js b/browser/lib/search.js
index cf5b3b1b..4374fa94 100644
--- a/browser/lib/search.js
+++ b/browser/lib/search.js
@@ -1,31 +1,38 @@
import _ from 'lodash'
-export default function searchFromNotes (notes, search) {
+export default function searchFromNotes(notes, search) {
if (search.trim().length === 0) return []
- const searchBlocks = search.split(' ').filter(block => { return block !== '' })
+ const searchBlocks = search.split(' ').filter(block => {
+ return block !== ''
+ })
let foundNotes = notes
- searchBlocks.forEach((block) => {
+ searchBlocks.forEach(block => {
foundNotes = findByWordOrTag(foundNotes, block)
})
return foundNotes
}
-function findByWordOrTag (notes, block) {
+function findByWordOrTag(notes, block) {
let tag = block
if (tag.match(/^#.+/)) {
tag = tag.match(/#(.+)/)[1]
}
const tagRegExp = new RegExp(_.escapeRegExp(tag), 'i')
const wordRegExp = new RegExp(_.escapeRegExp(block), 'i')
- return notes.filter((note) => {
- if (_.isArray(note.tags) && note.tags.some((_tag) => _tag.match(tagRegExp))) {
+ return notes.filter(note => {
+ if (_.isArray(note.tags) && note.tags.some(_tag => _tag.match(tagRegExp))) {
return true
}
if (note.type === 'SNIPPET_NOTE') {
- return note.description.match(wordRegExp) || note.snippets.some((snippet) => {
- return snippet.name.match(wordRegExp) || snippet.content.match(wordRegExp)
- })
+ return (
+ note.description.match(wordRegExp) ||
+ note.snippets.some(snippet => {
+ return (
+ snippet.name.match(wordRegExp) || snippet.content.match(wordRegExp)
+ )
+ })
+ )
} else if (note.type === 'MARKDOWN_NOTE') {
return note.content.match(wordRegExp)
}
diff --git a/browser/lib/slugify.js b/browser/lib/slugify.js
index 21c18e02..a00b4bd0 100644
--- a/browser/lib/slugify.js
+++ b/browser/lib/slugify.js
@@ -1,10 +1,14 @@
-module.exports = function slugify (title) {
+module.exports = function slugify(title) {
const slug = encodeURI(
- title.trim()
+ title
+ .trim()
.replace(/^\s+/, '')
.replace(/\s+$/, '')
.replace(/\s+/g, '-')
- .replace(/[\]\[\!\'\#\$\%\&\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\{\|\}\~\`]/g, '')
+ .replace(
+ /[\]\[\!\'\#\$\%\&\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\{\|\}\~\`]/g,
+ ''
+ )
)
return slug
diff --git a/browser/lib/spellcheck.js b/browser/lib/spellcheck.js
index ab8fc81b..96aac454 100644
--- a/browser/lib/spellcheck.js
+++ b/browser/lib/spellcheck.js
@@ -12,19 +12,19 @@ const MILLISECONDS_TILL_LIVECHECK = 500
let dictionary = null
let self
-function getAvailableDictionaries () {
+function getAvailableDictionaries() {
return [
- {label: i18n.__('Spellcheck disabled'), value: SPELLCHECK_DISABLED},
- {label: i18n.__('English'), value: 'en_GB'},
- {label: i18n.__('German'), value: 'de_DE'},
- {label: i18n.__('French'), value: 'fr_FR'}
+ { label: i18n.__('Spellcheck disabled'), value: SPELLCHECK_DISABLED },
+ { label: i18n.__('English'), value: 'en_GB' },
+ { label: i18n.__('German'), value: 'de_DE' },
+ { label: i18n.__('French'), value: 'fr_FR' }
]
}
/**
* Only to be used in the tests :)
*/
-function setDictionaryForTestsOnly (newDictionary) {
+function setDictionaryForTestsOnly(newDictionary) {
dictionary = newDictionary
}
@@ -34,7 +34,7 @@ function setDictionaryForTestsOnly (newDictionary) {
* @param {Codemirror} editor CodeMirror-Editor
* @param {String} lang on of the values from getAvailableDictionaries()-Method
*/
-function setLanguage (editor, lang) {
+function setLanguage(editor, lang) {
self = this
dictionary = null
@@ -50,8 +50,7 @@ function setLanguage (editor, lang) {
dictionary = new Typo(lang, false, false, {
dictionaryPath: DICTIONARY_PATH,
asyncLoad: true,
- loadedCallback: () =>
- checkWholeDocument(editor)
+ loadedCallback: () => checkWholeDocument(editor)
})
}
}
@@ -60,12 +59,12 @@ function setLanguage (editor, lang) {
* Checks the whole content of the editor for typos
* @param {Codemirror} editor CodeMirror-Editor
*/
-function checkWholeDocument (editor) {
+function checkWholeDocument(editor) {
const lastLine = editor.lineCount() - 1
const textOfLastLine = editor.getLine(lastLine) || ''
const lastChar = textOfLastLine.length
- const from = {line: 0, ch: 0}
- const to = {line: lastLine, ch: lastChar}
+ const from = { line: 0, ch: 0 }
+ const to = { line: lastLine, ch: lastChar }
checkMultiLineRange(editor, from, to)
}
@@ -75,15 +74,18 @@ function checkWholeDocument (editor) {
* @param {line, ch} from starting position of the spellcheck
* @param {line, ch} to end position of the spellcheck
*/
-function checkMultiLineRange (editor, from, to) {
- function sortRange (pos1, pos2) {
- if (pos1.line > pos2.line || (pos1.line === pos2.line && pos1.ch > pos2.ch)) {
- return {from: pos2, to: pos1}
+function checkMultiLineRange(editor, from, to) {
+ function sortRange(pos1, pos2) {
+ if (
+ pos1.line > pos2.line ||
+ (pos1.line === pos2.line && pos1.ch > pos2.ch)
+ ) {
+ return { from: pos2, to: pos1 }
}
- return {from: pos1, to: pos2}
+ return { from: pos1, to: pos2 }
}
- const {from: smallerPos, to: higherPos} = sortRange(from, to)
+ const { from: smallerPos, to: higherPos } = sortRange(from, to)
for (let l = smallerPos.line; l <= higherPos.line; l++) {
const line = editor.getLine(l) || ''
let w = 0
@@ -95,9 +97,9 @@ function checkMultiLineRange (editor, from, to) {
wEnd = higherPos.ch
}
while (w <= wEnd) {
- const wordRange = editor.findWordAt({line: l, ch: w})
+ const wordRange = editor.findWordAt({ line: l, ch: w })
self.checkWord(editor, wordRange)
- w += (wordRange.head.ch - wordRange.anchor.ch) + 1
+ w += wordRange.head.ch - wordRange.anchor.ch + 1
}
}
}
@@ -110,13 +112,15 @@ function checkMultiLineRange (editor, from, to) {
* @param wordRange Object specifying the range that should be checked.
* Having the following structure: {anchor: {line: integer, ch: integer}, head: {line: integer, ch: integer}}
*/
-function checkWord (editor, wordRange) {
+function checkWord(editor, wordRange) {
const word = editor.getRange(wordRange.anchor, wordRange.head)
if (word == null || word.length <= 3) {
return
}
if (!dictionary.check(word)) {
- editor.markText(wordRange.anchor, wordRange.head, {className: styles[CSS_ERROR_CLASS]})
+ editor.markText(wordRange.anchor, wordRange.head, {
+ className: styles[CSS_ERROR_CLASS]
+ })
}
}
@@ -126,32 +130,40 @@ function checkWord (editor, wordRange) {
* @param fromChangeObject codeMirror changeObject describing the start of the editing
* @param toChangeObject codeMirror changeObject describing the end of the editing
*/
-function checkChangeRange (editor, fromChangeObject, toChangeObject) {
+function checkChangeRange(editor, fromChangeObject, toChangeObject) {
/**
* Calculate the smallest respectively largest position as a start, resp. end, position and return it
* @param start CodeMirror change object
* @param end CodeMirror change object
* @returns {{start: {line: *, ch: *}, end: {line: *, ch: *}}}
*/
- function getStartAndEnd (start, end) {
+ function getStartAndEnd(start, end) {
const possiblePositions = [start.from, start.to, end.from, end.to]
let smallest = start.from
let biggest = end.to
for (const currentPos of possiblePositions) {
- if (currentPos.line < smallest.line || (currentPos.line === smallest.line && currentPos.ch < smallest.ch)) {
+ if (
+ currentPos.line < smallest.line ||
+ (currentPos.line === smallest.line && currentPos.ch < smallest.ch)
+ ) {
smallest = currentPos
}
- if (currentPos.line > biggest.line || (currentPos.line === biggest.line && currentPos.ch > biggest.ch)) {
+ if (
+ currentPos.line > biggest.line ||
+ (currentPos.line === biggest.line && currentPos.ch > biggest.ch)
+ ) {
biggest = currentPos
}
}
- return {start: smallest, end: biggest}
+ return { start: smallest, end: biggest }
}
- if (dictionary === null || editor == null) { return }
+ if (dictionary === null || editor == null) {
+ return
+ }
try {
- const {start, end} = getStartAndEnd(fromChangeObject, toChangeObject)
+ const { start, end } = getStartAndEnd(fromChangeObject, toChangeObject)
// Expand the range to include words after/before whitespaces
start.ch = Math.max(start.ch - 1, 0)
@@ -165,29 +177,40 @@ function checkChangeRange (editor, fromChangeObject, toChangeObject) {
self.checkMultiLineRange(editor, start, end)
} catch (e) {
- console.info('Error during the spell check. It might be due to problems figuring out the range of the new text..', e)
+ console.info(
+ 'Error during the spell check. It might be due to problems figuring out the range of the new text..',
+ e
+ )
}
}
-function saveLiveSpellCheckFrom (changeObject) {
+function saveLiveSpellCheckFrom(changeObject) {
liveSpellCheckFrom = changeObject
}
let liveSpellCheckFrom
-const debouncedSpellCheckLeading = _.debounce(saveLiveSpellCheckFrom, MILLISECONDS_TILL_LIVECHECK, {
- 'leading': true,
- 'trailing': false
-})
-const debouncedSpellCheck = _.debounce(checkChangeRange, MILLISECONDS_TILL_LIVECHECK, {
- 'leading': false,
- 'trailing': true
-})
+const debouncedSpellCheckLeading = _.debounce(
+ saveLiveSpellCheckFrom,
+ MILLISECONDS_TILL_LIVECHECK,
+ {
+ leading: true,
+ trailing: false
+ }
+)
+const debouncedSpellCheck = _.debounce(
+ checkChangeRange,
+ MILLISECONDS_TILL_LIVECHECK,
+ {
+ leading: false,
+ trailing: true
+ }
+)
/**
* Handles a keystroke. Buffers the input and performs a live spell check after a certain time. Uses _debounce from lodash to buffer the input
* @param {Codemirror} editor CodeMirror-Editor
* @param changeObject codeMirror changeObject
*/
-function handleChange (editor, changeObject) {
+function handleChange(editor, changeObject) {
if (dictionary === null) {
return
}
@@ -201,7 +224,7 @@ function handleChange (editor, changeObject) {
* @param word word to be checked
* @returns {String[]} Array of suggestions
*/
-function getSpellingSuggestion (word) {
+function getSpellingSuggestion(word) {
if (dictionary == null || word == null) {
return []
}
@@ -211,7 +234,7 @@ function getSpellingSuggestion (word) {
/**
* Returns the name of the CSS class used for errors
*/
-function getCSSClassName () {
+function getCSSClassName() {
return styles[CSS_ERROR_CLASS]
}
diff --git a/browser/lib/turndown.js b/browser/lib/turndown.js
index a1c3e128..aae5e1d8 100644
--- a/browser/lib/turndown.js
+++ b/browser/lib/turndown.js
@@ -1,7 +1,7 @@
const TurndownService = require('turndown')
const { gfm } = require('turndown-plugin-gfm')
-export const createTurndownService = function () {
+export const createTurndownService = function() {
const turndown = new TurndownService()
turndown.use(gfm)
turndown.remove('script')
diff --git a/browser/lib/ui-themes.js b/browser/lib/ui-themes.js
new file mode 100644
index 00000000..0a66a349
--- /dev/null
+++ b/browser/lib/ui-themes.js
@@ -0,0 +1,44 @@
+import i18n from 'browser/lib/i18n'
+
+export default [
+ {
+ name: 'dark',
+ label: i18n.__('Dark'),
+ isDark: true
+ },
+ {
+ name: 'default',
+ label: i18n.__('Default'),
+ isDark: false
+ },
+ {
+ name: 'dracula',
+ label: i18n.__('Dracula'),
+ isDark: true
+ },
+ {
+ name: 'monokai',
+ label: i18n.__('Monokai'),
+ isDark: true
+ },
+ {
+ name: 'nord',
+ label: i18n.__('Nord'),
+ isDark: true
+ },
+ {
+ name: 'solarized-dark',
+ label: i18n.__('Solarized Dark'),
+ isDark: true
+ },
+ {
+ name: 'vulcan',
+ label: i18n.__('Vulcan'),
+ isDark: true
+ },
+ {
+ name: 'white',
+ label: i18n.__('White'),
+ isDark: false
+ }
+]
diff --git a/browser/lib/utils.js b/browser/lib/utils.js
index 9f6f1425..794b4d62 100644
--- a/browser/lib/utils.js
+++ b/browser/lib/utils.js
@@ -1,4 +1,4 @@
-export function lastFindInArray (array, callback) {
+export function lastFindInArray(array, callback) {
for (let i = array.length - 1; i >= 0; --i) {
if (callback(array[i], i, array)) {
return array[i]
@@ -6,7 +6,7 @@ export function lastFindInArray (array, callback) {
}
}
-export function escapeHtmlCharacters (
+export function escapeHtmlCharacters(
html,
opt = { detectCodeBlock: false, skipSingleQuote: false }
) {
@@ -115,7 +115,7 @@ export function escapeHtmlCharacters (
return html
}
-export function isObjectEqual (a, b) {
+export function isObjectEqual(a, b) {
const aProps = Object.getOwnPropertyNames(a)
const bProps = Object.getOwnPropertyNames(b)
@@ -132,11 +132,13 @@ export function isObjectEqual (a, b) {
return true
}
-export function isMarkdownTitleURL (str) {
- return /(^#{1,6}\s)(?:\w+:|^)\/\/(?:[^\s\.]+\.\S{2}|localhost[\:?\d]*)/.test(str)
+export function isMarkdownTitleURL(str) {
+ return /(^#{1,6}\s)(?:\w+:|^)\/\/(?:[^\s\.]+\.\S{2}|localhost[\:?\d]*)/.test(
+ str
+ )
}
-export function humanFileSize (bytes) {
+export function humanFileSize(bytes) {
const threshold = 1000
if (Math.abs(bytes) < threshold) {
return bytes + ' B'
diff --git a/browser/main/Detail/Detail.styl b/browser/main/Detail/Detail.styl
index 1b7bd606..f03de5d7 100644
--- a/browser/main/Detail/Detail.styl
+++ b/browser/main/Detail/Detail.styl
@@ -24,23 +24,16 @@ body[data-theme="dark"]
.empty-message
color $ui-dark-inactive-text-color
-body[data-theme="solarized-dark"]
- .root
- background-color $ui-solarized-dark-noteDetail-backgroundColor
- border-left 1px solid $ui-solarized-dark-borderColor
- .empty-message
- color $ui-solarized-dark-text-color
+apply-theme(theme)
+ body[data-theme={theme}]
+ .root
+ background-color get-theme-var(theme, 'noteDetail-backgroundColor')
+ border-left 1px solid get-theme-var(theme, 'borderColor')
+ .empty-message
+ color get-theme-var(theme, 'text-color')
-body[data-theme="monokai"]
- .root
- background-color $ui-monokai-noteDetail-backgroundColor
- border-left 1px solid $ui-monokai-borderColor
- .empty-message
- color $ui-monokai-text-color
+for theme in 'solarized-dark' 'dracula'
+ apply-theme(theme)
-body[data-theme="dracula"]
- .root
- background-color $ui-dracula-noteDetail-backgroundColor
- border-left 1px solid $ui-dracula-borderColor
- .empty-message
- color $ui-dracula-text-color
\ No newline at end of file
+for theme in $themes
+ apply-theme(theme)
\ No newline at end of file
diff --git a/browser/main/Detail/FolderSelect.js b/browser/main/Detail/FolderSelect.js
index 66ca1552..9b2398ad 100644
--- a/browser/main/Detail/FolderSelect.js
+++ b/browser/main/Detail/FolderSelect.js
@@ -6,7 +6,7 @@ import _ from 'lodash'
import i18n from 'browser/lib/i18n'
class FolderSelect extends React.Component {
- constructor (props) {
+ constructor(props) {
super(props)
this.state = {
@@ -16,24 +16,27 @@ class FolderSelect extends React.Component {
}
}
- componentDidMount () {
+ componentDidMount() {
this.value = this.props.value
}
- componentDidUpdate () {
+ componentDidUpdate() {
this.value = this.props.value
}
- handleClick (e) {
- this.setState({
- status: 'SEARCH',
- optionIndex: -1
- }, () => {
- this.refs.search.focus()
- })
+ handleClick(e) {
+ this.setState(
+ {
+ status: 'SEARCH',
+ optionIndex: -1
+ },
+ () => {
+ this.refs.search.focus()
+ }
+ )
}
- handleFocus (e) {
+ handleFocus(e) {
if (this.state.status === 'IDLE') {
this.setState({
status: 'FOCUS'
@@ -41,7 +44,7 @@ class FolderSelect extends React.Component {
}
}
- handleBlur (e) {
+ handleBlur(e) {
if (this.state.status === 'FOCUS') {
this.setState({
status: 'IDLE'
@@ -49,40 +52,49 @@ class FolderSelect extends React.Component {
}
}
- handleKeyDown (e) {
+ handleKeyDown(e) {
switch (e.keyCode) {
case 13:
if (this.state.status === 'FOCUS') {
- this.setState({
- status: 'SEARCH',
- optionIndex: -1
- }, () => {
- this.refs.search.focus()
- })
+ this.setState(
+ {
+ status: 'SEARCH',
+ optionIndex: -1
+ },
+ () => {
+ this.refs.search.focus()
+ }
+ )
}
break
case 40:
case 38:
if (this.state.status === 'FOCUS') {
- this.setState({
- status: 'SEARCH',
- optionIndex: 0
- }, () => {
- this.refs.search.focus()
- })
+ this.setState(
+ {
+ status: 'SEARCH',
+ optionIndex: 0
+ },
+ () => {
+ this.refs.search.focus()
+ }
+ )
}
break
case 9:
if (e.shiftKey) {
e.preventDefault()
- const tabbable = document.querySelectorAll('a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])')
- const previousEl = tabbable[Array.prototype.indexOf.call(tabbable, this.refs.root) - 1]
+ const tabbable = document.querySelectorAll(
+ 'a:not([disabled]), button:not([disabled]), input[type=text]:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])'
+ )
+ const previousEl =
+ tabbable[Array.prototype.indexOf.call(tabbable, this.refs.root) - 1]
if (previousEl != null) previousEl.focus()
}
}
}
- handleSearchInputBlur (e) {
+ handleSearchInputBlur(e) {
if (e.relatedTarget !== this.refs.root) {
this.setState({
status: 'IDLE'
@@ -90,14 +102,17 @@ class FolderSelect extends React.Component {
}
}
- handleSearchInputChange (e) {
+ handleSearchInputChange(e) {
const { folders } = this.props
const search = this.refs.search.value
- const optionIndex = search.length > 0
- ? _.findIndex(folders, (folder) => {
- return folder.name.match(new RegExp('^' + _.escapeRegExp(search), 'i'))
- })
- : -1
+ const optionIndex =
+ search.length > 0
+ ? _.findIndex(folders, folder => {
+ return folder.name.match(
+ new RegExp('^' + _.escapeRegExp(search), 'i')
+ )
+ })
+ : -1
this.setState({
search: this.refs.search.value,
@@ -105,7 +120,7 @@ class FolderSelect extends React.Component {
})
}
- handleSearchInputKeyDown (e) {
+ handleSearchInputKeyDown(e) {
switch (e.keyCode) {
case 40:
e.stopPropagation()
@@ -121,15 +136,18 @@ class FolderSelect extends React.Component {
break
case 27:
e.stopPropagation()
- this.setState({
- status: 'FOCUS'
- }, () => {
- this.refs.root.focus()
- })
+ this.setState(
+ {
+ status: 'FOCUS'
+ },
+ () => {
+ this.refs.root.focus()
+ }
+ )
}
}
- nextOption () {
+ nextOption() {
let { optionIndex } = this.state
const { folders } = this.props
@@ -141,7 +159,7 @@ class FolderSelect extends React.Component {
})
}
- previousOption () {
+ previousOption() {
const { folders } = this.props
let { optionIndex } = this.state
@@ -153,46 +171,52 @@ class FolderSelect extends React.Component {
})
}
- selectOption () {
+ selectOption() {
const { folders } = this.props
const optionIndex = this.state.optionIndex
const folder = folders[optionIndex]
if (folder != null) {
- this.setState({
- status: 'FOCUS'
- }, () => {
- this.setValue(folder.key)
- this.refs.root.focus()
- })
+ this.setState(
+ {
+ status: 'FOCUS'
+ },
+ () => {
+ this.setValue(folder.key)
+ this.refs.root.focus()
+ }
+ )
}
}
- handleOptionClick (storageKey, folderKey) {
- return (e) => {
+ handleOptionClick(storageKey, folderKey) {
+ return e => {
e.stopPropagation()
- this.setState({
- status: 'FOCUS'
- }, () => {
- this.setValue(storageKey + '-' + folderKey)
- this.refs.root.focus()
- })
+ this.setState(
+ {
+ status: 'FOCUS'
+ },
+ () => {
+ this.setValue(storageKey + '-' + folderKey)
+ this.refs.root.focus()
+ }
+ )
}
}
- setValue (value) {
+ setValue(value) {
this.value = value
this.props.onChange()
}
- render () {
+ render() {
const { className, data, value } = this.props
const splitted = value.split('-')
const storageKey = splitted.shift()
const folderKey = splitted.shift()
let options = []
data.storageMap.forEach((storage, index) => {
- storage.folders.forEach((folder) => {
+ storage.folders.forEach(folder => {
options.push({
storage: storage,
folder: folder
@@ -200,68 +224,78 @@ class FolderSelect extends React.Component {
})
})
- const currentOption = options.filter((option) => option.storage.key === storageKey && option.folder.key === folderKey)[0]
+ const currentOption = options.filter(
+ option =>
+ option.storage.key === storageKey && option.folder.key === folderKey
+ )[0]
if (this.state.search.trim().length > 0) {
const filter = new RegExp('^' + _.escapeRegExp(this.state.search), 'i')
- options = options.filter((option) => filter.test(option.folder.name))
+ options = options.filter(option => filter.test(option.folder.name))
}
- const optionList = options
- .map((option, index) => {
- return (
- {
+ return (
+
this.handleOptionClick(option.storage.key, option.folder.key)(e)}
+ }
+ key={option.storage.key + '-' + option.folder.key}
+ onClick={e =>
+ this.handleOptionClick(option.storage.key, option.folder.key)(e)
+ }
+ >
+
-
- {option.folder.name}
- in {option.storage.name}
+ {option.folder.name}
+
+ in {option.storage.name}
-
- )
- })
+
+
+ )
+ })
return (
- this.handleClick(e)}
- onFocus={(e) => this.handleFocus(e)}
- onBlur={(e) => this.handleBlur(e)}
- onKeyDown={(e) => this.handleKeyDown(e)}
+ onClick={e => this.handleClick(e)}
+ onFocus={e => this.handleFocus(e)}
+ onBlur={e => this.handleBlur(e)}
+ onKeyDown={e => this.handleKeyDown(e)}
>
- {this.state.status === 'SEARCH'
- ?
-
+
this.handleSearchInputChange(e)}
- onBlur={(e) => this.handleSearchInputBlur(e)}
- onKeyDown={(e) => this.handleSearchInputKeyDown(e)}
+ onChange={e => this.handleSearchInputChange(e)}
+ onBlur={e => this.handleSearchInputBlur(e)}
+ onKeyDown={e => this.handleSearchInputKeyDown(e)}
/>
-
- :
+ ) : currentOption ? (
+
@@ -269,8 +303,7 @@ class FolderSelect extends React.Component {
- }
-
+ ) : null}
)
}
@@ -280,11 +313,13 @@ FolderSelect.propTypes = {
className: PropTypes.string,
onChange: PropTypes.func,
value: PropTypes.string,
- folders: PropTypes.arrayOf(PropTypes.shape({
- key: PropTypes.string,
- name: PropTypes.string,
- color: PropTypes.string
- }))
+ folders: PropTypes.arrayOf(
+ PropTypes.shape({
+ key: PropTypes.string,
+ name: PropTypes.string,
+ color: PropTypes.string
+ })
+ )
}
export default CSSModules(FolderSelect, styles)
diff --git a/browser/main/Detail/FolderSelect.styl b/browser/main/Detail/FolderSelect.styl
index fe045e3a..ac903c6c 100644
--- a/browser/main/Detail/FolderSelect.styl
+++ b/browser/main/Detail/FolderSelect.styl
@@ -134,54 +134,39 @@ body[data-theme="dark"]
.search-optionList-item-name-surfix
color $ui-dark-inactive-text-color
-body[data-theme="monokai"]
- .root
- color $ui-dark-text-color
- &:hover
- color white
- background-color $ui-monokai-button--hover-backgroundColor
- border-color $ui-monokai-borderColor
+apply-theme(theme)
+ body[data-theme={theme}]
+ .root
+ &:hover
+ background-color get-theme-var(theme, 'button--hover-backgroundColor')
+ border-color get-theme-var(theme, 'borderColor')
- .search-optionList
- color white
- border-color $ui-monokai-borderColor
- background-color $ui-monokai-button-backgroundColor
+ .search-input
+ color get-theme-var(theme, 'text-color')
+ background-color transparent
+ border-color get-theme-var(theme, 'borderColor')
- .search-optionList-item
- &:hover
- background-color lighten($ui-monokai-button--hover-backgroundColor, 15%)
+ .search-optionList
+ color get-theme-var(theme, 'text-color')
+ border-color get-theme-var(theme, 'borderColor')
+ background-color get-theme-var(theme, 'button-backgroundColor')
- .search-optionList-item--active
- background-color $ui-monokai-button--active-backgroundColor
- color $ui-monokai-button--active-color
- &:hover
- background-color $ui-monokai-button--active-backgroundColor
- color $ui-monokai-button--active-color
- .search-optionList-item-name-surfix
- color $ui-monokai-inactive-text-color
+ .search-optionList-item
+ &:hover
+ background-color lighten(get-theme-var(theme, 'button--hover-backgroundColor'), 15%)
-body[data-theme="dracula"]
- .root
- color $ui-dracula-text-color
- &:hover
- color #f8f8f2
- background-color $ui-dark-button--hover-backgroundColor
- border-color $ui-dracula-borderColor
+ .search-optionList-item--active
+ background-color get-theme-var(theme, 'button--active-backgroundColor')
+ color get-theme-var(theme, 'button--active-color')
+ &:hover
+ background-color get-theme-var(theme, 'button--active-backgroundColor')
+ color get-theme-var(theme, 'button--active-color')
- .search-optionList
- color #f8f8f2
- border-color $ui-dracula-borderColor
- background-color $ui-dracula-button-backgroundColor
+ .search-optionList-item-name-surfix
+ color get-theme-var(theme, 'inactive-text-color')
- .search-optionList-item
- &:hover
- background-color lighten($ui-dracula-button--hover-backgroundColor, 15%)
+for theme in 'solarized-dark' 'dracula'
+ apply-theme(theme)
- .search-optionList-item--active
- background-color $ui-dracula-button--active-backgroundColor
- color $ui-dracula-button--active-color
- &:hover
- background-color $ui-dark-button--hover-backgroundColor
- color $ui-dracula-button--active-color
- .search-optionList-item-name-surfix
- color $ui-dracula-inactive-text-color
+for theme in $themes
+ apply-theme(theme)
\ No newline at end of file
diff --git a/browser/main/Detail/FromUrlButton.js b/browser/main/Detail/FromUrlButton.js
index 0d1c1b4c..1481a176 100644
--- a/browser/main/Detail/FromUrlButton.js
+++ b/browser/main/Detail/FromUrlButton.js
@@ -6,7 +6,7 @@ import _ from 'lodash'
import i18n from 'browser/lib/i18n'
class FromUrlButton extends React.Component {
- constructor (props) {
+ constructor(props) {
super(props)
this.state = {
@@ -14,44 +14,46 @@ class FromUrlButton extends React.Component {
}
}
- handleMouseDown (e) {
+ handleMouseDown(e) {
this.setState({
isActive: true
})
}
- handleMouseUp (e) {
+ handleMouseUp(e) {
this.setState({
isActive: false
})
}
- handleMouseLeave (e) {
+ handleMouseLeave(e) {
this.setState({
isActive: false
})
}
- render () {
+ render() {
const { className } = this.props
return (
-