From 8d59bd9f71c61aa8be0a87cecd86bb48eb57dbfe Mon Sep 17 00:00:00 2001 From: Nikolay Lopin Date: Sun, 25 Feb 2018 02:42:15 +0300 Subject: [PATCH 01/75] Remove redundant symbol from regexp --- browser/main/lib/dataApi/exportNote.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/lib/dataApi/exportNote.js b/browser/main/lib/dataApi/exportNote.js index 3ed46b92..740baa20 100755 --- a/browser/main/lib/dataApi/exportNote.js +++ b/browser/main/lib/dataApi/exportNote.js @@ -4,7 +4,7 @@ import {findStorage} from 'browser/lib/findStorage' const fs = require('fs') const path = require('path') -const LOCAL_STORED_REGEX = /!\[(.*?)\]\(\s*?\/:storage\/(.*\.\S*?)\)/gi +const LOCAL_STORED_REGEX = /!\[(.*?)]\(\s*?\/:storage\/(.*\.\S*?)\)/gi const IMAGES_FOLDER_NAME = 'images' /** From e5825e898dc0418c04230e6f07526b2507a67b7e Mon Sep 17 00:00:00 2001 From: Nikolay Lopin Date: Sun, 25 Feb 2018 02:45:59 +0300 Subject: [PATCH 02/75] allow to copy images without generating new name --- browser/main/lib/dataApi/copyImage.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/browser/main/lib/dataApi/copyImage.js b/browser/main/lib/dataApi/copyImage.js index ae79f8fb..6a79b8b7 100644 --- a/browser/main/lib/dataApi/copyImage.js +++ b/browser/main/lib/dataApi/copyImage.js @@ -3,19 +3,20 @@ const path = require('path') const { findStorage } = require('browser/lib/findStorage') /** - * @description To copy an image and return the path. + * @description Copy an image and return the path. * @param {String} filePath * @param {String} storageKey - * @return {String} an image path + * @param {Boolean} rename create new filename or leave the old one + * @return {Promise} an image path */ -function copyImage (filePath, storageKey) { +function copyImage (filePath, storageKey, rename = true) { return new Promise((resolve, reject) => { try { const targetStorage = findStorage(storageKey) const inputImage = fs.createReadStream(filePath) const imageExt = path.extname(filePath) - const imageName = Math.random().toString(36).slice(-16) + const imageName = rename ? Math.random().toString(36).slice(-16) : path.basename(filePath, imageExt) const basename = `${imageName}${imageExt}` const imageDir = path.join(targetStorage.path, 'images') if (!fs.existsSync(imageDir)) fs.mkdirSync(imageDir) From 9473a268925938b048fc1595ab0a6e28790b6f75 Mon Sep 17 00:00:00 2001 From: Nikolay Lopin Date: Sun, 25 Feb 2018 02:47:28 +0300 Subject: [PATCH 03/75] Move images between storages together with note 1. Added new step of moving note's images to `moveNote` function 2. Changed behaviour of sidebar navigation after move finished Issue #1578 --- browser/main/SideNav/StorageItem.js | 27 +++++---------------------- browser/main/lib/dataApi/moveNote.js | 23 +++++++++++++++++++++++ 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/browser/main/SideNav/StorageItem.js b/browser/main/SideNav/StorageItem.js index 5d7e6005..0df7a98e 100644 --- a/browser/main/SideNav/StorageItem.js +++ b/browser/main/SideNav/StorageItem.js @@ -191,33 +191,16 @@ class StorageItem extends React.Component { dropNote (storage, folder, dispatch, location, noteData) { noteData = noteData.filter((note) => folder.key !== note.folder) if (noteData.length === 0) return - const newNoteData = noteData.map((note) => Object.assign({}, note, {storage: storage, folder: folder.key})) Promise.all( - newNoteData.map((note) => dataApi.createNote(storage.key, note)) + noteData.map((note) => dataApi.moveNote(note.storage, note.key, storage.key, folder.key)) ) .then((createdNoteData) => { - createdNoteData.forEach((note) => { + createdNoteData.forEach((newNote) => { dispatch({ - type: 'UPDATE_NOTE', - note: note - }) - }) - }) - .catch((err) => { - console.error(`error on create notes: ${err}`) - }) - .then(() => { - return Promise.all( - noteData.map((note) => dataApi.deleteNote(note.storage, note.key)) - ) - }) - .then((deletedNoteData) => { - deletedNoteData.forEach((note) => { - dispatch({ - type: 'DELETE_NOTE', - storageKey: note.storageKey, - noteKey: note.noteKey + type: 'MOVE_NOTE', + originNote: noteData.find((note) => note.content === newNote.content), + note: newNote }) }) }) diff --git a/browser/main/lib/dataApi/moveNote.js b/browser/main/lib/dataApi/moveNote.js index 4580062e..b37b6ac5 100644 --- a/browser/main/lib/dataApi/moveNote.js +++ b/browser/main/lib/dataApi/moveNote.js @@ -1,10 +1,12 @@ const resolveStorageData = require('./resolveStorageData') const _ = require('lodash') const path = require('path') +const fs = require('fs') const CSON = require('@rokt33r/season') const keygen = require('browser/lib/keygen') const sander = require('sander') const { findStorage } = require('browser/lib/findStorage') +const copyImage = require('./copyImage') function moveNote (storageKey, noteKey, newStorageKey, newFolderKey) { let oldStorage, newStorage @@ -65,6 +67,27 @@ function moveNote (storageKey, noteKey, newStorageKey, newFolderKey) { return noteData }) + .then(function moveImages (noteData) { + const searchImagesRegex = /!\[.*?]\(\s*?\/:storage\/(.*\.\S*?)\)/gi + let match = searchImagesRegex.exec(noteData.content) + + const moveTasks = [] + while (match != null) { + const [, filename] = match + const oldPath = path.join(oldStorage.path, 'images', filename) + moveTasks.push( + copyImage(oldPath, noteData.storage, false) + .then(() => { + fs.unlinkSync(oldPath) + }) + ) + + // find next occurence + match = searchImagesRegex.exec(noteData.content) + } + + return Promise.all(moveTasks).then(() => noteData) + }) .then(function writeAndReturn (noteData) { CSON.writeFileSync(path.join(newStorage.path, 'notes', noteData.key + '.cson'), _.omit(noteData, ['key', 'storage'])) return noteData From f3f6095d81dec384c5b8b07588b76c1b5eef927b Mon Sep 17 00:00:00 2001 From: lurong Date: Sat, 24 Feb 2018 01:01:54 +0800 Subject: [PATCH 04/75] allow publishing markdown to wordpress --- browser/components/NoteItem.js | 6 +- browser/main/NoteList/index.js | 125 +++++++++++ browser/main/lib/ConfigManager.js | 9 + browser/main/lib/dataApi/updateNote.js | 3 + browser/main/modals/PreferencesModal/Blog.js | 198 ++++++++++++++++++ browser/main/modals/PreferencesModal/index.js | 15 +- 6 files changed, 353 insertions(+), 3 deletions(-) create mode 100644 browser/main/modals/PreferencesModal/Blog.js diff --git a/browser/components/NoteItem.js b/browser/components/NoteItem.js index 2c93dc18..253faa81 100644 --- a/browser/components/NoteItem.js +++ b/browser/components/NoteItem.js @@ -123,7 +123,11 @@ NoteItem.propTypes = { title: PropTypes.string.isrequired, tags: PropTypes.array, isStarred: PropTypes.bool.isRequired, - isTrashed: PropTypes.bool.isRequired + isTrashed: PropTypes.bool.isRequired, + blog: { + blogLink: PropTypes.string, + blogId: PropTypes.number + } }), handleNoteClick: PropTypes.func.isRequired, handleNoteContextMenu: PropTypes.func.isRequired, diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 8c3e8790..ff90404d 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -13,10 +13,13 @@ import searchFromNotes from 'browser/lib/search' import fs from 'fs' import path from 'path' import { hashHistory } from 'react-router' +import electron from 'electron' import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' +import markdown from '../../lib/markdown' const { remote } = require('electron') const { Menu, MenuItem, dialog } = remote +const WP_POST_PATH = '/wp/v2/posts' function sortByCreatedAt (a, b) { return new Date(b.createdAt) - new Date(a.createdAt) @@ -458,6 +461,9 @@ class NoteList extends React.Component { const deleteLabel = 'Delete Note' const cloneNote = 'Clone Note' const restoreNote = 'Restore Note' + const publishLabel = 'Publish Blog' + const updateLabel = 'Update Blog' + const openBlogLabel = 'Open Blog' const menu = new Menu() if (!location.pathname.match(/\/starred|\/trash/)) { @@ -482,6 +488,24 @@ class NoteList extends React.Component { label: cloneNote, click: this.cloneNote.bind(this) })) + if (note.type === 'MARKDOWN_NOTE') { + if (note.blog) { + menu.append(new MenuItem({ + label: updateLabel, + click: this.publishMarkdown.bind(this) + })) + menu.append(new MenuItem({ + label: openBlogLabel, + click: () => this.openBlog.bind(this)(note) + })) + } else { + menu.append(new MenuItem({ + label: publishLabel, + click: this.publishMarkdown.bind(this) + })) + } + } + menu.popup() } @@ -630,6 +654,107 @@ class NoteList extends React.Component { }) } + save (note) { + const { dispatch } = this.props + dataApi + .updateNote(note.storage, note.key, note) + .then((note) => { + dispatch({ + type: 'UPDATE_NOTE', + note: note + }) + }) + } + + publishMarkdown () { + if (this.pendingPublish) { + clearTimeout(this.pendingPublish) + } + this.pendingPublish = setTimeout(() => { + this.publishMarkdownNow() + }, 1000) + } + + publishMarkdownNow () { + const {selectedNoteKeys} = this.state + const notes = this.notes.map((note) => Object.assign({}, note)) + const selectedNotes = findNotesByKeys(notes, selectedNoteKeys) + const firstNote = selectedNotes[0] + const config = ConfigManager.get() + let {address, token, authMethod, username, password} = config.blog + if (authMethod === 'USER') { + token = `Basic ${window.btoa(`${username}:${password}`)}` + } else { + token = `Bearer ${token}` + } + var data = { + title: firstNote.title, + content: markdown.render(firstNote.content), + status: 'publish' + } + + let url = '' + let method = '' + if (firstNote.blog) { + url = `${address}${WP_POST_PATH}/${firstNote.blog.blogId}` + method = 'PUT' + } else { + url = `${address}${WP_POST_PATH}` + method = 'POST' + } + // eslint-disable-next-line no-undef + fetch(url, { + method: method, + body: JSON.stringify(data), + headers: { + 'Authorization': token, + 'Content-Type': 'application/json' + } + }).then(res => res.json()) + .then(response => { + firstNote.blog = { + blogLink: response.link, + blogId: response.id + } + this.save(firstNote) + this.confirmPublish(firstNote) + }) + .catch(() => { + this.confirmPublishError() + }) + } + + confirmPublishError () { + const { remote } = electron + const { dialog } = remote + const alertError = { + type: 'warning', + message: 'Publish Failed', + detail: 'Check and update your blog setting and try again.', + buttons: ['Confirm'] + } + dialog.showMessageBox(remote.getCurrentWindow(), alertError) + } + + confirmPublish (note) { + const buttonIndex = dialog.showMessageBox(remote.getCurrentWindow(), { + type: 'warning', + message: 'Publish Succeeded', + detail: `${note.title} is published at ${note.blog.blogLink}`, + buttons: ['Confirm', 'Open Blog'] + }) + + if (buttonIndex === 1) { + this.openBlog(note) + } + } + + openBlog (note) { + const { shell } = electron + console.log(note) + shell.openExternal(note.blog.blogLink) + } + importFromFile () { const options = { filters: [ diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 0c8d6ee9..e7e82a9b 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -49,6 +49,14 @@ export const DEFAULT_CONFIG = { latexBlockOpen: '$$', latexBlockClose: '$$', scrollPastEnd: false + }, + blog: { + type: 'wordpress', // Available value: wordpress, add more types in the future plz + address: 'http://wordpress.com/wp-json', + authMethod: 'JWT', // Available value: JWT, USER + token: '', + username: '', + password: '' } } @@ -151,6 +159,7 @@ function set (updates) { function assignConfigValues (originalConfig, rcConfig) { const config = Object.assign({}, DEFAULT_CONFIG, originalConfig, rcConfig) config.hotkey = Object.assign({}, DEFAULT_CONFIG.hotkey, originalConfig.hotkey, rcConfig.hotkey) + config.blog = Object.assign({}, DEFAULT_CONFIG.blog, originalConfig.blog, rcConfig.blog) config.ui = Object.assign({}, DEFAULT_CONFIG.ui, originalConfig.ui, rcConfig.ui) config.editor = Object.assign({}, DEFAULT_CONFIG.editor, originalConfig.editor, rcConfig.editor) config.preview = Object.assign({}, DEFAULT_CONFIG.preview, originalConfig.preview, rcConfig.preview) diff --git a/browser/main/lib/dataApi/updateNote.js b/browser/main/lib/dataApi/updateNote.js index 2fbd52c2..147fbc06 100644 --- a/browser/main/lib/dataApi/updateNote.js +++ b/browser/main/lib/dataApi/updateNote.js @@ -30,6 +30,9 @@ function validateInput (input) { validatedInput.isPinned = !!input.isPinned } + if (!_.isNil(input.blog)) { + validatedInput.blog = input.blog + } validatedInput.type = input.type switch (input.type) { case 'MARKDOWN_NOTE': diff --git a/browser/main/modals/PreferencesModal/Blog.js b/browser/main/modals/PreferencesModal/Blog.js new file mode 100644 index 00000000..675455f7 --- /dev/null +++ b/browser/main/modals/PreferencesModal/Blog.js @@ -0,0 +1,198 @@ +import React from 'react' +import CSSModules from 'browser/lib/CSSModules' +import styles from './ConfigTab.styl' +import ConfigManager from 'browser/main/lib/ConfigManager' +import store from 'browser/main/store' +import PropTypes from 'prop-types' +import _ from 'lodash' + +const electron = require('electron') +const { shell } = electron +const ipc = electron.ipcRenderer +class Blog extends React.Component { + constructor (props) { + super(props) + + this.state = { + config: props.config, + BlogAlert: null + } + } + + handleLinkClick (e) { + shell.openExternal(e.currentTarget.href) + e.preventDefault() + } + + clearMessage () { + _.debounce(() => { + this.setState({ + BlogAlert: null + }) + }, 2000)() + } + + componentDidMount () { + this.handleSettingDone = () => { + this.setState({BlogAlert: { + type: 'success', + message: 'Successfully applied!' + }}) + } + this.handleSettingError = (err) => { + this.setState({BlogAlert: { + type: 'error', + message: err.message != null ? err.message : 'Error occurs!' + }}) + } + this.oldBlog = this.state.config.blog + ipc.addListener('APP_SETTING_DONE', this.handleSettingDone) + ipc.addListener('APP_SETTING_ERROR', this.handleSettingError) + } + + handleBlogChange (e) { + const { config } = this.state + config.blog = { + password: !_.isNil(this.refs.passwordInput) ? this.refs.passwordInput.value : config.blog.password, + username: !_.isNil(this.refs.usernameInput) ? this.refs.usernameInput.value : config.blog.username, + token: !_.isNil(this.refs.tokenInput) ? this.refs.tokenInput.value : config.blog.token, + authMethod: this.refs.authMethodDropdown.value, + address: this.refs.addressInput.value, + type: this.refs.typeDropdown.value + } + this.setState({ + config + }) + if (_.isEqual(this.oldBlog, config.blog)) { + this.props.haveToSave() + } else { + this.props.haveToSave({ + tab: 'Blog', + type: 'warning', + message: 'You have to save!' + }) + } + } + + handleSaveButtonClick (e) { + const newConfig = { + blog: this.state.config.blog + } + + ConfigManager.set(newConfig) + + store.dispatch({ + type: 'SET_UI', + config: newConfig + }) + this.clearMessage() + this.props.haveToSave() + } + + render () { + const {config, BlogAlert} = this.state + const blogAlertElement = BlogAlert != null + ?

+ {BlogAlert.message} +

+ : null + return ( +
+
+
Blog
+
+
+ Blog Type +
+
+ +
+
+
+
Blog Address
+
+ this.handleBlogChange(e)} + ref='addressInput' + value={config.blog.address} + type='text' + /> +
+
+
+ + {blogAlertElement} +
+
+
Auth
+ +
+
+ Authentication Method +
+
+ +
+
+ { config.blog.authMethod === 'JWT' && +
+
Token
+
+ this.handleBlogChange(e)} + ref='tokenInput' + value={config.blog.token} + type='text' /> +
+
+ } + { config.blog.authMethod === 'USER' && +
+
+
UserName
+
+ this.handleBlogChange(e)} + ref='usernameInput' + value={config.blog.username} + type='text' /> +
+
+
+
Password
+
+ this.handleBlogChange(e)} + ref='passwordInput' + value={config.blog.password} + type='password' /> +
+
+
+ } +
+ ) + } +} + +Blog.propTypes = { + dispatch: PropTypes.func, + haveToSave: PropTypes.func +} + +export default CSSModules(Blog, styles) diff --git a/browser/main/modals/PreferencesModal/index.js b/browser/main/modals/PreferencesModal/index.js index 6cd5badc..09ca9a4e 100644 --- a/browser/main/modals/PreferencesModal/index.js +++ b/browser/main/modals/PreferencesModal/index.js @@ -6,6 +6,7 @@ import UiTab from './UiTab' import InfoTab from './InfoTab' import Crowdfunding from './Crowdfunding' import StoragesTab from './StoragesTab' +import Blog from './Blog' import ModalEscButton from 'browser/components/ModalEscButton' import CSSModules from 'browser/lib/CSSModules' import styles from './PreferencesModal.styl' @@ -19,7 +20,8 @@ class Preferences extends React.Component { this.state = { currentTab: 'STORAGES', UIAlert: '', - HotkeyAlert: '' + HotkeyAlert: '', + BlogAlert: '' } } @@ -75,6 +77,14 @@ class Preferences extends React.Component { return ( ) + case 'BLOG': + return ( + this.setState({BlogAlert: alert})} + /> + ) case 'STORAGES': default: return ( @@ -111,7 +121,8 @@ class Preferences extends React.Component { {target: 'HOTKEY', label: 'Hotkeys', Hotkey: this.state.HotkeyAlert}, {target: 'UI', label: 'Interface', UI: this.state.UIAlert}, {target: 'INFO', label: 'About'}, - {target: 'CROWDFUNDING', label: 'Crowdfunding'} + {target: 'CROWDFUNDING', label: 'Crowdfunding'}, + {target: 'BLOG', label: 'Blog', Blog: this.state.BlogAlert} ] const navButtons = tabs.map((tab) => { From 97600e526b0188ef317195df65f7e60109fd320b Mon Sep 17 00:00:00 2001 From: lurong Date: Sat, 24 Feb 2018 02:51:01 +0800 Subject: [PATCH 05/75] remove the first occurrence of title in content when publishing to WP --- browser/main/NoteList/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index ff90404d..56101b63 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -687,9 +687,10 @@ class NoteList extends React.Component { } else { token = `Bearer ${token}` } + let contentToRender = firstNote.content.replace(`# ${firstNote.title}`, '') var data = { title: firstNote.title, - content: markdown.render(firstNote.content), + content: markdown.render(contentToRender), status: 'publish' } From aef603ed8ce45feba9e19ffffdfd412cc7c85bea Mon Sep 17 00:00:00 2001 From: lurong Date: Sun, 25 Feb 2018 22:50:51 +0800 Subject: [PATCH 06/75] rebase and prefer const in node list --- browser/main/NoteList/index.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 56101b63..3db88dd1 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -681,13 +681,14 @@ class NoteList extends React.Component { const selectedNotes = findNotesByKeys(notes, selectedNoteKeys) const firstNote = selectedNotes[0] const config = ConfigManager.get() - let {address, token, authMethod, username, password} = config.blog + const {address, token, authMethod, username, password} = config.blog + let authToken = '' if (authMethod === 'USER') { - token = `Basic ${window.btoa(`${username}:${password}`)}` + authToken = `Basic ${window.btoa(`${username}:${password}`)}` } else { - token = `Bearer ${token}` + authToken = `Bearer ${token}` } - let contentToRender = firstNote.content.replace(`# ${firstNote.title}`, '') + const contentToRender = firstNote.content.replace(`# ${firstNote.title}`, '') var data = { title: firstNote.title, content: markdown.render(contentToRender), @@ -708,7 +709,7 @@ class NoteList extends React.Component { method: method, body: JSON.stringify(data), headers: { - 'Authorization': token, + 'Authorization': authToken, 'Content-Type': 'application/json' } }).then(res => res.json()) From 0d5e57eeabd635f4016e421b1c20cd653014fb10 Mon Sep 17 00:00:00 2001 From: pfftdammitchris Date: Sun, 25 Feb 2018 07:17:01 -0800 Subject: [PATCH 07/75] Adding the ability to copy the note link from the note list --- browser/main/NoteList/index.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 8c3e8790..8957b432 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -13,6 +13,7 @@ import searchFromNotes from 'browser/lib/search' import fs from 'fs' import path from 'path' import { hashHistory } from 'react-router' +import copy from 'copy-to-clipboard' import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' const { remote } = require('electron') @@ -70,6 +71,7 @@ class NoteList extends React.Component { this.getNoteFolder = this.getNoteFolder.bind(this) this.getViewType = this.getViewType.bind(this) this.restoreNote = this.restoreNote.bind(this) + this.copyNoteLink = this.copyNoteLink.bind(this) // TODO: not Selected noteKeys but SelectedNote(for reusing) this.state = { @@ -458,6 +460,7 @@ class NoteList extends React.Component { const deleteLabel = 'Delete Note' const cloneNote = 'Clone Note' const restoreNote = 'Restore Note' + const copyNoteLink = 'Copy Note Link' const menu = new Menu() if (!location.pathname.match(/\/starred|\/trash/)) { @@ -482,6 +485,10 @@ class NoteList extends React.Component { label: cloneNote, click: this.cloneNote.bind(this) })) + menu.append(new MenuItem({ + label: copyNoteLink, + click: this.copyNoteLink(note) + })) menu.popup() } @@ -630,6 +637,11 @@ class NoteList extends React.Component { }) } + copyNoteLink (note) { + const noteLink = `[${note.title}](${note.storage}-${note.key})` + return copy(noteLink) + } + importFromFile () { const options = { filters: [ From 6c341d8fa5bc2e741f93be9a1fdcdcf5ea39caae Mon Sep 17 00:00:00 2001 From: pfftdammitchris Date: Sun, 25 Feb 2018 07:41:50 -0800 Subject: [PATCH 08/75] Fixes UI overlapping in the snippet editor (bottom options) --- browser/styles/index.styl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/styles/index.styl b/browser/styles/index.styl index 1bd183bf..6fb208b1 100644 --- a/browser/styles/index.styl +++ b/browser/styles/index.styl @@ -5,7 +5,7 @@ $danger-color = #c9302c $danger-lighten-color = lighten(#c9302c, 5%) // Layouts -$statusBar-height = 0px +$statusBar-height = 22px $sideNav-width = 200px $sideNav--folded-width = 44px $topBar-height = 60px @@ -347,4 +347,4 @@ modalSolarizedDark() width 100% background-color $ui-solarized-dark-backgroundColor overflow hidden - border-radius $modal-border-radius \ No newline at end of file + border-radius $modal-border-radius From d76ecd5423ab2352ad4d26e0475c1897e172d25d Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Mon, 26 Feb 2018 13:20:24 +0100 Subject: [PATCH 09/75] Fixed bad merge; closes #1586; related to #1521 --- browser/components/CodeEditor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 29c3748b..f2b3d8f1 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -32,6 +32,7 @@ export default class CodeEditor extends React.Component { constructor (props) { super(props) + this.scrollHandler = _.debounce(this.handleScroll.bind(this), 100, {leading: false, trailing: true}) this.changeHandler = (e) => this.handleChange(e) this.blurHandler = (editor, e) => { if (e == null) return null @@ -81,7 +82,6 @@ export default class CodeEditor extends React.Component { } } }) - this.scrollHandler = _.debounce(this.handleScroll.bind(this), 100, {leading: false, trailing: true}) } componentDidMount () { From e5f986a95932ae14a36590bc4dcf22f2acb025f8 Mon Sep 17 00:00:00 2001 From: lijinglue Date: Mon, 26 Feb 2018 21:12:42 +0800 Subject: [PATCH 10/75] checking if return is valid before creating the blog attr in note --- browser/main/NoteList/index.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 3db88dd1..7075c0ef 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -489,7 +489,7 @@ class NoteList extends React.Component { click: this.cloneNote.bind(this) })) if (note.type === 'MARKDOWN_NOTE') { - if (note.blog) { + if (note.blog && note.blog.blogLink && note.blog.blogId) { menu.append(new MenuItem({ label: updateLabel, click: this.publishMarkdown.bind(this) @@ -697,7 +697,7 @@ class NoteList extends React.Component { let url = '' let method = '' - if (firstNote.blog) { + if (firstNote.blog && firstNote.blog.blogId) { url = `${address}${WP_POST_PATH}/${firstNote.blog.blogId}` method = 'PUT' } else { @@ -714,6 +714,9 @@ class NoteList extends React.Component { } }).then(res => res.json()) .then(response => { + if (_.isNil(response.link) || _.isNil(response.id)) { + return Promise.reject(); + } firstNote.blog = { blogLink: response.link, blogId: response.id @@ -721,7 +724,8 @@ class NoteList extends React.Component { this.save(firstNote) this.confirmPublish(firstNote) }) - .catch(() => { + .catch((error) => { + console.error(error) this.confirmPublishError() }) } @@ -753,7 +757,6 @@ class NoteList extends React.Component { openBlog (note) { const { shell } = electron - console.log(note) shell.openExternal(note.blog.blogLink) } From 7c525ab7a650d565e6a05ec971434e79490be37b Mon Sep 17 00:00:00 2001 From: lurong Date: Mon, 26 Feb 2018 21:27:42 +0800 Subject: [PATCH 11/75] fix lint --- browser/main/NoteList/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 7075c0ef..13cb4400 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -715,7 +715,7 @@ class NoteList extends React.Component { }).then(res => res.json()) .then(response => { if (_.isNil(response.link) || _.isNil(response.id)) { - return Promise.reject(); + return Promise.reject() } firstNote.blog = { blogLink: response.link, From 650215871684d3c7f7445440708039f0b07b8eca Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Mon, 26 Feb 2018 16:07:27 +0100 Subject: [PATCH 12/75] Add search clear options; closes #1525 --- browser/components/CodeEditor.js | 7 +++++ browser/main/Detail/SnippetNoteDetail.js | 3 ++ browser/main/NoteList/index.js | 15 ++++++++-- browser/main/TopBar/TopBar.styl | 28 ++++++++++++++++- browser/main/TopBar/index.js | 38 +++++++++++++++++------- lib/main-menu.js | 18 +++++++++++ 6 files changed, 96 insertions(+), 13 deletions(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 29c3748b..6cbec121 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -8,6 +8,7 @@ import copyImage from 'browser/main/lib/dataApi/copyImage' import { findStorage } from 'browser/lib/findStorage' import fs from 'fs' import eventEmitter from 'browser/main/lib/eventEmitter' +const { ipcRenderer } = require('electron') CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js' @@ -33,7 +34,11 @@ export default class CodeEditor extends React.Component { super(props) this.changeHandler = (e) => this.handleChange(e) + this.focusHandler = () => { + ipcRenderer.send('editor:focused', true) + } this.blurHandler = (editor, e) => { + ipcRenderer.send('editor:focused', false) if (e == null) return null let el = e.relatedTarget while (el != null) { @@ -139,6 +144,7 @@ export default class CodeEditor extends React.Component { this.setMode(this.props.mode) + this.editor.on('focus', this.focusHandler) this.editor.on('blur', this.blurHandler) this.editor.on('change', this.changeHandler) this.editor.on('paste', this.pasteHandler) @@ -162,6 +168,7 @@ export default class CodeEditor extends React.Component { } componentWillUnmount () { + this.editor.off('focus', this.focusHandler) this.editor.off('blur', this.blurHandler) this.editor.off('change', this.changeHandler) this.editor.off('paste', this.pasteHandler) diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index dbef37ca..6f8bbb3d 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -343,6 +343,7 @@ class SnippetNoteDetail extends React.Component { handleKeyDown (e) { switch (e.keyCode) { + // tab key case 9: if (e.ctrlKey && !e.shiftKey) { e.preventDefault() @@ -355,6 +356,7 @@ class SnippetNoteDetail extends React.Component { this.focusEditor() } break + // L key case 76: { const isSuper = global.process.platform === 'darwin' @@ -366,6 +368,7 @@ class SnippetNoteDetail extends React.Component { } } break + // T key case 84: { const isSuper = global.process.platform === 'darwin' diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 8c3e8790..795b4503 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -257,27 +257,38 @@ class NoteList extends React.Component { handleNoteListKeyDown (e) { if (e.metaKey || e.ctrlKey) return true + // A key if (e.keyCode === 65 && !e.shiftKey) { e.preventDefault() ee.emit('top:new-note') } + // D key if (e.keyCode === 68) { e.preventDefault() this.deleteNote() } + // E key if (e.keyCode === 69) { e.preventDefault() ee.emit('detail:focus') } - if (e.keyCode === 38) { + // F or S key + if (e.keyCode === 70 || e.keyCode === 83) { + e.preventDefault() + ee.emit('top:focus-search') + } + + // UP or K key + if (e.keyCode === 38 || e.keyCode === 75) { e.preventDefault() this.selectPriorNote() } - if (e.keyCode === 40) { + // DOWN or J key + if (e.keyCode === 40 || e.keyCode === 74) { e.preventDefault() this.selectNextNote() } diff --git a/browser/main/TopBar/TopBar.styl b/browser/main/TopBar/TopBar.styl index eb0fc12f..0956571f 100644 --- a/browser/main/TopBar/TopBar.styl +++ b/browser/main/TopBar/TopBar.styl @@ -40,6 +40,32 @@ $control-height = 34px padding-bottom 2px background-color $ui-noteList-backgroundColor +.control-search-input-clear + height 16px + width 16px + position absolute + right 40px + top 10px + z-index 300 + border none + background-color transparent + color #999 + &:hover .control-search-input-clear-tooltip + opacity 1 + +.control-search-input-clear-tooltip + tooltip() + position fixed + pointer-events none + top 50px + left 433px + z-index 200 + padding 5px + line-height normal + border-radius 2px + opacity 0 + transition 0.1s + .control-search-optionList position fixed z-index 200 @@ -207,4 +233,4 @@ body[data-theme="solarized-dark"] background-color $ui-solarized-dark-noteList-backgroundColor input background-color $ui-solarized-dark-noteList-backgroundColor - color $ui-solarized-dark-text-color \ No newline at end of file + color $ui-solarized-dark-text-color diff --git a/browser/main/TopBar/index.js b/browser/main/TopBar/index.js index 6b4a118e..0a602a5c 100644 --- a/browser/main/TopBar/index.js +++ b/browser/main/TopBar/index.js @@ -36,6 +36,17 @@ class TopBar extends React.Component { ee.off('code:init', this.codeInitHandler) } + handleSearchClearButton (e) { + const { router } = this.context + this.setState({ + search: '', + isSearching: false + }) + this.refs.search.childNodes[0].blur + router.push('/searched') + e.preventDefault() + } + handleKeyDown (e) { // reset states this.setState({ @@ -43,6 +54,11 @@ class TopBar extends React.Component { isIME: false }) + // Clear search on ESC + if (e.keyCode === 27) { + return this.handleSearchClearButton(e) + } + // When the key is an alphabet, del, enter or ctr if (e.keyCode <= 90 || e.keyCode >= 186 && e.keyCode <= 222) { this.setState({ @@ -114,10 +130,12 @@ class TopBar extends React.Component { } handleOnSearchFocus () { + const el = this.refs.search.childNodes[0] if (this.state.isSearching) { - this.refs.search.childNodes[0].blur() + el.blur() } else { - this.refs.search.childNodes[0].focus() + el.focus() + el.setSelectionRange(0, el.value.length) } } @@ -150,15 +168,15 @@ class TopBar extends React.Component { type='text' className='searchInput' /> + {this.state.search !== '' && + + } - {this.state.search > 0 && - - } - {location.pathname === '/trashed' ? '' diff --git a/lib/main-menu.js b/lib/main-menu.js index 0d49ab86..81e5fc22 100644 --- a/lib/main-menu.js +++ b/lib/main-menu.js @@ -1,6 +1,7 @@ const electron = require('electron') const BrowserWindow = electron.BrowserWindow const shell = electron.shell +const ipc = electron.ipcMain const mainWindow = require('./main-window') const macOS = process.platform === 'darwin' @@ -259,6 +260,23 @@ const view = { ] } +let editorFocused + +// Define extra shortcut keys +mainWindow.webContents.on('before-input-event', (event, input) => { + // Synonyms for Search (Find) + if (input.control && input.key === 'f' && input.type === 'keyDown') { + if (!editorFocused) { + mainWindow.webContents.send('top:focus-search') + event.preventDefault() + } + } +}) + +ipc.on('editor:focused', (event, isFocused) => { + editorFocused = isFocused +}) + const window = { label: 'Window', submenu: [ From 5b8519b2b806dfa7f2d31ae665af5cbfd651f94d Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Mon, 26 Feb 2018 16:20:45 +0100 Subject: [PATCH 13/75] Bind up/down to prev/next event; closes #1167 --- browser/main/TopBar/index.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/browser/main/TopBar/index.js b/browser/main/TopBar/index.js index 0a602a5c..246ef614 100644 --- a/browser/main/TopBar/index.js +++ b/browser/main/TopBar/index.js @@ -59,6 +59,18 @@ class TopBar extends React.Component { return this.handleSearchClearButton(e) } + // Next note on DOWN key + if (e.keyCode === 40) { + ee.emit('list:next') + e.preventDefault() + } + + // Prev note on UP key + if (e.keyCode === 38) { + ee.emit('list:prior') + e.preventDefault() + } + // When the key is an alphabet, del, enter or ctr if (e.keyCode <= 90 || e.keyCode >= 186 && e.keyCode <= 222) { this.setState({ From 1f1e54553889f93722dfca608040adf20e769b4a Mon Sep 17 00:00:00 2001 From: Jannick Hemelhof Date: Mon, 26 Feb 2018 12:26:29 +0100 Subject: [PATCH 14/75] Fix for list insertion --- .../boost/boostNewLineIndentContinueMarkdownList.js | 0 lib/main.html | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename {node_modules => extra_scripts}/boost/boostNewLineIndentContinueMarkdownList.js (100%) diff --git a/node_modules/boost/boostNewLineIndentContinueMarkdownList.js b/extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js similarity index 100% rename from node_modules/boost/boostNewLineIndentContinueMarkdownList.js rename to extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js diff --git a/lib/main.html b/lib/main.html index 53520957..8852bd9e 100644 --- a/lib/main.html +++ b/lib/main.html @@ -78,7 +78,7 @@ - + From 012908e32d32ccd9468be9634020922dfc95ae02 Mon Sep 17 00:00:00 2001 From: Jannick Hemelhof Date: Mon, 26 Feb 2018 16:43:13 +0100 Subject: [PATCH 15/75] Linting fixes --- .../boostNewLineIndentContinueMarkdownList.js | 90 ++++++++++--------- 1 file changed, 48 insertions(+), 42 deletions(-) diff --git a/extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js b/extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js index 159d20eb..aa766f6e 100644 --- a/extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js +++ b/extra_scripts/boost/boostNewLineIndentContinueMarkdownList.js @@ -1,46 +1,52 @@ -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("../codemirror/lib/codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["../codemirror/lib/codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; +(function (mod) { + if (typeof exports === 'object' && typeof module === 'object') { // Common JS + mod(require('../codemirror/lib/codemirror')) + } else if (typeof define === 'function' && define.amd) { // AMD + define(['../codemirror/lib/codemirror'], mod) + } else { // Plain browser env + mod(CodeMirror) + } +})(function (CodeMirror) { + 'use strict' - var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/, - emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/, - unorderedListRE = /[*+-]\s/; + var listRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]\s|[*+-]\s|(\d+)([.)]))(\s*)/ + var emptyListRE = /^(\s*)(>[> ]*|[*+-] \[[x ]\]|[*+-]|(\d+)[.)])(\s*)$/ + var unorderedListRE = /[*+-]\s/ - CodeMirror.commands.boostNewLineAndIndentContinueMarkdownList = function(cm) { - if (cm.getOption("disableInput")) return CodeMirror.Pass; - var ranges = cm.listSelections(), replacements = []; - for (var i = 0; i < ranges.length; i++) { - var pos = ranges[i].head; - var eolState = cm.getStateAfter(pos.line); - var inList = eolState.list !== false; - var inQuote = eolState.quote !== 0; - var line = cm.getLine(pos.line), match = listRE.exec(line); - if (!ranges[i].empty() || (!inList && !inQuote) || !match || pos.ch < match[2].length - 1) { - cm.execCommand("newlineAndIndent"); - return; - } - if (emptyListRE.test(line)) { - if (!/>\s*$/.test(line)) cm.replaceRange("", { - line: pos.line, ch: 0 - }, { - line: pos.line, ch: pos.ch + 1 - }); - replacements[i] = "\n"; - } else { - var indent = match[1], after = match[5]; - var bullet = unorderedListRE.test(match[2]) || match[2].indexOf(">") >= 0 - ? match[2].replace("x", " ") - : (parseInt(match[3], 10) + 1) + match[4]; - replacements[i] = "\n" + indent + bullet + after; - } + CodeMirror.commands.boostNewLineAndIndentContinueMarkdownList = function (cm) { + if (cm.getOption('disableInput')) return CodeMirror.Pass + var ranges = cm.listSelections() + var replacements = [] + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].head + var eolState = cm.getStateAfter(pos.line) + var inList = eolState.list !== false + var inQuote = eolState.quote !== 0 + var line = cm.getLine(pos.line) + var match = listRE.exec(line) + if (!ranges[i].empty() || (!inList && !inQuote) || !match || pos.ch < match[2].length - 1) { + cm.execCommand('newlineAndIndent') + return + } + if (emptyListRE.test(line)) { + if (!/>\s*$/.test(line)) { + cm.replaceRange('', { + line: pos.line, ch: 0 + }, { + line: pos.line, ch: pos.ch + 1 + }) } + replacements[i] = '\n' + } else { + var indent = match[1] + var after = match[5] + var bullet = unorderedListRE.test(match[2]) || match[2].indexOf('>') >= 0 + ? match[2].replace('x', ' ') + : (parseInt(match[3], 10) + 1) + match[4] + replacements[i] = '\n' + indent + bullet + after + } + } - cm.replaceSelections(replacements); - }; -}); + cm.replaceSelections(replacements) + } +}) From c5c78763d1b1066b5bdc8099919eed44aabdf831 Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Tue, 27 Feb 2018 23:17:15 +1100 Subject: [PATCH 16/75] fixed missing zoom button --- browser/main/StatusBar/StatusBar.styl | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/browser/main/StatusBar/StatusBar.styl b/browser/main/StatusBar/StatusBar.styl index e055dc0d..9f189fec 100644 --- a/browser/main/StatusBar/StatusBar.styl +++ b/browser/main/StatusBar/StatusBar.styl @@ -21,20 +21,19 @@ color white .zoom - display none - // navButtonColor() - // color rgba(0,0,0,.54) - // height 20px - // display flex - // padding 0 - // align-items center - // background-color transparent - // &:hover - // color $ui-active-color - // &:active - // color $ui-active-color - // span - // margin-left 5px + navButtonColor() + color rgba(0,0,0,.54) + height 20px + display flex + padding 0 + align-items center + background-color transparent + &:hover + color $ui-active-color + &:active + color $ui-active-color + span + margin-left 5px .update navButtonColor() From 6439810d03c27b092b77c6bbd608a525ed508f7c Mon Sep 17 00:00:00 2001 From: kawmra Date: Wed, 28 Feb 2018 01:54:31 +0900 Subject: [PATCH 17/75] Decode the fetched body correctly if content-type was provided --- browser/components/CodeEditor.js | 28 +++++++++++++++++++++++++++- package.json | 1 + yarn.lock | 4 ++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/browser/components/CodeEditor.js b/browser/components/CodeEditor.js index 29c3748b..9d7adcdb 100644 --- a/browser/components/CodeEditor.js +++ b/browser/components/CodeEditor.js @@ -8,6 +8,7 @@ import copyImage from 'browser/main/lib/dataApi/copyImage' import { findStorage } from 'browser/lib/findStorage' import fs from 'fs' import eventEmitter from 'browser/main/lib/eventEmitter' +import iconv from 'iconv-lite' CodeMirror.modeURL = '../node_modules/codemirror/mode/%N/%N.js' @@ -317,7 +318,7 @@ export default class CodeEditor extends React.Component { fetch(pastedTxt, { method: 'get' }).then((response) => { - return (response.text()) + return this.decodeResponse(response) }).then((response) => { const parsedResponse = (new window.DOMParser()).parseFromString(response, 'text/html') const value = editor.getValue() @@ -335,6 +336,31 @@ export default class CodeEditor extends React.Component { }) } + decodeResponse (response) { + const headers = response.headers + const _charset = headers.has('content-type') + ? this.extractContentTypeCharset(headers.get('content-type')) + : undefined + return response.arrayBuffer().then((buff) => { + return new Promise((resolve, reject) => { + try { + const charset = _charset !== undefined && iconv.encodingExists(_charset) ? _charset : 'utf-8' + resolve(iconv.decode(new Buffer(buff), charset).toString()) + } catch (e) { + reject(e) + } + }) + }) + } + + extractContentTypeCharset (contentType) { + return contentType.split(';').filter((str) => { + return str.trim().toLowerCase().startsWith('charset') + }).map((str) => { + return str.replace(/['"]/g, '').split('=')[1] + })[0] + } + render () { const { className, fontSize } = this.props let fontFamily = this.props.fontFamily diff --git a/package.json b/package.json index db2a9733..ff2d280b 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "electron-gh-releases": "^2.0.2", "flowchart.js": "^1.6.5", "font-awesome": "^4.3.0", + "iconv-lite": "^0.4.19", "immutable": "^3.8.1", "js-sequence-diagrams": "^1000000.0.6", "katex": "^0.8.3", diff --git a/yarn.lock b/yarn.lock index c1a949a4..c5da5dcd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3414,6 +3414,10 @@ iconv-lite@0.4.13, iconv-lite@~0.4.13: version "0.4.13" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" +iconv-lite@^0.4.19: + version "0.4.19" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" + iconv-lite@~0.2.11: version "0.2.11" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.2.11.tgz#1ce60a3a57864a292d1321ff4609ca4bb965adc8" From aab192223a14f31d2ce5a83f1d5ae03cf73a5679 Mon Sep 17 00:00:00 2001 From: Romain Le Quellec Date: Wed, 28 Feb 2018 11:39:45 +0100 Subject: [PATCH 18/75] add Toggle FullScreen feat + shortcut --- lib/main-menu.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/main-menu.js b/lib/main-menu.js index 0d49ab86..783b2f0d 100644 --- a/lib/main-menu.js +++ b/lib/main-menu.js @@ -267,6 +267,11 @@ const window = { accelerator: 'Command+M', selector: 'performMiniaturize:' }, + { + label: 'Toggle Full Screen', + accelerator: 'Command+Control+F', + selector: 'toggleFullScreen:' + }, { label: 'Close', accelerator: 'Command+W', From a537f9762b6a9a96bc94c999e2ebdd0101a76e04 Mon Sep 17 00:00:00 2001 From: Roman Klopsch Date: Wed, 28 Feb 2018 16:00:42 +0100 Subject: [PATCH 19/75] Fix missing progress bar in note list --- browser/components/NoteItem.styl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/components/NoteItem.styl b/browser/components/NoteItem.styl index f213348a..5203ccea 100644 --- a/browser/components/NoteItem.styl +++ b/browser/components/NoteItem.styl @@ -117,7 +117,7 @@ $control-height = 30px font-size 12px line-height 20px overflow ellipsis - display flex + display block .item-bottom-tagList flex 1 From 88ac6c6fc62e19581108cfcdb91d3834ca441a89 Mon Sep 17 00:00:00 2001 From: pfftdammitchris Date: Wed, 28 Feb 2018 16:34:42 -0800 Subject: [PATCH 20/75] Sort tags alphabetically --- browser/main/SideNav/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 6d05e37b..a08d2b39 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -117,9 +117,9 @@ class SideNav extends React.Component { tagListComponent () { const { data, location } = this.props - const tagList = data.tagNoteMap.map((tag, name) => { + const tagList = _.sortBy(data.tagNoteMap.map((tag, name) => { return { name, size: tag.size } - }) + }), ['name']) return ( tagList.map(tag => { return ( From 5aa7ef573837c76925d10e01fa3820d5037d321f Mon Sep 17 00:00:00 2001 From: pfftdammitchris Date: Wed, 28 Feb 2018 18:33:14 -0800 Subject: [PATCH 21/75] Folders in the side nav are now draggable --- browser/components/StorageItem.js | 48 ++++++++++++++++------------- browser/main/SideNav/StorageItem.js | 15 +++++---- browser/main/SideNav/index.js | 17 +++++++++- 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/browser/components/StorageItem.js b/browser/components/StorageItem.js index 25be3c57..c92579da 100644 --- a/browser/components/StorageItem.js +++ b/browser/components/StorageItem.js @@ -6,6 +6,7 @@ import React from 'react' import styles from './StorageItem.styl' import CSSModules from 'browser/lib/CSSModules' import _ from 'lodash' +import { SortableHandle } from 'react-sortable-hoc' /** * @param {boolean} isActive @@ -23,32 +24,35 @@ import _ from 'lodash' const StorageItem = ({ isActive, handleButtonClick, handleContextMenu, folderName, folderColor, isFolded, noteCount, handleDrop, handleDragEnter, handleDragLeave -}) => ( - -) + {(!isFolded && _.isNumber(noteCount)) && + {noteCount} + } + {isFolded && + + {folderName} + + } + + ) +} StorageItem.propTypes = { isActive: PropTypes.bool.isRequired, diff --git a/browser/main/SideNav/StorageItem.js b/browser/main/SideNav/StorageItem.js index 5d7e6005..89b654c0 100644 --- a/browser/main/SideNav/StorageItem.js +++ b/browser/main/SideNav/StorageItem.js @@ -9,6 +9,7 @@ import RenameFolderModal from 'browser/main/modals/RenameFolderModal' import dataApi from 'browser/main/lib/dataApi' import StorageItemChild from 'browser/components/StorageItem' import _ from 'lodash' +import { SortableElement } from 'react-sortable-hoc' const { remote } = require('electron') const { Menu, dialog } = remote @@ -236,7 +237,8 @@ class StorageItem extends React.Component { render () { const { storage, location, isFolded, data, dispatch } = this.props const { folderNoteMap, trashedSet } = data - const folderList = storage.folders.map((folder) => { + const SortableStorageItemChild = SortableElement(StorageItemChild) + const folderList = storage.folders.map((folder, index) => { const isActive = !!(location.pathname.match(new RegExp('\/storages\/' + storage.key + '\/folders\/' + folder.key))) const noteSet = folderNoteMap.get(storage.key + '-' + folder.key) @@ -250,8 +252,9 @@ class StorageItem extends React.Component { noteCount = noteSet.size - trashedNoteCount } return ( - this.handleFolderButtonClick(folder.key)(e)} handleContextMenu={(e) => this.handleFolderButtonContextMenu(e, folder)} @@ -273,9 +276,9 @@ class StorageItem extends React.Component { key={storage.key} >
this.handleHeaderContextMenu(e)} > diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 6d05e37b..19433477 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -17,6 +17,7 @@ import EventEmitter from 'browser/main/lib/eventEmitter' import PreferenceButton from './PreferenceButton' import ListButton from './ListButton' import TagButton from './TagButton' +import {SortableContainer} from 'react-sortable-hoc' class SideNav extends React.Component { // TODO: should not use electron stuff v0.7 @@ -68,6 +69,17 @@ class SideNav extends React.Component { router.push('/alltags') } + onSortEnd (storage) { + return ({oldIndex, newIndex}) => { + const { dispatch } = this.props + dataApi + .reorderFolder(storage.key, oldIndex, newIndex) + .then((data) => { + dispatch({ type: 'REORDER_FOLDER', storage: data.storage }) + }) + } + } + SideNavComponent (isFolded, storageList) { const { location, data } = this.props @@ -180,13 +192,16 @@ class SideNav extends React.Component { const isFolded = config.isSideNavFolded const storageList = data.storageMap.map((storage, key) => { - return }) const style = {} From e89c0a3e61e1eb5ac3761a1ede5fd6c6bd5d389e Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Fri, 2 Mar 2018 00:06:58 +1100 Subject: [PATCH 22/75] added support for toggling smart quotes in preview --- browser/components/MarkdownEditor.js | 1 + browser/components/MarkdownPreview.js | 24 +- browser/components/MarkdownSplitEditor.js | 1 + browser/lib/markdown.js | 322 +++++++++--------- browser/main/lib/ConfigManager.js | 3 +- browser/main/modals/PreferencesModal/UiTab.js | 13 +- 6 files changed, 197 insertions(+), 167 deletions(-) diff --git a/browser/components/MarkdownEditor.js b/browser/components/MarkdownEditor.js index f02a146a..d0e2f505 100644 --- a/browser/components/MarkdownEditor.js +++ b/browser/components/MarkdownEditor.js @@ -279,6 +279,7 @@ class MarkdownEditor extends React.Component { lineNumber={config.preview.lineNumber} indentSize={editorIndentSize} scrollPastEnd={config.preview.scrollPastEnd} + smartQuotes={config.preview.smartQuotes} ref='preview' onContextMenu={(e) => this.handleContextMenu(e)} onDoubleClick={(e) => this.handleDoubleClick(e)} diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index c5b0355d..ddda74bb 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types' import React from 'react' -import markdown from 'browser/lib/markdown' +import Markdown from 'browser/lib/markdown' import _ from 'lodash' import CodeMirror from 'codemirror' import 'codemirror-mode-elixir' @@ -130,6 +130,13 @@ export default class MarkdownPreview extends React.Component { this.printHandler = () => this.handlePrint() this.linkClickHandler = this.handlelinkClick.bind(this) + this.initMarkdown = this.initMarkdown.bind(this) + this.initMarkdown() + } + + initMarkdown () { + const { smartQuotes } = this.props + this.markdown = new Markdown({ typographer: smartQuotes }) } handlePreviewAnchorClick (e) { @@ -198,7 +205,7 @@ export default class MarkdownPreview extends React.Component { const {fontFamily, fontSize, codeBlockFontFamily, lineNumber, codeBlockTheme} = this.getStyleParams() const inlineStyles = buildStyle(fontFamily, fontSize, codeBlockFontFamily, lineNumber, codeBlockTheme, lineNumber) - const body = markdown.render(noteContent) + const body = this.markdown.render(noteContent) const files = [this.GetCodeThemeLink(codeBlockTheme), ...CSS_FILES] files.forEach((file) => { @@ -309,6 +316,10 @@ export default class MarkdownPreview extends React.Component { componentDidUpdate (prevProps) { if (prevProps.value !== this.props.value) this.rewriteIframe() + if (prevProps.smartQuotes !== this.props.smartQuotes) { + this.initMarkdown() + this.rewriteIframe() + } if (prevProps.fontFamily !== this.props.fontFamily || prevProps.fontSize !== this.props.fontSize || prevProps.codeBlockFontFamily !== this.props.codeBlockFontFamily || @@ -374,7 +385,7 @@ export default class MarkdownPreview extends React.Component { value = value.replace(codeBlock, htmlTextHelper.encodeEntities(codeBlock)) }) } - this.refs.root.contentWindow.document.body.innerHTML = markdown.render(value) + this.refs.root.contentWindow.document.body.innerHTML = this.markdown.render(value) _.forEach(this.refs.root.contentWindow.document.querySelectorAll('a'), (el) => { this.fixDecodedURI(el) @@ -390,9 +401,9 @@ export default class MarkdownPreview extends React.Component { }) _.forEach(this.refs.root.contentWindow.document.querySelectorAll('img'), (el) => { - el.src = markdown.normalizeLinkText(el.src) + el.src = this.markdown.normalizeLinkText(el.src) if (!/\/:storage/.test(el.src)) return - el.src = `file:///${markdown.normalizeLinkText(path.join(storagePath, 'images', path.basename(el.src)))}` + el.src = `file:///${this.markdown.normalizeLinkText(path.join(storagePath, 'images', path.basename(el.src)))}` }) codeBlockTheme = consts.THEMES.some((_theme) => _theme === codeBlockTheme) @@ -533,5 +544,6 @@ MarkdownPreview.propTypes = { className: PropTypes.string, value: PropTypes.string, showCopyNotification: PropTypes.bool, - storagePath: PropTypes.string + storagePath: PropTypes.string, + smartQuotes: PropTypes.bool } diff --git a/browser/components/MarkdownSplitEditor.js b/browser/components/MarkdownSplitEditor.js index 505fbaf4..0aa2d16c 100644 --- a/browser/components/MarkdownSplitEditor.js +++ b/browser/components/MarkdownSplitEditor.js @@ -127,6 +127,7 @@ class MarkdownSplitEditor extends React.Component { codeBlockFontFamily={config.editor.fontFamily} lineNumber={config.preview.lineNumber} scrollPastEnd={config.preview.scrollPastEnd} + smartQuotes={config.preview.smartQuotes} ref='preview' tabInde='0' value={value} diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index d0801a1b..e75e13ee 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -19,171 +19,175 @@ function createGutter (str, firstLineNumber) { return '' + lines.join('') + '' } -var md = markdownit({ - typographer: true, - linkify: true, - html: true, - xhtmlOut: true, - breaks: true, - highlight: function (str, lang) { - const delimiter = ':' - const langInfo = lang.split(delimiter) - const langType = langInfo[0] - const fileName = langInfo[1] || '' - const firstLineNumber = parseInt(langInfo[2], 10) +class Markdown { + constructor (options = {}) { + const defaultOptions = { + typographer: true, + linkify: true, + html: true, + xhtmlOut: true, + breaks: true, + highlight: function (str, lang) { + const delimiter = ':' + const langInfo = lang.split(delimiter) + const langType = langInfo[0] + const fileName = langInfo[1] || '' + const firstLineNumber = parseInt(langInfo[2], 10) - if (langType === 'flowchart') { - return `
${str}
` - } - if (langType === 'sequence') { - return `
${str}
` - } - return '
' +
-      '' + fileName + '' +
-      createGutter(str, firstLineNumber) +
-      '' +
-      str +
-      '
' - } -}) -md.use(emoji, { - shortcuts: {} -}) -md.use(math, { - inlineOpen: config.preview.latexInlineOpen, - inlineClose: config.preview.latexInlineClose, - blockOpen: config.preview.latexBlockOpen, - blockClose: config.preview.latexBlockClose, - inlineRenderer: function (str) { - let output = '' - try { - output = katex.renderToString(str.trim()) - } catch (err) { - output = `${err.message}` - } - return output - }, - blockRenderer: function (str) { - let output = '' - try { - output = katex.renderToString(str.trim(), { displayMode: true }) - } catch (err) { - output = `
${err.message}
` - } - return output - } -}) -md.use(require('markdown-it-imsize')) -md.use(require('markdown-it-footnote')) -md.use(require('markdown-it-multimd-table')) -md.use(require('markdown-it-named-headers'), { - slugify: (header) => { - return encodeURI(header.trim() - .replace(/[\]\[\!\"\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~]/g, '') - .replace(/\s+/g, '-')) - .replace(/\-+$/, '') - } -}) -md.use(require('markdown-it-kbd')) - -const deflate = require('markdown-it-plantuml/lib/deflate') -md.use(require('markdown-it-plantuml'), '', { - generateSource: function (umlCode) { - const s = unescape(encodeURIComponent(umlCode)) - const zippedCode = deflate.encode64( - deflate.zip_deflate(`@startuml\n${s}\n@enduml`, 9) - ) - return `http://www.plantuml.com/plantuml/svg/${zippedCode}` - } -}) - -// Override task item -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') - const endLine = state.lineMax - - // jump line-by-line until empty one or EOF - 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 } - - // quirk for blockquotes, this line should already be checked by that rule - if (state.sCount[nextLine] < 0) { continue } - - // Some tags can terminate paragraph without empty line. - terminate = false - for (i = 0, l = terminatorRules.length; i < l; i++) { - if (terminatorRules[i](state, nextLine, endLine, true)) { - terminate = true - break - } - } - if (terminate) { break } - } - - content = state.getLines(startLine, nextLine, state.blkIndent, false).trim() - - state.line = nextLine - - token = state.push('paragraph_open', 'p', 1) - token.map = [startLine, state.line] - - if (state.parentType === 'list') { - const match = content.match(/^\[( |x)\] ?(.+)/i) - if (match) { - const liToken = lastFindInArray(state.tokens, token => token.type === 'list_item_open') - if (liToken) { - if (!liToken.attrs) { - liToken.attrs = [] + if (langType === 'flowchart') { + return `
${str}
` } - liToken.attrs.push(['class', 'taskListItem']) + if (langType === 'sequence') { + return `
${str}
` + } + return '
' +
+          '' + fileName + '' +
+          createGutter(str, firstLineNumber) +
+          '' +
+          str +
+          '
' } - content = `` } + + const updatedOptions = Object.assign(defaultOptions, options) + this.md = markdownit(updatedOptions) + this.md.use(emoji, { + shortcuts: {} + }) + this.md.use(math, { + inlineOpen: config.preview.latexInlineOpen, + inlineClose: config.preview.latexInlineClose, + blockOpen: config.preview.latexBlockOpen, + blockClose: config.preview.latexBlockClose, + inlineRenderer: function (str) { + let output = '' + try { + output = katex.renderToString(str.trim()) + } catch (err) { + output = `${err.message}` + } + return output + }, + blockRenderer: function (str) { + let output = '' + try { + output = katex.renderToString(str.trim(), { displayMode: true }) + } catch (err) { + output = `
${err.message}
` + } + return output + } + }) + this.md.use(require('markdown-it-imsize')) + this.md.use(require('markdown-it-footnote')) + this.md.use(require('markdown-it-multimd-table')) + this.md.use(require('markdown-it-named-headers'), { + slugify: (header) => { + return encodeURI(header.trim() + .replace(/[\]\[\!\"\#\$\%\&\'\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\_\{\|\}\~]/g, '') + .replace(/\s+/g, '-')) + .replace(/\-+$/, '') + } + }) + this.md.use(require('markdown-it-kbd')) + + const deflate = require('markdown-it-plantuml/lib/deflate') + this.md.use(require('markdown-it-plantuml'), '', { + generateSource: function (umlCode) { + const s = unescape(encodeURIComponent(umlCode)) + const zippedCode = deflate.encode64( + deflate.zip_deflate(`@startuml\n${s}\n@enduml`, 9) + ) + return `http://www.plantuml.com/plantuml/svg/${zippedCode}` + } + }) + + // Override task item + 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') + const endLine = state.lineMax + + // jump line-by-line until empty one or EOF + 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 } + + // quirk for blockquotes, this line should already be checked by that rule + if (state.sCount[nextLine] < 0) { continue } + + // Some tags can terminate paragraph without empty line. + terminate = false + for (i = 0, l = terminatorRules.length; i < l; i++) { + if (terminatorRules[i](state, nextLine, endLine, true)) { + terminate = true + break + } + } + if (terminate) { break } + } + + content = state.getLines(startLine, nextLine, state.blkIndent, false).trim() + + state.line = nextLine + + token = state.push('paragraph_open', 'p', 1) + token.map = [startLine, state.line] + + if (state.parentType === 'list') { + const match = content.match(/^\[( |x)\] ?(.+)/i) + if (match) { + const liToken = lastFindInArray(state.tokens, token => token.type === 'list_item_open') + if (liToken) { + if (!liToken.attrs) { + liToken.attrs = [] + } + liToken.attrs.push(['class', 'taskListItem']) + } + content = `` + } + } + + token = state.push('inline', '', 0) + token.content = content + token.map = [startLine, state.line] + token.children = [] + + token = state.push('paragraph_close', 'p', -1) + + return true + }) + + // Add line number attribute for scrolling + const originalRender = this.md.renderer.render + this.md.renderer.render = (tokens, options, env) => { + tokens.forEach((token) => { + switch (token.type) { + case 'heading_open': + case 'paragraph_open': + case 'blockquote_open': + case 'table_open': + token.attrPush(['data-line', token.map[0]]) + } + }) + const result = originalRender.call(this.md.renderer, tokens, options, env) + return result + } + // FIXME We should not depend on global variable. + window.md = this.md } - token = state.push('inline', '', 0) - token.content = content - token.map = [startLine, state.line] - token.children = [] - - token = state.push('paragraph_close', 'p', -1) - - return true -}) - -// Add line number attribute for scrolling -const originalRender = md.renderer.render -md.renderer.render = function render (tokens, options, env) { - tokens.forEach((token) => { - switch (token.type) { - case 'heading_open': - case 'paragraph_open': - case 'blockquote_open': - case 'table_open': - token.attrPush(['data-line', token.map[0]]) - } - }) - const result = originalRender.call(md.renderer, tokens, options, env) - return result -} -// FIXME We should not depend on global variable. -window.md = md - -function normalizeLinkText (linkText) { - return md.normalizeLinkText(linkText) -} - -const markdown = { - render: function markdown (content) { + render (content) { if (!_.isString(content)) content = '' - const renderedContent = md.render(content) - return renderedContent - }, - normalizeLinkText + return this.md.render(content) + } + + normalizeLinkText (linkText) { + return this.md.normalizeLinkText(linkText) + } } -export default markdown +export default Markdown + diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 0c8d6ee9..7080105c 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -48,7 +48,8 @@ export const DEFAULT_CONFIG = { latexInlineClose: '$', latexBlockOpen: '$$', latexBlockClose: '$$', - scrollPastEnd: false + scrollPastEnd: false, + smartQuotes: true } } diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 50e13f6c..ddffe6d9 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -88,7 +88,8 @@ class UiTab extends React.Component { latexInlineClose: this.refs.previewLatexInlineClose.value, latexBlockOpen: this.refs.previewLatexBlockOpen.value, latexBlockClose: this.refs.previewLatexBlockClose.value, - scrollPastEnd: this.refs.previewScrollPastEnd.checked + scrollPastEnd: this.refs.previewScrollPastEnd.checked, + smartQuotes: this.refs.previewSmartQuotes.checked } } @@ -402,6 +403,16 @@ class UiTab extends React.Component { Show line numbers for preview code blocks
+
+ +
LaTeX Inline Open Delimiter From 9344fd78d8bb12d962308a7974edaa6a665e3049 Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Sun, 4 Mar 2018 17:27:58 +0100 Subject: [PATCH 23/75] Remove xss attack; closes #1443 at least partially --- browser/lib/markdown-it-sanitize-html.js | 23 +++++++++++++++++++++++ browser/lib/markdown.js | 11 +++++++++++ package.json | 1 + 3 files changed, 35 insertions(+) create mode 100644 browser/lib/markdown-it-sanitize-html.js diff --git a/browser/lib/markdown-it-sanitize-html.js b/browser/lib/markdown-it-sanitize-html.js new file mode 100644 index 00000000..beec9566 --- /dev/null +++ b/browser/lib/markdown-it-sanitize-html.js @@ -0,0 +1,23 @@ +'use strict' + +import sanitizeHtml from 'sanitize-html' + +module.exports = function sanitizePlugin (md, options) { + options = options || {} + + md.core.ruler.after('linkify', 'sanitize_inline', state => { + for (let tokenIdx = 0; tokenIdx < state.tokens.length; tokenIdx++) { + if (state.tokens[tokenIdx].type === 'html_block') { + state.tokens[tokenIdx].content = sanitizeHtml(state.tokens[tokenIdx].content, options) + } + if (state.tokens[tokenIdx].type === 'inline') { + const inlineTokens = state.tokens[tokenIdx].children + for (let childIdx = 0; childIdx < inlineTokens.length; childIdx++) { + if (inlineTokens[childIdx].type === 'html_inline') { + inlineTokens[childIdx].content = sanitizeHtml(inlineTokens[childIdx].content, options) + } + } + } + } + }) +} diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index d0801a1b..5184ce16 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -1,4 +1,5 @@ import markdownit from 'markdown-it' +import sanitize from './markdown-it-sanitize-html' import emoji from 'markdown-it-emoji' import math from '@rokt33r/markdown-it-math' import _ from 'lodash' @@ -46,6 +47,16 @@ var md = markdownit({ '' } }) +// Sanitize use rinput before other plugins +md.use(sanitize, { + allowedTags: ['img', 'iframe'], + allowedAttributes: { + '*': ['alt', 'style'], + 'img': ['src', 'height', 'width'], + 'iframe': ['src'] + }, + allowedIframeHostnames: ['www.youtube.com'] +}) md.use(emoji, { shortcuts: {} }) diff --git a/package.json b/package.json index db2a9733..476e4b45 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "react-sortable-hoc": "^0.6.7", "redux": "^3.5.2", "sander": "^0.5.1", + "sanitize-html": "^1.18.2", "striptags": "^2.2.1", "superagent": "^1.2.0", "superagent-promise": "^1.0.3" From c22b7f81c139cd56eddfc28dce9b87d30f143b91 Mon Sep 17 00:00:00 2001 From: Sander Steenhuis Date: Sun, 4 Mar 2018 17:49:17 +0100 Subject: [PATCH 24/75] Allow iframe size, allow fullscreen --- browser/lib/markdown.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index 5184ce16..b97f9d56 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -52,8 +52,8 @@ md.use(sanitize, { allowedTags: ['img', 'iframe'], allowedAttributes: { '*': ['alt', 'style'], - 'img': ['src', 'height', 'width'], - 'iframe': ['src'] + 'img': ['src', 'width', 'height'], + 'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen'] }, allowedIframeHostnames: ['www.youtube.com'] }) From 0280a5f09e47b8f32bc3f8bac6a0bb847deca310 Mon Sep 17 00:00:00 2001 From: mirsch Date: Sun, 4 Mar 2018 22:21:14 +0100 Subject: [PATCH 25/75] use uuid in keygen, remove storage.key from note hash --- browser/components/MarkdownPreview.js | 15 +++++++++++++-- browser/components/NoteItem.js | 6 +++--- browser/components/NoteItemSimple.js | 6 +++--- browser/lib/keygen.js | 8 +++----- browser/main/Detail/MarkdownNoteDetail.js | 4 ++-- browser/main/Detail/SnippetNoteDetail.js | 4 ++-- browser/main/Detail/index.js | 7 ++----- browser/main/NoteList/index.js | 13 ++++++------- browser/main/modals/NewNoteModal.js | 4 ++-- browser/main/store.js | 12 ++++++------ package.json | 3 ++- tests/fixtures/TestDummy.js | 4 ++-- yarn.lock | 4 ++++ 13 files changed, 50 insertions(+), 40 deletions(-) diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index c5b0355d..470da1df 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -504,9 +504,20 @@ export default class MarkdownPreview extends React.Component { handlelinkClick (e) { const noteHash = e.target.href.split('/').pop() - const regexIsNoteLink = /^(.{20})-(.{20})$/ + // this will match the new uuid v4 hash and the old hash + // e.g. + // :note:1c211eb7dcb463de6490 and + // :note:7dd23275-f2b4-49cb-9e93-3454daf1af9c + const regexIsNoteLink = /^:note:([a-zA-Z0-9-]{20,36})$/ if (regexIsNoteLink.test(noteHash)) { - eventEmitter.emit('list:jump', noteHash) + eventEmitter.emit('list:jump', noteHash.replace(':note:', '')) + } + // this will match the old link format storage.key-note.key + // e.g. + // 877f99c3268608328037-1c211eb7dcb463de6490 + const regexIsLegacyNoteLink = /^(.{20})-(.{20})$/ + if (regexIsLegacyNoteLink.test(noteHash)) { + eventEmitter.emit('list:jump', noteHash.split('-')[1]) } } diff --git a/browser/components/NoteItem.js b/browser/components/NoteItem.js index 2c93dc18..72d1263a 100644 --- a/browser/components/NoteItem.js +++ b/browser/components/NoteItem.js @@ -62,9 +62,9 @@ const NoteItem = ({ ? 'item--active' : 'item' } - key={`${note.storage}-${note.key}`} - onClick={e => handleNoteClick(e, `${note.storage}-${note.key}`)} - onContextMenu={e => handleNoteContextMenu(e, `${note.storage}-${note.key}`)} + key={note.key} + onClick={e => handleNoteClick(e, note.key)} + onContextMenu={e => handleNoteContextMenu(e, note.key)} onDragStart={e => handleDragStart(e, note)} draggable='true' > diff --git a/browser/components/NoteItemSimple.js b/browser/components/NoteItemSimple.js index 0d2465e9..8262ea1d 100644 --- a/browser/components/NoteItemSimple.js +++ b/browser/components/NoteItemSimple.js @@ -28,9 +28,9 @@ const NoteItemSimple = ({ ? 'item-simple--active' : 'item-simple' } - key={`${note.storage}-${note.key}`} - onClick={e => handleNoteClick(e, `${note.storage}-${note.key}`)} - onContextMenu={e => handleNoteContextMenu(e, `${note.storage}-${note.key}`)} + key={note.key} + onClick={e => handleNoteClick(e, note.key)} + onContextMenu={e => handleNoteContextMenu(e, note.key)} onDragStart={e => handleDragStart(e, note)} draggable='true' > diff --git a/browser/lib/keygen.js b/browser/lib/keygen.js index f4937a83..8bf58a19 100644 --- a/browser/lib/keygen.js +++ b/browser/lib/keygen.js @@ -1,7 +1,5 @@ -const crypto = require('crypto') -const _ = require('lodash') +const uuidv4 = require('uuid/v4') -module.exports = function (length) { - if (!_.isFinite(length)) length = 10 - return crypto.randomBytes(length).toString('hex') +module.exports = function () { + return uuidv4() } diff --git a/browser/main/Detail/MarkdownNoteDetail.js b/browser/main/Detail/MarkdownNoteDetail.js index a543a5aa..6821bf2f 100755 --- a/browser/main/Detail/MarkdownNoteDetail.js +++ b/browser/main/Detail/MarkdownNoteDetail.js @@ -139,7 +139,7 @@ class MarkdownNoteDetail extends React.Component { hashHistory.replace({ pathname: location.pathname, query: { - key: newNote.storage + '-' + newNote.key + key: newNote.key } }) this.setState({ @@ -393,7 +393,7 @@ class MarkdownNoteDetail extends React.Component { `${note.storage}-${note.key}` === noteKey) + return notes.find((note) => note.key === noteKey) } function findNotesByKeys (notes, noteKeys) { @@ -39,7 +39,7 @@ function findNotesByKeys (notes, noteKeys) { } function getNoteKey (note) { - return `${note.storage}-${note.key}` + return note.key } class NoteList extends React.Component { @@ -114,10 +114,10 @@ class NoteList extends React.Component { componentDidUpdate (prevProps) { const { location } = this.props const { selectedNoteKeys } = this.state - const visibleNoteKeys = this.notes.map(note => `${note.storage}-${note.key}`) + const visibleNoteKeys = this.notes.map(note => note.key) const note = this.notes[0] const prevKey = prevProps.location.query.key - const noteKey = visibleNoteKeys.includes(prevKey) ? prevKey : note && `${note.storage}-${note.key}` + const noteKey = visibleNoteKeys.includes(prevKey) ? prevKey : note && note.key if (note && location.query.key == null) { const { router } = this.context @@ -613,19 +613,18 @@ class NoteList extends React.Component { content: firstNote.content }) .then((note) => { - const uniqueKey = note.storage + '-' + note.key dispatch({ type: 'UPDATE_NOTE', note: note }) this.setState({ - selectedNoteKeys: [uniqueKey] + selectedNoteKeys: [note.key] }) hashHistory.push({ pathname: location.pathname, - query: {key: uniqueKey} + query: {key: note.key} }) }) } diff --git a/browser/main/modals/NewNoteModal.js b/browser/main/modals/NewNoteModal.js index 8322d99f..84f510c4 100644 --- a/browser/main/modals/NewNoteModal.js +++ b/browser/main/modals/NewNoteModal.js @@ -35,7 +35,7 @@ class NewNoteModal extends React.Component { content: '' }) .then((note) => { - const noteHash = `${note.storage}-${note.key}` + const noteHash = note.key dispatch({ type: 'UPDATE_NOTE', note: note @@ -75,7 +75,7 @@ class NewNoteModal extends React.Component { }] }) .then((note) => { - const noteHash = `${note.storage}-${note.key}` + const noteHash = note.key dispatch({ type: 'UPDATE_NOTE', note: note diff --git a/browser/main/store.js b/browser/main/store.js index abd34889..1ee9fc88 100644 --- a/browser/main/store.js +++ b/browser/main/store.js @@ -27,7 +27,7 @@ function data (state = defaultDataMap(), action) { action.notes.some((note) => { if (note === undefined) return true - const uniqueKey = note.storage + '-' + note.key + const uniqueKey = note.key const folderKey = note.storage + '-' + note.folder state.noteMap.set(uniqueKey, note) @@ -66,7 +66,7 @@ function data (state = defaultDataMap(), action) { case 'UPDATE_NOTE': { const note = action.note - const uniqueKey = note.storage + '-' + note.key + const uniqueKey = note.key const folderKey = note.storage + '-' + note.folder const oldNote = state.noteMap.get(uniqueKey) @@ -162,9 +162,9 @@ function data (state = defaultDataMap(), action) { case 'MOVE_NOTE': { const originNote = action.originNote - const originKey = originNote.storage + '-' + originNote.key + const originKey = originNote.key const note = action.note - const uniqueKey = note.storage + '-' + note.key + const uniqueKey = note.key const folderKey = note.storage + '-' + note.folder const oldNote = state.noteMap.get(uniqueKey) @@ -423,7 +423,7 @@ function data (state = defaultDataMap(), action) { state.folderNoteMap = new Map(state.folderNoteMap) state.tagNoteMap = new Map(state.tagNoteMap) action.notes.forEach((note) => { - const uniqueKey = note.storage + '-' + note.key + const uniqueKey = note.key const folderKey = note.storage + '-' + note.folder state.noteMap.set(uniqueKey, note) @@ -483,7 +483,7 @@ function data (state = defaultDataMap(), action) { state.tagNoteMap = new Map(state.tagNoteMap) state.starredSet = new Set(state.starredSet) notes.forEach((note) => { - const noteKey = storage.key + '-' + note.key + const noteKey = note.key state.noteMap.delete(noteKey) state.starredSet.delete(noteKey) note.tags.forEach((tag) => { diff --git a/package.json b/package.json index db2a9733..4c258224 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,8 @@ "sander": "^0.5.1", "striptags": "^2.2.1", "superagent": "^1.2.0", - "superagent-promise": "^1.0.3" + "superagent-promise": "^1.0.3", + "uuid": "^3.2.1" }, "devDependencies": { "ava": "^0.16.0", diff --git a/tests/fixtures/TestDummy.js b/tests/fixtures/TestDummy.js index 4edcc9cf..1ded274b 100644 --- a/tests/fixtures/TestDummy.js +++ b/tests/fixtures/TestDummy.js @@ -149,9 +149,9 @@ function dummyLegacyStorage (storagePath, override = {}) { var folderNotes = [] var noteCount = Math.floor((Math.random() * 5)) + 1 for (var i = 0; i < noteCount; i++) { - var key = keygen(6) + var key = keygen() while (folderNotes.some((note) => note.key === key)) { - key = keygen(6) + key = keygen() } var noteData = dummyNote({ diff --git a/yarn.lock b/yarn.lock index c1a949a4..ffd1da24 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6672,6 +6672,10 @@ uuid@^2.0.1, uuid@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" +uuid@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" + validate-npm-package-license@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" From fa2d34dcfc7c88c2472a3902ec14896f4b8c25ad Mon Sep 17 00:00:00 2001 From: mirsch Date: Sun, 4 Mar 2018 23:28:18 +0100 Subject: [PATCH 26/75] fix delete and empty trash --- browser/main/NoteList/index.js | 6 ++---- browser/main/SideNav/index.js | 10 ++++------ browser/main/store.js | 2 +- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 4a67abeb..76d089cc 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -548,11 +548,9 @@ class NoteList extends React.Component { }) if (dialogueButtonIndex === 1) return Promise.all( - selectedNoteKeys.map((uniqueKey) => { - const storageKey = uniqueKey.split('-')[0] - const noteKey = uniqueKey.split('-')[1] + selectedNotes.map((note) => { return dataApi - .deleteNote(storageKey, noteKey) + .deleteNote(note.storage, note.key) }) ) .then((data) => { diff --git a/browser/main/SideNav/index.js b/browser/main/SideNav/index.js index 6d05e37b..6205300e 100644 --- a/browser/main/SideNav/index.js +++ b/browser/main/SideNav/index.js @@ -148,10 +148,8 @@ class SideNav extends React.Component { emptyTrash (entries) { const { dispatch } = this.props - const deletionPromises = entries.map((storageAndNoteKey) => { - const storageKey = storageAndNoteKey.split('-')[0] - const noteKey = storageAndNoteKey.split('-')[1] - return dataApi.deleteNote(storageKey, noteKey) + const deletionPromises = entries.map((note) => { + return dataApi.deleteNote(note.storage, note.key) }) Promise.all(deletionPromises) .then((arrayOfStorageAndNoteKeys) => { @@ -167,9 +165,9 @@ class SideNav extends React.Component { handleFilterButtonContextMenu (event) { const { data } = this.props - const entries = data.trashedSet.toJS() + const trashedNotes = data.trashedSet.toJS().map((uniqueKey) => data.noteMap.get(uniqueKey)) const menu = Menu.buildFromTemplate([ - { label: 'Empty Trash', click: () => this.emptyTrash(entries) } + { label: 'Empty Trash', click: () => this.emptyTrash(trashedNotes) } ]) menu.popup() } diff --git a/browser/main/store.js b/browser/main/store.js index 1ee9fc88..f078ad20 100644 --- a/browser/main/store.js +++ b/browser/main/store.js @@ -297,7 +297,7 @@ function data (state = defaultDataMap(), action) { } case 'DELETE_NOTE': { - const uniqueKey = action.storageKey + '-' + action.noteKey + const uniqueKey = action.noteKey const targetNote = state.noteMap.get(uniqueKey) state = Object.assign({}, state) From b74ba22c4460c46aba6c4e9633d5de0754b063fa Mon Sep 17 00:00:00 2001 From: mirsch Date: Mon, 5 Mar 2018 00:02:30 +0100 Subject: [PATCH 27/75] adjust keygen to use uuid only for notes (uuid on storage/folders woud need more refactoring) --- browser/lib/keygen.js | 10 ++++++++-- browser/main/lib/dataApi/createNote.js | 4 ++-- browser/main/lib/dataApi/moveNote.js | 4 ++-- tests/fixtures/TestDummy.js | 8 ++++---- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/browser/lib/keygen.js b/browser/lib/keygen.js index 8bf58a19..814efedd 100644 --- a/browser/lib/keygen.js +++ b/browser/lib/keygen.js @@ -1,5 +1,11 @@ +const crypto = require('crypto') +const _ = require('lodash') const uuidv4 = require('uuid/v4') -module.exports = function () { - return uuidv4() +module.exports = function (uuid) { + if (typeof uuid === typeof true && uuid) { + return uuidv4() + } + const length = 10 + return crypto.randomBytes(length).toString('hex') } diff --git a/browser/main/lib/dataApi/createNote.js b/browser/main/lib/dataApi/createNote.js index 4b667385..e5d44489 100644 --- a/browser/main/lib/dataApi/createNote.js +++ b/browser/main/lib/dataApi/createNote.js @@ -52,12 +52,12 @@ function createNote (storageKey, input) { return storage }) .then(function saveNote (storage) { - let key = keygen() + let key = keygen(true) let isUnique = false while (!isUnique) { try { sander.statSync(path.join(storage.path, 'notes', key + '.cson')) - key = keygen() + key = keygen(true) } catch (err) { if (err.code === 'ENOENT') { isUnique = true diff --git a/browser/main/lib/dataApi/moveNote.js b/browser/main/lib/dataApi/moveNote.js index 4580062e..ef6760d7 100644 --- a/browser/main/lib/dataApi/moveNote.js +++ b/browser/main/lib/dataApi/moveNote.js @@ -37,12 +37,12 @@ function moveNote (storageKey, noteKey, newStorageKey, newFolderKey) { return resolveStorageData(newStorage) .then(function findNewNoteKey (_newStorage) { newStorage = _newStorage - newNoteKey = keygen() + newNoteKey = keygen(true) let isUnique = false while (!isUnique) { try { sander.statSync(path.join(newStorage.path, 'notes', newNoteKey + '.cson')) - newNoteKey = keygen() + newNoteKey = keygen(true) } catch (err) { if (err.code === 'ENOENT') { isUnique = true diff --git a/tests/fixtures/TestDummy.js b/tests/fixtures/TestDummy.js index 1ded274b..b1b176ea 100644 --- a/tests/fixtures/TestDummy.js +++ b/tests/fixtures/TestDummy.js @@ -107,9 +107,9 @@ function dummyStorage (storagePath, override = {}) { var notesData = [] var noteCount = Math.floor((Math.random() * 15)) + 1 for (var i = 0; i < noteCount; i++) { - var key = keygen() + var key = keygen(true) while (notesData.some((note) => note.key === key)) { - key = keygen() + key = keygen(true) } var noteData = dummyNote({ @@ -149,9 +149,9 @@ function dummyLegacyStorage (storagePath, override = {}) { var folderNotes = [] var noteCount = Math.floor((Math.random() * 5)) + 1 for (var i = 0; i < noteCount; i++) { - var key = keygen() + var key = keygen(true) while (folderNotes.some((note) => note.key === key)) { - key = keygen() + key = keygen(true) } var noteData = dummyNote({ From 4800a88cf6fe761b9bc48f1bc178150fa0c7f307 Mon Sep 17 00:00:00 2001 From: David Gay Date: Mon, 5 Mar 2018 21:22:42 -0500 Subject: [PATCH 28/75] add UTF-8 tag to HTML export (fixes #1624) --- browser/components/MarkdownPreview.js | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index c5b0355d..2bb42291 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -216,6 +216,7 @@ export default class MarkdownPreview extends React.Component { return ` + ${styles} From b11dc2ca2058c9053fda81469b52f15a6a110b21 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 6 Mar 2018 09:54:37 +0100 Subject: [PATCH 29/75] first testing of translation --- browser/lib/i18n.js | 7 ++ browser/main/Detail/InfoPanel.js | 23 +++--- browser/main/Detail/index.js | 3 +- locales/de.js | 4 + locales/en.js | 15 ++++ locales/fr.js | 1 + package-lock.json | 35 ++++++++ package.json | 1 + yarn.lock | 138 ++++++++++++++++++++++++++++++- 9 files changed, 214 insertions(+), 13 deletions(-) create mode 100644 browser/lib/i18n.js create mode 100644 locales/de.js create mode 100644 locales/en.js create mode 100644 locales/fr.js create mode 100644 package-lock.json diff --git a/browser/lib/i18n.js b/browser/lib/i18n.js new file mode 100644 index 00000000..aa2f0a89 --- /dev/null +++ b/browser/lib/i18n.js @@ -0,0 +1,7 @@ +//load package for localization +const i18n = new (require('i18n-2'))({ + // setup some locales - other locales default to the first locale + locales: ['en', 'de', 'fr'] + }); + +export default i18n; \ No newline at end of file diff --git a/browser/main/Detail/InfoPanel.js b/browser/main/Detail/InfoPanel.js index 44b9f09a..629f0b97 100644 --- a/browser/main/Detail/InfoPanel.js +++ b/browser/main/Detail/InfoPanel.js @@ -3,6 +3,7 @@ import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './InfoPanel.styl' import copy from 'copy-to-clipboard' +import i18n from 'browser/lib/i18n' class InfoPanel extends React.Component { copyNoteLink () { @@ -19,7 +20,7 @@ class InfoPanel extends React.Component {

{updatedAt}

-

MODIFICATION DATE

+

{i18n.__('MODIFICATION DATE')}


@@ -29,11 +30,11 @@ class InfoPanel extends React.Component { :

{wordCount}

-

Words

+

{i18n.__('Words')}

{letterCount}

-

Letters

+

{i18n.__('Letters')}

} @@ -45,17 +46,17 @@ class InfoPanel extends React.Component {

{storageName}

-

STORAGE

+

{i18n.__('STORAGE')}

{folderName}

-

FOLDER

+

{i18n.__('FOLDER')}

{createdAt}

-

CREATION DATE

+

{i18n.__('CREATION DATE')}

@@ -63,7 +64,7 @@ class InfoPanel extends React.Component { -

NOTE LINK

+

{i18n.__('NOTE LINK')}


@@ -71,22 +72,22 @@ class InfoPanel extends React.Component {
diff --git a/browser/main/Detail/index.js b/browser/main/Detail/index.js index a9a8e4f2..89b1dd75 100644 --- a/browser/main/Detail/index.js +++ b/browser/main/Detail/index.js @@ -7,6 +7,7 @@ import MarkdownNoteDetail from './MarkdownNoteDetail' import SnippetNoteDetail from './SnippetNoteDetail' import ee from 'browser/main/lib/eventEmitter' import StatusBar from '../StatusBar' +import i18n from 'browser/lib/i18n' const OSX = global.process.platform === 'darwin' @@ -70,7 +71,7 @@ class Detail extends React.Component { tabIndex='0' >
-
{OSX ? 'Command(⌘)' : 'Ctrl(^)'} + N
to create a new note
+
{OSX ? i18n.__('Command(⌘)') : i18n.__('Ctrl(^)')} + N
{i18n.__('to create a new note')}
Date: Tue, 6 Mar 2018 14:07:04 +0100 Subject: [PATCH 30/75] extracted all strings from html lines --- browser/lib/i18n.js | 2 +- browser/main/Detail/InfoPanel.js | 2 +- browser/main/Detail/InfoPanelTrashed.js | 9 +- browser/main/Detail/PermanentDeleteButton.js | 3 +- browser/main/Detail/RestoreButton.js | 3 +- browser/main/Detail/ToggleModeButton.js | 3 +- browser/main/Detail/TrashButton.js | 3 +- browser/main/NewNoteButton/index.js | 3 +- browser/main/SideNav/ListButton.js | 3 +- browser/main/SideNav/PreferenceButton.js | 3 +- browser/main/SideNav/TagButton.js | 3 +- browser/main/StatusBar/index.js | 3 +- browser/main/TopBar/index.js | 3 +- browser/main/modals/NewNoteModal.js | 11 ++- .../modals/PreferencesModal/Crowdfunding.js | 21 +++-- .../modals/PreferencesModal/FolderItem.js | 11 ++- .../main/modals/PreferencesModal/InfoTab.js | 37 ++++---- .../modals/PreferencesModal/StorageItem.js | 7 +- .../modals/PreferencesModal/StoragesTab.js | 25 ++--- browser/main/modals/PreferencesModal/UiTab.js | 71 +++++++------- browser/main/modals/PreferencesModal/index.js | 3 +- browser/main/modals/RenameFolderModal.js | 3 +- locales/de.js | 94 ++++++++++++++++++- locales/en.js | 87 ++++++++++++++++- 24 files changed, 302 insertions(+), 111 deletions(-) diff --git a/browser/lib/i18n.js b/browser/lib/i18n.js index aa2f0a89..0b51ea54 100644 --- a/browser/lib/i18n.js +++ b/browser/lib/i18n.js @@ -2,6 +2,6 @@ const i18n = new (require('i18n-2'))({ // setup some locales - other locales default to the first locale locales: ['en', 'de', 'fr'] - }); +}); export default i18n; \ No newline at end of file diff --git a/browser/main/Detail/InfoPanel.js b/browser/main/Detail/InfoPanel.js index 629f0b97..4ce610fa 100644 --- a/browser/main/Detail/InfoPanel.js +++ b/browser/main/Detail/InfoPanel.js @@ -82,7 +82,7 @@ class InfoPanel extends React.Component { ) diff --git a/browser/main/Detail/RestoreButton.js b/browser/main/Detail/RestoreButton.js index 0f9c992e..5d0186db 100644 --- a/browser/main/Detail/RestoreButton.js +++ b/browser/main/Detail/RestoreButton.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types' import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './RestoreButton.styl' +import i18n from 'browser/lib/i18n' const RestoreButton = ({ onClick @@ -10,7 +11,7 @@ const RestoreButton = ({ onClick={onClick} > - Restore + {i18n.__('Restore')} ) diff --git a/browser/main/Detail/ToggleModeButton.js b/browser/main/Detail/ToggleModeButton.js index e2d143d4..c414a3e5 100644 --- a/browser/main/Detail/ToggleModeButton.js +++ b/browser/main/Detail/ToggleModeButton.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types' import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './ToggleModeButton.styl' +import i18n from 'browser/lib/i18n' const ToggleModeButton = ({ onClick, editorType @@ -13,7 +14,7 @@ const ToggleModeButton = ({
onClick('EDITOR_PREVIEW')}>
- Toggle Mode + {i18n.__('Toggle Mode')}
) diff --git a/browser/main/Detail/TrashButton.js b/browser/main/Detail/TrashButton.js index 474eb9e5..473c2d0b 100644 --- a/browser/main/Detail/TrashButton.js +++ b/browser/main/Detail/TrashButton.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types' import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './TrashButton.styl' +import i18n from 'browser/lib/i18n' const TrashButton = ({ onClick @@ -10,7 +11,7 @@ const TrashButton = ({ onClick={(e) => onClick(e)} > - Trash + {i18n.__('Trash')} ) diff --git a/browser/main/NewNoteButton/index.js b/browser/main/NewNoteButton/index.js index 633433df..b2d8cec6 100644 --- a/browser/main/NewNoteButton/index.js +++ b/browser/main/NewNoteButton/index.js @@ -6,6 +6,7 @@ import _ from 'lodash' import modal from 'browser/main/lib/modal' import NewNoteModal from 'browser/main/modals/NewNoteModal' import eventEmitter from 'browser/main/lib/eventEmitter' +import i18n from 'browser/lib/i18n' const { remote } = require('electron') const { dialog } = remote @@ -86,7 +87,7 @@ class NewNoteButton extends React.Component { onClick={(e) => this.handleNewNoteButtonClick(e)}> - Make a note {OSX ? '⌘' : 'Ctrl'} + N + {i18n.__('Make a note')} {OSX ? '⌘' : i18n.__('Ctrl')} + N
diff --git a/browser/main/SideNav/ListButton.js b/browser/main/SideNav/ListButton.js index 1365c4cb..b5bc1488 100644 --- a/browser/main/SideNav/ListButton.js +++ b/browser/main/SideNav/ListButton.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types' import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './SwitchButton.styl' +import i18n from 'browser/lib/i18n' const ListButton = ({ onClick, isTagActive @@ -12,7 +13,7 @@ const ListButton = ({ : '../resources/icon/icon-list-active.svg' } /> - Notes + {i18n.__('Notes')} ) diff --git a/browser/main/SideNav/PreferenceButton.js b/browser/main/SideNav/PreferenceButton.js index 9f483a28..187171f4 100644 --- a/browser/main/SideNav/PreferenceButton.js +++ b/browser/main/SideNav/PreferenceButton.js @@ -2,13 +2,14 @@ import PropTypes from 'prop-types' import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './PreferenceButton.styl' +import i18n from 'browser/lib/i18n' const PreferenceButton = ({ onClick }) => ( ) diff --git a/browser/main/SideNav/TagButton.js b/browser/main/SideNav/TagButton.js index 87d92c49..d91ae2c4 100644 --- a/browser/main/SideNav/TagButton.js +++ b/browser/main/SideNav/TagButton.js @@ -2,6 +2,7 @@ import PropTypes from 'prop-types' import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './SwitchButton.styl' +import i18n from 'browser/lib/i18n' const TagButton = ({ onClick, isTagActive @@ -12,7 +13,7 @@ const TagButton = ({ : '../resources/icon/icon-tag.svg' } /> - Tags + {i18n.__('Tags')} ) diff --git a/browser/main/StatusBar/index.js b/browser/main/StatusBar/index.js index 49c1b40c..e3dd8fac 100644 --- a/browser/main/StatusBar/index.js +++ b/browser/main/StatusBar/index.js @@ -3,6 +3,7 @@ import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './StatusBar.styl' import ZoomManager from 'browser/main/lib/ZoomManager' +import i18n from 'browser/lib/i18n' const electron = require('electron') const { remote, ipcRenderer } = electron @@ -62,7 +63,7 @@ class StatusBar extends React.Component { {status.updateReady ? : null } diff --git a/browser/main/TopBar/index.js b/browser/main/TopBar/index.js index 246ef614..860d5b0d 100644 --- a/browser/main/TopBar/index.js +++ b/browser/main/TopBar/index.js @@ -5,6 +5,7 @@ import styles from './TopBar.styl' import _ from 'lodash' import ee from 'browser/main/lib/eventEmitter' import NewNoteButton from 'browser/main/NewNoteButton' +import i18n from 'browser/lib/i18n' class TopBar extends React.Component { constructor (props) { @@ -185,7 +186,7 @@ class TopBar extends React.Component { onClick={(e) => this.handleSearchClearButton(e)} > - Clear Search + {i18n.__('Clear Search')} } diff --git a/browser/main/modals/NewNoteModal.js b/browser/main/modals/NewNoteModal.js index 8322d99f..641c348d 100644 --- a/browser/main/modals/NewNoteModal.js +++ b/browser/main/modals/NewNoteModal.js @@ -6,6 +6,7 @@ import { hashHistory } from 'react-router' import ee from 'browser/main/lib/eventEmitter' import ModalEscButton from 'browser/components/ModalEscButton' import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' +import i18n from 'browser/lib/i18n' class NewNoteModal extends React.Component { constructor (props) { @@ -122,8 +123,8 @@ class NewNoteModal extends React.Component {
- Markdown Note
- This format is for creating text documents. Checklists, code blocks and Latex blocks are available. + {i18n.__('Markdown Note')}
+ {i18n.__('This format is for creating text documents. Checklists, code blocks and Latex blocks are available.')} -
Tab to switch format
+
{i18n.__('Tab to switch format')}
) diff --git a/browser/main/modals/PreferencesModal/Crowdfunding.js b/browser/main/modals/PreferencesModal/Crowdfunding.js index 048520b0..196c1cb3 100644 --- a/browser/main/modals/PreferencesModal/Crowdfunding.js +++ b/browser/main/modals/PreferencesModal/Crowdfunding.js @@ -1,6 +1,7 @@ import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './Crowdfunding.styl' +import i18n from 'browser/lib/i18n' const electron = require('electron') const { shell } = electron @@ -21,22 +22,22 @@ class Crowdfunding extends React.Component { render () { return (
-
Crowdfunding
-

Dear everyone,

+
{i18n.__('Crowdfunding')}
+

{i18n.__('Dear everyone,')}


-

Thank you for using Boostnote!

-

Boostnote is used in about 200 different countries and regions by an awesome community of developers.

+

{i18n.__('Thank you for using Boostnote!')}

+

{i18n.__('Boostnote is used in about 200 different countries and regions by an awesome community of developers.')}


-

To continue supporting this growth, and to satisfy community expectations,

-

we would like to invest more time and resources in this project.

+

{i18n.__('To continue supporting this growth, and to satisfy community expectations,')}

+

{i18n.__('we would like to invest more time and resources in this project.')}


-

If you like this project and see its potential, you can help by supporting us on OpenCollective!

+

{i18n.__('If you like this project and see its potential, you can help by supporting us on OpenCollective!')}


-

Thanks,

-

Boostnote maintainers

+

{i18n.__('Thanks,')}

+

{i18n.__('Boostnote maintainers')}


) diff --git a/browser/main/modals/PreferencesModal/FolderItem.js b/browser/main/modals/PreferencesModal/FolderItem.js index 9d1cd08f..779ad0be 100644 --- a/browser/main/modals/PreferencesModal/FolderItem.js +++ b/browser/main/modals/PreferencesModal/FolderItem.js @@ -7,6 +7,7 @@ import dataApi from 'browser/main/lib/dataApi' import store from 'browser/main/store' import { SketchPicker } from 'react-color' import { SortableElement, SortableHandle } from 'react-sortable-hoc' +import i18n from 'browser/lib/i18n' class FolderItem extends React.Component { constructor (props) { @@ -179,18 +180,18 @@ class FolderItem extends React.Component { return (
- Are you sure to delete this folder? + {i18n.__('Are you sure to ')} {i18n.__(' delete')} {i18n.__('this folder?')}
@@ -231,12 +232,12 @@ class FolderItem extends React.Component { diff --git a/browser/main/modals/PreferencesModal/InfoTab.js b/browser/main/modals/PreferencesModal/InfoTab.js index 25c0b255..964b02f3 100644 --- a/browser/main/modals/PreferencesModal/InfoTab.js +++ b/browser/main/modals/PreferencesModal/InfoTab.js @@ -5,6 +5,7 @@ import ConfigManager from 'browser/main/lib/ConfigManager' import store from 'browser/main/store' import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' import _ from 'lodash' +import i18n from 'browser/lib/i18n' const electron = require('electron') const { shell, remote } = electron @@ -69,48 +70,48 @@ class InfoTab extends React.Component { return (
-
Community
+
{i18n.__('Community')}

-
About
+
{i18n.__('About')}
-
Boostnote {appVersion}
+
{i18n.__('Boostnote')} {appVersion}
- An open source note-taking app made for programmers just like you. + {i18n.__('An open source note-taking app made for programmers just like you.')}
@@ -120,34 +121,34 @@ class InfoTab extends React.Component {
  • this.handleLinkClick(e)} - >Website + >{i18n.__('Website')}
  • this.handleLinkClick(e)} - >Development : Development configurations for Boostnote. + >{i18n.__('Development')}{i18n.__(' : Development configurations for Boostnote.')}
  • - Copyright (C) 2017 - 2018 BoostIO + {i18n.__('Copyright (C) 2017 - 2018 BoostIO')}
  • - License: GPL v3 + {i18n.__('License: GPL v3')}

  • -
    Analytics
    -
    Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.
    -
    You can see how it works on this.handleLinkClick(e)}>GitHub.
    +
    {i18n.__('Analytics')}
    +
    {i18n.__('Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.')}
    +
    {i18n.__('You can see how it works on ')} this.handleLinkClick(e)}>GitHub.

    -
    You can choose to enable or disable this option.
    +
    {i18n.__('You can choose to enable or disable this option.')}
    this.handleConfigChange(e)} checked={this.state.config.amaEnabled} ref='amaEnabled' type='checkbox' /> - Enable analytics to help improve Boostnote
    + {i18n.__('Enable analytics to help improve Boostnote')}

    {this.infoMessage()} diff --git a/browser/main/modals/PreferencesModal/StorageItem.js b/browser/main/modals/PreferencesModal/StorageItem.js index f2092835..28675860 100644 --- a/browser/main/modals/PreferencesModal/StorageItem.js +++ b/browser/main/modals/PreferencesModal/StorageItem.js @@ -6,6 +6,7 @@ import consts from 'browser/lib/consts' import dataApi from 'browser/main/lib/dataApi' import store from 'browser/main/store' import FolderList from './FolderList' +import i18n from 'browser/lib/i18n' const { shell, remote } = require('electron') const { dialog } = remote @@ -127,7 +128,7 @@ class StorageItem extends React.Component { Add Folder + >{i18n.__('Add Folder')}
    diff --git a/browser/main/modals/PreferencesModal/StoragesTab.js b/browser/main/modals/PreferencesModal/StoragesTab.js index f66a617e..a6be9555 100644 --- a/browser/main/modals/PreferencesModal/StoragesTab.js +++ b/browser/main/modals/PreferencesModal/StoragesTab.js @@ -4,6 +4,7 @@ import CSSModules from 'browser/lib/CSSModules' import styles from './StoragesTab.styl' import dataApi from 'browser/main/lib/dataApi' import StorageItem from './StorageItem' +import i18n from 'browser/lib/i18n' const electron = require('electron') const { shell, remote } = electron @@ -69,16 +70,16 @@ class StoragesTab extends React.Component { }) return (
    -
    Storages
    +
    {i18n.__('Storages')}
    {storageList.length > 0 ? storageList - :
    No storage found.
    + :
    {i18n.__('No storage found.')}
    }
    @@ -140,13 +141,13 @@ class StoragesTab extends React.Component { return (
    -
    Add Storage
    +
    {i18n.__('Add Storage')}
    - Name + {i18n.__('Name')}
    -
    Type
    +
    {i18n.__('Type')}
    - Setting up 3rd-party cloud storage integration:{' '} + {i18n.__('Setting up 3rd-party cloud storage integration:')}{' '} this.handleLinkClick(e)} - >Cloud-Syncing-and-Backup + >{i18n.__('Cloud-Syncing-and-Backup')}
    -
    Location +
    {i18n.__('Location')}
    + >{i18n.__('Add')} + >{i18n.__('Cancel')}
    diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 50e13f6c..2e6ae7e1 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -9,6 +9,7 @@ import ReactCodeMirror from 'react-codemirror' import CodeMirror from 'codemirror' import 'codemirror-mode-elixir' import _ from 'lodash' +import i18n from 'browser/lib/i18n' const OSX = global.process.platform === 'darwin' @@ -151,19 +152,19 @@ class UiTab extends React.Component { return (
    -
    Interface
    +
    {i18n.__('Interface')}
    - Interface Theme + {i18n.__('Interface Theme')}
    @@ -174,7 +175,7 @@ class UiTab extends React.Component { ref='showCopyNotification' type='checkbox' />  - Show "Saved to Clipboard" notification when copying + {i18n.__('Show "Saved to Clipboard" notification when copying')}
    @@ -184,7 +185,7 @@ class UiTab extends React.Component { ref='confirmDeletion' type='checkbox' />  - Show a confirmation dialog when deleting notes + {i18n.__('Show a confirmation dialog when deleting notes')}
    { @@ -206,7 +207,7 @@ class UiTab extends React.Component {
    - Editor Theme + {i18n.__('Editor Theme')}
    - Editor Font Family + {i18n.__('Editor Font Family')}
    - Editor Indent Style + {i18n.__('Editor Indent Style')}
    - Switch to Preview + {i18n.__('Switch to Preview')}
    - Editor Keymap + {i18n.__('Editor Keymap')}
    -

    ⚠️ Please restart boostnote after you change the keymap

    +

    {i18n.__('⚠️ Please restart boostnote after you change the keymap')}

    @@ -314,7 +315,7 @@ class UiTab extends React.Component { ref='editorDisplayLineNumbers' type='checkbox' />  - Show line numbers in the editor + {i18n.__('Show line numbers in the editor')}
    @@ -325,7 +326,7 @@ class UiTab extends React.Component { ref='scrollPastEnd' type='checkbox' />  - Allow editor to scroll past the last line + {i18n.__('Allow editor to scroll past the last line')}
    @@ -336,14 +337,14 @@ class UiTab extends React.Component { ref='editorFetchUrlTitle' type='checkbox' />  - Bring in web page title when pasting URL on editor + {i18n.__('Bring in web page title when pasting URL on editor')}
    Preview
    - Preview Font Size + {i18n.__('Preview Font Size')}
    - Preview Font Family + {i18n.__('Preview Font Family')}
    -
    Code block Theme
    +
    {i18n.__('Code block Theme')}
    - LaTeX Inline Close Delimiter + {i18n.__('LaTeX Inline Close Delimiter')}
    - LaTeX Block Open Delimiter + {i18n.__('LaTeX Block Open Delimiter')}
    - LaTeX Block Close Delimiter + {i18n.__('LaTeX Block Close Delimiter')}
    this.handleKeyDown(e)} >
    -

    Your preferences for Boostnote

    +

    {i18n.__('Your preferences for Boostnote')}

    this.handleEscButtonClick(e)} />
    diff --git a/browser/main/modals/RenameFolderModal.js b/browser/main/modals/RenameFolderModal.js index bb08f36d..f4197196 100644 --- a/browser/main/modals/RenameFolderModal.js +++ b/browser/main/modals/RenameFolderModal.js @@ -5,6 +5,7 @@ import styles from './RenameFolderModal.styl' import dataApi from 'browser/main/lib/dataApi' import store from 'browser/main/store' import ModalEscButton from 'browser/components/ModalEscButton' +import i18n from 'browser/lib/i18n' class RenameFolderModal extends React.Component { constructor (props) { @@ -72,7 +73,7 @@ class RenameFolderModal extends React.Component { onKeyDown={(e) => this.handleKeyDown(e)} >
    -
    Rename Folder
    +
    {i18n.__('Rename Folder')}
    this.handleCloseButtonClick(e)} /> diff --git a/locales/de.js b/locales/de.js index 23d80003..6bd695e0 100644 --- a/locales/de.js +++ b/locales/de.js @@ -1,4 +1,94 @@ { - "Ctrl(^)": "Strg", - "to create a new note": "um eine neue Notiz zu erstellen" + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl(^)", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Deine Boostnote Einstellungen", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Default", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show "Saved to Clipboard" notification when copying": "Show "Saved to Clipboard" notification when copying", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective" } \ No newline at end of file diff --git a/locales/en.js b/locales/en.js index bf5d5513..d78c361f 100644 --- a/locales/en.js +++ b/locales/en.js @@ -1,5 +1,5 @@ { - "Ctrl(^)": "Ctrl(^)", + "Ctrl(^)": "Ctrl", "to create a new note": "to create a new note", "MODIFICATION DATE": "MODIFICATION DATE", "Words": "Words", @@ -10,6 +10,87 @@ "NOTE LINK": "NOTE LINK", ".md": ".md", ".txt": ".txt", - ".html Date: Tue, 6 Mar 2018 15:04:04 +0100 Subject: [PATCH 31/75] Implemented language switch in Interface Config Tab --- browser/main/Main.js | 10 ++- browser/main/lib/ConfigManager.js | 9 +++ browser/main/modals/PreferencesModal/UiTab.js | 18 +++++- locales/de.js | 7 ++- locales/en.js | 7 ++- locales/fr.js | 61 ++++++++++++++++++- 6 files changed, 106 insertions(+), 6 deletions(-) diff --git a/browser/main/Main.js b/browser/main/Main.js index f9be6085..f05ad52d 100644 --- a/browser/main/Main.js +++ b/browser/main/Main.js @@ -14,6 +14,7 @@ import mobileAnalytics from 'browser/main/lib/AwsMobileAnalyticsConfig' import eventEmitter from 'browser/main/lib/eventEmitter' import { hashHistory } from 'react-router' import store from 'browser/main/store' +import i18n from 'browser/lib/i18n' const path = require('path') const electron = require('electron') const { remote } = electron @@ -148,7 +149,14 @@ class Main extends React.Component { } else { document.body.setAttribute('data-theme', 'default') } - + if (config.ui.language === 'en') { + i18n.setLocale('en') + } else if (config.ui.language === 'de') { + i18n.setLocale('de') + } else { + i18n.setLocale('fr') + } + // Reload all data dataApi.init() .then((data) => { diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index e7e82a9b..0d4730fe 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -1,5 +1,6 @@ import _ from 'lodash' import RcParser from 'browser/lib/RcParser' +import i18n from 'browser/lib/i18n' const OSX = global.process.platform === 'darwin' const win = global.process.platform === 'win32' @@ -132,6 +133,14 @@ function set (updates) { document.body.setAttribute('data-theme', 'default') } + if (newConfig.ui.language === 'en') { + i18n.setLocale('en') + } else if (newConfig.ui.language === 'de') { + i18n.setLocale('de') + } else { + i18n.setLocale('fr') + } + let editorTheme = document.getElementById('editorTheme') if (editorTheme == null) { editorTheme = document.createElement('link') diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 2e6ae7e1..f2132bdf 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -62,6 +62,7 @@ class UiTab extends React.Component { const newConfig = { ui: { theme: this.refs.uiTheme.value, + language: this.refs.uiLanguage.value, showCopyNotification: this.refs.showCopyNotification.checked, confirmDeletion: this.refs.confirmDeletion.checked, disableDirectWrite: this.refs.uiD2w != null @@ -168,6 +169,21 @@ class UiTab extends React.Component {
    + +
    + {i18n.__('Language')} +
    + +
    +
    +
    diff --git a/locales/de.js b/locales/de.js index 6bd695e0..f3adcdb7 100644 --- a/locales/de.js +++ b/locales/de.js @@ -90,5 +90,10 @@ "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", "Thanks,": "Thanks,", "Boostnote maintainers": "Boostnote maintainers", - "Support via OpenCollective": "Support via OpenCollective" + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "Englisch", + "German": "Deutsch", + "French": "Französisch", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying" } \ No newline at end of file diff --git a/locales/en.js b/locales/en.js index d78c361f..0ea0f034 100644 --- a/locales/en.js +++ b/locales/en.js @@ -27,7 +27,6 @@ "Thanks,": "Thanks,", "Boostnote maintainers": "Boostnote maintainers", "Support via OpenCollective": "Support via OpenCollective", - "Thank you for using Boostnote!": "Thank you for using Boostnote!", "Make a note": "Make a note", "Ctrl": "Ctrl", "Notes": "Notes", @@ -92,5 +91,9 @@ "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", - ".html": ".html" + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French" } \ No newline at end of file diff --git a/locales/fr.js b/locales/fr.js index 9e26dfee..cfcca1a5 100644 --- a/locales/fr.js +++ b/locales/fr.js @@ -1 +1,60 @@ -{} \ No newline at end of file +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Default", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter" +} \ No newline at end of file From aa3597881abe2d882fef8a0931d83362659407a9 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 6 Mar 2018 15:56:48 +0100 Subject: [PATCH 32/75] added more strings --- browser/components/SideNavFilter.js | 7 +- locales/de.js | 105 +++++++++++++++------------- locales/en.js | 4 +- 3 files changed, 65 insertions(+), 51 deletions(-) diff --git a/browser/components/SideNavFilter.js b/browser/components/SideNavFilter.js index 2f839a84..06cfc19a 100644 --- a/browser/components/SideNavFilter.js +++ b/browser/components/SideNavFilter.js @@ -5,6 +5,7 @@ import PropTypes from 'prop-types' import React from 'react' import CSSModules from 'browser/lib/CSSModules' import styles from './SideNavFilter.styl' +import i18n from 'browser/lib/i18n' /** * @param {boolean} isFolded @@ -31,7 +32,7 @@ const SideNavFilter = ({ } />
    - All Notes + {i18n.__('All Notes')} {counterTotalNote} @@ -45,7 +46,7 @@ const SideNavFilter = ({ } />
    - Starred + {i18n.__('Starred')} {counterStarredNote} @@ -59,7 +60,7 @@ const SideNavFilter = ({ } />
    - Trash + {i18n.__('Trash')} {counterDelNote} diff --git a/locales/de.js b/locales/de.js index f3adcdb7..70bd3c76 100644 --- a/locales/de.js +++ b/locales/de.js @@ -1,79 +1,78 @@ { - "Notes": "Notes", + "Notes": "Notizen", "Tags": "Tags", - "Preferences": "Preferences", - "Make a note": "Make a note", + "Preferences": "Einstellungen", + "Make a note": "Notiz erstellen", "Ctrl": "Ctrl", - "Ctrl(^)": "Ctrl(^)", - "to create a new note": "to create a new note", - "Toggle Mode": "Toggle Mode", - "Trash": "Trash", + "Ctrl(^)": "Ctrl", + "to create a new note": "um eine neue Notiz zu erstellen", + "Toggle Mode": "Modus umschalten", + "Trash": "Papierkorb", "MODIFICATION DATE": "MODIFICATION DATE", - "Words": "Words", - "Letters": "Letters", - "STORAGE": "STORAGE", - "FOLDER": "FOLDER", - "CREATION DATE": "CREATION DATE", - "NOTE LINK": "NOTE LINK", + "Words": "Wörter", + "Letters": "Buchstaben", + "STORAGE": "SPEICHERORT", + "FOLDER": "ORDNER", + "CREATION DATE": "ERSTELLUNGSDATUM", + "NOTE LINK": "NOTIZ LINK", ".md": ".md", ".txt": ".txt", ".html": ".html", "Print": "Print", "Your preferences for Boostnote": "Deine Boostnote Einstellungen", - "Storages": "Storages", - "Add Storage Location": "Add Storage Location", - "Add Folder": "Add Folder", - "Open Storage folder": "Open Storage folder", + "Storages": "Speicherorte", + "Add Storage Location": "Speicherort Hinzufügen", + "Add Folder": "Ordner Hinzufügen", + "Open Storage folder": "Speicherort Öffnen", "Unlink": "Unlink", - "Edit": "Edit", - "Delete": "Delete", + "Edit": "Bearbeiten", + "Delete": "Löschen", "Interface": "Interface", "Interface Theme": "Interface Theme", - "Default": "Default", - "White": "White", + "Default": "Standard", + "White": "Weiß", "Solarized Dark": "Solarized Dark", "Dark": "Dark", - "Show "Saved to Clipboard" notification when copying": "Show "Saved to Clipboard" notification when copying", - "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Show a confirmation dialog when deleting notes": "Bestätigungsdialog beim Löschen von Notizen anzeigen", "Editor Theme": "Editor Theme", - "Editor Font Size": "Editor Font Size", - "Editor Font Family": "Editor Font Family", - "Editor Indent Style": "Editor Indent Style", - "Spaces": "Spaces", + "Editor Font Size": "Editor Schriftgröße", + "Editor Font Family": "Editor Schriftart", + "Editor Indent Style": "Editor Einrückestil", + "Spaces": "Leerzeichen", "Tabs": "Tabs", - "Switch to Preview": "Switch to Preview", - "When Editor Blurred": "When Editor Blurred", - "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", - "On Right Click": "On Right Click", - "Editor Keymap": "Editor Keymap", - "default": "default", + "Switch to Preview": "Zur Vorschau wechseln", + "When Editor Blurred": "Wenn Editor verschwommen ist", + "When Editor Blurred, Edit On Double Click": "Mit Doppelklick bearbeiten, wenn Editor verschwommen ist", + "On Right Click": "Mit Rechtsklcik", + "Editor Keymap": "Editor Tastenbelegung", + "default": "standard", "vim": "vim", "emacs": "emacs", - "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", - "Show line numbers in the editor": "Show line numbers in the editor", - "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", - "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", - "Preview Font Size": "Preview Font Size", - "Preview Font Family": "Preview Font Family", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Boostnote nach Änderung der Tastenbelegung neu starten", + "Show line numbers in the editor": "Zeilennummern im Editor anzeigen", + "Allow editor to scroll past the last line": "Editor das Scrollen über das Ende hinaus erlauben", + "Bring in web page title when pasting URL on editor": "Websitetitel beim Einfügen in den Editor anzeigen", + "Preview Font Size": "Vorschau Schriftgröße", + "Preview Font Family": "Vorschau Schriftart", "Code block Theme": "Code block Theme", - "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", - "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "Allow preview to scroll past the last line": "Vorschau das Scrollen über das Ende hinaus erlauben", + "Show line numbers for preview code blocks": "Zeilennummern in Vorschau-Code-Blöcken anzeigen", "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", "Community": "Community", - "Subscribe to Newsletter": "Subscribe to Newsletter", + "Subscribe to Newsletter": "Newsletter abonieren", "GitHub": "GitHub", "Blog": "Blog", "Facebook Group": "Facebook Group", "Twitter": "Twitter", "About": "About", "Boostnote": "Boostnote", - "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "An open source note-taking app made for programmers just like you.": "Eine OpenSource-Notizapp für Programmierer wie du und ich.", "Website": "Website", - "Development": "Development", - " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Development": "Entwicklung", + " : Development configurations for Boostnote.": " : Entwicklungseinstellungen für Boostnote.", "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", "License: GPL v3": "License: GPL v3", "Analytics": "Analytics", @@ -91,9 +90,21 @@ "Thanks,": "Thanks,", "Boostnote maintainers": "Boostnote maintainers", "Support via OpenCollective": "Support via OpenCollective", - "Language": "Language", + "Language": "Sprache", "English": "Englisch", "German": "Deutsch", "French": "Französisch", - "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying" + "Show \"Saved to Clipboard\" notification when copying": "\"Auf Clipboard gespeichert\" Benachrichtigungen beim kopieren anzeigen", + "All Notes": "Alle Notizen", + "Starred": "Starred", + "Are you sure to ": "Sind sie sicher ", + " delete": " zu löschen", + "this folder?": "diesen Ordner?", + "Confirm": "Bestätigen", + "Cancel": "Abbrechen", + "Markdown Note": "Markdown Notiz", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Dieses Format dient der Erstellung von Text Dokumenten. Checklisten, Code-Blöcke und Latex-Blöcke sind verfügbar.", + "Snippet Note": "Snippet Notiz", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Dieses Format dient der Erstellung von Code-Schnipslen. Mehrere snippets können zu einer Notiz zusammengefasst werden.", + "Tab to switch format": "Tab drücken, um das Format zu wechseln" } \ No newline at end of file diff --git a/locales/en.js b/locales/en.js index 0ea0f034..95701092 100644 --- a/locales/en.js +++ b/locales/en.js @@ -95,5 +95,7 @@ "Language": "Language", "English": "English", "German": "German", - "French": "French" + "French": "French", + "All Notes": "All Notes", + "Starred": "Starred" } \ No newline at end of file From f370508c936e034ab9d8475fcc2c7d2e73892740 Mon Sep 17 00:00:00 2001 From: mirsch Date: Wed, 7 Mar 2018 01:08:10 +0100 Subject: [PATCH 33/75] fixes #1442, Export responsive html --- browser/components/MarkdownPreview.js | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index 2bb42291..ae2bdea2 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -217,6 +217,7 @@ export default class MarkdownPreview extends React.Component { return ` + ${styles} From 0f82085cae6973c22aa3d131697e28aaeb7b2035 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 7 Mar 2018 07:10:49 +0100 Subject: [PATCH 34/75] Adjustments for Travis CI --- browser/lib/i18n.js | 11 ++++++----- browser/main/Main.js | 2 +- browser/main/modals/PreferencesModal/FolderItem.js | 2 +- browser/main/modals/PreferencesModal/StoragesTab.js | 4 ++-- browser/main/modals/PreferencesModal/UiTab.js | 12 ++++++------ locales/{de.js => de.json} | 0 locales/{en.js => en.json} | 0 locales/{fr.js => fr.json} | 0 8 files changed, 16 insertions(+), 15 deletions(-) rename locales/{de.js => de.json} (100%) rename locales/{en.js => en.json} (100%) rename locales/{fr.js => fr.json} (100%) diff --git a/browser/lib/i18n.js b/browser/lib/i18n.js index 0b51ea54..56c0da71 100644 --- a/browser/lib/i18n.js +++ b/browser/lib/i18n.js @@ -1,7 +1,8 @@ -//load package for localization +// load package for localization const i18n = new (require('i18n-2'))({ - // setup some locales - other locales default to the first locale - locales: ['en', 'de', 'fr'] -}); + // setup some locales - other locales default to the first locale + locales: ['en', 'de', 'fr'], + extension: '.json' +}) -export default i18n; \ No newline at end of file +export default i18n diff --git a/browser/main/Main.js b/browser/main/Main.js index f05ad52d..50596615 100644 --- a/browser/main/Main.js +++ b/browser/main/Main.js @@ -156,7 +156,7 @@ class Main extends React.Component { } else { i18n.setLocale('fr') } - + // Reload all data dataApi.init() .then((data) => { diff --git a/browser/main/modals/PreferencesModal/FolderItem.js b/browser/main/modals/PreferencesModal/FolderItem.js index 779ad0be..50d28013 100644 --- a/browser/main/modals/PreferencesModal/FolderItem.js +++ b/browser/main/modals/PreferencesModal/FolderItem.js @@ -180,7 +180,7 @@ class FolderItem extends React.Component { return (
    - {i18n.__('Are you sure to ')} {i18n.__(' delete')} {i18n.__('this folder?')} + {i18n.__('Are you sure to ')} {i18n.__(' delete')} {i18n.__('this folder?')}
    - {blogAlertElement}
    -
    Auth
    +
    {i18n.__('Auth')}
    - Authentication Method + {i18n.__('Authentication Method')}
    { config.blog.authMethod === 'JWT' &&
    -
    Token
    +
    {i18n.__('Token')}
    this.handleBlogChange(e)} @@ -164,7 +165,7 @@ class Blog extends React.Component { { config.blog.authMethod === 'USER' &&
    -
    UserName
    +
    {i18n.__('UserName')}
    this.handleBlogChange(e)} @@ -174,7 +175,7 @@ class Blog extends React.Component {
    -
    Password
    +
    {i18n.__('Password')}
    this.handleBlogChange(e)} diff --git a/browser/main/modals/PreferencesModal/HotkeyTab.js b/browser/main/modals/PreferencesModal/HotkeyTab.js index 32552d48..91473c3b 100644 --- a/browser/main/modals/PreferencesModal/HotkeyTab.js +++ b/browser/main/modals/PreferencesModal/HotkeyTab.js @@ -5,6 +5,7 @@ import styles from './ConfigTab.styl' import ConfigManager from 'browser/main/lib/ConfigManager' import store from 'browser/main/store' import _ from 'lodash' +import i18n from 'browser/lib/i18n' const electron = require('electron') const ipc = electron.ipcRenderer @@ -23,7 +24,7 @@ class HotkeyTab extends React.Component { this.handleSettingDone = () => { this.setState({keymapAlert: { type: 'success', - message: 'Successfully applied!' + message: i18n.__('Successfully applied!') }}) } this.handleSettingError = (err) => { @@ -77,7 +78,7 @@ class HotkeyTab extends React.Component { this.props.haveToSave({ tab: 'Hotkey', type: 'warning', - message: 'You have to save!' + message: i18n.__('You have to save!') }) } } @@ -102,9 +103,9 @@ class HotkeyTab extends React.Component { return (
    -
    Hotkeys
    +
    {i18n.__('Hotkeys')}
    -
    Show/Hide Boostnote
    +
    {i18n.__('Show/Hide Boostnote')}
    this.handleHotkeyChange(e)} @@ -124,7 +125,7 @@ class HotkeyTab extends React.Component { } {keymapAlertElement}
    diff --git a/browser/main/modals/PreferencesModal/InfoTab.js b/browser/main/modals/PreferencesModal/InfoTab.js index 964b02f3..1173389e 100644 --- a/browser/main/modals/PreferencesModal/InfoTab.js +++ b/browser/main/modals/PreferencesModal/InfoTab.js @@ -39,11 +39,11 @@ class InfoTab extends React.Component { if (!newConfig.amaEnabled) { AwsMobileAnalyticsConfig.recordDynamicCustomEvent('DISABLE_AMA') this.setState({ - amaMessage: 'We hope we will gain your trust' + amaMessage: i18n.__('We hope we will gain your trust') }) } else { this.setState({ - amaMessage: 'Thank\'s for trust us' + amaMessage: i18n.__('Thank\'s for trust us') }) } @@ -149,7 +149,7 @@ class InfoTab extends React.Component { type='checkbox' /> {i18n.__('Enable analytics to help improve Boostnote')}
    - +
    {this.infoMessage()}
    diff --git a/browser/main/modals/PreferencesModal/StorageItem.js b/browser/main/modals/PreferencesModal/StorageItem.js index 28675860..bbd082c6 100644 --- a/browser/main/modals/PreferencesModal/StorageItem.js +++ b/browser/main/modals/PreferencesModal/StorageItem.js @@ -47,9 +47,9 @@ class StorageItem extends React.Component { handleUnlinkButtonClick (e) { const index = dialog.showMessageBox(remote.getCurrentWindow(), { type: 'warning', - message: 'Unlink Storage', - detail: 'Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.', - buttons: ['Unlink', 'Cancel'] + message: i18n.__('Unlink Storage'), + detail: i18n.__('Unlinking removes this linked storage from Boostnote. No data is removed, please manually delete the folder from your hard drive if needed.'), + buttons: [i18n.__('Unlink'), i18n.__('Cancel')] }) if (index === 0) { diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 1939e0a9..fbcae1d0 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -30,7 +30,7 @@ class UiTab extends React.Component { this.handleSettingDone = () => { this.setState({UiAlert: { type: 'success', - message: 'Successfully applied!' + message: i18n.__('Successfully applied!') }}) } this.handleSettingError = (err) => { @@ -108,7 +108,7 @@ class UiTab extends React.Component { this.props.haveToSave({ tab: 'UI', type: 'warning', - message: 'You have to save!' + message: i18n.__('You have to save!') }) } }) @@ -474,7 +474,7 @@ class UiTab extends React.Component {
    {UiAlertElement}
    diff --git a/browser/main/modals/PreferencesModal/index.js b/browser/main/modals/PreferencesModal/index.js index 490237ab..70e25a88 100644 --- a/browser/main/modals/PreferencesModal/index.js +++ b/browser/main/modals/PreferencesModal/index.js @@ -118,12 +118,12 @@ class Preferences extends React.Component { const content = this.renderContent() const tabs = [ - {target: 'STORAGES', label: 'Storage'}, - {target: 'HOTKEY', label: 'Hotkeys', Hotkey: this.state.HotkeyAlert}, - {target: 'UI', label: 'Interface', UI: this.state.UIAlert}, - {target: 'INFO', label: 'About'}, - {target: 'CROWDFUNDING', label: 'Crowdfunding'}, - {target: 'BLOG', label: 'Blog', Blog: this.state.BlogAlert} + {target: 'STORAGES', label: i18n.__('Storage')}, + {target: 'HOTKEY', label: i18n.__('Hotkeys'), Hotkey: this.state.HotkeyAlert}, + {target: 'UI', label: i18n.__('Interface'), UI: this.state.UIAlert}, + {target: 'INFO', label: i18n.__('About')}, + {target: 'CROWDFUNDING', label: i18n.__('Crowdfunding')}, + {target: 'BLOG', label: i18n.__('Blog'), Blog: this.state.BlogAlert} ] const navButtons = tabs.map((tab) => { diff --git a/locales/de.json b/locales/de.json index 70bd3c76..3e7138a5 100644 --- a/locales/de.json +++ b/locales/de.json @@ -88,8 +88,8 @@ "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", "Thanks,": "Thanks,", - "Boostnote maintainers": "Boostnote maintainers", - "Support via OpenCollective": "Support via OpenCollective", + "Boostnote maintainers": "Boostnote Betreuer", + "Support via OpenCollective": "Support per OpenCollective", "Language": "Sprache", "English": "Englisch", "German": "Deutsch", @@ -106,5 +106,26 @@ "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Dieses Format dient der Erstellung von Text Dokumenten. Checklisten, Code-Blöcke und Latex-Blöcke sind verfügbar.", "Snippet Note": "Snippet Notiz", "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Dieses Format dient der Erstellung von Code-Schnipslen. Mehrere snippets können zu einer Notiz zusammengefasst werden.", - "Tab to switch format": "Tab drücken, um das Format zu wechseln" + "Tab to switch format": "Tab drücken, um das Format zu wechseln", + "Updated": "Bearbeitet", + "Created": "Erstellt", + "Alphabetically": "Alphabetisch", + "Default View": "Standardansicht", + "Compressed View": "Komprimierte Ansicht", + "Search": "Suchen", + "Blog Type": "Blog-Typ", + "Blog Address": "Blog Adresse", + "Save": "Speichern", + "Auth": "Authentifizierung", + "Authentication Method": "Authentifizierungsmethode", + "JWT": "JWT", + "USER": "BENUTZER", + "Token": "Token", + "Storage": "Speicherorte", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Boostnote anzeigen/verstecken", + "Restore": "Restore", + "Permanent Delete": "Dauerhaft Löschen", + "Confirm note deletion": "Löschen bestätigen", + "This will permanently remove this note.": "Notiz wird dauerhaft gelöscht" } \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index 95701092..aba9be61 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1,6 +1,13 @@ { + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", "Ctrl(^)": "Ctrl", "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", "MODIFICATION DATE": "MODIFICATION DATE", "Words": "Words", "Letters": "Letters", @@ -12,57 +19,20 @@ ".txt": ".txt", ".html": ".html", "Print": "Print", - "Toggle Mode": "Toggle Mode", - "Trash": "Trash", "Your preferences for Boostnote": "Your preferences for Boostnote", - "Edit": "Edit", - "Delete": "Delete", - "Crowdfunding": "Crowdfunding", - "Dear everyone,": "Dear everyone,", - "Thank you for using Boostnote!": "Thank you for using Boostnote!", - "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", - "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", - "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", - "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", - "Thanks,": "Thanks,", - "Boostnote maintainers": "Boostnote maintainers", - "Support via OpenCollective": "Support via OpenCollective", - "Make a note": "Make a note", - "Ctrl": "Ctrl", - "Notes": "Notes", - "Tags": "Tags", - "Preferences": "Preferences", "Storages": "Storages", "Add Storage Location": "Add Storage Location", "Add Folder": "Add Folder", "Open Storage folder": "Open Storage folder", "Unlink": "Unlink", - "Community": "Community", - "Subscribe to Newsletter": "Subscribe to Newsletter", - "GitHub": "GitHub", - "Blog": "Blog", - "Facebook Group": "Facebook Group", - "Twitter": "Twitter", - "About": "About", - "Boostnote": "Boostnote", - "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", - "Website": "Website", - "Development": "Development", - " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", - "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", - "License: GPL v3": "License: GPL v3", - "Analytics": "Analytics", - "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", - "You can see how it works on ": "You can see how it works on ", - "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", - "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Edit": "Edit", + "Delete": "Delete", "Interface": "Interface", "Interface Theme": "Interface Theme", - "Default": "Default", + "Default": "Delete", "White": "White", "Solarized Dark": "Solarized Dark", "Dark": "Dark", - "Show "Saved to Clipboard" notification when copying": "Show "Saved to Clipboard" notification when copying", "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", "Editor Theme": "Editor Theme", "Editor Font Size": "Editor Font Size", @@ -91,11 +61,71 @@ "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", - "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", "Language": "Language", "English": "English", "German": "German", "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", "All Notes": "All Notes", - "Starred": "Starred" + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note." } \ No newline at end of file diff --git a/locales/fr.json b/locales/fr.json index cfcca1a5..aba9be61 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -4,6 +4,8 @@ "Preferences": "Preferences", "Make a note": "Make a note", "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", "Toggle Mode": "Toggle Mode", "Trash": "Trash", "MODIFICATION DATE": "MODIFICATION DATE", @@ -18,17 +20,19 @@ ".html": ".html", "Print": "Print", "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", "Interface": "Interface", "Interface Theme": "Interface Theme", - "Default": "Default", + "Default": "Delete", "White": "White", "Solarized Dark": "Solarized Dark", "Dark": "Dark", - "Language": "Language", - "English": "English", - "German": "German", - "French": "French", - "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", "Editor Theme": "Editor Theme", "Editor Font Size": "Editor Font Size", @@ -56,5 +60,72 @@ "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", - "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter" + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note." } \ No newline at end of file From 40b5472866ea2bc692384d041917d8e906e7f431 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 7 Mar 2018 08:37:55 +0100 Subject: [PATCH 36/75] Adjustments for Travis CI --- browser/main/Detail/SnippetNoteDetail.js | 10 +++++----- browser/main/Detail/index.js | 6 +++--- locales/de.json | 3 ++- locales/en.json | 3 ++- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/browser/main/Detail/SnippetNoteDetail.js b/browser/main/Detail/SnippetNoteDetail.js index 9b5c7456..048dccad 100644 --- a/browser/main/Detail/SnippetNoteDetail.js +++ b/browser/main/Detail/SnippetNoteDetail.js @@ -265,9 +265,9 @@ class SnippetNoteDetail extends React.Component { if (this.state.note.snippets[index].content.trim().length > 0) { const dialogIndex = dialog.showMessageBox(remote.getCurrentWindow(), { type: 'warning', - message: i18n.__('Delete a snippet'), - detail: i18n.__('This work cannot be undone.'), - buttons: [ i18n.__('Confirm'), i18n.__('Cancel')] + message: i18n.__('Delete a snippet'), + detail: i18n.__('This work cannot be undone.'), + buttons: [i18n.__('Confirm'), i18n.__('Cancel')] }) if (dialogIndex === 0) { this.deleteSnippetByIndex(index) @@ -508,8 +508,8 @@ class SnippetNoteDetail extends React.Component { showWarning () { dialog.showMessageBox(remote.getCurrentWindow(), { type: 'warning', - message: i18n.__('Sorry!'), - detail: i18n.__('md/text import is available only a markdown note.'), + message: i18n.__('Sorry!'), + detail: i18n.__('md/text import is available only a markdown note.'), buttons: ['OK'] }) } diff --git a/browser/main/Detail/index.js b/browser/main/Detail/index.js index 70084cf9..d07df204 100644 --- a/browser/main/Detail/index.js +++ b/browser/main/Detail/index.js @@ -41,9 +41,9 @@ class Detail extends React.Component { const alertConfig = { type: 'warning', - message: i18n.__('Confirm note deletion'), - detail: i18n.__('This will permanently remove this note.'), - buttons: [ i18n.__('Confirm'), i18n.__('Cancel')] + message: i18n.__('Confirm note deletion'), + detail: i18n.__('This will permanently remove this note.'), + buttons: [i18n.__('Confirm'), i18n.__('Cancel')] } const dialogueButtonIndex = dialog.showMessageBox(remote.getCurrentWindow(), alertConfig) diff --git a/locales/de.json b/locales/de.json index 3e7138a5..a3d0d92e 100644 --- a/locales/de.json +++ b/locales/de.json @@ -127,5 +127,6 @@ "Restore": "Restore", "Permanent Delete": "Dauerhaft Löschen", "Confirm note deletion": "Löschen bestätigen", - "This will permanently remove this note.": "Notiz wird dauerhaft gelöscht" + "This will permanently remove this note.": "Notiz wird dauerhaft gelöscht", + "You have to save!": "You have to save!" } \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index aba9be61..a43c6de9 100644 --- a/locales/en.json +++ b/locales/en.json @@ -127,5 +127,6 @@ "Restore": "Restore", "Permanent Delete": "Permanent Delete", "Confirm note deletion": "Confirm note deletion", - "This will permanently remove this note.": "This will permanently remove this note." + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!" } \ No newline at end of file From 74c32bed296600b1de4dd709a6e9f59aa05875b4 Mon Sep 17 00:00:00 2001 From: Kazz Yokomizo Date: Thu, 8 Mar 2018 11:35:41 +0900 Subject: [PATCH 37/75] Update-readme --- readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/readme.md b/readme.md index 67a5689d..b5d02729 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -:mega: Open sourcing our [Android and iOS apps](https://github.com/BoostIO/Boostnote-mobile)! +:mega: We've launched a blogging platform with markdown called **[Boostlog](https://boostlog.io/)**. ![Boostnote app screenshot](./resources/repository/top.png) @@ -25,8 +25,8 @@ Boostnote is an open source project. It's an independent project with its ongoin ## Community - [Facebook Group](https://www.facebook.com/groups/boostnote/) - [Twitter](https://twitter.com/boostnoteapp) -- [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/enQtMzAzMjI1MTIyNTQ3LTc2MjNiYWU3NTc1YjZlMTk3NzFmOWE1ZWU1MGRhMzBkMGIwMWFjOWMxMDRiM2I2NzkzYzc4OGZhNmVhZjYzZTM) -- [Blog](https://boostlog.io/@junp1234) +- [Slack Group](https://join.slack.com/t/boostnote-group/shared_invite/enQtMzI3NTIxMTQzMTQzLTUyYWZmZWM1YzcwYzQ5OWQ5YzA3Y2M2NzUzNmIwNzYzMjg5NmQyOGJlNzcyZDJhMGY0ZDc0ZjdlZDFhMDdiMWE) +- [Blog](https://boostlog.io/tags/boostnote) - [Reddit](https://www.reddit.com/r/Boostnote/) From d01a7b16a111290a976678afecee50aad81d41cd Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Thu, 8 Mar 2018 23:40:13 +1100 Subject: [PATCH 38/75] fixed codeblock style in exported HTML file --- browser/components/MarkdownPreview.js | 4 ++-- browser/lib/markdown.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/browser/components/MarkdownPreview.js b/browser/components/MarkdownPreview.js index ae2bdea2..537ebe38 100755 --- a/browser/components/MarkdownPreview.js +++ b/browser/components/MarkdownPreview.js @@ -421,9 +421,9 @@ export default class MarkdownPreview extends React.Component { el.innerHTML = '' if (codeBlockTheme.indexOf('solarized') === 0) { const [refThema, color] = codeBlockTheme.split(' ') - el.parentNode.className += ` cm-s-${refThema} cm-s-${color} CodeMirror` + el.parentNode.className += ` cm-s-${refThema} cm-s-${color}` } else { - el.parentNode.className += ` cm-s-${codeBlockTheme} CodeMirror` + el.parentNode.className += ` cm-s-${codeBlockTheme}` } CodeMirror.runMode(content, syntax.mime, el, { tabSize: indentSize diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index b97f9d56..bfe621f7 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -39,7 +39,7 @@ var md = markdownit({ if (langType === 'sequence') { return `
    ${str}
    ` } - return '
    ' +
    +    return '
    ' +
           '' + fileName + '' +
           createGutter(str, firstLineNumber) +
           '' +
    
    From 4d41c7f37f1de2f1baf55c868dcc838f7ad26a3f Mon Sep 17 00:00:00 2001
    From: Simon 
    Date: Fri, 9 Mar 2018 07:39:08 +0100
    Subject: [PATCH 39/75] Changed default language to en
    
    ---
     browser/main/Main.js              | 6 +++---
     browser/main/lib/ConfigManager.js | 6 +++---
     2 files changed, 6 insertions(+), 6 deletions(-)
    
    diff --git a/browser/main/Main.js b/browser/main/Main.js
    index 50596615..ae6fa471 100644
    --- a/browser/main/Main.js
    +++ b/browser/main/Main.js
    @@ -149,12 +149,12 @@ class Main extends React.Component {
         } else {
           document.body.setAttribute('data-theme', 'default')
         }
    -    if (config.ui.language === 'en') {
    -      i18n.setLocale('en')
    +    if (config.ui.language === 'fr') {
    +      i18n.setLocale('fr')
         } else if (config.ui.language === 'de') {
           i18n.setLocale('de')
         } else {
    -      i18n.setLocale('fr')
    +      i18n.setLocale('en')
         }
     
         // Reload all data
    diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js
    index 0d4730fe..71eecd57 100644
    --- a/browser/main/lib/ConfigManager.js
    +++ b/browser/main/lib/ConfigManager.js
    @@ -133,12 +133,12 @@ function set (updates) {
         document.body.setAttribute('data-theme', 'default')
       }
     
    -  if (newConfig.ui.language === 'en') {
    -    i18n.setLocale('en')
    +  if (newConfig.ui.language === 'fr') {
    +    i18n.setLocale('fr')
       } else if (newConfig.ui.language === 'de') {
         i18n.setLocale('de')
       } else {
    -    i18n.setLocale('fr')
    +    i18n.setLocale('en')
       }
     
       let editorTheme = document.getElementById('editorTheme')
    
    From bd385ec062c4692bd1d3e58e68771cfaac346c0f Mon Sep 17 00:00:00 2001
    From: Yu-Hung Ou 
    Date: Fri, 9 Mar 2018 23:27:49 +1100
    Subject: [PATCH 40/75] increased the minimum count of dummy folders to 2
    
    ---
     tests/fixtures/TestDummy.js | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/tests/fixtures/TestDummy.js b/tests/fixtures/TestDummy.js
    index 4edcc9cf..c62d3849 100644
    --- a/tests/fixtures/TestDummy.js
    +++ b/tests/fixtures/TestDummy.js
    @@ -22,7 +22,7 @@ function dummyBoostnoteJSONData (override = {}, isLegacy = false) {
       if (override.folders == null) {
         data.folders = []
     
    -    var folderCount = Math.floor((Math.random() * 5)) + 1
    +    var folderCount = Math.floor((Math.random() * 5)) + 2
         for (var i = 0; i < folderCount; i++) {
           var key = keygen()
           while (data.folders.some((folder) => folder.key === key)) {
    
    From 410e82e3754f3640cad514925716129a30ad433b Mon Sep 17 00:00:00 2001
    From: Yu-Hung Ou 
    Date: Fri, 9 Mar 2018 23:28:01 +1100
    Subject: [PATCH 41/75] increased the minimum count of dummy notes to 2
    
    ---
     tests/fixtures/TestDummy.js | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/tests/fixtures/TestDummy.js b/tests/fixtures/TestDummy.js
    index c62d3849..a1f5d16e 100644
    --- a/tests/fixtures/TestDummy.js
    +++ b/tests/fixtures/TestDummy.js
    @@ -105,7 +105,7 @@ function dummyStorage (storagePath, override = {}) {
     
       sander.writeFileSync(path.join(storagePath, 'boostnote.json'), JSON.stringify(jsonData))
       var notesData = []
    -  var noteCount = Math.floor((Math.random() * 15)) + 1
    +  var noteCount = Math.floor((Math.random() * 15)) + 2
       for (var i = 0; i < noteCount; i++) {
         var key = keygen()
         while (notesData.some((note) => note.key === key)) {
    
    From 8fb0b5b57231a079b90828ba16d8ca841d7fb406 Mon Sep 17 00:00:00 2001
    From: paalon 
    Date: Sat, 10 Mar 2018 00:36:00 +0900
    Subject: [PATCH 42/75] Update KaTeX Library from 0.8.3 to 0.9.0.
    
    ---
     package.json |   2 +-
     yarn.lock    | 135 ++++++++++++++++++++++++++++++++++++++++++++++++---
     2 files changed, 128 insertions(+), 9 deletions(-)
    
    diff --git a/package.json b/package.json
    index 6b90ade9..04ca2baa 100644
    --- a/package.json
    +++ b/package.json
    @@ -61,7 +61,7 @@
         "iconv-lite": "^0.4.19",
         "immutable": "^3.8.1",
         "js-sequence-diagrams": "^1000000.0.6",
    -    "katex": "^0.8.3",
    +    "katex": "^0.9.0",
         "lodash": "^4.11.1",
         "lodash-move": "^1.1.1",
         "markdown-it": "^6.0.1",
    diff --git a/yarn.lock b/yarn.lock
    index c5da5dcd..f0c81311 100644
    --- a/yarn.lock
    +++ b/yarn.lock
    @@ -114,6 +114,12 @@ ansi-styles@^2.2.1:
       version "2.2.1"
       resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
     
    +ansi-styles@^3.2.1:
    +  version "3.2.1"
    +  resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
    +  dependencies:
    +    color-convert "^1.9.0"
    +
     ansi-styles@~1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178"
    @@ -1381,6 +1387,14 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
         strip-ansi "^3.0.0"
         supports-color "^2.0.0"
     
    +chalk@^2.3.0, chalk@^2.3.1:
    +  version "2.3.2"
    +  resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
    +  dependencies:
    +    ansi-styles "^3.2.1"
    +    escape-string-regexp "^1.0.5"
    +    supports-color "^5.3.0"
    +
     charenc@~0.0.1:
       version "0.0.2"
       resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
    @@ -1523,6 +1537,12 @@ color-convert@^1.3.0:
       dependencies:
         color-name "^1.1.1"
     
    +color-convert@^1.9.0:
    +  version "1.9.1"
    +  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
    +  dependencies:
    +    color-name "^1.1.1"
    +
     color-name@^1.0.0, color-name@^1.1.1:
       version "1.1.2"
       resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.2.tgz#5c8ab72b64bd2215d617ae9559ebb148475cf98d"
    @@ -2057,6 +2077,13 @@ doctrine@^2.0.0:
         esutils "^2.0.2"
         isarray "^1.0.0"
     
    +dom-serializer@0:
    +  version "0.1.0"
    +  resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82"
    +  dependencies:
    +    domelementtype "~1.1.1"
    +    entities "~1.1.1"
    +
     dom-storage@^2.0.2:
       version "2.0.2"
       resolved "https://registry.yarnpkg.com/dom-storage/-/dom-storage-2.0.2.tgz#ed17cbf68abd10e0aef8182713e297c5e4b500b0"
    @@ -2069,6 +2096,27 @@ domain-browser@^1.1.1:
       version "1.1.7"
       resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.1.7.tgz#867aa4b093faa05f1de08c06f4d7b21fdf8698bc"
     
    +domelementtype@1, domelementtype@^1.3.0:
    +  version "1.3.0"
    +  resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2"
    +
    +domelementtype@~1.1.1:
    +  version "1.1.3"
    +  resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b"
    +
    +domhandler@^2.3.0:
    +  version "2.4.1"
    +  resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259"
    +  dependencies:
    +    domelementtype "1"
    +
    +domutils@^1.5.1:
    +  version "1.7.0"
    +  resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
    +  dependencies:
    +    dom-serializer "0"
    +    domelementtype "1"
    +
     dot-prop@^3.0.0:
       version "3.0.0"
       resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177"
    @@ -2249,7 +2297,7 @@ enhanced-resolve@~0.9.0:
         memory-fs "^0.2.0"
         tapable "^0.1.8"
     
    -entities@~1.1.1:
    +entities@^1.1.1, entities@~1.1.1:
       version "1.1.1"
       resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
     
    @@ -3274,6 +3322,10 @@ has-flag@^2.0.0:
       version "2.0.0"
       resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51"
     
    +has-flag@^3.0.0:
    +  version "3.0.0"
    +  resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
    +
     has-unicode@^2.0.0:
       version "2.0.1"
       resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
    @@ -3361,6 +3413,17 @@ html-encoding-sniffer@^1.0.1:
       dependencies:
         whatwg-encoding "^1.0.1"
     
    +htmlparser2@^3.9.0:
    +  version "3.9.2"
    +  resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
    +  dependencies:
    +    domelementtype "^1.3.0"
    +    domhandler "^2.3.0"
    +    domutils "^1.5.1"
    +    entities "^1.1.1"
    +    inherits "^2.0.1"
    +    readable-stream "^2.0.2"
    +
     http-errors@~1.6.1:
       version "1.6.1"
       resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257"
    @@ -3910,11 +3973,11 @@ jsx-ast-utils@^2.0.0:
       dependencies:
         array-includes "^3.0.3"
     
    -katex@^0.8.3:
    -  version "0.8.3"
    -  resolved "https://registry.yarnpkg.com/katex/-/katex-0.8.3.tgz#909d99864baf964c3ccae39c4a99a8e0fb9a1bd0"
    +katex@^0.9.0:
    +  version "0.9.0"
    +  resolved "https://registry.yarnpkg.com/katex/-/katex-0.9.0.tgz#26a7d082c21d53725422d2d71da9b2d8455fbd4a"
       dependencies:
    -    match-at "^0.1.0"
    +    match-at "^0.1.1"
     
     kind-of@^3.0.2:
       version "3.2.2"
    @@ -4019,14 +4082,30 @@ lodash.difference@^4.3.0:
       version "4.5.0"
       resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
     
    +lodash.escaperegexp@^4.1.2:
    +  version "4.1.2"
    +  resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
    +
     lodash.get@^4.0.0:
       version "4.4.2"
       resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
     
    +lodash.isplainobject@^4.0.6:
    +  version "4.0.6"
    +  resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
    +
    +lodash.isstring@^4.0.1:
    +  version "4.0.1"
    +  resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
    +
     lodash.memoize@^4.1.2:
       version "4.1.2"
       resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
     
    +lodash.mergewith@^4.6.0:
    +  version "4.6.1"
    +  resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927"
    +
     lodash.some@^4.5.1:
       version "4.6.0"
       resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
    @@ -4162,9 +4241,9 @@ markdown-it@^6.0.1:
         mdurl "~1.0.1"
         uc.micro "^1.0.1"
     
    -match-at@^0.1.0:
    -  version "0.1.0"
    -  resolved "https://registry.yarnpkg.com/match-at/-/match-at-0.1.0.tgz#f561e7709ff9a105b85cc62c6b8ee7c15bf24f31"
    +match-at@^0.1.1:
    +  version "0.1.1"
    +  resolved "https://registry.yarnpkg.com/match-at/-/match-at-0.1.1.tgz#25d040d291777704d5e6556bbb79230ec2de0540"
     
     matcher@^0.1.1:
       version "0.1.2"
    @@ -5142,6 +5221,14 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0
         source-map "^0.5.6"
         supports-color "^3.2.3"
     
    +postcss@^6.0.14:
    +  version "6.0.19"
    +  resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555"
    +  dependencies:
    +    chalk "^2.3.1"
    +    source-map "^0.6.1"
    +    supports-color "^5.2.0"
    +
     power-assert-context-formatter@^1.0.4:
       version "1.1.1"
       resolved "https://registry.yarnpkg.com/power-assert-context-formatter/-/power-assert-context-formatter-1.1.1.tgz#edba352d3ed8a603114d667265acce60d689ccdf"
    @@ -5847,6 +5934,21 @@ sander@^0.5.1:
         mkdirp "^0.5.1"
         rimraf "^2.5.2"
     
    +sanitize-html@^1.18.2:
    +  version "1.18.2"
    +  resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.18.2.tgz#61877ba5a910327e42880a28803c2fbafa8e4642"
    +  dependencies:
    +    chalk "^2.3.0"
    +    htmlparser2 "^3.9.0"
    +    lodash.clonedeep "^4.5.0"
    +    lodash.escaperegexp "^4.1.2"
    +    lodash.isplainobject "^4.0.6"
    +    lodash.isstring "^4.0.1"
    +    lodash.mergewith "^4.6.0"
    +    postcss "^6.0.14"
    +    srcset "^1.0.0"
    +    xtend "^4.0.0"
    +
     sax@0.5.x:
       version "0.5.8"
       resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
    @@ -6012,6 +6114,10 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1:
       version "0.5.6"
       resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
     
    +source-map@^0.6.1:
    +  version "0.6.1"
    +  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
    +
     source-map@~0.2.0:
       version "0.2.0"
       resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d"
    @@ -6050,6 +6156,13 @@ sprintf-js@~1.0.2:
       version "1.0.3"
       resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
     
    +srcset@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/srcset/-/srcset-1.0.0.tgz#a5669de12b42f3b1d5e83ed03c71046fc48f41ef"
    +  dependencies:
    +    array-uniq "^1.0.2"
    +    number-is-nan "^1.0.0"
    +
     sshpk@^1.7.0:
       version "1.13.0"
       resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c"
    @@ -6287,6 +6400,12 @@ supports-color@^3.1.0, supports-color@^3.1.1, supports-color@^3.2.3:
       dependencies:
         has-flag "^1.0.0"
     
    +supports-color@^5.2.0, supports-color@^5.3.0:
    +  version "5.3.0"
    +  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0"
    +  dependencies:
    +    has-flag "^3.0.0"
    +
     svgo@^0.7.0:
       version "0.7.2"
       resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5"
    
    From 4f6c35713e7914219c09b7aeac37b7ec4d9e0f79 Mon Sep 17 00:00:00 2001
    From: Simon 
    Date: Fri, 9 Mar 2018 17:30:11 +0100
    Subject: [PATCH 43/75] Added languages; better German translation
    
    ---
     browser/lib/i18n.js                           |   2 +-
     browser/main/Main.js                          |  22 ++-
     browser/main/lib/ConfigManager.js             |  22 ++-
     browser/main/modals/PreferencesModal/UiTab.js |  12 +-
     locales/da.json                               | 143 ++++++++++++++++++
     locales/de.json                               |  27 +++-
     locales/en.json                               |  13 +-
     locales/es.json                               | 143 ++++++++++++++++++
     locales/fr.json                               |  14 +-
     locales/ja.json                               | 143 ++++++++++++++++++
     locales/ko.json                               | 143 ++++++++++++++++++
     locales/no.json                               | 143 ++++++++++++++++++
     locales/pl.json                               | 143 ++++++++++++++++++
     locales/pt.json                               | 143 ++++++++++++++++++
     locales/sq.json                               | 143 ++++++++++++++++++
     locales/zh-CN.json                            | 143 ++++++++++++++++++
     locales/zh-TW.json                            | 143 ++++++++++++++++++
     17 files changed, 1528 insertions(+), 14 deletions(-)
     create mode 100644 locales/da.json
     create mode 100644 locales/es.json
     create mode 100644 locales/ja.json
     create mode 100644 locales/ko.json
     create mode 100644 locales/no.json
     create mode 100644 locales/pl.json
     create mode 100644 locales/pt.json
     create mode 100644 locales/sq.json
     create mode 100644 locales/zh-CN.json
     create mode 100644 locales/zh-TW.json
    
    diff --git a/browser/lib/i18n.js b/browser/lib/i18n.js
    index 56c0da71..1f3c95c5 100644
    --- a/browser/lib/i18n.js
    +++ b/browser/lib/i18n.js
    @@ -1,7 +1,7 @@
     // load package for localization
     const i18n = new (require('i18n-2'))({
       // setup some locales - other locales default to the first locale
    -  locales: ['en', 'de', 'fr'],
    +  locales: ['en', 'sq', 'zh-CN', 'zh-TW', 'da', 'fr', 'de', 'ja', 'ko', 'no', 'pl', 'pt', 'es'],
       extension: '.json'
     })
     
    diff --git a/browser/main/Main.js b/browser/main/Main.js
    index ae6fa471..13294c0f 100644
    --- a/browser/main/Main.js
    +++ b/browser/main/Main.js
    @@ -149,10 +149,30 @@ class Main extends React.Component {
         } else {
           document.body.setAttribute('data-theme', 'default')
         }
    -    if (config.ui.language === 'fr') {
    +    if (config.ui.language === 'sq') {
    +      i18n.setLocale('sq')
    +    } else if (config.ui.language === 'zh-CN') {
    +      i18n.setLocale('zh-CN')
    +    } else if (config.ui.language === 'zh-TW') {
    +      i18n.setLocale('zh-TW')
    +    } else if (config.ui.language === 'da') {
    +      i18n.setLocale('da')
    +    } else if (config.ui.language === 'fr') {
           i18n.setLocale('fr')
         } else if (config.ui.language === 'de') {
           i18n.setLocale('de')
    +    } else if (config.ui.language === 'ja') {
    +      i18n.setLocale('ja')
    +    } else if (config.ui.language === 'ko') {
    +      i18n.setLocale('ko')
    +    } else if (config.ui.language === 'no') {
    +      i18n.setLocale('no')
    +    } else if (config.ui.language === 'pl') {
    +      i18n.setLocale('pl')
    +    } else if (config.ui.language === 'pt') {
    +      i18n.setLocale('pt')
    +    } else if (config.ui.language === 'es') {
    +      i18n.setLocale('es')
         } else {
           i18n.setLocale('en')
         }
    diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js
    index 71eecd57..28c8d806 100644
    --- a/browser/main/lib/ConfigManager.js
    +++ b/browser/main/lib/ConfigManager.js
    @@ -133,10 +133,30 @@ function set (updates) {
         document.body.setAttribute('data-theme', 'default')
       }
     
    -  if (newConfig.ui.language === 'fr') {
    +  if (newConfig.ui.language === 'sq') {
    +    i18n.setLocale('sq')
    +  } else if (newConfig.ui.language === 'zh-CN') {
    +    i18n.setLocale('zh-CN')
    +  } else if (newConfig.ui.language === 'zh-TW') {
    +    i18n.setLocale('zh-TW')
    +  } else if (newConfig.ui.language === 'da') {
    +    i18n.setLocale('da')
    +  } else if (newConfig.ui.language === 'fr') {
         i18n.setLocale('fr')
       } else if (newConfig.ui.language === 'de') {
         i18n.setLocale('de')
    +  } else if (newConfig.ui.language === 'ja') {
    +    i18n.setLocale('ja')
    +  } else if (newConfig.ui.language === 'ko') {
    +    i18n.setLocale('ko')
    +  } else if (newConfig.ui.language === 'no') {
    +    i18n.setLocale('no')
    +  } else if (newConfig.ui.language === 'pl') {
    +    i18n.setLocale('pl')
    +  } else if (newConfig.ui.language === 'pt') {
    +    i18n.setLocale('pt')
    +  } else if (newConfig.ui.language === 'es') {
    +    i18n.setLocale('es')
       } else {
         i18n.setLocale('en')
       }
    diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js
    index fbcae1d0..b6144d51 100644
    --- a/browser/main/modals/PreferencesModal/UiTab.js
    +++ b/browser/main/modals/PreferencesModal/UiTab.js
    @@ -177,9 +177,19 @@ class UiTab extends React.Component {
                     onChange={(e) => this.handleUIChange(e)}
                     ref='uiLanguage'
                   >
    +                
    +                
    +                
    +                
                     
    -                
                     
    +                
    +                
    +                
    +                
    +                
    +                
    +                
                   
                 
    diff --git a/locales/da.json b/locales/da.json new file mode 100644 index 00000000..27c94e6e --- /dev/null +++ b/locales/da.json @@ -0,0 +1,143 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" +} \ No newline at end of file diff --git a/locales/de.json b/locales/de.json index a3d0d92e..ae9c84d6 100644 --- a/locales/de.json +++ b/locales/de.json @@ -8,7 +8,7 @@ "to create a new note": "um eine neue Notiz zu erstellen", "Toggle Mode": "Modus umschalten", "Trash": "Papierkorb", - "MODIFICATION DATE": "MODIFICATION DATE", + "MODIFICATION DATE": "ÄNDERUNGSDATUM", "Words": "Wörter", "Letters": "Buchstaben", "STORAGE": "SPEICHERORT", @@ -24,11 +24,11 @@ "Add Storage Location": "Speicherort Hinzufügen", "Add Folder": "Ordner Hinzufügen", "Open Storage folder": "Speicherort Öffnen", - "Unlink": "Unlink", + "Unlink": "Verknüpfung aufheben", "Edit": "Bearbeiten", "Delete": "Löschen", "Interface": "Interface", - "Interface Theme": "Interface Theme", + "Interface Theme": "Interface-Thema", "Default": "Standard", "White": "Weiß", "Solarized Dark": "Solarized Dark", @@ -62,7 +62,7 @@ "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", "Community": "Community", - "Subscribe to Newsletter": "Newsletter abonieren", + "Subscribe to Newsletter": "Newsletter abonnieren", "GitHub": "GitHub", "Blog": "Blog", "Facebook Group": "Facebook Group", @@ -76,10 +76,10 @@ "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", "License: GPL v3": "License: GPL v3", "Analytics": "Analytics", - "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote sammelt anonyme Daten, um die App zu verbessern und nicht persönliche Informationen, wie z.B. der Inhalt deiner Notizen.", "You can see how it works on ": "You can see how it works on ", - "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", - "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "You can choose to enable or disable this option.": "Du kannst wählen, ob du diese Option aktivierst oder daektivierst.", + "Enable analytics to help improve Boostnote": "Datenerhebung zur Verbesserung von Boostnote aktivieren", "Crowdfunding": "Crowdfunding", "Dear everyone,": "Dear everyone,", "Thank you for using Boostnote!": "Thank you for using Boostnote!", @@ -128,5 +128,16 @@ "Permanent Delete": "Dauerhaft Löschen", "Confirm note deletion": "Löschen bestätigen", "This will permanently remove this note.": "Notiz wird dauerhaft gelöscht", - "You have to save!": "You have to save!" + "You have to save!": "Es muss gespeichert werden", + "Albanian": "Albanisch", + "Danish": "Dänisch", + "Japanese": "Japanisch", + "Korean": "Koreanisch", + "Norwegian": "Norwegisch", + "Polish": "Polnish", + "Portuguese": "Portugiesisch", + "Spanish": "Spanisch", + "Chinese (zh-CN)": "Chinesisch (zh-CN)", + "Chinese (zh-TW)": "Chinesisch (zh-TW)", + "Successfully applied!": "Erfolgreich angewendet!" } \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index a43c6de9..27c94e6e 100644 --- a/locales/en.json +++ b/locales/en.json @@ -128,5 +128,16 @@ "Permanent Delete": "Permanent Delete", "Confirm note deletion": "Confirm note deletion", "This will permanently remove this note.": "This will permanently remove this note.", - "Successfully applied!": "Successfully applied!" + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" } \ No newline at end of file diff --git a/locales/es.json b/locales/es.json new file mode 100644 index 00000000..27c94e6e --- /dev/null +++ b/locales/es.json @@ -0,0 +1,143 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" +} \ No newline at end of file diff --git a/locales/fr.json b/locales/fr.json index aba9be61..27c94e6e 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -127,5 +127,17 @@ "Restore": "Restore", "Permanent Delete": "Permanent Delete", "Confirm note deletion": "Confirm note deletion", - "This will permanently remove this note.": "This will permanently remove this note." + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" } \ No newline at end of file diff --git a/locales/ja.json b/locales/ja.json new file mode 100644 index 00000000..27c94e6e --- /dev/null +++ b/locales/ja.json @@ -0,0 +1,143 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" +} \ No newline at end of file diff --git a/locales/ko.json b/locales/ko.json new file mode 100644 index 00000000..27c94e6e --- /dev/null +++ b/locales/ko.json @@ -0,0 +1,143 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" +} \ No newline at end of file diff --git a/locales/no.json b/locales/no.json new file mode 100644 index 00000000..27c94e6e --- /dev/null +++ b/locales/no.json @@ -0,0 +1,143 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" +} \ No newline at end of file diff --git a/locales/pl.json b/locales/pl.json new file mode 100644 index 00000000..27c94e6e --- /dev/null +++ b/locales/pl.json @@ -0,0 +1,143 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" +} \ No newline at end of file diff --git a/locales/pt.json b/locales/pt.json new file mode 100644 index 00000000..27c94e6e --- /dev/null +++ b/locales/pt.json @@ -0,0 +1,143 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" +} \ No newline at end of file diff --git a/locales/sq.json b/locales/sq.json new file mode 100644 index 00000000..27c94e6e --- /dev/null +++ b/locales/sq.json @@ -0,0 +1,143 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" +} \ No newline at end of file diff --git a/locales/zh-CN.json b/locales/zh-CN.json new file mode 100644 index 00000000..27c94e6e --- /dev/null +++ b/locales/zh-CN.json @@ -0,0 +1,143 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" +} \ No newline at end of file diff --git a/locales/zh-TW.json b/locales/zh-TW.json new file mode 100644 index 00000000..27c94e6e --- /dev/null +++ b/locales/zh-TW.json @@ -0,0 +1,143 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!" +} \ No newline at end of file From cfffa1b10a8f97513ebf4cf838bb42b725aa8048 Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Sun, 11 Mar 2018 16:22:04 +1100 Subject: [PATCH 44/75] fixed missing classname in lib/markdown highlight render function --- browser/lib/markdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index d1f32640..8b6b4d30 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -41,7 +41,7 @@ class Markdown { if (langType === 'sequence') { return `
    ${str}
    ` } - return '
    ' +
    +        return '
    ' +
               '' + fileName + '' +
               createGutter(str, firstLineNumber) +
               '' +
    
    From 46fc010cf9da5de3472d2f53be01341ddfaaf9d8 Mon Sep 17 00:00:00 2001
    From: Junyoung Choi 
    Date: Mon, 12 Mar 2018 11:34:17 +0900
    Subject: [PATCH 45/75] v0.11.0
    
    ---
     package.json | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/package.json b/package.json
    index 567159c5..72741792 100644
    --- a/package.json
    +++ b/package.json
    @@ -1,7 +1,7 @@
     {
       "name": "boost",
       "productName": "Boostnote",
    -  "version": "0.10.0",
    +  "version": "0.11.0",
       "main": "index.js",
       "description": "Boostnote",
       "license": "GPL-3.0",
    
    From ecabd37cbbf2b43a5e8aaee9324179966dfb5005 Mon Sep 17 00:00:00 2001
    From: Simon 
    Date: Mon, 12 Mar 2018 07:26:19 +0100
    Subject: [PATCH 46/75] Setting default language in DEFAULT_CONFIG
    
    ---
     browser/main/lib/ConfigManager.js | 1 +
     1 file changed, 1 insertion(+)
    
    diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js
    index 28c8d806..c7c5fc26 100644
    --- a/browser/main/lib/ConfigManager.js
    +++ b/browser/main/lib/ConfigManager.js
    @@ -22,6 +22,7 @@ export const DEFAULT_CONFIG = {
         toggleMain: OSX ? 'Cmd + Alt + L' : 'Super + Alt + E'
       },
       ui: {
    +    language: 'en',
         theme: 'default',
         showCopyNotification: true,
         disableDirectWrite: false,
    
    From 10b86aec495e1fe88b2c54aa3d84e256f506d64e Mon Sep 17 00:00:00 2001
    From: Junyoung Choi 
    Date: Mon, 12 Mar 2018 17:40:27 +0900
    Subject: [PATCH 47/75] Allow checkbox
    
    ---
     browser/lib/markdown.js | 5 +++--
     1 file changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js
    index 8b6b4d30..a2b9da51 100644
    --- a/browser/lib/markdown.js
    +++ b/browser/lib/markdown.js
    @@ -55,11 +55,12 @@ class Markdown {
     
         // Sanitize use rinput before other plugins
         this.md.use(sanitize, {
    -      allowedTags: ['img', 'iframe'],
    +      allowedTags: ['img', 'iframe', 'input'],
           allowedAttributes: {
             '*': ['alt', 'style'],
             'img': ['src', 'width', 'height'],
    -        'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen']
    +        'iframe': ['src', 'width', 'height', 'frameborder', 'allowfullscreen'],
    +        'input': ['type', 'id', 'checked']
           },
           allowedIframeHostnames: ['www.youtube.com']
         })
    
    From f435595ad8d81ea7d972b81f5727d2dcd02446c6 Mon Sep 17 00:00:00 2001
    From: Jeroen Ketelaar 
    Date: Mon, 12 Mar 2018 09:42:44 +0100
    Subject: [PATCH 48/75] Fixed English typo & grammar
    
    ---
     browser/main/modals/PreferencesModal/InfoTab.js | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/browser/main/modals/PreferencesModal/InfoTab.js b/browser/main/modals/PreferencesModal/InfoTab.js
    index 25c0b255..57385f28 100644
    --- a/browser/main/modals/PreferencesModal/InfoTab.js
    +++ b/browser/main/modals/PreferencesModal/InfoTab.js
    @@ -42,7 +42,7 @@ class InfoTab extends React.Component {
           })
         } else {
           this.setState({
    -        amaMessage: 'Thank\'s for trust us'
    +        amaMessage: 'Thanks for trusting us'
           })
         }
     
    
    From bb2978b3704d359b0d28004a4f4aeb558f156f66 Mon Sep 17 00:00:00 2001
    From: Junyoung Choi 
    Date: Mon, 12 Mar 2018 17:53:16 +0900
    Subject: [PATCH 49/75] v0.11.1
    
    ---
     package.json | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/package.json b/package.json
    index 72741792..3f1248e6 100644
    --- a/package.json
    +++ b/package.json
    @@ -1,7 +1,7 @@
     {
       "name": "boost",
       "productName": "Boostnote",
    -  "version": "0.11.0",
    +  "version": "0.11.1 ",
       "main": "index.js",
       "description": "Boostnote",
       "license": "GPL-3.0",
    
    From f53c182cfb9bf40df4a89f2c189f0cffc3ce01f0 Mon Sep 17 00:00:00 2001
    From: Junyoung Choi 
    Date: Mon, 12 Mar 2018 18:50:22 +0900
    Subject: [PATCH 50/75] Fix version
    
    ---
     package.json | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/package.json b/package.json
    index 3f1248e6..bf277851 100644
    --- a/package.json
    +++ b/package.json
    @@ -1,7 +1,7 @@
     {
       "name": "boost",
       "productName": "Boostnote",
    -  "version": "0.11.1 ",
    +  "version": "0.11.1",
       "main": "index.js",
       "description": "Boostnote",
       "license": "GPL-3.0",
    
    From 5ed5950ed5d772e418e68c0b773718ff90e7fb79 Mon Sep 17 00:00:00 2001
    From: Kazu Yokomizo 
    Date: Mon, 12 Mar 2018 22:14:06 +0900
    Subject: [PATCH 51/75] Fix note list UI
    
    ---
     browser/components/NoteItem.js   |  2 +-
     browser/components/NoteItem.styl | 12 ++++++------
     2 files changed, 7 insertions(+), 7 deletions(-)
    
    diff --git a/browser/components/NoteItem.js b/browser/components/NoteItem.js
    index 2013cfa0..d5d3d549 100644
    --- a/browser/components/NoteItem.js
    +++ b/browser/components/NoteItem.js
    @@ -100,7 +100,7 @@ const NoteItem = ({
               {note.isStarred
                 ?  : ''
               }
    -          {note.isPinned && !pathname.match(/\/home|\/starred|\/trash/)
    +          {note.isPinned && !pathname.match(/\/starred|\/trash/)
                 ?  : ''
               }
               {note.type === 'MARKDOWN_NOTE'
    diff --git a/browser/components/NoteItem.styl b/browser/components/NoteItem.styl
    index 5203ccea..4067a6cd 100644
    --- a/browser/components/NoteItem.styl
    +++ b/browser/components/NoteItem.styl
    @@ -144,18 +144,18 @@ $control-height = 30px
       padding-bottom 2px
     
     .item-star
    -  position relative
    -  width 16px
    -  height 16px
    +  position absolute
    +  right 2px
    +  top 5px
       color alpha($ui-favorite-star-button-color, 60%)
       font-size 12px
       padding 0
       border-radius 17px
     
     .item-pin
    -  position relative
    -  width 34px
    -  height 34px
    +  position absolute
    +  right 25px
    +  top 7px
       color #E54D42
       font-size 14px
       padding 0
    
    From da9067a67292c23ec50a179a0a57dc73612b48b5 Mon Sep 17 00:00:00 2001
    From: mirsch 
    Date: Mon, 12 Mar 2018 15:23:37 +0100
    Subject: [PATCH 52/75] fix "copy note link from note list" introduced in #1583
     to reflect changes from #1636
    
    ---
     browser/main/NoteList/index.js | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js
    index e12b5c75..21265763 100644
    --- a/browser/main/NoteList/index.js
    +++ b/browser/main/NoteList/index.js
    @@ -669,7 +669,7 @@ class NoteList extends React.Component {
       }
     
       copyNoteLink (note) {
    -    const noteLink = `[${note.title}](${note.storage}-${note.key})`
    +    const noteLink = `[${note.title}](${note.key})`
         return copy(noteLink)
       }
     
    
    From a30d977727c8f2c0d3fb52a19cbc4c3f69c889af Mon Sep 17 00:00:00 2001
    From: Yu-Hung Ou 
    Date: Tue, 13 Mar 2018 23:42:14 +1100
    Subject: [PATCH 53/75] added draggable folder handle
    
    ---
     browser/components/StorageItem.js   | 66 ++++++++++++++++++++---------
     browser/components/StorageItem.styl | 22 +++++++---
     2 files changed, 63 insertions(+), 25 deletions(-)
    
    diff --git a/browser/components/StorageItem.js b/browser/components/StorageItem.js
    index c92579da..87696a57 100644
    --- a/browser/components/StorageItem.js
    +++ b/browser/components/StorageItem.js
    @@ -8,6 +8,17 @@ import CSSModules from 'browser/lib/CSSModules'
     import _ from 'lodash'
     import { SortableHandle } from 'react-sortable-hoc'
     
    +const DraggableIcon = SortableHandle(({ className }) => (
    +  
    +))
    +
    +const FolderIcon = ({ className, color, isActive }) => {
    +  const iconStyle = isActive ? 'fa-folder-open-o' : 'fa-folder-o'
    +  return (
    +    
    +  )
    +}
    +
     /**
      * @param {boolean} isActive
      * @param {Function} handleButtonClick
    @@ -22,34 +33,51 @@ import { SortableHandle } from 'react-sortable-hoc'
      * @return {React.Component}
      */
     const StorageItem = ({
    -  isActive, handleButtonClick, handleContextMenu, folderName,
    -  folderColor, isFolded, noteCount, handleDrop, handleDragEnter, handleDragLeave
    +  styles,
    +  isActive,
    +  handleButtonClick,
    +  handleContextMenu,
    +  folderName,
    +  folderColor,
    +  isFolded,
    +  noteCount,
    +  handleDrop,
    +  handleDragEnter,
    +  handleDragLeave
     }) => {
    -  const FolderDragger = SortableHandle(({ className }) => )
       return (
    -    
       )
     }
    diff --git a/browser/components/StorageItem.styl b/browser/components/StorageItem.styl
    index c89d195f..842f8d66 100644
    --- a/browser/components/StorageItem.styl
    +++ b/browser/components/StorageItem.styl
    @@ -13,6 +13,7 @@
       border none
       overflow ellipsis
       font-size 14px
    +  align-items: center
       &:first-child
         margin-top 0
       &:hover
    @@ -22,7 +23,7 @@
       &:active
         color $$ui-button-default-color
         background-color alpha($ui-button-default--active-backgroundColor, 20%)
    -    
    +
     .folderList-item--active
       @extend .folderList-item
       color #1EC38B
    @@ -34,9 +35,7 @@
     .folderList-item-name
       display block
       flex 1
    -  padding 0 12px
    -  height 26px
    -  line-height 26px
    +  padding-right: 10px
       border-width 0 0 0 2px
       border-style solid
       border-color transparent
    @@ -69,9 +68,20 @@
     .folderList-item-name--folded
       @extend .folderList-item-name
       padding-left 7px
    -  text
    +  .folderList-item-icon
         font-size 9px
     
    +.folderList-item-icon
    +  padding-right: 10px
    +
    +.folderList-item-reorder
    +  font-size: 9px
    +  padding: 10px 8px 10px 9px;
    +  color: rgba(147, 147, 149, 0.3)
    +  cursor: ns-resize
    +  &:before
    +    content: "\f142 \f142"
    +
     body[data-theme="white"]
       .folderList-item
         color $ui-inactive-text-color
    @@ -127,4 +137,4 @@ body[data-theme="solarized-dark"]
           background-color $ui-solarized-dark-button-backgroundColor
         &:hover
           color $ui-solarized-dark-text-color
    -      background-color $ui-solarized-dark-button-backgroundColor
    \ No newline at end of file
    +      background-color $ui-solarized-dark-button-backgroundColor
    
    From 571d159a1f01b558d0d4863666383550f4160ddb Mon Sep 17 00:00:00 2001
    From: Junyoung Choi 
    Date: Tue, 13 Mar 2018 22:00:07 +0900
    Subject: [PATCH 54/75] Add table and details stuff to whitelist
    
    ---
     browser/lib/markdown.js | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js
    index a2b9da51..b16838f6 100644
    --- a/browser/lib/markdown.js
    +++ b/browser/lib/markdown.js
    @@ -55,7 +55,7 @@ class Markdown {
     
         // Sanitize use rinput before other plugins
         this.md.use(sanitize, {
    -      allowedTags: ['img', 'iframe', 'input'],
    +      allowedTags: ['img', 'iframe', 'input', 'details', 'summary', 'table', 'th', 'tr', 'td', 'thead', 'tfoot', 'tbody'],
           allowedAttributes: {
             '*': ['alt', 'style'],
             'img': ['src', 'width', 'height'],
    
    From 0816a9410ba2f7c486cd387a1dbba815f7ba29a4 Mon Sep 17 00:00:00 2001
    From: Junyoung Choi 
    Date: Tue, 13 Mar 2018 22:41:17 +0900
    Subject: [PATCH 55/75] Use same settings of github
    
    ---
     browser/lib/markdown.js | 32 ++++++++++++++++++++++++++++++--
     1 file changed, 30 insertions(+), 2 deletions(-)
    
    diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js
    index b16838f6..7a2a7a8a 100644
    --- a/browser/lib/markdown.js
    +++ b/browser/lib/markdown.js
    @@ -55,9 +55,37 @@ class Markdown {
     
         // Sanitize use rinput before other plugins
         this.md.use(sanitize, {
    -      allowedTags: ['img', 'iframe', 'input', 'details', 'summary', 'table', 'th', 'tr', 'td', 'thead', 'tfoot', 'tbody'],
    +      allowedTags: ['iframe', 'input',
    +        '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'
    +      ],
           allowedAttributes: {
    -        '*': ['alt', 'style'],
    +        '*': [
    +          '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'
    +        ],
    +        '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']
    
    From b8658abbadf743b1a3c14042e472d7b8a228360e Mon Sep 17 00:00:00 2001
    From: Junyoung Choi 
    Date: Tue, 13 Mar 2018 23:12:32 +0900
    Subject: [PATCH 56/75] v0.11.2
    
    ---
     package.json | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/package.json b/package.json
    index bf277851..a4a53173 100644
    --- a/package.json
    +++ b/package.json
    @@ -1,7 +1,7 @@
     {
       "name": "boost",
       "productName": "Boostnote",
    -  "version": "0.11.1",
    +  "version": "0.11.2",
       "main": "index.js",
       "description": "Boostnote",
       "license": "GPL-3.0",
    
    From 65434453b8a58644f2b93674e13fa06c3a27369a Mon Sep 17 00:00:00 2001
    From: lijinglue 
    Date: Wed, 14 Mar 2018 00:23:38 +0800
    Subject: [PATCH 57/75] hotfix: update markdown render in blog post feature
    
    ---
     browser/main/NoteList/index.js | 5 +++--
     1 file changed, 3 insertions(+), 2 deletions(-)
    
    diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js
    index 21265763..06880bab 100644
    --- a/browser/main/NoteList/index.js
    +++ b/browser/main/NoteList/index.js
    @@ -15,11 +15,12 @@ import path from 'path'
     import { hashHistory } from 'react-router'
     import copy from 'copy-to-clipboard'
     import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig'
    -import markdown from '../../lib/markdown'
    +import Markdown from '../../lib/markdown'
     
     const { remote } = require('electron')
     const { Menu, MenuItem, dialog } = remote
     const WP_POST_PATH = '/wp/v2/posts'
    +const markdown = new Markdown()
     
     function sortByCreatedAt (a, b) {
       return new Date(b.createdAt) - new Date(a.createdAt)
    @@ -708,7 +709,7 @@ class NoteList extends React.Component {
           authToken = `Bearer ${token}`
         }
         const contentToRender = firstNote.content.replace(`# ${firstNote.title}`, '')
    -    var data = {
    +    const data = {
           title: firstNote.title,
           content: markdown.render(contentToRender),
           status: 'publish'
    
    From f3d59a9b61ecd0fa2182b3894fbbefa6f7055bfe Mon Sep 17 00:00:00 2001
    From: Junyoung Choi 
    Date: Wed, 14 Mar 2018 13:03:57 +0900
    Subject: [PATCH 58/75] Allow b tag and style attribute
    
    ---
     browser/lib/markdown.js | 3 ++-
     1 file changed, 2 insertions(+), 1 deletion(-)
    
    diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js
    index 7a2a7a8a..22f581e4 100644
    --- a/browser/lib/markdown.js
    +++ b/browser/lib/markdown.js
    @@ -55,13 +55,14 @@ class Markdown {
     
         // Sanitize use rinput before other plugins
         this.md.use(sanitize, {
    -      allowedTags: ['iframe', 'input',
    +      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'
           ],
           allowedAttributes: {
             '*': [
    +          'style',
               'abbr', 'accept', 'accept-charset',
               'accesskey', 'action', 'align', 'alt', 'axis',
               'border', 'cellpadding', 'cellspacing', 'char',
    
    From 6a1e9c58180a29c3e3b2e6992485050c86069975 Mon Sep 17 00:00:00 2001
    From: Yu-Hung Ou 
    Date: Sun, 11 Mar 2018 16:43:20 +1100
    Subject: [PATCH 59/75] removed katex script tag from main.html, use import
     instead
    
    ---
     browser/lib/markdown.js | 3 +--
     lib/main.html           | 1 -
     2 files changed, 1 insertion(+), 3 deletions(-)
    
    diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js
    index 22f581e4..5c887b3d 100644
    --- a/browser/lib/markdown.js
    +++ b/browser/lib/markdown.js
    @@ -4,10 +4,9 @@ import emoji from 'markdown-it-emoji'
     import math from '@rokt33r/markdown-it-math'
     import _ from 'lodash'
     import ConfigManager from 'browser/main/lib/ConfigManager'
    +import katex from 'katex'
     import {lastFindInArray} from './utils'
     
    -// FIXME We should not depend on global variable.
    -const katex = window.katex
     const config = ConfigManager.get()
     
     function createGutter (str, firstLineNumber) {
    diff --git a/lib/main.html b/lib/main.html
    index 8852bd9e..dbb61b75 100644
    --- a/lib/main.html
    +++ b/lib/main.html
    @@ -97,7 +97,6 @@
       
     
       
    -  
       
       
       
    
    From 3cba71b7a87e04af430ca649ec0e4e9741550554 Mon Sep 17 00:00:00 2001
    From: Yu-Hung Ou 
    Date: Sun, 11 Mar 2018 16:59:00 +1100
    Subject: [PATCH 60/75] upgraded ava to 0.25.0
    
    ---
     package.json                |    2 +-
     tests/lib/rc-parser-test.js |    2 +-
     yarn.lock                   | 1340 +++++++++++++++++++++++------------
     3 files changed, 905 insertions(+), 439 deletions(-)
    
    diff --git a/package.json b/package.json
    index a4a53173..c2d56760 100644
    --- a/package.json
    +++ b/package.json
    @@ -92,7 +92,7 @@
         "uuid": "^3.2.1"
       },
       "devDependencies": {
    -    "ava": "^0.16.0",
    +    "ava": "^0.25.0",
         "babel-core": "^6.14.0",
         "babel-loader": "^6.2.0",
         "babel-plugin-react-transform": "^2.0.0",
    diff --git a/tests/lib/rc-parser-test.js b/tests/lib/rc-parser-test.js
    index 19e5bf94..21d70d3c 100644
    --- a/tests/lib/rc-parser-test.js
    +++ b/tests/lib/rc-parser-test.js
    @@ -29,5 +29,5 @@ test('RcParser should return a json object', t => {
     })
     
     function filePath (filename) {
    -  return path.join('boostnoterc', filename)
    +  return path.join(`${__dirname}/boostnoterc`, filename)
     }
    diff --git a/yarn.lock b/yarn.lock
    index 84ed3d1c..e5019fea 100644
    --- a/yarn.lock
    +++ b/yarn.lock
    @@ -2,6 +2,57 @@
     # yarn lockfile v1
     
     
    +"@ava/babel-plugin-throws-helper@^2.0.0":
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-2.0.0.tgz#2fc1fe3c211a71071a4eca7b8f7af5842cd1ae7c"
    +
    +"@ava/babel-preset-stage-4@^1.1.0":
    +  version "1.1.0"
    +  resolved "https://registry.yarnpkg.com/@ava/babel-preset-stage-4/-/babel-preset-stage-4-1.1.0.tgz#ae60be881a0babf7d35f52aba770d1f6194f76bd"
    +  dependencies:
    +    babel-plugin-check-es2015-constants "^6.8.0"
    +    babel-plugin-syntax-trailing-function-commas "^6.20.0"
    +    babel-plugin-transform-async-to-generator "^6.16.0"
    +    babel-plugin-transform-es2015-destructuring "^6.19.0"
    +    babel-plugin-transform-es2015-function-name "^6.9.0"
    +    babel-plugin-transform-es2015-modules-commonjs "^6.18.0"
    +    babel-plugin-transform-es2015-parameters "^6.21.0"
    +    babel-plugin-transform-es2015-spread "^6.8.0"
    +    babel-plugin-transform-es2015-sticky-regex "^6.8.0"
    +    babel-plugin-transform-es2015-unicode-regex "^6.11.0"
    +    babel-plugin-transform-exponentiation-operator "^6.8.0"
    +    package-hash "^1.2.0"
    +
    +"@ava/babel-preset-transform-test-files@^3.0.0":
    +  version "3.0.0"
    +  resolved "https://registry.yarnpkg.com/@ava/babel-preset-transform-test-files/-/babel-preset-transform-test-files-3.0.0.tgz#cded1196a8d8d9381a509240ab92e91a5ec069f7"
    +  dependencies:
    +    "@ava/babel-plugin-throws-helper" "^2.0.0"
    +    babel-plugin-espower "^2.3.2"
    +
    +"@ava/write-file-atomic@^2.2.0":
    +  version "2.2.0"
    +  resolved "https://registry.yarnpkg.com/@ava/write-file-atomic/-/write-file-atomic-2.2.0.tgz#d625046f3495f1f5e372135f473909684b429247"
    +  dependencies:
    +    graceful-fs "^4.1.11"
    +    imurmurhash "^0.1.4"
    +    slide "^1.1.5"
    +
    +"@concordance/react@^1.0.0":
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/@concordance/react/-/react-1.0.0.tgz#fcf3cad020e5121bfd1c61d05bc3516aac25f734"
    +  dependencies:
    +    arrify "^1.0.1"
    +
    +"@ladjs/time-require@^0.1.4":
    +  version "0.1.4"
    +  resolved "https://registry.yarnpkg.com/@ladjs/time-require/-/time-require-0.1.4.tgz#5c615d75fd647ddd5de9cf6922649558856b21a1"
    +  dependencies:
    +    chalk "^0.4.0"
    +    date-time "^0.1.1"
    +    pretty-ms "^0.2.1"
    +    text-table "^0.2.0"
    +
     "@rokt33r/markdown-it-math@^4.0.1":
       version "4.0.2"
       resolved "https://registry.yarnpkg.com/@rokt33r/markdown-it-math/-/markdown-it-math-4.0.2.tgz#87c7172f459833b05e406cfc846e0c0b7ebc24ef"
    @@ -88,16 +139,20 @@ amdefine@>=0.0.4:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
     
    -ansi-align@^1.1.0:
    -  version "1.1.0"
    -  resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-1.1.0.tgz#2f0c1658829739add5ebb15e6b0c6e3423f016ba"
    +ansi-align@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f"
       dependencies:
    -    string-width "^1.0.1"
    +    string-width "^2.0.0"
     
     ansi-escapes@^1.1.0:
       version "1.4.0"
       resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e"
     
    +ansi-escapes@^3.0.0:
    +  version "3.0.0"
    +  resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
    +
     ansi-regex@^0.2.0, ansi-regex@^0.2.1:
       version "0.2.1"
       resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-0.2.1.tgz#0d8e946967a3d8143f93e24e298525fc1b2235f9"
    @@ -106,6 +161,10 @@ ansi-regex@^2.0.0:
       version "2.1.1"
       resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
     
    +ansi-regex@^3.0.0:
    +  version "3.0.0"
    +  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
    +
     ansi-styles@^1.1.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.1.0.tgz#eaecbf66cd706882760b2f4691582b8f55d7a7de"
    @@ -114,7 +173,7 @@ ansi-styles@^2.2.1:
       version "2.2.1"
       resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
     
    -ansi-styles@^3.2.1:
    +ansi-styles@^3.1.0, ansi-styles@^3.2.1:
       version "3.2.1"
       resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
       dependencies:
    @@ -206,7 +265,7 @@ array-unique@^0.2.1:
       version "0.2.1"
       resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"
     
    -arrify@^1.0.0:
    +arrify@^1.0.0, arrify@^1.0.1:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
     
    @@ -307,6 +366,10 @@ asynckit@^0.4.0:
       version "0.4.0"
       resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
     
    +auto-bind@^1.1.0:
    +  version "1.2.0"
    +  resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-1.2.0.tgz#8b7e318aad53d43ba8a8ecaf0066d85d5f798cd6"
    +
     autoprefixer@^6.3.1:
       version "6.7.7"
       resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-6.7.7.tgz#1dbd1c835658e35ce3f9984099db00585c782014"
    @@ -318,103 +381,103 @@ autoprefixer@^6.3.1:
         postcss "^5.2.16"
         postcss-value-parser "^3.2.3"
     
    -ava-files@^0.1.1:
    -  version "0.1.1"
    -  resolved "https://registry.yarnpkg.com/ava-files/-/ava-files-0.1.1.tgz#18abb6f4b87029c32fc35f2053fecd3a55f1d2b0"
    -  dependencies:
    -    arr-flatten "^1.0.1"
    -    bluebird "^3.4.1"
    -    globby "^5.0.0"
    -    ignore-by-default "^1.0.1"
    -    multimatch "^2.1.0"
    -    slash "^1.0.0"
    -
    -ava-init@^0.1.0:
    -  version "0.1.6"
    -  resolved "https://registry.yarnpkg.com/ava-init/-/ava-init-0.1.6.tgz#ef19ed0b24b6bf359dad6fbadf1a05d836395c91"
    +ava-init@^0.2.0:
    +  version "0.2.1"
    +  resolved "https://registry.yarnpkg.com/ava-init/-/ava-init-0.2.1.tgz#75ac4c8553326290d2866e63b62fa7035684bd58"
       dependencies:
         arr-exclude "^1.0.0"
    -    cross-spawn "^4.0.0"
    -    pinkie-promise "^2.0.0"
    -    read-pkg-up "^1.0.1"
    -    the-argv "^1.0.0"
    -    write-pkg "^1.0.0"
    +    execa "^0.7.0"
    +    has-yarn "^1.0.0"
    +    read-pkg-up "^2.0.0"
    +    write-pkg "^3.1.0"
     
    -ava@^0.16.0:
    -  version "0.16.0"
    -  resolved "https://registry.yarnpkg.com/ava/-/ava-0.16.0.tgz#07d7e06c627820115a84d7ee346f0bb165730454"
    +ava@^0.25.0:
    +  version "0.25.0"
    +  resolved "https://registry.yarnpkg.com/ava/-/ava-0.25.0.tgz#8ac87780514f96a6fd42e1306eaa0752ce3a407f"
       dependencies:
    +    "@ava/babel-preset-stage-4" "^1.1.0"
    +    "@ava/babel-preset-transform-test-files" "^3.0.0"
    +    "@ava/write-file-atomic" "^2.2.0"
    +    "@concordance/react" "^1.0.0"
    +    "@ladjs/time-require" "^0.1.4"
    +    ansi-escapes "^3.0.0"
    +    ansi-styles "^3.1.0"
         arr-flatten "^1.0.1"
         array-union "^1.0.1"
         array-uniq "^1.0.2"
         arrify "^1.0.0"
    -    ava-files "^0.1.1"
    -    ava-init "^0.1.0"
    -    babel-code-frame "^6.7.5"
    -    babel-core "^6.3.21"
    -    babel-plugin-ava-throws-helper "^0.1.0"
    -    babel-plugin-detective "^2.0.0"
    -    babel-plugin-espower "^2.2.0"
    -    babel-plugin-transform-runtime "^6.3.13"
    -    babel-preset-es2015 "^6.3.13"
    -    babel-preset-stage-2 "^6.3.13"
    -    babel-runtime "^6.3.19"
    +    auto-bind "^1.1.0"
    +    ava-init "^0.2.0"
    +    babel-core "^6.17.0"
    +    babel-generator "^6.26.0"
    +    babel-plugin-syntax-object-rest-spread "^6.13.0"
         bluebird "^3.0.0"
         caching-transform "^1.0.0"
    -    chalk "^1.0.0"
    +    chalk "^2.0.1"
         chokidar "^1.4.2"
    +    clean-stack "^1.1.1"
         clean-yaml-object "^0.1.0"
    -    cli-cursor "^1.0.2"
    -    cli-spinners "^0.1.2"
    -    cli-truncate "^0.2.0"
    +    cli-cursor "^2.1.0"
    +    cli-spinners "^1.0.0"
    +    cli-truncate "^1.0.0"
         co-with-promise "^4.6.0"
    +    code-excerpt "^2.1.1"
         common-path-prefix "^1.0.0"
    -    convert-source-map "^1.2.0"
    +    concordance "^3.0.0"
    +    convert-source-map "^1.5.1"
         core-assert "^0.2.0"
         currently-unhandled "^0.4.1"
    -    debug "^2.2.0"
    +    debug "^3.0.1"
    +    dot-prop "^4.1.0"
         empower-core "^0.6.1"
    -    figures "^1.4.0"
    -    find-cache-dir "^0.1.1"
    +    equal-length "^1.0.0"
    +    figures "^2.0.0"
    +    find-cache-dir "^1.0.0"
         fn-name "^2.0.0"
    +    get-port "^3.0.0"
    +    globby "^6.0.0"
         has-flag "^2.0.0"
    +    hullabaloo-config-manager "^1.1.0"
         ignore-by-default "^1.0.0"
    +    import-local "^0.1.1"
    +    indent-string "^3.0.0"
         is-ci "^1.0.7"
         is-generator-fn "^1.0.0"
         is-obj "^1.0.0"
    -    is-observable "^0.2.0"
    +    is-observable "^1.0.0"
         is-promise "^2.1.0"
         last-line-stream "^1.0.0"
    +    lodash.clonedeepwith "^4.5.0"
         lodash.debounce "^4.0.3"
         lodash.difference "^4.3.0"
    +    lodash.flatten "^4.2.0"
         loud-rejection "^1.2.0"
    -    matcher "^0.1.1"
    -    max-timeout "^1.0.0"
    -    md5-hex "^1.2.0"
    +    make-dir "^1.0.0"
    +    matcher "^1.0.0"
    +    md5-hex "^2.0.0"
         meow "^3.7.0"
    -    ms "^0.7.1"
    -    not-so-shallow "^0.1.3"
    -    object-assign "^4.0.1"
    -    observable-to-promise "^0.4.0"
    -    option-chain "^0.1.0"
    -    package-hash "^1.1.0"
    -    pkg-conf "^1.0.1"
    +    ms "^2.0.0"
    +    multimatch "^2.1.0"
    +    observable-to-promise "^0.5.0"
    +    option-chain "^1.0.0"
    +    package-hash "^2.0.0"
    +    pkg-conf "^2.0.0"
         plur "^2.0.0"
    -    power-assert-context-formatter "^1.0.4"
    -    power-assert-renderer-assertion "^1.0.1"
    -    power-assert-renderer-succinct "^1.0.1"
    -    pretty-ms "^2.0.0"
    -    repeating "^2.0.0"
    +    pretty-ms "^3.0.0"
         require-precompiled "^0.1.0"
    -    resolve-cwd "^1.0.0"
    -    set-immediate-shim "^1.0.1"
    -    source-map-support "^0.4.0"
    -    stack-utils "^0.4.0"
    -    strip-ansi "^3.0.1"
    -    strip-bom "^2.0.0"
    -    time-require "^0.1.2"
    +    resolve-cwd "^2.0.0"
    +    safe-buffer "^5.1.1"
    +    semver "^5.4.1"
    +    slash "^1.0.0"
    +    source-map-support "^0.5.0"
    +    stack-utils "^1.0.1"
    +    strip-ansi "^4.0.0"
    +    strip-bom-buf "^1.0.0"
    +    supertap "^1.0.0"
    +    supports-color "^5.0.0"
    +    trim-off-newlines "^1.0.1"
         unique-temp-dir "^1.0.0"
    -    update-notifier "^1.0.0"
    +    update-notifier "^2.3.0"
     
     aws-sdk-mobile-analytics@^0.9.2:
       version "0.9.2"
    @@ -448,7 +511,7 @@ aws4@^1.2.1:
       version "1.6.0"
       resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
     
    -babel-code-frame@^6.16.0, babel-code-frame@^6.22.0, babel-code-frame@^6.7.5:
    +babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
       version "6.22.0"
       resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
       dependencies:
    @@ -456,7 +519,15 @@ babel-code-frame@^6.16.0, babel-code-frame@^6.22.0, babel-code-frame@^6.7.5:
         esutils "^2.0.2"
         js-tokens "^3.0.0"
     
    -babel-core@^6.14.0, babel-core@^6.24.1, babel-core@^6.3.21:
    +babel-code-frame@^6.26.0:
    +  version "6.26.0"
    +  resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
    +  dependencies:
    +    chalk "^1.1.3"
    +    esutils "^2.0.2"
    +    js-tokens "^3.0.2"
    +
    +babel-core@^6.14.0, babel-core@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.1.tgz#8c428564dce1e1f41fb337ec34f4c3b022b5ad83"
       dependencies:
    @@ -480,6 +551,30 @@ babel-core@^6.14.0, babel-core@^6.24.1, babel-core@^6.3.21:
         slash "^1.0.0"
         source-map "^0.5.0"
     
    +babel-core@^6.17.0, babel-core@^6.26.0:
    +  version "6.26.0"
    +  resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8"
    +  dependencies:
    +    babel-code-frame "^6.26.0"
    +    babel-generator "^6.26.0"
    +    babel-helpers "^6.24.1"
    +    babel-messages "^6.23.0"
    +    babel-register "^6.26.0"
    +    babel-runtime "^6.26.0"
    +    babel-template "^6.26.0"
    +    babel-traverse "^6.26.0"
    +    babel-types "^6.26.0"
    +    babylon "^6.18.0"
    +    convert-source-map "^1.5.0"
    +    debug "^2.6.8"
    +    json5 "^0.5.1"
    +    lodash "^4.17.4"
    +    minimatch "^3.0.4"
    +    path-is-absolute "^1.0.1"
    +    private "^0.1.7"
    +    slash "^1.0.0"
    +    source-map "^0.5.6"
    +
     babel-generator@^6.1.0, babel-generator@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.1.tgz#e715f486c58ded25649d888944d52aa07c5d9497"
    @@ -493,13 +588,18 @@ babel-generator@^6.1.0, babel-generator@^6.24.1:
         source-map "^0.5.0"
         trim-right "^1.0.1"
     
    -babel-helper-bindify-decorators@^6.24.1:
    -  version "6.24.1"
    -  resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.24.1.tgz#14c19e5f142d7b47f19a52431e52b1ccbc40a330"
    +babel-generator@^6.26.0:
    +  version "6.26.1"
    +  resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90"
       dependencies:
    -    babel-runtime "^6.22.0"
    -    babel-traverse "^6.24.1"
    -    babel-types "^6.24.1"
    +    babel-messages "^6.23.0"
    +    babel-runtime "^6.26.0"
    +    babel-types "^6.26.0"
    +    detect-indent "^4.0.0"
    +    jsesc "^1.3.0"
    +    lodash "^4.17.4"
    +    source-map "^0.5.7"
    +    trim-right "^1.0.1"
     
     babel-helper-builder-binary-assignment-operator-visitor@^6.24.1:
       version "6.24.1"
    @@ -543,15 +643,6 @@ babel-helper-explode-assignable-expression@^6.24.1:
         babel-traverse "^6.24.1"
         babel-types "^6.24.1"
     
    -babel-helper-explode-class@^6.24.1:
    -  version "6.24.1"
    -  resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.24.1.tgz#7dc2a3910dee007056e1e31d640ced3d54eaa9eb"
    -  dependencies:
    -    babel-helper-bindify-decorators "^6.24.1"
    -    babel-runtime "^6.22.0"
    -    babel-traverse "^6.24.1"
    -    babel-types "^6.24.1"
    -
     babel-helper-function-name@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
    @@ -634,26 +725,15 @@ babel-messages@^6.23.0:
       dependencies:
         babel-runtime "^6.22.0"
     
    -babel-plugin-ava-throws-helper@^0.1.0:
    -  version "0.1.0"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-ava-throws-helper/-/babel-plugin-ava-throws-helper-0.1.0.tgz#951107708a12208026bf8ca4cef18a87bc9b0cfe"
    -  dependencies:
    -    babel-template "^6.7.0"
    -    babel-types "^6.7.2"
    -
    -babel-plugin-check-es2015-constants@^6.22.0:
    +babel-plugin-check-es2015-constants@^6.22.0, babel-plugin-check-es2015-constants@^6.8.0:
       version "6.22.0"
       resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a"
       dependencies:
         babel-runtime "^6.22.0"
     
    -babel-plugin-detective@^2.0.0:
    -  version "2.0.0"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-detective/-/babel-plugin-detective-2.0.0.tgz#6e642e83c22a335279754ebe2d754d2635f49f13"
    -
    -babel-plugin-espower@^2.2.0:
    -  version "2.3.2"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-espower/-/babel-plugin-espower-2.3.2.tgz#5516b8fcdb26c9f0e1d8160749f6e4c65e71271e"
    +babel-plugin-espower@^2.3.2:
    +  version "2.4.0"
    +  resolved "https://registry.yarnpkg.com/babel-plugin-espower/-/babel-plugin-espower-2.4.0.tgz#9f92c080e9adfe73f69baed7ab3e24f649009373"
       dependencies:
         babel-generator "^6.1.0"
         babylon "^6.1.0"
    @@ -673,22 +753,6 @@ babel-plugin-syntax-async-functions@^6.8.0:
       version "6.13.0"
       resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95"
     
    -babel-plugin-syntax-async-generators@^6.5.0:
    -  version "6.13.0"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a"
    -
    -babel-plugin-syntax-class-properties@^6.8.0:
    -  version "6.13.0"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de"
    -
    -babel-plugin-syntax-decorators@^6.13.0:
    -  version "6.13.0"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b"
    -
    -babel-plugin-syntax-dynamic-import@^6.18.0:
    -  version "6.18.0"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da"
    -
     babel-plugin-syntax-exponentiation-operator@^6.8.0:
       version "6.13.0"
       resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de"
    @@ -701,23 +765,15 @@ babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0:
       version "6.18.0"
       resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
     
    -babel-plugin-syntax-object-rest-spread@^6.8.0:
    +babel-plugin-syntax-object-rest-spread@^6.13.0:
       version "6.13.0"
       resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5"
     
    -babel-plugin-syntax-trailing-function-commas@^6.22.0:
    +babel-plugin-syntax-trailing-function-commas@^6.20.0:
       version "6.22.0"
       resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3"
     
    -babel-plugin-transform-async-generator-functions@^6.24.1:
    -  version "6.24.1"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.24.1.tgz#f058900145fd3e9907a6ddf28da59f215258a5db"
    -  dependencies:
    -    babel-helper-remap-async-to-generator "^6.24.1"
    -    babel-plugin-syntax-async-generators "^6.5.0"
    -    babel-runtime "^6.22.0"
    -
    -babel-plugin-transform-async-to-generator@^6.24.1:
    +babel-plugin-transform-async-to-generator@^6.16.0:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761"
       dependencies:
    @@ -725,25 +781,6 @@ babel-plugin-transform-async-to-generator@^6.24.1:
         babel-plugin-syntax-async-functions "^6.8.0"
         babel-runtime "^6.22.0"
     
    -babel-plugin-transform-class-properties@^6.24.1:
    -  version "6.24.1"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac"
    -  dependencies:
    -    babel-helper-function-name "^6.24.1"
    -    babel-plugin-syntax-class-properties "^6.8.0"
    -    babel-runtime "^6.22.0"
    -    babel-template "^6.24.1"
    -
    -babel-plugin-transform-decorators@^6.24.1:
    -  version "6.24.1"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.24.1.tgz#788013d8f8c6b5222bdf7b344390dfd77569e24d"
    -  dependencies:
    -    babel-helper-explode-class "^6.24.1"
    -    babel-plugin-syntax-decorators "^6.13.0"
    -    babel-runtime "^6.22.0"
    -    babel-template "^6.24.1"
    -    babel-types "^6.24.1"
    -
     babel-plugin-transform-es2015-arrow-functions@^6.22.0:
       version "6.22.0"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221"
    @@ -787,7 +824,7 @@ babel-plugin-transform-es2015-computed-properties@^6.24.1:
         babel-runtime "^6.22.0"
         babel-template "^6.24.1"
     
    -babel-plugin-transform-es2015-destructuring@^6.22.0:
    +babel-plugin-transform-es2015-destructuring@^6.19.0, babel-plugin-transform-es2015-destructuring@^6.22.0:
       version "6.23.0"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d"
       dependencies:
    @@ -806,7 +843,7 @@ babel-plugin-transform-es2015-for-of@^6.22.0:
       dependencies:
         babel-runtime "^6.22.0"
     
    -babel-plugin-transform-es2015-function-name@^6.24.1:
    +babel-plugin-transform-es2015-function-name@^6.24.1, babel-plugin-transform-es2015-function-name@^6.9.0:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b"
       dependencies:
    @@ -828,6 +865,15 @@ babel-plugin-transform-es2015-modules-amd@^6.24.1:
         babel-runtime "^6.22.0"
         babel-template "^6.24.1"
     
    +babel-plugin-transform-es2015-modules-commonjs@^6.18.0:
    +  version "6.26.0"
    +  resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz#0d8394029b7dc6abe1a97ef181e00758dd2e5d8a"
    +  dependencies:
    +    babel-plugin-transform-strict-mode "^6.24.1"
    +    babel-runtime "^6.26.0"
    +    babel-template "^6.26.0"
    +    babel-types "^6.26.0"
    +
     babel-plugin-transform-es2015-modules-commonjs@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz#d3e310b40ef664a36622200097c6d440298f2bfe"
    @@ -860,7 +906,7 @@ babel-plugin-transform-es2015-object-super@^6.24.1:
         babel-helper-replace-supers "^6.24.1"
         babel-runtime "^6.22.0"
     
    -babel-plugin-transform-es2015-parameters@^6.24.1:
    +babel-plugin-transform-es2015-parameters@^6.21.0, babel-plugin-transform-es2015-parameters@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b"
       dependencies:
    @@ -878,13 +924,13 @@ babel-plugin-transform-es2015-shorthand-properties@^6.24.1:
         babel-runtime "^6.22.0"
         babel-types "^6.24.1"
     
    -babel-plugin-transform-es2015-spread@^6.22.0:
    +babel-plugin-transform-es2015-spread@^6.22.0, babel-plugin-transform-es2015-spread@^6.8.0:
       version "6.22.0"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1"
       dependencies:
         babel-runtime "^6.22.0"
     
    -babel-plugin-transform-es2015-sticky-regex@^6.24.1:
    +babel-plugin-transform-es2015-sticky-regex@^6.24.1, babel-plugin-transform-es2015-sticky-regex@^6.8.0:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc"
       dependencies:
    @@ -904,7 +950,7 @@ babel-plugin-transform-es2015-typeof-symbol@^6.22.0:
       dependencies:
         babel-runtime "^6.22.0"
     
    -babel-plugin-transform-es2015-unicode-regex@^6.24.1:
    +babel-plugin-transform-es2015-unicode-regex@^6.11.0, babel-plugin-transform-es2015-unicode-regex@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9"
       dependencies:
    @@ -912,7 +958,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.24.1:
         babel-runtime "^6.22.0"
         regexpu-core "^2.0.0"
     
    -babel-plugin-transform-exponentiation-operator@^6.24.1:
    +babel-plugin-transform-exponentiation-operator@^6.8.0:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e"
       dependencies:
    @@ -927,13 +973,6 @@ babel-plugin-transform-flow-strip-types@^6.22.0:
         babel-plugin-syntax-flow "^6.18.0"
         babel-runtime "^6.22.0"
     
    -babel-plugin-transform-object-rest-spread@^6.22.0:
    -  version "6.23.0"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921"
    -  dependencies:
    -    babel-plugin-syntax-object-rest-spread "^6.8.0"
    -    babel-runtime "^6.22.0"
    -
     babel-plugin-transform-react-display-name@^6.23.0:
       version "6.23.0"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.23.0.tgz#4398910c358441dc4cef18787264d0412ed36b37"
    @@ -968,12 +1007,6 @@ babel-plugin-transform-regenerator@^6.24.1:
       dependencies:
         regenerator-transform "0.9.11"
     
    -babel-plugin-transform-runtime@^6.3.13:
    -  version "6.23.0"
    -  resolved "https://registry.yarnpkg.com/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz#88490d446502ea9b8e7efb0fe09ec4d99479b1ee"
    -  dependencies:
    -    babel-runtime "^6.22.0"
    -
     babel-plugin-transform-strict-mode@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758"
    @@ -1045,25 +1078,6 @@ babel-preset-react@^6.3.13:
         babel-plugin-transform-react-jsx-source "^6.22.0"
         babel-preset-flow "^6.23.0"
     
    -babel-preset-stage-2@^6.3.13:
    -  version "6.24.1"
    -  resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.24.1.tgz#d9e2960fb3d71187f0e64eec62bc07767219bdc1"
    -  dependencies:
    -    babel-plugin-syntax-dynamic-import "^6.18.0"
    -    babel-plugin-transform-class-properties "^6.24.1"
    -    babel-plugin-transform-decorators "^6.24.1"
    -    babel-preset-stage-3 "^6.24.1"
    -
    -babel-preset-stage-3@^6.24.1:
    -  version "6.24.1"
    -  resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.24.1.tgz#836ada0a9e7a7fa37cb138fb9326f87934a48395"
    -  dependencies:
    -    babel-plugin-syntax-trailing-function-commas "^6.22.0"
    -    babel-plugin-transform-async-generator-functions "^6.24.1"
    -    babel-plugin-transform-async-to-generator "^6.24.1"
    -    babel-plugin-transform-exponentiation-operator "^6.24.1"
    -    babel-plugin-transform-object-rest-spread "^6.22.0"
    -
     babel-register@^6.11.6, babel-register@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.1.tgz#7e10e13a2f71065bdfad5a1787ba45bca6ded75f"
    @@ -1076,14 +1090,26 @@ babel-register@^6.11.6, babel-register@^6.24.1:
         mkdirp "^0.5.1"
         source-map-support "^0.4.2"
     
    -babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.3.19:
    +babel-register@^6.26.0:
    +  version "6.26.0"
    +  resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071"
    +  dependencies:
    +    babel-core "^6.26.0"
    +    babel-runtime "^6.26.0"
    +    core-js "^2.5.0"
    +    home-or-tmp "^2.0.0"
    +    lodash "^4.17.4"
    +    mkdirp "^0.5.1"
    +    source-map-support "^0.4.15"
    +
    +babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0:
       version "6.26.0"
       resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
       dependencies:
         core-js "^2.4.0"
         regenerator-runtime "^0.11.0"
     
    -babel-template@^6.24.1, babel-template@^6.7.0:
    +babel-template@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.24.1.tgz#04ae514f1f93b3a2537f2a0f60a5a45fb8308333"
       dependencies:
    @@ -1093,6 +1119,16 @@ babel-template@^6.24.1, babel-template@^6.7.0:
         babylon "^6.11.0"
         lodash "^4.2.0"
     
    +babel-template@^6.26.0:
    +  version "6.26.0"
    +  resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
    +  dependencies:
    +    babel-runtime "^6.26.0"
    +    babel-traverse "^6.26.0"
    +    babel-types "^6.26.0"
    +    babylon "^6.18.0"
    +    lodash "^4.17.4"
    +
     babel-traverse@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695"
    @@ -1107,7 +1143,21 @@ babel-traverse@^6.24.1:
         invariant "^2.2.0"
         lodash "^4.2.0"
     
    -babel-types@^6.14.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.7.2:
    +babel-traverse@^6.26.0:
    +  version "6.26.0"
    +  resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
    +  dependencies:
    +    babel-code-frame "^6.26.0"
    +    babel-messages "^6.23.0"
    +    babel-runtime "^6.26.0"
    +    babel-types "^6.26.0"
    +    babylon "^6.18.0"
    +    debug "^2.6.8"
    +    globals "^9.18.0"
    +    invariant "^2.2.2"
    +    lodash "^4.17.4"
    +
    +babel-types@^6.14.0, babel-types@^6.19.0, babel-types@^6.24.1:
       version "6.24.1"
       resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975"
       dependencies:
    @@ -1116,10 +1166,23 @@ babel-types@^6.14.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.7.
         lodash "^4.2.0"
         to-fast-properties "^1.0.1"
     
    +babel-types@^6.26.0:
    +  version "6.26.0"
    +  resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
    +  dependencies:
    +    babel-runtime "^6.26.0"
    +    esutils "^2.0.2"
    +    lodash "^4.17.4"
    +    to-fast-properties "^1.0.3"
    +
     babylon@^6.1.0, babylon@^6.11.0, babylon@^6.15.0:
       version "6.17.1"
       resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.1.tgz#17f14fddf361b695981fe679385e4f1c01ebd86f"
     
    +babylon@^6.18.0:
    +  version "6.18.0"
    +  resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3"
    +
     balanced-match@^0.4.1, balanced-match@^0.4.2:
       version "0.4.2"
       resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
    @@ -1173,7 +1236,7 @@ bluebird@^2.9.30:
       version "2.11.0"
       resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
     
    -bluebird@^3.0.0, bluebird@^3.1.1, bluebird@^3.4.1:
    +bluebird@^3.0.0, bluebird@^3.1.1:
       version "3.5.0"
       resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
     
    @@ -1187,19 +1250,17 @@ boom@2.x.x:
       dependencies:
         hoek "2.x.x"
     
    -boxen@^0.6.0:
    -  version "0.6.0"
    -  resolved "https://registry.yarnpkg.com/boxen/-/boxen-0.6.0.tgz#8364d4248ac34ff0ef1b2f2bf49a6c60ce0d81b6"
    +boxen@^1.2.1:
    +  version "1.3.0"
    +  resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b"
       dependencies:
    -    ansi-align "^1.1.0"
    -    camelcase "^2.1.0"
    -    chalk "^1.1.1"
    +    ansi-align "^2.0.0"
    +    camelcase "^4.0.0"
    +    chalk "^2.0.1"
         cli-boxes "^1.0.0"
    -    filled-array "^1.0.0"
    -    object-assign "^4.0.1"
    -    repeating "^2.0.0"
    -    string-width "^1.0.1"
    -    widest-line "^1.0.0"
    +    string-width "^2.0.0"
    +    term-size "^1.2.0"
    +    widest-line "^2.0.0"
     
     brace-expansion@^1.0.0, brace-expansion@^1.1.7:
       version "1.1.7"
    @@ -1239,10 +1300,6 @@ buf-compare@^1.0.0:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/buf-compare/-/buf-compare-1.0.1.tgz#fef28da8b8113a0a0db4430b0b6467b69730b34a"
     
    -buffer-equals@^1.0.3:
    -  version "1.0.4"
    -  resolved "https://registry.yarnpkg.com/buffer-equals/-/buffer-equals-1.0.4.tgz#0353b54fd07fd9564170671ae6f66b9cf10d27f5"
    -
     buffer-shims@~1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51"
    @@ -1313,7 +1370,7 @@ camelcase@^1.0.2:
       version "1.2.1"
       resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39"
     
    -camelcase@^2.0.0, camelcase@^2.0.1, camelcase@^2.1.0:
    +camelcase@^2.0.0, camelcase@^2.0.1:
       version "2.1.1"
       resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f"
     
    @@ -1321,6 +1378,10 @@ camelcase@^3.0.0:
       version "3.0.0"
       resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a"
     
    +camelcase@^4.0.0:
    +  version "4.1.0"
    +  resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd"
    +
     caniuse-api@^1.5.2:
       version "1.6.1"
       resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-1.6.1.tgz#b534e7c734c4f81ec5fbe8aca2ad24354b962c6c"
    @@ -1387,7 +1448,7 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
         strip-ansi "^3.0.0"
         supports-color "^2.0.0"
     
    -chalk@^2.3.0, chalk@^2.3.1:
    +chalk@^2.0.1, chalk@^2.3.0, chalk@^2.3.1:
       version "2.3.2"
       resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
       dependencies:
    @@ -1440,6 +1501,10 @@ classnames@^2.2.5:
       version "2.2.5"
       resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
     
    +clean-stack@^1.1.1:
    +  version "1.3.0"
    +  resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31"
    +
     clean-yaml-object@^0.1.0:
       version "0.1.0"
       resolved "https://registry.yarnpkg.com/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz#63fb110dc2ce1a84dc21f6d9334876d010ae8b68"
    @@ -1448,22 +1513,28 @@ cli-boxes@^1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143"
     
    -cli-cursor@^1.0.1, cli-cursor@^1.0.2:
    +cli-cursor@^1.0.1:
       version "1.0.2"
       resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987"
       dependencies:
         restore-cursor "^1.0.1"
     
    -cli-spinners@^0.1.2:
    -  version "0.1.2"
    -  resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c"
    -
    -cli-truncate@^0.2.0:
    -  version "0.2.1"
    -  resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574"
    +cli-cursor@^2.1.0:
    +  version "2.1.0"
    +  resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
       dependencies:
    -    slice-ansi "0.0.4"
    -    string-width "^1.0.1"
    +    restore-cursor "^2.0.0"
    +
    +cli-spinners@^1.0.0:
    +  version "1.1.0"
    +  resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.1.0.tgz#f1847b168844d917a671eb9d147e3df497c90d06"
    +
    +cli-truncate@^1.0.0:
    +  version "1.1.0"
    +  resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-1.1.0.tgz#2b2dfd83c53cfd3572b87fc4d430a808afb04086"
    +  dependencies:
    +    slice-ansi "^1.0.0"
    +    string-width "^2.0.0"
     
     cli-width@^2.0.0:
       version "2.1.0"
    @@ -1505,6 +1576,12 @@ coa@~1.0.1:
       dependencies:
         q "^1.1.2"
     
    +code-excerpt@^2.1.1:
    +  version "2.1.1"
    +  resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-2.1.1.tgz#5fe3057bfbb71a5f300f659ef2cc0a47651ba77c"
    +  dependencies:
    +    convert-to-spaces "^1.0.1"
    +
     code-point-at@^1.0.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
    @@ -1644,6 +1721,22 @@ concat-stream@1.6.0, concat-stream@^1.4.6, concat-stream@^1.5.2:
         readable-stream "^2.2.2"
         typedarray "^0.0.6"
     
    +concordance@^3.0.0:
    +  version "3.0.0"
    +  resolved "https://registry.yarnpkg.com/concordance/-/concordance-3.0.0.tgz#b2286af54405fc995fc7345b0b106d8dd073cb29"
    +  dependencies:
    +    date-time "^2.1.0"
    +    esutils "^2.0.2"
    +    fast-diff "^1.1.1"
    +    function-name-support "^0.2.0"
    +    js-string-escape "^1.0.1"
    +    lodash.clonedeep "^4.5.0"
    +    lodash.flattendeep "^4.4.0"
    +    lodash.merge "^4.6.0"
    +    md5-hex "^2.0.0"
    +    semver "^5.3.0"
    +    well-known-symbols "^1.0.0"
    +
     concurrently@^3.4.0:
       version "3.4.0"
       resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-3.4.0.tgz#60662b3defde07375bae19aac0ab780ec748ba79"
    @@ -1666,19 +1759,16 @@ conf@^0.11.1:
         mkdirp "^0.5.1"
         pkg-up "^1.0.0"
     
    -configstore@^2.0.0:
    -  version "2.1.0"
    -  resolved "https://registry.yarnpkg.com/configstore/-/configstore-2.1.0.tgz#737a3a7036e9886102aa6099e47bb33ab1aba1a1"
    +configstore@^3.0.0:
    +  version "3.1.1"
    +  resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.1.tgz#094ee662ab83fad9917678de114faaea8fcdca90"
       dependencies:
    -    dot-prop "^3.0.0"
    +    dot-prop "^4.1.0"
         graceful-fs "^4.1.2"
    -    mkdirp "^0.5.0"
    -    object-assign "^4.0.1"
    -    os-tmpdir "^1.0.0"
    -    osenv "^0.1.0"
    -    uuid "^2.0.1"
    -    write-file-atomic "^1.1.2"
    -    xdg-basedir "^2.0.0"
    +    make-dir "^1.0.0"
    +    unique-string "^1.0.0"
    +    write-file-atomic "^2.0.0"
    +    xdg-basedir "^3.0.0"
     
     connect-history-api-fallback@^1.3.0:
       version "1.3.0"
    @@ -1710,10 +1800,18 @@ content-type@~1.0.2:
       version "1.0.2"
       resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed"
     
    -convert-source-map@^1.1.0, convert-source-map@^1.2.0:
    +convert-source-map@^1.1.0:
       version "1.5.0"
       resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5"
     
    +convert-source-map@^1.5.0, convert-source-map@^1.5.1:
    +  version "1.5.1"
    +  resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.1.tgz#b8278097b9bc229365de5c62cf5fcaed8b5599e5"
    +
    +convert-to-spaces@^1.0.1:
    +  version "1.0.2"
    +  resolved "https://registry.yarnpkg.com/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz#7e3e48bbe6d997b1417ddca2868204b4d3d85715"
    +
     cookie-signature@1.0.6:
       version "1.0.6"
       resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
    @@ -1747,11 +1845,15 @@ core-js@^2.0.0, core-js@^2.4.0:
       version "2.4.1"
       resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
     
    +core-js@^2.5.0:
    +  version "2.5.3"
    +  resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e"
    +
     core-util-is@~1.0.0:
       version "1.0.2"
       resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
     
    -create-error-class@^3.0.1:
    +create-error-class@^3.0.0, create-error-class@^3.0.1:
       version "3.0.2"
       resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6"
       dependencies:
    @@ -1765,11 +1867,12 @@ create-react-class@^15.5.1, create-react-class@^15.5.2, create-react-class@^15.6
         loose-envify "^1.3.1"
         object-assign "^4.1.1"
     
    -cross-spawn@^4.0.0:
    -  version "4.0.2"
    -  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41"
    +cross-spawn@^5.0.1:
    +  version "5.1.0"
    +  resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
       dependencies:
         lru-cache "^4.0.1"
    +    shebang-command "^1.2.0"
         which "^1.2.9"
     
     crypt@~0.0.1:
    @@ -1795,6 +1898,10 @@ crypto-browserify@3.3.0:
         ripemd160 "0.2.0"
         sha.js "2.2.6"
     
    +crypto-random-string@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
    +
     cson-parser@1.3.4:
       version "1.3.4"
       resolved "https://registry.yarnpkg.com/cson-parser/-/cson-parser-1.3.4.tgz#55f10d5aa9f960ccaa385551ae085cb3c8d284fc"
    @@ -1929,6 +2036,12 @@ date-time@^0.1.1:
       version "0.1.1"
       resolved "https://registry.yarnpkg.com/date-time/-/date-time-0.1.1.tgz#ed2f6d93d9790ce2fd66d5b5ff3edd5bbcbf3b07"
     
    +date-time@^2.1.0:
    +  version "2.1.0"
    +  resolved "https://registry.yarnpkg.com/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2"
    +  dependencies:
    +    time-zone "^1.0.0"
    +
     dateformat@1.0.2-1.2.3:
       version "1.0.2-1.2.3"
       resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-1.0.2-1.2.3.tgz#b0220c02de98617433b72851cf47de3df2cdbee9"
    @@ -1955,6 +2068,18 @@ debug@2.6.7:
       dependencies:
         ms "2.0.0"
     
    +debug@^2.6.8:
    +  version "2.6.9"
    +  resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
    +  dependencies:
    +    ms "2.0.0"
    +
    +debug@^3.0.1:
    +  version "3.1.0"
    +  resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
    +  dependencies:
    +    ms "2.0.0"
    +
     decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2:
       version "1.2.0"
       resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
    @@ -2055,6 +2180,10 @@ detect-indent@^4.0.0:
       dependencies:
         repeating "^2.0.0"
     
    +detect-indent@^5.0.0:
    +  version "5.0.0"
    +  resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
    +
     devtron@^1.1.0:
       version "1.4.0"
       resolved "https://registry.yarnpkg.com/devtron/-/devtron-1.4.0.tgz#b5e748bd6e95bbe70bfcc68aae6fe696119441e1"
    @@ -2123,15 +2252,21 @@ dot-prop@^3.0.0:
       dependencies:
         is-obj "^1.0.0"
     
    +dot-prop@^4.1.0:
    +  version "4.2.0"
    +  resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
    +  dependencies:
    +    is-obj "^1.0.0"
    +
     duplexer2@^0.1.4:
       version "0.1.4"
       resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
       dependencies:
         readable-stream "^2.0.2"
     
    -eastasianwidth@^0.1.1:
    -  version "0.1.1"
    -  resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.1.1.tgz#44d656de9da415694467335365fb3147b8572b7c"
    +duplexer3@^0.1.4:
    +  version "0.1.4"
    +  resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
     
     easy-stack@^1.0.0:
       version "1.0.0"
    @@ -2305,13 +2440,17 @@ env-paths@^0.3.0:
       version "0.3.1"
       resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-0.3.1.tgz#c30ccfcbc30c890943dc08a85582517ef00da463"
     
    +equal-length@^1.0.0:
    +  version "1.0.1"
    +  resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c"
    +
     errno@^0.1.3:
       version "0.1.4"
       resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d"
       dependencies:
         prr "~0.0.0"
     
    -error-ex@^1.2.0:
    +error-ex@^1.2.0, error-ex@^1.3.1:
       version "1.3.1"
       resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc"
       dependencies:
    @@ -2348,6 +2487,10 @@ es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14:
         es6-iterator "2"
         es6-symbol "~3.1"
     
    +es6-error@^4.0.1, es6-error@^4.0.2:
    +  version "4.1.1"
    +  resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d"
    +
     es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1:
       version "2.0.1"
       resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512"
    @@ -2571,6 +2714,10 @@ esprima@^3.1.1:
       version "3.1.3"
       resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
     
    +esprima@^4.0.0:
    +  version "4.0.0"
    +  resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
    +
     "esprima@~ 1.0.2":
       version "1.0.4"
       resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad"
    @@ -2598,7 +2745,7 @@ estraverse@^1.9.1:
       version "1.9.3"
       resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
     
    -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
    +estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0:
       version "4.2.0"
       resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
     
    @@ -2651,6 +2798,18 @@ eventsource@0.1.6:
       dependencies:
         original ">=0.0.5"
     
    +execa@^0.7.0:
    +  version "0.7.0"
    +  resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777"
    +  dependencies:
    +    cross-spawn "^5.0.1"
    +    get-stream "^3.0.0"
    +    is-stream "^1.1.0"
    +    npm-run-path "^2.0.0"
    +    p-finally "^1.0.0"
    +    signal-exit "^3.0.0"
    +    strip-eof "^1.0.0"
    +
     exit-hook@^1.0.0:
       version "1.1.1"
       resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
    @@ -2731,6 +2890,10 @@ faker@^3.1.0:
       version "3.1.0"
       resolved "https://registry.yarnpkg.com/faker/-/faker-3.1.0.tgz#0f908faf4e6ec02524e54a57e432c5c013e08c9f"
     
    +fast-diff@^1.1.1:
    +  version "1.1.2"
    +  resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154"
    +
     fast-levenshtein@~2.0.4:
       version "2.0.6"
       resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
    @@ -2781,13 +2944,19 @@ fd-slicer@~1.0.1:
       dependencies:
         pend "~1.2.0"
     
    -figures@^1.3.5, figures@^1.4.0:
    +figures@^1.3.5:
       version "1.7.0"
       resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e"
       dependencies:
         escape-string-regexp "^1.0.5"
         object-assign "^4.1.0"
     
    +figures@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
    +  dependencies:
    +    escape-string-regexp "^1.0.5"
    +
     file-entry-cache@^2.0.0:
       version "2.0.0"
       resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361"
    @@ -2809,10 +2978,6 @@ fill-range@^2.1.0:
         repeat-element "^1.1.2"
         repeat-string "^1.5.2"
     
    -filled-array@^1.0.0:
    -  version "1.1.0"
    -  resolved "https://registry.yarnpkg.com/filled-array/-/filled-array-1.1.0.tgz#c3c4f6c663b923459a9aa29912d2d031f1507f84"
    -
     finalhandler@~1.0.3:
       version "1.0.3"
       resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89"
    @@ -2833,6 +2998,14 @@ find-cache-dir@^0.1.1:
         mkdirp "^0.5.1"
         pkg-dir "^1.0.0"
     
    +find-cache-dir@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f"
    +  dependencies:
    +    commondir "^1.0.1"
    +    make-dir "^1.0.0"
    +    pkg-dir "^2.0.0"
    +
     find-root@^1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.0.0.tgz#962ff211aab25c6520feeeb8d6287f8f6e95807a"
    @@ -2844,7 +3017,7 @@ find-up@^1.0.0:
         path-exists "^2.0.0"
         pinkie-promise "^2.0.0"
     
    -find-up@^2.0.0:
    +find-up@^2.0.0, find-up@^2.1.0:
       version "2.1.0"
       resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
       dependencies:
    @@ -3015,6 +3188,10 @@ function-bind@^1.0.2, function-bind@^1.1.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
     
    +function-name-support@^0.2.0:
    +  version "0.2.0"
    +  resolved "https://registry.yarnpkg.com/function-name-support/-/function-name-support-0.2.0.tgz#55d3bfaa6eafd505a50f9bc81fdf57564a0bb071"
    +
     gauge@~2.7.3:
       version "2.7.4"
       resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
    @@ -3057,6 +3234,10 @@ get-package-info@0.0.2:
         lodash.get "^4.0.0"
         resolve "^1.1.6"
     
    +get-port@^3.0.0:
    +  version "3.2.0"
    +  resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc"
    +
     get-stdin@^4.0.1:
       version "4.0.1"
       resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
    @@ -3065,6 +3246,10 @@ get-stdin@^5.0.1:
       version "5.0.1"
       resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398"
     
    +get-stream@^3.0.0:
    +  version "3.0.0"
    +  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
    +
     getobject@~0.1.0:
       version "0.1.0"
       resolved "https://registry.yarnpkg.com/getobject/-/getobject-0.1.0.tgz#047a449789fa160d018f5486ed91320b6ec7885c"
    @@ -3145,6 +3330,12 @@ glob@~3.1.21:
         inherits "1"
         minimatch "~0.2.11"
     
    +global-dirs@^0.1.0:
    +  version "0.1.1"
    +  resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
    +  dependencies:
    +    ini "^1.3.4"
    +
     global@^4.3.0:
       version "4.3.2"
       resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f"
    @@ -3156,6 +3347,10 @@ globals@^9.0.0, globals@^9.14.0, globals@^9.2.0:
       version "9.17.0"
       resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286"
     
    +globals@^9.18.0:
    +  version "9.18.0"
    +  resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
    +
     globby@^5.0.0:
       version "5.0.0"
       resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
    @@ -3167,7 +3362,17 @@ globby@^5.0.0:
         pify "^2.0.0"
         pinkie-promise "^2.0.0"
     
    -got@^5.0.0, got@^5.1.0:
    +globby@^6.0.0:
    +  version "6.1.0"
    +  resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
    +  dependencies:
    +    array-union "^1.0.1"
    +    glob "^7.0.3"
    +    object-assign "^4.0.1"
    +    pify "^2.0.0"
    +    pinkie-promise "^2.0.0"
    +
    +got@^5.1.0:
       version "5.7.1"
       resolved "https://registry.yarnpkg.com/got/-/got-5.7.1.tgz#5f81635a61e4a6589f180569ea4e381680a51f35"
       dependencies:
    @@ -3187,6 +3392,22 @@ got@^5.0.0, got@^5.1.0:
         unzip-response "^1.0.2"
         url-parse-lax "^1.0.0"
     
    +got@^6.7.1:
    +  version "6.7.1"
    +  resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0"
    +  dependencies:
    +    create-error-class "^3.0.0"
    +    duplexer3 "^0.1.4"
    +    get-stream "^3.0.0"
    +    is-redirect "^1.0.0"
    +    is-retry-allowed "^1.0.0"
    +    is-stream "^1.0.0"
    +    lowercase-keys "^1.0.0"
    +    safe-buffer "^5.0.1"
    +    timed-out "^4.0.0"
    +    unzip-response "^2.0.1"
    +    url-parse-lax "^1.0.0"
    +
     graceful-fs@^3.0.0, graceful-fs@^3.0.5:
       version "3.0.11"
       resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818"
    @@ -3330,6 +3551,10 @@ has-unicode@^2.0.0:
       version "2.0.1"
       resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
     
    +has-yarn@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-1.0.0.tgz#89e25db604b725c8f5976fff0addc921b828a5a7"
    +
     has@^1.0.1:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
    @@ -3469,6 +3694,25 @@ https-browserify@0.0.1:
       version "0.0.1"
       resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
     
    +hullabaloo-config-manager@^1.1.0:
    +  version "1.1.1"
    +  resolved "https://registry.yarnpkg.com/hullabaloo-config-manager/-/hullabaloo-config-manager-1.1.1.tgz#1d9117813129ad035fd9e8477eaf066911269fe3"
    +  dependencies:
    +    dot-prop "^4.1.0"
    +    es6-error "^4.0.2"
    +    graceful-fs "^4.1.11"
    +    indent-string "^3.1.0"
    +    json5 "^0.5.1"
    +    lodash.clonedeep "^4.5.0"
    +    lodash.clonedeepwith "^4.5.0"
    +    lodash.isequal "^4.5.0"
    +    lodash.merge "^4.6.0"
    +    md5-hex "^2.0.0"
    +    package-hash "^2.0.0"
    +    pkg-dir "^2.0.0"
    +    resolve-from "^3.0.0"
    +    safe-buffer "^5.0.1"
    +
     humanize-plus@^1.8.1:
       version "1.8.2"
       resolved "https://registry.yarnpkg.com/humanize-plus/-/humanize-plus-1.8.2.tgz#a65b34459ad6367adbb3707a82a3c9f916167030"
    @@ -3489,7 +3733,7 @@ ieee754@^1.1.4:
       version "1.1.8"
       resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4"
     
    -ignore-by-default@^1.0.0, ignore-by-default@^1.0.1:
    +ignore-by-default@^1.0.0:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
     
    @@ -3501,6 +3745,17 @@ immutable@^3.8.1:
       version "3.8.1"
       resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.1.tgz#200807f11ab0f72710ea485542de088075f68cd2"
     
    +import-lazy@^2.1.0:
    +  version "2.1.0"
    +  resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
    +
    +import-local@^0.1.1:
    +  version "0.1.1"
    +  resolved "https://registry.yarnpkg.com/import-local/-/import-local-0.1.1.tgz#b1179572aacdc11c6a91009fb430dbcab5f668a8"
    +  dependencies:
    +    pkg-dir "^2.0.0"
    +    resolve-cwd "^2.0.0"
    +
     imurmurhash@^0.1.4:
       version "0.1.4"
       resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
    @@ -3511,6 +3766,10 @@ indent-string@^2.1.0:
       dependencies:
         repeating "^2.0.0"
     
    +indent-string@^3.0.0, indent-string@^3.1.0, indent-string@^3.2.0:
    +  version "3.2.0"
    +  resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289"
    +
     indexes-of@^1.0.1:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
    @@ -3538,6 +3797,10 @@ inherits@2.0.1:
       version "2.0.1"
       resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
     
    +ini@^1.3.4:
    +  version "1.3.5"
    +  resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
    +
     ini@~1.3.0:
       version "1.3.4"
       resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
    @@ -3574,6 +3837,12 @@ invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1:
       dependencies:
         loose-envify "^1.0.0"
     
    +invariant@^2.2.2:
    +  version "2.2.3"
    +  resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.3.tgz#1a827dfde7dcbd7c323f0ca826be8fa7c5e9d688"
    +  dependencies:
    +    loose-envify "^1.0.0"
    +
     invert-kv@^1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
    @@ -3650,7 +3919,7 @@ is-extglob@^2.1.0:
       version "2.1.1"
       resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
     
    -is-finite@^1.0.0, is-finite@^1.0.1:
    +is-finite@^1.0.0:
       version "1.0.2"
       resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa"
       dependencies:
    @@ -3682,6 +3951,13 @@ is-glob@^3.1.0:
       dependencies:
         is-extglob "^2.1.0"
     
    +is-installed-globally@^0.1.0:
    +  version "0.1.0"
    +  resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80"
    +  dependencies:
    +    global-dirs "^0.1.0"
    +    is-path-inside "^1.0.0"
    +
     is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.0:
       version "2.16.0"
       resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693"
    @@ -3711,6 +3987,12 @@ is-observable@^0.2.0:
       dependencies:
         symbol-observable "^0.2.2"
     
    +is-observable@^1.0.0:
    +  version "1.1.0"
    +  resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-1.1.0.tgz#b3e986c8f44de950867cab5403f5a3465005975e"
    +  dependencies:
    +    symbol-observable "^1.1.0"
    +
     is-path-cwd@^1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d"
    @@ -3767,7 +4049,7 @@ is-retry-allowed@^1.0.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34"
     
    -is-stream@^1.0.0, is-stream@^1.0.1:
    +is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
     
    @@ -3789,7 +4071,7 @@ is-url@^1.2.1:
       version "1.2.2"
       resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.2.tgz#498905a593bf47cc2d9e7f738372bbf7696c7f26"
     
    -is-utf8@^0.2.0:
    +is-utf8@^0.2.0, is-utf8@^0.2.1:
       version "0.2.1"
       resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
     
    @@ -3853,10 +4135,25 @@ js-sequence-diagrams@^1000000.0.6:
         raphael "~2.1.x"
         underscore "~1.4.x"
     
    +js-string-escape@^1.0.1:
    +  version "1.0.1"
    +  resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef"
    +
     js-tokens@^3.0.0:
       version "3.0.1"
       resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
     
    +js-tokens@^3.0.2:
    +  version "3.0.2"
    +  resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
    +
    +js-yaml@^3.10.0:
    +  version "3.11.0"
    +  resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef"
    +  dependencies:
    +    argparse "^1.0.7"
    +    esprima "^4.0.0"
    +
     js-yaml@^3.5.1:
       version "3.8.4"
       resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6"
    @@ -3918,6 +4215,10 @@ json-loader@^0.5.4:
       version "0.5.4"
       resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.4.tgz#8baa1365a632f58a3c46d20175fc6002c96e37de"
     
    +json-parse-better-errors@^1.0.1:
    +  version "1.0.1"
    +  resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a"
    +
     json-schema@0.2.3:
       version "0.2.3"
       resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
    @@ -3936,7 +4237,7 @@ json3@^3.3.2:
       version "3.3.2"
       resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1"
     
    -json5@^0.5.0:
    +json5@^0.5.0, json5@^0.5.1:
       version "0.5.1"
       resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
     
    @@ -3997,20 +4298,16 @@ last-line-stream@^1.0.0:
       dependencies:
         through2 "^2.0.0"
     
    -latest-version@^2.0.0:
    -  version "2.0.0"
    -  resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-2.0.0.tgz#56f8d6139620847b8017f8f1f4d78e211324168b"
    +latest-version@^3.0.0:
    +  version "3.1.0"
    +  resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15"
       dependencies:
    -    package-json "^2.0.0"
    +    package-json "^4.0.0"
     
     lazy-cache@^1.0.3:
       version "1.0.4"
       resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e"
     
    -lazy-req@^1.1.0:
    -  version "1.1.0"
    -  resolved "https://registry.yarnpkg.com/lazy-req/-/lazy-req-1.1.0.tgz#bdaebead30f8d824039ce0ce149d4daa07ba1fac"
    -
     lcid@^1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835"
    @@ -4030,7 +4327,7 @@ linkify-it@~1.2.0, linkify-it@~1.2.2:
       dependencies:
         uc.micro "^1.0.1"
     
    -load-json-file@^1.0.0, load-json-file@^1.1.0:
    +load-json-file@^1.0.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
       dependencies:
    @@ -4040,6 +4337,24 @@ load-json-file@^1.0.0, load-json-file@^1.1.0:
         pinkie-promise "^2.0.0"
         strip-bom "^2.0.0"
     
    +load-json-file@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8"
    +  dependencies:
    +    graceful-fs "^4.1.2"
    +    parse-json "^2.2.0"
    +    pify "^2.0.0"
    +    strip-bom "^3.0.0"
    +
    +load-json-file@^4.0.0:
    +  version "4.0.0"
    +  resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
    +  dependencies:
    +    graceful-fs "^4.1.2"
    +    parse-json "^4.0.0"
    +    pify "^3.0.0"
    +    strip-bom "^3.0.0"
    +
     loader-utils@^0.2.11, loader-utils@^0.2.16, loader-utils@^0.2.7, loader-utils@^0.2.9, loader-utils@~0.2.2:
       version "0.2.17"
       resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
    @@ -4074,6 +4389,10 @@ lodash.clonedeep@^4.5.0:
       version "4.5.0"
       resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
     
    +lodash.clonedeepwith@^4.5.0:
    +  version "4.5.0"
    +  resolved "https://registry.yarnpkg.com/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz#6ee30573a03a1a60d670a62ef33c10cf1afdbdd4"
    +
     lodash.debounce@^4.0.3, lodash.debounce@^4.0.8:
       version "4.0.8"
       resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
    @@ -4086,10 +4405,22 @@ lodash.escaperegexp@^4.1.2:
       version "4.1.2"
       resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
     
    +lodash.flatten@^4.2.0:
    +  version "4.4.0"
    +  resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
    +
    +lodash.flattendeep@^4.4.0:
    +  version "4.4.0"
    +  resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
    +
     lodash.get@^4.0.0:
       version "4.4.2"
       resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
     
    +lodash.isequal@^4.5.0:
    +  version "4.5.0"
    +  resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
    +
     lodash.isplainobject@^4.0.6:
       version "4.0.6"
       resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
    @@ -4102,6 +4433,10 @@ lodash.memoize@^4.1.2:
       version "4.1.2"
       resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
     
    +lodash.merge@^4.6.0:
    +  version "4.6.1"
    +  resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.1.tgz#adc25d9cb99b9391c59624f379fbba60d7111d54"
    +
     lodash.mergewith@^4.6.0:
       version "4.6.1"
       resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz#639057e726c3afbdb3e7d42741caa8d6e4335927"
    @@ -4135,6 +4470,10 @@ lodash@^4.0.0, lodash@^4.0.1, lodash@^4.11.1, lodash@^4.12.0, lodash@^4.14.0, lo
       version "4.17.4"
       resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
     
    +lodash@^4.17.4:
    +  version "4.17.5"
    +  resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
    +
     lodash@~0.9.2:
       version "0.9.2"
       resolved "https://registry.yarnpkg.com/lodash/-/lodash-0.9.2.tgz#8f3499c5245d346d682e5b0d3b40767e09f1a92c"
    @@ -4179,6 +4518,12 @@ macaddress@^0.2.8:
       version "0.2.8"
       resolved "https://registry.yarnpkg.com/macaddress/-/macaddress-0.2.8.tgz#5904dc537c39ec6dbefeae902327135fa8511f12"
     
    +make-dir@^1.0.0:
    +  version "1.2.0"
    +  resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.2.0.tgz#6d6a49eead4aae296c53bbf3a1a008bd6c89469b"
    +  dependencies:
    +    pify "^3.0.0"
    +
     map-obj@^1.0.0, map-obj@^1.0.1:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
    @@ -4245,9 +4590,9 @@ match-at@^0.1.1:
       version "0.1.1"
       resolved "https://registry.yarnpkg.com/match-at/-/match-at-0.1.1.tgz#25d040d291777704d5e6556bbb79230ec2de0540"
     
    -matcher@^0.1.1:
    -  version "0.1.2"
    -  resolved "https://registry.yarnpkg.com/matcher/-/matcher-0.1.2.tgz#ef20cbde64c24c50cc61af5b83ee0b1b8ff00101"
    +matcher@^1.0.0:
    +  version "1.1.0"
    +  resolved "https://registry.yarnpkg.com/matcher/-/matcher-1.1.0.tgz#4ad3a9cb6585186dc95cb8a08c7de936caed17ee"
       dependencies:
         escape-string-regexp "^1.0.4"
     
    @@ -4259,16 +4604,18 @@ math-expression-evaluator@^1.2.14:
       version "1.2.17"
       resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.17.tgz#de819fdbcd84dccd8fae59c6aeb79615b9d266ac"
     
    -max-timeout@^1.0.0:
    -  version "1.0.0"
    -  resolved "https://registry.yarnpkg.com/max-timeout/-/max-timeout-1.0.0.tgz#b68f69a2f99e0b476fd4cb23e2059ca750715e1f"
    -
     md5-hex@^1.2.0, md5-hex@^1.3.0:
       version "1.3.0"
       resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4"
       dependencies:
         md5-o-matic "^0.1.1"
     
    +md5-hex@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33"
    +  dependencies:
    +    md5-o-matic "^0.1.1"
    +
     md5-o-matic@^0.1.1:
       version "0.1.1"
       resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3"
    @@ -4378,6 +4725,10 @@ mime@1.3.4, mime@^1.3.4:
       version "1.3.4"
       resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53"
     
    +mimic-fn@^1.0.0:
    +  version "1.2.0"
    +  resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022"
    +
     min-document@^2.19.0:
       version "2.19.0"
       resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
    @@ -4462,9 +4813,9 @@ ms@2.0.0:
       version "2.0.0"
       resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
     
    -ms@^0.7.1:
    -  version "0.7.3"
    -  resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff"
    +ms@^2.0.0:
    +  version "2.1.1"
    +  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
     
     multimatch@^2.1.0:
       version "2.1.0"
    @@ -4626,11 +4977,11 @@ normalize-url@^1.4.0:
         query-string "^4.1.0"
         sort-keys "^1.0.0"
     
    -not-so-shallow@^0.1.3:
    -  version "0.1.4"
    -  resolved "https://registry.yarnpkg.com/not-so-shallow/-/not-so-shallow-0.1.4.tgz#e8c7f7b9c9b9f069594344368330cbcea387c3c7"
    +npm-run-path@^2.0.0:
    +  version "2.0.2"
    +  resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
       dependencies:
    -    buffer-equals "^1.0.3"
    +    path-key "^2.0.0"
     
     npmlog@^4.0.2:
       version "4.1.0"
    @@ -4708,12 +5059,12 @@ object.omit@^2.0.0:
         for-own "^0.1.4"
         is-extendable "^0.1.1"
     
    -observable-to-promise@^0.4.0:
    -  version "0.4.0"
    -  resolved "https://registry.yarnpkg.com/observable-to-promise/-/observable-to-promise-0.4.0.tgz#28afe71645308f2d41d71f47ad3fece1a377e52b"
    +observable-to-promise@^0.5.0:
    +  version "0.5.0"
    +  resolved "https://registry.yarnpkg.com/observable-to-promise/-/observable-to-promise-0.5.0.tgz#c828f0f0dc47e9f86af8a4977c5d55076ce7a91f"
       dependencies:
         is-observable "^0.2.0"
    -    symbol-observable "^0.2.2"
    +    symbol-observable "^1.0.4"
     
     on-finished@~2.3.0:
       version "2.3.0"
    @@ -4735,6 +5086,12 @@ onetime@^1.0.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
     
    +onetime@^2.0.0:
    +  version "2.0.1"
    +  resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4"
    +  dependencies:
    +    mimic-fn "^1.0.0"
    +
     open@0.0.5:
       version "0.0.5"
       resolved "https://registry.yarnpkg.com/open/-/open-0.0.5.tgz#42c3e18ec95466b6bf0dc42f3a2945c3f0cad8fc"
    @@ -4752,11 +5109,9 @@ optimist@~0.6.0, optimist@~0.6.1:
         minimist "~0.0.1"
         wordwrap "~0.0.2"
     
    -option-chain@^0.1.0:
    -  version "0.1.1"
    -  resolved "https://registry.yarnpkg.com/option-chain/-/option-chain-0.1.1.tgz#e9b811e006f1c0f54802f28295bfc8970f8dcfbd"
    -  dependencies:
    -    object-assign "^4.0.1"
    +option-chain@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/option-chain/-/option-chain-1.0.0.tgz#938d73bd4e1783f948d34023644ada23669e30f2"
     
     optionator@^0.8.1, optionator@^0.8.2:
       version "0.8.2"
    @@ -4793,13 +5148,17 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1:
       version "1.0.2"
       resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
     
    -osenv@^0.1.0, osenv@^0.1.4:
    +osenv@^0.1.4:
       version "0.1.4"
       resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
       dependencies:
         os-homedir "^1.0.0"
         os-tmpdir "^1.0.0"
     
    +p-finally@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
    +
     p-limit@^1.1.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc"
    @@ -4810,17 +5169,26 @@ p-locate@^2.0.0:
       dependencies:
         p-limit "^1.1.0"
     
    -package-hash@^1.1.0:
    +package-hash@^1.2.0:
       version "1.2.0"
       resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-1.2.0.tgz#003e56cd57b736a6ed6114cc2b81542672770e44"
       dependencies:
         md5-hex "^1.3.0"
     
    -package-json@^2.0.0:
    -  version "2.4.0"
    -  resolved "https://registry.yarnpkg.com/package-json/-/package-json-2.4.0.tgz#0d15bd67d1cbbddbb2ca222ff2edb86bcb31a8bb"
    +package-hash@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-2.0.0.tgz#78ae326c89e05a4d813b68601977af05c00d2a0d"
       dependencies:
    -    got "^5.0.0"
    +    graceful-fs "^4.1.11"
    +    lodash.flattendeep "^4.4.0"
    +    md5-hex "^2.0.0"
    +    release-zalgo "^1.0.0"
    +
    +package-json@^4.0.0:
    +  version "4.0.1"
    +  resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed"
    +  dependencies:
    +    got "^6.7.1"
         registry-auth-token "^3.0.1"
         registry-url "^3.0.3"
         semver "^5.1.0"
    @@ -4844,6 +5212,13 @@ parse-json@^2.1.0, parse-json@^2.2.0:
       dependencies:
         error-ex "^1.2.0"
     
    +parse-json@^4.0.0:
    +  version "4.0.0"
    +  resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0"
    +  dependencies:
    +    error-ex "^1.3.1"
    +    json-parse-better-errors "^1.0.1"
    +
     parse-ms@^0.1.0:
       version "0.1.2"
       resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-0.1.2.tgz#dd3fa25ed6c2efc7bdde12ad9b46c163aa29224e"
    @@ -4878,7 +5253,7 @@ path-exists@^3.0.0:
       version "3.0.0"
       resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
     
    -path-is-absolute@^1.0.0:
    +path-is-absolute@^1.0.0, path-is-absolute@^1.0.1:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
     
    @@ -4886,6 +5261,10 @@ path-is-inside@^1.0.1:
       version "1.0.2"
       resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53"
     
    +path-key@^2.0.0:
    +  version "2.0.1"
    +  resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40"
    +
     path-parse@^1.0.5:
       version "1.0.5"
       resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1"
    @@ -4902,6 +5281,12 @@ path-type@^1.0.0:
         pify "^2.0.0"
         pinkie-promise "^2.0.0"
     
    +path-type@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73"
    +  dependencies:
    +    pify "^2.0.0"
    +
     pbkdf2-compat@2.0.1:
       version "2.0.1"
       resolved "https://registry.yarnpkg.com/pbkdf2-compat/-/pbkdf2-compat-2.0.1.tgz#b6e0c8fa99494d94e0511575802a59a5c142f288"
    @@ -4918,6 +5303,10 @@ pify@^2.0.0:
       version "2.3.0"
       resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
     
    +pify@^3.0.0:
    +  version "3.0.0"
    +  resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
    +
     pinkie-promise@^1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-1.0.0.tgz#d1da67f5482563bb7cf57f286ae2822ecfbf3670"
    @@ -4938,14 +5327,12 @@ pinkie@^2.0.0:
       version "2.0.4"
       resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
     
    -pkg-conf@^1.0.1:
    -  version "1.1.3"
    -  resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-1.1.3.tgz#378e56d6fd13e88bfb6f4a25df7a83faabddba5b"
    +pkg-conf@^2.0.0:
    +  version "2.1.0"
    +  resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-2.1.0.tgz#2126514ca6f2abfebd168596df18ba57867f0058"
       dependencies:
    -    find-up "^1.0.0"
    -    load-json-file "^1.1.0"
    -    object-assign "^4.0.1"
    -    symbol "^0.2.1"
    +    find-up "^2.0.0"
    +    load-json-file "^4.0.0"
     
     pkg-config@^1.0.1, pkg-config@^1.1.0:
       version "1.1.1"
    @@ -4961,6 +5348,12 @@ pkg-dir@^1.0.0:
       dependencies:
         find-up "^1.0.0"
     
    +pkg-dir@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b"
    +  dependencies:
    +    find-up "^2.1.0"
    +
     pkg-up@^1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26"
    @@ -4976,11 +5369,7 @@ plist@^1.1.0:
         xmlbuilder "4.0.0"
         xmldom "0.1.x"
     
    -plur@^1.0.0:
    -  version "1.0.0"
    -  resolved "https://registry.yarnpkg.com/plur/-/plur-1.0.0.tgz#db85c6814f5e5e5a3b49efc28d604fec62975156"
    -
    -plur@^2.0.0:
    +plur@^2.0.0, plur@^2.1.2:
       version "2.1.2"
       resolved "https://registry.yarnpkg.com/plur/-/plur-2.1.2.tgz#7482452c1a0f508e3e344eaec312c91c29dc655a"
       dependencies:
    @@ -5229,53 +5618,6 @@ postcss@^6.0.14:
         source-map "^0.6.1"
         supports-color "^5.2.0"
     
    -power-assert-context-formatter@^1.0.4:
    -  version "1.1.1"
    -  resolved "https://registry.yarnpkg.com/power-assert-context-formatter/-/power-assert-context-formatter-1.1.1.tgz#edba352d3ed8a603114d667265acce60d689ccdf"
    -  dependencies:
    -    core-js "^2.0.0"
    -    power-assert-context-traversal "^1.1.1"
    -
    -power-assert-context-traversal@^1.1.1:
    -  version "1.1.1"
    -  resolved "https://registry.yarnpkg.com/power-assert-context-traversal/-/power-assert-context-traversal-1.1.1.tgz#88cabca0d13b6359f07d3d3e8afa699264577ed9"
    -  dependencies:
    -    core-js "^2.0.0"
    -    estraverse "^4.1.0"
    -
    -power-assert-renderer-assertion@^1.0.1:
    -  version "1.1.1"
    -  resolved "https://registry.yarnpkg.com/power-assert-renderer-assertion/-/power-assert-renderer-assertion-1.1.1.tgz#cbfc0e77e0086a8f96af3f1d8e67b9ee7e28ce98"
    -  dependencies:
    -    power-assert-renderer-base "^1.1.1"
    -    power-assert-util-string-width "^1.1.1"
    -
    -power-assert-renderer-base@^1.1.1:
    -  version "1.1.1"
    -  resolved "https://registry.yarnpkg.com/power-assert-renderer-base/-/power-assert-renderer-base-1.1.1.tgz#96a650c6fd05ee1bc1f66b54ad61442c8b3f63eb"
    -
    -power-assert-renderer-diagram@^1.1.1:
    -  version "1.1.2"
    -  resolved "https://registry.yarnpkg.com/power-assert-renderer-diagram/-/power-assert-renderer-diagram-1.1.2.tgz#655f8f711935a9b6d541b86327654717c637a986"
    -  dependencies:
    -    core-js "^2.0.0"
    -    power-assert-renderer-base "^1.1.1"
    -    power-assert-util-string-width "^1.1.1"
    -    stringifier "^1.3.0"
    -
    -power-assert-renderer-succinct@^1.0.1:
    -  version "1.1.1"
    -  resolved "https://registry.yarnpkg.com/power-assert-renderer-succinct/-/power-assert-renderer-succinct-1.1.1.tgz#c2a468b23822abd6f80e2aba5322347b09df476e"
    -  dependencies:
    -    core-js "^2.0.0"
    -    power-assert-renderer-diagram "^1.1.1"
    -
    -power-assert-util-string-width@^1.1.1:
    -  version "1.1.1"
    -  resolved "https://registry.yarnpkg.com/power-assert-util-string-width/-/power-assert-util-string-width-1.1.1.tgz#be659eb7937fdd2e6c9a77268daaf64bd5b7c592"
    -  dependencies:
    -    eastasianwidth "^0.1.1"
    -
     prelude-ls@~1.1.2:
       version "1.1.2"
       resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
    @@ -5301,18 +5643,21 @@ pretty-ms@^0.2.1:
       dependencies:
         parse-ms "^0.1.0"
     
    -pretty-ms@^2.0.0:
    -  version "2.1.0"
    -  resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-2.1.0.tgz#4257c256df3fb0b451d6affaab021884126981dc"
    +pretty-ms@^3.0.0:
    +  version "3.1.0"
    +  resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-3.1.0.tgz#e9cac9c76bf6ee52fe942dd9c6c4213153b12881"
       dependencies:
    -    is-finite "^1.0.1"
         parse-ms "^1.0.0"
    -    plur "^1.0.0"
    +    plur "^2.1.2"
     
     private@^0.1.6:
       version "0.1.7"
       resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"
     
    +private@^0.1.7:
    +  version "0.1.8"
    +  resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"
    +
     process-nextick-args@~1.0.6:
       version "1.0.7"
       resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3"
    @@ -5589,6 +5934,13 @@ read-pkg-up@^1.0.1:
         find-up "^1.0.0"
         read-pkg "^1.0.0"
     
    +read-pkg-up@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be"
    +  dependencies:
    +    find-up "^2.0.0"
    +    read-pkg "^2.0.0"
    +
     read-pkg@^1.0.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28"
    @@ -5597,6 +5949,14 @@ read-pkg@^1.0.0:
         normalize-package-data "^2.3.2"
         path-type "^1.0.0"
     
    +read-pkg@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8"
    +  dependencies:
    +    load-json-file "^2.0.0"
    +    normalize-package-data "^2.3.2"
    +    path-type "^2.0.0"
    +
     readable-stream@1.0.27-1:
       version "1.0.27-1"
       resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.27-1.tgz#6b67983c20357cefd07f0165001a16d710d91078"
    @@ -5755,6 +6115,12 @@ regjsparser@^0.1.4:
       dependencies:
         jsesc "~0.5.0"
     
    +release-zalgo@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730"
    +  dependencies:
    +    es6-error "^4.0.1"
    +
     remove-trailing-separator@^1.0.1:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz#615ebb96af559552d4bf4057c8436d486ab63cc4"
    @@ -5846,19 +6212,19 @@ requires-port@1.0.x, requires-port@1.x.x:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
     
    -resolve-cwd@^1.0.0:
    -  version "1.0.0"
    -  resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-1.0.0.tgz#4eaeea41ed040d1702457df64a42b2b07d246f9f"
    +resolve-cwd@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"
       dependencies:
    -    resolve-from "^2.0.0"
    +    resolve-from "^3.0.0"
     
     resolve-from@^1.0.0:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
     
    -resolve-from@^2.0.0:
    -  version "2.0.0"
    -  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57"
    +resolve-from@^3.0.0:
    +  version "3.0.0"
    +  resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748"
     
     resolve@^1.1.6:
       version "1.3.3"
    @@ -5873,6 +6239,13 @@ restore-cursor@^1.0.1:
         exit-hook "^1.0.0"
         onetime "^1.0.0"
     
    +restore-cursor@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
    +  dependencies:
    +    onetime "^2.0.0"
    +    signal-exit "^3.0.2"
    +
     right-align@^0.1.1:
       version "0.1.3"
       resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
    @@ -5925,6 +6298,10 @@ safe-buffer@^5.0.1:
       version "5.0.1"
       resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
     
    +safe-buffer@^5.1.1:
    +  version "5.1.1"
    +  resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
    +
     sander@^0.5.1:
       version "0.5.1"
       resolved "https://registry.yarnpkg.com/sander/-/sander-0.5.1.tgz#741e245e231f07cafb6fdf0f133adfa216a502ad"
    @@ -5967,6 +6344,10 @@ semver-diff@^2.0.0:
       version "5.3.0"
       resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
     
    +semver@^5.4.1:
    +  version "5.5.0"
    +  resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
    +
     send@0.15.3:
       version "0.15.3"
       resolved "https://registry.yarnpkg.com/send/-/send-0.15.3.tgz#5013f9f99023df50d1bd9892c19e3defd1d53309"
    @@ -5985,6 +6366,10 @@ send@0.15.3:
         range-parser "~1.2.0"
         statuses "~1.3.1"
     
    +serialize-error@^2.1.0:
    +  version "2.1.0"
    +  resolved "https://registry.yarnpkg.com/serialize-error/-/serialize-error-2.1.0.tgz#50b679d5635cdf84667bdc8e59af4e5b81d5f60a"
    +
     serve-index@^1.7.2:
       version "1.9.0"
       resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.0.tgz#d2b280fc560d616ee81b48bf0fa82abed2485ce7"
    @@ -6026,6 +6411,16 @@ sha.js@2.2.6:
       version "2.2.6"
       resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.2.6.tgz#17ddeddc5f722fb66501658895461977867315ba"
     
    +shebang-command@^1.2.0:
    +  version "1.2.0"
    +  resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
    +  dependencies:
    +    shebang-regex "^1.0.0"
    +
    +shebang-regex@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
    +
     shelljs@^0.7.5:
       version "0.7.7"
       resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1"
    @@ -6038,7 +6433,7 @@ sigmund@~1.0.0:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590"
     
    -signal-exit@^3.0.0:
    +signal-exit@^3.0.0, signal-exit@^3.0.2:
       version "3.0.2"
       resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
     
    @@ -6060,6 +6455,12 @@ slice-ansi@0.0.4:
       version "0.0.4"
       resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
     
    +slice-ansi@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d"
    +  dependencies:
    +    is-fullwidth-code-point "^2.0.0"
    +
     slide@^1.1.5:
       version "1.1.6"
       resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707"
    @@ -6088,22 +6489,40 @@ sockjs@^0.3.15:
         faye-websocket "^0.10.0"
         uuid "^2.0.2"
     
    -sort-keys@^1.0.0, sort-keys@^1.1.1:
    +sort-keys@^1.0.0:
       version "1.1.2"
       resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad"
       dependencies:
         is-plain-obj "^1.0.0"
     
    +sort-keys@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128"
    +  dependencies:
    +    is-plain-obj "^1.0.0"
    +
     source-list-map@^0.1.4, source-list-map@~0.1.7:
       version "0.1.8"
       resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
     
    -source-map-support@^0.4.0, source-map-support@^0.4.2:
    +source-map-support@^0.4.15:
    +  version "0.4.18"
    +  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f"
    +  dependencies:
    +    source-map "^0.5.6"
    +
    +source-map-support@^0.4.2:
       version "0.4.15"
       resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1"
       dependencies:
         source-map "^0.5.6"
     
    +source-map-support@^0.5.0:
    +  version "0.5.3"
    +  resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.3.tgz#2b3d5fff298cfa4d1afd7d4352d569e9a0158e76"
    +  dependencies:
    +    source-map "^0.6.0"
    +
     source-map@0.1.x:
       version "0.1.43"
       resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346"
    @@ -6114,7 +6533,11 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1:
       version "0.5.6"
       resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
     
    -source-map@^0.6.1:
    +source-map@^0.5.7:
    +  version "0.5.7"
    +  resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
    +
    +source-map@^0.6.0, source-map@^0.6.1:
       version "0.6.1"
       resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
     
    @@ -6178,9 +6601,9 @@ sshpk@^1.7.0:
         jsbn "~0.1.0"
         tweetnacl "~0.14.0"
     
    -stack-utils@^0.4.0:
    -  version "0.4.0"
    -  resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-0.4.0.tgz#940cb82fccfa84e8ff2f3fdf293fe78016beccd1"
    +stack-utils@^1.0.1:
    +  version "1.0.1"
    +  resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620"
     
     stackframe@^0.3.1:
       version "0.3.1"
    @@ -6253,6 +6676,13 @@ string-width@^2.0.0:
         is-fullwidth-code-point "^2.0.0"
         strip-ansi "^3.0.0"
     
    +string-width@^2.1.1:
    +  version "2.1.1"
    +  resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
    +  dependencies:
    +    is-fullwidth-code-point "^2.0.0"
    +    strip-ansi "^4.0.0"
    +
     string@^3.0.1:
       version "3.3.3"
       resolved "https://registry.yarnpkg.com/string/-/string-3.3.3.tgz#5ea211cd92d228e184294990a6cc97b366a77cb0"
    @@ -6267,14 +6697,6 @@ string_decoder@~1.0.0:
       dependencies:
         safe-buffer "^5.0.1"
     
    -stringifier@^1.3.0:
    -  version "1.3.0"
    -  resolved "https://registry.yarnpkg.com/stringifier/-/stringifier-1.3.0.tgz#def18342f6933db0f2dbfc9aa02175b448c17959"
    -  dependencies:
    -    core-js "^2.0.0"
    -    traverse "^0.6.6"
    -    type-name "^2.0.1"
    -
     stringstream@~0.0.4:
       version "0.0.5"
       resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
    @@ -6291,10 +6713,22 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1:
       dependencies:
         ansi-regex "^2.0.0"
     
    +strip-ansi@^4.0.0:
    +  version "4.0.0"
    +  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
    +  dependencies:
    +    ansi-regex "^3.0.0"
    +
     strip-ansi@~0.1.0:
       version "0.1.1"
       resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991"
     
    +strip-bom-buf@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz#1cb45aaf57530f4caf86c7f75179d2c9a51dd572"
    +  dependencies:
    +    is-utf8 "^0.2.1"
    +
     strip-bom@^2.0.0:
       version "2.0.0"
       resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e"
    @@ -6305,6 +6739,10 @@ strip-bom@^3.0.0:
       version "3.0.0"
       resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
     
    +strip-eof@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
    +
     strip-indent@^1.0.1:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2"
    @@ -6386,6 +6824,16 @@ superagent@^1.2.0:
         readable-stream "1.0.27-1"
         reduce-component "1.0.1"
     
    +supertap@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/supertap/-/supertap-1.0.0.tgz#bd9751c7fafd68c68cf8222a29892206a119fa9e"
    +  dependencies:
    +    arrify "^1.0.1"
    +    indent-string "^3.2.0"
    +    js-yaml "^3.10.0"
    +    serialize-error "^2.1.0"
    +    strip-ansi "^4.0.0"
    +
     supports-color@^0.2.0:
       version "0.2.0"
       resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a"
    @@ -6400,7 +6848,7 @@ supports-color@^3.1.0, supports-color@^3.1.1, supports-color@^3.2.3:
       dependencies:
         has-flag "^1.0.0"
     
    -supports-color@^5.2.0, supports-color@^5.3.0:
    +supports-color@^5.0.0, supports-color@^5.2.0, supports-color@^5.3.0:
       version "5.3.0"
       resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0"
       dependencies:
    @@ -6426,14 +6874,14 @@ symbol-observable@^1.0.2:
       version "1.0.4"
       resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d"
     
    +symbol-observable@^1.0.4, symbol-observable@^1.1.0:
    +  version "1.2.0"
    +  resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804"
    +
     symbol-tree@^3.2.1:
       version "3.2.2"
       resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6"
     
    -symbol@^0.2.1:
    -  version "0.2.3"
    -  resolved "https://registry.yarnpkg.com/symbol/-/symbol-0.2.3.tgz#3b9873b8a901e47c6efe21526a3ac372ef28bbc7"
    -
     table@^3.7.8:
       version "3.8.3"
       resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f"
    @@ -6477,14 +6925,16 @@ temp@^0.8.3:
         os-tmpdir "^1.0.0"
         rimraf "~2.2.6"
     
    +term-size@^1.2.0:
    +  version "1.2.0"
    +  resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69"
    +  dependencies:
    +    execa "^0.7.0"
    +
     text-table@^0.2.0, text-table@~0.2.0:
       version "0.2.0"
       resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
     
    -the-argv@^1.0.0:
    -  version "1.0.0"
    -  resolved "https://registry.yarnpkg.com/the-argv/-/the-argv-1.0.0.tgz#0084705005730dd84db755253c931ae398db9522"
    -
     throttleit@0.0.2:
       version "0.0.2"
       resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf"
    @@ -6507,19 +6957,18 @@ through@^2.3.6:
       version "2.3.8"
       resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
     
    -time-require@^0.1.2:
    -  version "0.1.2"
    -  resolved "https://registry.yarnpkg.com/time-require/-/time-require-0.1.2.tgz#f9e12cb370fc2605e11404582ba54ef5ca2b2d98"
    -  dependencies:
    -    chalk "^0.4.0"
    -    date-time "^0.1.1"
    -    pretty-ms "^0.2.1"
    -    text-table "^0.2.0"
    +time-zone@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d"
     
     timed-out@^3.0.0:
       version "3.1.3"
       resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-3.1.3.tgz#95860bfcc5c76c277f8f8326fd0f5b2e20eba217"
     
    +timed-out@^4.0.0:
    +  version "4.0.1"
    +  resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f"
    +
     timers-browserify@^2.0.2:
       version "2.0.2"
       resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.2.tgz#ab4883cf597dcd50af211349a00fbca56ac86b86"
    @@ -6540,7 +6989,7 @@ to-arraybuffer@^1.0.0:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43"
     
    -to-fast-properties@^1.0.1:
    +to-fast-properties@^1.0.1, to-fast-properties@^1.0.3:
       version "1.0.3"
       resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
     
    @@ -6568,10 +7017,6 @@ tr46@~0.0.3:
       version "0.3.9"
       resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9"
     
    -traverse@^0.6.6:
    -  version "0.6.6"
    -  resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
    -
     tree-kill@^1.1.0:
       version "1.1.0"
       resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.1.0.tgz#c963dcf03722892ec59cba569e940b71954d1729"
    @@ -6580,6 +7025,10 @@ trim-newlines@^1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"
     
    +trim-off-newlines@^1.0.1:
    +  version "1.0.1"
    +  resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3"
    +
     trim-right@^1.0.1:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003"
    @@ -6619,10 +7068,6 @@ type-is@~1.6.15:
         media-typer "0.3.0"
         mime-types "~2.1.15"
     
    -type-name@^2.0.1:
    -  version "2.0.2"
    -  resolved "https://registry.yarnpkg.com/type-name/-/type-name-2.0.2.tgz#efe7d4123d8ac52afff7f40c7e4dec5266008fb4"
    -
     typedarray@^0.0.6:
       version "0.0.6"
       resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
    @@ -6704,6 +7149,12 @@ uniqs@^2.0.0:
       version "2.0.0"
       resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02"
     
    +unique-string@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a"
    +  dependencies:
    +    crypto-random-string "^1.0.0"
    +
     unique-temp-dir@^1.0.0:
       version "1.0.0"
       resolved "https://registry.yarnpkg.com/unique-temp-dir/-/unique-temp-dir-1.0.0.tgz#6dce95b2681ca003eebfb304a415f9cbabcc5385"
    @@ -6720,18 +7171,23 @@ unzip-response@^1.0.2:
       version "1.0.2"
       resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe"
     
    -update-notifier@^1.0.0:
    -  version "1.0.3"
    -  resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-1.0.3.tgz#8f92c515482bd6831b7c93013e70f87552c7cf5a"
    +unzip-response@^2.0.1:
    +  version "2.0.1"
    +  resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97"
    +
    +update-notifier@^2.3.0:
    +  version "2.3.0"
    +  resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.3.0.tgz#4e8827a6bb915140ab093559d7014e3ebb837451"
       dependencies:
    -    boxen "^0.6.0"
    -    chalk "^1.0.0"
    -    configstore "^2.0.0"
    +    boxen "^1.2.1"
    +    chalk "^2.0.1"
    +    configstore "^3.0.0"
    +    import-lazy "^2.1.0"
    +    is-installed-globally "^0.1.0"
         is-npm "^1.0.0"
    -    latest-version "^2.0.0"
    -    lazy-req "^1.1.0"
    +    latest-version "^3.0.0"
         semver-diff "^2.0.0"
    -    xdg-basedir "^2.0.0"
    +    xdg-basedir "^3.0.0"
     
     url-parse-lax@^1.0.0:
       version "1.0.0"
    @@ -6791,7 +7247,7 @@ uuid@3.0.1, uuid@^3.0.0:
       version "3.0.1"
       resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
     
    -uuid@^2.0.1, uuid@^2.0.2:
    +uuid@^2.0.2:
       version "2.0.3"
       resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
     
    @@ -6918,6 +7374,10 @@ websocket-extensions@>=0.1.1:
       version "0.1.1"
       resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.1.tgz#76899499c184b6ef754377c2dbb0cd6cb55d29e7"
     
    +well-known-symbols@^1.0.0:
    +  version "1.0.0"
    +  resolved "https://registry.yarnpkg.com/well-known-symbols/-/well-known-symbols-1.0.0.tgz#73c78ae81a7726a8fa598e2880801c8b16225518"
    +
     whatwg-encoding@^1.0.1:
       version "1.0.1"
       resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.1.tgz#3c6c451a198ee7aec55b1ec61d0920c67801a5f4"
    @@ -6963,11 +7423,11 @@ wide-align@^1.1.0:
       dependencies:
         string-width "^1.0.2"
     
    -widest-line@^1.0.0:
    -  version "1.0.0"
    -  resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-1.0.0.tgz#0c09c85c2a94683d0d7eaf8ee097d564bf0e105c"
    +widest-line@^2.0.0:
    +  version "2.0.0"
    +  resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.0.tgz#0142a4e8a243f8882c0233aa0e0281aa76152273"
       dependencies:
    -    string-width "^1.0.1"
    +    string-width "^2.1.1"
     
     window-size@0.1.0:
       version "0.1.0"
    @@ -7004,7 +7464,7 @@ wrappy@1:
       version "1.0.2"
       resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
     
    -write-file-atomic@^1.1.2, write-file-atomic@^1.1.4:
    +write-file-atomic@^1.1.4:
       version "1.3.4"
       resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
       dependencies:
    @@ -7012,23 +7472,31 @@ write-file-atomic@^1.1.2, write-file-atomic@^1.1.4:
         imurmurhash "^0.1.4"
         slide "^1.1.5"
     
    -write-json-file@^1.1.0:
    -  version "1.2.0"
    -  resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-1.2.0.tgz#2d5dfe96abc3c889057c93971aa4005efb548134"
    +write-file-atomic@^2.0.0:
    +  version "2.3.0"
    +  resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.3.0.tgz#1ff61575c2e2a4e8e510d6fa4e243cce183999ab"
       dependencies:
    -    graceful-fs "^4.1.2"
    -    mkdirp "^0.5.1"
    -    object-assign "^4.0.1"
    -    pify "^2.0.0"
    -    pinkie-promise "^2.0.0"
    -    sort-keys "^1.1.1"
    -    write-file-atomic "^1.1.2"
    +    graceful-fs "^4.1.11"
    +    imurmurhash "^0.1.4"
    +    signal-exit "^3.0.2"
     
    -write-pkg@^1.0.0:
    -  version "1.0.0"
    -  resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-1.0.0.tgz#aeb8aa9d4d788e1d893dfb0854968b543a919f57"
    +write-json-file@^2.2.0:
    +  version "2.3.0"
    +  resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f"
       dependencies:
    -    write-json-file "^1.1.0"
    +    detect-indent "^5.0.0"
    +    graceful-fs "^4.1.2"
    +    make-dir "^1.0.0"
    +    pify "^3.0.0"
    +    sort-keys "^2.0.0"
    +    write-file-atomic "^2.0.0"
    +
    +write-pkg@^3.1.0:
    +  version "3.1.0"
    +  resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-3.1.0.tgz#030a9994cc9993d25b4e75a9f1a1923607291ce9"
    +  dependencies:
    +    sort-keys "^2.0.0"
    +    write-json-file "^2.2.0"
     
     write@^0.2.1:
       version "0.2.1"
    @@ -7036,11 +7504,9 @@ write@^0.2.1:
       dependencies:
         mkdirp "^0.5.1"
     
    -xdg-basedir@^2.0.0:
    -  version "2.0.0"
    -  resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-2.0.0.tgz#edbc903cc385fc04523d966a335504b5504d1bd2"
    -  dependencies:
    -    os-homedir "^1.0.0"
    +xdg-basedir@^3.0.0:
    +  version "3.0.0"
    +  resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"
     
     xml-name-validator@^2.0.1:
       version "2.0.1"
    
    From bbcd674516aeeaf1ceaf205c478c56ea1f450b6b Mon Sep 17 00:00:00 2001
    From: Yu-Hung Ou 
    Date: Sun, 11 Mar 2018 23:17:14 +1100
    Subject: [PATCH 61/75] updated lib/consts to access electron remote.app only
     when in production mode
    
    ---
     browser/lib/consts.js | 3 +--
     1 file changed, 1 insertion(+), 2 deletions(-)
    
    diff --git a/browser/lib/consts.js b/browser/lib/consts.js
    index c6b2ea5b..23519916 100644
    --- a/browser/lib/consts.js
    +++ b/browser/lib/consts.js
    @@ -1,10 +1,9 @@
     const path = require('path')
     const fs = require('sander')
     const { remote } = require('electron')
    -const { app } = remote
     
     const themePath = process.env.NODE_ENV === 'production'
    -  ? path.join(app.getAppPath(), './node_modules/codemirror/theme')
    +  ? path.join(remote.app.getAppPath(), './node_modules/codemirror/theme')
       : require('path').resolve('./node_modules/codemirror/theme')
     const themes = fs.readdirSync(themePath)
       .map((themePath) => {
    
    From 1af374439d66dfcddfe74c6e8008ea8410e0974b Mon Sep 17 00:00:00 2001
    From: Yu-Hung Ou 
    Date: Sun, 11 Mar 2018 23:18:35 +1100
    Subject: [PATCH 62/75] added unit tests for lib/markdown
    
    ---
     tests/fixtures/markdowns.js               |  48 +++++++++++++++++++
     tests/lib/markdown-test.js                |  22 +++++++++
     tests/lib/snapshots/markdown-test.js.md   |  54 ++++++++++++++++++++++
     tests/lib/snapshots/markdown-test.js.snap | Bin 0 -> 1486 bytes
     4 files changed, 124 insertions(+)
     create mode 100644 tests/fixtures/markdowns.js
     create mode 100644 tests/lib/markdown-test.js
     create mode 100644 tests/lib/snapshots/markdown-test.js.md
     create mode 100644 tests/lib/snapshots/markdown-test.js.snap
    
    diff --git a/tests/fixtures/markdowns.js b/tests/fixtures/markdowns.js
    new file mode 100644
    index 00000000..3b535539
    --- /dev/null
    +++ b/tests/fixtures/markdowns.js
    @@ -0,0 +1,48 @@
    +const basic = `
    +# Welcome to Boostnote!
    +## Click here to edit markdown :wave:
    +
    +
    +
    +## Docs :memo:
    +- [Boostnote | Boost your happiness, productivity and creativity.](https://hackernoon.com/boostnote-boost-your-happiness-productivity-and-creativity-315034efeebe)
    +- [Cloud Syncing & Backups](https://github.com/BoostIO/Boostnote/wiki/Cloud-Syncing-and-Backup)
    +- [How to sync your data across Desktop and Mobile apps](https://github.com/BoostIO/Boostnote/wiki/Sync-Data-Across-Desktop-and-Mobile-apps)
    +- [Convert data from **Evernote** to Boostnote.](https://github.com/BoostIO/Boostnote/wiki/Evernote)
    +- [Keyboard Shortcuts](https://github.com/BoostIO/Boostnote/wiki/Keyboard-Shortcuts)
    +- [Keymaps in Editor mode](https://github.com/BoostIO/Boostnote/wiki/Keymaps-in-Editor-mode)
    +- [How to set syntax highlight in Snippet note](https://github.com/BoostIO/Boostnote/wiki/Syntax-Highlighting)
    +
    +---
    +
    +## Article Archive :books:
    +- [Reddit English](http://bit.ly/2mOJPu7)
    +- [Reddit Spanish](https://www.reddit.com/r/boostnote_es/)
    +- [Reddit Chinese](https://www.reddit.com/r/boostnote_cn/)
    +- [Reddit Japanese](https://www.reddit.com/r/boostnote_jp/)
    +
    +---
    +
    +## Community :beers:
    +- [GitHub](http://bit.ly/2AWWzkD)
    +- [Twitter](http://bit.ly/2z8BUJZ)
    +- [Facebook Group](http://bit.ly/2jcca8t)
    +`
    +
    +const codeblock = `
    +\`\`\`js:filename.js:2
    +var project = 'boostnote';
    +\`\`\`
    +`
    +
    +const katex = `
    +$$
    +c = \pm\sqrt{a^2 + b^2}
    +$$
    +`
    +
    +export default {
    +  basic,
    +  codeblock,
    +  katex
    +}
    diff --git a/tests/lib/markdown-test.js b/tests/lib/markdown-test.js
    new file mode 100644
    index 00000000..5ebe3c09
    --- /dev/null
    +++ b/tests/lib/markdown-test.js
    @@ -0,0 +1,22 @@
    +import test from 'ava'
    +import Markdown from 'browser/lib/markdown'
    +import markdownFixtures from '../fixtures/markdowns'
    +
    +// basic markdown instance which meant to be used in every test cases.
    +// To test markdown options, initialize a new instance in your test case
    +const md = new Markdown()
    +
    +test('Markdown.render() should renders markdown correctly', t => {
    +  const rendered = md.render(markdownFixtures.basic)
    +  t.snapshot(rendered)
    +})
    +
    +test('Markdown.render() should renders codeblock correctly', t => {
    +  const rendered = md.render(markdownFixtures.codeblock)
    +  t.snapshot(rendered)
    +})
    +
    +test('Markdown.render() should renders KaTeX correctly', t => {
    +  const rendered = md.render(markdownFixtures.katex)
    +  t.snapshot(rendered)
    +})
    diff --git a/tests/lib/snapshots/markdown-test.js.md b/tests/lib/snapshots/markdown-test.js.md
    new file mode 100644
    index 00000000..5c47d494
    --- /dev/null
    +++ b/tests/lib/snapshots/markdown-test.js.md
    @@ -0,0 +1,54 @@
    +# Snapshot report for `tests/lib/markdown-test.js`
    +
    +The actual snapshot is saved in `markdown-test.js.snap`.
    +
    +Generated by [AVA](https://ava.li).
    +
    +## Markdown.render() should renders KaTeX correctly
    +
    +> Snapshot 1
    +
    +    `c=pmsqrta2+b2c = pmsqrt{a^2 + b^2}␊
    +    `
    +
    +## Markdown.render() should renders codeblock correctly
    +
    +> Snapshot 1
    +
    +    `
    filename.js2var project = 'boostnote';␊
    +    
    ␊ + ` + +## Markdown.render() should renders markdown correctly + +> Snapshot 1 + + `

    Welcome to Boostnote!

    ␊ +

    Click here to edit markdown 👋

    ␊ + ␊ +

    Docs 📝

    ␊ + ␊ +
    ␊ +

    Article Archive 📚

    ␊ + ␊ +
    ␊ +

    Community 🍻

    ␊ + ␊ + ` diff --git a/tests/lib/snapshots/markdown-test.js.snap b/tests/lib/snapshots/markdown-test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..077a20c7b52c978e64937bbbac42e94753d73d2d GIT binary patch literal 1486 zcmV;<1u^2AS8mu_S|}IZI5p}zRe~? zAOtl0L^AMX8n^LFj~`&RbX)^jt4dhQ-JjPT8G-+%GWq3=F;aQD5B&pq|_jHZ5i#4w)y z$^OH>cjwm6AAa=0gU>gP&1mXxPaDP|-+b{2XsLr1wkZf0&}F_1Y_qXYH9>~818JLc zwT6jO;n`*&Ws)viR=3-&^mrySmsY@Ti$*T>t#j4w3zyENJ5levi8P$cg-?ZT0vHKH z-rdZ?F!cnbvD310jSo4vkUO}}y|naXZgy$ibQB3p{_^X>c2Kc{ULsL)66Jg8fwd}Bysq-I;t3A%TBm78@*DQb9kUaUVnEJdQ}XQ%5?gx z$`%x}V%g28VtFBhQ7DGMa640;q$8k13`#84Vy08?;}#!nSs}6o7&}C$8M8$_iEMPd z%>D6`;H6>)NpNh$+gFb4(%m7FUdKL5laTaA?9zMVXmGudK@`H4S^xu$NDM`p0zvRD zyqV**EO@sf?%1&6nwAta=0xQxEmzy+N|Y;Eta8*eOEi@f)L6wRQV}Y)xO1XV)@OAm zuv$4}@gXq;4rVit5se{q(B5nlMiN|?G}XF}btpUtbP}c8Lf$0T>gWV=uhnnC;VQ*d zvIfDh^6-o~9(fo82|+|eFoFZ-`!u#qDKa_|a+p(@giDv~g;1XPMQpiRX)esys*6kI zL!*=CSY28kxm-#fjl$F_)kd>1KY(chjGCO_c!&w~@^~3nE48Kh`T2riDOK@_c{V(EDls+nz;^eAhH`M)Gz}%G>e&_;H?>Q7nB|A1)#m;Es-~Z>I oo&Aw#^4WJ;Y^u)sSd~mULGJ%2=)X8Y(?3W52KDd!mM;+i0M%yK8~^|S literal 0 HcmV?d00001 From b5cb209f1478bd2504260d1a2d1211f1b22d80ff Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Wed, 14 Mar 2018 21:46:20 +1100 Subject: [PATCH 63/75] added browser testing support to ava --- package.json | 4 +- tests/helpers/setup-browser-env.js | 9 + yarn.lock | 349 ++++++++++++++++++++++++++++- 3 files changed, 351 insertions(+), 11 deletions(-) create mode 100644 tests/helpers/setup-browser-env.js diff --git a/package.json b/package.json index c2d56760..32d06176 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "babel-preset-react": "^6.3.13", "babel-preset-react-hmre": "^1.0.1", "babel-register": "^6.11.6", + "browser-env": "^3.2.5", "concurrently": "^3.4.0", "copy-to-clipboard": "^3.0.6", "css-loader": "^0.19.0", @@ -143,7 +144,8 @@ "tests/**/*-test.js" ], "require": [ - "babel-register" + "babel-register", + "./tests/helpers/setup-browser-env.js" ], "babel": "inherit" } diff --git a/tests/helpers/setup-browser-env.js b/tests/helpers/setup-browser-env.js new file mode 100644 index 00000000..d7615c01 --- /dev/null +++ b/tests/helpers/setup-browser-env.js @@ -0,0 +1,9 @@ +import browserEnv from 'browser-env' +browserEnv(['window', 'document']) + +window.localStorage = { + // polyfill + getItem () { + return '{}' + } +} diff --git a/yarn.lock b/yarn.lock index e5019fea..d9644df4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -73,6 +73,10 @@ abab@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.3.tgz#b81de5f7274ec4e756d797cd834f303642724e5d" +abab@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/abab/-/abab-1.0.4.tgz#5faad9c2c07f60dd76770f71cf025b62a63cfd4e" + abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" @@ -94,6 +98,12 @@ acorn-globals@^3.1.0: dependencies: acorn "^4.0.4" +acorn-globals@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.1.0.tgz#ab716025dbe17c54d3ef81d32ece2b2d99fe2538" + dependencies: + acorn "^5.0.0" + acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" @@ -108,6 +118,10 @@ acorn@^4.0.4: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" +acorn@^5.0.0, acorn@^5.3.0: + version "5.5.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" + acorn@^5.0.1: version "5.0.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d" @@ -123,6 +137,15 @@ ajv@^4.7.0, ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +ajv@^5.1.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -340,6 +363,10 @@ async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + async@^0.9.0, async@~0.9.0: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" @@ -507,7 +534,11 @@ aws-sign2@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" -aws4@^1.2.1: +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + +aws4@^1.2.1, aws4@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" @@ -1250,6 +1281,18 @@ boom@2.x.x: dependencies: hoek "2.x.x" +boom@4.x.x: + version "4.3.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-4.3.1.tgz#4f8a3005cb4a7e3889f749030fd25b96e01d2e31" + dependencies: + hoek "4.x.x" + +boom@5.x.x: + version "5.2.0" + resolved "https://registry.yarnpkg.com/boom/-/boom-5.2.0.tgz#5dd9da6ee3a5f302077436290cb717d3f4a54e02" + dependencies: + hoek "4.x.x" + boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" @@ -1277,6 +1320,16 @@ braces@^1.8.2: preserve "^0.2.0" repeat-element "^1.1.2" +browser-env@^3.2.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/browser-env/-/browser-env-3.2.5.tgz#4345b8094413552e1e32c0c7b048b85d90965cc1" + dependencies: + window "4.2.5" + +browser-process-hrtime@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e" + browserify-aes@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-0.4.0.tgz#067149b668df31c4b58533e02d01e806d8608e2c" @@ -1654,6 +1707,12 @@ colors@~0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.2.tgz#2423fe6678ac0c5dae8852e5d0e5be08c997abcc" +combined-stream@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" + dependencies: + delayed-stream "~1.0.0" + combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -1796,6 +1855,10 @@ content-type-parser@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.1.tgz#c3e56988c53c65127fb46d4032a3a900246fdc94" +content-type-parser@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/content-type-parser/-/content-type-parser-1.0.2.tgz#caabe80623e63638b2502fd4c7f12ff4ce2352e7" + content-type@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.2.tgz#b7d113aee7a8dd27bd21133c4dc2529df1721eed" @@ -1885,6 +1948,12 @@ cryptiles@2.x.x: dependencies: boom "2.x.x" +cryptiles@3.x.x: + version "3.1.2" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-3.1.2.tgz#a89fbb220f5ce25ec56e8c4aa8a4fd7b5b0d29fe" + dependencies: + boom "5.x.x" + crypto-browserify@1.0.9: version "1.0.9" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-1.0.9.tgz#cc5449685dfb85eb11c9828acc7cb87ab5bbfcc0" @@ -2233,6 +2302,12 @@ domelementtype@~1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" +domexception@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" + dependencies: + webidl-conversions "^4.0.2" + domhandler@^2.3.0: version "2.4.1" resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.1.tgz#892e47000a99be55bbf3774ffea0561d8879c259" @@ -2563,6 +2638,17 @@ escodegen@^1.6.1: optionalDependencies: source-map "~0.2.0" +escodegen@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.9.1.tgz#dbae17ef96c8e4bedb1356f4504fa4cc2f7cb7e2" + dependencies: + esprima "^3.1.3" + estraverse "^4.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + escope@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" @@ -2710,7 +2796,7 @@ esprima@^2.6.0, esprima@^2.7.1: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" -esprima@^3.1.1: +esprima@^3.1.1, esprima@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" @@ -2867,6 +2953,10 @@ extend@3.0.0, extend@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" +extend@~3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -2890,10 +2980,18 @@ faker@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/faker/-/faker-3.1.0.tgz#0f908faf4e6ec02524e54a57e432c5c013e08c9f" +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + fast-diff@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -3099,6 +3197,14 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" +form-data@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" + dependencies: + asynckit "^0.4.0" + combined-stream "1.0.6" + mime-types "^2.1.12" + formidable@~1.0.14: version "1.0.17" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.0.17.tgz#ef5491490f9433b705faa77249c99029ae348559" @@ -3503,6 +3609,10 @@ har-schema@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + har-validator@^1.4.0: version "1.8.0" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-1.8.0.tgz#d83842b0eb4c435960aeb108a067a3aa94c0eeb2" @@ -3519,6 +3629,13 @@ har-validator@~4.2.1: ajv "^4.9.1" har-schema "^1.0.5" +har-validator@~5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd" + dependencies: + ajv "^5.1.0" + har-schema "^2.0.0" + has-ansi@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-0.1.0.tgz#84f265aae8c0e6a88a12d7022894b7568894c62e" @@ -3579,6 +3696,15 @@ hawk@~3.1.3: hoek "2.x.x" sntp "1.x.x" +hawk@~6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-6.0.2.tgz#af4d914eb065f9b5ce4d9d11c1cb2126eecc3038" + dependencies: + boom "4.x.x" + cryptiles "3.x.x" + hoek "4.x.x" + sntp "2.x.x" + highlight.js@^9.3.0: version "9.11.0" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.11.0.tgz#47f98c7399918700db2caf230ded12cec41a84ae" @@ -3605,6 +3731,10 @@ hoek@2.x.x: version "2.16.3" resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" +hoek@4.x.x: + version "4.2.1" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-4.2.1.tgz#9634502aa12c445dd5a7c5734b572bb8738aacbb" + hoist-non-react-statics@^1.0.3, hoist-non-react-statics@^1.0.5, hoist-non-react-statics@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz#aa448cf0986d55cc40773b17174b7dd066cb7cfb" @@ -3638,6 +3768,12 @@ html-encoding-sniffer@^1.0.1: dependencies: whatwg-encoding "^1.0.1" +html-encoding-sniffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" + dependencies: + whatwg-encoding "^1.0.1" + htmlparser2@^3.9.0: version "3.9.2" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338" @@ -3690,6 +3826,14 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + https-browserify@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82" @@ -3721,7 +3865,7 @@ iconv-lite@0.4.13, iconv-lite@~0.4.13: version "0.4.13" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2" -iconv-lite@^0.4.19: +iconv-lite@0.4.19, iconv-lite@^0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" @@ -4179,6 +4323,37 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" +jsdom@11.6.2: + version "11.6.2" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.6.2.tgz#25d1ef332d48adf77fc5221fe2619967923f16bb" + dependencies: + abab "^1.0.4" + acorn "^5.3.0" + acorn-globals "^4.1.0" + array-equal "^1.0.0" + browser-process-hrtime "^0.1.2" + content-type-parser "^1.0.2" + cssom ">= 0.3.2 < 0.4.0" + cssstyle ">= 0.2.37 < 0.3.0" + domexception "^1.0.0" + escodegen "^1.9.0" + html-encoding-sniffer "^1.0.2" + left-pad "^1.2.0" + nwmatcher "^1.4.3" + parse5 "4.0.0" + pn "^1.1.0" + request "^2.83.0" + request-promise-native "^1.0.5" + sax "^1.2.4" + symbol-tree "^3.2.2" + tough-cookie "^2.3.3" + w3c-hr-time "^1.0.1" + webidl-conversions "^4.0.2" + whatwg-encoding "^1.0.3" + whatwg-url "^6.4.0" + ws "^4.0.0" + xml-name-validator "^3.0.0" + jsdom@^9.4.2: version "9.12.0" resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4" @@ -4219,6 +4394,10 @@ json-parse-better-errors@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.1.tgz#50183cd1b2d25275de069e9e71b467ac9eab973a" +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" @@ -4314,6 +4493,10 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" +left-pad@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.2.0.tgz#d30a73c6b8201d8f7d8e7956ba9616087a68e0ee" + levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -4445,6 +4628,10 @@ lodash.some@^4.5.1: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + lodash.template@^4.2.2, lodash.template@^4.3.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" @@ -4470,7 +4657,7 @@ lodash@^4.0.0, lodash@^4.0.1, lodash@^4.11.1, lodash@^4.12.0, lodash@^4.14.0, lo version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -lodash@^4.17.4: +lodash@^4.13.1, lodash@^4.17.4: version "4.17.5" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" @@ -4709,6 +4896,10 @@ mime-db@~1.12.0: version "1.12.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.12.0.tgz#3d0c63180f458eb10d325aaa37d7c58ae312e9d7" +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + mime-types@^2.1.12, mime-types@^2.1.3, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7: version "2.1.15" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed" @@ -4721,6 +4912,12 @@ mime-types@~2.0.1, mime-types@~2.0.3: dependencies: mime-db "~1.12.0" +mime-types@~2.1.17: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + dependencies: + mime-db "~1.33.0" + mime@1.3.4, mime@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" @@ -5028,11 +5225,15 @@ number-is-nan@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.0.tgz#b4389362170e7ef9798c3c7716d80ebc0106fccf" +nwmatcher@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/nwmatcher/-/nwmatcher-1.4.3.tgz#64348e3b3d80f035b40ac11563d278f8b72db89c" + oauth-sign@~0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.6.0.tgz#7dbeae44f6ca454e1f168451d630746735813ce3" -oauth-sign@~0.8.1: +oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" @@ -5227,6 +5428,10 @@ parse-ms@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-1.0.1.tgz#56346d4749d78f23430ca0c713850aef91aa361d" +parse5@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" + parse5@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-1.5.1.tgz#9b7f3b0de32be78dc2401b17573ccaf0f6f59d94" @@ -5299,6 +5504,10 @@ performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -5379,6 +5588,10 @@ pluralize@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" +pn@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" + postcss-calc@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-5.3.1.tgz#77bae7ca928ad85716e2fda42f261bf7c1d65b5e" @@ -5725,6 +5938,10 @@ punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" +punycode@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" + q@^1.1.2: version "1.5.0" resolved "https://registry.yarnpkg.com/q/-/q-1.5.0.tgz#dd01bac9d06d30e6f219aecb8253ee9ebdc308f1" @@ -5741,6 +5958,10 @@ qs@~2.4.0: version "2.4.2" resolved "https://registry.yarnpkg.com/qs/-/qs-2.4.2.tgz#f7ce788e5777df0b5010da7f7c4e73ba32470f5a" +qs@~6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" + query-string@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/query-string/-/query-string-3.0.3.tgz#ae2e14b4d05071d4e9b9eb4873c35b0dcd42e638" @@ -6139,6 +6360,20 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" +request-promise-core@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" + dependencies: + lodash "^4.13.1" + +request-promise-native@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" + dependencies: + request-promise-core "1.1.1" + stealthy-require "^1.1.0" + tough-cookie ">=2.3.3" + request@2.55.0: version "2.55.0" resolved "https://registry.yarnpkg.com/request/-/request-2.55.0.tgz#d75c1cdf679d76bb100f9bffe1fe551b5c24e93d" @@ -6189,6 +6424,33 @@ request@^2.45.0, request@^2.79.0, request@^2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" +request@^2.83.0: + version "2.85.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.85.0.tgz#5a03615a47c61420b3eb99b7dba204f83603e1fa" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.6.0" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.1" + forever-agent "~0.6.1" + form-data "~2.3.1" + har-validator "~5.0.3" + hawk "~6.0.2" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.17" + oauth-sign "~0.8.2" + performance-now "^2.1.0" + qs "~6.5.1" + safe-buffer "^5.1.1" + stringstream "~0.0.5" + tough-cookie "~2.3.3" + tunnel-agent "^0.6.0" + uuid "^3.1.0" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -6298,7 +6560,7 @@ safe-buffer@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" -safe-buffer@^5.1.1: +safe-buffer@^5.1.1, safe-buffer@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" @@ -6334,6 +6596,10 @@ sax@1.2.1, sax@>=0.6.0, sax@^1.2.1, sax@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" @@ -6471,6 +6737,12 @@ sntp@1.x.x: dependencies: hoek "2.x.x" +sntp@2.x.x: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-2.1.0.tgz#2c6cec14fedc2222739caf9b5c3d85d1cc5a2cc8" + dependencies: + hoek "4.x.x" + sockjs-client@^1.0.3: version "1.1.4" resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.1.4.tgz#5babe386b775e4cf14e7520911452654016c8b12" @@ -6537,7 +6809,7 @@ source-map@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" -source-map@^0.6.0, source-map@^0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -6636,6 +6908,10 @@ standard@^8.4.0: version "1.3.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" +stealthy-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + stream-browserify@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.1.tgz#66266ee5f9bdb9940a4e4514cafb43bb71e5c9db" @@ -6697,7 +6973,7 @@ string_decoder@~1.0.0: dependencies: safe-buffer "^5.0.1" -stringstream@~0.0.4: +stringstream@~0.0.4, stringstream@~0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" @@ -6878,7 +7154,7 @@ symbol-observable@^1.0.4, symbol-observable@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" -symbol-tree@^3.2.1: +symbol-tree@^3.2.1, symbol-tree@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" @@ -7009,6 +7285,18 @@ tough-cookie@>=0.12.0, tough-cookie@^2.3.2, tough-cookie@~2.3.0: dependencies: punycode "^1.4.1" +tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.3.3: + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" + dependencies: + punycode "^1.4.1" + +tr46@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + dependencies: + punycode "^2.1.0" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -7251,7 +7539,7 @@ uuid@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" -uuid@^3.2.1: +uuid@^3.1.0, uuid@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" @@ -7282,6 +7570,12 @@ vm-browserify@0.0.4: dependencies: indexof "0.0.1" +w3c-hr-time@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" + dependencies: + browser-process-hrtime "^0.1.2" + warning@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/warning/-/warning-2.1.0.tgz#21220d9c63afc77a8c92111e011af705ce0c6901" @@ -7310,6 +7604,10 @@ webidl-conversions@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.1.tgz#8015a17ab83e7e1b311638486ace81da6ce206a0" +webidl-conversions@^4.0.1, webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + webpack-core@~0.6.9: version "0.6.9" resolved "https://registry.yarnpkg.com/webpack-core/-/webpack-core-0.6.9.tgz#fc571588c8558da77be9efb6debdc5a3b172bdc2" @@ -7384,6 +7682,12 @@ whatwg-encoding@^1.0.1: dependencies: iconv-lite "0.4.13" +whatwg-encoding@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz#57c235bc8657e914d24e1a397d3c82daee0a6ba3" + dependencies: + iconv-lite "0.4.19" + whatwg-fetch@>=0.10.0: version "2.0.3" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" @@ -7395,6 +7699,14 @@ whatwg-url@^4.3.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" +whatwg-url@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.4.0.tgz#08fdf2b9e872783a7a1f6216260a1d66cc722e08" + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.0" + webidl-conversions "^4.0.1" + when@~3.6.x: version "3.6.4" resolved "https://registry.yarnpkg.com/when/-/when-3.6.4.tgz#473b517ec159e2b85005497a13983f095412e34e" @@ -7437,6 +7749,12 @@ window-size@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" +window@4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/window/-/window-4.2.5.tgz#02b5c48daf462481d5dfc6d331fbfa4d27d78ee4" + dependencies: + jsdom "11.6.2" + word-wrap@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.2.tgz#8fa78c3bda3e3138c7797fabceae709968814b41" @@ -7504,6 +7822,13 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" +ws@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" @@ -7512,6 +7837,10 @@ xml-name-validator@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-2.0.1.tgz#4d8b8f1eccd3419aa362061becef515e1e559635" +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + xml2js@0.4.17: version "0.4.17" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.17.tgz#17be93eaae3f3b779359c795b419705a8817e868" From f72b4f0249d9024ed26710f76dbf7eb7ebbc984a Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Wed, 14 Mar 2018 21:47:07 +1100 Subject: [PATCH 64/75] added unit test for checkbox markdown syntax --- tests/fixtures/markdowns.js | 8 +++++++- tests/lib/markdown-test.js | 5 +++++ tests/lib/snapshots/markdown-test.js.md | 12 +++++++++++- tests/lib/snapshots/markdown-test.js.snap | Bin 1486 -> 1581 bytes 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/tests/fixtures/markdowns.js b/tests/fixtures/markdowns.js index 3b535539..d6962514 100644 --- a/tests/fixtures/markdowns.js +++ b/tests/fixtures/markdowns.js @@ -41,8 +41,14 @@ c = \pm\sqrt{a^2 + b^2} $$ ` +const checkboxes = ` +- [ ] Unchecked +- [x] Checked +` + export default { basic, codeblock, - katex + katex, + checkboxes } diff --git a/tests/lib/markdown-test.js b/tests/lib/markdown-test.js index 5ebe3c09..554ea67c 100644 --- a/tests/lib/markdown-test.js +++ b/tests/lib/markdown-test.js @@ -20,3 +20,8 @@ test('Markdown.render() should renders KaTeX correctly', t => { const rendered = md.render(markdownFixtures.katex) t.snapshot(rendered) }) + +test('Markdown.render() should renders checkboxes', t => { + const rendered = md.render(markdownFixtures.checkboxes) + t.snapshot(rendered) +}) diff --git a/tests/lib/snapshots/markdown-test.js.md b/tests/lib/snapshots/markdown-test.js.md index 5c47d494..c678fc2f 100644 --- a/tests/lib/snapshots/markdown-test.js.md +++ b/tests/lib/snapshots/markdown-test.js.md @@ -51,4 +51,14 @@ Generated by [AVA](https://ava.li).
  • Twitter
  • Facebook Group
  • ␊ ␊ - ` + + +## Markdown.render() should renders checkboxes + +> Snapshot 1 + + `
      ␊ +
    • Unchecked
    • ␊ +
    • Checked
    • ␊ +
    ␊ + ` \ No newline at end of file diff --git a/tests/lib/snapshots/markdown-test.js.snap b/tests/lib/snapshots/markdown-test.js.snap index 077a20c7b52c978e64937bbbac42e94753d73d2d..a74d193fe197404b2f7fc89fedd87689430028fa 100644 GIT binary patch literal 1581 zcmV+|2GaRKRzV%)F3bAg}CQS$Xqm;vb6$00000000y1 zR!NN9L=^Qzkur*q*bm$)MnevX+uc1|&!pR8mP{5ViwGeIiJ-DwGp=d7%2O^+PbWkm z1YB4mgp>mkiMVk@AWjIxg)1TwH-wNl!3j>`gv771+r6Y`2}3yHgI)gh|NC40|BD%h zvETT9^zqMc|8Vts<+Gpc^slwYMhx}bJYX2%3!l998#wQt{e^NBm}Egc%s)E^%*jI}>Ue?KUH`Re2Ep8w|H1HT;|(bQWH8^%84 zfJPqKZ#=T^`hj{-K|Yq)3MnHEvtlCZH_S^U^ms%p$*py)e}bW+9|r(+Y^tNW`boim+(;1PuOBJ-x6@kHk7WHM&Fej(VCdkm$KsLkWJ!Y86(0vHZM-dah+F!2N-%&FU%#=9Jx${bweUQ&26 zJ~p#xI*J4)fACRmavH)bq)r{9K#-NLc>(sCL@>^ow$AND)Y2;pEEiUQ;~4ZMi4_a( zr=Fx6RJJY5dcv8Ug}PX!x{bkWuy?r8 zt5gQ5s}0uJr_R}hKD$Mm)LsaA>RT7u%%f~oTRIPprm@N~?4W!HJ%ywA7|QmNJ!@5{ z)}qSKoF_QMYmp>P$zyH68Sc`MSP+23bWZY?I${Y3WPwpxMOaIrTuKKelR`>r&*mN9 zP?=UWw7?mxWu|pS@CeltDL7koIy`kdC-l|X-V^f-X}cT?$W6e7^im1I=+IC>`#01? zI8H3etm9C|Tv!qJiB_fPh%%JXk)r<_iI;fOItfi6RE+?RRyW5)syxF!3Of5r{{=?l z81}Mg7Y5k6R0DzRyUM*Xoz?rCkko^tG$*`(Zjj#6pEI3&7v;OE3w*d;7XSxcDobJ8 zu14ohpHHVv=UL*b-glg>hBOIwh>mJ-LJQ~!iEa;hnIv`rb|J=WPhcMFf-MB9iR_fO zZNS#zF4$=druCz3lZ5JIK2>-WrA#%xJp8rAv3WH^I&=v9yI<}y@N<_gU1>twK0)Ql z)ZNCd9+@k(`HQDtG@a*KR7xUtC$#2yxF$_!341VccoUrvJdFoE@0-p)8}%3lq8H*M zX_y|A3tE8J87c%9rc+NKdY#=B=v53RmFaX=r8OvK#nR8HVtF=&Q7C%AtkqO`k_>?M zFeovm#Z0H#!OcI~vRq^hFgCDIGiHr=5;f4_BKL=nftQLIB*C!(Z=W9R)7`|9Y+61| z;t;n7?9zL~XmGudK@`H4S^xuyFoU8@fFO7a-qi8xHoWT*cN(zbnil6Y>O{pVDOT&n zN)#)ZuQJpmjWreLRHkASsR-p;+&Pjf>#(|8u-X}9{=p0a2eX+oL>Pn)+FQefkp$Nz zO|>^I9SRQu9Y@K!kXP~LDmsGP%hhXexC(KVtZp#uEIdPwM;69FLJ$!a6k7rHeZm^1 z6e$@9In1e4!lg^LLnzPeA~stt)utvY<>{H?A<;2&s4gv!TrMS#24O0t@?>ptq6&hGCMLF2;NoP^<_Io(NO@187QJCYnnR=^DNKT!=qijek^5Jj z?t5xms*ePLqu995N_riNcjSn6dI@pdib+@IV1#?!oea>3rrAlQS_6FlK*~6bJiiZ|qwKTnT z)zK^J{w-kcN(+9-6jJYT6iFpJG+6o0VB_EY=ibi#z_az)cPTSfXT7gVb~r)q|0n3b zI6*sq`mYmT7@fOc#}J8=<}w8Jlq3<@NLdWiN48^d+6#!+bopj>!R-85RTHkE=pxeu f;un{^dqT{G`;o^r@q_ literal 1486 zcmV;<1u^2AS8mu_S|}IZI5p}zRe~? zAOtl0L^AMX8n^LFj~`&RbX)^jt4dhQ-JjPT8G-+%GWq3=F;aQD5B&pq|_jHZ5i#4w)y z$^OH>cjwm6AAa=0gU>gP&1mXxPaDP|-+b{2XsLr1wkZf0&}F_1Y_qXYH9>~818JLc zwT6jO;n`*&Ws)viR=3-&^mrySmsY@Ti$*T>t#j4w3zyENJ5levi8P$cg-?ZT0vHKH z-rdZ?F!cnbvD310jSo4vkUO}}y|naXZgy$ibQB3p{_^X>c2Kc{ULsL)66Jg8fwd}Bysq-I;t3A%TBm78@*DQb9kUaUVnEJdQ}XQ%5?gx z$`%x}V%g28VtFBhQ7DGMa640;q$8k13`#84Vy08?;}#!nSs}6o7&}C$8M8$_iEMPd z%>D6`;H6>)NpNh$+gFb4(%m7FUdKL5laTaA?9zMVXmGudK@`H4S^xu$NDM`p0zvRD zyqV**EO@sf?%1&6nwAta=0xQxEmzy+N|Y;Eta8*eOEi@f)L6wRQV}Y)xO1XV)@OAm zuv$4}@gXq;4rVit5se{q(B5nlMiN|?G}XF}btpUtbP}c8Lf$0T>gWV=uhnnC;VQ*d zvIfDh^6-o~9(fo82|+|eFoFZ-`!u#qDKa_|a+p(@giDv~g;1XPMQpiRX)esys*6kI zL!*=CSY28kxm-#fjl$F_)kd>1KY(chjGCO_c!&w~@^~3nE48Kh`T2riDOK@_c{V(EDls+nz;^eAhH`M)Gz}%G>e&_;H?>Q7nB|A1)#m;Es-~Z>I oo&Aw#^4WJ;Y^u)sSd~mULGJ%2=)X8Y(?3W52KDd!mM;+i0M%yK8~^|S From ccb0302d3f28c5908bdb3619e2cd5e10b960f549 Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 14 Mar 2018 13:13:47 +0100 Subject: [PATCH 65/75] Resolved Merge issue; Added Russian; --- browser/main/Main.js | 2 + browser/main/NoteList/index.js | 2 +- browser/main/lib/ConfigManager.js | 2 + browser/main/modals/PreferencesModal/UiTab.js | 1 + locales/da.json | 3 +- locales/de.json | 5 +- locales/en.json | 5 +- locales/es.json | 3 +- locales/fr.json | 3 +- locales/ja.json | 3 +- locales/ko.json | 3 +- locales/no.json | 3 +- locales/pl.json | 3 +- locales/pt.json | 3 +- locales/ru.json | 146 ++++++++++++++++++ locales/sq.json | 3 +- locales/zh-CN.json | 3 +- locales/zh-TW.json | 3 +- 18 files changed, 182 insertions(+), 14 deletions(-) create mode 100644 locales/ru.json diff --git a/browser/main/Main.js b/browser/main/Main.js index 13294c0f..a2c8b658 100644 --- a/browser/main/Main.js +++ b/browser/main/Main.js @@ -171,6 +171,8 @@ class Main extends React.Component { i18n.setLocale('pl') } else if (config.ui.language === 'pt') { i18n.setLocale('pt') + } else if (config.ui.language === 'ru') { + i18n.setLocale('ru') } else if (config.ui.language === 'es') { i18n.setLocale('es') } else { diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index cfde1f84..0329a9cc 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -15,7 +15,7 @@ import path from 'path' import { hashHistory } from 'react-router' import copy from 'copy-to-clipboard' import AwsMobileAnalyticsConfig from 'browser/main/lib/AwsMobileAnalyticsConfig' -import markdown from '../../lib/markdown' +import Markdown from '../../lib/markdown' import i18n from 'browser/lib/i18n' const { remote } = require('electron') diff --git a/browser/main/lib/ConfigManager.js b/browser/main/lib/ConfigManager.js index 2da2f1c2..40b89198 100644 --- a/browser/main/lib/ConfigManager.js +++ b/browser/main/lib/ConfigManager.js @@ -157,6 +157,8 @@ function set (updates) { i18n.setLocale('pl') } else if (newConfig.ui.language === 'pt') { i18n.setLocale('pt') + } else if (newConfig.ui.language === 'ru') { + i18n.setLocale('ru') } else if (newConfig.ui.language === 'es') { i18n.setLocale('es') } else { diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index 23c302d0..deb70c06 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -190,6 +190,7 @@ class UiTab extends React.Component { +
    diff --git a/locales/da.json b/locales/da.json index 27c94e6e..60201b34 100644 --- a/locales/da.json +++ b/locales/da.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/de.json b/locales/de.json index ae9c84d6..fb2b6b11 100644 --- a/locales/de.json +++ b/locales/de.json @@ -139,5 +139,8 @@ "Spanish": "Spanisch", "Chinese (zh-CN)": "Chinesisch (zh-CN)", "Chinese (zh-TW)": "Chinesisch (zh-TW)", - "Successfully applied!": "Erfolgreich angewendet!" + "Successfully applied!": "Erfolgreich angewendet!", + "UserName": "UserName", + "Password": "Password", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/en.json b/locales/en.json index 27c94e6e..91cb7f18 100644 --- a/locales/en.json +++ b/locales/en.json @@ -139,5 +139,8 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "UserName": "UserName", + "Password": "Password", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/es.json b/locales/es.json index 27c94e6e..60201b34 100644 --- a/locales/es.json +++ b/locales/es.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/fr.json b/locales/fr.json index 27c94e6e..60201b34 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/ja.json b/locales/ja.json index 27c94e6e..60201b34 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/ko.json b/locales/ko.json index 27c94e6e..60201b34 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/no.json b/locales/no.json index 27c94e6e..60201b34 100644 --- a/locales/no.json +++ b/locales/no.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/pl.json b/locales/pl.json index 27c94e6e..60201b34 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/pt.json b/locales/pt.json index 27c94e6e..60201b34 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/ru.json b/locales/ru.json new file mode 100644 index 00000000..91cb7f18 --- /dev/null +++ b/locales/ru.json @@ -0,0 +1,146 @@ +{ + "Notes": "Notes", + "Tags": "Tags", + "Preferences": "Preferences", + "Make a note": "Make a note", + "Ctrl": "Ctrl", + "Ctrl(^)": "Ctrl", + "to create a new note": "to create a new note", + "Toggle Mode": "Toggle Mode", + "Trash": "Trash", + "MODIFICATION DATE": "MODIFICATION DATE", + "Words": "Words", + "Letters": "Letters", + "STORAGE": "STORAGE", + "FOLDER": "FOLDER", + "CREATION DATE": "CREATION DATE", + "NOTE LINK": "NOTE LINK", + ".md": ".md", + ".txt": ".txt", + ".html": ".html", + "Print": "Print", + "Your preferences for Boostnote": "Your preferences for Boostnote", + "Storages": "Storages", + "Add Storage Location": "Add Storage Location", + "Add Folder": "Add Folder", + "Open Storage folder": "Open Storage folder", + "Unlink": "Unlink", + "Edit": "Edit", + "Delete": "Delete", + "Interface": "Interface", + "Interface Theme": "Interface Theme", + "Default": "Delete", + "White": "White", + "Solarized Dark": "Solarized Dark", + "Dark": "Dark", + "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", + "Editor Theme": "Editor Theme", + "Editor Font Size": "Editor Font Size", + "Editor Font Family": "Editor Font Family", + "Editor Indent Style": "Editor Indent Style", + "Spaces": "Spaces", + "Tabs": "Tabs", + "Switch to Preview": "Switch to Preview", + "When Editor Blurred": "When Editor Blurred", + "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", + "On Right Click": "On Right Click", + "Editor Keymap": "Editor Keymap", + "default": "default", + "vim": "vim", + "emacs": "emacs", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", + "Show line numbers in the editor": "Show line numbers in the editor", + "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", + "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview Font Size": "Preview Font Size", + "Preview Font Family": "Preview Font Family", + "Code block Theme": "Code block Theme", + "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", + "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", + "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", + "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", + "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", + "Community": "Community", + "Subscribe to Newsletter": "Subscribe to Newsletter", + "GitHub": "GitHub", + "Blog": "Blog", + "Facebook Group": "Facebook Group", + "Twitter": "Twitter", + "About": "About", + "Boostnote": "Boostnote", + "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", + "Website": "Website", + "Development": "Development", + " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", + "License: GPL v3": "License: GPL v3", + "Analytics": "Analytics", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", + "You can see how it works on ": "You can see how it works on ", + "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", + "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Crowdfunding": "Crowdfunding", + "Dear everyone,": "Dear everyone,", + "Thank you for using Boostnote!": "Thank you for using Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", + "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", + "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", + "Thanks,": "Thanks,", + "Boostnote maintainers": "Boostnote maintainers", + "Support via OpenCollective": "Support via OpenCollective", + "Language": "Language", + "English": "English", + "German": "German", + "French": "French", + "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", + "All Notes": "All Notes", + "Starred": "Starred", + "Are you sure to ": "Are you sure to ", + " delete": " delete", + "this folder?": "this folder?", + "Confirm": "Confirm", + "Cancel": "Cancel", + "Markdown Note": "Markdown Note", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", + "Snippet Note": "Snippet Note", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", + "Tab to switch format": "Tab to switch format", + "Updated": "Updated", + "Created": "Created", + "Alphabetically": "Alphabetically", + "Default View": "Default View", + "Compressed View": "Compressed View", + "Search": "Search", + "Blog Type": "Blog Type", + "Blog Address": "Blog Address", + "Save": "Save", + "Auth": "Auth", + "Authentication Method": "Authentication Method", + "JWT": "JWT", + "USER": "USER", + "Token": "Token", + "Storage": "Storage", + "Hotkeys": "Hotkeys", + "Show/Hide Boostnote": "Show/Hide Boostnote", + "Restore": "Restore", + "Permanent Delete": "Permanent Delete", + "Confirm note deletion": "Confirm note deletion", + "This will permanently remove this note.": "This will permanently remove this note.", + "Successfully applied!": "Successfully applied!", + "Albanian": "Albanian", + "Chinese (zh-CN)": "Chinese (zh-CN)", + "Chinese (zh-TW)": "Chinese (zh-TW)", + "Danish": "Danish", + "Japanese": "Japanese", + "Korean": "Korean", + "Norwegian": "Norwegian", + "Polish": "Polish", + "Portuguese": "Portuguese", + "Spanish": "Spanish", + "You have to save!": "You have to save!", + "UserName": "UserName", + "Password": "Password", + "Russian": "Russian" +} \ No newline at end of file diff --git a/locales/sq.json b/locales/sq.json index 27c94e6e..60201b34 100644 --- a/locales/sq.json +++ b/locales/sq.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 27c94e6e..60201b34 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 27c94e6e..60201b34 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -139,5 +139,6 @@ "Polish": "Polish", "Portuguese": "Portuguese", "Spanish": "Spanish", - "You have to save!": "You have to save!" + "You have to save!": "You have to save!", + "Russian": "Russian" } \ No newline at end of file From 7c8939ecb8af8ed5ec0a4664c1a1b32273753aca Mon Sep 17 00:00:00 2001 From: Nikolai Lopin Date: Thu, 15 Mar 2018 02:23:15 +0300 Subject: [PATCH 66/75] Add russian translation --- locales/ru.json | 258 ++++++++++++++++++++++++------------------------ 1 file changed, 129 insertions(+), 129 deletions(-) diff --git a/locales/ru.json b/locales/ru.json index 91cb7f18..798f9c8d 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -1,146 +1,146 @@ { - "Notes": "Notes", - "Tags": "Tags", - "Preferences": "Preferences", - "Make a note": "Make a note", + "Notes": "Записи", + "Tags": "Теги", + "Preferences": "Настройки", + "Make a note": "Добавить запись", "Ctrl": "Ctrl", "Ctrl(^)": "Ctrl", - "to create a new note": "to create a new note", - "Toggle Mode": "Toggle Mode", - "Trash": "Trash", - "MODIFICATION DATE": "MODIFICATION DATE", - "Words": "Words", - "Letters": "Letters", - "STORAGE": "STORAGE", - "FOLDER": "FOLDER", - "CREATION DATE": "CREATION DATE", - "NOTE LINK": "NOTE LINK", + "to create a new note": "создать новую запись", + "Toggle Mode": "Переключить режим", + "Trash": "Корзина", + "MODIFICATION DATE": "Дата изменения", + "Words": "Слова", + "Letters": "Буквы", + "STORAGE": "Хранилище", + "FOLDER": "Папка", + "CREATION DATE": "Дата создания", + "NOTE LINK": "Ссылка на запись", ".md": ".md", ".txt": ".txt", ".html": ".html", "Print": "Print", - "Your preferences for Boostnote": "Your preferences for Boostnote", - "Storages": "Storages", - "Add Storage Location": "Add Storage Location", - "Add Folder": "Add Folder", - "Open Storage folder": "Open Storage folder", - "Unlink": "Unlink", - "Edit": "Edit", - "Delete": "Delete", - "Interface": "Interface", - "Interface Theme": "Interface Theme", - "Default": "Delete", - "White": "White", + "Your preferences for Boostnote": "Настройки Boostnote", + "Storages": "Хранилища", + "Add Storage Location": "Добавить хранилище", + "Add Folder": "Добавить папку", + "Open Storage folder": "Открыть хранилище", + "Unlink": "Удалить", + "Edit": "Редактировать", + "Delete": "Удалить", + "Interface": "Интерфейс", + "Interface Theme": "Тема оформления", + "Default": "По умолчанию", + "White": "Светлая", "Solarized Dark": "Solarized Dark", - "Dark": "Dark", - "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", - "Editor Theme": "Editor Theme", - "Editor Font Size": "Editor Font Size", - "Editor Font Family": "Editor Font Family", - "Editor Indent Style": "Editor Indent Style", - "Spaces": "Spaces", - "Tabs": "Tabs", - "Switch to Preview": "Switch to Preview", - "When Editor Blurred": "When Editor Blurred", - "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", - "On Right Click": "On Right Click", - "Editor Keymap": "Editor Keymap", - "default": "default", + "Dark": "Темная", + "Show a confirmation dialog when deleting notes": "Спрашивать подтверждение перед удалением записей?", + "Editor Theme": "Тема", + "Editor Font Size": "Размер шрифта", + "Editor Font Family": "Шрифт", + "Editor Indent Style": "Отступы", + "Spaces": "Пробелы", + "Tabs": "Табуляция", + "Switch to Preview": "Переключать на превью", + "When Editor Blurred": "При снятии фокуса с редактора", + "When Editor Blurred, Edit On Double Click": "При снятии фокуса, редактировать двойным кликом", + "On Right Click": "По правому клику", + "Editor Keymap": "Горячие клавиши", + "default": "по умолчанию", "vim": "vim", "emacs": "emacs", - "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", - "Show line numbers in the editor": "Show line numbers in the editor", - "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", - "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", - "Preview Font Size": "Preview Font Size", - "Preview Font Family": "Preview Font Family", - "Code block Theme": "Code block Theme", - "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", - "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", - "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", - "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", - "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", - "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", - "Community": "Community", - "Subscribe to Newsletter": "Subscribe to Newsletter", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Перезапустите Boostnote, чтобы применить изменения", + "Show line numbers in the editor": "Показывать номера строк в редакторе", + "Allow editor to scroll past the last line": "Разрешить прокрутку дальше последней строки в редакторе", + "Bring in web page title when pasting URL on editor": "Копировать заголовок страницы при вставке URL-ссылки в редакторе", + "Preview Font Size": "Размер шрифта", + "Preview Font Family": "Шрифт", + "Code block Theme": "Тема оформления кода", + "Allow preview to scroll past the last line": "Разрешить прокрутку дальше последней строки в превью", + "Show line numbers for preview code blocks": "Показывать номера строк в блоках кода", + "LaTeX Inline Open Delimiter": "Символ начала inline записи в LaTeX", + "LaTeX Inline Close Delimiter": "Символ окончания inline записи в LaTeX", + "LaTeX Block Open Delimiter": "Символ начала блока LaTeX", + "LaTeX Block Close Delimiter": "Символ окончания блока LaTeX", + "Community": "Сообщество", + "Subscribe to Newsletter": "Подпишитесь на рассылку", "GitHub": "GitHub", - "Blog": "Blog", - "Facebook Group": "Facebook Group", - "Twitter": "Twitter", - "About": "About", + "Blog": "Блог", + "Facebook Group": "Группа в Фейсбуке", + "Twitter": "Твиттер", + "About": "О нас", "Boostnote": "Boostnote", - "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", - "Website": "Website", - "Development": "Development", - " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "An open source note-taking app made for programmers just like you.": "Приложение для программерских и научных заметок с открытым кодом", + "Website": "Сайт", + "Development": "Разработка", + " : Development configurations for Boostnote.": " : Разработческие конфигурации для Boostnote.", "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", "License: GPL v3": "License: GPL v3", - "Analytics": "Analytics", - "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", - "You can see how it works on ": "You can see how it works on ", - "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", - "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", - "Crowdfunding": "Crowdfunding", - "Dear everyone,": "Dear everyone,", - "Thank you for using Boostnote!": "Thank you for using Boostnote!", - "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", - "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", - "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", - "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", - "Thanks,": "Thanks,", - "Boostnote maintainers": "Boostnote maintainers", - "Support via OpenCollective": "Support via OpenCollective", - "Language": "Language", - "English": "English", - "German": "German", - "French": "French", - "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", - "All Notes": "All Notes", - "Starred": "Starred", - "Are you sure to ": "Are you sure to ", - " delete": " delete", - "this folder?": "this folder?", - "Confirm": "Confirm", - "Cancel": "Cancel", - "Markdown Note": "Markdown Note", - "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", - "Snippet Note": "Snippet Note", - "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", - "Tab to switch format": "Tab to switch format", - "Updated": "Updated", - "Created": "Created", - "Alphabetically": "Alphabetically", - "Default View": "Default View", - "Compressed View": "Compressed View", - "Search": "Search", - "Blog Type": "Blog Type", - "Blog Address": "Blog Address", - "Save": "Save", - "Auth": "Auth", - "Authentication Method": "Authentication Method", + "Analytics": "Аналитика", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote собирает анонимные данные о пользовании приложением для того, чтобы улучшать пользовательский опыт. Мы не собираем личную информацию и содержание ваших записей.", + "You can see how it works on ": "Посмотрите исходный код на ", + "You can choose to enable or disable this option.": "Вы можете отказаться от передачи анонимной информации разработчикам.", + "Enable analytics to help improve Boostnote": "Отправлять анонимные данные, чтобы сделать Boostnote еще лучше", + "Crowdfunding": "Краудфандинг", + "Dear everyone,": "Привет,", + "Thank you for using Boostnote!": "Спасибо за использование Boostnote!", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote используется в 200 странах и регионов дружным сообществом разработчиков.", + "To continue supporting this growth, and to satisfy community expectations,": "Чтобы продукт развивался и удовлетворял ожиданиям пользователей,", + "we would like to invest more time and resources in this project.": "мы хотим выделять больше времени и ресурсов проекту.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "Если вам нравится Boostnote и его сообщество, вы можете профинансировать проект на OpenCollective!", + "Thanks,": "Спасибо,", + "Boostnote maintainers": "разработчики Boostnote", + "Support via OpenCollective": "Старница проекта на OpenCollective", + "Language": "Язык", + "English": "Английский", + "German": "Немецкий", + "French": "Французский", + "Show \"Saved to Clipboard\" notification when copying": "Показывать уведомление \"Скопировано в буфер\" при копировании?", + "All Notes": "Все записи", + "Starred": "Избранное", + "Are you sure to ": "Вы уверены, что хотите ", + " delete": " удалить", + "this folder?": "эту папку?", + "Confirm": "Да", + "Cancel": "Отмена", + "Markdown Note": "Markdown", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Этот формат подходит для создания текстовых документов. Сюда вы можете добавлять чек-листы, блоки кода и блоки в LaTeX.", + "Snippet Note": "Snippet", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Этот формат подходит для хранения кусков кода. Внутри одной записи можно создать несколько сниппетов.", + "Tab to switch format": "Tab для переключения формата", + "Updated": "По дате изменения", + "Created": "По дате создания", + "Alphabetically": "По алфавиту", + "Default View": "Стандартный вид", + "Compressed View": "Сокращенный вид", + "Search": "Поиск", + "Blog Type": "Тип блога", + "Blog Address": "Адрес блога", + "Save": "Сохранить", + "Auth": "Авторизоваться", + "Authentication Method": "Метод авторизации", "JWT": "JWT", "USER": "USER", "Token": "Token", - "Storage": "Storage", - "Hotkeys": "Hotkeys", - "Show/Hide Boostnote": "Show/Hide Boostnote", - "Restore": "Restore", - "Permanent Delete": "Permanent Delete", - "Confirm note deletion": "Confirm note deletion", - "This will permanently remove this note.": "This will permanently remove this note.", - "Successfully applied!": "Successfully applied!", - "Albanian": "Albanian", - "Chinese (zh-CN)": "Chinese (zh-CN)", - "Chinese (zh-TW)": "Chinese (zh-TW)", - "Danish": "Danish", - "Japanese": "Japanese", - "Korean": "Korean", - "Norwegian": "Norwegian", - "Polish": "Polish", - "Portuguese": "Portuguese", - "Spanish": "Spanish", - "You have to save!": "You have to save!", - "UserName": "UserName", - "Password": "Password", - "Russian": "Russian" -} \ No newline at end of file + "Storage": "Хранилище", + "Hotkeys": "Горячие клавиши", + "Show/Hide Boostnote": "Показать/скрыть Boostnote", + "Restore": "Восстановить", + "Permanent Delete": "Удалить без восстановления", + "Confirm note deletion": "Подтвердите удаление", + "This will permanently remove this note.": "Это действие приведет к полному удалению записи. Восстановить запись будет невозможно.", + "Successfully applied!": "Успешно!", + "Albanian": "Албанский", + "Chinese (zh-CN)": "Китайский (zh-CN)", + "Chinese (zh-TW)": "Китайский (zh-TW)", + "Danish": "Датский", + "Japanese": "Японский", + "Korean": "Корейский", + "Norwegian": "Норвежский", + "Polish": "Польский", + "Portuguese": "Португальский", + "Spanish": "Испанский", + "You have to save!": "Нужно сохранить!", + "UserName": "Имя пользователя", + "Password": "Пароль", + "Russian": "Русский" +} From 8bf5d02624e9f6b51bc858f502d0603c4f05dd79 Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Thu, 15 Mar 2018 22:12:22 +1100 Subject: [PATCH 67/75] Revert "updated lib/consts to access electron remote.app only when in production mode" This reverts commit bbcd674516aeeaf1ceaf205c478c56ea1f450b6b. --- browser/lib/consts.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/browser/lib/consts.js b/browser/lib/consts.js index 23519916..c6b2ea5b 100644 --- a/browser/lib/consts.js +++ b/browser/lib/consts.js @@ -1,9 +1,10 @@ const path = require('path') const fs = require('sander') const { remote } = require('electron') +const { app } = remote const themePath = process.env.NODE_ENV === 'production' - ? path.join(remote.app.getAppPath(), './node_modules/codemirror/theme') + ? path.join(app.getAppPath(), './node_modules/codemirror/theme') : require('path').resolve('./node_modules/codemirror/theme') const themes = fs.readdirSync(themePath) .map((themePath) => { From c147e0a789f82939e1cd4a8a7f5dd29d10b07ffd Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Thu, 15 Mar 2018 22:14:21 +1100 Subject: [PATCH 68/75] mocked electron in ava unit tests --- package.json | 4 +++- tests/helpers/setup-electron-mock.js | 11 +++++++++++ yarn.lock | 8 +++++++- 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/helpers/setup-electron-mock.js diff --git a/package.json b/package.json index 32d06176..71a000dd 100644 --- a/package.json +++ b/package.json @@ -121,6 +121,7 @@ "jsdom": "^9.4.2", "json-loader": "^0.5.4", "merge-stream": "^1.0.0", + "mock-require": "^3.0.1", "nib": "^1.1.0", "react-color": "^2.2.2", "react-css-modules": "^3.7.6", @@ -145,7 +146,8 @@ ], "require": [ "babel-register", - "./tests/helpers/setup-browser-env.js" + "./tests/helpers/setup-browser-env.js", + "./tests/helpers/setup-electron-mock.js" ], "babel": "inherit" } diff --git a/tests/helpers/setup-electron-mock.js b/tests/helpers/setup-electron-mock.js new file mode 100644 index 00000000..dd6a9733 --- /dev/null +++ b/tests/helpers/setup-electron-mock.js @@ -0,0 +1,11 @@ +import mock from 'mock-require' + +const noop = () => {} + +mock('electron', { + remote: { + app: { + getAppPath: noop + } + } +}) diff --git a/yarn.lock b/yarn.lock index d9644df4..e85c298d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3321,7 +3321,7 @@ generate-object-property@^1.1.0: dependencies: is-property "^1.0.0" -get-caller-file@^1.0.1: +get-caller-file@^1.0.1, get-caller-file@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" @@ -4998,6 +4998,12 @@ mksnapshot@^0.3.0: fs-extra "0.26.7" request "^2.79.0" +mock-require@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mock-require/-/mock-require-3.0.1.tgz#d5efd834c0da0cec73c7b67763d8167d32d851de" + dependencies: + get-caller-file "^1.0.2" + moment@^2.10.3: version "2.18.1" resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" From 433fce286eb9ab9a0335716ef8d8579064b18fd8 Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Fri, 16 Mar 2018 23:11:43 +1100 Subject: [PATCH 69/75] added electron as global variable to pass eslint check --- browser/main/NoteList/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 06880bab..2e31a5d7 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -1,3 +1,4 @@ +/* global electron */ import PropTypes from 'prop-types' import React from 'react' import CSSModules from 'browser/lib/CSSModules' From 00ba38beba19e7a4c0127d5b11739db44365c650 Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Fri, 16 Mar 2018 23:30:57 +1100 Subject: [PATCH 70/75] reload config every time when markdown lib initiated --- browser/lib/markdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index 22f581e4..cb6a3826 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -8,7 +8,6 @@ import {lastFindInArray} from './utils' // FIXME We should not depend on global variable. const katex = window.katex -const config = ConfigManager.get() function createGutter (str, firstLineNumber) { if (Number.isNaN(firstLineNumber)) firstLineNumber = 1 @@ -22,6 +21,7 @@ function createGutter (str, firstLineNumber) { class Markdown { constructor (options = {}) { + const config = ConfigManager.get() const defaultOptions = { typographer: true, linkify: true, From 33b3299ca2e8a5e09378a41f0328efda189b540d Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Fri, 16 Mar 2018 23:32:12 +1100 Subject: [PATCH 71/75] changed the default options of markdown lib to follow config --- browser/lib/markdown.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/lib/markdown.js b/browser/lib/markdown.js index cb6a3826..125ba3be 100644 --- a/browser/lib/markdown.js +++ b/browser/lib/markdown.js @@ -23,7 +23,7 @@ class Markdown { constructor (options = {}) { const config = ConfigManager.get() const defaultOptions = { - typographer: true, + typographer: config.preview.smartQuotes, linkify: true, html: true, xhtmlOut: true, From b9cab0dae813edd23b6c25333d9a479e443976ea Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Fri, 16 Mar 2018 23:33:40 +1100 Subject: [PATCH 72/75] Init markdown lib only when it's needed when posting a note to blog --- browser/main/NoteList/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/browser/main/NoteList/index.js b/browser/main/NoteList/index.js index 2e31a5d7..d8632da6 100644 --- a/browser/main/NoteList/index.js +++ b/browser/main/NoteList/index.js @@ -21,7 +21,6 @@ import Markdown from '../../lib/markdown' const { remote } = require('electron') const { Menu, MenuItem, dialog } = remote const WP_POST_PATH = '/wp/v2/posts' -const markdown = new Markdown() function sortByCreatedAt (a, b) { return new Date(b.createdAt) - new Date(a.createdAt) @@ -710,6 +709,7 @@ class NoteList extends React.Component { authToken = `Bearer ${token}` } const contentToRender = firstNote.content.replace(`# ${firstNote.title}`, '') + const markdown = new Markdown() const data = { title: firstNote.title, content: markdown.render(contentToRender), From a8431fae9609f995d2ca72a9a07a21fbf42eab14 Mon Sep 17 00:00:00 2001 From: Romain Le Quellec Date: Sat, 17 Mar 2018 10:16:51 +0100 Subject: [PATCH 73/75] add missing i18n preview word + fr translation --- browser/main/modals/PreferencesModal/UiTab.js | 2 +- locales/da.json | 1 + locales/de.json | 1 + locales/en.json | 1 + locales/es.json | 1 + locales/fr.json | 225 +++++++++--------- locales/ja.json | 1 + locales/ko.json | 1 + locales/no.json | 1 + locales/pl.json | 1 + locales/pt.json | 1 + locales/ru.json | 1 + locales/sq.json | 1 + locales/zh-CN.json | 1 + locales/zh-TW.json | 1 + 15 files changed, 126 insertions(+), 114 deletions(-) diff --git a/browser/main/modals/PreferencesModal/UiTab.js b/browser/main/modals/PreferencesModal/UiTab.js index deb70c06..81e29746 100644 --- a/browser/main/modals/PreferencesModal/UiTab.js +++ b/browser/main/modals/PreferencesModal/UiTab.js @@ -369,7 +369,7 @@ class UiTab extends React.Component {
    -
    Preview
    +
    {i18n.__('Preview')}
    {i18n.__('Preview Font Size')} diff --git a/locales/da.json b/locales/da.json index 60201b34..e54245f9 100644 --- a/locales/da.json +++ b/locales/da.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", diff --git a/locales/de.json b/locales/de.json index fb2b6b11..9c36871c 100644 --- a/locales/de.json +++ b/locales/de.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Zeilennummern im Editor anzeigen", "Allow editor to scroll past the last line": "Editor das Scrollen über das Ende hinaus erlauben", "Bring in web page title when pasting URL on editor": "Websitetitel beim Einfügen in den Editor anzeigen", + "Preview": "Vorschau", "Preview Font Size": "Vorschau Schriftgröße", "Preview Font Family": "Vorschau Schriftart", "Code block Theme": "Code block Theme", diff --git a/locales/en.json b/locales/en.json index 91cb7f18..ee3dda06 100644 --- a/locales/en.json +++ b/locales/en.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", diff --git a/locales/es.json b/locales/es.json index 60201b34..e54245f9 100644 --- a/locales/es.json +++ b/locales/es.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", diff --git a/locales/fr.json b/locales/fr.json index 60201b34..6f664280 100644 --- a/locales/fr.json +++ b/locales/fr.json @@ -1,144 +1,143 @@ { "Notes": "Notes", "Tags": "Tags", - "Preferences": "Preferences", - "Make a note": "Make a note", + "Preferences": "Préférences", + "Make a note": "Créer une note", "Ctrl": "Ctrl", "Ctrl(^)": "Ctrl", - "to create a new note": "to create a new note", + "to create a new note": "pour créer une nouvelle note", "Toggle Mode": "Toggle Mode", - "Trash": "Trash", - "MODIFICATION DATE": "MODIFICATION DATE", - "Words": "Words", - "Letters": "Letters", - "STORAGE": "STORAGE", - "FOLDER": "FOLDER", - "CREATION DATE": "CREATION DATE", - "NOTE LINK": "NOTE LINK", + "Trash": "Poubelle", + "MODIFICATION DATE": "DATE DE MODIFICATION", + "Words": "Mots", + "Letters": "Lettres", + "STORAGE": "STOCKAGE", + "FOLDER": "DOSSIER", + "CREATION DATE": "DATE DE CREATION", + "NOTE LINK": "LIEN DE LA NOTE", ".md": ".md", ".txt": ".txt", ".html": ".html", - "Print": "Print", - "Your preferences for Boostnote": "Your preferences for Boostnote", - "Storages": "Storages", - "Add Storage Location": "Add Storage Location", - "Add Folder": "Add Folder", - "Open Storage folder": "Open Storage folder", - "Unlink": "Unlink", - "Edit": "Edit", - "Delete": "Delete", + "Print": "Imprimer", + "Your preferences for Boostnote": "Vos préférences pour Boostnote", + "Storages": "Stockages", + "Add Storage Location": "Ajouter un espace de stockage", + "Add Folder": "Ajouter un dossier", + "Open Storage folder": "Ouvrir un dossier de stockage", + "Unlink": "Délier", + "Edit": "Editer", + "Delete": "Supprimer", "Interface": "Interface", - "Interface Theme": "Interface Theme", - "Default": "Delete", - "White": "White", - "Solarized Dark": "Solarized Dark", - "Dark": "Dark", - "Show a confirmation dialog when deleting notes": "Show a confirmation dialog when deleting notes", - "Editor Theme": "Editor Theme", - "Editor Font Size": "Editor Font Size", - "Editor Font Family": "Editor Font Family", - "Editor Indent Style": "Editor Indent Style", - "Spaces": "Spaces", - "Tabs": "Tabs", - "Switch to Preview": "Switch to Preview", - "When Editor Blurred": "When Editor Blurred", - "When Editor Blurred, Edit On Double Click": "When Editor Blurred, Edit On Double Click", - "On Right Click": "On Right Click", - "Editor Keymap": "Editor Keymap", - "default": "default", + "Interface Theme": "Thème d'interface", + "Default": "Effacer", + "White": "Blanc", + "Solarized Dark": "Foncé solarisé", + "Dark": "Foncé", + "Show a confirmation dialog when deleting notes": "Montrer une alerte de confirmation lors de la suppression de notes", + "Editor Theme": "Theme d'éditeur", + "Editor Font Size": "Taille de police de l'éditeur", + "Editor Font Family": "Police de l'éditeur", + "Editor Indent Style": "Style d'indentation de l'éditeur", + "Spaces": "Espaces", + "Tabs": "Tabulations", + "Switch to Preview": "Switcher vers l'aperçu", + "When Editor Blurred": "Quand l'éditeur n'est pas sélectionné", + "When Editor Blurred, Edit On Double Click": "Quand l'éditeur n'est pas sélectionné, éditer avec un double clic", + "On Right Click": "Avec un clic droit", + "Editor Keymap": "Keymap de l'éditeur", + "default": "Par défaut", "vim": "vim", "emacs": "emacs", - "⚠️ Please restart boostnote after you change the keymap": "⚠️ Please restart boostnote after you change the keymap", - "Show line numbers in the editor": "Show line numbers in the editor", - "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", - "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", - "Preview Font Size": "Preview Font Size", - "Preview Font Family": "Preview Font Family", - "Code block Theme": "Code block Theme", - "Allow preview to scroll past the last line": "Allow preview to scroll past the last line", - "Show line numbers for preview code blocks": "Show line numbers for preview code blocks", + "⚠️ Please restart boostnote after you change the keymap": "⚠️ Redémarrez Boostnote après avoir changé la keymap", + "Show line numbers in the editor": "Montrer les numéros de lignes dans l'éditeur", + "Allow editor to scroll past the last line": "Contrôle si l'éditeur défile au-delà de la dernière ligne", + "Bring in web page title when pasting URL on editor": "Mettre le titre de la page lors d'un collé d'une URL dans l'éditeur", + "Preview": "Aperçu", + "Preview Font Size": "Taille de police de l'aperçu", + "Preview Font Family": "Police de l'aperçu", + "Code block Theme": "Thème des blocs de code", + "Show line numbers for preview code blocks": "Montrer les numéros de lignes dans les blocs de code dans l'aperçu", "LaTeX Inline Open Delimiter": "LaTeX Inline Open Delimiter", "LaTeX Inline Close Delimiter": "LaTeX Inline Close Delimiter", "LaTeX Block Open Delimiter": "LaTeX Block Open Delimiter", "LaTeX Block Close Delimiter": "LaTeX Block Close Delimiter", - "Community": "Community", - "Subscribe to Newsletter": "Subscribe to Newsletter", + "Community": "Communauté", + "Subscribe to Newsletter": "Souscrire à la newsletter", "GitHub": "GitHub", "Blog": "Blog", - "Facebook Group": "Facebook Group", + "Facebook Group": "Groupe Facebook", "Twitter": "Twitter", - "About": "About", + "About": "A propos", "Boostnote": "Boostnote", - "An open source note-taking app made for programmers just like you.": "An open source note-taking app made for programmers just like you.", - "Website": "Website", - "Development": "Development", - " : Development configurations for Boostnote.": " : Development configurations for Boostnote.", + "An open source note-taking app made for programmers just like you.": "Une appli de prise de notes open-source faite pour les développeurs comme vous.", + "Website": "Site web", + "Development": "Développement", + " : Development configurations for Boostnote.": " : Configurations de développement pour Boostnote.", "Copyright (C) 2017 - 2018 BoostIO": "Copyright (C) 2017 - 2018 BoostIO", "License: GPL v3": "License: GPL v3", "Analytics": "Analytics", - "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.", - "You can see how it works on ": "You can see how it works on ", - "You can choose to enable or disable this option.": "You can choose to enable or disable this option.", - "Enable analytics to help improve Boostnote": "Enable analytics to help improve Boostnote", + "Boostnote collects anonymous data for the sole purpose of improving the application, and strictly does not collect any personal information such the contents of your notes.": "Boostnote collecte des données anonymisées dans le seul but d'améliorer l'application, et ne collecte aucune donnée personnelle telle que le contenu de vos notes.", + "You can see how it works on ": "Vous pouvez voir comment ça marche sur", + "You can choose to enable or disable this option.": "Vous pouvez choisir d'activer/désactiver cette option.", + "Enable analytics to help improve Boostnote": "Activer la collecte de données anonymisées pour améliorer Boostnote", "Crowdfunding": "Crowdfunding", - "Dear everyone,": "Dear everyone,", - "Thank you for using Boostnote!": "Thank you for using Boostnote!", - "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote is used in about 200 different countries and regions by an awesome community of developers.", - "To continue supporting this growth, and to satisfy community expectations,": "To continue supporting this growth, and to satisfy community expectations,", - "we would like to invest more time and resources in this project.": "we would like to invest more time and resources in this project.", - "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "If you like this project and see its potential, you can help by supporting us on OpenCollective!", - "Thanks,": "Thanks,", - "Boostnote maintainers": "Boostnote maintainers", + "Dear everyone,": "Cher utilisateur,", + "Thank you for using Boostnote!": "Merci d'utiliser Boostnote !", + "Boostnote is used in about 200 different countries and regions by an awesome community of developers.": "Boostnote est utilisé dans plus de 200 pays et régions par une impressionnante communauté de développeurs.", + "To continue supporting this growth, and to satisfy community expectations,": "Afin de continuer à grandir, et de satisfaire les attentes de la communauté,", + "we would like to invest more time and resources in this project.": "nous aimerions investir d'avantage de temps et de ressources dans ce proje.", + "If you like this project and see its potential, you can help by supporting us on OpenCollective!": "Si vous aimez ce projet et que vous en voyez tout le potentiel, vous pouvez aider par un support sur OpenCollective !", + "Thanks,": "Merci,", + "Boostnote maintainers": "Les mainteneurs de Boostnote", "Support via OpenCollective": "Support via OpenCollective", - "Language": "Language", - "English": "English", - "German": "German", - "French": "French", - "Show \"Saved to Clipboard\" notification when copying": "Show \"Saved to Clipboard\" notification when copying", - "All Notes": "All Notes", - "Starred": "Starred", - "Are you sure to ": "Are you sure to ", - " delete": " delete", - "this folder?": "this folder?", - "Confirm": "Confirm", - "Cancel": "Cancel", - "Markdown Note": "Markdown Note", - "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.", - "Snippet Note": "Snippet Note", - "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "This format is for creating code snippets. Multiple snippets can be grouped into a single note.", - "Tab to switch format": "Tab to switch format", - "Updated": "Updated", - "Created": "Created", - "Alphabetically": "Alphabetically", - "Default View": "Default View", - "Compressed View": "Compressed View", - "Search": "Search", + "Language": "Langues", + "English": "Anglais", + "German": "Allemand", + "French": "Français", + "Show \"Saved to Clipboard\" notification when copying": "Montrer la notification \"Sauvegardé dans le presse-papiers\" lors de la copie", + "All Notes": "Toutes les notes", + "Starred": "Favoris", + "Are you sure to ": "Etes-vous sûr de ", + " delete": " supprimer", + "this folder?": "ce dossier ?", + "Confirm": "Confimer", + "Cancel": "Annuler", + "Markdown Note": "Note Markdown", + "This format is for creating text documents. Checklists, code blocks and Latex blocks are available.": "Ce format est pour créer des documents texte. Checklists, blocks de code et blocks Latex sont disponibles.", + "Snippet Note": "Note Snippet", + "This format is for creating code snippets. Multiple snippets can be grouped into a single note.": "Ce format est pour créer des snippets de code. Plusieurs snippets peuvent être groupés en une seule note.", + "Tab to switch format": "Tab pour changer de format", + "Updated": "Mis à jour", + "Created": "Créé", + "Alphabetically": "De manière alphabétique", + "Default View": "Vue par défaut", + "Compressed View": "Vue compressée", + "Search": "Chercher", "Blog Type": "Blog Type", "Blog Address": "Blog Address", - "Save": "Save", + "Save": "Sauvegarder", "Auth": "Auth", - "Authentication Method": "Authentication Method", + "Authentication Method": "Méthode d'Authentification", "JWT": "JWT", "USER": "USER", "Token": "Token", - "Storage": "Storage", - "Hotkeys": "Hotkeys", - "Show/Hide Boostnote": "Show/Hide Boostnote", - "Restore": "Restore", - "Permanent Delete": "Permanent Delete", - "Confirm note deletion": "Confirm note deletion", - "This will permanently remove this note.": "This will permanently remove this note.", - "Successfully applied!": "Successfully applied!", - "Albanian": "Albanian", - "Chinese (zh-CN)": "Chinese (zh-CN)", - "Chinese (zh-TW)": "Chinese (zh-TW)", - "Danish": "Danish", - "Japanese": "Japanese", - "Korean": "Korean", - "Norwegian": "Norwegian", - "Polish": "Polish", - "Portuguese": "Portuguese", - "Spanish": "Spanish", - "You have to save!": "You have to save!", - "Russian": "Russian" -} \ No newline at end of file + "Storage": "Stockage", + "Hotkeys": "Raccourcis", + "Show/Hide Boostnote": "Montrer/Cacher Boostnote", + "Restore": "Restaurer", + "Permanent Delete": "Supprimer définivitement", + "Confirm note deletion": "Confirmer la suppression de la note", + "This will permanently remove this note.": "Cela va supprimer cette note définitivement.", + "Successfully applied!": " Succès !", + "Albanian": "Albanais", + "Chinese (zh-CN)": "Chinois (zh-CN)", + "Chinese (zh-TW)": "Chinois (zh-TW)", + "Danish": "Danois", + "Japanese": "Japonais", + "Korean": "Coréen", + "Norwegian": "Norvégien", + "Polish": "Polonais", + "Portuguese": "Portugais", + "Spanish": "Espagnol", + "You have to save!": "Il faut sauvegarder !" + } \ No newline at end of file diff --git a/locales/ja.json b/locales/ja.json index 60201b34..e54245f9 100644 --- a/locales/ja.json +++ b/locales/ja.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", diff --git a/locales/ko.json b/locales/ko.json index 60201b34..e54245f9 100644 --- a/locales/ko.json +++ b/locales/ko.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", diff --git a/locales/no.json b/locales/no.json index 60201b34..e54245f9 100644 --- a/locales/no.json +++ b/locales/no.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", diff --git a/locales/pl.json b/locales/pl.json index 60201b34..e54245f9 100644 --- a/locales/pl.json +++ b/locales/pl.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", diff --git a/locales/pt.json b/locales/pt.json index 60201b34..e54245f9 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", diff --git a/locales/ru.json b/locales/ru.json index 798f9c8d..74f83388 100644 --- a/locales/ru.json +++ b/locales/ru.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Показывать номера строк в редакторе", "Allow editor to scroll past the last line": "Разрешить прокрутку дальше последней строки в редакторе", "Bring in web page title when pasting URL on editor": "Копировать заголовок страницы при вставке URL-ссылки в редакторе", + "Preview": "Preview", "Preview Font Size": "Размер шрифта", "Preview Font Family": "Шрифт", "Code block Theme": "Тема оформления кода", diff --git a/locales/sq.json b/locales/sq.json index 60201b34..e54245f9 100644 --- a/locales/sq.json +++ b/locales/sq.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 60201b34..e54245f9 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", diff --git a/locales/zh-TW.json b/locales/zh-TW.json index 60201b34..e54245f9 100644 --- a/locales/zh-TW.json +++ b/locales/zh-TW.json @@ -52,6 +52,7 @@ "Show line numbers in the editor": "Show line numbers in the editor", "Allow editor to scroll past the last line": "Allow editor to scroll past the last line", "Bring in web page title when pasting URL on editor": "Bring in web page title when pasting URL on editor", + "Preview": "Preview", "Preview Font Size": "Preview Font Size", "Preview Font Family": "Preview Font Family", "Code block Theme": "Code block Theme", From 2cee54f70aff7bd8e1e9ce59f8c8ae0d2aea098c Mon Sep 17 00:00:00 2001 From: Romain Le Quellec Date: Sat, 17 Mar 2018 10:23:44 +0100 Subject: [PATCH 74/75] fix missing import --- browser/main/SideNav/StorageItem.js | 1 + 1 file changed, 1 insertion(+) diff --git a/browser/main/SideNav/StorageItem.js b/browser/main/SideNav/StorageItem.js index 92222d27..9ad1ec30 100644 --- a/browser/main/SideNav/StorageItem.js +++ b/browser/main/SideNav/StorageItem.js @@ -10,6 +10,7 @@ import dataApi from 'browser/main/lib/dataApi' import StorageItemChild from 'browser/components/StorageItem' import _ from 'lodash' import { SortableElement } from 'react-sortable-hoc' +import i18n from 'browser/lib/i18n' const { remote } = require('electron') const { Menu, dialog } = remote From 1dd7644e12da7d633d66c398600e8aa490129d88 Mon Sep 17 00:00:00 2001 From: Yu-Hung Ou Date: Sun, 18 Mar 2018 15:36:57 +1100 Subject: [PATCH 75/75] added smart quotes unit test for lib/markdown --- tests/fixtures/markdowns.js | 5 ++++- tests/lib/markdown-test.js | 9 ++++++++ tests/lib/snapshots/markdown-test.js.md | 26 ++++++++++++++++------ tests/lib/snapshots/markdown-test.js.snap | Bin 1581 -> 1665 bytes 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/tests/fixtures/markdowns.js b/tests/fixtures/markdowns.js index d6962514..8db35485 100644 --- a/tests/fixtures/markdowns.js +++ b/tests/fixtures/markdowns.js @@ -46,9 +46,12 @@ const checkboxes = ` - [x] Checked ` +const smartQuotes = 'This is a "QUOTE".' + export default { basic, codeblock, katex, - checkboxes + checkboxes, + smartQuotes } diff --git a/tests/lib/markdown-test.js b/tests/lib/markdown-test.js index 554ea67c..b2a81fdf 100644 --- a/tests/lib/markdown-test.js +++ b/tests/lib/markdown-test.js @@ -25,3 +25,12 @@ test('Markdown.render() should renders checkboxes', t => { const rendered = md.render(markdownFixtures.checkboxes) t.snapshot(rendered) }) + +test('Markdown.render() should text with quotes correctly', t => { + const renderedSmartQuotes = md.render(markdownFixtures.smartQuotes) + t.snapshot(renderedSmartQuotes) + + const newmd = new Markdown({ typographer: false }) + const renderedNonSmartQuotes = newmd.render(markdownFixtures.smartQuotes) + t.snapshot(renderedNonSmartQuotes) +}) diff --git a/tests/lib/snapshots/markdown-test.js.md b/tests/lib/snapshots/markdown-test.js.md index c678fc2f..d4f0469e 100644 --- a/tests/lib/snapshots/markdown-test.js.md +++ b/tests/lib/snapshots/markdown-test.js.md @@ -11,6 +11,16 @@ Generated by [AVA](https://ava.li). `c=pmsqrta2+b2c = pmsqrt{a^2 + b^2}␊ ` +## Markdown.render() should renders checkboxes + +> Snapshot 1 + + `
      ␊ +
    • Unchecked
    • ␊ +
    • Checked
    • ␊ +
    ␊ + ` + ## Markdown.render() should renders codeblock correctly > Snapshot 1 @@ -51,14 +61,16 @@ Generated by [AVA](https://ava.li).
  • Twitter
  • Facebook Group
  • ␊ ␊ - + ` -## Markdown.render() should renders checkboxes +## Markdown.render() should text with quotes correctly > Snapshot 1 - `
      ␊ -
    • Unchecked
    • ␊ -
    • Checked
    • ␊ -
    ␊ - ` \ No newline at end of file + `

    This is a “QUOTE”.

    ␊ + ` + +> Snapshot 2 + + `

    This is a "QUOTE".

    ␊ + ` diff --git a/tests/lib/snapshots/markdown-test.js.snap b/tests/lib/snapshots/markdown-test.js.snap index a74d193fe197404b2f7fc89fedd87689430028fa..71ff221d9f61036d05dda745e42bdb820e08eda5 100644 GIT binary patch literal 1665 zcmV-{27dWLRzV&Ul>7wp3L7 z^a8XXq#h7$#f@VH;)Fn4xNtyJLP7{3q@Lger*cB@X6$u#x0|1mmJ^m@&%Sx@dw=uZ zo4l)O+JoA6eNTLP^ZRp`3!nUK#(yn7-lNIq+BQw|UikRJlUI6gymtHAs~6`Ud8tQH z-|o}2$G)umTDf`U{MT>1x$E|&+1)*g`qQJDw)kh?@7u+#FFyMA)K}Xd{%wDcqF&#j zX=g5-ib7|{jc=C!{^6mEuRqnRs6VEEyLM_?ueMF;?s-7l*?W0g*)5eePZQ5!J~0F{CK-!Fzy#5)l!^pH8FhErbPLw@vRiD0DJC#e9(8JlOSnQJRVoZ0 z^IDbF1EYU7-#$``y; zan(592pk$LC`%{7(KwVjh8>jdpgq_R$5FBuZCR^CHKt{LCLGQnUehG12^J~?jxd{g z#DD-qx^AjTQ+ZIS!P<+&=d<`EfTHsocX963C@BA ztI1O~Q$kyvZ9Os1kcQ1LhupY~3nvy3j3y0bw0oh($6;j9z?gwDX58>ul_*t`j%a`q zI+FBzk$8bujDyewJlP1~Xsza$2$^TtM{aXp>OUUPFoeA%+L-~SDpi*w^Nw;aj3o6w z!3A~TC{1w3rOTwX^e1#H-9_oH>;fOG*9E{qn~I#*FpK`N!_USey7fG%%HB5 zH;9gGa9jzf2=Ub(@-m6c4D5J_gDrtM!7A94E1Sqhd0Pi;FZjKQ>av~`kD97?AO z^ZhuGjV}#&X6V@0{_nEn+*KK>C{XI!_+5k#-K zI}g1ofJvoW%~fs@idnL>Gs;*VjbRk>7BFKWmYzf%pe+niEKp*)Rczv>A7xo8vIrQ< zn9CWnNF0GGXm6JLz2o4eWClrati#)<``UEZuplc&l}4e58y$A3y>2wPUI^FsU`sB5 zf%rIpqKtsRSsmWga>^#W%RaLzuwsf9rZj5#*(%CbOWBHNE0L}e)F=)W6{pld#>kfu zO1GG`FICoLwbx)Z6Ug*~0|*?h4KoRdg6ha9vVVbHz}ha3Ij3A1!fl4xcHa zeaJpjJP(H}6PL+a4ThP7r_1q3!srSJBEpM^{+V6_LSCC?{fl2v2vf4v^o@S z$l-6u(Y0%|a;#x-eqgASn7QyF2?G&)R3-rhzUy>wQ(S!3nbeKSBS+3EKG6ex3MCYu^2uh6o(h z<{+qt1o6Q}8iX)?L?Z;J9hW#Yo2?`l%;qnnsKYfBoeUI#RI^LoT_L8z?Z^WPd8!Tf zjtgMV{&LuQ0nWpf)1~k)RD>|Pb>YM3P98fkbL+xY_}?(>kSwkvxo0V6Vq6I)%S8Sk Lf>1$nsS*GH)B7ad literal 1581 zcmV+|2GaRKRzV%)F3bAg}CQS$Xqm;vb6$00000000y1 zR!NN9L=^Qzkur*q*bm$)MnevX+uc1|&!pR8mP{5ViwGeIiJ-DwGp=d7%2O^+PbWkm z1YB4mgp>mkiMVk@AWjIxg)1TwH-wNl!3j>`gv771+r6Y`2}3yHgI)gh|NC40|BD%h zvETT9^zqMc|8Vts<+Gpc^slwYMhx}bJYX2%3!l998#wQt{e^NBm}Egc%s)E^%*jI}>Ue?KUH`Re2Ep8w|H1HT;|(bQWH8^%84 zfJPqKZ#=T^`hj{-K|Yq)3MnHEvtlCZH_S^U^ms%p$*py)e}bW+9|r(+Y^tNW`boim+(;1PuOBJ-x6@kHk7WHM&Fej(VCdkm$KsLkWJ!Y86(0vHZM-dah+F!2N-%&FU%#=9Jx${bweUQ&26 zJ~p#xI*J4)fACRmavH)bq)r{9K#-NLc>(sCL@>^ow$AND)Y2;pEEiUQ;~4ZMi4_a( zr=Fx6RJJY5dcv8Ug}PX!x{bkWuy?r8 zt5gQ5s}0uJr_R}hKD$Mm)LsaA>RT7u%%f~oTRIPprm@N~?4W!HJ%ywA7|QmNJ!@5{ z)}qSKoF_QMYmp>P$zyH68Sc`MSP+23bWZY?I${Y3WPwpxMOaIrTuKKelR`>r&*mN9 zP?=UWw7?mxWu|pS@CeltDL7koIy`kdC-l|X-V^f-X}cT?$W6e7^im1I=+IC>`#01? zI8H3etm9C|Tv!qJiB_fPh%%JXk)r<_iI;fOItfi6RE+?RRyW5)syxF!3Of5r{{=?l z81}Mg7Y5k6R0DzRyUM*Xoz?rCkko^tG$*`(Zjj#6pEI3&7v;OE3w*d;7XSxcDobJ8 zu14ohpHHVv=UL*b-glg>hBOIwh>mJ-LJQ~!iEa;hnIv`rb|J=WPhcMFf-MB9iR_fO zZNS#zF4$=druCz3lZ5JIK2>-WrA#%xJp8rAv3WH^I&=v9yI<}y@N<_gU1>twK0)Ql z)ZNCd9+@k(`HQDtG@a*KR7xUtC$#2yxF$_!341VccoUrvJdFoE@0-p)8}%3lq8H*M zX_y|A3tE8J87c%9rc+NKdY#=B=v53RmFaX=r8OvK#nR8HVtF=&Q7C%AtkqO`k_>?M zFeovm#Z0H#!OcI~vRq^hFgCDIGiHr=5;f4_BKL=nftQLIB*C!(Z=W9R)7`|9Y+61| z;t;n7?9zL~XmGudK@`H4S^xuyFoU8@fFO7a-qi8xHoWT*cN(zbnil6Y>O{pVDOT&n zN)#)ZuQJpmjWreLRHkASsR-p;+&Pjf>#(|8u-X}9{=p0a2eX+oL>Pn)+FQefkp$Nz zO|>^I9SRQu9Y@K!kXP~LDmsGP%hhXexC(KVtZp#uEIdPwM;69FLJ$!a6k7rHeZm^1 z6e$@9In1e4!lg^LLnzPeA~stt)utvY<>{H?A<;2&s4gv!TrMS#24O0t@?>ptq6&hGCMLF2;NoP^<_Io(NO@187QJCYnnR=^DNKT!=qijek^5Jj z?t5xms*ePLqu995N_riNcjSn6dI@pdib+@IV1#?!oea>3rrAlQS_6FlK*~6bJiiZ|qwKTnT z)zK^J{w-kcN(+9-6jJYT6iFpJG+6o0VB_EY=ibi#z_az)cPTSfXT7gVb~r)q|0n3b zI6*sq`mYmT7@fOc#}J8=<}w8Jlq3<@NLdWiN48^d+6#!+bopj>!R-85RTHkE=pxeu f;un{^dqT{G`;o^r@q_