diff --git a/.gitignore b/.gitignore index 3933cc672..c8a8ce14e 100755 --- a/.gitignore +++ b/.gitignore @@ -32,4 +32,7 @@ INFO.md sync_staging.sh *.swp _vieux/ -README.md \ No newline at end of file +_mydocs +.DS_Store +Assets/DownloadBadges*.psd +node_modules \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..9920f0ee1 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,49 @@ +rvm: 2.3.3 + +matrix: + include: + - os: osx + osx_image: xcode9.0 + language: node_js + node_js: "8" + env: + - ELECTRON_CACHE=$HOME/.cache/electron + - ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder + + - os: linux + sudo: required + dist: trusty + language: node_js + node_js: "8" + env: + - ELECTRON_CACHE=$HOME/.cache/electron + - ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder + +# cache: +# directories: +# - node_modules +# - $HOME/.cache/electron +# - $HOME/.cache/electron-builder + +before_install: + # HOMEBREW_NO_AUTO_UPDATE needed so that Homebrew doesn't upgrade to the next + # version, which requires Ruby 2.3, which is not available on the Travis VM. + + # Silence apt-get update errors (for example when a module doesn't exist) since + # otherwise it will make the whole build fails, even though all we need is yarn. + - | + if [ "$TRAVIS_OS_NAME" == "osx" ]; then + HOMEBREW_NO_AUTO_UPDATE=1 brew install yarn + else + curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - + echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list + sudo apt-get update || true + sudo apt-get install -y yarn + fi + +script: + - | + cd ElectronClient/app + rsync -aP ../../ReactNativeClient/lib/ lib/ + npm install + yarn dist diff --git a/Assets/All.psd b/Assets/All.psd new file mode 100644 index 000000000..ec95fbca7 Binary files /dev/null and b/Assets/All.psd differ diff --git a/Assets/AndroidFeatureGraphic.psd b/Assets/AndroidFeatureGraphic.psd index ea1cafe4d..af7159611 100644 Binary files a/Assets/AndroidFeatureGraphic.psd and b/Assets/AndroidFeatureGraphic.psd differ diff --git a/Assets/DemoDesktop.PNG b/Assets/DemoDesktop.PNG new file mode 100644 index 000000000..430214629 Binary files /dev/null and b/Assets/DemoDesktop.PNG differ diff --git a/Assets/DemoDesktop.psd b/Assets/DemoDesktop.psd new file mode 100644 index 000000000..25b319c29 Binary files /dev/null and b/Assets/DemoDesktop.psd differ diff --git a/Assets/Icon-Android-1024.png b/Assets/Icon-Android-1024.png new file mode 100644 index 000000000..b7000171f Binary files /dev/null and b/Assets/Icon-Android-1024.png differ diff --git a/Assets/Icon-Android-512.png b/Assets/Icon-Android-512.png new file mode 100644 index 000000000..d4bb73df9 Binary files /dev/null and b/Assets/Icon-Android-512.png differ diff --git a/Assets/Icon-Android.psd b/Assets/Icon-Android.psd new file mode 100644 index 000000000..e428042fd Binary files /dev/null and b/Assets/Icon-Android.psd differ diff --git a/Assets/Icon-ios-512.png b/Assets/Icon-ios-512.png new file mode 100644 index 000000000..c58ac4d77 Binary files /dev/null and b/Assets/Icon-ios-512.png differ diff --git a/Assets/Icon-ios.psd b/Assets/Icon-ios.psd new file mode 100644 index 000000000..7ebfd82b6 Binary files /dev/null and b/Assets/Icon-ios.psd differ diff --git a/Assets/Joplin.ico b/Assets/Joplin.ico new file mode 100644 index 000000000..a5e1174e2 Binary files /dev/null and b/Assets/Joplin.ico differ diff --git a/Assets/Laptop-Terminal.psd b/Assets/Laptop-Terminal.psd new file mode 100644 index 000000000..d85196026 Binary files /dev/null and b/Assets/Laptop-Terminal.psd differ diff --git a/Assets/LinuxIcons/1024x1024.png b/Assets/LinuxIcons/1024x1024.png new file mode 100644 index 000000000..fef719ed7 Binary files /dev/null and b/Assets/LinuxIcons/1024x1024.png differ diff --git a/Assets/LinuxIcons/128x128.png b/Assets/LinuxIcons/128x128.png new file mode 100644 index 000000000..2e25758b6 Binary files /dev/null and b/Assets/LinuxIcons/128x128.png differ diff --git a/Assets/LinuxIcons/144x144.png b/Assets/LinuxIcons/144x144.png new file mode 100644 index 000000000..252c16948 Binary files /dev/null and b/Assets/LinuxIcons/144x144.png differ diff --git a/Assets/LinuxIcons/16x16.png b/Assets/LinuxIcons/16x16.png new file mode 100644 index 000000000..9a4198a76 Binary files /dev/null and b/Assets/LinuxIcons/16x16.png differ diff --git a/Assets/LinuxIcons/24x24.png b/Assets/LinuxIcons/24x24.png new file mode 100644 index 000000000..35525f910 Binary files /dev/null and b/Assets/LinuxIcons/24x24.png differ diff --git a/Assets/LinuxIcons/256x256.png b/Assets/LinuxIcons/256x256.png new file mode 100644 index 000000000..a5e8d9747 Binary files /dev/null and b/Assets/LinuxIcons/256x256.png differ diff --git a/Assets/LinuxIcons/32x32.png b/Assets/LinuxIcons/32x32.png new file mode 100644 index 000000000..679aa6e67 Binary files /dev/null and b/Assets/LinuxIcons/32x32.png differ diff --git a/Assets/LinuxIcons/48x48.png b/Assets/LinuxIcons/48x48.png new file mode 100644 index 000000000..f5ab076ae Binary files /dev/null and b/Assets/LinuxIcons/48x48.png differ diff --git a/Assets/LinuxIcons/512x512.png b/Assets/LinuxIcons/512x512.png new file mode 100644 index 000000000..ef8624663 Binary files /dev/null and b/Assets/LinuxIcons/512x512.png differ diff --git a/Assets/LinuxIcons/72x72.png b/Assets/LinuxIcons/72x72.png new file mode 100644 index 000000000..dbac3fae8 Binary files /dev/null and b/Assets/LinuxIcons/72x72.png differ diff --git a/Assets/LinuxIcons/96x96.png b/Assets/LinuxIcons/96x96.png new file mode 100644 index 000000000..cb1faeb10 Binary files /dev/null and b/Assets/LinuxIcons/96x96.png differ diff --git a/Assets/Screenshot_1501238944.png b/Assets/Screenshots/Screenshot_1501238944.png similarity index 100% rename from Assets/Screenshot_1501238944.png rename to Assets/Screenshots/Screenshot_1501238944.png diff --git a/Assets/Screenshot_1501239078.png b/Assets/Screenshots/Screenshot_1501239078.png similarity index 100% rename from Assets/Screenshot_1501239078.png rename to Assets/Screenshots/Screenshot_1501239078.png diff --git a/Assets/Screenshots/Screenshot_1511192771.png b/Assets/Screenshots/Screenshot_1511192771.png new file mode 100644 index 000000000..1cce72824 Binary files /dev/null and b/Assets/Screenshots/Screenshot_1511192771.png differ diff --git a/Assets/Screenshots/Screenshot_1511192805.png b/Assets/Screenshots/Screenshot_1511192805.png new file mode 100644 index 000000000..6c8d467f1 Binary files /dev/null and b/Assets/Screenshots/Screenshot_1511192805.png differ diff --git a/Assets/Screenshots/Screenshot_1511193130.png b/Assets/Screenshots/Screenshot_1511193130.png new file mode 100644 index 000000000..e2eff7807 Binary files /dev/null and b/Assets/Screenshots/Screenshot_1511193130.png differ diff --git a/Assets/Screenshots/Screenshot_1511193142.png b/Assets/Screenshots/Screenshot_1511193142.png new file mode 100644 index 000000000..962ece093 Binary files /dev/null and b/Assets/Screenshots/Screenshot_1511193142.png differ diff --git a/Assets/Screenshots/Screenshot_1511193169.png b/Assets/Screenshots/Screenshot_1511193169.png new file mode 100644 index 000000000..718f650d0 Binary files /dev/null and b/Assets/Screenshots/Screenshot_1511193169.png differ diff --git a/Assets/Screenshots/Screenshot_1511193181.png b/Assets/Screenshots/Screenshot_1511193181.png new file mode 100644 index 000000000..6601b0726 Binary files /dev/null and b/Assets/Screenshots/Screenshot_1511193181.png differ diff --git a/Assets/Screenshots/Screenshot_1511193188.png b/Assets/Screenshots/Screenshot_1511193188.png new file mode 100644 index 000000000..37b00c184 Binary files /dev/null and b/Assets/Screenshots/Screenshot_1511193188.png differ diff --git a/Assets/Screenshots/Screenshot_1511193192.png b/Assets/Screenshots/Screenshot_1511193192.png new file mode 100644 index 000000000..8e4435bed Binary files /dev/null and b/Assets/Screenshots/Screenshot_1511193192.png differ diff --git a/Assets/Screenshots/iOS/Screenshot_iPad_Paysage.jpg b/Assets/Screenshots/iOS/Screenshot_iPad_Paysage.jpg new file mode 100644 index 000000000..b5f8e5ba5 Binary files /dev/null and b/Assets/Screenshots/iOS/Screenshot_iPad_Paysage.jpg differ diff --git a/Assets/Screenshots/iOS/Screenshot_iPad_Paysage.png b/Assets/Screenshots/iOS/Screenshot_iPad_Paysage.png new file mode 100644 index 000000000..113d33ddc Binary files /dev/null and b/Assets/Screenshots/iOS/Screenshot_iPad_Paysage.png differ diff --git a/Assets/Screenshots/iOS/Screenshot_iPad_Paysage.psd b/Assets/Screenshots/iOS/Screenshot_iPad_Paysage.psd new file mode 100644 index 000000000..d1fa17299 Binary files /dev/null and b/Assets/Screenshots/iOS/Screenshot_iPad_Paysage.psd differ diff --git a/Assets/Screenshots/iOS/Screenshot_iPhone_Portrait.jpg b/Assets/Screenshots/iOS/Screenshot_iPhone_Portrait.jpg new file mode 100644 index 000000000..f0cdef462 Binary files /dev/null and b/Assets/Screenshots/iOS/Screenshot_iPhone_Portrait.jpg differ diff --git a/Assets/Screenshots/iOS/Screenshot_iPhone_Portrait.png b/Assets/Screenshots/iOS/Screenshot_iPhone_Portrait.png new file mode 100644 index 000000000..11e5fe900 Binary files /dev/null and b/Assets/Screenshots/iOS/Screenshot_iPhone_Portrait.png differ diff --git a/Assets/Screenshots/iOS/Screenshot_iPhone_Portrait.psd b/Assets/Screenshots/iOS/Screenshot_iPhone_Portrait.psd new file mode 100644 index 000000000..a3fac7617 Binary files /dev/null and b/Assets/Screenshots/iOS/Screenshot_iPhone_Portrait.psd differ diff --git a/Assets/Tablet.psd b/Assets/Tablet.psd new file mode 100644 index 000000000..c98c3bf64 Binary files /dev/null and b/Assets/Tablet.psd differ diff --git a/Assets/build_mac_icons.sh b/Assets/build_mac_icons.sh new file mode 100644 index 000000000..66423a4c8 --- /dev/null +++ b/Assets/build_mac_icons.sh @@ -0,0 +1,2 @@ +#!/bin/bash +iconutil --convert icns macOs.iconset diff --git a/Assets/check-square-o.svg b/Assets/check-square-o.svg new file mode 100644 index 000000000..0d07b95e3 --- /dev/null +++ b/Assets/check-square-o.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Assets/check-square.svg b/Assets/check-square.svg new file mode 100644 index 000000000..6da396e48 --- /dev/null +++ b/Assets/check-square.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/Assets/iOSIcons/29.png b/Assets/iOSIcons/29.png new file mode 100644 index 000000000..f8628bfb5 Binary files /dev/null and b/Assets/iOSIcons/29.png differ diff --git a/Assets/iOSIcons/29x2.png b/Assets/iOSIcons/29x2.png new file mode 100644 index 000000000..d34b917b5 Binary files /dev/null and b/Assets/iOSIcons/29x2.png differ diff --git a/Assets/iOSIcons/29x3.png b/Assets/iOSIcons/29x3.png new file mode 100644 index 000000000..aeab7a85e Binary files /dev/null and b/Assets/iOSIcons/29x3.png differ diff --git a/Assets/iOSIcons/40.png b/Assets/iOSIcons/40.png new file mode 100644 index 000000000..bfe70299d Binary files /dev/null and b/Assets/iOSIcons/40.png differ diff --git a/Assets/iOSIcons/40x2.png b/Assets/iOSIcons/40x2.png new file mode 100644 index 000000000..71cf519a3 Binary files /dev/null and b/Assets/iOSIcons/40x2.png differ diff --git a/Assets/iOSIcons/40x3.png b/Assets/iOSIcons/40x3.png new file mode 100644 index 000000000..2600f4728 Binary files /dev/null and b/Assets/iOSIcons/40x3.png differ diff --git a/Assets/iOSIcons/57.png b/Assets/iOSIcons/57.png new file mode 100644 index 000000000..2597249bf Binary files /dev/null and b/Assets/iOSIcons/57.png differ diff --git a/Assets/iOSIcons/57x2.png b/Assets/iOSIcons/57x2.png new file mode 100644 index 000000000..ca8a919ae Binary files /dev/null and b/Assets/iOSIcons/57x2.png differ diff --git a/Assets/iOSIcons/60x2.png b/Assets/iOSIcons/60x2.png new file mode 100644 index 000000000..2600f4728 Binary files /dev/null and b/Assets/iOSIcons/60x2.png differ diff --git a/Assets/iOSIcons/60x3.png b/Assets/iOSIcons/60x3.png new file mode 100644 index 000000000..bc86493cd Binary files /dev/null and b/Assets/iOSIcons/60x3.png differ diff --git a/Assets/iOSIcons/AppStore.png b/Assets/iOSIcons/AppStore.png new file mode 100644 index 000000000..53fe37dda Binary files /dev/null and b/Assets/iOSIcons/AppStore.png differ diff --git a/Assets/macOs.icns b/Assets/macOs.icns new file mode 100644 index 000000000..c1a73076d Binary files /dev/null and b/Assets/macOs.icns differ diff --git a/Assets/macOs.iconset/icon_1024x1024.png b/Assets/macOs.iconset/icon_1024x1024.png new file mode 100644 index 000000000..fef719ed7 Binary files /dev/null and b/Assets/macOs.iconset/icon_1024x1024.png differ diff --git a/Assets/macOs.iconset/icon_128x128.png b/Assets/macOs.iconset/icon_128x128.png new file mode 100644 index 000000000..2e25758b6 Binary files /dev/null and b/Assets/macOs.iconset/icon_128x128.png differ diff --git a/Assets/macOs.iconset/icon_16x16.png b/Assets/macOs.iconset/icon_16x16.png new file mode 100644 index 000000000..9a4198a76 Binary files /dev/null and b/Assets/macOs.iconset/icon_16x16.png differ diff --git a/Assets/macOs.iconset/icon_256x256.png b/Assets/macOs.iconset/icon_256x256.png new file mode 100644 index 000000000..a5e8d9747 Binary files /dev/null and b/Assets/macOs.iconset/icon_256x256.png differ diff --git a/Assets/macOs.iconset/icon_32x32.png b/Assets/macOs.iconset/icon_32x32.png new file mode 100644 index 000000000..679aa6e67 Binary files /dev/null and b/Assets/macOs.iconset/icon_32x32.png differ diff --git a/Assets/macOs.iconset/icon_512x512.png b/Assets/macOs.iconset/icon_512x512.png new file mode 100644 index 000000000..ef8624663 Binary files /dev/null and b/Assets/macOs.iconset/icon_512x512.png differ diff --git a/Assets/square-o.svg b/Assets/square-o.svg new file mode 100644 index 000000000..9d9aee6d3 --- /dev/null +++ b/Assets/square-o.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/CliClient/.babelrc b/CliClient/.babelrc deleted file mode 100644 index 69163caed..000000000 --- a/CliClient/.babelrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "presets": ["env", "react"], - "plugins": ["syntax-async-functions","transform-runtime"] -} \ No newline at end of file diff --git a/CliClient/.gitignore b/CliClient/.gitignore index faab3d6fa..540f2f47c 100644 --- a/CliClient/.gitignore +++ b/CliClient/.gitignore @@ -16,4 +16,6 @@ tests/cli-integration/ *.mo *.*~ tests/sync -out.txt \ No newline at end of file +out.txt +linkToLocal.sh +yarn-error.log \ No newline at end of file diff --git a/CliClient/app/ResourceServer.js b/CliClient/app/ResourceServer.js new file mode 100644 index 000000000..cdeecc617 --- /dev/null +++ b/CliClient/app/ResourceServer.js @@ -0,0 +1,97 @@ +const { _ } = require('lib/locale.js'); +const { Logger } = require('lib/logger.js'); +const { Resource } = require('lib/models/resource.js'); +const { netUtils } = require('lib/net-utils.js'); + +const http = require("http"); +const urlParser = require("url"); +const enableServerDestroy = require('server-destroy'); + +class ResourceServer { + + constructor() { + this.server_ = null; + this.logger_ = new Logger(); + this.port_ = null; + this.linkHandler_ = null; + this.started_ = false; + } + + setLogger(logger) { + this.logger_ = logger; + } + + logger() { + return this.logger_; + } + + started() { + return this.started_; + } + + baseUrl() { + if (!this.port_) return ''; + return 'http://127.0.0.1:' + this.port_; + } + + setLinkHandler(handler) { + this.linkHandler_ = handler; + } + + async start() { + this.port_ = await netUtils.findAvailablePort([9167, 9267, 8167, 8267]); + if (!this.port_) { + this.logger().error('Could not find available port to start resource server. Please report the error at https://github.com/laurent22/joplin'); + return; + } + + this.server_ = http.createServer(); + + this.server_.on('request', async (request, response) => { + + const writeResponse = (message) => { + response.write(message); + response.end(); + } + + const url = urlParser.parse(request.url, true); + let resourceId = url.pathname.split('/'); + if (resourceId.length < 2) { + writeResponse('Error: could not get resource ID from path name: ' + url.pathname); + return; + } + resourceId = resourceId[1]; + + if (!this.linkHandler_) throw new Error('No link handler is defined'); + + try { + const done = await this.linkHandler_(resourceId, response); + if (!done) throw new Error('Unhandled resource: ' + resourceId); + } catch (error) { + response.setHeader('Content-Type', 'text/plain'); + response.statusCode = 400; + response.write(error.message); + } + + response.end(); + }); + + this.server_.on('error', (error) => { + this.logger().error('Resource server:', error); + }); + + this.server_.listen(this.port_); + + enableServerDestroy(this.server_); + + this.started_ = true; + } + + stop() { + if (this.server_) this.server_.destroy(); + this.server_ = null; + } + +} + +module.exports = ResourceServer; \ No newline at end of file diff --git a/CliClient/app/app-gui.js b/CliClient/app/app-gui.js new file mode 100644 index 000000000..c839f297e --- /dev/null +++ b/CliClient/app/app-gui.js @@ -0,0 +1,819 @@ +const { Logger } = require('lib/logger.js'); +const { Folder } = require('lib/models/folder.js'); +const { Tag } = require('lib/models/tag.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Note } = require('lib/models/note.js'); +const { Resource } = require('lib/models/resource.js'); +const { cliUtils } = require('./cli-utils.js'); +const { reducer, defaultState } = require('lib/reducer.js'); +const { splitCommandString } = require('lib/string-utils.js'); +const { reg } = require('lib/registry.js'); +const { _ } = require('lib/locale.js'); + +const chalk = require('chalk'); +const tk = require('terminal-kit'); +const TermWrapper = require('tkwidgets/framework/TermWrapper.js'); +const Renderer = require('tkwidgets/framework/Renderer.js'); + +const BaseWidget = require('tkwidgets/BaseWidget.js'); +const ListWidget = require('tkwidgets/ListWidget.js'); +const TextWidget = require('tkwidgets/TextWidget.js'); +const HLayoutWidget = require('tkwidgets/HLayoutWidget.js'); +const VLayoutWidget = require('tkwidgets/VLayoutWidget.js'); +const ReduxRootWidget = require('tkwidgets/ReduxRootWidget.js'); +const RootWidget = require('tkwidgets/RootWidget.js'); +const WindowWidget = require('tkwidgets/WindowWidget.js'); + +const NoteWidget = require('./gui/NoteWidget.js'); +const ResourceServer = require('./ResourceServer.js'); +const NoteMetadataWidget = require('./gui/NoteMetadataWidget.js'); +const FolderListWidget = require('./gui/FolderListWidget.js'); +const NoteListWidget = require('./gui/NoteListWidget.js'); +const StatusBarWidget = require('./gui/StatusBarWidget.js'); +const ConsoleWidget = require('./gui/ConsoleWidget.js'); + +class AppGui { + + constructor(app, store) { + this.app_ = app; + this.store_ = store; + + BaseWidget.setLogger(app.logger()); + + this.term_ = new TermWrapper(tk.terminal); + + this.renderer_ = null; + this.logger_ = new Logger(); + this.buildUi(); + + this.renderer_ = new Renderer(this.term(), this.rootWidget_); + + this.app_.on('modelAction', async (event) => { + await this.handleModelAction(event.action); + }); + + this.shortcuts_ = this.setupShortcuts(); + + this.inputMode_ = AppGui.INPUT_MODE_NORMAL; + + this.commandCancelCalled_ = false; + + this.currentShortcutKeys_ = []; + this.lastShortcutKeyTime_ = 0; + + // Recurrent sync is setup only when the GUI is started. In + // a regular command it's not necessary since the process + // exits right away. + reg.setupRecurrentSync(); + } + + store() { + return this.store_; + } + + renderer() { + return this.renderer_; + } + + async forceRender() { + this.widget('root').invalidate(); + await this.renderer_.renderRoot(); + } + + prompt(initialText = '', promptString = ':') { + return this.widget('statusBar').prompt(initialText, promptString); + } + + stdoutMaxWidth() { + return this.widget('console').innerWidth - 1; + } + + isDummy() { + return false; + } + + buildUi() { + this.rootWidget_ = new ReduxRootWidget(this.store_); + this.rootWidget_.name = 'root'; + + const folderList = new FolderListWidget(); + folderList.style = { + borderBottomWidth: 1, + borderRightWidth: 1, + }; + folderList.name = 'folderList'; + folderList.vStretch = true; + folderList.on('currentItemChange', async (event) => { + const item = folderList.currentItem; + + if (item === '-') { + let newIndex = event.currentIndex + (event.previousIndex < event.currentIndex ? +1 : -1); + let nextItem = folderList.itemAt(newIndex); + if (!nextItem) nextItem = folderList.itemAt(event.previousIndex); + + if (!nextItem) return; // Normally not possible + + let actionType = 'FOLDER_SELECT'; + if (nextItem.type_ === BaseModel.TYPE_TAG) actionType = 'TAG_SELECT'; + if (nextItem.type_ === BaseModel.TYPE_SEARCH) actionType = 'SEARCH_SELECT'; + + this.store_.dispatch({ + type: actionType, + id: nextItem.id, + }); + } else if (item.type_ === Folder.modelType()) { + this.store_.dispatch({ + type: 'FOLDER_SELECT', + id: item ? item.id : null, + }); + } else if (item.type_ === Tag.modelType()) { + this.store_.dispatch({ + type: 'TAG_SELECT', + id: item ? item.id : null, + }); + } else if (item.type_ === BaseModel.TYPE_SEARCH) { + this.store_.dispatch({ + type: 'SEARCH_SELECT', + id: item ? item.id : null, + }); + } + }); + this.rootWidget_.connect(folderList, (state) => { + return { + selectedFolderId: state.selectedFolderId, + selectedTagId: state.selectedTagId, + selectedSearchId: state.selectedSearchId, + notesParentType: state.notesParentType, + folders: state.folders, + tags: state.tags, + searches: state.searches, + }; + }); + + const noteList = new NoteListWidget(); + noteList.name = 'noteList'; + noteList.vStretch = true; + noteList.style = { + borderBottomWidth: 1, + borderLeftWidth: 1, + borderRightWidth: 1, + }; + noteList.on('currentItemChange', async () => { + let note = noteList.currentItem; + this.store_.dispatch({ + type: 'NOTE_SELECT', + id: note ? note.id : null, + }); + }); + this.rootWidget_.connect(noteList, (state) => { + return { + selectedNoteId: state.selectedNoteIds.length ? state.selectedNoteIds[0] : null, + items: state.notes, + }; + }); + + const noteText = new NoteWidget(); + noteText.hStretch = true; + noteText.name = 'noteText'; + noteText.style = { + borderBottomWidth: 1, + borderLeftWidth: 1, + }; + this.rootWidget_.connect(noteText, (state) => { + return { + noteId: state.selectedNoteIds.length ? state.selectedNoteIds[0] : null, + notes: state.notes, + }; + }); + + const noteMetadata = new NoteMetadataWidget(); + noteMetadata.hStretch = true; + noteMetadata.name = 'noteMetadata'; + noteMetadata.style = { + borderBottomWidth: 1, + borderLeftWidth: 1, + borderRightWidth: 1, + }; + this.rootWidget_.connect(noteMetadata, (state) => { + return { noteId: state.selectedNoteIds.length ? state.selectedNoteIds[0] : null }; + }); + noteMetadata.hide(); + + const consoleWidget = new ConsoleWidget(); + consoleWidget.hStretch = true; + consoleWidget.style = { + borderBottomWidth: 1, + }; + consoleWidget.hide(); + + const statusBar = new StatusBarWidget(); + statusBar.hStretch = true; + + const noteLayout = new VLayoutWidget(); + noteLayout.name = 'noteLayout'; + noteLayout.addChild(noteText, { type: 'stretch', factor: 1 }); + noteLayout.addChild(noteMetadata, { type: 'stretch', factor: 1 }); + + const hLayout = new HLayoutWidget(); + hLayout.name = 'hLayout'; + hLayout.addChild(folderList, { type: 'stretch', factor: 1 }); + hLayout.addChild(noteList, { type: 'stretch', factor: 1 }); + hLayout.addChild(noteLayout, { type: 'stretch', factor: 2 }); + + const vLayout = new VLayoutWidget(); + vLayout.name = 'vLayout'; + vLayout.addChild(hLayout, { type: 'stretch', factor: 2 }); + vLayout.addChild(consoleWidget, { type: 'stretch', factor: 1 }); + vLayout.addChild(statusBar, { type: 'fixed', factor: 1 }); + + const win1 = new WindowWidget(); + win1.addChild(vLayout); + win1.name = 'mainWindow'; + + this.rootWidget_.addChild(win1); + } + + showModalOverlay(text) { + if (!this.widget('overlayWindow')) { + const textWidget = new TextWidget(); + textWidget.hStretch = true; + textWidget.vStretch = true; + textWidget.text = 'testing'; + textWidget.name = 'overlayText'; + + const win = new WindowWidget(); + win.name = 'overlayWindow'; + win.addChild(textWidget); + + this.rootWidget_.addChild(win); + } + + this.widget('overlayWindow').activate(); + this.widget('overlayText').text = text; + } + + hideModalOverlay() { + if (this.widget('overlayWindow')) this.widget('overlayWindow').hide(); + this.widget('mainWindow').activate(); + } + + addCommandToConsole(cmd) { + if (!cmd) return; + this.stdout(chalk.cyan.bold('> ' + cmd)); + } + + setupShortcuts() { + const shortcuts = {}; + + shortcuts['TAB'] = { + friendlyName: 'Tab', + description: () => _('Give focus to next pane'), + isDocOnly: true, + } + + shortcuts['SHIFT_TAB'] = { + friendlyName: 'Shift+Tab', + description: () => _('Give focus to previous pane'), + isDocOnly: true, + } + + shortcuts[':'] = { + description: () => _('Enter command line mode'), + action: async () => { + const cmd = await this.widget('statusBar').prompt(); + if (!cmd) return; + this.addCommandToConsole(cmd); + await this.processCommand(cmd); + }, + }; + + shortcuts['ESC'] = { // Built into terminal-kit inputField + description: () => _('Exit command line mode'), + isDocOnly: true, + }; + + shortcuts['ENTER'] = { + description: () => _('Edit the selected note'), + action: () => { + const w = this.widget('mainWindow').focusedWidget; + if (w.name === 'folderList') { + this.widget('noteList').focus(); + } else if (w.name === 'noteList' || w.name === 'noteText') { + this.processCommand('edit $n'); + } + }, + } + + shortcuts['CTRL_C'] = { + description: () => _('Cancel the current command.'), + friendlyName: 'Ctrl+C', + isDocOnly: true, + } + + shortcuts['CTRL_D'] = { + description: () => _('Exit the application.'), + friendlyName: 'Ctrl+D', + isDocOnly: true, + } + + shortcuts['DELETE'] = { + description: () => _('Delete the currently selected note or notebook.'), + action: async () => { + if (this.widget('folderList').hasFocus) { + const item = this.widget('folderList').selectedJoplinItem; + if (item.type_ === BaseModel.TYPE_FOLDER) { + await this.processCommand('rmbook ' + item.id); + } else if (item.type_ === BaseModel.TYPE_TAG) { + this.stdout(_('To delete a tag, untag the associated notes.')); + } else if (item.type_ === BaseModel.TYPE_SEARCH) { + this.store().dispatch({ + type: 'SEARCH_DELETE', + id: item.id, + }); + } + } else if (this.widget('noteList').hasFocus) { + await this.processCommand('rmnote $n'); + } else { + this.stdout(_('Please select the note or notebook to be deleted first.')); + } + } + }; + + shortcuts[' '] = { + friendlyName: 'SPACE', + description: () => _('Set a to-do as completed / not completed'), + action: 'todo toggle $n', + } + + shortcuts['tc'] = { + description: () => _('[t]oggle [c]onsole between maximized/minimized/hidden/visible.'), + action: () => { + if (!this.consoleIsShown()) { + this.showConsole(); + this.minimizeConsole(); + } else { + if (this.consoleIsMaximized()) { + this.hideConsole(); + } else { + this.maximizeConsole(); + } + } + }, + canRunAlongOtherCommands: true, + } + + shortcuts['/'] = { + description: () => _('Search'), + action: { type: 'prompt', initialText: 'search ""', cursorPosition: -2 }, + }; + + shortcuts['tm'] = { + description: () => _('[t]oggle note [m]etadata.'), + action: () => { + this.toggleNoteMetadata(); + }, + canRunAlongOtherCommands: true, + } + + shortcuts['mn'] = { + description: () => _('[M]ake a new [n]ote'), + action: { type: 'prompt', initialText: 'mknote ""', cursorPosition: -2 }, + } + + shortcuts['mt'] = { + description: () => _('[M]ake a new [t]odo'), + action: { type: 'prompt', initialText: 'mktodo ""', cursorPosition: -2 }, + } + + shortcuts['mb'] = { + description: () => _('[M]ake a new note[b]ook'), + action: { type: 'prompt', initialText: 'mkbook ""', cursorPosition: -2 }, + } + + shortcuts['yn'] = { + description: () => _('Copy ([Y]ank) the [n]ote to a notebook.'), + action: { type: 'prompt', initialText: 'cp $n ""', cursorPosition: -2 }, + } + + shortcuts['dn'] = { + description: () => _('Move the note to a notebook.'), + action: { type: 'prompt', initialText: 'mv $n ""', cursorPosition: -2 }, + } + + return shortcuts; + } + + toggleConsole() { + this.showConsole(!this.consoleIsShown()); + } + + showConsole(doShow = true) { + this.widget('console').show(doShow); + } + + hideConsole() { + this.showConsole(false); + } + + consoleIsShown() { + return this.widget('console').shown; + } + + maximizeConsole(doMaximize = true) { + const consoleWidget = this.widget('console'); + + if (consoleWidget.isMaximized__ === undefined) { + consoleWidget.isMaximized__ = false; + } + + if (consoleWidget.isMaximized__ === doMaximize) return; + + let constraints = { + type: 'stretch', + factor: !doMaximize ? 1 : 4, + }; + + consoleWidget.isMaximized__ = doMaximize; + + this.widget('vLayout').setWidgetConstraints(consoleWidget, constraints); + } + + minimizeConsole() { + this.maximizeConsole(false); + } + + consoleIsMaximized() { + return this.widget('console').isMaximized__ === true; + } + + showNoteMetadata(show = true) { + this.widget('noteMetadata').show(show); + } + + hideNoteMetadata() { + this.showNoteMetadata(false); + } + + toggleNoteMetadata() { + this.showNoteMetadata(!this.widget('noteMetadata').shown); + } + + widget(name) { + if (name === 'root') return this.rootWidget_; + return this.rootWidget_.childByName(name); + } + + app() { + return this.app_; + } + + setLogger(l) { + this.logger_ = l; + } + + logger() { + return this.logger_; + } + + shortcuts() { + return this.shortcuts_; + } + + term() { + return this.term_; + } + + activeListItem() { + const widget = this.widget('mainWindow').focusedWidget; + if (!widget) return null; + + if (widget.name == 'noteList' || widget.name == 'folderList') { + return widget.currentItem; + } + + return null; + } + + async handleModelAction(action) { + this.logger().info('Action:', action); + + let state = Object.assign({}, defaultState); + state.notes = this.widget('noteList').items; + + let newState = reducer(state, action); + + if (newState !== state) { + this.widget('noteList').items = newState.notes; + } + } + + async processCommand(cmd) { + if (!cmd) return; + cmd = cmd.trim(); + if (!cmd.length) return; + + this.logger().info('Got command: ' + cmd); + + if (cmd === 'q' || cmd === 'wq' || cmd === 'qa') { // Vim bonus + await this.app().exit(); + return; + } + + let note = this.widget('noteList').currentItem; + let folder = this.widget('folderList').currentItem; + let args = splitCommandString(cmd); + + for (let i = 0; i < args.length; i++) { + if (args[i] == '$n') { + args[i] = note ? note.id : ''; + } else if (args[i] == '$b') { + args[i] = folder ? folder.id : ''; + } else if (args[i] == '$c') { + const item = this.activeListItem(); + args[i] = item ? item.id : ''; + } + } + + try { + await this.app().execCommand(args); + } catch (error) { + this.stdout(error.message); + } + + this.widget('console').scrollBottom(); + } + + async updateFolderList() { + const folders = await Folder.all(); + this.widget('folderList').items = folders; + } + + async updateNoteList(folderId) { + const fields = Note.previewFields(); + fields.splice(fields.indexOf('body'), 1); + const notes = folderId ? await Note.previews(folderId, { fields: fields }) : []; + this.widget('noteList').items = notes; + } + + async updateNoteText(note) { + const text = note ? note.body : ''; + this.widget('noteText').text = text; + } + + // Any key after which a shortcut is not possible. + isSpecialKey(name) { + return [':', 'ENTER', 'DOWN', 'UP', 'LEFT', 'RIGHT', 'DELETE', 'BACKSPACE', 'ESCAPE', 'TAB', 'SHIFT_TAB', 'PAGE_UP', 'PAGE_DOWN'].indexOf(name) >= 0; + } + + fullScreen(enable = true) { + if (enable) { + this.term().fullscreen(); + this.term().hideCursor(); + this.widget('root').invalidate(); + } else { + this.term().fullscreen(false); + this.term().showCursor(); + } + } + + stdout(text) { + if (text === null || text === undefined) return; + + let lines = text.split('\n'); + for (let i = 0; i < lines.length; i++) { + const v = typeof lines[i] === 'object' ? JSON.stringify(lines[i]) : lines[i]; + this.widget('console').addLine(v); + } + + this.updateStatusBarMessage(); + } + + exit() { + this.fullScreen(false); + this.resourceServer_.stop(); + } + + updateStatusBarMessage() { + const consoleWidget = this.widget('console'); + + let msg = ''; + + const text = consoleWidget.lastLine; + + const cmd = this.app().currentCommand(); + if (cmd) { + msg += cmd.name(); + if (cmd.cancellable()) msg += ' [Press Ctrl+C to cancel]'; + msg += ': '; + } + + if (text && text.length) { + msg += text; + } + + if (msg !== '') this.widget('statusBar').setItemAt(0, msg); + } + + async setupResourceServer() { + const linkStyle = chalk.blue.underline; + const noteTextWidget = this.widget('noteText'); + const resourceIdRegex = /^:\/[a-f0-9]+$/i + const noteLinks = {}; + + const hasProtocol = function(s, protocols) { + if (!s) return false; + s = s.trim().toLowerCase(); + for (let i = 0; i < protocols.length; i++) { + if (s.indexOf(protocols[i] + '://') === 0) return true; + } + return false; + } + + // By default, before the server is started, only the regular + // URLs appear in blue. + noteTextWidget.markdownRendererOptions = { + linkUrlRenderer: (index, url) => { + if (!url) return url; + + if (resourceIdRegex.test(url)) { + return url; + } else if (hasProtocol(url, ['http', 'https'])) { + return linkStyle(url); + } else { + return url; + } + }, + }; + + this.resourceServer_ = new ResourceServer(); + this.resourceServer_.setLogger(this.app().logger()); + this.resourceServer_.setLinkHandler(async (path, response) => { + const link = noteLinks[path]; + + if (link.type === 'url') { + response.writeHead(302, { 'Location': link.url }); + return true; + } + + if (link.type === 'resource') { + const resourceId = link.id; + let resource = await Resource.load(resourceId); + if (!resource) throw new Error('No resource with ID ' + resourceId); // Should be nearly impossible + if (resource.mime) response.setHeader('Content-Type', resource.mime); + response.write(await Resource.content(resource)); + return true; + } + + return false; + }); + + await this.resourceServer_.start(); + if (!this.resourceServer_.started()) return; + + noteTextWidget.markdownRendererOptions = { + linkUrlRenderer: (index, url) => { + if (!url) return url; + + if (resourceIdRegex.test(url)) { + noteLinks[index] = { + type: 'resource', + id: url.substr(2), + }; + } else if (hasProtocol(url, ['http', 'https', 'file', 'ftp'])) { + noteLinks[index] = { + type: 'url', + url: url, + }; + } else if (url.indexOf('#') === 0) { + return ''; // Anchors aren't supported for now + } else { + return url; + } + + return linkStyle(this.resourceServer_.baseUrl() + '/' + index); + }, + }; + } + + async start() { + const term = this.term(); + + this.fullScreen(); + + try { + this.setupResourceServer(); + + this.renderer_.start(); + + const statusBar = this.widget('statusBar'); + + term.grabInput(); + + term.on('key', async (name, matches, data) => { + + // ------------------------------------------------------------------------- + // Handle special shortcuts + // ------------------------------------------------------------------------- + + if (name === 'CTRL_D') { + const cmd = this.app().currentCommand(); + + if (cmd && cmd.cancellable() && !this.commandCancelCalled_) { + this.commandCancelCalled_ = true; + await cmd.cancel(); + this.commandCancelCalled_ = false; + } + + await this.app().exit(); + return; + } + + if (name === 'CTRL_C' ) { + const cmd = this.app().currentCommand(); + if (!cmd || !cmd.cancellable() || this.commandCancelCalled_) { + this.stdout(_('Press Ctrl+D or type "exit" to exit the application')); + } else { + this.commandCancelCalled_ = true; + await cmd.cancel() + this.commandCancelCalled_ = false; + } + return; + } + + // ------------------------------------------------------------------------- + // Build up current shortcut + // ------------------------------------------------------------------------- + + const now = (new Date()).getTime(); + + if (now - this.lastShortcutKeyTime_ > 800 || this.isSpecialKey(name)) { + this.currentShortcutKeys_ = [name]; + } else { + // If the previous key was a special key (eg. up, down arrow), this new key + // starts a new shortcut. + if (this.currentShortcutKeys_.length && this.isSpecialKey(this.currentShortcutKeys_[0])) { + this.currentShortcutKeys_ = [name]; + } else { + this.currentShortcutKeys_.push(name); + } + } + + this.lastShortcutKeyTime_ = now; + + // ------------------------------------------------------------------------- + // Process shortcut and execute associated command + // ------------------------------------------------------------------------- + + const shortcutKey = this.currentShortcutKeys_.join(''); + const cmd = shortcutKey in this.shortcuts_ ? this.shortcuts_[shortcutKey] : null; + + let processShortcutKeys = !this.app().currentCommand() && cmd; + if (cmd && cmd.canRunAlongOtherCommands) processShortcutKeys = true; + if (statusBar.promptActive) processShortcutKeys = false; + if (cmd && cmd.isDocOnly) processShortcutKeys = false; + + if (processShortcutKeys) { + this.logger().info('Shortcut:', shortcutKey, cmd.description()); + + this.currentShortcutKeys_ = []; + if (typeof cmd.action === 'function') { + await cmd.action(); + } else if (typeof cmd.action === 'object') { + if (cmd.action.type === 'prompt') { + let promptOptions = {}; + if ('cursorPosition' in cmd.action) promptOptions.cursorPosition = cmd.action.cursorPosition; + const commandString = await statusBar.prompt(cmd.action.initialText ? cmd.action.initialText : '', null, promptOptions); + this.addCommandToConsole(commandString); + await this.processCommand(commandString); + } else { + throw new Error('Unknown command: ' + JSON.stringify(cmd.action)); + } + } else { // String + this.stdout(cmd.action); + await this.processCommand(cmd.action); + } + } + + // Optimisation: Update the status bar only + // if the user is not already typing a command: + if (!statusBar.promptActive) this.updateStatusBarMessage(); + }); + } catch (error) { + this.fullScreen(false); + this.logger().error(error); + console.error(error); + } + + process.on('unhandledRejection', (reason, p) => { + this.fullScreen(false); + console.error('Unhandled promise rejection', p, 'reason:', reason); + process.exit(1); + }); + } + +} + +AppGui.INPUT_MODE_NORMAL = 1; +AppGui.INPUT_MODE_META = 2; + +module.exports = AppGui; \ No newline at end of file diff --git a/CliClient/app/app.js b/CliClient/app/app.js index 943cba2cb..f2863c49e 100644 --- a/CliClient/app/app.js +++ b/CliClient/app/app.js @@ -1,52 +1,47 @@ -import { JoplinDatabase } from 'lib/joplin-database.js'; -import { Database } from 'lib/database.js'; -import { DatabaseDriverNode } from 'lib/database-driver-node.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { BaseItem } from 'lib/models/base-item.js'; -import { Note } from 'lib/models/note.js'; -import { Setting } from 'lib/models/setting.js'; -import { Logger } from 'lib/logger.js'; -import { sprintf } from 'sprintf-js'; -import { reg } from 'lib/registry.js'; -import { fileExtension } from 'lib/path-utils.js'; -import { _, setLocale, defaultLocale, closestSupportedLocale } from 'lib/locale.js'; -import os from 'os'; -import fs from 'fs-extra'; -import yargParser from 'yargs-parser'; -import { handleAutocompletion, installAutocompletionFile } from './autocompletion.js'; -import { cliUtils } from './cli-utils.js'; +const { BaseApplication } = require('lib/BaseApplication'); +const { createStore, applyMiddleware } = require('redux'); +const { reducer, defaultState } = require('lib/reducer.js'); +const { JoplinDatabase } = require('lib/joplin-database.js'); +const { Database } = require('lib/database.js'); +const { FoldersScreenUtils } = require('lib/folders-screen-utils.js'); +const { DatabaseDriverNode } = require('lib/database-driver-node.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { BaseItem } = require('lib/models/base-item.js'); +const { Note } = require('lib/models/note.js'); +const { Tag } = require('lib/models/tag.js'); +const { Setting } = require('lib/models/setting.js'); +const { Logger } = require('lib/logger.js'); +const { sprintf } = require('sprintf-js'); +const { reg } = require('lib/registry.js'); +const { fileExtension } = require('lib/path-utils.js'); +const { shim } = require('lib/shim.js'); +const { _, setLocale, defaultLocale, closestSupportedLocale } = require('lib/locale.js'); +const os = require('os'); +const fs = require('fs-extra'); +const { cliUtils } = require('./cli-utils.js'); +const EventEmitter = require('events'); -class Application { +class Application extends BaseApplication { constructor() { + super(); + this.showPromptString_ = true; - this.logger_ = new Logger(); - this.dbLogger_ = new Logger(); - this.autocompletion_ = { active: false }; this.commands_ = {}; this.commandMetadata_ = null; this.activeCommand_ = null; this.allCommandsLoaded_ = false; this.showStackTraces_ = false; + this.gui_ = null; } - currentFolder() { - return this.currentFolder_; + gui() { + return this.gui_; } - async refreshCurrentFolder() { - let newFolder = null; - - if (this.currentFolder_) newFolder = await Folder.load(this.currentFolder_.id); - if (!newFolder) newFolder = await Folder.defaultFolder(); - - this.switchCurrentFolder(newFolder); - } - - switchCurrentFolder(folder) { - this.currentFolder_ = folder; - Setting.setValue('activeFolderId', folder ? folder.id : ''); + commandStdoutMaxWidth() { + return this.gui().stdoutMaxWidth(); } async guessTypeAndLoadItem(pattern, options = null) { @@ -60,10 +55,35 @@ class Application { async loadItem(type, pattern, options = null) { let output = await this.loadItems(type, pattern, options); - return output.length ? output[0] : null; + + if (output.length > 1) { + // output.sort((a, b) => { return a.user_updated_time < b.user_updated_time ? +1 : -1; }); + + // let answers = { 0: _('[Cancel]') }; + // for (let i = 0; i < output.length; i++) { + // answers[i + 1] = output[i].title; + // } + + // Not really useful with new UI? + throw new Error(_('More than one item match "%s". Please narrow down your query.', pattern)); + + // let msg = _('More than one item match "%s". Please select one:', pattern); + // const response = await cliUtils.promptMcq(msg, answers); + // if (!response) return null; + + return output[response - 1]; + } else { + return output.length ? output[0] : null; + } } async loadItems(type, pattern, options = null) { + if (type === 'folderOrNote') { + const folders = await this.loadItems(BaseModel.TYPE_FOLDER, pattern, options); + if (folders.length) return folders; + return await this.loadItems(BaseModel.TYPE_NOTE, pattern, options); + } + pattern = pattern ? pattern.toString() : ''; if (type == BaseModel.TYPE_FOLDER && (pattern == Folder.conflictFolderTitle() || pattern == Folder.conflictFolderId())) return [Folder.conflictFolder()]; @@ -89,150 +109,72 @@ class Application { item = await ItemClass.load(pattern); // Load by id if (item) return [item]; - if (pattern.length >= 4) { - item = await ItemClass.loadByPartialId(pattern); - if (item) return [item]; + if (pattern.length >= 2) { + return await ItemClass.loadByPartialId(pattern); } } return []; } - // Handles the initial flags passed to main script and - // returns the remaining args. - async handleStartFlags_(argv) { - let matched = {}; - argv = argv.slice(0); - argv.splice(0, 2); // First arguments are the node executable, and the node JS file + stdout(text) { + return this.gui().stdout(text); + } - while (argv.length) { - let arg = argv[0]; - let nextArg = argv.length >= 2 ? argv[1] : null; - - if (arg == '--profile') { - if (!nextArg) throw new Error(_('Usage: %s', '--profile ')); - matched.profileDir = nextArg; - argv.splice(0, 2); - continue; - } + setupCommand(cmd) { + cmd.setStdout((text) => { + return this.stdout(text); + }); - if (arg == '--env') { - if (!nextArg) throw new Error(_('Usage: %s', '--env ')); - matched.env = nextArg; - argv.splice(0, 2); - continue; - } - - if (arg == '--update-geolocation-disabled') { - Note.updateGeolocationEnabled_ = false; - argv.splice(0, 1); - continue; - } - - if (arg == '--stack-trace-enabled') { - this.showStackTraces_ = true; - argv.splice(0, 1); - continue; - } - - if (arg == '--log-level') { - if (!nextArg) throw new Error(_('Usage: %s', '--log-level ')); - matched.logLevel = Logger.levelStringToId(nextArg); - argv.splice(0, 2); - continue; - } - - if (arg == '--autocompletion') { - this.autocompletion_.active = true; - argv.splice(0, 1); - continue; - } - - if (arg == '--ac-install') { - this.autocompletion_.install = true; - argv.splice(0, 1); - continue; - } - - if (arg == '--ac-current') { - if (!nextArg) throw new Error(_('Usage: %s', '--ac-current ')); - this.autocompletion_.current = nextArg; - argv.splice(0, 2); - continue; - } - - if (arg == '--ac-line') { - if (!nextArg) throw new Error(_('Usage: %s', '--ac-line ')); - let line = nextArg.replace(/\|__QUOTE__\|/g, '"'); - line = line.replace(/\|__SPACE__\|/g, ' '); - line = line.replace(/\|__OPEN_RB__\|/g, '('); - line = line.replace(/\|__OPEN_CB__\|/g, ')'); - line = line.split('|__SEP__|'); - this.autocompletion_.line = line; - argv.splice(0, 2); - continue; - } - - if (arg.length && arg[0] == '-') { - throw new Error(_('Unknown flag: %s', arg)); + cmd.setDispatcher((action) => { + if (this.store()) { + return this.store().dispatch(action); } else { - break; + return (action) => {}; } - } + }); - if (!matched.logLevel) matched.logLevel = Logger.LEVEL_INFO; - if (!matched.env) matched.env = 'prod'; + cmd.setPrompt(async (message, options) => { + if (!options) options = {}; + if (!options.type) options.type = 'boolean'; + if (!options.booleanAnswerDefault) options.booleanAnswerDefault = 'y'; + if (!options.answers) options.answers = options.booleanAnswerDefault === 'y' ? [_('Y'), _('n')] : [_('N'), _('y')]; - return { - matched: matched, - argv: argv, + if (options.type == 'boolean') { + message += ' (' + options.answers.join('/') + ')'; + } + + let answer = await this.gui().prompt('', message + ' '); + + if (options.type === 'boolean') { + if (answer === null) return false; // Pressed ESCAPE + if (!answer) answer = options.answers[0]; + let positiveIndex = options.booleanAnswerDefault == 'y' ? 0 : 1; + return answer.toLowerCase() === options.answers[positiveIndex].toLowerCase(); + } + }); + + return cmd; + } + + async exit(code = 0) { + const doExit = async () => { + this.gui().exit(); + await super.exit(code); }; - } - escapeShellArg(arg) { - if (arg.indexOf('"') >= 0 && arg.indexOf("'") >= 0) throw new Error(_('Command line argument "%s" contains both quotes and double-quotes - aborting.', arg)); // Hopeless case - let quote = '"'; - if (arg.indexOf('"') >= 0) quote = "'"; - if (arg.indexOf(' ') >= 0 || arg.indexOf("\t") >= 0) return quote + arg + quote; - return arg; - } + // Give it a few seconds to cancel otherwise exit anyway + setTimeout(async () => { + await doExit(); + }, 5000); - shellArgsToString(args) { - let output = []; - for (let i = 0; i < args.length; i++) { - output.push(this.escapeShellArg(args[i])); + if (await reg.syncTarget().syncStarted()) { + this.stdout(_('Cancelling background synchronisation... Please wait.')); + const sync = await reg.syncTarget().synchronizer(); + await sync.cancel(); } - return output.join(' '); - } - onLocaleChanged() { - return; - - let currentCommands = this.vorpal().commands; - for (let i = 0; i < currentCommands.length; i++) { - let cmd = currentCommands[i]; - if (cmd._name == 'help') { - cmd.description(_('Provides help for a given command.')); - } else if (cmd._name == 'exit') { - cmd.description(_('Exits the application.')); - } else if (cmd.__commandObject) { - cmd.description(cmd.__commandObject.description()); - } - } - } - - baseModelListener(action) { - switch (action.type) { - - case 'NOTES_UPDATE_ONE': - case 'NOTES_DELETE': - case 'FOLDERS_UPDATE_ONE': - case 'FOLDER_DELETE': - - //reg.scheduleSync(); - break; - - } + await doExit(); } commands() { @@ -246,11 +188,7 @@ class Application { let CommandClass = require('./' + path); let cmd = new CommandClass(); if (!cmd.enabled()) return; - - cmd.log = (...object) => { - return console.log(...object); - } - + cmd = this.setupCommand(cmd); this.commands_[cmd.name()] = cmd; }); @@ -297,6 +235,10 @@ class Application { return Object.assign({}, this.commandMetadata_); } + hasGui() { + return this.gui() && !this.gui().isDummy(); + } + findCommandByName(name) { if (this.commands_[name]) return this.commands_[name]; @@ -308,132 +250,97 @@ class Application { e.type = 'notFound'; throw e; } + let cmd = new CommandClass(); - - cmd.log = (...object) => { - return console.log(...object); - } - + cmd = this.setupCommand(cmd); this.commands_[name] = cmd; return this.commands_[name]; } + dummyGui() { + return { + isDummy: () => { return true; }, + prompt: (initialText = '', promptString = '') => { return cliUtils.prompt(initialText, promptString); }, + showConsole: () => {}, + maximizeConsole: () => {}, + stdout: (text) => { console.info(text); }, + fullScreen: (b=true) => {}, + exit: () => {}, + showModalOverlay: (text) => {}, + hideModalOverlay: () => {}, + stdoutMaxWidth: () => { return 78; } + }; + } + async execCommand(argv) { if (!argv.length) return this.execCommand(['help']); + reg.logger().info('execCommand()', argv); const commandName = argv[0]; this.activeCommand_ = this.findCommandByName(commandName); - const cmdArgs = cliUtils.makeCommandArgs(this.activeCommand_, argv); - await this.activeCommand_.action(cmdArgs); + + let outException = null; + try { + if (this.gui().isDummy() && !this.activeCommand_.supportsUi('cli')) throw new Error(_('The command "%s" is only available in GUI mode', this.activeCommand_.name())); + const cmdArgs = cliUtils.makeCommandArgs(this.activeCommand_, argv); + await this.activeCommand_.action(cmdArgs); + } catch (error) { + outException = error; + } + this.activeCommand_ = null; + if (outException) throw outException; } currentCommand() { return this.activeCommand_; } - async start() { - let argv = process.argv; - let startFlags = await this.handleStartFlags_(argv); - argv = startFlags.argv; - let initArgs = startFlags.matched; - if (argv.length) this.showPromptString_ = false; + async start(argv) { + argv = await super.start(argv); - if (process.argv[1].indexOf('joplindev') >= 0) { - if (!initArgs.profileDir) initArgs.profileDir = '/mnt/d/Temp/TestNotes2'; - initArgs.logLevel = Logger.LEVEL_DEBUG; - initArgs.env = 'dev'; - } + cliUtils.setStdout((object) => { + return this.stdout(object); + }); - Setting.setConstant('appName', initArgs.env == 'dev' ? 'joplindev' : 'joplin'); + // If we have some arguments left at this point, it's a command + // so execute it. + if (argv.length) { + this.gui_ = this.dummyGui(); - const profileDir = initArgs.profileDir ? initArgs.profileDir : os.homedir() + '/.config/' + Setting.value('appName'); - const resourceDir = profileDir + '/resources'; - const tempDir = profileDir + '/tmp'; - - Setting.setConstant('env', initArgs.env); - Setting.setConstant('profileDir', profileDir); - Setting.setConstant('resourceDir', resourceDir); - Setting.setConstant('tempDir', tempDir); - - await fs.mkdirp(profileDir, 0o755); - await fs.mkdirp(resourceDir, 0o755); - await fs.mkdirp(tempDir, 0o755); - - this.logger_.addTarget('file', { path: profileDir + '/log.txt' }); - this.logger_.setLevel(initArgs.logLevel); - - reg.setLogger(this.logger_); - reg.dispatch = (o) => {}; - - this.dbLogger_.addTarget('file', { path: profileDir + '/log-database.txt' }); - this.dbLogger_.setLevel(initArgs.logLevel); - - const packageJson = require('./package.json'); - this.logger_.info(sprintf('Starting %s %s (%s)...', packageJson.name, packageJson.version, Setting.value('env'))); - this.logger_.info('Profile directory: ' + profileDir); - - this.database_ = new JoplinDatabase(new DatabaseDriverNode()); - this.database_.setLogger(this.dbLogger_); - await this.database_.open({ name: profileDir + '/database.sqlite' }); - - reg.setDb(this.database_); - BaseModel.db_ = this.database_; - BaseModel.dispatch = (action) => { this.baseModelListener(action) } - - await Setting.load(); - - if (Setting.value('firstStart')) { - let locale = process.env.LANG; - if (!locale) locale = defaultLocale(); - locale = locale.split('.'); - locale = locale[0]; - reg.logger().info('First start: detected locale as ' + locale); - Setting.setValue('locale', closestSupportedLocale(locale)); - Setting.setValue('firstStart', 0) - } - - setLocale(Setting.value('locale')); - - let currentFolderId = Setting.value('activeFolderId'); - this.currentFolder_ = null; - if (currentFolderId) this.currentFolder_ = await Folder.load(currentFolderId); - if (!this.currentFolder_) this.currentFolder_ = await Folder.defaultFolder(); - Setting.setValue('activeFolderId', this.currentFolder_ ? this.currentFolder_.id : ''); - - if (this.autocompletion_.active) { - if (this.autocompletion_.install) { - try { - await installAutocompletionFile(Setting.value('appName'), Setting.value('profileDir')); - } catch (error) { - if (error.code == 'shellNotSupported') { - console.info(error.message); - return; - } - throw error; + try { + await this.execCommand(argv); + } catch (error) { + if (this.showStackTraces_) { + console.info(error); + } else { + console.info(error.message); } - } else { - let items = await handleAutocompletion(this.autocompletion_); - if (!items.length) return; - for (let i = 0; i < items.length; i++) { - items[i] = items[i].replace(/ /g, '\\ '); - items[i] = items[i].replace(/'/g, "\\'"); - items[i] = items[i].replace(/:/g, "\\:"); - items[i] = items[i].replace(/\(/g, '\\('); - items[i] = items[i].replace(/\)/g, '\\)'); - } - console.info(items.join("\n")); } - - return; - } + } else { // Otherwise open the GUI + this.initRedux(); - try { - await this.execCommand(argv); - } catch (error) { - if (this.showStackTraces_) { - console.info(error); - } else { - console.info(error.message); - } + const AppGui = require('./app-gui.js'); + this.gui_ = new AppGui(this, this.store()); + this.gui_.setLogger(this.logger_); + await this.gui_.start(); + + // Since the settings need to be loaded before the store is created, it will never + // receive the SETTING_UPDATE_ALL even, which mean state.settings will not be + // initialised. So we manually call dispatchUpdateAll() to force an update. + Setting.dispatchUpdateAll(); + + await FoldersScreenUtils.refreshFolders(); + + const tags = await Tag.allWithNotes(); + + this.dispatch({ + type: 'TAG_UPDATE_ALL', + tags: tags, + }); + + this.store().dispatch({ + type: 'FOLDER_SELECT', + id: Setting.value('activeFolderId'), + }); } } @@ -447,4 +354,4 @@ function app() { return application_; } -export { app }; \ No newline at end of file +module.exports = { app }; \ No newline at end of file diff --git a/CliClient/app/autocompletion.js b/CliClient/app/autocompletion.js deleted file mode 100644 index 7ef2bff08..000000000 --- a/CliClient/app/autocompletion.js +++ /dev/null @@ -1,175 +0,0 @@ -import { app } from './app.js'; -import { Note } from 'lib/models/note.js'; -import { Folder } from 'lib/models/folder.js'; -import { Tag } from 'lib/models/tag.js'; -import { cliUtils } from './cli-utils.js'; -import { _ } from 'lib/locale.js'; -import fs from 'fs-extra'; -import os from 'os'; -import yargParser from 'yargs-parser'; - -function autocompletionFileContent(appName, alias) { - let content = fs.readFileSync(__dirname + '/autocompletion_template.txt', 'utf8'); - content = content.replace(/\|__APPNAME__\|/g, appName); - - if (!alias) alias = 'joplin_alias_support_is_disabled'; - content = content.replace(/\|__APPALIAS__\|/g, alias); - - return content; -} - -function autocompletionScriptPath(profileDir) { - return profileDir + '/autocompletion.sh'; -} - -async function installAutocompletionFile(appName, profileDir) { - if (process.env.SHELL.indexOf('bash') < 0) { - let error = new Error(_('Only Bash is currently supported for autocompletion.')); - error.code = 'shellNotSupported'; - throw error; - } - - const alias = await cliUtils.promptInput(_('Autocompletion can be made to work with an alias too (such as a one-letter command like "j").\nIf you would like to enable this, please type the alias now (leave it empty for no alias):')); - - const content = autocompletionFileContent(appName, alias); - const filePath = autocompletionScriptPath(profileDir); - fs.writeFileSync(filePath, content); - - console.info(_('Created autocompletion script "%s".', filePath)); - - const bashProfilePath = os.homedir() + '/.bashrc'; - - let bashrcContent = fs.readFileSync(bashProfilePath, 'utf8'); - - const lineToAdd = 'source ' + filePath; - - if (bashrcContent.indexOf(lineToAdd) >= 0) { - console.info(_('Autocompletion script is already present in "%s".', bashProfilePath)); - } else { - bashrcContent += "\n" + lineToAdd + "\n"; - fs.writeFileSync(bashProfilePath, bashrcContent); - console.info(_('Added autocompletion to "%s".', bashProfilePath)); - } - - if (alias) { - if (bashrcContent.indexOf('alias ' + alias + '=') >= 0) { - console.info(_('Alias is already set in "%s".', bashProfilePath)); - } else { - const l = 'alias ' + alias + '=' + appName; - bashrcContent += "\n" + l + "\n"; - fs.writeFileSync(bashProfilePath, bashrcContent); - console.info(_('Added alias to "%s".', bashProfilePath)); - } - } - - console.info(_("IMPORTANT: run the following command to initialise autocompletion in the current shell:\nsource '%s'", filePath)); -} - -async function handleAutocompletion(autocompletion) { - let args = autocompletion.line.slice(); - args.splice(0, 1); - let current = autocompletion.current - 1; - const currentWord = args[current] ? args[current] : ''; - - // Auto-complete the command name - - if (current == 0) { - const metadata = await app().commandMetadata(); - let commandNames = []; - for (let n in metadata) { - if (!metadata.hasOwnProperty(n)) continue; - const md = metadata[n]; - if (md.hidden) continue; - if (currentWord == n) return [n]; - if (n.indexOf(currentWord) === 0) commandNames.push(n); - } - return commandNames; - } - - const commandName = args[0]; - const metadata = await app().commandMetadata(); - const md = metadata[commandName]; - const options = md && md.options ? md.options : []; - - // Auto-complete the command options - - if (currentWord) { - const includeLongs = currentWord.length == 1 ? currentWord.substr(0, 1) == '-' : currentWord.substr(0, 2) == '--'; - const includeShorts = currentWord.length <= 2 && currentWord.substr(0, 1) == '-' && currentWord.substr(0, 2) != '--'; - - if (includeLongs || includeShorts) { - const output = []; - for (let i = 0; i < options.length; i++) { - const flags = cliUtils.parseFlags(options[i][0]); - const long = flags.long ? '--' + flags.long : null; - const short = flags.short ? '-' + flags.short : null; - if (includeLongs && long && long.indexOf(currentWord) === 0) output.push(long); - if (includeShorts && short && short.indexOf(currentWord) === 0) output.push(short); - } - return output; - } - } - - // Auto-complete the command arguments - - let argIndex = -1; - for (let i = 0; i < args.length; i++) { - const w = args[i]; - if (i == 0 || w.indexOf('-') == 0) { - continue; - } - argIndex++; - } - - if (argIndex < 0) return []; - - let cmdUsage = yargParser(md.usage)['_']; - cmdUsage.splice(0, 1); - - if (cmdUsage.length <= argIndex) return []; - - let argName = cmdUsage[argIndex]; - argName = cliUtils.parseCommandArg(argName).name; - - if (argName == 'note' || argName == 'note-pattern') { - if (!app().currentFolder()) return []; - const notes = await Note.previews(app().currentFolder().id, { titlePattern: currentWord + '*' }); - return notes.map((n) => n.title); - } - - if (argName == 'notebook') { - const folders = await Folder.search({ titlePattern: currentWord + '*' }); - return folders.map((n) => n.title); - } - - if (argName == 'tag') { - let tags = await Tag.search({ titlePattern: currentWord + '*' }); - return tags.map((n) => n.title); - } - - if (argName == 'tag-command') { - return filterList(['add', 'remove', 'list'], currentWord); - } - - if (argName == 'todo-command') { - return filterList(['toggle', 'clear'], currentWord); - } - - if (argName == 'command') { - const commands = await app().commandNames(); - return this.filterList(commands, currentWord); - } - - return []; -} - -function filterList(list, currentWord) { - let output = []; - for (let i = 0; i < list.length; i++) { - if (list[i].indexOf(currentWord) !== 0) continue; - output.push(list[i]); - } - return output; -} - -export { handleAutocompletion, installAutocompletionFile, autocompletionScriptPath }; \ No newline at end of file diff --git a/CliClient/app/autocompletion_template.txt b/CliClient/app/autocompletion_template.txt deleted file mode 100644 index 6ba3a59d4..000000000 --- a/CliClient/app/autocompletion_template.txt +++ /dev/null @@ -1,44 +0,0 @@ -export IFS=$'\n' - -_|__APPNAME__|_completion() { - - # COMP_WORDS contains each word in the current command, the last one - # being the one that needs to be completed. Convert this array - # to an "escaped" line which can be passed to the joplin CLI - # which will provide the possible autocompletion words. - - ESCAPED_LINE="" - for WORD in "${COMP_WORDS[@]}" - do - if [[ -n $ESCAPED_LINE ]]; then - ESCAPED_LINE="$ESCAPED_LINE|__SEP__|" - fi - WORD="${WORD/\"/|__QUOTE__|}" - WORD="${WORD/\\(/|__OPEN_RB__|}" - WORD="${WORD/\\)/|__CLOSE_RB__|}" - WORD="${WORD/\\ /|__SPACE__|}" - ESCAPED_LINE="$ESCAPED_LINE$WORD" - done - - # Call joplin with the --autocompletion flag to retrieve the autocompletion - # candidates (each on its own line), and put these into COMREPLY. - - # echo "joplindev --autocompletion --ac-current "$COMP_CWORD" --ac-line "$ESCAPED_LINE"" > ~/test.txt - - COMPREPLY=() - while read -r line; do - COMPREPLY+=("$line") - done <<< "$(|__APPNAME__| --autocompletion --ac-current "$COMP_CWORD" --ac-line "$ESCAPED_LINE")" - - # If there's only one element and it's empty, make COMREPLY - # completely empty so that default completion takes over - # (i.e. regular file completion) - # https://stackoverflow.com/a/19062943/561309 - - if [[ -z ${COMPREPLY[0]} ]]; then - COMPREPLY=() - fi -} - -complete -o default -F _|__APPNAME__|_completion |__APPNAME__| -complete -o default -F _|__APPNAME__|_completion |__APPALIAS__| \ No newline at end of file diff --git a/CliClient/app/base-command.js b/CliClient/app/base-command.js index 2b87a43c5..eb2cc3461 100644 --- a/CliClient/app/base-command.js +++ b/CliClient/app/base-command.js @@ -1,5 +1,13 @@ +const { _ } = require('lib/locale.js'); +const { reg } = require('lib/registry.js'); + class BaseCommand { + constructor() { + this.stdout_ = null; + this.prompt_ = null; + } + usage() { throw new Error('Usage not defined'); } @@ -12,6 +20,14 @@ class BaseCommand { throw new Error('Action not defined'); } + compatibleUis() { + return ['cli', 'gui']; + } + + supportsUi(ui) { + return this.compatibleUis().indexOf(ui) >= 0; + } + aliases() { return []; } @@ -39,6 +55,32 @@ class BaseCommand { return r[0]; } + setDispatcher(fn) { + this.dispatcher_ = fn; + } + + dispatch(action) { + if (!this.dispatcher_) throw new Error('Dispatcher not defined'); + return this.dispatcher_(action); + } + + setStdout(fn) { + this.stdout_ = fn; + } + + stdout(text) { + if (this.stdout_) this.stdout_(text); + } + + setPrompt(fn) { + this.prompt_ = fn; + } + + async prompt(message, options = null) { + if (!this.prompt_) throw new Error('Prompt is undefined'); + return await this.prompt_(message, options); + } + metadata() { return { name: this.name(), @@ -48,6 +90,10 @@ class BaseCommand { }; } + logger() { + return reg.logger(); + } + } -export { BaseCommand }; \ No newline at end of file +module.exports = { BaseCommand }; \ No newline at end of file diff --git a/CliClient/app/build-doc.js b/CliClient/app/build-doc.js index 8e8481736..f9da733b2 100644 --- a/CliClient/app/build-doc.js +++ b/CliClient/app/build-doc.js @@ -1,10 +1,7 @@ -require('source-map-support').install(); -require('babel-plugin-transform-runtime'); - -import fs from 'fs-extra'; -import { fileExtension, basename, dirname } from 'lib/path-utils.js'; -import wrap_ from 'word-wrap'; -import { _, setLocale, languageCode } from 'lib/locale.js'; +const fs = require('fs-extra'); +const { fileExtension, basename, dirname } = require('lib/path-utils.js'); +const wrap_ = require('word-wrap'); +const { _, setLocale, languageCode } = require('lib/locale.js'); const rootDir = dirname(dirname(__dirname)); const MAX_WIDTH = 78; @@ -80,7 +77,7 @@ function getHeader() { output.push('NAME'); output.push(''); - output.push(wrap('joplin - a note taking and todo app with synchronisation capabilities'), INDENT); + output.push(wrap('joplin - a note taking and to-do app with synchronisation capabilities'), INDENT); output.push(''); @@ -88,7 +85,7 @@ function getHeader() { output.push(''); let description = []; - description.push('Joplin is a note taking and todo application, which can handle a large number of notes organised into notebooks.'); + description.push('Joplin is a note taking and to-do application, which can handle a large number of notes organised into notebooks.'); description.push('The notes are searchable, can be copied, tagged and modified with your own text editor.'); description.push("\n\n"); description.push('The notes can be synchronised with various target including the file system (for example with a network directory) or with Microsoft OneDrive.'); diff --git a/CliClient/app/build-translation.js b/CliClient/app/build-translation.js index a2bccb8f7..5adc40f90 100644 --- a/CliClient/app/build-translation.js +++ b/CliClient/app/build-translation.js @@ -1,20 +1,20 @@ "use strict" -require('source-map-support').install(); -require('babel-plugin-transform-runtime'); +require('app-module-path').addPath(__dirname); const processArgs = process.argv.splice(2, process.argv.length); const silentLog = processArgs.indexOf('--silent') >= 0; -import { basename, dirname } from 'lib/path-utils.js'; -import fs from 'fs-extra'; -import gettextParser from 'gettext-parser'; +const { basename, dirname } = require('lib/path-utils.js'); +const fs = require('fs-extra'); +const gettextParser = require('gettext-parser'); const rootDir = dirname(dirname(__dirname)); const cliDir = rootDir + '/CliClient'; const cliLocalesDir = cliDir + '/locales'; const rnDir = rootDir + '/ReactNativeClient'; +const electronDir = rootDir + '/ElectronClient/app'; function execCommand(command) { if (!silentLog) console.info('Running: ' + command); @@ -117,6 +117,9 @@ async function main() { await createPotFile(potFilePath, [ cliDir + '/app/*.js', + cliDir + '/app/gui/*.js', + electronDir + '/*.js', + electronDir + '/gui/*.js', rnDir + '/lib/*.js', rnDir + '/lib/models/*.js', rnDir + '/lib/services/*.js', @@ -141,6 +144,9 @@ async function main() { const rnJsonLocaleDir = rnDir + '/locales'; await execCommand('rsync -a "' + jsonLocalesDir + '/" "' + rnJsonLocaleDir + '"'); + + const electronJsonLocaleDir = electronDir + '/locales'; + await execCommand('rsync -a "' + jsonLocalesDir + '/" "' + electronJsonLocaleDir + '"'); } main().catch((error) => { diff --git a/CliClient/app/build-website.js b/CliClient/app/build-website.js index 96b81546d..8558d59ac 100644 --- a/CliClient/app/build-website.js +++ b/CliClient/app/build-website.js @@ -1,26 +1,54 @@ -require('source-map-support').install(); -require('babel-plugin-transform-runtime'); +const fs = require('fs-extra'); +const { fileExtension, basename, dirname } = require('lib/path-utils.js'); +const { _, setLocale, languageCode } = require('lib/locale.js'); +const marked = require('lib/marked.js'); +const Mustache = require('mustache'); -import fs from 'fs-extra'; -import { fileExtension, basename, dirname } from 'lib/path-utils.js'; -import { _, setLocale, languageCode } from 'lib/locale.js'; -import marked from 'lib/marked.js'; - -const headerHtml = ` - +const headerHtml = ` - Joplin - a free, open source, note taking and todo application with synchronisation capabilities + Joplin - an open source note taking and to-do application with synchronisation capabilities + + + .nav-wrapper { + position: relative; + width: inherit; + } + .nav { + background-color: black; + display: table; + width: inherit; + } + .nav.sticky { + position:fixed; + top: 0; + width: inherit; + box-shadow: 0 0 10px #000000; + } + .nav a { + color: white; + display: inline-block; + padding: .6em .9em .6em .9em; + } + .nav ul { + padding-left: 2em; + margin-bottom: 0; + display: table-cell; + min-width: 165px; + } + .nav ul li { + display: inline-block; + padding: 0; + } + .nav li.selected { + background-color: #222; + font-weight: bold; + } + .nav-right { + display: table-cell; + width: 100%; + text-align: right; + vertical-align: middle; + line-height: 0; + } + .nav-right .share-btn { + display: none; + } + .share-btn-github { + display: inline-block; + } + .nav-right .small-share-btn { + display: none; + } + .nav-right .share-btn-github { + display: inline-block; + } + @media all and (min-width: 400px) { + .nav-right .share-btn { + display: inline-block; + } + .nav-right .small-share-btn { + display: none; + } + } + @@ -93,68 +184,96 @@ const headerHtml = `
- -

oplin

-

A free, open source, note taking and todo application with synchronisation capabilities.

+ +

oplin

+

An open source note taking and to-do application with synchronisation capabilities.

+
+ +
`; const footerHtml = ` -
Copyright (c) 2017 Laurent Cozic `; -const screenshotHtml = ` - - - - - - - - - -
- Mobile - - Command line -
- - -
-joplin:/My notebook$ ls -n 12
-[ ] 8am conference call ☎
-[ ] Make vet appointment
-[ ] Go pick up parcel
-[ ] Pay flat rent 💸
-[X] Book ferry 🚢
-[X] Deploy Joplin app
-    Open source stuff
-    Swimming pool time table 🏊
-    Grocery shopping list 📝
-    Work itinerary
-    Tuesday random note
-    Vacation plans ☀️
-			
-
-`; +// const screenshotHtml = ` +// +// +// +// +// +// +// +// +// +//
+// Mobile +// +// Command line +//
+// +// +//
+// joplin:/My notebook$ ls -n 12
+// [ ] 8am conference call ☎
+// [ ] Make vet appointment
+// [ ] Go pick up parcel
+// [ ] Pay flat rent 💸
+// [X] Book ferry 🚢
+// [X] Deploy Joplin app
+//     Open source stuff
+//     Swimming pool time table 🏊
+//     Grocery shopping list 📝
+//     Work itinerary
+//     Tuesday random note
+//     Vacation plans ☀
+// 			
+//
+// `; -const gaHtml = ` +const scriptHtml = ` `; +// +// +// + const rootDir = dirname(dirname(__dirname)); function markdownToHtml(md) { @@ -169,16 +288,31 @@ function markdownToHtml(md) { renderer: renderer, }); - output = output.replace(//, screenshotHtml); + //output = output.replace(//, screenshotHtml); - return headerHtml + output + gaHtml + footerHtml; + return headerHtml + output + scriptHtml + footerHtml; +} + +function renderFileToHtml(sourcePath, targetPath, params) { + const md = fs.readFileSync(sourcePath, 'utf8'); + params.baseUrl = 'http://joplin.cozic.net'; + params.imageBaseUrl = params.baseUrl + '/images'; + const html = Mustache.render(markdownToHtml(md), params); + fs.writeFileSync(targetPath, html); } async function main() { - const md = fs.readFileSync(rootDir + '/README.md', 'utf8'); - const html = markdownToHtml(md); + renderFileToHtml(rootDir + '/README.md', rootDir + '/docs/index.html', { + selectedHome: 'selected', + }); - fs.writeFileSync(rootDir + '/index.html', html); + renderFileToHtml(rootDir + '/README_terminal.md', rootDir + '/docs/terminal/index.html', { + selectedTerminal: 'selected', + }); + + renderFileToHtml(rootDir + '/README_desktop.md', rootDir + '/docs/desktop/index.html', { + selectedDesktop: 'selected', + }); } main().catch((error) => { diff --git a/CliClient/app/cli-integration-tests.js b/CliClient/app/cli-integration-tests.js index 3f9954a00..a445cce17 100644 --- a/CliClient/app/cli-integration-tests.js +++ b/CliClient/app/cli-integration-tests.js @@ -1,18 +1,15 @@ "use strict" -require('source-map-support').install(); -require('babel-plugin-transform-runtime'); - -import fs from 'fs-extra'; -import { Logger } from 'lib/logger.js'; -import { dirname } from 'lib/path-utils.js'; -import { DatabaseDriverNode } from 'lib/database-driver-node.js'; -import { JoplinDatabase } from 'lib/joplin-database.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { Setting } from 'lib/models/setting.js'; -import { sprintf } from 'sprintf-js'; +const fs = require('fs-extra'); +const { Logger } = require('lib/logger.js'); +const { dirname } = require('lib/path-utils.js'); +const { DatabaseDriverNode } = require('lib/database-driver-node.js'); +const { JoplinDatabase } = require('lib/joplin-database.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { Setting } = require('lib/models/setting.js'); +const { sprintf } = require('sprintf-js'); const exec = require('child_process').exec process.on('unhandledRejection', (reason, p) => { diff --git a/CliClient/app/cli-utils.js b/CliClient/app/cli-utils.js index bf7dc6230..3bf8a6680 100644 --- a/CliClient/app/cli-utils.js +++ b/CliClient/app/cli-utils.js @@ -1,6 +1,6 @@ -import yargParser from 'yargs-parser'; -import { _ } from 'lib/locale.js'; -import { time } from 'lib/time-utils.js'; +const yargParser = require('yargs-parser'); +const { _ } = require('lib/locale.js'); +const { time } = require('lib/time-utils.js'); const stringPadding = require('string-padding'); const cliUtils = {}; @@ -127,6 +127,37 @@ cliUtils.makeCommandArgs = function(cmd, argv) { return output; } +cliUtils.promptMcq = function(message, answers) { + const readline = require('readline'); + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + + message += "\n\n"; + for (let n in answers) { + if (!answers.hasOwnProperty(n)) continue; + message += _('%s: %s', n, answers[n]) + "\n"; + } + + message += "\n"; + message += _('Your choice: '); + + return new Promise((resolve, reject) => { + rl.question(message, (answer) => { + rl.close(); + + if (!(answer in answers)) { + reject(new Error(_('Invalid answer: %s', answer))); + return; + } + + resolve(answer); + }); + }); +} + cliUtils.promptConfirm = function(message, answers = null) { if (!answers) answers = [_('Y'), _('n')]; const readline = require('readline'); @@ -163,15 +194,38 @@ cliUtils.promptInput = function(message) { }); } +// Note: initialText is there to have the same signature as statusBar.prompt() so that +// it can be a drop-in replacement, however initialText is not used (and cannot be +// with readline.question?). +cliUtils.prompt = function(initialText = '', promptString = ':') { + const readline = require('readline'); + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + + return new Promise((resolve, reject) => { + rl.question(promptString, (answer) => { + rl.close(); + resolve(answer); + }); + }); +} + let redrawStarted_ = false; let redrawLastLog_ = null; let redrawLastUpdateTime_ = 0; +cliUtils.setStdout = function(v) { + this.stdout_ = v; +} + cliUtils.redraw = function(s) { const now = time.unixMs(); if (now - redrawLastUpdateTime_ > 4000) { - console.info(s); + this.stdout_(s); redrawLastUpdateTime_ = now; redrawLastLog_ = null; } else { @@ -185,11 +239,11 @@ cliUtils.redrawDone = function() { if (!redrawStarted_) return; if (redrawLastLog_) { - console.info(redrawLastLog_); + this.stdout_(redrawLastLog_); } redrawLastLog_ = null; redrawStarted_ = false; } -export { cliUtils }; \ No newline at end of file +module.exports = { cliUtils }; \ No newline at end of file diff --git a/CliClient/app/command-attach.js b/CliClient/app/command-attach.js new file mode 100644 index 000000000..ab7431710 --- /dev/null +++ b/CliClient/app/command-attach.js @@ -0,0 +1,31 @@ +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { shim } = require('lib/shim.js'); +const fs = require('fs-extra'); + +class Command extends BaseCommand { + + usage() { + return 'attach '; + } + + description() { + return _('Attaches the given file to the note.'); + } + + async action(args) { + let title = args['note']; + + let note = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() }); + if (!note) throw new Error(_('Cannot find "%s".', title)); + + const localFilePath = args['file']; + + await shim.attachFileToNote(note, localFilePath); + } + +} + +module.exports = Command; \ No newline at end of file diff --git a/CliClient/app/command-cat.js b/CliClient/app/command-cat.js index 194b1b1cf..15db03fe0 100644 --- a/CliClient/app/command-cat.js +++ b/CliClient/app/command-cat.js @@ -1,9 +1,9 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); class Command extends BaseCommand { @@ -21,6 +21,10 @@ class Command extends BaseCommand { ]; } + enabled() { + return false; + } + async action(args) { let title = args['note']; @@ -28,7 +32,7 @@ class Command extends BaseCommand { if (!item) throw new Error(_('Cannot find "%s".', title)); const content = args.options.verbose ? await Note.serialize(item) : await Note.serializeForEdit(item); - this.log(content); + this.stdout(content); } } diff --git a/CliClient/app/command-config.js b/CliClient/app/command-config.js index 1c9e0775c..c72967548 100644 --- a/CliClient/app/command-config.js +++ b/CliClient/app/command-config.js @@ -1,7 +1,7 @@ -import { BaseCommand } from './base-command.js'; -import { _, setLocale } from 'lib/locale.js'; -import { app } from './app.js'; -import { Setting } from 'lib/models/setting.js'; +const { BaseCommand } = require('./base-command.js'); +const { _, setLocale } = require('lib/locale.js'); +const { app } = require('./app.js'); +const { Setting } = require('lib/models/setting.js'); class Command extends BaseCommand { @@ -33,16 +33,21 @@ class Command extends BaseCommand { if (!args.name && !args.value) { let keys = Setting.keys(!verbose, 'cli'); + keys.sort(); for (let i = 0; i < keys.length; i++) { const value = Setting.value(keys[i]); if (!verbose && !value) continue; - this.log(renderKeyValue(keys[i])); + this.stdout(renderKeyValue(keys[i])); } + app().gui().showConsole(); + app().gui().maximizeConsole(); return; } if (args.name && !args.value) { - this.log(renderKeyValue(args.name)); + this.stdout(renderKeyValue(args.name)); + app().gui().showConsole(); + app().gui().maximizeConsole(); return; } diff --git a/CliClient/app/command-cp.js b/CliClient/app/command-cp.js index 2611e4439..9bef2918b 100644 --- a/CliClient/app/command-cp.js +++ b/CliClient/app/command-cp.js @@ -1,9 +1,9 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); class Command extends BaseCommand { diff --git a/CliClient/app/command-done.js b/CliClient/app/command-done.js index d23e0bb86..616cf77f9 100644 --- a/CliClient/app/command-done.js +++ b/CliClient/app/command-done.js @@ -1,10 +1,10 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { time } from 'lib/time-utils.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { time } = require('lib/time-utils.js'); class Command extends BaseCommand { @@ -13,13 +13,13 @@ class Command extends BaseCommand { } description() { - return _('Marks a todo as done.'); + return _('Marks a to-do as done.'); } static async handleAction(args, isCompleted) { const note = await app().loadItem(BaseModel.TYPE_NOTE, args.note); if (!note) throw new Error(_('Cannot find "%s".', args.note)); - if (!note.is_todo) throw new Error(_('Note is not a todo: "%s"', args.note)); + if (!note.is_todo) throw new Error(_('Note is not a to-do: "%s"', args.note)); const todoCompleted = !!note.todo_completed; @@ -32,7 +32,7 @@ class Command extends BaseCommand { } async action(args) { - Command.handleAction(args, true); + await Command.handleAction(args, true); } } diff --git a/CliClient/app/command-dump.js b/CliClient/app/command-dump.js index 7db87bf5c..61ec789b2 100644 --- a/CliClient/app/command-dump.js +++ b/CliClient/app/command-dump.js @@ -1,9 +1,9 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { Tag } from 'lib/models/tag.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { Tag } = require('lib/models/tag.js'); class Command extends BaseCommand { @@ -36,7 +36,7 @@ class Command extends BaseCommand { items = items.concat(tags); - this.log(JSON.stringify(items)); + this.stdout(JSON.stringify(items)); } } diff --git a/CliClient/app/command-edit.js b/CliClient/app/command-edit.js index c25d17d1d..9fc7fec7e 100644 --- a/CliClient/app/command-edit.js +++ b/CliClient/app/command-edit.js @@ -1,12 +1,14 @@ -import fs from 'fs-extra'; -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { Setting } from 'lib/models/setting.js'; -import { BaseModel } from 'lib/base-model.js'; -import { cliUtils } from './cli-utils.js'; +const fs = require('fs-extra'); +const { BaseCommand } = require('./base-command.js'); +const { uuid } = require('lib/uuid.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { Setting } = require('lib/models/setting.js'); +const { BaseModel } = require('lib/base-model.js'); +const { cliUtils } = require('./cli-utils.js'); +const { time } = require('lib/time-utils.js'); class Command extends BaseCommand { @@ -20,13 +22,10 @@ class Command extends BaseCommand { async action(args) { let watcher = null; - let newNote = null; + let tempFilePath = null; const onFinishedEditing = async () => { - if (watcher) watcher.close(); - //app().vorpal().show(); - newNote = null; - this.log(_('Done editing.')); + if (tempFilePath) fs.removeSync(tempFilePath); } const textEditorPath = () => { @@ -36,55 +35,75 @@ class Command extends BaseCommand { } try { + // ------------------------------------------------------------------------- + // Load note or create it if it doesn't exist + // ------------------------------------------------------------------------- + let title = args['note']; if (!app().currentFolder()) throw new Error(_('No active notebook.')); let note = await app().loadItem(BaseModel.TYPE_NOTE, title); if (!note) { - const ok = await cliUtils.promptConfirm(_('Note does not exist: "%s". Create it?', title)); + const ok = await this.prompt(_('Note does not exist: "%s". Create it?', title)); if (!ok) return; - newNote = await Note.save({ title: title, parent_id: app().currentFolder().id }); - note = await Note.load(newNote.id); + note = await Note.save({ title: title, parent_id: app().currentFolder().id }); + note = await Note.load(note.id); } + // ------------------------------------------------------------------------- + // Create the file to be edited and prepare the editor program arguments + // ------------------------------------------------------------------------- + let editorPath = textEditorPath(); let editorArgs = editorPath.split(' '); editorPath = editorArgs[0]; editorArgs = editorArgs.splice(1); - let content = await Note.serializeForEdit(note); + const originalContent = await Note.serializeForEdit(note); - let tempFilePath = Setting.value('tempDir') + '/' + Note.systemPath(note); + tempFilePath = Setting.value('tempDir') + '/' + uuid.create() + '.md'; editorArgs.push(tempFilePath); - const spawn = require('child_process').spawn; + await fs.writeFile(tempFilePath, originalContent); - this.log(_('Starting to edit note. Close the editor to get back to the prompt.')); + // ------------------------------------------------------------------------- + // Start editing the file + // ------------------------------------------------------------------------- - await fs.writeFile(tempFilePath, content); + this.logger().info('Disabling fullscreen...'); - let watchTimeout = null; - watcher = fs.watch(tempFilePath, (eventType, filename) => { - // We need a timeout because for each change to the file, multiple events are generated. + app().gui().showModalOverlay(_('Starting to edit note. Close the editor to get back to the prompt.')); + await app().gui().forceRender(); + const termState = app().gui().term().saveState(); - if (watchTimeout) return; + const spawnSync = require('child_process').spawnSync; + spawnSync(editorPath, editorArgs, { stdio: 'inherit' }); - watchTimeout = setTimeout(async () => { - let updatedNote = await fs.readFile(tempFilePath, 'utf8'); - updatedNote = await Note.unserializeForEdit(updatedNote); - updatedNote.id = note.id; - await Note.save(updatedNote); - process.stdout.write('.'); - watchTimeout = null; - }, 200); + app().gui().term().restoreState(termState); + app().gui().hideModalOverlay(); + app().gui().forceRender(); + + // ------------------------------------------------------------------------- + // Save the note and clean up + // ------------------------------------------------------------------------- + + const updatedContent = await fs.readFile(tempFilePath, 'utf8'); + if (updatedContent !== originalContent) { + let updatedNote = await Note.unserializeForEdit(updatedContent); + updatedNote.id = note.id; + await Note.save(updatedNote); + this.stdout(_('Note has been saved.')); + } + + this.dispatch({ + type: 'NOTE_SELECT', + id: note.id, }); - const childProcess = spawn(editorPath, editorArgs, { stdio: 'inherit' }); - childProcess.on('exit', async (error, code) => { - await onFinishedEditing(); - }); + await onFinishedEditing(); + } catch(error) { await onFinishedEditing(); throw error; diff --git a/CliClient/app/command-exit.js b/CliClient/app/command-exit.js new file mode 100644 index 000000000..5d73513f1 --- /dev/null +++ b/CliClient/app/command-exit.js @@ -0,0 +1,21 @@ +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); + +class Command extends BaseCommand { + + usage() { + return 'exit'; + } + + description() { + return _('Exits the application.'); + } + + async action(args) { + await app().exit(); + } + +} + +module.exports = Command; \ No newline at end of file diff --git a/CliClient/app/command-export-sync-status.js b/CliClient/app/command-export-sync-status.js new file mode 100644 index 000000000..c8ecd7328 --- /dev/null +++ b/CliClient/app/command-export-sync-status.js @@ -0,0 +1,36 @@ +const { BaseCommand } = require('./base-command.js'); +const { Database } = require('lib/database.js'); +const { app } = require('./app.js'); +const { Setting } = require('lib/models/setting.js'); +const { _ } = require('lib/locale.js'); +const { ReportService } = require('lib/services/report.js'); +const fs = require('fs-extra'); + +class Command extends BaseCommand { + + usage() { + return 'export-sync-status'; + } + + description() { + return 'Export sync status'; + } + + hidden() { + return true; + } + + async action(args) { + const service = new ReportService(); + const csv = await service.basicItemList({ format: 'csv' }); + const filePath = Setting.value('profileDir') + '/syncReport-' + (new Date()).getTime() + '.csv'; + await fs.writeFileSync(filePath, csv); + this.stdout('Sync status exported to ' + filePath); + + app().gui().showConsole(); + app().gui().maximizeConsole(); + } + +} + +module.exports = Command; \ No newline at end of file diff --git a/CliClient/app/command-export.js b/CliClient/app/command-export.js index 0e34723eb..798e3dc0c 100644 --- a/CliClient/app/command-export.js +++ b/CliClient/app/command-export.js @@ -1,20 +1,20 @@ -import { BaseCommand } from './base-command.js'; -import { Exporter } from 'lib/services/exporter.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Note } from 'lib/models/note.js'; -import { reg } from 'lib/registry.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import fs from 'fs-extra'; +const { BaseCommand } = require('./base-command.js'); +const { Exporter } = require('lib/services/exporter.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Note } = require('lib/models/note.js'); +const { reg } = require('lib/registry.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const fs = require('fs-extra'); class Command extends BaseCommand { usage() { - return 'export '; + return 'export '; } description() { - return _('Exports Joplin data to the given target.'); + return _('Exports Joplin data to the given directory. By default, it will export the complete database including notebooks, notes, tags and resources.'); } options() { @@ -26,7 +26,7 @@ class Command extends BaseCommand { async action(args) { let exportOptions = {}; - exportOptions.destDir = args.destination; + exportOptions.destDir = args.directory; exportOptions.writeFile = (filePath, data) => { return fs.writeFile(filePath, data); }; diff --git a/CliClient/app/command-geoloc.js b/CliClient/app/command-geoloc.js index f9055f16d..32aa9078f 100644 --- a/CliClient/app/command-geoloc.js +++ b/CliClient/app/command-geoloc.js @@ -1,9 +1,9 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); class Command extends BaseCommand { @@ -21,7 +21,9 @@ class Command extends BaseCommand { let item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() }); if (!item) throw new Error(_('Cannot find "%s".', title)); const url = Note.geolocationUrl(item); - this.log(url); + this.stdout(url); + + app().gui().showConsole(); } } diff --git a/CliClient/app/command-help.js b/CliClient/app/command-help.js index d54d9ab13..a34e118bd 100644 --- a/CliClient/app/command-help.js +++ b/CliClient/app/command-help.js @@ -1,10 +1,11 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { renderCommandHelp } from './help-utils.js'; -import { Database } from 'lib/database.js'; -import { Setting } from 'lib/models/setting.js'; -import { _ } from 'lib/locale.js'; -import { ReportService } from 'lib/services/report.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { renderCommandHelp } = require('./help-utils.js'); +const { Database } = require('lib/database.js'); +const { Setting } = require('lib/models/setting.js'); +const { wrap } = require('lib/string-utils.js'); +const { _ } = require('lib/locale.js'); +const { cliUtils } = require('./cli-utils.js'); class Command extends BaseCommand { @@ -16,19 +17,72 @@ class Command extends BaseCommand { return _('Displays usage information.'); } - async action(args) { - const commands = args['command'] ? [app().findCommandByName(args['command'])] : app().commands(); - + allCommands() { + const commands = app().commands(); let output = []; for (let n in commands) { if (!commands.hasOwnProperty(n)) continue; const command = commands[n]; - output.push(renderCommandHelp(command)); + if (command.hidden()) continue; + if (!command.enabled()) continue; + output.push(command); } - output.sort(); + output.sort((a, b) => a.name() < b.name() ? -1 : +1); - this.log(output.join("\n\n")); + return output; + } + + async action(args) { + const stdoutWidth = app().commandStdoutMaxWidth(); + + if (args.command === 'shortcuts') { + if (app().gui().isDummy()) { + throw new Error(_('Shortcuts are not available in CLI mode.')); + } + + const shortcuts = app().gui().shortcuts(); + + let rows = []; + + for (let n in shortcuts) { + if (!shortcuts.hasOwnProperty(n)) continue; + const shortcut = shortcuts[n]; + if (!shortcut.description) continue; + n = shortcut.friendlyName ? shortcut.friendlyName : n; + rows.push([n, shortcut.description()]); + } + + cliUtils.printArray(this.stdout.bind(this), rows); + } else if (args.command === 'all') { + const commands = this.allCommands(); + const output = commands.map((c) => renderCommandHelp(c)); + this.stdout(output.join('\n\n')); + } else if (args.command) { + const command = app().findCommandByName(args['command']); + if (!command) throw new Error(_('Cannot find "%s".', args.command)); + this.stdout(renderCommandHelp(command, stdoutWidth)); + } else { + const commandNames = this.allCommands().map((a) => a.name()); + + this.stdout(_('Type `help [command]` for more information about a command.')); + this.stdout(''); + this.stdout(_('The possible commands are:')); + this.stdout(''); + this.stdout(commandNames.join(', ')); + this.stdout(''); + this.stdout(_('In any command, a note or notebook can be refered to by title or ID, or using the shortcuts `$n` or `$b` for, respectively, the currently selected note or notebook. `$c` can be used to refer to the currently selected item.')); + this.stdout(''); + this.stdout(_('To move from one pane to another, press Tab or Shift+Tab.')); + this.stdout(_('Use the arrows and page up/down to scroll the lists and text areas (including this console).')); + this.stdout(_('To maximise/minimise the console, press "TC".')); + this.stdout(_('To enter command line mode, press ":"')); + this.stdout(_('To exit command line mode, press ESCAPE')); + this.stdout(_('For the complete list of available keyboard shortcuts, type `help shortcuts`')); + } + + app().gui().showConsole(); + app().gui().maximizeConsole(); } } diff --git a/CliClient/app/command-import-enex.js b/CliClient/app/command-import-enex.js index 2665b905a..7e401c41c 100644 --- a/CliClient/app/command-import-enex.js +++ b/CliClient/app/command-import-enex.js @@ -1,10 +1,10 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { Folder } from 'lib/models/folder.js'; -import { importEnex } from 'import-enex'; -import { filename, basename } from 'lib/path-utils.js'; -import { cliUtils } from './cli-utils.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { Folder } = require('lib/models/folder.js'); +const { importEnex } = require('import-enex'); +const { filename, basename } = require('lib/path-utils.js'); +const { cliUtils } = require('./cli-utils.js'); class Command extends BaseCommand { @@ -19,7 +19,6 @@ class Command extends BaseCommand { options() { return [ ['-f, --force', _('Do not ask for confirmation.')], - ['--fuzzy-matching', 'For debugging purposes. Do not use.'], ]; } @@ -32,11 +31,12 @@ class Command extends BaseCommand { if (!folderTitle) folderTitle = filename(filePath); folder = await Folder.loadByField('title', folderTitle); const msg = folder ? _('File "%s" will be imported into existing notebook "%s". Continue?', basename(filePath), folderTitle) : _('New notebook "%s" will be created and file "%s" will be imported into it. Continue?', folderTitle, basename(filePath)); - const ok = force ? true : await cliUtils.promptConfirm(msg); + const ok = force ? true : await this.prompt(msg); if (!ok) return; + let lastProgress = ''; + let options = { - fuzzyMatching: args.options['fuzzy-matching'] === true, onProgress: (progressState) => { let line = []; line.push(_('Found: %d.', progressState.loaded)); @@ -45,18 +45,22 @@ class Command extends BaseCommand { if (progressState.skipped) line.push(_('Skipped: %d.', progressState.skipped)); if (progressState.resourcesCreated) line.push(_('Resources: %d.', progressState.resourcesCreated)); if (progressState.notesTagged) line.push(_('Tagged: %d.', progressState.notesTagged)); - cliUtils.redraw(line.join(' ')); + lastProgress = line.join(' '); + cliUtils.redraw(lastProgress); }, onError: (error) => { let s = error.trace ? error.trace : error.toString(); - this.log(s); + this.stdout(s); }, } folder = !folder ? await Folder.save({ title: folderTitle }) : folder; - this.log(_('Importing notes...')); + + app().gui().showConsole(); + this.stdout(_('Importing notes...')); await importEnex(folder.id, filePath, options); cliUtils.redrawDone(); + this.stdout(_('The notes have been imported: %s', lastProgress)); } } diff --git a/CliClient/app/command-ls.js b/CliClient/app/command-ls.js index 4b242ff94..5429ba689 100644 --- a/CliClient/app/command-ls.js +++ b/CliClient/app/command-ls.js @@ -1,13 +1,13 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Setting } from 'lib/models/setting.js'; -import { Note } from 'lib/models/note.js'; -import { sprintf } from 'sprintf-js'; -import { time } from 'lib/time-utils.js'; -import { cliUtils } from './cli-utils.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Setting } = require('lib/models/setting.js'); +const { Note } = require('lib/models/note.js'); +const { sprintf } = require('sprintf-js'); +const { time } = require('lib/time-utils.js'); +const { cliUtils } = require('./cli-utils.js'); class Command extends BaseCommand { @@ -18,15 +18,19 @@ class Command extends BaseCommand { description() { return _('Displays the notes in the current notebook. Use `ls /` to display the list of notebooks.'); } + + enabled() { + return false; + } options() { return [ ['-n, --limit ', _('Displays only the first top notes.')], ['-s, --sort ', _('Sorts the item by (eg. title, updated_time, created_time).')], ['-r, --reverse', _('Reverses the sorting order.')], - ['-t, --type ', _('Displays only the items of the specific type(s). Can be `n` for notes, `t` for todos, or `nt` for notes and todos (eg. `-tt` would display only the todos, while `-ttd` would display notes and todos.')], + ['-t, --type ', _('Displays only the items of the specific type(s). Can be `n` for notes, `t` for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the to-dos, while `-ttd` would display notes and to-dos.')], ['-f, --format ', _('Either "text" or "json"')], - ['-l, --long', _('Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, TODO_CHECKED (for todos), TITLE')], + ['-l, --long', _('Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, TODO_CHECKED (for to-dos), TITLE')], ]; } @@ -63,7 +67,7 @@ class Command extends BaseCommand { } if (options.format && options.format == 'json') { - this.log(JSON.stringify(items)); + this.stdout(JSON.stringify(items)); } else { let hasTodos = false; for (let i = 0; i < items.length; i++) { @@ -112,7 +116,7 @@ class Command extends BaseCommand { rows.push(row); } - cliUtils.printArray(this.log, rows); + cliUtils.printArray(this.stdout.bind(this), rows); } } diff --git a/CliClient/app/command-mkbook.js b/CliClient/app/command-mkbook.js index 7dd6143c5..68e5df875 100644 --- a/CliClient/app/command-mkbook.js +++ b/CliClient/app/command-mkbook.js @@ -1,8 +1,8 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { Folder } from 'lib/models/folder.js'; -import { reg } from 'lib/registry.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { Folder } = require('lib/models/folder.js'); +const { reg } = require('lib/registry.js'); class Command extends BaseCommand { diff --git a/CliClient/app/command-mknote.js b/CliClient/app/command-mknote.js index e44937185..a4d93b3ef 100644 --- a/CliClient/app/command-mknote.js +++ b/CliClient/app/command-mknote.js @@ -1,7 +1,7 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { Note } from 'lib/models/note.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { Note } = require('lib/models/note.js'); class Command extends BaseCommand { @@ -23,6 +23,8 @@ class Command extends BaseCommand { note = await Note.save(note); Note.updateGeolocation(note.id); + + app().switchCurrentFolder(app().currentFolder()); } } diff --git a/CliClient/app/command-mktodo.js b/CliClient/app/command-mktodo.js index 04bb02325..6163928ee 100644 --- a/CliClient/app/command-mktodo.js +++ b/CliClient/app/command-mktodo.js @@ -1,7 +1,7 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { Note } from 'lib/models/note.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { Note } = require('lib/models/note.js'); class Command extends BaseCommand { @@ -10,7 +10,7 @@ class Command extends BaseCommand { } description() { - return _('Creates a new todo.'); + return _('Creates a new to-do.'); } async action(args) { @@ -24,6 +24,8 @@ class Command extends BaseCommand { note = await Note.save(note); Note.updateGeolocation(note.id); + + app().switchCurrentFolder(app().currentFolder()); } } diff --git a/CliClient/app/command-mv.js b/CliClient/app/command-mv.js index 50925ead0..9bf37a5c8 100644 --- a/CliClient/app/command-mv.js +++ b/CliClient/app/command-mv.js @@ -1,22 +1,22 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); class Command extends BaseCommand { usage() { - return 'mv [notebook]'; + return 'mv [notebook]'; } description() { - return _('Moves the notes matching to [notebook].'); + return _('Moves the notes matching to [notebook].'); } async action(args) { - const pattern = args['note-pattern']; + const pattern = args['note']; const destination = args['notebook']; const folder = await Folder.loadByField('title', destination); diff --git a/CliClient/app/command-ren.js b/CliClient/app/command-ren.js new file mode 100644 index 000000000..2e09a5438 --- /dev/null +++ b/CliClient/app/command-ren.js @@ -0,0 +1,40 @@ +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); + +class Command extends BaseCommand { + + usage() { + return 'ren '; + } + + description() { + return _('Renames the given (note or notebook) to .'); + } + + async action(args) { + const pattern = args['item']; + const name = args['name']; + + const item = await app().loadItem('folderOrNote', pattern); + if (!item) throw new Error(_('Cannot find "%s".', pattern)); + + const newItem = { + id: item.id, + title: name, + type_: item.type_, + }; + + if (item.type_ === BaseModel.TYPE_FOLDER) { + await Folder.save(newItem); + } else { + await Note.save(newItem); + } + } + +} + +module.exports = Command; \ No newline at end of file diff --git a/CliClient/app/command-rm.js b/CliClient/app/command-rm.js deleted file mode 100644 index c65cd4f12..000000000 --- a/CliClient/app/command-rm.js +++ /dev/null @@ -1,50 +0,0 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseItem } from 'lib/models/base-item.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { BaseModel } from 'lib/base-model.js'; -import { cliUtils } from './cli-utils.js'; - -class Command extends BaseCommand { - - usage() { - return 'rm '; - } - - description() { - return _('Deletes the notes matching .'); - } - - options() { - return [ - ['-f, --force', _('Deletes the items without asking for confirmation.')], - ]; - } - - async action(args) { - const pattern = args['note-pattern']; - const recursive = args.options && args.options.recursive === true; - const force = args.options && args.options.force === true; - - // if (recursive) { - // const folder = await app().loadItem(BaseModel.TYPE_FOLDER, pattern); - // if (!folder) throw new Error(_('Cannot find "%s".', pattern)); - // //const ok = force ? true : await vorpalUtils.cmdPromptConfirm(this, _('Delete notebook "%s"?', folder.title)); - // if (!ok) return; - // await Folder.delete(folder.id); - // await app().refreshCurrentFolder(); - // } else { - - const notes = await app().loadItems(BaseModel.TYPE_NOTE, pattern); - if (!notes.length) throw new Error(_('Cannot find "%s".', pattern)); - const ok = force ? true : await cliUtils.promptConfirm(_('%d notes match this pattern. Delete them?', notes.length)); - if (!ok) return; - let ids = notes.map((n) => n.id); - await Note.batchDelete(ids); - } - -} - -module.exports = Command; \ No newline at end of file diff --git a/CliClient/app/command-rmbook.js b/CliClient/app/command-rmbook.js new file mode 100644 index 000000000..c5dc34597 --- /dev/null +++ b/CliClient/app/command-rmbook.js @@ -0,0 +1,40 @@ +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseItem } = require('lib/models/base-item.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { BaseModel } = require('lib/base-model.js'); +const { cliUtils } = require('./cli-utils.js'); + +class Command extends BaseCommand { + + usage() { + return 'rmbook '; + } + + description() { + return _('Deletes the given notebook.'); + } + + options() { + return [ + ['-f, --force', _('Deletes the notebook without asking for confirmation.')], + ]; + } + + async action(args) { + const pattern = args['notebook']; + const force = args.options && args.options.force === true; + + const folder = await app().loadItem(BaseModel.TYPE_FOLDER, pattern); + if (!folder) throw new Error(_('Cannot find "%s".', pattern)); + const ok = force ? true : await this.prompt(_('Delete notebook "%s"?', folder.title), { booleanAnswerDefault: 'n' }); + if (!ok) return; + + await Folder.delete(folder.id); + } + +} + +module.exports = Command; \ No newline at end of file diff --git a/CliClient/app/command-rmnote.js b/CliClient/app/command-rmnote.js new file mode 100644 index 000000000..8ad657763 --- /dev/null +++ b/CliClient/app/command-rmnote.js @@ -0,0 +1,41 @@ +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseItem } = require('lib/models/base-item.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { BaseModel } = require('lib/base-model.js'); +const { cliUtils } = require('./cli-utils.js'); + +class Command extends BaseCommand { + + usage() { + return 'rmnote '; + } + + description() { + return _('Deletes the notes matching .'); + } + + options() { + return [ + ['-f, --force', _('Deletes the notes without asking for confirmation.')], + ]; + } + + async action(args) { + const pattern = args['note-pattern']; + const force = args.options && args.options.force === true; + + const notes = await app().loadItems(BaseModel.TYPE_NOTE, pattern); + if (!notes.length) throw new Error(_('Cannot find "%s".', pattern)); + + const ok = force ? true : await this.prompt(notes.length > 1 ? _('%d notes match this pattern. Delete them?', notes.length) : _('Delete note?'), { booleanAnswerDefault: 'n' }); + if (!ok) return; + let ids = notes.map((n) => n.id); + await Note.batchDelete(ids); + } + +} + +module.exports = Command; \ No newline at end of file diff --git a/CliClient/app/command-search.js b/CliClient/app/command-search.js index 00c24c9ec..24031aee4 100644 --- a/CliClient/app/command-search.js +++ b/CliClient/app/command-search.js @@ -1,11 +1,12 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { sprintf } from 'sprintf-js'; -import { time } from 'lib/time-utils.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { sprintf } = require('sprintf-js'); +const { time } = require('lib/time-utils.js'); +const { uuid } = require('lib/uuid.js'); class Command extends BaseCommand { @@ -17,6 +18,10 @@ class Command extends BaseCommand { return _('Searches for the given in all the notes.'); } + compatibleUis() { + return ['gui']; + } + async action(args) { let pattern = args['pattern']; let folderTitle = args['notebook']; @@ -27,34 +32,52 @@ class Command extends BaseCommand { if (!folder) throw new Error(_('Cannot find "%s".', folderTitle)); } - let fields = Note.previewFields(); - fields.push('body'); - const notes = await Note.previews(folder ? folder.id : null, { - fields: fields, - anywherePattern: '*' + pattern + '*', + const searchId = uuid.create(); + + this.dispatch({ + type: 'SEARCH_ADD', + search: { + id: searchId, + title: pattern, + query_pattern: pattern, + query_folder_id: folder ? folder.id : '', + type_: BaseModel.TYPE_SEARCH, + }, }); - const fragmentLength = 50; + this.dispatch({ + type: 'SEARCH_SELECT', + id: searchId, + }); - let parents = {}; + // let fields = Note.previewFields(); + // fields.push('body'); + // const notes = await Note.previews(folder ? folder.id : null, { + // fields: fields, + // anywherePattern: '*' + pattern + '*', + // }); - for (let i = 0; i < notes.length; i++) { - const note = notes[i]; - const parent = parents[note.parent_id] ? parents[note.parent_id] : await Folder.load(note.parent_id); - parents[note.parent_id] = parent; + // const fragmentLength = 50; - const idx = note.body.indexOf(pattern); - let line = ''; - if (idx >= 0) { - let fragment = note.body.substr(Math.max(0, idx - fragmentLength / 2), fragmentLength); - fragment = fragment.replace(/\n/g, ' '); - line = sprintf('%s: %s / %s: %s', BaseModel.shortId(note.id), parent.title, note.title, fragment); - } else { - line = sprintf('%s: %s / %s', BaseModel.shortId(note.id), parent.title, note.title); - } + // let parents = {}; - this.log(line); - } + // for (let i = 0; i < notes.length; i++) { + // const note = notes[i]; + // const parent = parents[note.parent_id] ? parents[note.parent_id] : await Folder.load(note.parent_id); + // parents[note.parent_id] = parent; + + // const idx = note.body.indexOf(pattern); + // let line = ''; + // if (idx >= 0) { + // let fragment = note.body.substr(Math.max(0, idx - fragmentLength / 2), fragmentLength); + // fragment = fragment.replace(/\n/g, ' '); + // line = sprintf('%s: %s / %s: %s', BaseModel.shortId(note.id), parent.title, note.title, fragment); + // } else { + // line = sprintf('%s: %s / %s', BaseModel.shortId(note.id), parent.title, note.title); + // } + + // this.stdout(line); + // } } } diff --git a/CliClient/app/command-set.js b/CliClient/app/command-set.js index 8c11a5856..37274be92 100644 --- a/CliClient/app/command-set.js +++ b/CliClient/app/command-set.js @@ -1,10 +1,10 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { BaseItem } from 'lib/models/base-item.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { BaseItem } = require('lib/models/base-item.js'); class Command extends BaseCommand { @@ -12,6 +12,10 @@ class Command extends BaseCommand { return 'set [value]'; } + enabled() { + return false; + } + description() { return _('Sets the property of the given to the given [value].'); } diff --git a/CliClient/app/command-status.js b/CliClient/app/command-status.js index 66d59cb8c..1b252e66f 100644 --- a/CliClient/app/command-status.js +++ b/CliClient/app/command-status.js @@ -1,8 +1,9 @@ -import { BaseCommand } from './base-command.js'; -import { Database } from 'lib/database.js'; -import { Setting } from 'lib/models/setting.js'; -import { _ } from 'lib/locale.js'; -import { ReportService } from 'lib/services/report.js'; +const { BaseCommand } = require('./base-command.js'); +const { Database } = require('lib/database.js'); +const { app } = require('./app.js'); +const { Setting } = require('lib/models/setting.js'); +const { _ } = require('lib/locale.js'); +const { ReportService } = require('lib/services/report.js'); class Command extends BaseCommand { @@ -21,17 +22,20 @@ class Command extends BaseCommand { for (let i = 0; i < report.length; i++) { let section = report[i]; - if (i > 0) this.log(''); + if (i > 0) this.stdout(''); - this.log('# ' + section.title); - this.log(''); + this.stdout('# ' + section.title); + this.stdout(''); for (let n in section.body) { if (!section.body.hasOwnProperty(n)) continue; let line = section.body[n]; - this.log(line); + this.stdout(line); } } + + app().gui().showConsole(); + app().gui().maximizeConsole(); } } diff --git a/CliClient/app/command-sync.js b/CliClient/app/command-sync.js index db100b6a2..eba65ff68 100644 --- a/CliClient/app/command-sync.js +++ b/CliClient/app/command-sync.js @@ -1,13 +1,13 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { OneDriveApiNodeUtils } from './onedrive-api-node-utils.js'; -import { Setting } from 'lib/models/setting.js'; -import { BaseItem } from 'lib/models/base-item.js'; -import { Synchronizer } from 'lib/synchronizer.js'; -import { reg } from 'lib/registry.js'; -import { cliUtils } from './cli-utils.js'; -import md5 from 'md5'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { OneDriveApiNodeUtils } = require('./onedrive-api-node-utils.js'); +const { Setting } = require('lib/models/setting.js'); +const { BaseItem } = require('lib/models/base-item.js'); +const { Synchronizer } = require('lib/synchronizer.js'); +const { reg } = require('lib/registry.js'); +const { cliUtils } = require('./cli-utils.js'); +const md5 = require('md5'); const locker = require('proper-lockfile'); const fs = require('fs-extra'); const osTmpdir = require('os-tmpdir'); @@ -16,8 +16,9 @@ class Command extends BaseCommand { constructor() { super(); - this.syncTarget_ = null; + this.syncTargetId_ = null; this.releaseLockFn_ = null; + this.oneDriveApiUtils_ = null; } usage() { @@ -61,6 +62,27 @@ class Command extends BaseCommand { }); } + async doAuth(syncTargetId) { + const syncTarget = reg.syncTarget(this.syncTargetId_); + this.oneDriveApiUtils_ = new OneDriveApiNodeUtils(syncTarget.api()); + const auth = await this.oneDriveApiUtils_.oauthDance({ + log: (...s) => { return this.stdout(...s); } + }); + this.oneDriveApiUtils_ = null; + return auth; + } + + cancelAuth() { + if (this.oneDriveApiUtils_) { + this.oneDriveApiUtils_.cancelOAuthDance(); + return; + } + } + + doingAuth() { + return !!this.oneDriveApiUtils_; + } + async action(args) { this.releaseLockFn_ = null; @@ -75,24 +97,39 @@ class Command extends BaseCommand { } catch (error) { if (error.code == 'ELOCKED') { const msg = _('Lock file is already being hold. If you know that no synchronisation is taking place, you may delete the lock file at "%s" and resume the operation.', error.file); - this.log(msg); + this.stdout(msg); return; } throw error; } - try { - this.syncTarget_ = Setting.value('sync.target'); - if (args.options.target) this.syncTarget_ = args.options.target; + const cleanUp = () => { + cliUtils.redrawDone(); + if (this.releaseLockFn_) { + this.releaseLockFn_(); + this.releaseLockFn_ = null; + } + }; - if (this.syncTarget_ == Setting.SYNC_TARGET_ONEDRIVE && !reg.syncHasAuth(this.syncTarget_)) { - const oneDriveApiUtils = new OneDriveApiNodeUtils(reg.oneDriveApi()); - const auth = await oneDriveApiUtils.oauthDance(this); - Setting.setValue('sync.3.auth', auth ? JSON.stringify(auth) : null); - if (!auth) return; + try { + this.syncTargetId_ = Setting.value('sync.target'); + if (args.options.target) this.syncTargetId_ = args.options.target; + + const syncTarget = reg.syncTarget(this.syncTargetId_); + + if (!syncTarget.isAuthenticated()) { + app().gui().showConsole(); + app().gui().maximizeConsole(); + + const auth = await this.doAuth(this.syncTargetId_); + Setting.setValue('sync.' + this.syncTargetId_ + '.auth', auth ? JSON.stringify(auth) : null); + if (!auth) { + this.stdout(_('Authentication was not completed (did not receive an authentication token).')); + return cleanUp(); + } } - let sync = await reg.synchronizer(this.syncTarget_); + const sync = await syncTarget.synchronizer(); let options = { onProgress: (report) => { @@ -101,18 +138,18 @@ class Command extends BaseCommand { }, onMessage: (msg) => { cliUtils.redrawDone(); - this.log(msg); + this.stdout(msg); }, randomFailures: args.options['random-failures'] === true, }; - this.log(_('Synchronisation target: %s (%s)', Setting.enumOptionLabel('sync.target', this.syncTarget_), this.syncTarget_)); + this.stdout(_('Synchronisation target: %s (%s)', Setting.enumOptionLabel('sync.target', this.syncTargetId_), this.syncTargetId_)); if (!sync) throw new Error(_('Cannot initialize synchroniser.')); - this.log(_('Starting synchronisation...')); + this.stdout(_('Starting synchronisation...')); - const contextKey = 'sync.' + this.syncTarget_ + '.context'; + const contextKey = 'sync.' + this.syncTargetId_ + '.context'; let context = Setting.value(contextKey); context = context ? JSON.parse(context) : {}; @@ -123,7 +160,7 @@ class Command extends BaseCommand { Setting.setValue(contextKey, JSON.stringify(newContext)); } catch (error) { if (error.code == 'alreadyStarted') { - this.log(error.message); + this.stdout(error.message); } else { throw error; } @@ -131,33 +168,36 @@ class Command extends BaseCommand { await app().refreshCurrentFolder(); } catch (error) { - cliUtils.redrawDone(); - this.releaseLockFn_(); - this.releaseLockFn_ = null; + cleanUp(); throw error; } - cliUtils.redrawDone(); - this.releaseLockFn_(); - this.releaseLockFn_ = null; + cleanUp(); } async cancel() { - const target = this.syncTarget_ ? this.syncTarget_ : Setting.value('sync.target'); + if (this.doingAuth()) { + this.cancelAuth(); + return; + } + + const syncTargetId = this.syncTargetId_ ? this.syncTargetId_ : Setting.value('sync.target'); cliUtils.redrawDone(); - this.log(_('Cancelling... Please wait.')); + this.stdout(_('Cancelling... Please wait.')); - if (reg.syncHasAuth(target)) { - let sync = await reg.synchronizer(target); - if (sync) sync.cancel(); + const syncTarget = reg.syncTarget(syncTargetId); + + if (syncTarget.isAuthenticated()) { + const sync = await syncTarget.synchronizer(); + if (sync) await sync.cancel(); } else { if (this.releaseLockFn_) this.releaseLockFn_(); this.releaseLockFn_ = null; } - this.syncTarget_ = null; + this.syncTargetId_ = null; } cancellable() { diff --git a/CliClient/app/command-tag.js b/CliClient/app/command-tag.js index 33ad6f532..e31bf2330 100644 --- a/CliClient/app/command-tag.js +++ b/CliClient/app/command-tag.js @@ -1,8 +1,8 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { Tag } from 'lib/models/tag.js'; -import { BaseModel } from 'lib/base-model.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { Tag } = require('lib/models/tag.js'); +const { BaseModel } = require('lib/base-model.js'); class Command extends BaseCommand { @@ -28,7 +28,7 @@ class Command extends BaseCommand { if (command == 'add') { if (!notes.length) throw new Error(_('Cannot find "%s".', args.note)); - if (!tag) tag = await Tag.save({ title: args.tag }); + if (!tag) tag = await Tag.save({ title: args.tag }, { userSideValidation: true }); for (let i = 0; i < notes.length; i++) { await Tag.addNote(tag.id, notes[i].id); } @@ -41,10 +41,10 @@ class Command extends BaseCommand { } else if (command == 'list') { if (tag) { let notes = await Tag.notes(tag.id); - notes.map((note) => { this.log(note.title); }); + notes.map((note) => { this.stdout(note.title); }); } else { let tags = await Tag.all(); - tags.map((tag) => { this.log(tag.title); }); + tags.map((tag) => { this.stdout(tag.title); }); } } else { throw new Error(_('Invalid command: "%s"', command)); diff --git a/CliClient/app/command-todo.js b/CliClient/app/command-todo.js index 06385a02f..d31b7faeb 100644 --- a/CliClient/app/command-todo.js +++ b/CliClient/app/command-todo.js @@ -1,10 +1,10 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { time } from 'lib/time-utils.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { time } = require('lib/time-utils.js'); class Command extends BaseCommand { @@ -13,7 +13,7 @@ class Command extends BaseCommand { } description() { - return _(' can either be "toggle" or "clear". Use "toggle" to toggle the given todo between completed and uncompleted state (If the target is a regular note it will be converted to a todo). Use "clear" to convert the todo back to a regular note.'); + return _(' can either be "toggle" or "clear". Use "toggle" to toggle the given to-do between completed and uncompleted state (If the target is a regular note it will be converted to a to-do). Use "clear" to convert the to-do back to a regular note.'); } async action(args) { diff --git a/CliClient/app/command-undone.js b/CliClient/app/command-undone.js index 8c3c7012c..282a25dd5 100644 --- a/CliClient/app/command-undone.js +++ b/CliClient/app/command-undone.js @@ -1,10 +1,10 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { time } from 'lib/time-utils.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { time } = require('lib/time-utils.js'); const CommandDone = require('./command-done.js'); @@ -15,11 +15,11 @@ class Command extends BaseCommand { } description() { - return _('Marks a todo as non-completed.'); + return _('Marks a to-do as non-completed.'); } async action(args) { - CommandDone.handleAction(args, false); + await CommandDone.handleAction(args, false); } } diff --git a/CliClient/app/command-use.js b/CliClient/app/command-use.js index da55d7167..91157c10a 100644 --- a/CliClient/app/command-use.js +++ b/CliClient/app/command-use.js @@ -1,8 +1,8 @@ -import { BaseCommand } from './base-command.js'; -import { app } from './app.js'; -import { _ } from 'lib/locale.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; +const { BaseCommand } = require('./base-command.js'); +const { app } = require('./app.js'); +const { _ } = require('lib/locale.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); class Command extends BaseCommand { @@ -18,6 +18,10 @@ class Command extends BaseCommand { return { data: autocompleteFolders }; } + enabled() { + return false; + } + async action(args) { let folder = await app().loadItem(BaseModel.TYPE_FOLDER, args['notebook']); if (!folder) throw new Error(_('Cannot find "%s".', args['notebook'])); diff --git a/CliClient/app/command-version.js b/CliClient/app/command-version.js index 6372e6df2..cfb9bc11a 100644 --- a/CliClient/app/command-version.js +++ b/CliClient/app/command-version.js @@ -1,6 +1,6 @@ -import { BaseCommand } from './base-command.js'; -import { Setting } from 'lib/models/setting.js' -import { _ } from 'lib/locale.js'; +const { BaseCommand } = require('./base-command.js'); +const { Setting } = require('lib/models/setting.js'); +const { _ } = require('lib/locale.js'); class Command extends BaseCommand { @@ -14,7 +14,7 @@ class Command extends BaseCommand { async action(args) { const p = require('./package.json'); - this.log(_('%s %s (%s)', p.name, p.version, Setting.value('env'))); + this.stdout(_('%s %s (%s)', p.name, p.version, Setting.value('env'))); } } diff --git a/CliClient/app/fuzzing.js b/CliClient/app/fuzzing.js index 1d247959e..261678760 100644 --- a/CliClient/app/fuzzing.js +++ b/CliClient/app/fuzzing.js @@ -1,14 +1,11 @@ "use strict" -require('source-map-support').install(); -require('babel-plugin-transform-runtime'); - -import { time } from 'lib/time-utils.js'; -import { Logger } from 'lib/logger.js'; -import { Resource } from 'lib/models/resource.js'; -import { dirname } from 'lib/path-utils.js'; -import { FsDriverNode } from './fs-driver-node.js'; -import lodash from 'lodash'; +const { time } = require('lib/time-utils.js'); +const { Logger } = require('lib/logger.js'); +const { Resource } = require('lib/models/resource.js'); +const { dirname } = require('lib/path-utils.js'); +const { FsDriverNode } = require('./fs-driver-node.js'); +const lodash = require('lodash'); const exec = require('child_process').exec const fs = require('fs-extra'); diff --git a/CliClient/app/gui/ConsoleWidget.js b/CliClient/app/gui/ConsoleWidget.js new file mode 100644 index 000000000..e6bc30bd1 --- /dev/null +++ b/CliClient/app/gui/ConsoleWidget.js @@ -0,0 +1,52 @@ +const TextWidget = require('tkwidgets/TextWidget.js'); + +class ConsoleWidget extends TextWidget { + + constructor() { + super(); + this.lines_ = []; + this.updateText_ = false; + this.markdownRendering = false; + this.stickToBottom = true; + this.maxLines_ = 1000; + } + + get name() { + return 'console'; + } + + get lastLine() { + return this.lines_.length ? this.lines_[this.lines_.length-1] : ''; + } + + addLine(line) { + this.lines_.push(line); + this.updateText_ = true; + this.invalidate(); + } + + onFocus() { + this.stickToBottom = false; + super.onFocus(); + } + + onBlur() { + this.stickToBottom = true; + super.onBlur(); + } + + render() { + if (this.updateText_) { + if (this.lines_.length > this.maxLines_) { + this.lines_.splice(0, this.lines_.length - this.maxLines_); + } + this.text = this.lines_.join("\n"); + this.updateText_ = false; + } + + super.render(); + } + +} + +module.exports = ConsoleWidget; \ No newline at end of file diff --git a/CliClient/app/gui/FolderListWidget.js b/CliClient/app/gui/FolderListWidget.js new file mode 100644 index 000000000..8b9f5e15e --- /dev/null +++ b/CliClient/app/gui/FolderListWidget.js @@ -0,0 +1,165 @@ +const Folder = require('lib/models/folder.js').Folder; +const Tag = require('lib/models/tag.js').Tag; +const BaseModel = require('lib/base-model.js').BaseModel; +const ListWidget = require('tkwidgets/ListWidget.js'); +const _ = require('lib/locale.js')._; + +class FolderListWidget extends ListWidget { + + constructor() { + super(); + + this.tags_ = []; + this.folders_ = []; + this.searches_ = []; + this.selectedFolderId_ = null; + this.selectedTagId_ = null; + this.selectedSearchId_ = null; + this.notesParentType_ = 'Folder'; + this.updateIndexFromSelectedFolderId_ = false; + this.updateItems_ = false; + + this.itemRenderer = (item) => { + let output = []; + if (item === '-') { + output.push('-'.repeat(this.innerWidth)); + } else if (item.type_ === Folder.modelType()) { + output.push(item.title); + } else if (item.type_ === Tag.modelType()) { + output.push('[' + item.title + ']'); + } else if (item.type_ === BaseModel.TYPE_SEARCH) { + output.push(_('Search:')); + output.push(item.title); + } + + // if (item && item.id) output.push(item.id.substr(0, 5)); + + return output.join(' '); + }; + } + + get selectedFolderId() { + return this.selectedFolderId_; + } + + set selectedFolderId(v) { + this.selectedFolderId_ = v; + this.updateIndexFromSelectedItemId() + this.invalidate(); + } + + get selectedSearchId() { + return this.selectedSearchId_; + } + + set selectedSearchId(v) { + this.selectedSearchId_ = v; + this.updateIndexFromSelectedItemId() + this.invalidate(); + } + + get selectedTagId() { + return this.selectedTagId_; + } + + set selectedTagId(v) { + this.selectedTagId_ = v; + this.updateIndexFromSelectedItemId() + this.invalidate(); + } + + get notesParentType() { + return this.notesParentType_; + } + + set notesParentType(v) { + //if (this.notesParentType_ === v) return; + this.notesParentType_ = v; + this.updateIndexFromSelectedItemId() + this.invalidate(); + } + + get searches() { + return this.searches_; + } + + set searches(v) { + this.searches_ = v; + this.updateItems_ = true; + this.updateIndexFromSelectedItemId() + this.invalidate(); + } + + get tags() { + return this.tags_; + } + + set tags(v) { + this.tags_ = v; + this.updateItems_ = true; + this.updateIndexFromSelectedItemId() + this.invalidate(); + } + + get folders() { + return this.folders_; + } + + set folders(v) { + this.folders_ = v; + this.updateItems_ = true; + this.updateIndexFromSelectedItemId() + this.invalidate(); + } + + render() { + if (this.updateItems_) { + this.logger().debug('Rebuilding items...', this.notesParentType, this.selectedJoplinItemId, this.selectedSearchId); + const wasSelectedItemId = this.selectedJoplinItemId; + const previousParentType = this.notesParentType; + + let newItems = this.folders.slice(); + + if (this.tags.length) { + if (newItems.length) newItems.push('-'); + newItems = newItems.concat(this.tags); + } + + if (this.searches.length) { + if (newItems.length) newItems.push('-'); + newItems = newItems.concat(this.searches); + } + + this.items = newItems; + + this.notesParentType = previousParentType; + this.updateIndexFromSelectedItemId(wasSelectedItemId) + this.updateItems_ = false; + } + + super.render(); + } + + get selectedJoplinItemId() { + if (!this.notesParentType) return ''; + if (this.notesParentType === 'Folder') return this.selectedFolderId; + if (this.notesParentType === 'Tag') return this.selectedTagId; + if (this.notesParentType === 'Search') return this.selectedSearchId; + throw new Error('Unknown parent type: ' + this.notesParentType); + } + + get selectedJoplinItem() { + const id = this.selectedJoplinItemId; + const index = this.itemIndexByKey('id', id); + return this.itemAt(index); + } + + updateIndexFromSelectedItemId(itemId = null) { + if (itemId === null) itemId = this.selectedJoplinItemId; + const index = this.itemIndexByKey('id', itemId); + this.currentIndex = index >= 0 ? index : 0; + } + +} + +module.exports = FolderListWidget; \ No newline at end of file diff --git a/CliClient/app/gui/NoteListWidget.js b/CliClient/app/gui/NoteListWidget.js new file mode 100644 index 000000000..81341d25c --- /dev/null +++ b/CliClient/app/gui/NoteListWidget.js @@ -0,0 +1,38 @@ +const Note = require('lib/models/note.js').Note; +const ListWidget = require('tkwidgets/ListWidget.js'); + +class NoteListWidget extends ListWidget { + + constructor() { + super(); + this.selectedNoteId_ = 0; + + this.updateIndexFromSelectedNoteId_ = false; + + this.itemRenderer = (note) => { + let label = note.title; // + ' ' + note.id; + if (note.is_todo) { + label = '[' + (note.todo_completed ? 'X' : ' ') + '] ' + label; + } + return label; + }; + } + + set selectedNoteId(v) { + this.updateIndexFromSelectedNoteId_ = true; + this.selectedNoteId_ = v; + } + + render() { + if (this.updateIndexFromSelectedNoteId_) { + const index = this.itemIndexByKey('id', this.selectedNoteId_); + this.currentIndex = index >= 0 ? index : 0; + this.updateIndexFromSelectedNoteId_ = false; + } + + super.render(); + } + +} + +module.exports = NoteListWidget; \ No newline at end of file diff --git a/CliClient/app/gui/NoteMetadataWidget.js b/CliClient/app/gui/NoteMetadataWidget.js new file mode 100644 index 000000000..fc29e04f2 --- /dev/null +++ b/CliClient/app/gui/NoteMetadataWidget.js @@ -0,0 +1,36 @@ +const Note = require('lib/models/note.js').Note; +const TextWidget = require('tkwidgets/TextWidget.js'); + +class NoteMetadataWidget extends TextWidget { + + constructor() { + super(); + this.noteId_ = 0; + this.note_ = null; + } + + get noteId() { + return this.noteId_; + } + + set noteId(v) { + // If this is called it means either the note ID has changed OR + // the note content has changed, so we always set note_ to null + // so that it can be reloaded in onWillRender(). + this.noteId_ = v; + this.note_ = null; + this.invalidate(); + } + + async onWillRender() { + if (!this.visible) return; + + if (!this.note_ && this.noteId_) { + this.note_ = await Note.load(this.noteId_); + this.text = this.note_ ? await Note.minimalSerializeForDisplay(this.note_) : ''; + } + } + +} + +module.exports = NoteMetadataWidget; \ No newline at end of file diff --git a/CliClient/app/gui/NoteWidget.js b/CliClient/app/gui/NoteWidget.js new file mode 100644 index 000000000..eb565457f --- /dev/null +++ b/CliClient/app/gui/NoteWidget.js @@ -0,0 +1,51 @@ +const Note = require('lib/models/note.js').Note; +const TextWidget = require('tkwidgets/TextWidget.js'); + +class NoteWidget extends TextWidget { + + constructor() { + super(); + this.noteId_ = 0; + this.note_ = null; + this.notes_ = []; + this.lastLoadedNoteId_ = null; + } + + get notes() { + return this.notes_; + } + + set notes(v) { + // If the note collection has changed it means the current note might + // have changed or has been deleted, so refresh the note. + this.notes_ = v; + this.reloadNote(); + } + + get noteId() { + return this.noteId_; + } + + set noteId(v) { + this.noteId_ = v; + this.note_ = null; + this.reloadNote(); + } + + reloadNote() { + if (this.noteId_) { + this.doAsync('loadNote', async () => { + this.note_ = await Note.load(this.noteId_); + this.text = this.note_ ? this.note_.title + "\n\n" + this.note_.body : ''; + if (this.lastLoadedNoteId_ !== this.noteId_) this.scrollTop = 0; + this.lastLoadedNoteId_ = this.noteId_; + }); + } else { + this.text = ''; + this.scrollTop = 0; + } + } + +} + +module.exports = NoteWidget; \ No newline at end of file diff --git a/CliClient/app/gui/StatusBarWidget.js b/CliClient/app/gui/StatusBarWidget.js new file mode 100644 index 000000000..9b339a5a9 --- /dev/null +++ b/CliClient/app/gui/StatusBarWidget.js @@ -0,0 +1,162 @@ +const BaseWidget = require('tkwidgets/BaseWidget.js'); +const chalk = require('chalk'); +const termutils = require('tkwidgets/framework/termutils.js'); +const stripAnsi = require('strip-ansi'); + +class StatusBarWidget extends BaseWidget { + + constructor() { + super(); + + this.promptState_ = null; + this.inputEventEmitter_ = null; + this.history_ = []; + this.items_ = []; + } + + get name() { + return 'statusBar'; + } + + get canHaveFocus() { + return false; + } + + setItemAt(index, text) { + this.items_[index] = stripAnsi(text).trim(); + this.invalidate(); + } + + async prompt(initialText = '', promptString = null, options = null) { + if (this.promptState_) throw new Error('Another prompt already active'); + if (promptString === null) promptString = ':'; + if (options === null) options = {}; + + this.root.globalDisableKeyboard(this); + + this.promptState_ = { + promise: null, + initialText: stripAnsi(initialText), + promptString: stripAnsi(promptString), + }; + + if ('cursorPosition' in options) this.promptState_.cursorPosition = options.cursorPosition; + + this.promptState_.promise = new Promise((resolve, reject) => { + this.promptState_.resolve = resolve; + this.promptState_.reject = reject; + }); + + this.invalidate(); + + return this.promptState_.promise; + } + + get promptActive() { + return !!this.promptState_; + } + + get history() { + return this.history_; + } + + resetCursor() { + if (!this.promptActive) return; + if (!this.inputEventEmitter_) return; + + this.inputEventEmitter_.redraw(); + this.inputEventEmitter_.rebase(this.absoluteInnerX + termutils.textLength(this.promptState_.promptString), this.absoluteInnerY); + this.term.moveTo(this.absoluteInnerX + termutils.textLength(this.promptState_.promptString) + this.inputEventEmitter_.getInput().length, this.absoluteInnerY); + } + + render() { + super.render(); + + const doSaveCursor = !this.promptActive; + + if (doSaveCursor) this.term.saveCursor(); + + this.innerClear(); + + // Note: + // On Ubuntu, bgBlueBright looks too bright which makes the white text illegible + // On Windows, bgBlueBright is fine and looks dark enough (Windows is probably in the wrong though) + // For now, just don't use any colour at all. + + //const textStyle = this.promptActive ? (s) => s : chalk.bgBlueBright.white; + //const textStyle = (s) => s; + const textStyle = this.promptActive ? (s) => s : chalk.gray; + + this.term.drawHLine(this.absoluteInnerX, this.absoluteInnerY, this.innerWidth, textStyle(' ')); + + this.term.moveTo(this.absoluteInnerX, this.absoluteInnerY); + + if (this.promptActive) { + + this.term.write(textStyle(this.promptState_.promptString)); + + if (this.inputEventEmitter_) { + // inputField is already waiting for input so in that case just make + // sure that the cursor is at the right position and exit. + this.resetCursor(); + return; + } + + this.term.showCursor(true); + + let options = { + cancelable: true, + history: this.history, + default: this.promptState_.initialText, + }; + + if ('cursorPosition' in this.promptState_) options.cursorPosition = this.promptState_.cursorPosition; + + this.inputEventEmitter_ = this.term.inputField(options, (error, input) => { + let resolveResult = null; + const resolveFn = this.promptState_.resolve; + + if (error) { + this.logger().error('StatusBar: inputField error:', error); + } else { + if (input === undefined) { + // User cancel + } else { + resolveResult = input ? input.trim() : input; + // Add the command to history but only if it's longer than one character. + // Below that it's usually an answer like "y"/"n", etc. + if (input && input.length > 1) this.history_.push(input); + } + } + + // If the inputField spans several lines invalidate the root so that + // the interface is relayouted. + if (termutils.textLength(this.promptState_.promptString) + termutils.textLength(input) >= this.innerWidth - 5) { + this.root.invalidate(); + } + + this.inputEventEmitter_ = null; + this.term.showCursor(false); + this.promptState_ = null; + this.root.globalEnableKeyboard(this); + this.invalidate(); + + // Only callback once everything has been cleaned up and reset + resolveFn(resolveResult); + }); + + } else { + + for (let i = 0; i < this.items_.length; i++) { + const s = this.items_[i].substr(0, this.innerWidth - 1); + this.term.write(textStyle(s)); + } + + } + + if (doSaveCursor) this.term.restoreCursor(); + } + +} + +module.exports = StatusBarWidget; \ No newline at end of file diff --git a/CliClient/app/help-utils.js b/CliClient/app/help-utils.js index 8f3f38160..b45d4d0d1 100644 --- a/CliClient/app/help-utils.js +++ b/CliClient/app/help-utils.js @@ -1,23 +1,14 @@ -require('source-map-support').install(); -require('babel-plugin-transform-runtime'); - -import fs from 'fs-extra'; -import { fileExtension, basename, dirname } from 'lib/path-utils.js'; -import wrap_ from 'word-wrap'; -import { _, setLocale, languageCode } from 'lib/locale.js'; +const fs = require('fs-extra'); +const { wrap } = require('lib/string-utils.js'); +const { Setting } = require('lib/models/setting.js'); +const { fileExtension, basename, dirname } = require('lib/path-utils.js'); +const { _, setLocale, languageCode } = require('lib/locale.js'); const rootDir = dirname(dirname(__dirname)); const MAX_WIDTH = 78; const INDENT = ' '; -function wrap(text, indent) { - return wrap_(text, { - width: MAX_WIDTH - indent.length, - indent: indent, - }); -} - -function renderOptions(options, baseIndent) { +function renderTwoColumnData(options, baseIndent, width) { let output = []; const optionColWidth = getOptionColWidth(options); @@ -26,7 +17,7 @@ function renderOptions(options, baseIndent) { const flag = option[0]; const indent = baseIndent + INDENT + ' '.repeat(optionColWidth + 2); - let r = wrap(option[1], indent); + let r = wrap(option[1], indent, width); r = r.substr(flag.length + (baseIndent + INDENT).length); r = baseIndent + INDENT + flag + r; output.push(r); @@ -35,20 +26,73 @@ function renderOptions(options, baseIndent) { return output.join("\n"); } -function renderCommandHelp(cmd) { +function renderCommandHelp(cmd, width = null) { + if (width === null) width = MAX_WIDTH; + const baseIndent = ''; let output = []; output.push(baseIndent + cmd.usage()); output.push(''); - output.push(wrap(cmd.description(), baseIndent + INDENT)); + output.push(wrap(cmd.description(), baseIndent + INDENT, width)); - const optionString = renderOptions(cmd.options(), baseIndent); + const optionString = renderTwoColumnData(cmd.options(), baseIndent, width); if (optionString) { output.push(''); output.push(optionString); } + + if (cmd.name() === 'config') { + const renderMetadata = (md) => { + let desc = []; + + if (md.label) { + let label = md.label(); + if (label.length && label[label.length - 1] !== '.') label += '.'; + desc.push(label); + } + + if (md.description) { + desc.push(md.description()); + } + + desc.push(_('Type: %s.', md.isEnum ? _('Enum') : Setting.typeToString(md.type))); + if (md.isEnum) desc.push(_('Possible values: %s.', Setting.enumOptionsDoc(md.key, '%s (%s)'))); + + let defaultString = null; + + if ('value' in md) { + if (md.type === Setting.TYPE_STRING) { + defaultString = md.value ? '"' + md.value + '"' : null; + } else if (md.type === Setting.TYPE_INT) { + defaultString = (md.value ? md.value : 0).toString(); + } else if (md.type === Setting.TYPE_BOOL) { + defaultString = (md.value === true ? 'true' : 'false'); + } + } + + if (defaultString !== null) desc.push(_('Default: %s', defaultString)); + + return [md.key, desc.join("\n")]; + }; + + output.push(''); + output.push(_('Possible keys/values:')); + output.push(''); + + let keysValues = []; + const keys = Setting.keys(true, 'cli'); + for (let i = 0; i < keys.length; i++) { + if (keysValues.length) keysValues.push(['','']); + const md = Setting.settingMetadata(keys[i]); + if (!md.label) continue; + keysValues.push(renderMetadata(md)); + } + + output.push(renderTwoColumnData(keysValues, baseIndent, width)); + } + return output.join("\n"); } @@ -61,4 +105,4 @@ function getOptionColWidth(options) { return output; } -export { renderCommandHelp }; \ No newline at end of file +module.exports = { renderCommandHelp }; \ No newline at end of file diff --git a/CliClient/app/main.js b/CliClient/app/main.js index 5b9a2a0b4..3ddfe5a95 100644 --- a/CliClient/app/main.js +++ b/CliClient/app/main.js @@ -2,26 +2,21 @@ // Loading time: 20170803: 1.5s with no commands -require('source-map-support').install(); -require('babel-plugin-transform-runtime'); +require('app-module-path').addPath(__dirname); -import { app } from './app.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Resource } from 'lib/models/resource.js'; -import { BaseItem } from 'lib/models/base-item.js'; -import { Note } from 'lib/models/note.js'; -import { Tag } from 'lib/models/tag.js'; -import { NoteTag } from 'lib/models/note-tag.js'; -import { Setting } from 'lib/models/setting.js'; -import { Logger } from 'lib/logger.js'; -import { FsDriverNode } from './fs-driver-node.js'; -import { shimInit } from 'lib/shim-init-node.js'; -import { _ } from 'lib/locale.js'; - -process.on('unhandledRejection', (reason, p) => { - console.error('Unhandled promise rejection', p, 'reason:', reason); -}); +const { app } = require('./app.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Resource } = require('lib/models/resource.js'); +const { BaseItem } = require('lib/models/base-item.js'); +const { Note } = require('lib/models/note.js'); +const { Tag } = require('lib/models/tag.js'); +const { NoteTag } = require('lib/models/note-tag.js'); +const { Setting } = require('lib/models/setting.js'); +const { Logger } = require('lib/logger.js'); +const { FsDriverNode } = require('lib/fs-driver-node.js'); +const { shimInit } = require('lib/shim-init-node.js'); +const { _ } = require('lib/locale.js'); const fsDriver = new FsDriverNode(); Logger.fsDriver_ = fsDriver; @@ -53,19 +48,6 @@ if (process.platform === "win32") { }); } -let commandCancelCalled_ = false; - -process.on("SIGINT", async function() { - const cmd = application.currentCommand(); - - if (!cmd.cancellable() || commandCancelCalled_) { - process.exit(0); - } else { - commandCancelCalled_ = true; - await cmd.cancel(); - } -}); - process.stdout.on('error', function( err ) { // https://stackoverflow.com/questions/12329816/error-write-epipe-when-piping-node-output-to-head#15884508 if (err.code == "EPIPE") { @@ -73,7 +55,7 @@ process.stdout.on('error', function( err ) { } }); -application.start().catch((error) => { +application.start(process.argv).catch((error) => { console.error(_('Fatal error:')); console.error(error); }); \ No newline at end of file diff --git a/CliClient/app/onedrive-api-node-utils.js b/CliClient/app/onedrive-api-node-utils.js index 2bc3b1b69..b9ba88183 100644 --- a/CliClient/app/onedrive-api-node-utils.js +++ b/CliClient/app/onedrive-api-node-utils.js @@ -1,6 +1,6 @@ -import { _ } from 'lib/locale.js' +const { _ } = require('lib/locale.js'); +const { netUtils } = require('lib/net-utils.js'); -const tcpPortUsed = require('tcp-port-used'); const http = require("http"); const urlParser = require("url"); const FormData = require('form-data'); @@ -10,6 +10,7 @@ class OneDriveApiNodeUtils { constructor(api) { this.api_ = api; + this.oauthServer_ = null; } api() { @@ -32,33 +33,35 @@ class OneDriveApiNodeUtils { return header + message + footer; } + cancelOAuthDance() { + if (!this.oauthServer_) return; + this.oauthServer_.destroy(); + } + async oauthDance(targetConsole = null) { if (targetConsole === null) targetConsole = console; this.api().setAuth(null); - - - let ports = this.possibleOAuthDancePorts(); - let port = null; - for (let i = 0; i < ports.length; i++) { - let inUse = await tcpPortUsed.check(ports[i]); - if (!inUse) { - port = ports[i]; - break; - } - } - + const port = await netUtils.findAvailablePort(this.possibleOAuthDancePorts(), 0); if (!port) throw new Error(_('All potential ports are in use - please report the issue at %s', 'https://github.com/laurent22/joplin')); let authCodeUrl = this.api().authCodeUrl('http://localhost:' + port); return new Promise((resolve, reject) => { - let server = http.createServer(); + this.oauthServer_ = http.createServer(); let errorMessage = null; - server.on('request', (request, response) => { - const query = urlParser.parse(request.url, true).query; + this.oauthServer_.on('request', (request, response) => { + const url = urlParser.parse(request.url, true); + + if (url.pathname === '/auth') { + response.writeHead(302, { 'Location': authCodeUrl }); + response.end(); + return; + } + + const query = url.query; const writeResponse = (code, message) => { response.writeHead(code, {"Content-Type": "text/html"}); @@ -66,22 +69,32 @@ class OneDriveApiNodeUtils { response.end(); } + // After the response has been received, don't destroy the server right + // away or the browser might display a connection reset error (even + // though it worked). + const waitAndDestroy = () => { + setTimeout(() => { + this.oauthServer_.destroy(); + this.oauthServer_ = null; + }, 1000); + } + if (!query.code) return writeResponse(400, '"code" query parameter is missing'); this.api().execTokenRequest(query.code, 'http://localhost:' + port.toString()).then(() => { writeResponse(200, _('The application has been authorised - you may now close this browser tab.')); targetConsole.log(''); targetConsole.log(_('The application has been successfully authorised.')); - server.destroy(); + waitAndDestroy(); }).catch((error) => { writeResponse(400, error.message); targetConsole.log(''); targetConsole.log(error.message); - server.destroy(); + waitAndDestroy(); }); }); - server.on('close', () => { + this.oauthServer_.on('close', () => { if (errorMessage) { reject(new Error(errorMessage)); } else { @@ -89,16 +102,21 @@ class OneDriveApiNodeUtils { } }); - server.listen(port); + this.oauthServer_.listen(port); - enableServerDestroy(server); + enableServerDestroy(this.oauthServer_); + + // Rather than displaying authCodeUrl directly, we go throught the local + // server. This is just so that the URL being displayed is shorter and + // doesn't get cut in terminals (especially those that don't handle multi + // lines URLs). targetConsole.log(_('Please open the following URL in your browser to authenticate the application. The application will create a directory in "Apps/Joplin" and will only read and write files in this directory. It will have no access to any files outside this directory nor to any other personal data. No data will be shared with any third party.')); targetConsole.log(''); - targetConsole.log(authCodeUrl); + targetConsole.log('http://127.0.0.1:' + port + '/auth'); }); } } -export { OneDriveApiNodeUtils }; \ No newline at end of file +module.exports = { OneDriveApiNodeUtils }; \ No newline at end of file diff --git a/CliClient/build-website.sh b/CliClient/build-website.sh index 1c413050f..7d3c5dcfb 100755 --- a/CliClient/build-website.sh +++ b/CliClient/build-website.sh @@ -1,3 +1,4 @@ #!/bin/bash set -e -./build.sh && NODE_PATH=build node build/build-website.js \ No newline at end of file +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +"$ROOT_DIR/build.sh" && NODE_PATH="$ROOT_DIR/build" node "$ROOT_DIR/build/build-website.js" \ No newline at end of file diff --git a/CliClient/build.sh b/CliClient/build.sh index cf6a07898..133037199 100755 --- a/CliClient/build.sh +++ b/CliClient/build.sh @@ -1,37 +1,60 @@ #!/bin/bash ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +BUILD_DIR="$ROOT_DIR/build" -# require('cache-require-paths'); +rsync -a --exclude "node_modules/" "$ROOT_DIR/app/" "$BUILD_DIR/" +rsync -a "$ROOT_DIR/../ReactNativeClient/lib/" "$BUILD_DIR/lib/" +cp "$ROOT_DIR/package.json" "$BUILD_DIR" +chmod 755 "$BUILD_DIR/main.js" -mkdir -p "$ROOT_DIR/build" -rm -f "$ROOT_DIR/app/lib" -ln -s "$ROOT_DIR/../ReactNativeClient/lib" "$ROOT_DIR/app" +cd "$BUILD_DIR" +node build-translation.js --silent -npm run build -cp "$ROOT_DIR/package.json" "$ROOT_DIR/build" -cp "$ROOT_DIR/app/autocompletion_template.txt" "$ROOT_DIR/build" -chmod 755 "$ROOT_DIR/build/main.js" -if [[ ! -f "$ROOT_DIR/package.json.md5" ]]; then - "$ROOT_DIR/update-package-md5.sh" -fi -# Add modules on top of main.js: -# - cache-require-paths to cache require() calls -# - app-module-path so that lib/something paths can be resolved. -PACKAGE_MD5=$(cat "$ROOT_DIR/package.json.md5") -MAIN_PATH="$ROOT_DIR/build/main.js" -LINE_TO_ADD="var osTmpdir = require('os-tmpdir'); process.env.CACHE_REQUIRE_PATHS_FILE = osTmpdir() + '/joplin-module-path-cache-$PACKAGE_MD5'; require('cache-require-paths'); require('app-module-path').addPath(__dirname);" -RESULT="$(grep "$LINE_TO_ADD" "$MAIN_PATH")" -if [[ -z "$RESULT" ]]; then - echo "Adding extra modules..." - sed -i "2i $LINE_TO_ADD" "$MAIN_PATH" -else - echo "Extra modules already added." -fi -NODE_PATH="$ROOT_DIR/build" node "$ROOT_DIR/build/build-translation.js" --silent \ No newline at end of file + + +# ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +# # require('cache-require-paths'); + +# mkdir -p "$ROOT_DIR/build" +# rm -f "$ROOT_DIR/app/lib" +# ln -s "$ROOT_DIR/../ReactNativeClient/lib" "$ROOT_DIR/app" + +# npm run build || exit 1 + +# # Files under app/gui are in ES6 already but I cannot get Babel +# # to ignore them, so copy them back to the build directory. +# rsync -a "$ROOT_DIR/app/gui/" "$ROOT_DIR/build/gui/" + +# cp "$ROOT_DIR/package.json" "$ROOT_DIR/build" + +# chmod 755 "$ROOT_DIR/build/main.js" + +# # if [[ ! -f "$ROOT_DIR/package.json.md5" ]]; then +# # "$ROOT_DIR/update-package-md5.sh" +# # fi + +# # Add modules on top of main.js: +# # - cache-require-paths to cache require() calls +# # - app-module-path so that lib/something paths can be resolved. + +# #PACKAGE_MD5=$(cat "$ROOT_DIR/package.json.md5") +# MAIN_PATH="$ROOT_DIR/build/main.js" +# #LINE_TO_ADD="var osTmpdir = require('os-tmpdir'); process.env.CACHE_REQUIRE_PATHS_FILE = osTmpdir() + '/joplin-module-path-cache-$PACKAGE_MD5'; require('cache-require-paths'); require('app-module-path').addPath(__dirname);" +# LINE_TO_ADD="require('app-module-path').addPath(__dirname);" +# RESULT="$(grep "$LINE_TO_ADD" "$MAIN_PATH")" +# if [[ -z "$RESULT" ]]; then +# echo "Adding extra modules..." +# sed -i "2i $LINE_TO_ADD" "$MAIN_PATH" +# else +# echo "Extra modules already added." +# fi + +# NODE_PATH="$ROOT_DIR/build" node "$ROOT_DIR/build/build-translation.js" --silent \ No newline at end of file diff --git a/CliClient/install.sh b/CliClient/install.sh index e730ae2f1..7efe03e82 100755 --- a/CliClient/install.sh +++ b/CliClient/install.sh @@ -1,7 +1,6 @@ #!/bin/bash -set -e CLIENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -npm version patch -$CLIENT_DIR/build.sh -sudo rsync -aP "$CLIENT_DIR/build/" "/usr/lib/node_modules/joplin/" \ No newline at end of file + +"$CLIENT_DIR/publish.sh" +npm install -g joplin \ No newline at end of file diff --git a/CliClient/locales/en_GB.po b/CliClient/locales/en_GB.po index fbe27ed99..a955d5bb6 100644 --- a/CliClient/locales/en_GB.po +++ b/CliClient/locales/en_GB.po @@ -15,89 +15,123 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" +msgid "Give focus to next pane" +msgstr "" + +msgid "Give focus to previous pane" +msgstr "" + +msgid "Enter command line mode" +msgstr "" + +msgid "Exit command line mode" +msgstr "" + +msgid "Edit the selected note" +msgstr "" + +msgid "Cancel the current command." +msgstr "" + +msgid "Exit the application." +msgstr "" + +msgid "Delete the currently selected note or notebook." +msgstr "" + +msgid "To delete a tag, untag the associated notes." +msgstr "" + +msgid "Please select the note or notebook to be deleted first." +msgstr "" + +msgid "Set a to-do as completed / not completed" +msgstr "" + +msgid "[t]oggle [c]onsole between maximized/minimized/hidden/visible." +msgstr "" + +msgid "Search" +msgstr "" + +msgid "[t]oggle note [m]etadata." +msgstr "" + +msgid "[M]ake a new [n]ote" +msgstr "" + +msgid "[M]ake a new [t]odo" +msgstr "" + +msgid "[M]ake a new note[b]ook" +msgstr "" + +msgid "Copy ([Y]ank) the [n]ote to a notebook." +msgstr "" + +msgid "Move the note to a notebook." +msgstr "" + +msgid "Press Ctrl+D or type \"exit\" to exit the application" +msgstr "" + +#, javascript-format +msgid "More than one item match \"%s\". Please narrow down your query." +msgstr "" + msgid "No notebook selected." msgstr "" msgid "No notebook has been specified." msgstr "" -#, javascript-format -msgid "Usage: %s" -msgstr "" - -#, javascript-format -msgid "Unknown flag: %s" -msgstr "" - -#, javascript-format -msgid "" -"Command line argument \"%s\" contains both quotes and double-quotes - " -"aborting." -msgstr "" - -msgid "Provides help for a given command." -msgstr "" - -msgid "Exits the application." -msgstr "" - -msgid "Only Bash is currently supported for autocompletion." -msgstr "" - -msgid "" -"Autocompletion can be made to work with an alias too (such as a one-letter " -"command like \"j\").\n" -"If you would like to enable this, please type the alias now (leave it empty " -"for no alias):" -msgstr "" - -#, javascript-format -msgid "Created autocompletion script \"%s\"." -msgstr "" - -#, javascript-format -msgid "Autocompletion script is already present in \"%s\"." -msgstr "" - -#, javascript-format -msgid "Added autocompletion to \"%s\"." -msgstr "" - -#, javascript-format -msgid "Alias is already set in \"%s\"." -msgstr "" - -#, javascript-format -msgid "Added alias to \"%s\"." -msgstr "" - -#, javascript-format -msgid "" -"IMPORTANT: run the following command to initialise autocompletion in the " -"current shell:\n" -"source '%s'" -msgstr "" - -#, javascript-format -msgid "Missing required argument: %s" -msgstr "" - msgid "Y" msgstr "" msgid "n" msgstr "" -msgid "Displays the given note." +msgid "N" msgstr "" -msgid "Displays the complete information about note." +msgid "y" +msgstr "" + +msgid "Cancelling background synchronisation... Please wait." +msgstr "" + +#, javascript-format +msgid "The command \"%s\" is only available in GUI mode" +msgstr "" + +#, javascript-format +msgid "Missing required argument: %s" +msgstr "" + +#, javascript-format +msgid "%s: %s" +msgstr "" + +msgid "Your choice: " +msgstr "" + +#, javascript-format +msgid "Invalid answer: %s" +msgstr "" + +msgid "Attaches the given file to the note." msgstr "" #, javascript-format msgid "Cannot find \"%s\"." msgstr "" +msgid "Displays the given note." +msgstr "" + +msgid "Displays the complete information about note." +msgstr "" + msgid "" "Gets or sets a config value. If [value] is not provided, it will show the " "value of [name]. If neither [name] nor [value] is provided, it will list the " @@ -120,19 +154,16 @@ msgid "" "specified the note is duplicated in the current notebook." msgstr "" -msgid "Marks a todo as done." +msgid "Marks a to-do as done." msgstr "" #, javascript-format -msgid "Note is not a todo: \"%s\"" +msgid "Note is not a to-do: \"%s\"" msgstr "" msgid "Edit note." msgstr "" -msgid "Done editing." -msgstr "" - msgid "" "No text editor is defined. Please set it using `config editor `" msgstr "" @@ -147,7 +178,15 @@ msgstr "" msgid "Starting to edit note. Close the editor to get back to the prompt." msgstr "" -msgid "Exports Joplin data to the given target." +msgid "Note has been saved." +msgstr "" + +msgid "Exits the application." +msgstr "" + +msgid "" +"Exports Joplin data to the given directory. By default, it will export the " +"complete database including notebooks, notes, tags and resources." msgstr "" msgid "Exports only the given note." @@ -162,6 +201,42 @@ msgstr "" msgid "Displays usage information." msgstr "" +msgid "Shortcuts are not available in CLI mode." +msgstr "" + +msgid "Type `help [command]` for more information about a command." +msgstr "" + +msgid "The possible commands are:" +msgstr "" + +msgid "" +"In any command, a note or notebook can be refered to by title or ID, or " +"using the shortcuts `$n` or `$b` for, respectively, the currently selected " +"note or notebook. `$c` can be used to refer to the currently selected item." +msgstr "" + +msgid "To move from one pane to another, press Tab or Shift+Tab." +msgstr "" + +msgid "" +"Use the arrows and page up/down to scroll the lists and text areas " +"(including this console)." +msgstr "" + +msgid "To maximise/minimise the console, press \"TC\"." +msgstr "" + +msgid "To enter command line mode, press \":\"" +msgstr "" + +msgid "To exit command line mode, press ESCAPE" +msgstr "" + +msgid "" +"For the complete list of available keyboard shortcuts, type `help shortcuts`" +msgstr "" + msgid "Imports an Evernote notebook file (.enex file)." msgstr "" @@ -205,6 +280,10 @@ msgstr "" msgid "Importing notes..." msgstr "" +#, javascript-format +msgid "The notes have been imported: %s" +msgstr "" + msgid "" "Displays the notes in the current notebook. Use `ls /` to display the list " "of notebooks." @@ -221,8 +300,8 @@ msgstr "" msgid "" "Displays only the items of the specific type(s). Can be `n` for notes, `t` " -"for todos, or `nt` for notes and todos (eg. `-tt` would display only the " -"todos, while `-ttd` would display notes and todos." +"for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the " +"to-dos, while `-ttd` would display notes and to-dos." msgstr "" msgid "Either \"text\" or \"json\"" @@ -230,7 +309,7 @@ msgstr "" msgid "" "Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, " -"TODO_CHECKED (for todos), TITLE" +"TODO_CHECKED (for to-dos), TITLE" msgstr "" msgid "Please select a notebook first." @@ -245,22 +324,38 @@ msgstr "" msgid "Notes can only be created within a notebook." msgstr "" -msgid "Creates a new todo." +msgid "Creates a new to-do." msgstr "" -msgid "Moves the notes matching to [notebook]." +msgid "Moves the notes matching to [notebook]." +msgstr "" + +msgid "Renames the given (note or notebook) to ." +msgstr "" + +msgid "Deletes the given notebook." +msgstr "" + +msgid "Deletes the notebook without asking for confirmation." +msgstr "" + +#, javascript-format +msgid "Delete notebook \"%s\"?" msgstr "" msgid "Deletes the notes matching ." msgstr "" -msgid "Deletes the items without asking for confirmation." +msgid "Deletes the notes without asking for confirmation." msgstr "" #, javascript-format msgid "%d notes match this pattern. Delete them?" msgstr "" +msgid "Delete note?" +msgstr "" + msgid "Searches for the given in all the notes." msgstr "" @@ -286,6 +381,10 @@ msgid "" "operation." msgstr "" +msgid "" +"Authentication was not completed (did not receive an authentication token)." +msgstr "" + #, javascript-format msgid "Synchronisation target: %s (%s)" msgstr "" @@ -311,12 +410,12 @@ msgstr "" msgid "" " can either be \"toggle\" or \"clear\". Use \"toggle\" to " -"toggle the given todo between completed and uncompleted state (If the target " -"is a regular note it will be converted to a todo). Use \"clear\" to convert " -"the todo back to a regular note." +"toggle the given to-do between completed and uncompleted state (If the " +"target is a regular note it will be converted to a to-do). Use \"clear\" to " +"convert the to-do back to a regular note." msgstr "" -msgid "Marks a todo as non-completed." +msgid "Marks a to-do as non-completed." msgstr "" msgid "" @@ -331,6 +430,24 @@ msgstr "" msgid "%s %s (%s)" msgstr "" +msgid "Enum" +msgstr "" + +#, javascript-format +msgid "Type: %s." +msgstr "" + +#, javascript-format +msgid "Possible values: %s." +msgstr "" + +#, javascript-format +msgid "Default: %s" +msgstr "" + +msgid "Possible keys/values:" +msgstr "" + msgid "Fatal error:" msgstr "" @@ -349,6 +466,180 @@ msgid "" "will be shared with any third party." msgstr "" +msgid "Search:" +msgstr "" + +msgid "File" +msgstr "" + +msgid "New note" +msgstr "" + +msgid "New to-do" +msgstr "" + +msgid "New notebook" +msgstr "" + +msgid "Import Evernote notes" +msgstr "" + +msgid "Evernote Export Files" +msgstr "" + +msgid "Quit" +msgstr "" + +msgid "Edit" +msgstr "" + +msgid "Copy" +msgstr "" + +msgid "Cut" +msgstr "" + +msgid "Paste" +msgstr "" + +msgid "Search in all the notes" +msgstr "" + +msgid "Tools" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Help" +msgstr "" + +msgid "Website and documentation" +msgstr "" + +msgid "About Joplin" +msgstr "" + +#, javascript-format +msgid "%s %s (%s, %s)" +msgstr "" + +msgid "OK" +msgstr "" + +msgid "Cancel" +msgstr "" + +msgid "Back" +msgstr "" + +#, javascript-format +msgid "" +"New notebook \"%s\" will be created and file \"%s\" will be imported into it" +msgstr "" + +msgid "Please create a notebook first." +msgstr "" + +msgid "Note title:" +msgstr "" + +msgid "Please create a notebook first" +msgstr "" + +msgid "To-do title:" +msgstr "" + +msgid "Notebook title:" +msgstr "" + +msgid "Add or remove tags:" +msgstr "" + +msgid "Separate each tag by a comma." +msgstr "" + +msgid "Rename notebook:" +msgstr "" + +msgid "Layout" +msgstr "" + +msgid "Add or remove tags" +msgstr "" + +msgid "Switch between note and to-do type" +msgstr "" + +msgid "Delete" +msgstr "" + +msgid "Delete notes?" +msgstr "" + +msgid "No notes in here. Create one by clicking on \"New note\"." +msgstr "" + +#, javascript-format +msgid "Unsupported link or message: %s" +msgstr "" + +msgid "Attach file" +msgstr "" + +msgid "Refresh" +msgstr "" + +msgid "OneDrive Login" +msgstr "" + +msgid "Import" +msgstr "" + +msgid "Configuration" +msgstr "" + +msgid "Delete notebook?" +msgstr "" + +msgid "Remove this tag from all the notes?" +msgstr "" + +msgid "Remove this search from the sidebar?" +msgstr "" + +msgid "Rename" +msgstr "" + +msgid "Synchronise" +msgstr "" + +msgid "Notebooks" +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "Searches" +msgstr "" + +#, javascript-format +msgid "Usage: %s" +msgstr "" + +#, javascript-format +msgid "Unknown flag: %s" +msgstr "" + +msgid "File system" +msgstr "" + +msgid "OneDrive" +msgstr "" + +msgid "OneDrive Dev (For testing only)" +msgstr "" + #, javascript-format msgid "Unknown log level: %s" msgstr "" @@ -362,9 +653,8 @@ msgid "" "synchronisation again may fix the problem." msgstr "" -msgid "" -"Please set the \"sync.2.path\" config value to the desired synchronisation " -"destination." +#, javascript-format +msgid "Cannot access %s" msgstr "" #, javascript-format @@ -431,42 +721,38 @@ msgstr "" msgid "Cannot move note to \"%s\" notebook" msgstr "" -#, javascript-format -msgid "Invalid option value: \"%s\". Possible values are: %s." +msgid "File system synchronisation target directory" msgstr "" -#, javascript-format -msgid "%s: %s" +msgid "" +"The path to synchronise with when file system synchronisation is enabled. " +"See `sync.target`." msgstr "" -msgid "Synchronisation target" +msgid "Text editor" msgstr "" -msgid "File system" -msgstr "" - -msgid "OneDrive" +msgid "" +"The editor that will be used to open a note. If none is provided it will try " +"to auto-detect the default editor." msgstr "" msgid "Language" msgstr "" -msgid "Todo filter" +msgid "Theme" msgstr "" -msgid "Show all" +msgid "Light" msgstr "" -msgid "Non-completed and recently completed ones" -msgstr "" - -msgid "Non-completed ones only" +msgid "Dark" msgstr "" msgid "Show uncompleted todos on top of the lists" msgstr "" -msgid "Save location with notes" +msgid "Save geo-location with notes" msgstr "" msgid "Synchronisation interval" @@ -487,13 +773,22 @@ msgstr "" msgid "%d hours" msgstr "" -msgid "Theme" +msgid "Automatically update the application" msgstr "" -msgid "Light" +msgid "Show advanced options" msgstr "" -msgid "Dark" +msgid "Synchronisation target" +msgstr "" + +msgid "" +"The target to synchonise to. If synchronising with the file system, set " +"`sync.2.path` to specify the target directory." +msgstr "" + +#, javascript-format +msgid "Invalid option value: \"%s\". Possible values are: %s." msgstr "" msgid "Sync status (synced items / total items)" @@ -522,28 +817,26 @@ msgstr "" msgid "%s: %d notes" msgstr "" -msgid "New todo" -msgstr "" - -msgid "New note" -msgstr "" - -msgid "New notebook" -msgstr "" - msgid "There are currently no notes. Create one by clicking on the (+) button." msgstr "" +msgid "Delete these notes?" +msgstr "" + msgid "Log" msgstr "" msgid "Status" msgstr "" -msgid "Configuration" +msgid "Export Debug Report" msgstr "" -msgid "Synchronise" +msgid "Move to notebook..." +msgstr "" + +#, javascript-format +msgid "Move %d notes to notebook \"%s\"?" msgstr "" msgid "Cancel synchronisation" @@ -556,13 +849,23 @@ msgstr "" msgid "Edit notebook" msgstr "" -msgid "Refresh" +msgid "This note has been modified:" msgstr "" -msgid "Delete note?" +msgid "Save changes" msgstr "" -msgid "Attach file" +msgid "Discard changes" +msgstr "" + +#, javascript-format +msgid "Unsupported image type: %s" +msgstr "" + +msgid "Attach image" +msgstr "" + +msgid "Attach any other file" msgstr "" msgid "Delete note" @@ -583,21 +886,12 @@ msgstr "" msgid "View location on map" msgstr "" -msgid "Edit" -msgstr "" - -msgid "Delete notebook?" -msgstr "" - msgid "Delete notebook" msgstr "" msgid "Login with OneDrive" msgstr "" -msgid "Search" -msgstr "" - msgid "" "Click on the (+) button to create a new note or notebook. Click on the side " "menu to access your existing notebooks." diff --git a/CliClient/locales/fr_FR.po b/CliClient/locales/fr_FR.po index 9515b39e0..d8a79573b 100644 --- a/CliClient/locales/fr_FR.po +++ b/CliClient/locales/fr_FR.po @@ -15,80 +15,117 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Generator: Poedit 2.0.3\n" +msgid "Give focus to next pane" +msgstr "Activer le volet suivant" + +msgid "Give focus to previous pane" +msgstr "Activer le volet précédent" + +msgid "Enter command line mode" +msgstr "Démarrer le mode de ligne de commande" + +msgid "Exit command line mode" +msgstr "Sortir du mode de ligne de commande" + +msgid "Edit the selected note" +msgstr "Éditer la note sélectionnée" + +msgid "Cancel the current command." +msgstr "Annuler la commande en cours." + +msgid "Exit the application." +msgstr "Quitter le logiciel." + +msgid "Delete the currently selected note or notebook." +msgstr "Supprimer la note ou carnet sélectionné." + +msgid "To delete a tag, untag the associated notes." +msgstr "Pour supprimer une vignette, enlever là des notes associées." + +msgid "Please select the note or notebook to be deleted first." +msgstr "Veuillez d'abord sélectionner un carnet." + +msgid "Set a to-do as completed / not completed" +msgstr "Marquer une tâches comme complétée / non-complétée" + +msgid "[t]oggle [c]onsole between maximized/minimized/hidden/visible." +msgstr "Maximiser, minimiser, cacher ou rendre visible la console." + +msgid "Search" +msgstr "Chercher" + +msgid "[t]oggle note [m]etadata." +msgstr "Afficher/Cacher les métadonnées des notes." + +msgid "[M]ake a new [n]ote" +msgstr "Créer une nouvelle note" + +msgid "[M]ake a new [t]odo" +msgstr "Créer une nouvelle tâche" + +msgid "[M]ake a new note[b]ook" +msgstr "Créer un nouveau carnet" + +msgid "Copy ([Y]ank) the [n]ote to a notebook." +msgstr "Copier la note dans un autre carnet." + +msgid "Move the note to a notebook." +msgstr "Déplacer la note vers un carnet." + +msgid "Press Ctrl+D or type \"exit\" to exit the application" +msgstr "Appuyez sur Ctrl+D ou tapez \"exit\" pour sortir du logiciel" + +#, javascript-format +msgid "More than one item match \"%s\". Please narrow down your query." +msgstr "Plus d'un objet correspond à \"%s\". Veuillez préciser votre requête." + msgid "No notebook selected." msgstr "Aucun carnet n'est sélectionné." msgid "No notebook has been specified." msgstr "Aucun carnet n'est spécifié." -#, javascript-format -msgid "Usage: %s" -msgstr "Utilisation : %s." +msgid "Y" +msgstr "O" + +msgid "n" +msgstr "n" + +msgid "N" +msgstr "N" + +msgid "y" +msgstr "o" + +msgid "Cancelling background synchronisation... Please wait." +msgstr "Annulation de la synchronisation... Veuillez patienter." #, javascript-format -msgid "Unknown flag: %s" -msgstr "Paramètre inconnu : %s" - -#, javascript-format -msgid "" -"Command line argument \"%s\" contains both quotes and double-quotes - " -"aborting." -msgstr "" -"Le paramètre de ligne de commande \"%s\" contient à la fois des guillemets " -"simples et doubles - impossible de continuer." - -msgid "Provides help for a given command." -msgstr "Affiche l'aide pour la commande donnée." - -msgid "Exits the application." -msgstr "Quitter le logiciel." - -msgid "Only Bash is currently supported for autocompletion." -msgstr "" - -msgid "" -"Autocompletion can be made to work with an alias too (such as a one-letter " -"command like \"j\").\n" -"If you would like to enable this, please type the alias now (leave it empty " -"for no alias):" -msgstr "" - -#, javascript-format -msgid "Created autocompletion script \"%s\"." -msgstr "" - -#, javascript-format -msgid "Autocompletion script is already present in \"%s\"." -msgstr "" - -#, javascript-format -msgid "Added autocompletion to \"%s\"." -msgstr "" - -#, javascript-format -msgid "Alias is already set in \"%s\"." -msgstr "" - -#, javascript-format -msgid "Added alias to \"%s\"." -msgstr "" - -#, javascript-format -msgid "" -"IMPORTANT: run the following command to initialise autocompletion in the " -"current shell:\n" -"source '%s'" +msgid "The command \"%s\" is only available in GUI mode" msgstr "" +"La commande \"%s\" est disponible uniquement en mode d'interface graphique" #, javascript-format msgid "Missing required argument: %s" -msgstr "" +msgstr "Paramètre requis manquant : %s" -msgid "Y" -msgstr "" +#, javascript-format +msgid "%s: %s" +msgstr "%s : %s" -msgid "n" -msgstr "" +msgid "Your choice: " +msgstr "Votre choix : " + +#, javascript-format +msgid "Invalid answer: %s" +msgstr "Réponse invalide : %s" + +msgid "Attaches the given file to the note." +msgstr "Joindre le fichier fourni à la note." + +#, javascript-format +msgid "Cannot find \"%s\"." +msgstr "Impossible de trouver \"%s\"." msgid "Displays the given note." msgstr "Affiche la note." @@ -96,10 +133,6 @@ msgstr "Affiche la note." msgid "Displays the complete information about note." msgstr "Affiche tous les détails de la note." -#, javascript-format -msgid "Cannot find \"%s\"." -msgstr "Impossible de trouver \"%s\"." - msgid "" "Gets or sets a config value. If [value] is not provided, it will show the " "value of [name]. If neither [name] nor [value] is provided, it will list the " @@ -109,7 +142,6 @@ msgstr "" "fournie, la valeur de [nom] est affichée. Si ni le [nom] ni la [valeur] ne " "sont fournis, la configuration complète est affichée." -#, fuzzy msgid "Also displays unset and hidden config variables." msgstr "Afficher également les variables cachées." @@ -121,26 +153,22 @@ msgstr "%s = %s (%s)" msgid "%s = %s" msgstr "%s = %s" -#, fuzzy msgid "" "Duplicates the notes matching to [notebook]. If no notebook is " "specified the note is duplicated in the current notebook." msgstr "" -"Copie les notes correspondant à [nom] vers [carnet]. Si aucun carnet n'est " -"spécifié, la note est dupliqué sur place." +"Copier les notes correspondant à vers [carnet]. Si aucun carnet n'est " +"spécifié, la note est dupliquée sur place." -msgid "Marks a todo as done." -msgstr "" +msgid "Marks a to-do as done." +msgstr "Marquer la tâche comme complétée." #, javascript-format -msgid "Note is not a todo: \"%s\"" -msgstr "" +msgid "Note is not a to-do: \"%s\"" +msgstr "La note n'est pas une tâche : \"%s\"" msgid "Edit note." -msgstr "Editer la note." - -msgid "Done editing." -msgstr "Edition terminée." +msgstr "Éditer la note." msgid "" "No text editor is defined. Please set it using `config editor `" @@ -157,26 +185,77 @@ msgstr "Cette note n'existe pas : \"%s\". La créer ?" msgid "Starting to edit note. Close the editor to get back to the prompt." msgstr "" -"Edition de la note en cours. Fermez l'éditeur de texte pour retourner à " +"Édition de la note en cours. Fermez l'éditeur de texte pour retourner à " "l'invite de commande." -msgid "Exports Joplin data to the given target." +msgid "Note has been saved." +msgstr "La note a été enregistrée." + +msgid "Exits the application." +msgstr "Quitter le logiciel." + +msgid "" +"Exports Joplin data to the given directory. By default, it will export the " +"complete database including notebooks, notes, tags and resources." msgstr "" +"Exporter les données de Joplin vers le dossier fourni. Par défaut, la base " +"de donnée complète sera exportée, y compris les carnets, notes, tags et " +"resources." -#, fuzzy msgid "Exports only the given note." -msgstr "Affiche la note." +msgstr "Exporter uniquement la note spécifiée." -#, fuzzy msgid "Exports only the given notebook." -msgstr "Affiche la note." +msgstr "Exporter uniquement le carnet spécifié." msgid "Displays a geolocation URL for the note." msgstr "Afficher l'URL de l'emplacement de la note." -#, fuzzy msgid "Displays usage information." -msgstr "Affiche les informations de version" +msgstr "Affiche les informations d'utilisation." + +msgid "Shortcuts are not available in CLI mode." +msgstr "Les raccourcis ne sont pas disponible en mode de ligne de commande." + +msgid "Type `help [command]` for more information about a command." +msgstr "Tapez `help [command]` pour plus d'information sur une commande." + +msgid "The possible commands are:" +msgstr "Les commandes possibles sont :" + +msgid "" +"In any command, a note or notebook can be refered to by title or ID, or " +"using the shortcuts `$n` or `$b` for, respectively, the currently selected " +"note or notebook. `$c` can be used to refer to the currently selected item." +msgstr "" +"Dans une commande, une note ou carnet peut être référé par titre ou " +"identifiant, ou en utilisant les raccourcis `$n` et `$b` pour, " +"respectivement, la note sélectionnée et le carnet sélectionné. `$c` peut " +"être utilisé pour faire référence à l'objet sélectionné en cours." + +msgid "To move from one pane to another, press Tab or Shift+Tab." +msgstr "Pour aller d'un volet à l'autre, pressez Tab ou Maj+Tab." + +msgid "" +"Use the arrows and page up/down to scroll the lists and text areas " +"(including this console)." +msgstr "" +"Utilisez les touches fléchées et page précédente/suivante pour faire défiler " +"les listes et zones de texte (y compris cette console)." + +msgid "To maximise/minimise the console, press \"TC\"." +msgstr "Pour maximiser ou minimiser la console, pressez \"TC\"." + +msgid "To enter command line mode, press \":\"" +msgstr "Pour démarrer le mode ligne de commande, pressez \":\"" + +msgid "To exit command line mode, press ESCAPE" +msgstr "Pour sortir du mode ligne de commande, pressez ECHAP" + +msgid "" +"For the complete list of available keyboard shortcuts, type `help shortcuts`" +msgstr "" +"Pour la liste complète des raccourcis disponibles, tapez `help shortcuts`" msgid "Imports an Evernote notebook file (.enex file)." msgstr "Importer un carnet Evernote (fichier .enex)." @@ -207,7 +286,7 @@ msgstr "Créés : %d." #, javascript-format msgid "Updated: %d." -msgstr "Mise à jour : %d." +msgstr "Mis à jour : %d." #, javascript-format msgid "Skipped: %d." @@ -219,12 +298,15 @@ msgstr "Ressources : %d." #, javascript-format msgid "Tagged: %d." -msgstr "Etiquettes : %d." +msgstr "Étiquettes : %d." msgid "Importing notes..." msgstr "Importation des notes..." -#, fuzzy +#, javascript-format +msgid "The notes have been imported: %s" +msgstr "Les notes ont été importées : %s" + msgid "" "Displays the notes in the current notebook. Use `ls /` to display the list " "of notebooks." @@ -244,8 +326,8 @@ msgstr "Inverser l'ordre." msgid "" "Displays only the items of the specific type(s). Can be `n` for notes, `t` " -"for todos, or `nt` for notes and todos (eg. `-tt` would display only the " -"todos, while `-ttd` would display notes and todos." +"for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the " +"to-dos, while `-ttd` would display notes and to-dos." msgstr "" "Affiche uniquement les notes du ou des types spécifiés. Le type peut-être " "`n` pour les notes, `t` pour les tâches (par exemple, `-tt` affiche " @@ -256,7 +338,7 @@ msgstr "Soit \"text\" soit \"json\"" msgid "" "Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, " -"TODO_CHECKED (for todos), TITLE" +"TODO_CHECKED (for to-dos), TITLE" msgstr "" "Utilise le format de liste longue. Le format est ID, NOMBRE_DE_NOTES (pour " "les carnets), DATE, TACHE_TERMINE (pour les tâches), TITRE" @@ -273,24 +355,38 @@ msgstr "Créer une note." msgid "Notes can only be created within a notebook." msgstr "Les notes ne peuvent être créées que dans un carnet." -msgid "Creates a new todo." +msgid "Creates a new to-do." msgstr "Créer une nouvelle tâche." -#, fuzzy -msgid "Moves the notes matching to [notebook]." -msgstr "Supprime les objets correspondants à ." +msgid "Moves the notes matching to [notebook]." +msgstr "Déplacer les notes correspondant à vers [notebook]." + +msgid "Renames the given (note or notebook) to ." +msgstr "Renommer l'objet (note ou carnet) en ." + +msgid "Deletes the given notebook." +msgstr "Supprimer le carnet." + +msgid "Deletes the notebook without asking for confirmation." +msgstr "Supprimer le carnet sans demander la confirmation." + +#, javascript-format +msgid "Delete notebook \"%s\"?" +msgstr "Supprimer le carnet \"%s\" ?" -#, fuzzy msgid "Deletes the notes matching ." -msgstr "Supprime les objets correspondants à ." +msgstr "Supprimer les notes correspondants à ." -msgid "Deletes the items without asking for confirmation." -msgstr "Supprime les objets sans demander la confirmation." +msgid "Deletes the notes without asking for confirmation." +msgstr "Supprimer les notes sans demander la confirmation." #, javascript-format msgid "%d notes match this pattern. Delete them?" msgstr "%d notes correspondent à ce motif. Les supprimer ?" +msgid "Delete note?" +msgstr "Supprimer la note ?" + msgid "Searches for the given in all the notes." msgstr "Chercher le motif dans toutes les notes." @@ -317,6 +413,13 @@ msgid "" "taking place, you may delete the lock file at \"%s\" and resume the " "operation." msgstr "" +"La synchronisation est déjà en cours ou ne s'est pas interrompue " +"correctement. Si vous savez qu'aucune autre synchronisation est en cours, " +"vous pouvez supprimer le fichier \"%s\" pour reprendre l'opération." + +msgid "" +"Authentication was not completed (did not receive an authentication token)." +msgstr "Impossible d'autoriser le logiciel (jeton d'identification non-reçu)." #, javascript-format msgid "Synchronisation target: %s (%s)" @@ -328,39 +431,36 @@ msgstr "Impossible d'initialiser la synchronisation." msgid "Starting synchronisation..." msgstr "Commencement de la synchronisation..." -#, fuzzy msgid "Cancelling... Please wait." -msgstr "Annulation..." +msgstr "Annulation... Veuillez attendre." -#, fuzzy msgid "" " can be \"add\", \"remove\" or \"list\" to assign or remove " "[tag] from [note], or to list the notes associated with [tag]. The command " "`tag list` can be used to list all the tags." msgstr "" -" peut être \"add\", \"remove\" ou \"list\" pour assigner ou enlever " -"l'étiquette [tag] de la [note], our pour lister les notes associées avec " -"l'étiquette [tag]. La commande `tag list` peut être utilisée pour lister les " -"étiquettes." +" peut être \"add\", \"remove\" ou \"list\" pour assigner ou " +"enlever l'étiquette [tag] de la [note], our pour lister les notes associées " +"avec l'étiquette [tag]. La commande `tag list` peut être utilisée pour " +"lister les étiquettes." #, javascript-format msgid "Invalid command: \"%s\"" msgstr "Commande invalide : \"%s\"" -#, fuzzy msgid "" " can either be \"toggle\" or \"clear\". Use \"toggle\" to " -"toggle the given todo between completed and uncompleted state (If the target " -"is a regular note it will be converted to a todo). Use \"clear\" to convert " -"the todo back to a regular note." +"toggle the given to-do between completed and uncompleted state (If the " +"target is a regular note it will be converted to a to-do). Use \"clear\" to " +"convert the to-do back to a regular note." msgstr "" -"Gère le status des tâches. peut être \"toggle\" ou \"clear\". " +"Gère le status des tâches. peut être \"toggle\" ou \"clear\". " "Utilisez \"toggle\" pour basculer la tâche entre le status terminé et non-" "terminé (Si la cible est une note, elle sera convertie en tâche). Utilisez " "\"clear\" pour convertir la tâche en note." -msgid "Marks a todo as non-completed." -msgstr "" +msgid "Marks a to-do as non-completed." +msgstr "Marquer une tâche comme non-complétée." msgid "" "Switches to [notebook] - all further operations will happen within this " @@ -375,6 +475,24 @@ msgstr "Affiche les informations de version" msgid "%s %s (%s)" msgstr "%s %s (%s)" +msgid "Enum" +msgstr "Enum" + +#, javascript-format +msgid "Type: %s." +msgstr "Type : %s." + +#, javascript-format +msgid "Possible values: %s." +msgstr "Valeurs possibles : %s." + +#, javascript-format +msgid "Default: %s" +msgstr "Défaut : %s" + +msgid "Possible keys/values:" +msgstr "Clefs/Valeurs possibles :" + msgid "Fatal error:" msgstr "Erreur fatale :" @@ -392,12 +510,194 @@ msgid "" "any files outside this directory nor to any other personal data. No data " "will be shared with any third party." msgstr "" +"Veuillez ouvrir le lien ci-dessous dans votre navigateur pour authentifier " +"le logiciel. Joplin va créer un répertoire \"Apps/Joplin\" et lire/écrira " +"des fichiers uniquement dans ce répertoire. Le logiciel n'aura pas d'accès à " +"aucun fichier en dehors de ce répertoire, ni à d'autres données " +"personnelles. Aucune donnée ne sera partagé avec aucun tier." -#, fuzzy, javascript-format +msgid "Search:" +msgstr "Recherche :" + +msgid "File" +msgstr "Fichier" + +msgid "New note" +msgstr "Nouvelle note" + +msgid "New to-do" +msgstr "Nouvelle tâche" + +msgid "New notebook" +msgstr "Nouveau carnet" + +msgid "Import Evernote notes" +msgstr "Importer notes d'Evernote" + +msgid "Evernote Export Files" +msgstr "Fichiers d'export Evernote" + +msgid "Quit" +msgstr "Quitter" + +msgid "Edit" +msgstr "Édition" + +msgid "Copy" +msgstr "Copier" + +msgid "Cut" +msgstr "Couper" + +msgid "Paste" +msgstr "Coller" + +msgid "Search in all the notes" +msgstr "Chercher dans toutes les notes" + +msgid "Tools" +msgstr "Outils" + +msgid "Options" +msgstr "Options" + +msgid "Help" +msgstr "Aide" + +msgid "Website and documentation" +msgstr "Documentation en ligne" + +msgid "About Joplin" +msgstr "A propos de Joplin" + +#, javascript-format +msgid "%s %s (%s, %s)" +msgstr "%s %s (%s, %s)" + +msgid "OK" +msgstr "OK" + +msgid "Cancel" +msgstr "Annulation" + +msgid "Back" +msgstr "Retour" + +#, javascript-format +msgid "" +"New notebook \"%s\" will be created and file \"%s\" will be imported into it" +msgstr "" +"Un nouveau carnet \"%s\" va être créé et le fichier \"%s\" va être importé " +"dedans" + +msgid "Please create a notebook first." +msgstr "Veuillez d'abord sélectionner un carnet." + +msgid "Note title:" +msgstr "Titre de la note :" + +msgid "Please create a notebook first" +msgstr "Veuillez d'abord créer un carnet d'abord" + +msgid "To-do title:" +msgstr "Titre de la tâche :" + +msgid "Notebook title:" +msgstr "Titre du carnet :" + +msgid "Add or remove tags:" +msgstr "Modifier les étiquettes :" + +msgid "Separate each tag by a comma." +msgstr "Séparez chaque étiquette par une virgule." + +msgid "Rename notebook:" +msgstr "Renommer le carnet :" + +msgid "Layout" +msgstr "Disposition" + +msgid "Add or remove tags" +msgstr "Gérer les étiquettes" + +msgid "Switch between note and to-do type" +msgstr "Alterner entre note et tâche" + +msgid "Delete" +msgstr "Supprimer" + +msgid "Delete notes?" +msgstr "Supprimer les notes ?" + +msgid "No notes in here. Create one by clicking on \"New note\"." +msgstr "" +"Pas de notes ici. Créez-en une en pressant le bouton \"Nouvelle note\"." + +#, javascript-format +msgid "Unsupported link or message: %s" +msgstr "Lien ou message non géré : %s" + +msgid "Attach file" +msgstr "Attacher un fichier" + +msgid "Refresh" +msgstr "Rafraîchir" + +msgid "OneDrive Login" +msgstr "Connexion OneDrive" + +msgid "Import" +msgstr "Importer" + +msgid "Configuration" +msgstr "Configuration" + +msgid "Delete notebook?" +msgstr "Supprimer le carnet ?" + +msgid "Remove this tag from all the notes?" +msgstr "Enlever cette étiquette de toutes les notes ?" + +msgid "Remove this search from the sidebar?" +msgstr "Enlever cette recherche de la barre latérale ?" + +msgid "Rename" +msgstr "Renommer" + +msgid "Synchronise" +msgstr "Synchroniser" + +msgid "Notebooks" +msgstr "Carnets" + +msgid "Tags" +msgstr "Étiquettes" + +msgid "Searches" +msgstr "Recherches" + +#, javascript-format +msgid "Usage: %s" +msgstr "Utilisation : %s" + +#, javascript-format +msgid "Unknown flag: %s" +msgstr "Paramètre inconnu : %s" + +msgid "File system" +msgstr "Système de fichier" + +msgid "OneDrive" +msgstr "OneDrive" + +msgid "OneDrive Dev (For testing only)" +msgstr "OneDrive Dév (Pour tester uniquement)" + +#, javascript-format msgid "Unknown log level: %s" msgstr "Paramètre inconnu : %s" -#, fuzzy, javascript-format +#, javascript-format msgid "Unknown level ID: %s" msgstr "Paramètre inconnu : %s" @@ -405,15 +705,12 @@ msgid "" "Cannot refresh token: authentication data is missing. Starting the " "synchronisation again may fix the problem." msgstr "" -"Impossible de rafraîchir la connection à OneDrive. Démarrez la " +"Impossible de rafraîchir la connexion à OneDrive. Démarrez la " "synchronisation à nouveau pour corriger le problème." -msgid "" -"Please set the \"sync.2.path\" config value to the desired synchronisation " -"destination." -msgstr "" -"Veuillez attribuer une valeur au paramètre de configuration \"sync.2.path\" " -"pour indiquer le dossier où devra se faire la synchronisation." +#, javascript-format +msgid "Cannot access %s" +msgstr "Impossible d'accéder à %s" #, javascript-format msgid "Created local items: %d." @@ -439,9 +736,9 @@ msgstr "Objets supprimés localement : %d." msgid "Deleted remote items: %d." msgstr "Objets distants supprimés : %d." -#, fuzzy, javascript-format +#, javascript-format msgid "State: \"%s\"." -msgstr "Etat : %s." +msgstr "État : \"%s\"." msgid "Cancelling..." msgstr "Annulation..." @@ -452,7 +749,7 @@ msgstr "Terminé : %s" #, javascript-format msgid "Synchronisation is already in progress. State: %s" -msgstr "La synchronisation est déjà en cours. Etat : %s" +msgstr "La synchronisation est déjà en cours. État : %s" msgid "Conflicts" msgstr "Conflits" @@ -473,55 +770,55 @@ msgstr "Cette note n'a pas d'information d'emplacement." #, javascript-format msgid "Cannot copy note to \"%s\" notebook" -msgstr "Impossible de copier la note dans le carnet \"%s\"" +msgstr "Impossible de copier la note vers le carnet \"%s\"" #, javascript-format msgid "Cannot move note to \"%s\" notebook" msgstr "Impossible de déplacer la note vers le carnet \"%s\"" -#, javascript-format -msgid "Invalid option value: \"%s\". Possible values are: %s." -msgstr "Option invalide: \"%s\". Les valeurs possibles sont : %s." +msgid "File system synchronisation target directory" +msgstr "Cible de la synchronisation sur le disque dur" -#, fuzzy, javascript-format -msgid "%s: %s" -msgstr "%s: %d/%d" +msgid "" +"The path to synchronise with when file system synchronisation is enabled. " +"See `sync.target`." +msgstr "" +"Le chemin du répertoire avec lequel synchroniser lorsque la synchronisation " +"par système de fichier est activée. Voir `sync.target`." -msgid "Synchronisation target" -msgstr "Cible de la synchronisation" +msgid "Text editor" +msgstr "Éditeur de texte" -msgid "File system" -msgstr "Système de fichier" - -msgid "OneDrive" -msgstr "OneDrive" +msgid "" +"The editor that will be used to open a note. If none is provided it will try " +"to auto-detect the default editor." +msgstr "" +"L'éditeur de texte pour ouvrir et modifier les notes. Si aucun n'est " +"spécifié, il sera détecté automatiquement." msgid "Language" msgstr "Langue" -msgid "Todo filter" -msgstr "Filtre des tâches" +msgid "Theme" +msgstr "Apparence" -msgid "Show all" -msgstr "Afficher tous" +msgid "Light" +msgstr "Clair" -msgid "Non-completed and recently completed ones" -msgstr "Tâches non-complétées et récentes" - -msgid "Non-completed ones only" -msgstr "Tâches complétées seulement" +msgid "Dark" +msgstr "Sombre" msgid "Show uncompleted todos on top of the lists" msgstr "Tâches non-terminées en haut des listes" -msgid "Save location with notes" +msgid "Save geo-location with notes" msgstr "Enregistrer l'emplacement avec les notes" msgid "Synchronisation interval" -msgstr "Interval de synchronisation" +msgstr "Intervalle de synchronisation" msgid "Disabled" -msgstr "" +msgstr "Désactivé" #, javascript-format msgid "%d minutes" @@ -535,14 +832,25 @@ msgstr "%d heure" msgid "%d hours" msgstr "%d heures" -msgid "Theme" -msgstr "Apparence" +msgid "Automatically update the application" +msgstr "Mettre à jour le logiciel automatiquement" -msgid "Light" -msgstr "Clair" +msgid "Show advanced options" +msgstr "Montrer les options avancées" -msgid "Dark" -msgstr "Sombre" +msgid "Synchronisation target" +msgstr "Cible de la synchronisation" + +msgid "" +"The target to synchonise to. If synchronising with the file system, set " +"`sync.2.path` to specify the target directory." +msgstr "" +"La cible avec laquelle synchroniser. Pour synchroniser avec le système de " +"fichier, veuillez spécifier le répertoire avec `sync.2.path`." + +#, javascript-format +msgid "Invalid option value: \"%s\". Possible values are: %s." +msgstr "Option invalide: \"%s\". Les valeurs possibles sont : %s." msgid "Sync status (synced items / total items)" msgstr "Status de la synchronisation (objets synchro. / total)" @@ -570,31 +878,29 @@ msgstr "Carnets" msgid "%s: %d notes" msgstr "%s : %d notes" -msgid "New todo" -msgstr "Nouvelle tâche" - -msgid "New note" -msgstr "Nouvelle note" - -msgid "New notebook" -msgstr "Nouveau carnet" - msgid "There are currently no notes. Create one by clicking on the (+) button." msgstr "" "Ce carnet ne contient aucune note. Créez-en une en appuyant sur le bouton " "(+)." +msgid "Delete these notes?" +msgstr "Supprimer ces notes ?" + msgid "Log" msgstr "Journal" msgid "Status" -msgstr "Etat" +msgstr "État" -msgid "Configuration" -msgstr "Configuration" +msgid "Export Debug Report" +msgstr "Exporter rapport de débogage" -msgid "Synchronise" -msgstr "Synchroniser" +msgid "Move to notebook..." +msgstr "Déplacer la note vers carnet..." + +#, javascript-format +msgid "Move %d notes to notebook \"%s\"?" +msgstr "Déplacer %d notes vers carnet \"%s\" ?" msgid "Cancel synchronisation" msgstr "Annuler synchronisation" @@ -604,16 +910,26 @@ msgid "The notebook could not be saved: %s" msgstr "Ce carnet n'a pas pu être sauvegardé : %s" msgid "Edit notebook" -msgstr "Editer le carnet" +msgstr "Éditer le carnet" -msgid "Refresh" -msgstr "Rafraîchir" +msgid "This note has been modified:" +msgstr "Cette note a été modifiée :" -msgid "Delete note?" -msgstr "Supprimer la note ?" +msgid "Save changes" +msgstr "Enregistrer les changements" -msgid "Attach file" -msgstr "Attacher un fichier" +msgid "Discard changes" +msgstr "Ignorer les changements" + +#, javascript-format +msgid "Unsupported image type: %s" +msgstr "Type d'image non géré : %s" + +msgid "Attach image" +msgstr "Joindre une image ou photo" + +msgid "Attach any other file" +msgstr "Joindre un fichier" msgid "Delete note" msgstr "Supprimer la note" @@ -633,20 +949,11 @@ msgstr "Afficher les métadonnées" msgid "View location on map" msgstr "Voir l'emplacement sur la carte" -msgid "Edit" -msgstr "Editer" - -msgid "Delete notebook?" -msgstr "Supprimer le carnet ?" - msgid "Delete notebook" msgstr "Supprimer le carnet" msgid "Login with OneDrive" -msgstr "Se connecter avec OneDrive" - -msgid "Search" -msgstr "Chercher" +msgstr "Se connecter à OneDrive" msgid "" "Click on the (+) button to create a new note or notebook. Click on the side " @@ -663,15 +970,73 @@ msgstr "" msgid "Welcome" msgstr "Bienvenue" +#~ msgid "" +#~ "Please set the \"sync.2.path\" config value to the desired " +#~ "synchronisation destination." +#~ msgstr "" +#~ "Veuillez attribuer une valeur au paramètre de configuration \"sync.2.path" +#~ "\" pour indiquer le dossier où devra se faire la synchronisation." + +#~ msgid "Seach:" +#~ msgstr "Chercher :" + +#~ msgid "Seach" +#~ msgstr "Chercher" + +#~ msgid "" +#~ "Command line argument \"%s\" contains both quotes and double-quotes - " +#~ "aborting." +#~ msgstr "" +#~ "Le paramètre de ligne de commande \"%s\" contient à la fois des " +#~ "guillemets simples et doubles - impossible de continuer." + +#~ msgid "Provides help for a given command." +#~ msgstr "Affiche l'aide pour la commande donnée." + +#, fuzzy +#~ msgid "Create a [n]ew [n]otebook" +#~ msgstr "Créer un carnet." + +#, fuzzy +#~ msgid "[Cancel]" +#~ msgstr "Annulation..." + +#~ msgid "Todo filter" +#~ msgstr "Filtre des tâches" + +#~ msgid "Show all" +#~ msgstr "Afficher tous" + +#~ msgid "Non-completed and recently completed ones" +#~ msgstr "Tâches non-complétées et récentes" + +#~ msgid "Non-completed ones only" +#~ msgstr "Tâches complétées seulement" + +#, fuzzy +#~ msgid "Delete a note" +#~ msgstr "Supprimer la note" + #~ msgid "%s (%s)" #~ msgstr "%s (%s)" -#~ msgid "Last error: %s (stacktrace in log)." -#~ msgstr "Dernière erreur : %s (Plus d'information dans le journal d'erreurs)" +#, fuzzy +#~ msgid "Show/Hide the console" +#~ msgstr "Quitter le logiciel." #, fuzzy -#~ msgid "Cancelling command..." -#~ msgstr "Annulation..." +#~ msgid "Last command: %s" +#~ msgstr "Commande invalide : \"%s\"" + +#~ msgid "Done editing." +#~ msgstr "Edition terminée." + +#, fuzzy +#~ msgid "Confirm" +#~ msgstr "Conflits" + +#~ msgid "Last error: %s (stacktrace in log)." +#~ msgstr "Dernière erreur : %s (Plus d'information dans le journal d'erreurs)" #~ msgid "Done." #~ msgstr "Terminé." @@ -694,12 +1059,6 @@ msgstr "Bienvenue" #~ " est une note, elle sera déplacée vers le carnet . Si " #~ " est un carnet, il sera renommé ." -#~ msgid "Deletes a notebook." -#~ msgstr "Supprime le carnet." - -#~ msgid "Delete notebook \"%s\"?" -#~ msgstr "Supprimer le carnet \"%s\" ?" - #~ msgid "No notebook is defined. Create one with `mkbook `." #~ msgstr "Aucun carnet n'est défini. Créez-en un avec `mkbook `." @@ -730,9 +1089,6 @@ msgstr "Bienvenue" #~ msgid "Usage: --log-level " #~ msgstr "Utilisation: --log-level " -#~ msgid "cat " -#~ msgstr "cat <titre>" - #~ msgid "config [name] [value]" #~ msgstr "config [nom] [valeur]" @@ -742,10 +1098,6 @@ msgstr "Bienvenue" #~ msgid "edit <title>" #~ msgstr "edit <titre>" -#, fuzzy -#~ msgid "geoloc <title>" -#~ msgstr "cat <titre>" - #~ msgid "import-enex <file> [notebook]" #~ msgstr "import-enex <fichier> [carnet]" @@ -781,9 +1133,6 @@ msgstr "Bienvenue" #~ "Tous les ports sont en cours d'utilisation. Veuillez signaler ce problème " #~ "sur %s" -#~ msgid "Imported - %s" -#~ msgstr "Importé - %s" - #~ msgid "" #~ "There is currently no notebook. Create one by clicking on the (+) button." #~ msgstr "" diff --git a/CliClient/locales/joplin.pot b/CliClient/locales/joplin.pot index fbe27ed99..a955d5bb6 100644 --- a/CliClient/locales/joplin.pot +++ b/CliClient/locales/joplin.pot @@ -15,89 +15,123 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" +msgid "Give focus to next pane" +msgstr "" + +msgid "Give focus to previous pane" +msgstr "" + +msgid "Enter command line mode" +msgstr "" + +msgid "Exit command line mode" +msgstr "" + +msgid "Edit the selected note" +msgstr "" + +msgid "Cancel the current command." +msgstr "" + +msgid "Exit the application." +msgstr "" + +msgid "Delete the currently selected note or notebook." +msgstr "" + +msgid "To delete a tag, untag the associated notes." +msgstr "" + +msgid "Please select the note or notebook to be deleted first." +msgstr "" + +msgid "Set a to-do as completed / not completed" +msgstr "" + +msgid "[t]oggle [c]onsole between maximized/minimized/hidden/visible." +msgstr "" + +msgid "Search" +msgstr "" + +msgid "[t]oggle note [m]etadata." +msgstr "" + +msgid "[M]ake a new [n]ote" +msgstr "" + +msgid "[M]ake a new [t]odo" +msgstr "" + +msgid "[M]ake a new note[b]ook" +msgstr "" + +msgid "Copy ([Y]ank) the [n]ote to a notebook." +msgstr "" + +msgid "Move the note to a notebook." +msgstr "" + +msgid "Press Ctrl+D or type \"exit\" to exit the application" +msgstr "" + +#, javascript-format +msgid "More than one item match \"%s\". Please narrow down your query." +msgstr "" + msgid "No notebook selected." msgstr "" msgid "No notebook has been specified." msgstr "" -#, javascript-format -msgid "Usage: %s" -msgstr "" - -#, javascript-format -msgid "Unknown flag: %s" -msgstr "" - -#, javascript-format -msgid "" -"Command line argument \"%s\" contains both quotes and double-quotes - " -"aborting." -msgstr "" - -msgid "Provides help for a given command." -msgstr "" - -msgid "Exits the application." -msgstr "" - -msgid "Only Bash is currently supported for autocompletion." -msgstr "" - -msgid "" -"Autocompletion can be made to work with an alias too (such as a one-letter " -"command like \"j\").\n" -"If you would like to enable this, please type the alias now (leave it empty " -"for no alias):" -msgstr "" - -#, javascript-format -msgid "Created autocompletion script \"%s\"." -msgstr "" - -#, javascript-format -msgid "Autocompletion script is already present in \"%s\"." -msgstr "" - -#, javascript-format -msgid "Added autocompletion to \"%s\"." -msgstr "" - -#, javascript-format -msgid "Alias is already set in \"%s\"." -msgstr "" - -#, javascript-format -msgid "Added alias to \"%s\"." -msgstr "" - -#, javascript-format -msgid "" -"IMPORTANT: run the following command to initialise autocompletion in the " -"current shell:\n" -"source '%s'" -msgstr "" - -#, javascript-format -msgid "Missing required argument: %s" -msgstr "" - msgid "Y" msgstr "" msgid "n" msgstr "" -msgid "Displays the given note." +msgid "N" msgstr "" -msgid "Displays the complete information about note." +msgid "y" +msgstr "" + +msgid "Cancelling background synchronisation... Please wait." +msgstr "" + +#, javascript-format +msgid "The command \"%s\" is only available in GUI mode" +msgstr "" + +#, javascript-format +msgid "Missing required argument: %s" +msgstr "" + +#, javascript-format +msgid "%s: %s" +msgstr "" + +msgid "Your choice: " +msgstr "" + +#, javascript-format +msgid "Invalid answer: %s" +msgstr "" + +msgid "Attaches the given file to the note." msgstr "" #, javascript-format msgid "Cannot find \"%s\"." msgstr "" +msgid "Displays the given note." +msgstr "" + +msgid "Displays the complete information about note." +msgstr "" + msgid "" "Gets or sets a config value. If [value] is not provided, it will show the " "value of [name]. If neither [name] nor [value] is provided, it will list the " @@ -120,19 +154,16 @@ msgid "" "specified the note is duplicated in the current notebook." msgstr "" -msgid "Marks a todo as done." +msgid "Marks a to-do as done." msgstr "" #, javascript-format -msgid "Note is not a todo: \"%s\"" +msgid "Note is not a to-do: \"%s\"" msgstr "" msgid "Edit note." msgstr "" -msgid "Done editing." -msgstr "" - msgid "" "No text editor is defined. Please set it using `config editor <editor-path>`" msgstr "" @@ -147,7 +178,15 @@ msgstr "" msgid "Starting to edit note. Close the editor to get back to the prompt." msgstr "" -msgid "Exports Joplin data to the given target." +msgid "Note has been saved." +msgstr "" + +msgid "Exits the application." +msgstr "" + +msgid "" +"Exports Joplin data to the given directory. By default, it will export the " +"complete database including notebooks, notes, tags and resources." msgstr "" msgid "Exports only the given note." @@ -162,6 +201,42 @@ msgstr "" msgid "Displays usage information." msgstr "" +msgid "Shortcuts are not available in CLI mode." +msgstr "" + +msgid "Type `help [command]` for more information about a command." +msgstr "" + +msgid "The possible commands are:" +msgstr "" + +msgid "" +"In any command, a note or notebook can be refered to by title or ID, or " +"using the shortcuts `$n` or `$b` for, respectively, the currently selected " +"note or notebook. `$c` can be used to refer to the currently selected item." +msgstr "" + +msgid "To move from one pane to another, press Tab or Shift+Tab." +msgstr "" + +msgid "" +"Use the arrows and page up/down to scroll the lists and text areas " +"(including this console)." +msgstr "" + +msgid "To maximise/minimise the console, press \"TC\"." +msgstr "" + +msgid "To enter command line mode, press \":\"" +msgstr "" + +msgid "To exit command line mode, press ESCAPE" +msgstr "" + +msgid "" +"For the complete list of available keyboard shortcuts, type `help shortcuts`" +msgstr "" + msgid "Imports an Evernote notebook file (.enex file)." msgstr "" @@ -205,6 +280,10 @@ msgstr "" msgid "Importing notes..." msgstr "" +#, javascript-format +msgid "The notes have been imported: %s" +msgstr "" + msgid "" "Displays the notes in the current notebook. Use `ls /` to display the list " "of notebooks." @@ -221,8 +300,8 @@ msgstr "" msgid "" "Displays only the items of the specific type(s). Can be `n` for notes, `t` " -"for todos, or `nt` for notes and todos (eg. `-tt` would display only the " -"todos, while `-ttd` would display notes and todos." +"for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the " +"to-dos, while `-ttd` would display notes and to-dos." msgstr "" msgid "Either \"text\" or \"json\"" @@ -230,7 +309,7 @@ msgstr "" msgid "" "Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, " -"TODO_CHECKED (for todos), TITLE" +"TODO_CHECKED (for to-dos), TITLE" msgstr "" msgid "Please select a notebook first." @@ -245,22 +324,38 @@ msgstr "" msgid "Notes can only be created within a notebook." msgstr "" -msgid "Creates a new todo." +msgid "Creates a new to-do." msgstr "" -msgid "Moves the notes matching <note-pattern> to [notebook]." +msgid "Moves the notes matching <note> to [notebook]." +msgstr "" + +msgid "Renames the given <item> (note or notebook) to <name>." +msgstr "" + +msgid "Deletes the given notebook." +msgstr "" + +msgid "Deletes the notebook without asking for confirmation." +msgstr "" + +#, javascript-format +msgid "Delete notebook \"%s\"?" msgstr "" msgid "Deletes the notes matching <note-pattern>." msgstr "" -msgid "Deletes the items without asking for confirmation." +msgid "Deletes the notes without asking for confirmation." msgstr "" #, javascript-format msgid "%d notes match this pattern. Delete them?" msgstr "" +msgid "Delete note?" +msgstr "" + msgid "Searches for the given <pattern> in all the notes." msgstr "" @@ -286,6 +381,10 @@ msgid "" "operation." msgstr "" +msgid "" +"Authentication was not completed (did not receive an authentication token)." +msgstr "" + #, javascript-format msgid "Synchronisation target: %s (%s)" msgstr "" @@ -311,12 +410,12 @@ msgstr "" msgid "" "<todo-command> can either be \"toggle\" or \"clear\". Use \"toggle\" to " -"toggle the given todo between completed and uncompleted state (If the target " -"is a regular note it will be converted to a todo). Use \"clear\" to convert " -"the todo back to a regular note." +"toggle the given to-do between completed and uncompleted state (If the " +"target is a regular note it will be converted to a to-do). Use \"clear\" to " +"convert the to-do back to a regular note." msgstr "" -msgid "Marks a todo as non-completed." +msgid "Marks a to-do as non-completed." msgstr "" msgid "" @@ -331,6 +430,24 @@ msgstr "" msgid "%s %s (%s)" msgstr "" +msgid "Enum" +msgstr "" + +#, javascript-format +msgid "Type: %s." +msgstr "" + +#, javascript-format +msgid "Possible values: %s." +msgstr "" + +#, javascript-format +msgid "Default: %s" +msgstr "" + +msgid "Possible keys/values:" +msgstr "" + msgid "Fatal error:" msgstr "" @@ -349,6 +466,180 @@ msgid "" "will be shared with any third party." msgstr "" +msgid "Search:" +msgstr "" + +msgid "File" +msgstr "" + +msgid "New note" +msgstr "" + +msgid "New to-do" +msgstr "" + +msgid "New notebook" +msgstr "" + +msgid "Import Evernote notes" +msgstr "" + +msgid "Evernote Export Files" +msgstr "" + +msgid "Quit" +msgstr "" + +msgid "Edit" +msgstr "" + +msgid "Copy" +msgstr "" + +msgid "Cut" +msgstr "" + +msgid "Paste" +msgstr "" + +msgid "Search in all the notes" +msgstr "" + +msgid "Tools" +msgstr "" + +msgid "Options" +msgstr "" + +msgid "Help" +msgstr "" + +msgid "Website and documentation" +msgstr "" + +msgid "About Joplin" +msgstr "" + +#, javascript-format +msgid "%s %s (%s, %s)" +msgstr "" + +msgid "OK" +msgstr "" + +msgid "Cancel" +msgstr "" + +msgid "Back" +msgstr "" + +#, javascript-format +msgid "" +"New notebook \"%s\" will be created and file \"%s\" will be imported into it" +msgstr "" + +msgid "Please create a notebook first." +msgstr "" + +msgid "Note title:" +msgstr "" + +msgid "Please create a notebook first" +msgstr "" + +msgid "To-do title:" +msgstr "" + +msgid "Notebook title:" +msgstr "" + +msgid "Add or remove tags:" +msgstr "" + +msgid "Separate each tag by a comma." +msgstr "" + +msgid "Rename notebook:" +msgstr "" + +msgid "Layout" +msgstr "" + +msgid "Add or remove tags" +msgstr "" + +msgid "Switch between note and to-do type" +msgstr "" + +msgid "Delete" +msgstr "" + +msgid "Delete notes?" +msgstr "" + +msgid "No notes in here. Create one by clicking on \"New note\"." +msgstr "" + +#, javascript-format +msgid "Unsupported link or message: %s" +msgstr "" + +msgid "Attach file" +msgstr "" + +msgid "Refresh" +msgstr "" + +msgid "OneDrive Login" +msgstr "" + +msgid "Import" +msgstr "" + +msgid "Configuration" +msgstr "" + +msgid "Delete notebook?" +msgstr "" + +msgid "Remove this tag from all the notes?" +msgstr "" + +msgid "Remove this search from the sidebar?" +msgstr "" + +msgid "Rename" +msgstr "" + +msgid "Synchronise" +msgstr "" + +msgid "Notebooks" +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "Searches" +msgstr "" + +#, javascript-format +msgid "Usage: %s" +msgstr "" + +#, javascript-format +msgid "Unknown flag: %s" +msgstr "" + +msgid "File system" +msgstr "" + +msgid "OneDrive" +msgstr "" + +msgid "OneDrive Dev (For testing only)" +msgstr "" + #, javascript-format msgid "Unknown log level: %s" msgstr "" @@ -362,9 +653,8 @@ msgid "" "synchronisation again may fix the problem." msgstr "" -msgid "" -"Please set the \"sync.2.path\" config value to the desired synchronisation " -"destination." +#, javascript-format +msgid "Cannot access %s" msgstr "" #, javascript-format @@ -431,42 +721,38 @@ msgstr "" msgid "Cannot move note to \"%s\" notebook" msgstr "" -#, javascript-format -msgid "Invalid option value: \"%s\". Possible values are: %s." +msgid "File system synchronisation target directory" msgstr "" -#, javascript-format -msgid "%s: %s" +msgid "" +"The path to synchronise with when file system synchronisation is enabled. " +"See `sync.target`." msgstr "" -msgid "Synchronisation target" +msgid "Text editor" msgstr "" -msgid "File system" -msgstr "" - -msgid "OneDrive" +msgid "" +"The editor that will be used to open a note. If none is provided it will try " +"to auto-detect the default editor." msgstr "" msgid "Language" msgstr "" -msgid "Todo filter" +msgid "Theme" msgstr "" -msgid "Show all" +msgid "Light" msgstr "" -msgid "Non-completed and recently completed ones" -msgstr "" - -msgid "Non-completed ones only" +msgid "Dark" msgstr "" msgid "Show uncompleted todos on top of the lists" msgstr "" -msgid "Save location with notes" +msgid "Save geo-location with notes" msgstr "" msgid "Synchronisation interval" @@ -487,13 +773,22 @@ msgstr "" msgid "%d hours" msgstr "" -msgid "Theme" +msgid "Automatically update the application" msgstr "" -msgid "Light" +msgid "Show advanced options" msgstr "" -msgid "Dark" +msgid "Synchronisation target" +msgstr "" + +msgid "" +"The target to synchonise to. If synchronising with the file system, set " +"`sync.2.path` to specify the target directory." +msgstr "" + +#, javascript-format +msgid "Invalid option value: \"%s\". Possible values are: %s." msgstr "" msgid "Sync status (synced items / total items)" @@ -522,28 +817,26 @@ msgstr "" msgid "%s: %d notes" msgstr "" -msgid "New todo" -msgstr "" - -msgid "New note" -msgstr "" - -msgid "New notebook" -msgstr "" - msgid "There are currently no notes. Create one by clicking on the (+) button." msgstr "" +msgid "Delete these notes?" +msgstr "" + msgid "Log" msgstr "" msgid "Status" msgstr "" -msgid "Configuration" +msgid "Export Debug Report" msgstr "" -msgid "Synchronise" +msgid "Move to notebook..." +msgstr "" + +#, javascript-format +msgid "Move %d notes to notebook \"%s\"?" msgstr "" msgid "Cancel synchronisation" @@ -556,13 +849,23 @@ msgstr "" msgid "Edit notebook" msgstr "" -msgid "Refresh" +msgid "This note has been modified:" msgstr "" -msgid "Delete note?" +msgid "Save changes" msgstr "" -msgid "Attach file" +msgid "Discard changes" +msgstr "" + +#, javascript-format +msgid "Unsupported image type: %s" +msgstr "" + +msgid "Attach image" +msgstr "" + +msgid "Attach any other file" msgstr "" msgid "Delete note" @@ -583,21 +886,12 @@ msgstr "" msgid "View location on map" msgstr "" -msgid "Edit" -msgstr "" - -msgid "Delete notebook?" -msgstr "" - msgid "Delete notebook" msgstr "" msgid "Login with OneDrive" msgstr "" -msgid "Search" -msgstr "" - msgid "" "Click on the (+) button to create a new note or notebook. Click on the side " "menu to access your existing notebooks." diff --git a/CliClient/package-lock.json b/CliClient/package-lock.json new file mode 100644 index 000000000..7a4ae8480 --- /dev/null +++ b/CliClient/package-lock.json @@ -0,0 +1,2177 @@ +{ + "name": "joplin", + "version": "0.10.74", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ajv": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz", + "integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "requires": { + "color-convert": "1.9.0" + } + }, + "app-module-path": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", + "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async-kit": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/async-kit/-/async-kit-2.2.3.tgz", + "integrity": "sha1-JkdRonndxfWbQZY4uAWuLEmFj7c=", + "requires": { + "nextgen-events": "0.9.9", + "tree-kit": "0.5.26" + }, + "dependencies": { + "nextgen-events": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/nextgen-events/-/nextgen-events-0.9.9.tgz", + "integrity": "sha1-OaivxKK4RTiMV+LGu5cWcRmGo6A=" + } + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "requires": { + "get-proxy": "2.1.0", + "isurl": "1.0.0", + "tunnel-agent": "0.6.0", + "url-to-options": "1.0.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-2.0.0.tgz", + "integrity": "sha1-4MmXLR6WmFcASxAeqlXOq1lh1n0=", + "requires": { + "color-convert": "1.9.0", + "color-string": "1.5.2" + } + }, + "color-convert": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", + "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", + "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", + "requires": { + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" + } + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "config-chain": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "requires": { + "ini": "1.3.4", + "proto-list": "1.2.4" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "cwise-compiler": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", + "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", + "requires": { + "uniq": "1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "data-uri-to-buffer": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-0.0.3.tgz", + "integrity": "sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "1.0.0" + } + }, + "deep-is": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.2.tgz", + "integrity": "sha1-nO1l6gvAsJ9CptecGxkD+dkTzBg=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "detect-libc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-0.2.0.tgz", + "integrity": "sha1-R/31ZzSKF+wl/L8LnkRjSKdvn7U=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "emphasize": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/emphasize/-/emphasize-1.5.0.tgz", + "integrity": "sha1-48WvLdzLSYKCKjNJtHFhPMfOzJI=", + "requires": { + "chalk": "1.1.3", + "highlight.js": "9.12.0", + "lowlight": "1.9.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.19" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "follow-redirects": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.2.5.tgz", + "integrity": "sha512-lMhwQTryFbG+wYsAIEKC1Kf5IGDlVNnONRogIBllh7LLoV7pNIxW0z9fhjRar9NBql+hd2Y49KboVVNxf6GEfg==", + "requires": { + "debug": "2.6.9" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "3.0.1", + "universalify": "0.1.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "get-pixels": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/get-pixels/-/get-pixels-3.3.0.tgz", + "integrity": "sha1-jZeVvq4YhQuED3SVgbrcBdPjbkE=", + "requires": { + "data-uri-to-buffer": "0.0.3", + "jpeg-js": "0.1.2", + "mime-types": "2.1.17", + "ndarray": "1.0.18", + "ndarray-pack": "1.2.1", + "node-bitmap": "0.0.1", + "omggif": "1.0.8", + "parse-data-uri": "0.2.0", + "pngjs": "2.3.1", + "request": "2.83.0", + "through": "2.3.8" + } + }, + "get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "requires": { + "npm-conf": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "gettext-parser": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/gettext-parser/-/gettext-parser-1.3.0.tgz", + "integrity": "sha512-iloxjcw+uTPnQ8DrGICWtqkHNgk3mAiDI77pLmXQCnhM+BxFQXstzTA4zj3EpIYMysRQnnNzHyHzBUEazz80Sw==", + "dev": true, + "requires": { + "encoding": "0.1.12", + "safe-buffer": "5.1.1" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.3.0", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "has-symbol-support-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.1.tgz", + "integrity": "sha512-JkaetveU7hFbqnAC1EV1sF4rlojU2D4Usc5CmS69l6NfmPDnpnFUegzFg33eDkkpNCxZ0mQp65HwUDrNFS/8MA==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "1.4.1" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "highlight.js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=" + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" + }, + "iota-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" + }, + "is-absolute": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "requires": { + "is-relative": "0.2.1", + "is-windows": "0.2.0" + } + }, + "is-arrayish": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.1.tgz", + "integrity": "sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0=" + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, + "is-relative": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "requires": { + "is-unc-path": "0.1.2" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-unc-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=" + }, + "is2": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/is2/-/is2-0.0.9.tgz", + "integrity": "sha1-EZVW0dFlGkG6EFr4AyZ8gLKZ9ik=", + "requires": { + "deep-is": "0.1.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" + } + }, + "jasmine": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-2.8.0.tgz", + "integrity": "sha1-awicChFXax8W3xG4AUbZHU6Lij4=", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "7.1.2", + "jasmine-core": "2.8.0" + } + }, + "jasmine-core": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.8.0.tgz", + "integrity": "sha1-vMl5rh+f0FcB5F5S5l06XWPxok4=", + "dev": true + }, + "jpeg-js": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.1.2.tgz", + "integrity": "sha1-E1uZLAV1yYXPoPSUoyJ+0jhYPs4=" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jssha": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/jssha/-/jssha-2.3.1.tgz", + "integrity": "sha1-FHshJTaQNcpLL30hDcU58Amz3po=" + }, + "levenshtein": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/levenshtein/-/levenshtein-1.0.5.tgz", + "integrity": "sha1-ORFzepy1baNF0Aj1V4LG8TiXm6M=" + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash-es": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", + "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" + }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "requires": { + "js-tokens": "3.0.2" + } + }, + "lowlight": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.9.1.tgz", + "integrity": "sha512-CpDhyVhI+xHjruiGvH2F/Fr5q5aTn5A6Oyh7MI+4oI8G0A1E7p9a3Zqv9Hzx9WByK8gAiNifEueAXz+cA2xdEA==", + "requires": { + "highlight.js": "9.12.0" + } + }, + "md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "requires": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "1.1.5" + } + }, + "mime": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.0.3.tgz", + "integrity": "sha512-TrpAd/vX3xaLPDgVRm6JkZwLR0KHfukMdU2wTEbqMDdCnY6Yo3mE+mjs9YE6oMNw2QRfXVeBEYpmpO94BIqiug==" + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "mimic-response": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "minipass": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.1.tgz", + "integrity": "sha512-u1aUllxPJUI07cOqzR7reGmQxmCqlH88uIIsf6XZFEWgw7gXKpJdR+5R9Y3KEDmWYkdIz9wXZs3C0jOPxejk/Q==", + "requires": { + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.4.tgz", + "integrity": "sha512-sN4U9tIJtBRwKbwgFh9qJfrPIQ/GGTRr1MGqkgOeMTLy8/lM0FcWU//FqlnZ3Vb7gJ+Mxh3FOg1EklibdajbaQ==", + "requires": { + "minipass": "2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "moment": { + "version": "2.19.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.1.tgz", + "integrity": "sha1-VtoaLRy/AdOLfhr8McELz6GSkWc=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mustache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz", + "integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA=", + "dev": true + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + }, + "ndarray": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.18.tgz", + "integrity": "sha1-tg06cyJOxVXQ+qeXEeUCRI/T95M=", + "requires": { + "iota-array": "1.0.0", + "is-buffer": "1.1.5" + } + }, + "ndarray-pack": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ndarray-pack/-/ndarray-pack-1.2.1.tgz", + "integrity": "sha1-jK6+qqJNXs9w/4YCBjeXfajuWFo=", + "requires": { + "cwise-compiler": "1.1.3", + "ndarray": "1.0.18" + } + }, + "nextgen-events": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/nextgen-events/-/nextgen-events-0.10.2.tgz", + "integrity": "sha512-P6efDoVOOJjVLOhwINq+aqhC2B3a9IxojbWMn9fTv2coDiyRaaGLSgWsm84wQHlQeuqVgqiLEE+xiHXf3EVN6w==" + }, + "node-bitmap": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/node-bitmap/-/node-bitmap-0.0.1.tgz", + "integrity": "sha1-GA6scAPgxwdhjvMTaPYvhLKmkJE=" + }, + "node-emoji": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz", + "integrity": "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg==", + "requires": { + "lodash.toarray": "4.4.0" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, + "node-persist": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-2.1.0.tgz", + "integrity": "sha1-5lK784haBNrWo1PXQXYXfIORRwc=", + "requires": { + "is-absolute": "0.2.6", + "mkdirp": "0.5.1", + "q": "1.1.2" + } + }, + "npm-conf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.2.tgz", + "integrity": "sha512-dotwbpwVzfNB/2EF3A2wjK5tEMLggKfuA/8TG6WvBB1Zrv+JsvF7E8ei9B/HGq211st/GwXFbREcNJvJ1eySUQ==", + "requires": { + "config-chain": "1.1.11", + "pify": "3.0.0" + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "omggif": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.8.tgz", + "integrity": "sha1-F483sqsLPXtG7ToORr0HkLWNNTA=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "parse-data-uri": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/parse-data-uri/-/parse-data-uri-0.2.0.tgz", + "integrity": "sha1-vwTYUd1ch7CrI45dAazklLYEtMk=", + "requires": { + "data-uri-to-buffer": "0.0.3" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pngjs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-2.3.1.tgz", + "integrity": "sha1-EdHhK5y2TWPjDBQ6Mw9MH1Z9qF8=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "2.0.6" + } + }, + "proper-lockfile": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-2.0.1.tgz", + "integrity": "sha1-FZ+wYZPTIAP0s2kd0uwaY0qoDR0=", + "requires": { + "graceful-fs": "4.1.11", + "retry": "0.10.1" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "q": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/q/-/q-1.1.2.tgz", + "integrity": "sha1-Y1fikSBnAdmfGXq4TlforRlvKok=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "requires": { + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "redux": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", + "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "requires": { + "lodash": "4.17.4", + "lodash-es": "4.17.4", + "loose-envify": "1.3.1", + "symbol-observable": "1.0.4" + } + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "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" + } + }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=" + }, + "sharp": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.18.4.tgz", + "integrity": "sha1-/jKcDwaJbCiqJDdt8f/wKuV/LTQ=", + "requires": { + "caw": "2.0.1", + "color": "2.0.0", + "detect-libc": "0.2.0", + "nan": "2.7.0", + "semver": "5.4.1", + "simple-get": "2.7.0", + "tar": "3.2.1" + } + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.7.0.tgz", + "integrity": "sha512-RkE9rGPHcxYZ/baYmgJtOSM63vH0Vyq+ma5TijBcLla41SWlh8t6XYIGMR/oeZcmr+/G8k+zrClkkVrtnQ0esg==", + "requires": { + "decompress-response": "3.3.0", + "once": "1.4.0", + "simple-concat": "1.0.0" + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "0.3.1" + } + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.0" + } + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "sqlite3": { + "version": "3.1.13", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-3.1.13.tgz", + "integrity": "sha512-JxXKPJnkZ6NuHRojq+g2WXWBt3M1G9sjZaYiHEWSTGijDM3cwju/0T2XbWqMXFmPqDgw+iB7zKQvnns4bvzXlw==", + "requires": { + "nan": "2.7.0", + "node-pre-gyp": "0.6.38" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.8", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.4", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "mime-db": { + "version": "1.30.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.17", + "bundled": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "node-pre-gyp": { + "version": "0.6.38", + "bundled": true, + "requires": { + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.2", + "semver": "5.4.1", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "readable-stream": { + "version": "2.3.3", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "0.6.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.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "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": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "semver": { + "version": "5.4.1", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.1", + "bundled": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "bundled": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "requires": { + "debug": "2.6.9", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.3", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.3", + "bundled": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "uuid": { + "version": "3.1.0", + "bundled": true + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + } + } + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-kit": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/string-kit/-/string-kit-0.6.3.tgz", + "integrity": "sha512-G2T92klsuE+S9mqdKQyWurFweNQV5X+FRzSKTqYHRdaVUN/4dL6urbYJJ+xb9ep/4XWm+4RNT8j3acncNhFRBg==", + "requires": { + "xregexp": "3.2.0" + } + }, + "string-padding": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-padding/-/string-padding-1.0.2.tgz", + "integrity": "sha1-OqrYVbPpc1xeQS3+chmMz5nH9I4=" + }, + "string-to-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-1.1.0.tgz", + "integrity": "sha1-rPLJ6tHEGOFIUJoS0su0afMzohg=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "requires": { + "has-flag": "2.0.0" + } + }, + "symbol-observable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", + "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" + }, + "tar": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-3.2.1.tgz", + "integrity": "sha512-ZSzds1E0IqutvMU8HxjMaU8eB7urw2fGwTq88ukDOVuUIh0656l7/P7LiVPxhO5kS4flcRJQk8USG+cghQbTUQ==", + "requires": { + "chownr": "1.0.1", + "minipass": "2.2.1", + "minizlib": "1.0.4", + "mkdirp": "0.5.1", + "yallist": "3.0.2" + } + }, + "tcp-port-used": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-0.1.2.tgz", + "integrity": "sha1-lFDodoyDtBb9TRpqlEnuzL9JbCk=", + "requires": { + "debug": "0.7.4", + "is2": "0.0.9", + "q": "0.9.7" + }, + "dependencies": { + "debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=" + }, + "q": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "integrity": "sha1-TeLmyzspCIyeTLwDv51C+5bOL3U=" + } + } + }, + "terminal-kit": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/terminal-kit/-/terminal-kit-1.14.0.tgz", + "integrity": "sha512-ir0I2QtcBDSg2w0UvohlqdDpGlS3S2UYBG4NnYKnK/4VywgnbfxgdpXN3el0uCH3OeH6fG38luW7RmDM96FqUw==", + "requires": { + "async-kit": "2.2.3", + "get-pixels": "3.3.0", + "ndarray": "1.0.18", + "nextgen-events": "0.10.2", + "string-kit": "0.6.3", + "tree-kit": "0.5.26" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "tkwidgets": { + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/tkwidgets/-/tkwidgets-0.5.20.tgz", + "integrity": "sha512-9wGsMrrFJvE/6TKUc0dEFFhwxvZLeNsYOxnpy1JCwyk/hYCEF70nuvk7VvJeG4TPaQBaGKPj6c7pCgdREvz4Jw==", + "requires": { + "chalk": "2.3.0", + "emphasize": "1.5.0", + "node-emoji": "git+https://github.com/laurent22/node-emoji.git#9fa01eac463e94dde1316ef8c53089eeef4973b5", + "slice-ansi": "1.0.0", + "string-width": "2.1.1", + "terminal-kit": "1.14.0", + "wrap-ansi": "3.0.1" + }, + "dependencies": { + "node-emoji": { + "version": "git+https://github.com/laurent22/node-emoji.git#9fa01eac463e94dde1316ef8c53089eeef4973b5", + "requires": { + "lodash.toarray": "4.4.0" + } + } + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "tree-kit": { + "version": "0.5.26", + "resolved": "https://registry.npmjs.org/tree-kit/-/tree-kit-0.5.26.tgz", + "integrity": "sha1-hXHIb6JNHbdU5bDLOn4J9B50qN8=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xregexp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-3.2.0.tgz", + "integrity": "sha1-yzYBmHv+JpW1hAAMGPHEqMMih44=" + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "requires": { + "camelcase": "4.1.0" + } + } + } +} diff --git a/CliClient/package.json b/CliClient/package.json index 195ebd38d..56df02f30 100644 --- a/CliClient/package.json +++ b/CliClient/package.json @@ -1,63 +1,70 @@ { "name": "joplin", - "description": "CLI client for Joplin", + "description": "Joplin CLI Client", "license": "MIT", + "author": "Laurent Cozic", + "bugs": { + "url": "https://github.com/laurent22/joplin/issues" + }, "repository": { "type": "git", "url": "https://github.com/laurent22/joplin" }, - "url": "git://github.com/laurent22/joplin.git", - "version": "0.9.17", + "copyright": { + "title": "Joplin CLI", + "years": [ + 2016, + 2017 + ], + "owner": "Laurent Cozic" + }, + "version": "0.10.74", "bin": { "joplin": "./main.js" }, + "engines": { + "node": ">=8.7.0" + }, "dependencies": { "app-module-path": "^2.2.0", - "babel-plugin-transform-runtime": "^6.23.0", - "cache-require-paths": "^0.3.0", "follow-redirects": "^1.2.4", "form-data": "^2.1.4", "fs-extra": "^3.0.1", + "html-entities": "^1.2.1", "jssha": "^2.3.0", "levenshtein": "^1.0.5", "lodash": "^4.17.4", "md5": "^2.2.1", + "mime": "^2.0.3", "moment": "^2.18.1", + "node-emoji": "^1.8.1", "node-fetch": "^1.7.1", "node-persist": "^2.1.0", "os-tmpdir": "^1.0.2", "promise": "^7.1.1", "proper-lockfile": "^2.0.1", "query-string": "4.3.4", + "redux": "^3.7.2", "sax": "^1.2.2", "server-destroy": "^1.0.1", - "source-map-support": "^0.4.15", + "sharp": "^0.18.4", "sprintf-js": "^1.1.1", "sqlite3": "^3.1.8", "string-padding": "^1.0.2", "string-to-stream": "^1.1.0", + "strip-ansi": "^4.0.0", "tcp-port-used": "^0.1.2", + "tkwidgets": "^0.5.20", "uuid": "^3.0.1", - "yargs-parser": "^7.0.0", - "word-wrap": "^1.2.3" + "word-wrap": "^1.2.3", + "yargs-parser": "^7.0.0" }, "devDependencies": { - "babel-changed": "^7.0.0", - "babel-cli": "^6.24.1", - "babel-plugin-syntax-async-functions": "^6.1.4", - "babel-plugin-transform-regenerator": "^6.1.4", - "babel-polyfill": "^6.1.4", - "babel-preset-env": "^1.5.1", - "babel-preset-es2015": "^6.1.4", - "babel-preset-react": "^6.24.1", "gettext-parser": "^1.2.2", - "jasmine": "^2.6.0" + "jasmine": "^2.6.0", + "mustache": "^2.3.0" }, "scripts": { - "babelbuild": "babel app -d build", - "build": "babel-changed app -d build --source-maps && babel-changed app/lib/models -d build/lib/models --source-maps && babel-changed app/lib/services -d build/lib/services --source-maps", - "clean": "babel-changed --reset", - "test": "babel-changed tests -d tests-build --source-maps && jasmine", - "postinstall": "joplin --autocompletion --ac-install" + "test": "jasmine" } } diff --git a/CliClient/package.json.md5 b/CliClient/package.json.md5 deleted file mode 100644 index d3387bab0..000000000 --- a/CliClient/package.json.md5 +++ /dev/null @@ -1 +0,0 @@ -320eb753be882e5509e873e2b5f624e3 \ No newline at end of file diff --git a/CliClient/publish.sh b/CliClient/publish.sh index 30b8471b5..91e19d64e 100755 --- a/CliClient/publish.sh +++ b/CliClient/publish.sh @@ -2,8 +2,8 @@ set -e SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$SCRIPT_DIR" npm version patch -$SCRIPT_DIR/update-package-md5.sh touch "$SCRIPT_DIR/app/main.js" bash $SCRIPT_DIR/build.sh cp "$SCRIPT_DIR/package.json" build/ diff --git a/CliClient/run.sh b/CliClient/run.sh index 43779cf85..eeb6dc569 100755 --- a/CliClient/run.sh +++ b/CliClient/run.sh @@ -2,5 +2,6 @@ set -e CLIENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -bash $CLIENT_DIR/build.sh && NODE_PATH="$CLIENT_DIR/build/" node build/main.js --profile ~/Temp/TestNotes2 --stack-trace-enabled --log-level debug --env dev "$@" -#bash $CLIENT_DIR/build.sh && NODE_PATH="$CLIENT_DIR/build/" node build/main.js --stack-trace-enabled --log-level debug "$@" +bash "$CLIENT_DIR/build.sh" && node "$CLIENT_DIR/build/main.js" --profile ~/Temp/TestNotes2 --stack-trace-enabled --log-level debug --env dev "$@" + +#bash $CLIENT_DIR/build.sh && NODE_PATH="$CLIENT_DIR/build/" node build/main.js --profile ~/Temp/TestNotes2 --stack-trace-enabled --log-level debug --env dev "$@" \ No newline at end of file diff --git a/CliClient/run_test.sh b/CliClient/run_test.sh index 9267b88b6..b235e24cc 100755 --- a/CliClient/run_test.sh +++ b/CliClient/run_test.sh @@ -1,11 +1,10 @@ #!/bin/bash -CLIENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +BUILD_DIR="$ROOT_DIR/tests-build" -rm -f "$CLIENT_DIR/tests-build/lib" -mkdir -p "$CLIENT_DIR/tests-build/data" -ln -s "$CLIENT_DIR/build/lib" "$CLIENT_DIR/tests-build" +rsync -a --exclude "node_modules/" "$ROOT_DIR/tests/" "$BUILD_DIR/" +rsync -a "$ROOT_DIR/../ReactNativeClient/lib/" "$BUILD_DIR/lib/" +rsync -a "$ROOT_DIR/build/locales/" "$BUILD_DIR/locales/" +mkdir -p "$BUILD_DIR/data" -npm run build && NODE_PATH="$CLIENT_DIR/tests-build/" npm test tests-build/synchronizer.js - -#npm run build && NODE_PATH="$CLIENT_DIR/tests-build/" npm test tests-build/synchronizer.js -#npm run build && NODE_PATH="$CLIENT_DIR/tests-build/" npm test tests-build/base-model.js \ No newline at end of file +npm test tests-build/synchronizer.js \ No newline at end of file diff --git a/CliClient/tests/base-model.js b/CliClient/tests/base-model.js index 5fa29dbcb..a4b690add 100644 --- a/CliClient/tests/base-model.js +++ b/CliClient/tests/base-model.js @@ -1,10 +1,10 @@ -import { time } from 'lib/time-utils.js'; -import { setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient } from 'test-utils.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { Setting } from 'lib/models/setting.js'; -import { BaseItem } from 'lib/models/base-item.js'; -import { BaseModel } from 'lib/base-model.js'; +const { time } = require('lib/time-utils.js'); +const { setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient } = require('test-utils.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { Setting } = require('lib/models/setting.js'); +const { BaseItem } = require('lib/models/base-item.js'); +const { BaseModel } = require('lib/base-model.js'); process.on('unhandledRejection', (reason, p) => { console.error('Unhandled promise rejection at: Promise', p, 'reason:', reason); diff --git a/CliClient/tests/synchronizer.js b/CliClient/tests/synchronizer.js index 142cb74b4..bf0a5277f 100644 --- a/CliClient/tests/synchronizer.js +++ b/CliClient/tests/synchronizer.js @@ -1,15 +1,15 @@ -require('source-map-support').install(); -require('babel-plugin-transform-runtime'); +require('app-module-path').addPath(__dirname); -import { time } from 'lib/time-utils.js'; -import { setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId } from 'test-utils.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { Tag } from 'lib/models/tag.js'; -import { Database } from 'lib/database.js'; -import { Setting } from 'lib/models/setting.js'; -import { BaseItem } from 'lib/models/base-item.js'; -import { BaseModel } from 'lib/base-model.js'; +const { time } = require('lib/time-utils.js'); +const { setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId } = require('test-utils.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { Tag } = require('lib/models/tag.js'); +const { Database } = require('lib/database.js'); +const { Setting } = require('lib/models/setting.js'); +const { BaseItem } = require('lib/models/base-item.js'); +const { BaseModel } = require('lib/base-model.js'); +const SyncTargetRegistry = require('lib/SyncTargetRegistry.js'); process.on('unhandledRejection', (reason, p) => { console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); @@ -38,7 +38,7 @@ async function localItemsSameAsRemote(locals, expect) { expect(!!remote).toBe(true); if (!remote) continue; - if (syncTargetId() == Setting.SYNC_TARGET_FILESYSTEM) { + if (syncTargetId() == SyncTargetRegistry.nameToId('filesystem')) { expect(remote.updated_time).toBe(Math.floor(dbItem.updated_time / 1000) * 1000); } else { expect(remote.updated_time).toBe(dbItem.updated_time); @@ -321,7 +321,7 @@ describe('Synchronizer', function() { let note = await Note.save({ title: "note1", parent_id: folder1.id }); await synchronizer().start(); - let items = await allItems(); + let items = await allItems(); expect(items.length).toBe(1); expect(items[0].title).toBe('note1'); expect(items[0].is_conflict).toBe(1); @@ -567,5 +567,65 @@ describe('Synchronizer', function() { done(); }); + + it('should not consider it is a conflict if neither the title nor body of the note have changed', async (done) => { + // That was previously a common conflict: + // - Client 1 mark todo as "done", and sync + // - Client 2 doesn't sync, mark todo as "done" todo. Then sync. + // In theory it is a conflict because the todo_completed dates are different + // but in practice it doesn't matter, we can just take the date when the + // todo was marked as "done" the first time. + + let folder1 = await Folder.save({ title: "folder1" }); + let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id }); + await synchronizer().start(); + + await switchClient(2); + + await synchronizer().start(); + let note2 = await Note.load(note1.id); + note2.todo_completed = time.unixMs()-1; + await Note.save(note2); + note2 = await Note.load(note2.id); + await synchronizer().start(); + + await switchClient(1); + + let note2conf = await Note.load(note1.id); + note2conf.todo_completed = time.unixMs(); + await Note.save(note2conf); + note2conf = await Note.load(note1.id); + await synchronizer().start(); + + let conflictedNotes = await Note.conflictedNotes(); + expect(conflictedNotes.length).toBe(0); + + let notes = await Note.all(); + expect(notes.length).toBe(1); + expect(notes[0].id).toBe(note1.id); + expect(notes[0].todo_completed).toBe(note2.todo_completed); + + done(); + }); + + it('items should be downloaded again when user cancels in the middle of delta operation', async (done) => { + let folder1 = await Folder.save({ title: "folder1" }); + let note1 = await Note.save({ title: "un", is_todo: 1, parent_id: folder1.id }); + await synchronizer().start(); + + await switchClient(2); + + synchronizer().debugFlags_ = ['cancelDeltaLoop2']; + let context = await synchronizer().start(); + let notes = await Note.all(); + expect(notes.length).toBe(0); + + synchronizer().debugFlags_ = []; + await synchronizer().start({ context: context }); + notes = await Note.all(); + expect(notes.length).toBe(1); + + done(); + }); }); \ No newline at end of file diff --git a/CliClient/tests/test-utils.js b/CliClient/tests/test-utils.js index f43386d73..d9ca69092 100644 --- a/CliClient/tests/test-utils.js +++ b/CliClient/tests/test-utils.js @@ -1,21 +1,24 @@ -import fs from 'fs-extra'; -import { JoplinDatabase } from 'lib/joplin-database.js'; -import { DatabaseDriverNode } from 'lib/database-driver-node.js'; -import { BaseModel } from 'lib/base-model.js'; -import { Folder } from 'lib/models/folder.js'; -import { Note } from 'lib/models/note.js'; -import { Resource } from 'lib/models/resource.js'; -import { Tag } from 'lib/models/tag.js'; -import { NoteTag } from 'lib/models/note-tag.js'; -import { Logger } from 'lib/logger.js'; -import { Setting } from 'lib/models/setting.js'; -import { BaseItem } from 'lib/models/base-item.js'; -import { Synchronizer } from 'lib/synchronizer.js'; -import { FileApi } from 'lib/file-api.js'; -import { FileApiDriverMemory } from 'lib/file-api-driver-memory.js'; -import { FileApiDriverLocal } from 'lib/file-api-driver-local.js'; -import { FsDriverNode } from '../app/fs-driver-node.js'; -import { time } from 'lib/time-utils.js'; +const fs = require('fs-extra'); +const { JoplinDatabase } = require('lib/joplin-database.js'); +const { DatabaseDriverNode } = require('lib/database-driver-node.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { Resource } = require('lib/models/resource.js'); +const { Tag } = require('lib/models/tag.js'); +const { NoteTag } = require('lib/models/note-tag.js'); +const { Logger } = require('lib/logger.js'); +const { Setting } = require('lib/models/setting.js'); +const { BaseItem } = require('lib/models/base-item.js'); +const { Synchronizer } = require('lib/synchronizer.js'); +const { FileApi } = require('lib/file-api.js'); +const { FileApiDriverMemory } = require('lib/file-api-driver-memory.js'); +const { FileApiDriverLocal } = require('lib/file-api-driver-local.js'); +const { FsDriverNode } = require('lib/fs-driver-node.js'); +const { time } = require('lib/time-utils.js'); +const SyncTargetRegistry = require('lib/SyncTargetRegistry.js'); +const SyncTargetMemory = require('lib/SyncTargetMemory.js'); +const SyncTargetFilesystem = require('lib/SyncTargetFilesystem.js'); let databases_ = []; let synchronizers_ = []; @@ -29,12 +32,13 @@ Resource.fsDriver_ = fsDriver; const logDir = __dirname + '/../tests/logs'; fs.mkdirpSync(logDir, 0o755); -const syncTargetId_ = Setting.SYNC_TARGET_MEMORY; -//const syncTargetId_ = Setting.SYNC_TARGET_FILESYSTEM; -//const syncTargetId_ = Setting.SYNC_TARGET_ONEDRIVE; +SyncTargetRegistry.addClass(SyncTargetMemory); +SyncTargetRegistry.addClass(SyncTargetFilesystem); + +const syncTargetId_ = SyncTargetRegistry.nameToId('memory'); const syncDir = __dirname + '/../tests/sync'; -const sleepTime = syncTargetId_ == Setting.SYNC_TARGET_FILESYSTEM ? 1001 : 400; +const sleepTime = syncTargetId_ == SyncTargetRegistry.nameToId('filesystem') ? 1001 : 400; const logger = new Logger(); logger.addTarget('file', { path: logDir + '/log.txt' }); @@ -106,6 +110,8 @@ function setupDatabase(id = null) { // Don't care if the file doesn't exist }).then(() => { databases_[id] = new JoplinDatabase(new DatabaseDriverNode()); + // databases_[id].setLogger(logger); + // console.info(filePath); return databases_[id].open({ name: filePath }).then(() => { BaseModel.db_ = databases_[id]; return setupDatabase(id); @@ -119,11 +125,14 @@ async function setupDatabaseAndSynchronizer(id = null) { await setupDatabase(id); if (!synchronizers_[id]) { - synchronizers_[id] = new Synchronizer(db(id), fileApi(), Setting.value('appType')); - synchronizers_[id].setLogger(logger); + const SyncTargetClass = SyncTargetRegistry.classById(syncTargetId_); + const syncTarget = new SyncTargetClass(db(id)); + syncTarget.setFileApi(fileApi()); + syncTarget.setLogger(logger); + synchronizers_[id] = await syncTarget.synchronizer(); } - if (syncTargetId_ == Setting.SYNC_TARGET_FILESYSTEM) { + if (syncTargetId_ == SyncTargetRegistry.nameToId('filesystem')) { fs.removeSync(syncDir) fs.mkdirpSync(syncDir, 0o755); } else { @@ -144,13 +153,12 @@ function synchronizer(id = null) { function fileApi() { if (fileApi_) return fileApi_; - if (syncTargetId_ == Setting.SYNC_TARGET_FILESYSTEM) { + if (syncTargetId_ == SyncTargetRegistry.nameToId('filesystem')) { fs.removeSync(syncDir) fs.mkdirpSync(syncDir, 0o755); fileApi_ = new FileApi(syncDir, new FileApiDriverLocal()); - } else if (syncTargetId_ == Setting.SYNC_TARGET_MEMORY) { + } else if (syncTargetId_ == SyncTargetRegistry.nameToId('memory')) { fileApi_ = new FileApi('/root', new FileApiDriverMemory()); - fileApi_.setLogger(logger); } // } else if (syncTargetId == Setting.SYNC_TARGET_ONEDRIVE) { // let auth = require('./onedrive-auth.json'); @@ -174,4 +182,4 @@ function fileApi() { return fileApi_; } -export { setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId }; \ No newline at end of file +module.exports = { setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId }; \ No newline at end of file diff --git a/CliClient/update-package-md5.sh b/CliClient/update-package-md5.sh deleted file mode 100755 index 962efedac..000000000 --- a/CliClient/update-package-md5.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -MD5="$(cat "$ROOT_DIR/package.json" | md5sum | cut -d' ' -f 1)" -echo -n $MD5 > "$ROOT_DIR/package.json.md5" \ No newline at end of file diff --git a/CliClient/yarn.lock b/CliClient/yarn.lock deleted file mode 100644 index d29160c29..000000000 --- a/CliClient/yarn.lock +++ /dev/null @@ -1,2106 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -abbrev@1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" - -ajv@^4.9.1: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -anymatch@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" - dependencies: - micromatch "^2.1.5" - normalize-path "^2.0.0" - -app-module-path@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" - -aproba@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" - -are-we-there-yet@~1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - dependencies: - arr-flatten "^1.0.1" - -arr-flatten@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - -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: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - -asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - -async-each@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - -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: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - -babel-changed@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/babel-changed/-/babel-changed-7.0.0.tgz#fe7a57135ca29badc2ba82821c1f94e99bda334c" - dependencies: - file-entry-cache "^2.0.0" - flat-cache "^1.2.1" - fs-extra "^0.30.0" - glob "^7.1.0" - hash-sum "^1.0.2" - lodash.uniq "^4.5.0" - path-exists "^3.0.0" - pty.js "^0.3.1" - -babel-cli@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-cli/-/babel-cli-6.24.1.tgz#207cd705bba61489b2ea41b5312341cf6aca2283" - dependencies: - babel-core "^6.24.1" - babel-polyfill "^6.23.0" - babel-register "^6.24.1" - babel-runtime "^6.22.0" - commander "^2.8.1" - convert-source-map "^1.1.0" - fs-readdir-recursive "^1.0.0" - glob "^7.0.0" - lodash "^4.2.0" - output-file-sync "^1.1.0" - path-is-absolute "^1.0.0" - slash "^1.0.0" - source-map "^0.5.0" - v8flags "^2.0.10" - optionalDependencies: - chokidar "^1.6.1" - -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: - chalk "^1.1.0" - esutils "^2.0.2" - js-tokens "^3.0.0" - -babel-core@^6.24.1: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729" - dependencies: - babel-code-frame "^6.22.0" - babel-generator "^6.25.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.25.0" - babel-traverse "^6.25.0" - babel-types "^6.25.0" - babylon "^6.17.2" - convert-source-map "^1.1.0" - debug "^2.1.1" - json5 "^0.5.0" - lodash "^4.2.0" - minimatch "^3.0.2" - path-is-absolute "^1.0.0" - private "^0.1.6" - slash "^1.0.0" - source-map "^0.5.0" - -babel-generator@^6.25.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc" - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-types "^6.25.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.2.0" - source-map "^0.5.0" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-builder-react-jsx@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.24.1.tgz#0ad7917e33c8d751e646daca4e77cc19377d2cbc" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - esutils "^2.0.0" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz#7a9747f258d8947d32d515f6aa1c7bd02204a080" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - lodash "^4.2.0" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - dependencies: - 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" - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz#d36e22fab1008d79d88648e32116868128456ce8" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - lodash "^4.2.0" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.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-syntax-async-functions@^6.1.4, 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-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" - -babel-plugin-syntax-flow@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" - -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-trailing-function-commas@^6.22.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-to-generator@^6.22.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: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -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" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0, babel-plugin-transform-es2015-block-scoping@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz#76c295dc3a4741b1665adfd3167215dcff32a576" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - lodash "^4.2.0" - -babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0, babel-plugin-transform-es2015-computed-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.22.0, babel-plugin-transform-es2015-destructuring@^6.23.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: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0, babel-plugin-transform-es2015-duplicate-keys@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.22.0, babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.24.1: - 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: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.23.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" - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0, babel-plugin-transform-es2015-modules-systemjs@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0, babel-plugin-transform-es2015-modules-umd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0, babel-plugin-transform-es2015-object-super@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.23.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: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0, babel-plugin-transform-es2015-shorthand-properties@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.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.22.0, babel-plugin-transform-es2015-sticky-regex@^6.24.1: - 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: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.22.0, babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.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: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.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: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-flow-strip-types@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" - dependencies: - babel-plugin-syntax-flow "^6.18.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-display-name@^6.23.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz#67e2bf1f1e9c93ab08db96792e05392bf2cc28d1" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-self@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-source@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz#840a028e7df460dfc3a2d29f0c0d91f6376e66a3" - dependencies: - babel-helper-builder-react-jsx "^6.24.1" - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-regenerator@^6.1.4, babel-plugin-transform-regenerator@^6.22.0, babel-plugin-transform-regenerator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418" - dependencies: - regenerator-transform "0.9.11" - -babel-plugin-transform-runtime@^6.23.0: - 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" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-polyfill@^6.1.4, babel-polyfill@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-polyfill/-/babel-polyfill-6.23.0.tgz#8364ca62df8eafb830499f699177466c3b03499d" - dependencies: - babel-runtime "^6.22.0" - core-js "^2.4.0" - regenerator-runtime "^0.10.0" - -babel-preset-env@^1.5.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.0.tgz#2de1c782a780a0a5d605d199c957596da43c44e4" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^2.1.2" - invariant "^2.2.2" - semver "^5.3.0" - -babel-preset-es2015@^6.1.4: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz#d44050d6bc2c9feea702aaf38d727a0210538939" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.24.1" - babel-plugin-transform-es2015-classes "^6.24.1" - babel-plugin-transform-es2015-computed-properties "^6.24.1" - babel-plugin-transform-es2015-destructuring "^6.22.0" - babel-plugin-transform-es2015-duplicate-keys "^6.24.1" - babel-plugin-transform-es2015-for-of "^6.22.0" - babel-plugin-transform-es2015-function-name "^6.24.1" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-plugin-transform-es2015-modules-systemjs "^6.24.1" - babel-plugin-transform-es2015-modules-umd "^6.24.1" - babel-plugin-transform-es2015-object-super "^6.24.1" - babel-plugin-transform-es2015-parameters "^6.24.1" - babel-plugin-transform-es2015-shorthand-properties "^6.24.1" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.24.1" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.22.0" - babel-plugin-transform-es2015-unicode-regex "^6.24.1" - babel-plugin-transform-regenerator "^6.24.1" - -babel-preset-flow@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" - dependencies: - babel-plugin-transform-flow-strip-types "^6.22.0" - -babel-preset-react@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.24.1.tgz#ba69dfaea45fc3ec639b6a4ecea6e17702c91380" - dependencies: - babel-plugin-syntax-jsx "^6.3.13" - babel-plugin-transform-react-display-name "^6.23.0" - babel-plugin-transform-react-jsx "^6.24.1" - babel-plugin-transform-react-jsx-self "^6.22.0" - babel-plugin-transform-react-jsx-source "^6.22.0" - babel-preset-flow "^6.23.0" - -babel-register@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.1.tgz#7e10e13a2f71065bdfad5a1787ba45bca6ded75f" - dependencies: - babel-core "^6.24.1" - babel-runtime "^6.22.0" - core-js "^2.4.0" - home-or-tmp "^2.0.0" - lodash "^4.2.0" - mkdirp "^0.5.1" - source-map-support "^0.4.2" - -babel-runtime@^6.18.0, babel-runtime@^6.22.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.25.0.tgz#33b98eaa5d482bb01a8d1aa6b437ad2b01aec41c" - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.10.0" - -babel-template@^6.24.1, babel-template@^6.25.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.25.0" - babel-types "^6.25.0" - babylon "^6.17.2" - lodash "^4.2.0" - -babel-traverse@^6.24.1, babel-traverse@^6.25.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1" - dependencies: - babel-code-frame "^6.22.0" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-types "^6.25.0" - babylon "^6.17.2" - debug "^2.2.0" - globals "^9.0.0" - invariant "^2.2.0" - lodash "^4.2.0" - -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.25.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e" - dependencies: - babel-runtime "^6.22.0" - esutils "^2.0.2" - lodash "^4.2.0" - to-fast-properties "^1.0.1" - -babylon@^6.17.2: - version "6.17.4" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" - dependencies: - tweetnacl "^0.14.3" - -binary-extensions@^1.0.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.9.0.tgz#66506c16ce6f4d6928a5b3cd6a33ca41e941e37b" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - dependencies: - inherits "~2.0.0" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - -brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -browserslist@^2.1.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.2.2.tgz#e9b4618b8a01c193f9786beea09f6fd10dbe31c3" - dependencies: - caniuse-lite "^1.0.30000704" - electron-to-chromium "^1.3.16" - -cache-require-paths@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/cache-require-paths/-/cache-require-paths-0.3.0.tgz#12a6075a3e4988da4c22f218e29485663e4c4a63" - -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - -caniuse-lite@^1.0.30000704: - version "1.0.30000710" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000710.tgz#1c249bf7c6a61161c9b10906e3ad9fa5b6761af1" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - -chalk@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -charenc@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - -chokidar@^1.6.1: - version "1.7.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - dependencies: - anymatch "^1.3.0" - async-each "^1.0.0" - glob-parent "^2.0.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^2.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - optionalDependencies: - fsevents "^1.0.0" - -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -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" - -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" - dependencies: - delayed-stream "~1.0.0" - -commander@^2.8.1: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - -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" - -core-js@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" - -core-util-is@1.0.2, 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" - -crypt@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - dependencies: - assert-plus "^1.0.0" - -debug@0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" - -debug@^2.1.1, debug@^2.2.0, debug@^2.4.5: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" - dependencies: - ms "2.0.0" - -deep-extend@~0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" - -deep-is@0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.2.tgz#9ced65ea0bc0b09f42a6d79c1b1903f9d913cc18" - -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - dependencies: - repeating "^2.0.0" - -ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" - dependencies: - jsbn "~0.1.0" - -electron-to-chromium@^1.3.16: - version "1.3.17" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.17.tgz#41c13457cc7166c5c15e767ae61d86a8cacdee5d" - -encoding@^0.1.11, encoding@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - dependencies: - iconv-lite "~0.4.13" - -escape-string-regexp@^1.0.2: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -esutils@^2.0.0, esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - dependencies: - fill-range "^2.1.0" - -extend@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-1.2.1.tgz#a0f5fd6cfc83a5fe49ef698d60ec8a624dd4576c" - -extend@~3.0.0: - 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" - dependencies: - is-extglob "^1.0.0" - -extsprintf@1.3.0, extsprintf@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - -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" - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - -fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^1.1.3" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -flat-cache@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" - dependencies: - circular-json "^0.3.1" - del "^2.0.2" - graceful-fs "^4.1.2" - write "^0.2.1" - -follow-redirects@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.2.4.tgz#355e8f4d16876b43f577b0d5ce2668b9723214ea" - dependencies: - debug "^2.4.5" - -for-in@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - dependencies: - for-in "^1.0.1" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -form-data@^2.1.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.2.0.tgz#9a5e3b9295f980b2623cf64fa238b14cebca707b" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" - -fs-extra@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^3.0.0" - universalify "^0.1.0" - -fs-readdir-recursive@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz#8cd1745c8b4f8a29c8caec392476921ba195f560" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -fsevents@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4" - dependencies: - nan "^2.3.0" - node-pre-gyp "^0.6.36" - -fstream-ignore@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" - dependencies: - fstream "^1.0.0" - inherits "2" - minimatch "^3.0.0" - -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - dependencies: - assert-plus "^1.0.0" - -gettext-parser@^1.2.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/gettext-parser/-/gettext-parser-1.3.0.tgz#61465851c266f8521ba69e61ef505aa54f635d0a" - dependencies: - encoding "^0.1.12" - safe-buffer "^5.1.1" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - dependencies: - is-glob "^2.0.0" - -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.0: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^9.0.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" - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6, graceful-fs@^4.1.9: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -har-schema@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - -har-validator@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - dependencies: - ajv "^4.9.1" - har-schema "^1.0.5" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - -hash-sum@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/hash-sum/-/hash-sum-1.0.2.tgz#33b40777754c6432573c120cc3808bbd10d47f04" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -iconv-lite@~0.4.13: - version "0.4.18" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@~2.0.0, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -ini@~1.3.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" - -invariant@^2.2.0, invariant@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" - dependencies: - loose-envify "^1.0.0" - -is-absolute@^0.2.6: - version "0.2.6" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.2.6.tgz#20de69f3db942ef2d87b9c2da36f172235b1b5eb" - dependencies: - is-relative "^0.2.1" - is-windows "^0.2.0" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5, is-buffer@~1.1.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - dependencies: - number-is-nan "^1.0.0" - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - dependencies: - is-extglob "^1.0.0" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - dependencies: - kind-of "^3.0.2" - -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" - -is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" - dependencies: - path-is-inside "^1.0.1" - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - -is-relative@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5" - dependencies: - is-unc-path "^0.1.1" - -is-stream@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -is-unc-path@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-0.1.2.tgz#6ab053a72573c10250ff416a3814c35178af39b9" - dependencies: - unc-path-regex "^0.1.0" - -is-windows@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" - -is2@0.0.9: - version "0.0.9" - resolved "https://registry.yarnpkg.com/is2/-/is2-0.0.9.tgz#119556d1d1651a41ba105af803267c80b299f629" - dependencies: - deep-is "0.1.2" - -isarray@1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - dependencies: - isarray "1.0.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -jasmine-core@~2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.7.0.tgz#50ff8c4f92d8ef5c0b2c1b846dd263ed85152091" - -jasmine@^2.6.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/jasmine/-/jasmine-2.7.0.tgz#5cf0bb4e594b4600bb4235560366212ac5aea1b2" - dependencies: - exit "^0.1.2" - glob "^7.0.6" - jasmine-core "~2.7.0" - -js-tokens@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -json5@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - -jsonfile@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -jssha@^2.3.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/jssha/-/jssha-2.3.1.tgz#147b2125369035ca4b2f7d210dc539f009b3de9a" - -kind-of@^3.0.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - dependencies: - is-buffer "^1.1.5" - -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - optionalDependencies: - graceful-fs "^4.1.9" - -levenshtein@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/levenshtein/-/levenshtein-1.0.5.tgz#3911737a9cb56da345d008f55782c6f138979ba3" - -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - -lodash@^4.17.4, lodash@^4.2.0: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - -loose-envify@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" - dependencies: - js-tokens "^3.0.0" - -md5@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" - dependencies: - charenc "~0.0.1" - crypt "~0.0.1" - is-buffer "~1.1.1" - -micromatch@^2.1.5: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -mime-db@~1.29.0: - version "1.29.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878" - -mime-types@^2.1.12, mime-types@~2.1.7: - version "2.1.16" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.16.tgz#2b858a52e5ecd516db897ac2be87487830698e23" - dependencies: - mime-db "~1.29.0" - -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -"mkdirp@>=0.5 0", mkdirp@^0.5.1, mkdirp@~0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -moment@^2.18.1: - version "2.18.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - -nan@2.3.5: - version "2.3.5" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.3.5.tgz#822a0dc266290ce4cd3a12282ca3e7e364668a08" - -nan@^2.3.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" - -nan@~2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.4.0.tgz#fb3c59d45fe4effe215f0b890f8adf6eb32d2232" - -node-fetch@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.1.tgz#899cb3d0a3c92f952c47f1b876f4c8aeabd400d5" - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-persist@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/node-persist/-/node-persist-2.1.0.tgz#e652bbf3885a04dad6a353d74176177c83914707" - dependencies: - is-absolute "^0.2.6" - mkdirp "~0.5.1" - q "~1.1.1" - -node-pre-gyp@^0.6.36, node-pre-gyp@~0.6.31: - version "0.6.36" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786" - dependencies: - mkdirp "^0.5.1" - nopt "^4.0.1" - npmlog "^4.0.2" - rc "^1.1.7" - request "^2.81.0" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^2.2.1" - tar-pack "^3.4.0" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-path@^2.0.0, normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - dependencies: - remove-trailing-separator "^1.0.1" - -npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -oauth-sign@~0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - -object-assign@^4.0.1, object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -once@^1.3.0, once@^1.3.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - -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" - -output-file-sync@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/output-file-sync/-/output-file-sync-1.1.2.tgz#d0a33eefe61a205facb90092e826598d5245ce76" - dependencies: - graceful-fs "^4.1.4" - mkdirp "^0.5.1" - object-assign "^4.1.0" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -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: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -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" - -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - -private@^0.1.6: - version "0.1.7" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" - -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" - -promise@^7.1.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - dependencies: - asap "~2.0.3" - -proper-lockfile@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-2.0.1.tgz#159fb06193d32003f4b3691dd2ec1a634aa80d1d" - dependencies: - graceful-fs "^4.1.2" - retry "^0.10.0" - -pty.js@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/pty.js/-/pty.js-0.3.1.tgz#81f5bed332d6e5e7ab685688d1ba0373410d51b5" - dependencies: - extend "~1.2.1" - nan "2.3.5" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -q@0.9.7: - version "0.9.7" - resolved "https://registry.yarnpkg.com/q/-/q-0.9.7.tgz#4de2e6cb3b29088c9e4cbc03bf9d42fb96ce2f75" - -q@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/q/-/q-1.1.2.tgz#6357e291206701d99f197ab84e57e8ad196f2a89" - -qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - -query-string@4.3.4: - version "4.3.4" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" - dependencies: - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -rc@^1.1.7: - version "1.2.1" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" - dependencies: - deep-extend "~0.4.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.0, readable-stream@^2.1.4: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -readdirp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" - dependencies: - graceful-fs "^4.1.2" - minimatch "^3.0.2" - readable-stream "^2.0.2" - set-immediate-shim "^1.0.1" - -regenerate@^1.2.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" - -regenerator-runtime@^0.10.0: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - -regenerator-transform@0.9.11: - version "0.9.11" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.11.tgz#3a7d067520cb7b7176769eb5ff868691befe1283" - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - -regex-cache@^0.4.2: - version "0.4.3" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" - dependencies: - is-equal-shallow "^0.1.3" - is-primitive "^2.0.0" - -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - dependencies: - jsesc "~0.5.0" - -remove-trailing-separator@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz#69b062d978727ad14dc6b56ba4ab772fd8d70511" - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - dependencies: - is-finite "^1.0.0" - -request@^2.81.0: - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "^0.6.0" - uuid "^3.0.0" - -retry@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" - -rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" - dependencies: - glob "^7.0.5" - -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - -sax@^1.2.2: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - -semver@^5.3.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - -server-destroy@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" - -set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - -signal-exit@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - -source-map-support@^0.4.15, 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@^0.5.0, source-map@^0.5.6: - version "0.5.6" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" - -sprintf-js@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" - -sqlite3@^3.1.8: - version "3.1.8" - resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-3.1.8.tgz#4cbcf965d8b901d1b1015cbc7fc415aae157dfaa" - dependencies: - nan "~2.4.0" - node-pre-gyp "~0.6.31" - -sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - -string-padding@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-padding/-/string-padding-1.0.2.tgz#3aaad855b3e9735c5e412dfe72198ccf99c7f48e" - -string-to-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/string-to-stream/-/string-to-stream-1.1.0.tgz#acf2c9ead1c418e148509a12d2cbb469f333a218" - dependencies: - inherits "^2.0.1" - readable-stream "^2.1.0" - -string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -tar-pack@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984" - dependencies: - debug "^2.2.0" - fstream "^1.0.10" - fstream-ignore "^1.0.5" - once "^1.3.3" - readable-stream "^2.1.4" - rimraf "^2.5.1" - tar "^2.2.1" - uid-number "^0.0.6" - -tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - -tcp-port-used@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/tcp-port-used/-/tcp-port-used-0.1.2.tgz#9450e8768c83b416fd4d1a6a9449eeccbf496c29" - dependencies: - debug "0.7.4" - is2 "0.0.9" - q "0.9.7" - -to-fast-properties@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - -tough-cookie@~2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" - dependencies: - punycode "^1.4.1" - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - -uid-number@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - -unc-path-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - -universalify@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" - -user-home@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -uuid@^3.0.0, uuid@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" - -v8flags@^2.0.10: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.1.1.tgz#aab1a1fa30d45f88dd321148875ac02c0b55e5b4" - dependencies: - user-home "^1.1.1" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -wide-align@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" - dependencies: - string-width "^1.0.2" - -word-wrap@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - dependencies: - mkdirp "^0.5.1" - -yargs-parser@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - dependencies: - camelcase "^4.1.0" diff --git a/CliClientDemo/.gitignore b/CliClientDemo/.gitignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/CliClientDemo/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/CliClientDemo/database.sqlite b/CliClientDemo/database.sqlite new file mode 100644 index 000000000..d1b9b6f69 Binary files /dev/null and b/CliClientDemo/database.sqlite differ diff --git a/CliClientDemo/index.js b/CliClientDemo/index.js new file mode 100644 index 000000000..2bccfac51 --- /dev/null +++ b/CliClientDemo/index.js @@ -0,0 +1,31 @@ +#!/usr/bin/env node + +'use strict'; + +const spawn = require('child_process').spawn; +const os = require('os'); +const fs = require('fs-extra'); + +const joplinPath = __dirname + '/node_modules/.bin/joplin'; +const profileDir = os.homedir() + '/.config/demo-joplin'; +const dbFilename = 'database.sqlite'; + +fs.ensureDirSync(profileDir); +if (!fs.pathExistsSync(profileDir + '/' + dbFilename)) { + fs.copySync(__dirname + '/' + dbFilename, profileDir + '/' + dbFilename); +} + +const opt = { + cwd: __dirname, + env: (function() { + process.env.NODE_PATH = '.'; + return process.env; + }()), + stdio: [process.stdin, process.stdout, process.stderr] +}; + +const app = spawn(joplinPath, ['--is-demo', '--profile', profileDir], opt); + +app.on('close', (code) => { + process.exit(code); +}); \ No newline at end of file diff --git a/CliClientDemo/package-lock.json b/CliClientDemo/package-lock.json new file mode 100644 index 000000000..35b65b146 --- /dev/null +++ b/CliClientDemo/package-lock.json @@ -0,0 +1,2124 @@ +{ + "name": "demo-joplin", + "version": "1.0.8", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "ajv": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz", + "integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "requires": { + "color-convert": "1.9.1" + } + }, + "app-module-path": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", + "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=" + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async-kit": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/async-kit/-/async-kit-2.2.3.tgz", + "integrity": "sha1-JkdRonndxfWbQZY4uAWuLEmFj7c=", + "requires": { + "nextgen-events": "0.9.9", + "tree-kit": "0.5.26" + }, + "dependencies": { + "nextgen-events": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/nextgen-events/-/nextgen-events-0.9.9.tgz", + "integrity": "sha1-OaivxKK4RTiMV+LGu5cWcRmGo6A=" + } + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "requires": { + "get-proxy": "2.1.0", + "isurl": "1.0.0", + "tunnel-agent": "0.6.0", + "url-to-options": "1.0.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "color": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz", + "integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==", + "requires": { + "color-convert": "1.9.1", + "color-string": "1.5.2" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", + "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", + "requires": { + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" + } + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "config-chain": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "requires": { + "ini": "1.3.4", + "proto-list": "1.2.4" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "cwise-compiler": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", + "integrity": "sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=", + "requires": { + "uniq": "1.0.1" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "data-uri-to-buffer": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-0.0.3.tgz", + "integrity": "sha1-GK6XmmoMqZSwYlhTkW0mYruuCxo=" + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "1.0.0" + } + }, + "deep-is": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.2.tgz", + "integrity": "sha1-nO1l6gvAsJ9CptecGxkD+dkTzBg=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "detect-libc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-0.2.0.tgz", + "integrity": "sha1-R/31ZzSKF+wl/L8LnkRjSKdvn7U=" + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "emphasize": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/emphasize/-/emphasize-1.5.0.tgz", + "integrity": "sha1-48WvLdzLSYKCKjNJtHFhPMfOzJI=", + "requires": { + "chalk": "1.1.3", + "highlight.js": "9.12.0", + "lowlight": "1.9.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } + } + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.19" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "follow-redirects": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.2.5.tgz", + "integrity": "sha512-lMhwQTryFbG+wYsAIEKC1Kf5IGDlVNnONRogIBllh7LLoV7pNIxW0z9fhjRar9NBql+hd2Y49KboVVNxf6GEfg==", + "requires": { + "debug": "2.6.9" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + } + }, + "get-pixels": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/get-pixels/-/get-pixels-3.3.0.tgz", + "integrity": "sha1-jZeVvq4YhQuED3SVgbrcBdPjbkE=", + "requires": { + "data-uri-to-buffer": "0.0.3", + "jpeg-js": "0.1.2", + "mime-types": "2.1.17", + "ndarray": "1.0.18", + "ndarray-pack": "1.2.1", + "node-bitmap": "0.0.1", + "omggif": "1.0.8", + "parse-data-uri": "0.2.0", + "pngjs": "2.3.1", + "request": "2.83.0", + "through": "2.3.8" + } + }, + "get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "requires": { + "npm-conf": "1.1.3" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.3.0", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + }, + "has-symbol-support-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.1.tgz", + "integrity": "sha512-JkaetveU7hFbqnAC1EV1sF4rlojU2D4Usc5CmS69l6NfmPDnpnFUegzFg33eDkkpNCxZ0mQp65HwUDrNFS/8MA==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "1.4.1" + } + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "highlight.js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=" + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" + }, + "iota-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha1-ge9X/l0FgUzVjCSDYyqZwwoOgIc=" + }, + "is-absolute": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "requires": { + "is-relative": "0.2.1", + "is-windows": "0.2.0" + } + }, + "is-arrayish": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.1.tgz", + "integrity": "sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0=" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, + "is-relative": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "requires": { + "is-unc-path": "0.1.2" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-unc-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=" + }, + "is2": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/is2/-/is2-0.0.9.tgz", + "integrity": "sha1-EZVW0dFlGkG6EFr4AyZ8gLKZ9ik=", + "requires": { + "deep-is": "0.1.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" + } + }, + "joplin": { + "version": "0.10.69", + "resolved": "https://registry.npmjs.org/joplin/-/joplin-0.10.69.tgz", + "integrity": "sha512-P5b7pRiUqM2O/vG4etiAquGd7LM6j/eh93OmQgJmfcGu5F6D9DJERIjBP8Po/BnzXQVxsGnURHr3SmLlaUxQSg==", + "requires": { + "app-module-path": "2.2.0", + "follow-redirects": "1.2.5", + "form-data": "2.3.1", + "fs-extra": "3.0.1", + "html-entities": "1.2.1", + "jssha": "2.3.1", + "levenshtein": "1.0.5", + "lodash": "4.17.4", + "md5": "2.2.1", + "mime": "2.0.3", + "moment": "2.19.2", + "node-fetch": "1.7.3", + "node-persist": "2.1.0", + "os-tmpdir": "1.0.2", + "promise": "7.3.1", + "proper-lockfile": "2.0.1", + "query-string": "4.3.4", + "redux": "3.7.2", + "sax": "1.2.4", + "server-destroy": "1.0.1", + "sharp": "0.18.4", + "sprintf-js": "1.1.1", + "sqlite3": "3.1.13", + "string-padding": "1.0.2", + "string-to-stream": "1.1.0", + "strip-ansi": "4.0.0", + "tcp-port-used": "0.1.2", + "tkwidgets": "0.5.20", + "uuid": "3.1.0", + "word-wrap": "1.2.3", + "yargs-parser": "7.0.0" + }, + "dependencies": { + "fs-extra": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", + "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "3.0.1", + "universalify": "0.1.1" + } + }, + "jsonfile": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", + "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "requires": { + "graceful-fs": "4.1.11" + } + } + } + }, + "jpeg-js": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.1.2.tgz", + "integrity": "sha1-E1uZLAV1yYXPoPSUoyJ+0jhYPs4=" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jssha": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/jssha/-/jssha-2.3.1.tgz", + "integrity": "sha1-FHshJTaQNcpLL30hDcU58Amz3po=" + }, + "levenshtein": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/levenshtein/-/levenshtein-1.0.5.tgz", + "integrity": "sha1-ORFzepy1baNF0Aj1V4LG8TiXm6M=" + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash-es": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", + "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" + }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=" + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "requires": { + "js-tokens": "3.0.2" + } + }, + "lowlight": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-1.9.1.tgz", + "integrity": "sha512-CpDhyVhI+xHjruiGvH2F/Fr5q5aTn5A6Oyh7MI+4oI8G0A1E7p9a3Zqv9Hzx9WByK8gAiNifEueAXz+cA2xdEA==", + "requires": { + "highlight.js": "9.12.0" + } + }, + "md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "requires": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "1.1.6" + } + }, + "mime": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.0.3.tgz", + "integrity": "sha512-TrpAd/vX3xaLPDgVRm6JkZwLR0KHfukMdU2wTEbqMDdCnY6Yo3mE+mjs9YE6oMNw2QRfXVeBEYpmpO94BIqiug==" + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "mimic-response": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "minipass": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.1.tgz", + "integrity": "sha512-u1aUllxPJUI07cOqzR7reGmQxmCqlH88uIIsf6XZFEWgw7gXKpJdR+5R9Y3KEDmWYkdIz9wXZs3C0jOPxejk/Q==", + "requires": { + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.4.tgz", + "integrity": "sha512-sN4U9tIJtBRwKbwgFh9qJfrPIQ/GGTRr1MGqkgOeMTLy8/lM0FcWU//FqlnZ3Vb7gJ+Mxh3FOg1EklibdajbaQ==", + "requires": { + "minipass": "2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "moment": { + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.2.tgz", + "integrity": "sha512-Rf6jiHPEfxp9+dlzxPTmRHbvoFXsh2L/U8hOupUMpnuecHQmI6cF6lUbJl3QqKPko1u6ujO+FxtcajLVfLpAtA==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=" + }, + "ndarray": { + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.0.18.tgz", + "integrity": "sha1-tg06cyJOxVXQ+qeXEeUCRI/T95M=", + "requires": { + "iota-array": "1.0.0", + "is-buffer": "1.1.6" + } + }, + "ndarray-pack": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ndarray-pack/-/ndarray-pack-1.2.1.tgz", + "integrity": "sha1-jK6+qqJNXs9w/4YCBjeXfajuWFo=", + "requires": { + "cwise-compiler": "1.1.3", + "ndarray": "1.0.18" + } + }, + "nextgen-events": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/nextgen-events/-/nextgen-events-0.10.2.tgz", + "integrity": "sha512-P6efDoVOOJjVLOhwINq+aqhC2B3a9IxojbWMn9fTv2coDiyRaaGLSgWsm84wQHlQeuqVgqiLEE+xiHXf3EVN6w==" + }, + "node-bitmap": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/node-bitmap/-/node-bitmap-0.0.1.tgz", + "integrity": "sha1-GA6scAPgxwdhjvMTaPYvhLKmkJE=" + }, + "node-emoji": { + "version": "git+https://github.com/laurent22/node-emoji.git#9fa01eac463e94dde1316ef8c53089eeef4973b5", + "requires": { + "lodash.toarray": "4.4.0" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, + "node-persist": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-2.1.0.tgz", + "integrity": "sha1-5lK784haBNrWo1PXQXYXfIORRwc=", + "requires": { + "is-absolute": "0.2.6", + "mkdirp": "0.5.1", + "q": "1.1.2" + } + }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "requires": { + "config-chain": "1.1.11", + "pify": "3.0.0" + } + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "omggif": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.8.tgz", + "integrity": "sha1-F483sqsLPXtG7ToORr0HkLWNNTA=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "parse-data-uri": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/parse-data-uri/-/parse-data-uri-0.2.0.tgz", + "integrity": "sha1-vwTYUd1ch7CrI45dAazklLYEtMk=", + "requires": { + "data-uri-to-buffer": "0.0.3" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pngjs": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-2.3.1.tgz", + "integrity": "sha1-EdHhK5y2TWPjDBQ6Mw9MH1Z9qF8=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "2.0.6" + } + }, + "proper-lockfile": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-2.0.1.tgz", + "integrity": "sha1-FZ+wYZPTIAP0s2kd0uwaY0qoDR0=", + "requires": { + "graceful-fs": "4.1.11", + "retry": "0.10.1" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "q": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/q/-/q-1.1.2.tgz", + "integrity": "sha1-Y1fikSBnAdmfGXq4TlforRlvKok=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "requires": { + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "redux": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", + "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "requires": { + "lodash": "4.17.4", + "lodash-es": "4.17.4", + "loose-envify": "1.3.1", + "symbol-observable": "1.0.4" + } + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "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" + } + }, + "retry": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.10.1.tgz", + "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "server-destroy": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", + "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=" + }, + "sharp": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.18.4.tgz", + "integrity": "sha1-/jKcDwaJbCiqJDdt8f/wKuV/LTQ=", + "requires": { + "caw": "2.0.1", + "color": "2.0.1", + "detect-libc": "0.2.0", + "nan": "2.8.0", + "semver": "5.4.1", + "simple-get": "2.7.0", + "tar": "3.2.1" + } + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.7.0.tgz", + "integrity": "sha512-RkE9rGPHcxYZ/baYmgJtOSM63vH0Vyq+ma5TijBcLla41SWlh8t6XYIGMR/oeZcmr+/G8k+zrClkkVrtnQ0esg==", + "requires": { + "decompress-response": "3.3.0", + "once": "1.4.0", + "simple-concat": "1.0.0" + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "0.3.1" + } + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "requires": { + "is-fullwidth-code-point": "2.0.0" + } + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "requires": { + "hoek": "4.2.0" + } + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "sqlite3": { + "version": "3.1.13", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-3.1.13.tgz", + "integrity": "sha512-JxXKPJnkZ6NuHRojq+g2WXWBt3M1G9sjZaYiHEWSTGijDM3cwju/0T2XbWqMXFmPqDgw+iB7zKQvnns4bvzXlw==", + "requires": { + "nan": "2.7.0", + "node-pre-gyp": "0.6.38" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.8", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.4", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "mime-db": { + "version": "1.30.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.17", + "bundled": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + }, + "node-pre-gyp": { + "version": "0.6.38", + "bundled": true, + "requires": { + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.2", + "semver": "5.4.1", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "readable-stream": { + "version": "2.3.3", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "0.6.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.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "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": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "semver": { + "version": "5.4.1", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.1", + "bundled": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "bundled": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "requires": { + "debug": "2.6.9", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.3", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.3", + "bundled": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "uuid": { + "version": "3.1.0", + "bundled": true + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + } + } + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-kit": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/string-kit/-/string-kit-0.6.3.tgz", + "integrity": "sha512-G2T92klsuE+S9mqdKQyWurFweNQV5X+FRzSKTqYHRdaVUN/4dL6urbYJJ+xb9ep/4XWm+4RNT8j3acncNhFRBg==", + "requires": { + "xregexp": "3.2.0" + } + }, + "string-padding": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-padding/-/string-padding-1.0.2.tgz", + "integrity": "sha1-OqrYVbPpc1xeQS3+chmMz5nH9I4=" + }, + "string-to-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-1.1.0.tgz", + "integrity": "sha1-rPLJ6tHEGOFIUJoS0su0afMzohg=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "requires": { + "has-flag": "2.0.0" + } + }, + "symbol-observable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", + "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" + }, + "tar": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-3.2.1.tgz", + "integrity": "sha512-ZSzds1E0IqutvMU8HxjMaU8eB7urw2fGwTq88ukDOVuUIh0656l7/P7LiVPxhO5kS4flcRJQk8USG+cghQbTUQ==", + "requires": { + "chownr": "1.0.1", + "minipass": "2.2.1", + "minizlib": "1.0.4", + "mkdirp": "0.5.1", + "yallist": "3.0.2" + } + }, + "tcp-port-used": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-0.1.2.tgz", + "integrity": "sha1-lFDodoyDtBb9TRpqlEnuzL9JbCk=", + "requires": { + "debug": "0.7.4", + "is2": "0.0.9", + "q": "0.9.7" + }, + "dependencies": { + "debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=" + }, + "q": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "integrity": "sha1-TeLmyzspCIyeTLwDv51C+5bOL3U=" + } + } + }, + "terminal-kit": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/terminal-kit/-/terminal-kit-1.14.3.tgz", + "integrity": "sha512-ZHtuElnBhK0IXOYNvQ7eYgaArwEoOv7saQc4Q0Z9p02JeC7iajC20/odV77BKB3jw/Qthvf9mpASf8gNDYv7xQ==", + "requires": { + "async-kit": "2.2.3", + "get-pixels": "3.3.0", + "ndarray": "1.0.18", + "nextgen-events": "0.10.2", + "string-kit": "0.6.3", + "tree-kit": "0.5.26" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "tkwidgets": { + "version": "0.5.20", + "resolved": "https://registry.npmjs.org/tkwidgets/-/tkwidgets-0.5.20.tgz", + "integrity": "sha512-9wGsMrrFJvE/6TKUc0dEFFhwxvZLeNsYOxnpy1JCwyk/hYCEF70nuvk7VvJeG4TPaQBaGKPj6c7pCgdREvz4Jw==", + "requires": { + "chalk": "2.3.0", + "emphasize": "1.5.0", + "node-emoji": "git+https://github.com/laurent22/node-emoji.git#9fa01eac463e94dde1316ef8c53089eeef4973b5", + "slice-ansi": "1.0.0", + "string-width": "2.1.1", + "terminal-kit": "1.14.3", + "wrap-ansi": "3.0.1" + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "tree-kit": { + "version": "0.5.26", + "resolved": "https://registry.npmjs.org/tree-kit/-/tree-kit-0.5.26.tgz", + "integrity": "sha1-hXHIb6JNHbdU5bDLOn4J9B50qN8=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=" + }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" + }, + "wrap-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz", + "integrity": "sha1-KIoE2H7aXChuBg3+jxNc6NAH+Lo=", + "requires": { + "string-width": "2.1.1", + "strip-ansi": "4.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xregexp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-3.2.0.tgz", + "integrity": "sha1-yzYBmHv+JpW1hAAMGPHEqMMih44=" + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "requires": { + "camelcase": "4.1.0" + } + } + } +} diff --git a/CliClientDemo/package.json b/CliClientDemo/package.json new file mode 100644 index 000000000..136a2687e --- /dev/null +++ b/CliClientDemo/package.json @@ -0,0 +1,32 @@ +{ + "name": "demo-joplin", + "version": "1.0.8", + "description": "Demo for Joplin CLI", + "bin": { + "demo-joplin": "./index.js" + }, + "bugs": { + "url": "https://github.com/laurent22/joplin/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/laurent22/joplin" + }, + "engines": { + "node": ">=8.7.0" + }, + "copyright": { + "title": "Demo for Joplin CLI", + "years": [ + 2016, + 2017 + ], + "owner": "Laurent Cozic" + }, + "dependencies": { + "fs-extra": "^4.0.2", + "joplin": "^0.10.69" + }, + "author": "Laurent Cozic", + "license": "MIT" +} diff --git a/CliClientDemo/publish.sh b/CliClientDemo/publish.sh new file mode 100644 index 000000000..3387f5474 --- /dev/null +++ b/CliClientDemo/publish.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +npm version patch +npm publish \ No newline at end of file diff --git a/ElectronClient/.gitignore b/ElectronClient/.gitignore new file mode 100644 index 000000000..0eccafe32 --- /dev/null +++ b/ElectronClient/.gitignore @@ -0,0 +1,5 @@ +app/node_modules/ +dist/ +app/lib/ +app/gui/*.min.js +.DS_Store \ No newline at end of file diff --git a/ElectronClient/app/ElectronAppWrapper.js b/ElectronClient/app/ElectronAppWrapper.js new file mode 100644 index 000000000..20f8393a9 --- /dev/null +++ b/ElectronClient/app/ElectronAppWrapper.js @@ -0,0 +1,110 @@ +const { _ } = require('lib/locale.js'); +const { BrowserWindow } = require('electron'); +const url = require('url') +const path = require('path') +const urlUtils = require('lib/urlUtils.js'); + +class ElectronAppWrapper { + + constructor(electronApp, env) { + this.electronApp_ = electronApp; + this.env_ = env; + this.win_ = null; + this.willQuitApp_ = false; + } + + electronApp() { + return this.electronApp_; + } + + setLogger(v) { + this.logger_ = v; + } + + logger() { + return this.logger_; + } + + window() { + return this.win_; + } + + createWindow() { + const windowStateKeeper = require('electron-window-state'); + + // Load the previous state with fallback to defaults + const windowState = windowStateKeeper({ + defaultWidth: 800, + defaultHeight: 600, + }); + + this.win_ = new BrowserWindow({ + 'x': windowState.x, + 'y': windowState.y, + 'width': windowState.width, + 'height': windowState.height + }) + + this.win_.loadURL(url.format({ + pathname: path.join(__dirname, 'index.html'), + protocol: 'file:', + slashes: true + })) + + //if (this.env_ === 'dev') this.win_.webContents.openDevTools(); + + this.win_.on('close', (event) => { + if (this.willQuitApp_ || process.platform !== 'darwin') { + this.win_ = null; + } else { + event.preventDefault(); + this.win_.hide(); + } + }) + + // Let us register listeners on the window, so we can update the state + // automatically (the listeners will be removed when the window is closed) + // and restore the maximized or full screen state + windowState.manage(this.win_); + } + + async waitForElectronAppReady() { + if (this.electronApp().isReady()) return Promise.resolve(); + + return new Promise((resolve, reject) => { + const iid = setInterval(() => { + if (this.electronApp().isReady()) { + clearInterval(iid); + resolve(); + } + }, 10); + }); + } + + async exit() { + this.electronApp_.quit(); + } + + async start() { + // Since we are doing other async things before creating the window, we might miss + // the "ready" event. So we use the function below to make sure that the app is ready. + await this.waitForElectronAppReady(); + + this.createWindow(); + + this.electronApp_.on('before-quit', () => { + this.willQuitApp_ = true; + }) + + this.electronApp_.on('window-all-closed', () => { + this.electronApp_.quit(); + }) + + this.electronApp_.on('activate', () => { + this.win_.show(); + }) + } + +} + +module.exports = { ElectronAppWrapper }; \ No newline at end of file diff --git a/ElectronClient/app/app.js b/ElectronClient/app/app.js new file mode 100644 index 000000000..d2bbc1523 --- /dev/null +++ b/ElectronClient/app/app.js @@ -0,0 +1,361 @@ +require('app-module-path').addPath(__dirname); + +const { BaseApplication } = require('lib/BaseApplication'); +const { FoldersScreenUtils } = require('lib/folders-screen-utils.js'); +const { Setting } = require('lib/models/setting.js'); +const { shim } = require('lib/shim.js'); +const { BaseModel } = require('lib/base-model.js'); +const { _, setLocale } = require('lib/locale.js'); +const os = require('os'); +const fs = require('fs-extra'); +const { Tag } = require('lib/models/tag.js'); +const { reg } = require('lib/registry.js'); +const { sprintf } = require('sprintf-js'); +const { JoplinDatabase } = require('lib/joplin-database.js'); +const { DatabaseDriverNode } = require('lib/database-driver-node.js'); +const { ElectronAppWrapper } = require('./ElectronAppWrapper'); +const { defaultState } = require('lib/reducer.js'); + +const { bridge } = require('electron').remote.require('./bridge'); +const Menu = bridge().Menu; +const MenuItem = bridge().MenuItem; + +const appDefaultState = Object.assign({}, defaultState, { + route: { + type: 'NAV_GO', + routeName: 'Main', + props: {}, + }, + navHistory: [], + fileToImport: null, + windowCommand: null, + noteVisiblePanes: ['editor', 'viewer'], + windowContentSize: bridge().windowContentSize(), +}); + +class Application extends BaseApplication { + + constructor() { + super(); + this.lastMenuScreen_ = null; + } + + hasGui() { + return true; + } + + reducer(state = appDefaultState, action) { + let newState = state; + + try { + switch (action.type) { + + case 'NAV_BACK': + case 'NAV_GO': + + const goingBack = action.type === 'NAV_BACK'; + + if (goingBack && !state.navHistory.length) break; + + const currentRoute = state.route; + + newState = Object.assign({}, state); + let newNavHistory = state.navHistory.slice(); + + if (goingBack) { + let newAction = null; + while (newNavHistory.length) { + newAction = newNavHistory.pop(); + if (newAction.routeName !== state.route.routeName) break; + } + + if (!newAction) break; + + action = newAction; + } + + if (!goingBack) newNavHistory.push(currentRoute); + newState.navHistory = newNavHistory + newState.route = action; + break; + + case 'WINDOW_CONTENT_SIZE_SET': + + newState = Object.assign({}, state); + newState.windowContentSize = action.size; + break; + + case 'WINDOW_COMMAND': + + newState = Object.assign({}, state); + let command = Object.assign({}, action); + delete command.type; + newState.windowCommand = command; + break; + + case 'NOTE_VISIBLE_PANES_TOGGLE': + + let panes = state.noteVisiblePanes.slice(); + if (panes.length === 2) { + panes = ['editor']; + } else if (panes.indexOf('editor') >= 0) { + panes = ['viewer']; + } else if (panes.indexOf('viewer') >= 0) { + panes = ['editor', 'viewer']; + } else { + panes = ['editor', 'viewer']; + } + + newState = Object.assign({}, state); + newState.noteVisiblePanes = panes; + break; + + case 'NOTE_VISIBLE_PANES_SET': + + newState = Object.assign({}, state); + newState.noteVisiblePanes = action.panes; + break; + + } + } catch (error) { + error.message = 'In reducer: ' + error.message + ' Action: ' + JSON.stringify(action); + throw error; + } + + return super.reducer(newState, action); + } + + async generalMiddleware(store, next, action) { + if (action.type == 'SETTING_UPDATE_ONE' && action.key == 'locale' || action.type == 'SETTING_UPDATE_ALL') { + setLocale(Setting.value('locale')); + this.refreshMenu(); + } + + if (['NOTE_UPDATE_ONE', 'NOTE_DELETE', 'FOLDER_UPDATE_ONE', 'FOLDER_DELETE'].indexOf(action.type) >= 0) { + if (!await reg.syncTarget().syncStarted()) reg.scheduleSync(); + } + + const result = await super.generalMiddleware(store, next, action); + const newState = store.getState(); + + if (action.type === 'NAV_GO' || action.type === 'NAV_BACK') { + app().updateMenu(newState.route.routeName); + } + + if (['NOTE_VISIBLE_PANES_TOGGLE', 'NOTE_VISIBLE_PANES_SET'].indexOf(action.type) >= 0) { + Setting.setValue('noteVisiblePanes', newState.noteVisiblePanes); + } + + return result; + } + + refreshMenu() { + const screen = this.lastMenuScreen_; + this.lastMenuScreen_ = null; + this.updateMenu(screen); + } + + updateMenu(screen) { + if (this.lastMenuScreen_ === screen) return; + + const template = [ + { + label: _('File'), + submenu: [{ + label: _('New note'), + accelerator: 'CommandOrControl+N', + screens: ['Main'], + click: () => { + this.dispatch({ + type: 'WINDOW_COMMAND', + name: 'newNote', + }); + } + }, { + label: _('New to-do'), + accelerator: 'CommandOrControl+T', + screens: ['Main'], + click: () => { + this.dispatch({ + type: 'WINDOW_COMMAND', + name: 'newTodo', + }); + } + }, { + label: _('New notebook'), + screens: ['Main'], + click: () => { + this.dispatch({ + type: 'WINDOW_COMMAND', + name: 'newNotebook', + }); + } + }, { + type: 'separator', + }, { + label: _('Import Evernote notes'), + click: () => { + const filePaths = bridge().showOpenDialog({ + properties: ['openFile', 'createDirectory'], + filters: [ + { name: _('Evernote Export Files'), extensions: ['enex'] }, + ] + }); + if (!filePaths || !filePaths.length) return; + + this.dispatch({ + type: 'NAV_GO', + routeName: 'Import', + props: { + filePath: filePaths[0], + }, + }); + } + }, { + type: 'separator', + }, { + label: _('Quit'), + accelerator: 'CommandOrControl+Q', + click: () => { bridge().electronApp().exit() } + }] + }, { + label: _('Edit'), + submenu: [{ + label: _('Copy'), + screens: ['Main'], + role: 'copy', + accelerator: 'CommandOrControl+C', + }, { + label: _('Cut'), + screens: ['Main'], + role: 'copy', + accelerator: 'CommandOrControl+X', + }, { + label: _('Paste'), + screens: ['Main'], + role: 'copy', + accelerator: 'CommandOrControl+V', + }, { + type: 'separator', + }, { + label: _('Search in all the notes'), + screens: ['Main'], + accelerator: 'F6', + click: () => { + this.dispatch({ + type: 'WINDOW_COMMAND', + name: 'search', + }); + }, + }] + }, { + label: _('Tools'), + submenu: [{ + label: _('Options'), + click: () => { + this.dispatch({ + type: 'NAV_GO', + routeName: 'Config', + }); + } + }] + }, { + label: _('Help'), + submenu: [{ + label: _('Website and documentation'), + accelerator: 'F1', + click () { bridge().openExternal('http://joplin.cozic.net') } + }, { + label: _('About Joplin'), + click: () => { + const p = require('./package.json'); + let message = [ + p.description, + '', + 'Copyright © 2016-2017 Laurent Cozic', + _('%s %s (%s, %s)', p.name, p.version, Setting.value('env'), process.platform), + ]; + bridge().showMessageBox({ + message: message.join('\n'), + }); + } + }] + }, + ]; + + function removeUnwantedItems(template, screen) { + let output = []; + for (let i = 0; i < template.length; i++) { + const t = Object.assign({}, template[i]); + if (t.screens && t.screens.indexOf(screen) < 0) continue; + if (t.submenu) t.submenu = removeUnwantedItems(t.submenu, screen); + output.push(t); + } + return output; + } + + let screenTemplate = removeUnwantedItems(template, screen); + + const menu = Menu.buildFromTemplate(screenTemplate); + Menu.setApplicationMenu(menu); + + this.lastMenuScreen_ = screen; + } + + async start(argv) { + argv = await super.start(argv); + + if (Setting.value('openDevTools')) { + bridge().window().webContents.openDevTools(); + } + + this.updateMenu('Main'); + + this.initRedux(); + + // Since the settings need to be loaded before the store is created, it will never + // receive the SETTING_UPDATE_ALL even, which mean state.settings will not be + // initialised. So we manually call dispatchUpdateAll() to force an update. + Setting.dispatchUpdateAll(); + + await FoldersScreenUtils.refreshFolders(); + + const tags = await Tag.allWithNotes(); + + this.dispatch({ + type: 'TAG_UPDATE_ALL', + tags: tags, + }); + + this.store().dispatch({ + type: 'FOLDER_SELECT', + id: Setting.value('activeFolderId'), + }); + + // Note: Auto-update currently doesn't work in Linux: it downloads the update + // but then doesn't install it on exit. + if (shim.isWindows() || shim.isMac()) { + const runAutoUpdateCheck = function() { + if (Setting.value('autoUpdateEnabled')) { + bridge().checkForUpdatesAndNotify(Setting.value('profileDir') + '/log-autoupdater.txt'); + } + } + + setTimeout(() => { runAutoUpdateCheck() }, 5000); + // For those who leave the app always open + setInterval(() => { runAutoUpdateCheck() }, 2 * 60 * 60 * 1000); + } + + reg.scheduleSync(); + } + +} + +let application_ = null; + +function app() { + if (!application_) application_ = new Application(); + return application_; +} + +module.exports = { app }; \ No newline at end of file diff --git a/ElectronClient/app/bridge.js b/ElectronClient/app/bridge.js new file mode 100644 index 000000000..e1294a184 --- /dev/null +++ b/ElectronClient/app/bridge.js @@ -0,0 +1,114 @@ +const { _ } = require('lib/locale.js'); +const { Logger } = require('lib/logger.js'); + +class Bridge { + + constructor(electronWrapper) { + this.electronWrapper_ = electronWrapper; + this.autoUpdateLogger_ = null; + } + + electronApp() { + return this.electronWrapper_; + } + + processArgv() { + return process.argv; + } + + window() { + return this.electronWrapper_.window(); + } + + windowContentSize() { + if (!this.window()) return { width: 0, height: 0 }; + const s = this.window().getContentSize(); + return { width: s[0], height: s[1] }; + } + + windowSize() { + if (!this.window()) return { width: 0, height: 0 }; + const s = this.window().getSize(); + return { width: s[0], height: s[1] }; + } + + windowSetSize(width, height) { + if (!this.window()) return; + return this.window().setSize(width, height); + } + + showOpenDialog(options) { + const {dialog} = require('electron'); + return dialog.showOpenDialog(options); + } + + showMessageBox(options) { + const {dialog} = require('electron'); + return dialog.showMessageBox(options); + } + + showErrorMessageBox(message) { + return this.showMessageBox({ + type: 'error', + message: message, + }); + } + + showConfirmMessageBox(message) { + const result = this.showMessageBox({ + type: 'question', + message: message, + buttons: [_('OK'), _('Cancel')], + }); + return result === 0; + } + + get Menu() { + return require('electron').Menu; + } + + get MenuItem() { + return require('electron').MenuItem; + } + + openExternal(url) { + return require('electron').shell.openExternal(url) + } + + openItem(fullPath) { + return require('electron').shell.openItem(fullPath) + } + + async checkForUpdatesAndNotify(logFilePath) { + if (!this.autoUpdater_) { + this.autoUpdateLogger_ = new Logger(); + this.autoUpdateLogger_.addTarget('file', { path: logFilePath }); + this.autoUpdateLogger_.setLevel(Logger.LEVEL_DEBUG); + this.autoUpdateLogger_.info('checkForUpdatesAndNotify: Intializing...'); + this.autoUpdater_ = require("electron-updater").autoUpdater; + this.autoUpdater_.logger = this.autoUpdateLogger_; + } + + try { + await this.autoUpdater_.checkForUpdatesAndNotify(); + } catch (error) { + this.autoUpdateLogger_.error(error); + } + } + +} + +let bridge_ = null; + +function initBridge(wrapper) { + if (bridge_) throw new Error('Bridge already initialized'); + bridge_ = new Bridge(wrapper); + return bridge_; +} + +function bridge() { + if (!bridge_) throw new Error('Bridge not initialized'); + return bridge_; +} + +module.exports = { bridge, initBridge } \ No newline at end of file diff --git a/ElectronClient/app/build/icons/1024x1024.png b/ElectronClient/app/build/icons/1024x1024.png new file mode 100644 index 000000000..fef719ed7 Binary files /dev/null and b/ElectronClient/app/build/icons/1024x1024.png differ diff --git a/ElectronClient/app/build/icons/128x128.png b/ElectronClient/app/build/icons/128x128.png new file mode 100644 index 000000000..2e25758b6 Binary files /dev/null and b/ElectronClient/app/build/icons/128x128.png differ diff --git a/ElectronClient/app/build/icons/144x144.png b/ElectronClient/app/build/icons/144x144.png new file mode 100644 index 000000000..252c16948 Binary files /dev/null and b/ElectronClient/app/build/icons/144x144.png differ diff --git a/ElectronClient/app/build/icons/16x16.png b/ElectronClient/app/build/icons/16x16.png new file mode 100644 index 000000000..9a4198a76 Binary files /dev/null and b/ElectronClient/app/build/icons/16x16.png differ diff --git a/ElectronClient/app/build/icons/24x24.png b/ElectronClient/app/build/icons/24x24.png new file mode 100644 index 000000000..35525f910 Binary files /dev/null and b/ElectronClient/app/build/icons/24x24.png differ diff --git a/ElectronClient/app/build/icons/256x256.png b/ElectronClient/app/build/icons/256x256.png new file mode 100644 index 000000000..a5e8d9747 Binary files /dev/null and b/ElectronClient/app/build/icons/256x256.png differ diff --git a/ElectronClient/app/build/icons/32x32.png b/ElectronClient/app/build/icons/32x32.png new file mode 100644 index 000000000..679aa6e67 Binary files /dev/null and b/ElectronClient/app/build/icons/32x32.png differ diff --git a/ElectronClient/app/build/icons/48x48.png b/ElectronClient/app/build/icons/48x48.png new file mode 100644 index 000000000..f5ab076ae Binary files /dev/null and b/ElectronClient/app/build/icons/48x48.png differ diff --git a/ElectronClient/app/build/icons/512x512.png b/ElectronClient/app/build/icons/512x512.png new file mode 100644 index 000000000..ef8624663 Binary files /dev/null and b/ElectronClient/app/build/icons/512x512.png differ diff --git a/ElectronClient/app/build/icons/72x72.png b/ElectronClient/app/build/icons/72x72.png new file mode 100644 index 000000000..dbac3fae8 Binary files /dev/null and b/ElectronClient/app/build/icons/72x72.png differ diff --git a/ElectronClient/app/build/icons/96x96.png b/ElectronClient/app/build/icons/96x96.png new file mode 100644 index 000000000..cb1faeb10 Binary files /dev/null and b/ElectronClient/app/build/icons/96x96.png differ diff --git a/ElectronClient/app/compile-jsx.js b/ElectronClient/app/compile-jsx.js new file mode 100644 index 000000000..c84e490b0 --- /dev/null +++ b/ElectronClient/app/compile-jsx.js @@ -0,0 +1,40 @@ +const fs = require('fs-extra'); +const spawnSync = require('child_process').spawnSync; + +const babelPath = __dirname + '/node_modules/.bin/babel' + (process.platform === 'win32' ? '.cmd' : ''); +const guiPath = __dirname + '/gui'; + +function fileIsNewerThan(path1, path2) { + if (!fs.existsSync(path2)) return true; + + const stat1 = fs.statSync(path1); + const stat2 = fs.statSync(path2); + + return stat1.mtime > stat2.mtime; +} + +fs.readdirSync(guiPath).forEach((filename) => { + const jsxPath = guiPath + '/' + filename; + const p = jsxPath.split('.'); + if (p.length <= 1) return; + const ext = p[p.length - 1]; + if (ext !== 'jsx') return; + p.pop(); + + const basePath = p.join('/'); + + const jsPath = basePath + '.min.js'; + + if (fileIsNewerThan(jsxPath, jsPath)) { + console.info('Compiling ' + jsxPath + '...'); + const result = spawnSync(babelPath, ['--presets', 'react', '--out-file',jsPath, jsxPath]); + if (result.status !== 0) { + const msg = []; + if (result.stdout) msg.push(result.stdout.toString()); + if (result.stderr) msg.push(result.stderr.toString()); + console.error(msg.join('\n')); + if (result.error) console.error(result.error); + process.exit(result.status); + } + } +}); diff --git a/ElectronClient/app/css/font-awesome.min.css b/ElectronClient/app/css/font-awesome.min.css new file mode 100644 index 000000000..540440ce8 --- /dev/null +++ b/ElectronClient/app/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.7.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.7.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.7.0') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.7.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.7.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.7.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook-f:before,.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-feed:before,.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before,.fa-gratipay:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper-pp:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-resistance:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-y-combinator-square:before,.fa-yc-square:before,.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}.fa-buysellads:before{content:"\f20d"}.fa-connectdevelop:before{content:"\f20e"}.fa-dashcube:before{content:"\f210"}.fa-forumbee:before{content:"\f211"}.fa-leanpub:before{content:"\f212"}.fa-sellsy:before{content:"\f213"}.fa-shirtsinbulk:before{content:"\f214"}.fa-simplybuilt:before{content:"\f215"}.fa-skyatlas:before{content:"\f216"}.fa-cart-plus:before{content:"\f217"}.fa-cart-arrow-down:before{content:"\f218"}.fa-diamond:before{content:"\f219"}.fa-ship:before{content:"\f21a"}.fa-user-secret:before{content:"\f21b"}.fa-motorcycle:before{content:"\f21c"}.fa-street-view:before{content:"\f21d"}.fa-heartbeat:before{content:"\f21e"}.fa-venus:before{content:"\f221"}.fa-mars:before{content:"\f222"}.fa-mercury:before{content:"\f223"}.fa-intersex:before,.fa-transgender:before{content:"\f224"}.fa-transgender-alt:before{content:"\f225"}.fa-venus-double:before{content:"\f226"}.fa-mars-double:before{content:"\f227"}.fa-venus-mars:before{content:"\f228"}.fa-mars-stroke:before{content:"\f229"}.fa-mars-stroke-v:before{content:"\f22a"}.fa-mars-stroke-h:before{content:"\f22b"}.fa-neuter:before{content:"\f22c"}.fa-genderless:before{content:"\f22d"}.fa-facebook-official:before{content:"\f230"}.fa-pinterest-p:before{content:"\f231"}.fa-whatsapp:before{content:"\f232"}.fa-server:before{content:"\f233"}.fa-user-plus:before{content:"\f234"}.fa-user-times:before{content:"\f235"}.fa-hotel:before,.fa-bed:before{content:"\f236"}.fa-viacoin:before{content:"\f237"}.fa-train:before{content:"\f238"}.fa-subway:before{content:"\f239"}.fa-medium:before{content:"\f23a"}.fa-yc:before,.fa-y-combinator:before{content:"\f23b"}.fa-optin-monster:before{content:"\f23c"}.fa-opencart:before{content:"\f23d"}.fa-expeditedssl:before{content:"\f23e"}.fa-battery-4:before,.fa-battery:before,.fa-battery-full:before{content:"\f240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\f241"}.fa-battery-2:before,.fa-battery-half:before{content:"\f242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\f243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\f244"}.fa-mouse-pointer:before{content:"\f245"}.fa-i-cursor:before{content:"\f246"}.fa-object-group:before{content:"\f247"}.fa-object-ungroup:before{content:"\f248"}.fa-sticky-note:before{content:"\f249"}.fa-sticky-note-o:before{content:"\f24a"}.fa-cc-jcb:before{content:"\f24b"}.fa-cc-diners-club:before{content:"\f24c"}.fa-clone:before{content:"\f24d"}.fa-balance-scale:before{content:"\f24e"}.fa-hourglass-o:before{content:"\f250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\f251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\f252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\f253"}.fa-hourglass:before{content:"\f254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\f255"}.fa-hand-stop-o:before,.fa-hand-paper-o:before{content:"\f256"}.fa-hand-scissors-o:before{content:"\f257"}.fa-hand-lizard-o:before{content:"\f258"}.fa-hand-spock-o:before{content:"\f259"}.fa-hand-pointer-o:before{content:"\f25a"}.fa-hand-peace-o:before{content:"\f25b"}.fa-trademark:before{content:"\f25c"}.fa-registered:before{content:"\f25d"}.fa-creative-commons:before{content:"\f25e"}.fa-gg:before{content:"\f260"}.fa-gg-circle:before{content:"\f261"}.fa-tripadvisor:before{content:"\f262"}.fa-odnoklassniki:before{content:"\f263"}.fa-odnoklassniki-square:before{content:"\f264"}.fa-get-pocket:before{content:"\f265"}.fa-wikipedia-w:before{content:"\f266"}.fa-safari:before{content:"\f267"}.fa-chrome:before{content:"\f268"}.fa-firefox:before{content:"\f269"}.fa-opera:before{content:"\f26a"}.fa-internet-explorer:before{content:"\f26b"}.fa-tv:before,.fa-television:before{content:"\f26c"}.fa-contao:before{content:"\f26d"}.fa-500px:before{content:"\f26e"}.fa-amazon:before{content:"\f270"}.fa-calendar-plus-o:before{content:"\f271"}.fa-calendar-minus-o:before{content:"\f272"}.fa-calendar-times-o:before{content:"\f273"}.fa-calendar-check-o:before{content:"\f274"}.fa-industry:before{content:"\f275"}.fa-map-pin:before{content:"\f276"}.fa-map-signs:before{content:"\f277"}.fa-map-o:before{content:"\f278"}.fa-map:before{content:"\f279"}.fa-commenting:before{content:"\f27a"}.fa-commenting-o:before{content:"\f27b"}.fa-houzz:before{content:"\f27c"}.fa-vimeo:before{content:"\f27d"}.fa-black-tie:before{content:"\f27e"}.fa-fonticons:before{content:"\f280"}.fa-reddit-alien:before{content:"\f281"}.fa-edge:before{content:"\f282"}.fa-credit-card-alt:before{content:"\f283"}.fa-codiepie:before{content:"\f284"}.fa-modx:before{content:"\f285"}.fa-fort-awesome:before{content:"\f286"}.fa-usb:before{content:"\f287"}.fa-product-hunt:before{content:"\f288"}.fa-mixcloud:before{content:"\f289"}.fa-scribd:before{content:"\f28a"}.fa-pause-circle:before{content:"\f28b"}.fa-pause-circle-o:before{content:"\f28c"}.fa-stop-circle:before{content:"\f28d"}.fa-stop-circle-o:before{content:"\f28e"}.fa-shopping-bag:before{content:"\f290"}.fa-shopping-basket:before{content:"\f291"}.fa-hashtag:before{content:"\f292"}.fa-bluetooth:before{content:"\f293"}.fa-bluetooth-b:before{content:"\f294"}.fa-percent:before{content:"\f295"}.fa-gitlab:before{content:"\f296"}.fa-wpbeginner:before{content:"\f297"}.fa-wpforms:before{content:"\f298"}.fa-envira:before{content:"\f299"}.fa-universal-access:before{content:"\f29a"}.fa-wheelchair-alt:before{content:"\f29b"}.fa-question-circle-o:before{content:"\f29c"}.fa-blind:before{content:"\f29d"}.fa-audio-description:before{content:"\f29e"}.fa-volume-control-phone:before{content:"\f2a0"}.fa-braille:before{content:"\f2a1"}.fa-assistive-listening-systems:before{content:"\f2a2"}.fa-asl-interpreting:before,.fa-american-sign-language-interpreting:before{content:"\f2a3"}.fa-deafness:before,.fa-hard-of-hearing:before,.fa-deaf:before{content:"\f2a4"}.fa-glide:before{content:"\f2a5"}.fa-glide-g:before{content:"\f2a6"}.fa-signing:before,.fa-sign-language:before{content:"\f2a7"}.fa-low-vision:before{content:"\f2a8"}.fa-viadeo:before{content:"\f2a9"}.fa-viadeo-square:before{content:"\f2aa"}.fa-snapchat:before{content:"\f2ab"}.fa-snapchat-ghost:before{content:"\f2ac"}.fa-snapchat-square:before{content:"\f2ad"}.fa-pied-piper:before{content:"\f2ae"}.fa-first-order:before{content:"\f2b0"}.fa-yoast:before{content:"\f2b1"}.fa-themeisle:before{content:"\f2b2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\f2b3"}.fa-fa:before,.fa-font-awesome:before{content:"\f2b4"}.fa-handshake-o:before{content:"\f2b5"}.fa-envelope-open:before{content:"\f2b6"}.fa-envelope-open-o:before{content:"\f2b7"}.fa-linode:before{content:"\f2b8"}.fa-address-book:before{content:"\f2b9"}.fa-address-book-o:before{content:"\f2ba"}.fa-vcard:before,.fa-address-card:before{content:"\f2bb"}.fa-vcard-o:before,.fa-address-card-o:before{content:"\f2bc"}.fa-user-circle:before{content:"\f2bd"}.fa-user-circle-o:before{content:"\f2be"}.fa-user-o:before{content:"\f2c0"}.fa-id-badge:before{content:"\f2c1"}.fa-drivers-license:before,.fa-id-card:before{content:"\f2c2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\f2c3"}.fa-quora:before{content:"\f2c4"}.fa-free-code-camp:before{content:"\f2c5"}.fa-telegram:before{content:"\f2c6"}.fa-thermometer-4:before,.fa-thermometer:before,.fa-thermometer-full:before{content:"\f2c7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\f2c8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\f2c9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\f2ca"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\f2cb"}.fa-shower:before{content:"\f2cc"}.fa-bathtub:before,.fa-s15:before,.fa-bath:before{content:"\f2cd"}.fa-podcast:before{content:"\f2ce"}.fa-window-maximize:before{content:"\f2d0"}.fa-window-minimize:before{content:"\f2d1"}.fa-window-restore:before{content:"\f2d2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\f2d3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\f2d4"}.fa-bandcamp:before{content:"\f2d5"}.fa-grav:before{content:"\f2d6"}.fa-etsy:before{content:"\f2d7"}.fa-imdb:before{content:"\f2d8"}.fa-ravelry:before{content:"\f2d9"}.fa-eercast:before{content:"\f2da"}.fa-microchip:before{content:"\f2db"}.fa-snowflake-o:before{content:"\f2dc"}.fa-superpowers:before{content:"\f2dd"}.fa-wpexplorer:before{content:"\f2de"}.fa-meetup:before{content:"\f2e0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto} diff --git a/ElectronClient/app/fonts/fontawesome-webfont.woff2 b/ElectronClient/app/fonts/fontawesome-webfont.woff2 new file mode 100644 index 000000000..4d13fc604 Binary files /dev/null and b/ElectronClient/app/fonts/fontawesome-webfont.woff2 differ diff --git a/ElectronClient/app/gui/ConfigScreen.jsx b/ElectronClient/app/gui/ConfigScreen.jsx new file mode 100644 index 000000000..69736360c --- /dev/null +++ b/ElectronClient/app/gui/ConfigScreen.jsx @@ -0,0 +1,114 @@ +const React = require('react'); +const { connect } = require('react-redux'); +const { reg } = require('lib/registry.js'); +const { Setting } = require('lib/models/setting.js'); +const { bridge } = require('electron').remote.require('./bridge'); +const { Header } = require('./Header.min.js'); +const { themeStyle } = require('../theme.js'); +const { _ } = require('lib/locale.js'); + +class ConfigScreenComponent extends React.Component { + + settingToComponent(key, value) { + const theme = themeStyle(this.props.theme); + + let output = null; + + const rowStyle = { + marginBottom: 10, + }; + + const labelStyle = Object.assign({}, theme.textStyle, { + display: 'inline-block', + marginRight: 10, + }); + + const controlStyle = { + display: 'inline-block', + }; + + const updateSettingValue = (key, value) => { + Setting.setValue(key, value); + } + + const md = Setting.settingMetadata(key); + + if (md.isEnum) { + let items = []; + const settingOptions = md.options(); + for (let k in settingOptions) { + if (!settingOptions.hasOwnProperty(k)) continue; + items.push(<option value={k.toString()} key={k}>{settingOptions[k]}</option>); + } + + return ( + <div key={key} style={rowStyle}> + <div style={labelStyle}><label>{md.label()}</label></div> + <select value={value} style={controlStyle} onChange={(event) => { updateSettingValue(key, event.target.value) }}> + {items} + </select> + </div> + ); + } else if (md.type === Setting.TYPE_BOOL) { + return ( + <div key={key} style={rowStyle}> + <div style={controlStyle}> + <label><input type="checkbox" defaultChecked={!!value} onChange={(event) => { updateSettingValue(key, !!event.target.checked) }}/><span style={labelStyle}> {md.label()}</span></label> + </div> + </div> + ); + } + + return output; + } + + render() { + const theme = themeStyle(this.props.theme); + const style = this.props.style; + const settings = this.props.settings; + + const headerStyle = { + width: style.width, + }; + + const containerStyle = { + padding: 10, + }; + + let settingComps = []; + let keys = Setting.keys(true, 'desktop'); + for (let i = 0; i < keys.length; i++) { + const key = keys[i]; + if (key === 'sync.target') continue; + if (!(key in settings)) { + console.warn('Missing setting: ' + key); + continue; + } + const comp = this.settingToComponent(key, settings[key]); + if (!comp) continue; + settingComps.push(comp); + } + + return ( + <div style={style}> + <Header style={headerStyle} /> + <div style={containerStyle}> + { settingComps } + </div> + </div> + ); + } + +} + +const mapStateToProps = (state) => { + return { + theme: state.settings.theme, + settings: state.settings, + locale: state.settings.locale, + }; +}; + +const ConfigScreen = connect(mapStateToProps)(ConfigScreenComponent); + +module.exports = { ConfigScreen }; \ No newline at end of file diff --git a/ElectronClient/app/gui/Header.jsx b/ElectronClient/app/gui/Header.jsx new file mode 100644 index 000000000..05fd5157f --- /dev/null +++ b/ElectronClient/app/gui/Header.jsx @@ -0,0 +1,95 @@ +const React = require('react'); +const { connect } = require('react-redux'); +const { reg } = require('lib/registry.js'); +const { themeStyle } = require('../theme.js'); +const { _ } = require('lib/locale.js'); + +class HeaderComponent extends React.Component { + + back_click() { + this.props.dispatch({ type: 'NAV_BACK' }); + } + + makeButton(key, style, options) { + let icon = null; + if (options.iconName) { + const iconStyle = { + fontSize: Math.round(style.fontSize * 1.4), + color: style.color + }; + if (options.title) iconStyle.marginRight = 5; + icon = <i style={iconStyle} className={"fa " + options.iconName}></i> + } + + const isEnabled = (!('enabled' in options) || options.enabled); + let classes = ['button']; + if (!isEnabled) classes.push('disabled'); + + const finalStyle = Object.assign({}, style, { + opacity: isEnabled ? 1 : 0.4, + }); + + return <a + className={classes.join(' ')} + style={finalStyle} + key={key} + href="#" + onClick={() => { if (isEnabled) options.onClick() }} + > + {icon}{options.title ? options.title : ''} + </a> + } + + render() { + const style = this.props.style; + const theme = themeStyle(this.props.theme); + const showBackButton = this.props.showBackButton === undefined || this.props.showBackButton === true; + style.height = theme.headerHeight; + style.display = 'flex'; + style.flexDirection = 'row'; + style.borderBottom = '1px solid ' + theme.dividerColor; + style.boxSizing = 'border-box'; + + const buttons = []; + + const buttonStyle = { + height: theme.headerHeight, + display: 'flex', + alignItems: 'center', + paddingLeft: theme.headerButtonHPadding, + paddingRight: theme.headerButtonHPadding, + color: theme.color, + textDecoration: 'none', + fontFamily: theme.fontFamily, + fontSize: theme.fontSize, + boxSizing: 'border-box', + cursor: 'default', + }; + + if (showBackButton) { + buttons.push(this.makeButton('back', buttonStyle, { title: _('Back'), onClick: () => this.back_click(), iconName: 'fa-chevron-left ' })); + } + + if (this.props.buttons) { + for (let i = 0; i < this.props.buttons.length; i++) { + const o = this.props.buttons[i]; + buttons.push(this.makeButton('btn_' + i + '_' + o.title, buttonStyle, o)); + } + } + + return ( + <div className="header" style={style}> + { buttons } + </div> + ); + } + +} + +const mapStateToProps = (state) => { + return { theme: state.settings.theme }; +}; + +const Header = connect(mapStateToProps)(HeaderComponent); + +module.exports = { Header }; \ No newline at end of file diff --git a/ElectronClient/app/gui/IconButton.jsx b/ElectronClient/app/gui/IconButton.jsx new file mode 100644 index 000000000..1671d5a33 --- /dev/null +++ b/ElectronClient/app/gui/IconButton.jsx @@ -0,0 +1,38 @@ +const React = require('react'); +const { connect } = require('react-redux'); +const { themeStyle } = require('../theme.js'); + +class IconButton extends React.Component { + + render() { + const style = this.props.style; + const theme = themeStyle(this.props.theme); + const iconStyle = { + color: theme.color, + fontSize: theme.fontSize * 1.4, + }; + const icon = <i style={iconStyle} className={"fa " + this.props.iconName}></i> + + const rootStyle = Object.assign({ + display: 'flex', + textDecoration: 'none', + padding: 10, + width: theme.buttonMinHeight, + height: theme.buttonMinHeight, + boxSizing: 'border-box', + alignItems: 'center', + justifyContent: 'center', + backgroundColor: theme.backgroundColor, + cursor: 'default', + }, style); + + return ( + <a href="#" style={rootStyle} className="icon-button" onClick={() => { if (this.props.onClick) this.props.onClick() }}> + { icon } + </a> + ); + } + +} + +module.exports = { IconButton }; \ No newline at end of file diff --git a/ElectronClient/app/gui/ImportScreen.jsx b/ElectronClient/app/gui/ImportScreen.jsx new file mode 100644 index 000000000..3c80b1c7d --- /dev/null +++ b/ElectronClient/app/gui/ImportScreen.jsx @@ -0,0 +1,136 @@ +const React = require('react'); +const { connect } = require('react-redux'); +const { reg } = require('lib/registry.js'); +const { Folder } = require('lib/models/folder.js'); +const { bridge } = require('electron').remote.require('./bridge'); +const { Header } = require('./Header.min.js'); +const { themeStyle } = require('../theme.js'); +const { _ } = require('lib/locale.js'); +const { filename, basename } = require('lib/path-utils.js'); +const { importEnex } = require('lib/import-enex'); + +class ImportScreenComponent extends React.Component { + + componentWillMount() { + this.setState({ + doImport: true, + filePath: this.props.filePath, + messages: [], + }); + } + + componentWillReceiveProps(newProps) { + if (newProps.filePath) { + this.setState({ + doImport: true, + filePath: newProps.filePath, + messages: [], + }); + + this.doImport(); + } + } + + componentDidMount() { + if (this.state.filePath && this.state.doImport) { + this.doImport(); + } + } + + addMessage(key, text) { + const messages = this.state.messages.slice(); + let found = false; + + for (let i = 0; i < messages.length; i++) { + if (messages[i].key === key) { + messages[i].text = text; + found = true; + break; + } + } + + if (!found) messages.push({ key: key, text: text }); + + this.setState({ messages: messages }); + } + + async doImport() { + const filePath = this.props.filePath; + const folderTitle = await Folder.findUniqueFolderTitle(filename(filePath)); + const messages = this.state.messages.slice(); + + this.addMessage('start', _('New notebook "%s" will be created and file "%s" will be imported into it', folderTitle, basename(filePath))); + + let lastProgress = ''; + let progressCount = 0; + + const options = { + onProgress: (progressState) => { + let line = []; + line.push(_('Found: %d.', progressState.loaded)); + line.push(_('Created: %d.', progressState.created)); + if (progressState.updated) line.push(_('Updated: %d.', progressState.updated)); + if (progressState.skipped) line.push(_('Skipped: %d.', progressState.skipped)); + if (progressState.resourcesCreated) line.push(_('Resources: %d.', progressState.resourcesCreated)); + if (progressState.notesTagged) line.push(_('Tagged: %d.', progressState.notesTagged)); + lastProgress = line.join(' '); + this.addMessage('progress', lastProgress); + }, + onError: (error) => { + const messages = this.state.messages.slice(); + let s = error.trace ? error.trace : error.toString(); + messages.push({ key: 'error_' + (progressCount++), text: s }); + this.addMessage('error_' + (progressCount++), lastProgress); + }, + } + + const folder = await Folder.save({ title: folderTitle }); + + await importEnex(folder.id, filePath, options); + + this.addMessage('done', _('The notes have been imported: %s', lastProgress)); + this.setState({ doImport: false }); + } + + render() { + const theme = themeStyle(this.props.theme); + const style = this.props.style; + const messages = this.state.messages; + + const messagesStyle = { + padding: 10, + fontSize: theme.fontSize, + fontFamily: theme.fontFamily, + backgroundColor: theme.backgroundColor, + }; + + const headerStyle = { + width: style.width, + }; + + const messageComps = []; + for (let i = 0; i < messages.length; i++) { + messageComps.push(<div key={messages[i].key}>{messages[i].text}</div>); + } + + return ( + <div style={{}}> + <Header style={headerStyle} /> + <div style={messagesStyle}> + {messageComps} + </div> + </div> + ); + } + +} + +const mapStateToProps = (state) => { + return { + theme: state.settings.theme, + }; +}; + +const ImportScreen = connect(mapStateToProps)(ImportScreenComponent); + +module.exports = { ImportScreen }; \ No newline at end of file diff --git a/ElectronClient/app/gui/ItemList.jsx b/ElectronClient/app/gui/ItemList.jsx new file mode 100644 index 000000000..ee9e877e1 --- /dev/null +++ b/ElectronClient/app/gui/ItemList.jsx @@ -0,0 +1,74 @@ +const React = require('react'); + +class ItemList extends React.Component { + + constructor() { + super(); + + this.scrollTop_ = 0; + } + + updateStateItemIndexes(props) { + if (typeof props === 'undefined') props = this.props; + + const topItemIndex = Math.floor(this.scrollTop_ / props.itemHeight); + const visibleItemCount = Math.ceil(props.style.height / props.itemHeight); + + let bottomItemIndex = topItemIndex + visibleItemCount; + if (bottomItemIndex >= props.items.length) bottomItemIndex = props.items.length - 1; + + this.setState({ + topItemIndex: topItemIndex, + bottomItemIndex: bottomItemIndex, + }); + } + + componentWillMount() { + this.updateStateItemIndexes(); + } + + componentWillReceiveProps(newProps) { + this.updateStateItemIndexes(newProps); + } + + onScroll(scrollTop) { + this.scrollTop_ = scrollTop; + this.updateStateItemIndexes(); + } + + render() { + const items = this.props.items; + const style = Object.assign({}, this.props.style, { + overflowX: 'hidden', + overflowY: 'auto', + }); + + if (!this.props.itemHeight) throw new Error('itemHeight is required'); + + const blankItem = function(key, height) { + return <div key={key} style={{height:height}}></div> + } + + let itemComps = [blankItem('top', this.state.topItemIndex * this.props.itemHeight)]; + + for (let i = this.state.topItemIndex; i <= this.state.bottomItemIndex; i++) { + const itemComp = this.props.itemRenderer(items[i]); + itemComps.push(itemComp); + } + + itemComps.push(blankItem('bottom', (items.length - this.state.bottomItemIndex - 1) * this.props.itemHeight)); + + let classes = ['item-list']; + if (this.props.className) classes.push(this.props.className); + + const that = this; + + return ( + <div className={classes.join(' ')} style={style} onScroll={ (event) => { this.onScroll(event.target.scrollTop) }}> + { itemComps } + </div> + ); + } +} + +module.exports = { ItemList }; \ No newline at end of file diff --git a/ElectronClient/app/gui/MainScreen.jsx b/ElectronClient/app/gui/MainScreen.jsx new file mode 100644 index 000000000..47564544d --- /dev/null +++ b/ElectronClient/app/gui/MainScreen.jsx @@ -0,0 +1,303 @@ +const React = require('react'); +const { connect } = require('react-redux'); +const { Header } = require('./Header.min.js'); +const { SideBar } = require('./SideBar.min.js'); +const { NoteList } = require('./NoteList.min.js'); +const { NoteText } = require('./NoteText.min.js'); +const { PromptDialog } = require('./PromptDialog.min.js'); +const { Setting } = require('lib/models/setting.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Tag } = require('lib/models/tag.js'); +const { Note } = require('lib/models/note.js'); +const { uuid } = require('lib/uuid.js'); +const { Folder } = require('lib/models/folder.js'); +const { themeStyle } = require('../theme.js'); +const { _ } = require('lib/locale.js'); +const layoutUtils = require('lib/layout-utils.js'); +const { bridge } = require('electron').remote.require('./bridge'); + +class MainScreenComponent extends React.Component { + + componentWillMount() { + this.setState({ + promptOptions: null, + }); + } + + componentWillReceiveProps(newProps) { + if (newProps.windowCommand) { + this.doCommand(newProps.windowCommand); + } + } + + toggleVisiblePanes() { + this.props.dispatch({ + type: 'NOTE_VISIBLE_PANES_TOGGLE', + }); + } + + async doCommand(command) { + if (!command) return; + + const createNewNote = async (title, isTodo) => { + const folderId = Setting.value('activeFolderId'); + if (!folderId) return; + + const note = await Note.save({ + title: title, + parent_id: folderId, + is_todo: isTodo ? 1 : 0, + }); + Note.updateGeolocation(note.id); + + this.props.dispatch({ + type: 'NOTE_SELECT', + id: note.id, + }); + } + + let commandProcessed = true; + + if (command.name === 'newNote') { + if (!this.props.folders.length) { + bridge().showErrorMessageBox(_('Please create a notebook first.')); + return; + } + + this.setState({ + promptOptions: { + label: _('Note title:'), + onClose: async (answer) => { + if (answer) await createNewNote(answer, false); + this.setState({ promptOptions: null }); + } + }, + }); + } else if (command.name === 'newTodo') { + if (!this.props.folders.length) { + bridge().showErrorMessageBox(_('Please create a notebook first')); + return; + } + + this.setState({ + promptOptions: { + label: _('To-do title:'), + onClose: async (answer) => { + if (answer) await createNewNote(answer, true); + this.setState({ promptOptions: null }); + } + }, + }); + } else if (command.name === 'newNotebook') { + this.setState({ + promptOptions: { + label: _('Notebook title:'), + onClose: async (answer) => { + if (answer) { + let folder = null; + try { + folder = await Folder.save({ title: answer }, { userSideValidation: true }); + } catch (error) { + bridge().showErrorMessageBox(error.message); + } + + if (folder) { + this.props.dispatch({ + type: 'FOLDER_SELECT', + id: folder.id, + }); + } + } + + this.setState({ promptOptions: null }); + } + }, + }); + } else if (command.name === 'setTags') { + const tags = await Tag.tagsByNoteId(command.noteId); + const tagTitles = tags.map((a) => { return a.title }); + + this.setState({ + promptOptions: { + label: _('Add or remove tags:'), + description: _('Separate each tag by a comma.'), + value: tagTitles.join(', '), + onClose: async (answer) => { + if (answer !== null) { + const tagTitles = answer.split(',').map((a) => { return a.trim() }); + await Tag.setNoteTagsByTitles(command.noteId, tagTitles); + } + this.setState({ promptOptions: null }); + } + }, + }); + } else if (command.name === 'renameNotebook') { + const folder = await Folder.load(command.id); + if (!folder) return; + + this.setState({ + promptOptions: { + label: _('Rename notebook:'), + value: folder.title, + onClose: async (answer) => { + if (answer !== null) { + try { + await Folder.save({ id: folder.id, title: answer }, { userSideValidation: true }); + } catch (error) { + bridge().showErrorMessageBox(error.message); + } + } + this.setState({ promptOptions: null }); + } + }, + }); + } else if (command.name === 'search') { + this.setState({ + promptOptions: { + label: _('Search:'), + onClose: async (answer) => { + if (answer !== null) { + const searchId = uuid.create(); + + this.props.dispatch({ + type: 'SEARCH_ADD', + search: { + id: searchId, + title: answer, + query_pattern: answer, + query_folder_id: null, + type_: BaseModel.TYPE_SEARCH, + }, + }); + + this.props.dispatch({ + type: 'SEARCH_SELECT', + id: searchId, + }); + } + this.setState({ promptOptions: null }); + } + }, + }); + } else { + commandProcessed = false; + } + + if (commandProcessed) { + this.props.dispatch({ + type: 'WINDOW_COMMAND', + name: null, + }); + } + } + + render() { + const style = this.props.style; + const theme = themeStyle(this.props.theme); + const promptOptions = this.state.promptOptions; + const folders = this.props.folders; + const notes = this.props.notes; + + const headerStyle = { + width: style.width, + }; + + const rowHeight = style.height - theme.headerHeight; + + const sideBarStyle = { + width: Math.floor(layoutUtils.size(style.width * .2, 150, 300)), + height: rowHeight, + display: 'inline-block', + verticalAlign: 'top', + }; + + const noteListStyle = { + width: Math.floor(layoutUtils.size(style.width * .2, 150, 300)), + height: rowHeight, + display: 'inline-block', + verticalAlign: 'top', + }; + + const noteTextStyle = { + width: Math.floor(layoutUtils.size(style.width - sideBarStyle.width - noteListStyle.width, 0)), + height: rowHeight, + display: 'inline-block', + verticalAlign: 'top', + }; + + const promptStyle = { + width: style.width, + height: style.height, + }; + + const headerButtons = []; + + headerButtons.push({ + title: _('New note'), + iconName: 'fa-file-o', + enabled: !!folders.length, + onClick: () => { this.doCommand({ name: 'newNote' }) }, + }); + + headerButtons.push({ + title: _('New to-do'), + iconName: 'fa-check-square-o', + enabled: !!folders.length, + onClick: () => { this.doCommand({ name: 'newTodo' }) }, + }); + + headerButtons.push({ + title: _('New notebook'), + iconName: 'fa-folder-o', + onClick: () => { this.doCommand({ name: 'newNotebook' }) }, + }); + + headerButtons.push({ + title: _('Search'), + iconName: 'fa-search', + onClick: () => { this.doCommand({ name: 'search' }) }, + }); + + headerButtons.push({ + title: _('Layout'), + iconName: 'fa-columns', + enabled: !!notes.length, + onClick: () => { + this.toggleVisiblePanes(); + }, + }); + + return ( + <div style={style}> + <PromptDialog + autocomplete={promptOptions && ('autocomplete' in promptOptions) ? promptOptions.autocomplete : null} + value={promptOptions && promptOptions.value ? promptOptions.value : ''} + theme={this.props.theme} + style={promptStyle} + onClose={(answer) => promptOptions.onClose(answer)} + label={promptOptions ? promptOptions.label : ''} + description={promptOptions ? promptOptions.description : null} + visible={!!this.state.promptOptions} /> + <Header style={headerStyle} showBackButton={false} buttons={headerButtons} /> + <SideBar style={sideBarStyle} /> + <NoteList style={noteListStyle} /> + <NoteText style={noteTextStyle} visiblePanes={this.props.noteVisiblePanes} /> + </div> + ); + } + +} + +const mapStateToProps = (state) => { + return { + theme: state.settings.theme, + windowCommand: state.windowCommand, + noteVisiblePanes: state.noteVisiblePanes, + folders: state.folders, + notes: state.notes, + }; +}; + +const MainScreen = connect(mapStateToProps)(MainScreenComponent); + +module.exports = { MainScreen }; \ No newline at end of file diff --git a/ElectronClient/app/gui/Navigator.jsx b/ElectronClient/app/gui/Navigator.jsx new file mode 100644 index 000000000..231203a6e --- /dev/null +++ b/ElectronClient/app/gui/Navigator.jsx @@ -0,0 +1,53 @@ +const React = require('react'); const Component = React.Component; +const { connect } = require('react-redux'); +const { app } = require('../app.js'); +const { bridge } = require('electron').remote.require('./bridge'); + +class NavigatorComponent extends Component { + + componentWillReceiveProps(newProps) { + if (newProps.route) { + const screenInfo = this.props.screens[newProps.route.routeName]; + let windowTitle = ['Joplin']; + if (screenInfo.title) { + windowTitle.push(screenInfo.title()); + } + this.updateWindowTitle(windowTitle.join(' - ')); + } + } + + updateWindowTitle(title) { + bridge().window().setTitle(title); + } + + render() { + if (!this.props.route) throw new Error('Route must not be null'); + + const route = this.props.route; + const screenProps = route.props ? route.props : {}; + const screenInfo = this.props.screens[route.routeName]; + const Screen = screenInfo.screen; + + const screenStyle = { + width: this.props.style.width, + height: this.props.style.height, + }; + + return ( + <div style={this.props.style}> + <Screen style={screenStyle} {...screenProps}/> + </div> + ); + } + +} + +const Navigator = connect( + (state) => { + return { + route: state.route, + }; + } +)(NavigatorComponent) + +module.exports = { Navigator }; \ No newline at end of file diff --git a/ElectronClient/app/gui/NoteList.jsx b/ElectronClient/app/gui/NoteList.jsx new file mode 100644 index 000000000..4ba935af7 --- /dev/null +++ b/ElectronClient/app/gui/NoteList.jsx @@ -0,0 +1,201 @@ +const { ItemList } = require('./ItemList.min.js'); +const React = require('react'); +const { connect } = require('react-redux'); +const { time } = require('lib/time-utils.js'); +const { themeStyle } = require('../theme.js'); +const { _ } = require('lib/locale.js'); +const { bridge } = require('electron').remote.require('./bridge'); +const Menu = bridge().Menu; +const MenuItem = bridge().MenuItem; + +class NoteListComponent extends React.Component { + + style() { + const theme = themeStyle(this.props.theme); + + const itemHeight = 34; + + let style = { + root: { + backgroundColor: theme.backgroundColor, + }, + listItem: { + height: itemHeight, + boxSizing: 'border-box', + display: 'flex', + alignItems: 'stretch', + backgroundColor: theme.backgroundColor, + borderBottom: '1px solid ' + theme.dividerColor, + }, + listItemSelected: { + backgroundColor: theme.selectedColor, + }, + listItemTitle: { + fontFamily: theme.fontFamily, + fontSize: theme.fontSize, + textDecoration: 'none', + color: theme.color, + cursor: 'default', + whiteSpace: 'nowrap', + flex: 1, + display: 'flex', + alignItems: 'center', + overflow: 'hidden', + }, + listItemTitleCompleted: { + opacity: 0.5, + textDecoration: 'line-through', + }, + }; + + return style; + } + + itemContextMenu(event) { + const noteIds = this.props.selectedNoteIds; + if (!noteIds.length) return; + + const menu = new Menu() + + menu.append(new MenuItem({label: _('Add or remove tags'), enabled: noteIds.length === 1, click: async () => { + this.props.dispatch({ + type: 'WINDOW_COMMAND', + name: 'setTags', + noteId: noteIds[0], + }); + }})); + + menu.append(new MenuItem({label: _('Switch between note and to-do type'), click: async () => { + for (let i = 0; i < noteIds.length; i++) { + const note = await Note.load(noteIds[i]); + await Note.save(Note.toggleIsTodo(note)); + } + }})); + + menu.append(new MenuItem({label: _('Delete'), click: async () => { + const ok = bridge().showConfirmMessageBox(noteIds.length > 1 ? _('Delete notes?') : _('Delete note?')); + if (!ok) return; + await Note.batchDelete(noteIds); + }})); + + menu.popup(bridge().window()); + } + + itemRenderer(item, theme, width) { + const onTitleClick = async (event, item) => { + if (event.ctrlKey) { + event.preventDefault(); + this.props.dispatch({ + type: 'NOTE_SELECT_TOGGLE', + id: item.id, + }); + } else if (event.shiftKey) { + event.preventDefault(); + this.props.dispatch({ + type: 'NOTE_SELECT_EXTEND', + id: item.id, + }); + } else { + this.props.dispatch({ + type: 'NOTE_SELECT', + id: item.id, + }); + } + } + + const onDragStart = (event) => { + const noteIds = this.props.selectedNoteIds; + if (!noteIds.length) return; + + event.dataTransfer.setDragImage(new Image(), 1, 1); + event.dataTransfer.clearData(); + event.dataTransfer.setData('text/x-jop-note-ids', JSON.stringify(noteIds)); + } + + const onCheckboxClick = async (event) => { + const checked = event.target.checked; + const newNote = { + id: item.id, + todo_completed: checked ? time.unixMs() : 0, + } + await Note.save(newNote); + } + + const hPadding = 10; + + let style = Object.assign({ width: width }, this.style().listItem); + if (this.props.selectedNoteIds.indexOf(item.id) >= 0) style = Object.assign(style, this.style().listItemSelected); + + // Setting marginBottom = 1 because it makes the checkbox looks more centered, at least on Windows + // but don't know how it will look in other OSes. + const checkbox = item.is_todo ? + <div style={{display: 'flex', height: style.height, alignItems: 'center', paddingLeft: hPadding}}> + <input style={{margin:0, marginBottom:1}} type="checkbox" defaultChecked={!!item.todo_completed} onClick={(event) => { onCheckboxClick(event, item) }}/> + </div> + : null; + + let listItemTitleStyle = Object.assign({}, this.style().listItemTitle); + listItemTitleStyle.paddingLeft = !checkbox ? hPadding : 4; + if (item.is_todo && !!item.todo_completed) listItemTitleStyle = Object.assign(listItemTitleStyle, this.style().listItemTitleCompleted); + + // Need to include "todo_completed" in key so that checkbox is updated when + // item is changed via sync. + return <div key={item.id + '_' + item.todo_completed} style={style}> + {checkbox} + <a + className="list-item" + onContextMenu={(event) => this.itemContextMenu(event)} + href="#" + draggable={true} + style={listItemTitleStyle} + onClick={(event) => { onTitleClick(event, item) }} + onDragStart={(event) => onDragStart(event) } + > + {item.title} + </a> + </div> + } + + render() { + const theme = themeStyle(this.props.theme); + const style = this.props.style; + + if (!this.props.notes.length) { + const padding = 10; + const emptyDivStyle = Object.assign({ + padding: padding + 'px', + fontSize: theme.fontSize, + color: theme.color, + backgroundColor: theme.backgroundColor, + fontFamily: theme.fontFamily, + }, style); + emptyDivStyle.width = emptyDivStyle.width - padding * 2; + emptyDivStyle.height = emptyDivStyle.height - padding * 2; + return <div style={emptyDivStyle}>{_('No notes in here. Create one by clicking on "New note".')}</div> + } + + return ( + <ItemList + itemHeight={this.style().listItem.height} + style={style} + className={"note-list"} + items={this.props.notes} + itemRenderer={ (item) => { return this.itemRenderer(item, theme, style.width) } } + ></ItemList> + ); + } + +} + +const mapStateToProps = (state) => { + return { + notes: state.notes, + selectedNoteIds: state.selectedNoteIds, + theme: state.settings.theme, + // uncompletedTodosOnTop: state.settings.uncompletedTodosOnTop, + }; +}; + +const NoteList = connect(mapStateToProps)(NoteListComponent); + +module.exports = { NoteList }; \ No newline at end of file diff --git a/ElectronClient/app/gui/NoteText.jsx b/ElectronClient/app/gui/NoteText.jsx new file mode 100644 index 000000000..15ac652cd --- /dev/null +++ b/ElectronClient/app/gui/NoteText.jsx @@ -0,0 +1,519 @@ +const React = require('react'); +const { Note } = require('lib/models/note.js'); +const { Setting } = require('lib/models/setting.js'); +const { IconButton } = require('./IconButton.min.js'); +const { connect } = require('react-redux'); +const { _ } = require('lib/locale.js'); +const { reg } = require('lib/registry.js'); +const MdToHtml = require('lib/MdToHtml'); +const shared = require('lib/components/shared/note-screen-shared.js'); +const { bridge } = require('electron').remote.require('./bridge'); +const { themeStyle } = require('../theme.js'); +const AceEditor = require('react-ace').default; +const Menu = bridge().Menu; +const MenuItem = bridge().MenuItem; +const { shim } = require('lib/shim.js'); + +require('brace/mode/markdown'); +// https://ace.c9.io/build/kitchen-sink.html +// https://highlightjs.org/static/demo/ +require('brace/theme/chrome'); + +class NoteTextComponent extends React.Component { + + constructor() { + super(); + + this.state = { + note: null, + noteMetadata: '', + showNoteMetadata: false, + folder: null, + lastSavedNote: null, + isLoading: true, + webviewReady: false, + scrollHeight: null, + editorScrollTop: 0, + }; + + this.lastLoadedNoteId_ = null; + + this.webviewListeners_ = null; + this.ignoreNextEditorScroll_ = false; + this.scheduleSaveTimeout_ = null; + this.restoreScrollTop_ = null; + + // Complicated but reliable method to get editor content height + // https://github.com/ajaxorg/ace/issues/2046 + this.editorMaxScrollTop_ = 0; + this.onAfterEditorRender_ = () => { + const r = this.editor_.editor.renderer; + this.editorMaxScrollTop_ = Math.max(0, r.layerConfig.maxHeight - r.$size.scrollerHeight); + + if (this.restoreScrollTop_ !== null) { + this.editorSetScrollTop(this.restoreScrollTop_); + this.restoreScrollTop_ = null; + } + } + } + + mdToHtml() { + if (this.mdToHtml_) return this.mdToHtml_; + this.mdToHtml_ = new MdToHtml({ + supportsResourceLinks: true, + resourceBaseUrl: 'file://' + Setting.value('resourceDir') + '/', + }); + return this.mdToHtml_; + } + + async componentWillMount() { + let note = null; + if (this.props.noteId) { + note = await Note.load(this.props.noteId); + } + + const folder = note ? Folder.byId(this.props.folders, note.parent_id) : null; + + this.setState({ + lastSavedNote: Object.assign({}, note), + note: note, + folder: folder, + isLoading: false, + }); + + this.lastLoadedNoteId_ = note ? note.id : null; + } + + componentWillUnmount() { + this.saveIfNeeded(); + + this.mdToHtml_ = null; + this.destroyWebview(); + } + + async saveIfNeeded() { + if (this.scheduleSaveTimeout_) clearTimeout(this.scheduleSaveTimeout_); + this.scheduleSaveTimeout_ = null; + if (!shared.isModified(this)) return; + await shared.saveNoteButton_press(this); + } + + async saveOneProperty(name, value) { + await shared.saveOneProperty(this, name, value); + } + + scheduleSave() { + if (this.scheduleSaveTimeout_) clearTimeout(this.scheduleSaveTimeout_); + this.scheduleSaveTimeout_ = setTimeout(() => { + this.saveIfNeeded(); + }, 500); + } + + async reloadNote(props) { + this.mdToHtml_ = null; + + const noteId = props.noteId; + this.lastLoadedNoteId_ = noteId; + const note = noteId ? await Note.load(noteId) : null; + if (noteId !== this.lastLoadedNoteId_) return; // Race condition - current note was changed while this one was loading + + // If we are loading nothing (noteId == null), make sure to + // set webviewReady to false too because the webview component + // is going to be removed in render(). + const webviewReady = this.webview_ && this.state.webviewReady && noteId; + + this.editorMaxScrollTop_ = 0; + + // HACK: To go around a bug in Ace editor, we first set the scroll position to 1 + // and then (in the renderer callback) to the value we actually need. The first + // operation helps clear the scroll position cache. See: + // https://github.com/ajaxorg/ace/issues/2195 + this.editorSetScrollTop(1); + this.restoreScrollTop_ = 0; + + this.setState({ + note: note, + lastSavedNote: Object.assign({}, note), + webviewReady: webviewReady, + }); + } + + async componentWillReceiveProps(nextProps) { + if ('noteId' in nextProps && nextProps.noteId !== this.props.noteId) { + await this.reloadNote(nextProps); + } + + if ('syncStarted' in nextProps && !nextProps.syncStarted && !this.isModified()) { + await this.reloadNote(nextProps); + } + } + + isModified() { + return shared.isModified(this); + } + + refreshNoteMetadata(force = null) { + return shared.refreshNoteMetadata(this, force); + } + + title_changeText(event) { + shared.noteComponent_change(this, 'title', event.target.value); + this.scheduleSave(); + } + + toggleIsTodo_onPress() { + shared.toggleIsTodo_onPress(this); + this.scheduleSave(); + } + + showMetadata_onPress() { + shared.showMetadata_onPress(this); + } + + webview_ipcMessage(event) { + const msg = event.channel ? event.channel : ''; + const args = event.args; + const arg0 = args && args.length >= 1 ? args[0] : null; + const arg1 = args && args.length >= 2 ? args[1] : null; + + reg.logger().debug('Got ipc-message: ' + msg, args); + + if (msg.indexOf('checkboxclick:') === 0) { + // Ugly hack because setting the body here will make the scrollbar + // go to some random position. So we save the scrollTop here and it + // will be restored after the editor ref has been reset, and the + // "afterRender" event has been called. + this.restoreScrollTop_ = this.editorScrollTop(); + + const newBody = this.mdToHtml_.handleCheckboxClick(msg, this.state.note.body); + this.saveOneProperty('body', newBody); + } else if (msg.toLowerCase().indexOf('http') === 0) { + require('electron').shell.openExternal(msg); + } else if (msg === 'percentScroll') { + this.ignoreNextEditorScroll_ = true; + this.setEditorPercentScroll(arg0); + } else if (msg.indexOf('joplin://') === 0) { + const resourceId = msg.substr('joplin://'.length); + Resource.load(resourceId).then((resource) => { + const filePath = Resource.fullPath(resource); + bridge().openItem(filePath); + }); + } else { + bridge().showMessageBox({ + type: 'error', + message: _('Unsupported link or message: %s', msg), + }); + } + } + + editorMaxScroll() { + return this.editorMaxScrollTop_; + } + + editorScrollTop() { + return this.editor_.editor.getSession().getScrollTop(); + } + + editorSetScrollTop(v) { + if (!this.editor_) return; + this.editor_.editor.getSession().setScrollTop(v); + } + + setEditorPercentScroll(p) { + this.editorSetScrollTop(p * this.editorMaxScroll()); + } + + setViewerPercentScroll(p) { + this.webview_.send('setPercentScroll', p); + } + + editor_scroll() { + if (this.ignoreNextEditorScroll_) { + this.ignoreNextEditorScroll_ = false; + return; + } + + const m = this.editorMaxScroll(); + this.setViewerPercentScroll(m ? this.editorScrollTop() / m : 0); + } + + webview_domReady() { + if (!this.webview_) return; + + this.setState({ + webviewReady: true, + }); + + // if (Setting.value('env') === 'dev') this.webview_.openDevTools(); + } + + webview_ref(element) { + if (this.webview_) { + if (this.webview_ === element) return; + this.destroyWebview(); + } + + if (!element) { + this.destroyWebview(); + } else { + this.initWebview(element); + } + } + + editor_ref(element) { + if (this.editor_ === element) return; + + if (this.editor_) { + this.editor_.editor.renderer.off('afterRender', this.onAfterEditorRender_); + } + + this.editor_ = element; + + if (this.editor_) { + this.editor_.editor.renderer.on('afterRender', this.onAfterEditorRender_); + } + } + + initWebview(wv) { + if (!this.webviewListeners_) { + this.webviewListeners_ = { + 'dom-ready': this.webview_domReady.bind(this), + 'ipc-message': this.webview_ipcMessage.bind(this), + }; + } + + for (let n in this.webviewListeners_) { + if (!this.webviewListeners_.hasOwnProperty(n)) continue; + const fn = this.webviewListeners_[n]; + wv.addEventListener(n, fn); + } + + this.webview_ = wv; + } + + destroyWebview() { + if (!this.webview_) return; + + for (let n in this.webviewListeners_) { + if (!this.webviewListeners_.hasOwnProperty(n)) continue; + const fn = this.webviewListeners_[n]; + this.webview_.removeEventListener(n, fn); + } + + this.webview_ = null; + } + + aceEditor_change(body) { + shared.noteComponent_change(this, 'body', body); + this.scheduleSave(); + } + + itemContextMenu(event) { + const noteId = this.props.noteId; + if (!noteId) return; + + const menu = new Menu() + + menu.append(new MenuItem({label: _('Attach file'), click: async () => { + const filePaths = bridge().showOpenDialog({ + properties: ['openFile', 'createDirectory'], + }); + if (!filePaths || !filePaths.length) return; + + await this.saveIfNeeded(); + const note = await Note.load(noteId); + + try { + reg.logger().info('Attaching ' + filePaths[0]); + const newNote = await shim.attachFileToNote(note, filePaths[0]); + reg.logger().info('File was attached.'); + this.setState({ + note: newNote, + lastSavedNote: Object.assign({}, newNote), + }); + } catch (error) { + reg.logger().error(error); + } + }})); + + menu.popup(bridge().window()); + } + + render() { + const style = this.props.style; + const note = this.state.note; + const body = note ? note.body : ''; + const theme = themeStyle(this.props.theme); + const visiblePanes = this.props.visiblePanes || ['editor', 'viewer']; + + const borderWidth = 1; + + const rootStyle = Object.assign({ + borderLeft: borderWidth + 'px solid ' + theme.dividerColor, + boxSizing: 'border-box', + paddingLeft: 10, + paddingRight: 0, + }, style); + + const innerWidth = rootStyle.width - rootStyle.paddingLeft - rootStyle.paddingRight - borderWidth; + + if (!note) { + const emptyDivStyle = Object.assign({ + backgroundColor: 'black', + opacity: 0.1, + }, rootStyle); + return <div style={emptyDivStyle}></div> + } + + const titleBarStyle = { + width: innerWidth - rootStyle.paddingLeft, + height: 30, + boxSizing: 'border-box', + marginTop: 10, + marginBottom: 10, + display: 'flex', + flexDirection: 'row', + }; + + const titleEditorStyle = { + display: 'flex', + flex: 1, + display: 'inline-block', + paddingTop: 5, + paddingBottom: 5, + paddingLeft: 8, + paddingRight: 8, + marginRight: rootStyle.paddingLeft, + }; + + const bottomRowHeight = rootStyle.height - titleBarStyle.height - titleBarStyle.marginBottom - titleBarStyle.marginTop; + + const viewerStyle = { + width: Math.floor(innerWidth / 2), + height: bottomRowHeight, + overflow: 'hidden', + float: 'left', + verticalAlign: 'top', + boxSizing: 'border-box', + }; + + const paddingTop = 14; + + const editorStyle = { + width: innerWidth - viewerStyle.width, + height: bottomRowHeight - paddingTop, + overflowY: 'hidden', + float: 'left', + verticalAlign: 'top', + paddingTop: paddingTop + 'px', + lineHeight: theme.textAreaLineHeight + 'px', + fontSize: theme.fontSize + 'px', + }; + + if (visiblePanes.indexOf('viewer') < 0) { + // Note: setting webview.display to "none" is currently not supported due + // to this bug: https://github.com/electron/electron/issues/8277 + // So instead setting the width 0. + viewerStyle.width = 0; + editorStyle.width = innerWidth; + } + + if (visiblePanes.indexOf('editor') < 0) { + editorStyle.display = 'none'; + viewerStyle.width = innerWidth; + } + + if (visiblePanes.indexOf('viewer') >= 0 && visiblePanes.indexOf('editor') >= 0) { + viewerStyle.borderLeft = '1px solid ' + theme.dividerColor; + } else { + viewerStyle.borderLeft = 'none'; + } + + if (this.state.webviewReady) { + const mdOptions = { + onResourceLoaded: () => { + this.forceUpdate(); + }, + postMessageSyntax: 'ipcRenderer.sendToHost', + }; + const html = this.mdToHtml().render(body, theme, mdOptions); + this.webview_.send('setHtml', html); + } + + const titleEditor = <input + type="text" + style={titleEditorStyle} + value={note ? note.title : ''} + onChange={(event) => { this.title_changeText(event); }} + /> + + const titleBarMenuButton = <IconButton style={{ + display: 'flex', + }} iconName="fa-caret-down" theme={this.props.theme} onClick={() => { this.itemContextMenu() }} /> + + const viewer = <webview + style={viewerStyle} + nodeintegration="1" + src="gui/note-viewer/index.html" + ref={(elem) => { this.webview_ref(elem); } } + /> + + const editorRootStyle = Object.assign({}, editorStyle); + delete editorRootStyle.width; + delete editorRootStyle.height; + delete editorRootStyle.fontSize; + + const editor = <AceEditor + value={body} + mode="markdown" + theme="chrome" + style={editorRootStyle} + width={editorStyle.width + 'px'} + height={editorStyle.height + 'px'} + fontSize={editorStyle.fontSize} + showGutter={false} + name="note-editor" + wrapEnabled={true} + onScroll={(event) => { this.editor_scroll(); }} + ref={(elem) => { this.editor_ref(elem); } } + onChange={(body) => { this.aceEditor_change(body) }} + showPrintMargin={false} + + // Disable warning: "Automatically scrolling cursor into view after + // selection change this will be disabled in the next version set + // editor.$blockScrolling = Infinity to disable this message" + editorProps={{$blockScrolling: true}} + + // This is buggy (gets outside the container) + highlightActiveLine={false} + /> + + return ( + <div style={rootStyle}> + <div style={titleBarStyle}> + { titleEditor } + { titleBarMenuButton } + </div> + { editor } + { viewer } + </div> + ); + } + +} + +const mapStateToProps = (state) => { + return { + noteId: state.selectedNoteIds.length === 1 ? state.selectedNoteIds[0] : null, + folderId: state.selectedFolderId, + itemType: state.selectedItemType, + folders: state.folders, + theme: state.settings.theme, + showAdvancedOptions: state.settings.showAdvancedOptions, + syncStarted: state.syncStarted, + }; +}; + +const NoteText = connect(mapStateToProps)(NoteTextComponent); + +module.exports = { NoteText }; \ No newline at end of file diff --git a/ElectronClient/app/gui/OneDriveLoginScreen.jsx b/ElectronClient/app/gui/OneDriveLoginScreen.jsx new file mode 100644 index 000000000..3c7a84be9 --- /dev/null +++ b/ElectronClient/app/gui/OneDriveLoginScreen.jsx @@ -0,0 +1,112 @@ +const React = require('react'); +const { connect } = require('react-redux'); +const { reg } = require('lib/registry.js'); +const { bridge } = require('electron').remote.require('./bridge'); +const { Header } = require('./Header.min.js'); +const { themeStyle } = require('../theme.js'); +const { _ } = require('lib/locale.js'); + +class OneDriveLoginScreenComponent extends React.Component { + + constructor() { + super(); + this.webview_ = null; + this.authCode_ = null; + } + + refresh_click() { + if (!this.webview_) return; + this.webview_.src = this.startUrl(); + } + + componentWillMount() { + this.setState({ + webviewUrl: this.startUrl(), + webviewReady: false, + }); + } + + componentDidMount() { + this.webview_.addEventListener('dom-ready', this.webview_domReady.bind(this)); + } + + componentWillUnmount() { + this.webview_.addEventListener('dom-ready', this.webview_domReady.bind(this)); + } + + webview_domReady() { + this.setState({ webviewReady: true }); + + this.webview_.addEventListener('did-navigate', async (event) => { + const url = event.url; + + if (this.authCode_) return; + if (url.indexOf(this.redirectUrl() + '?code=') !== 0) return; + + let code = url.split('?code='); + this.authCode_ = code[1]; + + try { + await reg.syncTarget().api().execTokenRequest(this.authCode_, this.redirectUrl(), true); + this.props.dispatch({ type: 'NAV_BACK' }); + reg.scheduleSync(0); + } catch (error) { + bridge().showMessageBox({ + type: 'error', + message: error.message, + }); + } + + this.authCode_ = null; + }); + } + + startUrl() { + return reg.syncTarget().api().authCodeUrl(this.redirectUrl()); + } + + redirectUrl() { + return reg.syncTarget().api().nativeClientRedirectUrl(); + } + + render() { + const style = this.props.style; + const theme = themeStyle(this.props.theme); + + const headerStyle = { + width: style.width, + }; + + const webviewStyle = { + width: this.props.style.width, + height: this.props.style.height - theme.headerHeight, + overflow: 'hidden', + }; + + const headerButtons = [ + { + title: _('Refresh'), + onClick: () => this.refresh_click(), + iconName: 'fa-refresh', + }, + ]; + + return ( + <div> + <Header style={headerStyle} buttons={headerButtons} /> + <webview src={this.startUrl()} style={webviewStyle} nodeintegration="1" ref={elem => this.webview_ = elem} /> + </div> + ); + } + +} + +const mapStateToProps = (state) => { + return { + theme: state.settings.theme, + }; +}; + +const OneDriveLoginScreen = connect(mapStateToProps)(OneDriveLoginScreenComponent); + +module.exports = { OneDriveLoginScreen }; \ No newline at end of file diff --git a/ElectronClient/app/gui/PromptDialog.jsx b/ElectronClient/app/gui/PromptDialog.jsx new file mode 100644 index 000000000..846bf7180 --- /dev/null +++ b/ElectronClient/app/gui/PromptDialog.jsx @@ -0,0 +1,123 @@ +const React = require('react'); +const { connect } = require('react-redux'); +const { _ } = require('lib/locale.js'); +const { themeStyle } = require('../theme.js'); + +class PromptDialog extends React.Component { + + componentWillMount() { + this.setState({ + visible: false, + answer: this.props.value ? this.props.value : '', + }); + this.focusInput_ = true; + } + + componentWillReceiveProps(newProps) { + if ('visible' in newProps) { + this.setState({ visible: newProps.visible }); + if (newProps.visible) this.focusInput_ = true; + } + + if ('value' in newProps) { + this.setState({ answer: newProps.value }); + } + } + + componentDidUpdate() { + if (this.focusInput_ && this.answerInput_) this.answerInput_.focus(); + this.focusInput_ = false; + } + + render() { + const style = this.props.style; + const theme = themeStyle(this.props.theme); + + const modalLayerStyle = { + zIndex: 9999, + position: 'absolute', + top: 0, + left: 0, + width: style.width, + height: style.height, + backgroundColor: 'rgba(0,0,0,0.6)', + display: this.state.visible ? 'flex' : 'none', + alignItems: 'center', + justifyContent: 'center', + }; + + const promptDialogStyle = { + backgroundColor: 'white', + padding: 16, + display: 'inline-block', + boxShadow: '6px 6px 20px rgba(0,0,0,0.5)', + }; + + const buttonStyle = { + minWidth: theme.buttonMinWidth, + minHeight: theme.buttonMinHeight, + marginLeft: 5, + }; + + const labelStyle = { + marginRight: 5, + fontSize: theme.fontSize, + color: theme.color, + fontFamily: theme.fontFamily, + verticalAlign: 'top', + }; + + const inputStyle = { + width: 0.5 * style.width, + maxWidth: 400, + }; + + const descStyle = Object.assign({}, theme.textStyle, { + marginTop: 10, + }); + + const onClose = (accept) => { + if (this.props.onClose) this.props.onClose(accept ? this.state.answer : null); + this.setState({ visible: false, answer: '' }); + } + + const onChange = (event) => { + this.setState({ answer: event.target.value }); + } + + const onKeyDown = (event) => { + if (event.key === 'Enter') { + onClose(true); + } else if (event.key === 'Escape') { + onClose(false); + } + } + + const descComp = this.props.description ? <div style={descStyle}>{this.props.description}</div> : null; + + return ( + <div style={modalLayerStyle}> + <div style={promptDialogStyle}> + <label style={labelStyle}>{this.props.label ? this.props.label : ''}</label> + <div style={{display: 'inline-block'}}> + <input + style={inputStyle} + ref={input => this.answerInput_ = input} + value={this.state.answer} + type="text" + onChange={(event) => onChange(event)} + onKeyDown={(event) => onKeyDown(event)} /> + {descComp} + </div> + <div style={{ textAlign: 'right', marginTop: 10 }}> + <button style={buttonStyle} onClick={() => onClose(true)}>OK</button> + <button style={buttonStyle} onClick={() => onClose(false)}>Cancel</button> + </div> + </div> + </div> + ); + } + +} + +module.exports = { PromptDialog }; \ No newline at end of file diff --git a/ElectronClient/app/gui/Root.jsx b/ElectronClient/app/gui/Root.jsx new file mode 100644 index 000000000..f1ab3a6f4 --- /dev/null +++ b/ElectronClient/app/gui/Root.jsx @@ -0,0 +1,103 @@ +const React = require('react'); +const { render } = require('react-dom'); +const { createStore } = require('redux'); +const { connect, Provider } = require('react-redux'); + +const { _ } = require('lib/locale.js'); +const { Setting } = require('lib/models/setting.js'); + +const { MainScreen } = require('./MainScreen.min.js'); +const { OneDriveLoginScreen } = require('./OneDriveLoginScreen.min.js'); +const { ImportScreen } = require('./ImportScreen.min.js'); +const { ConfigScreen } = require('./ConfigScreen.min.js'); +const { Navigator } = require('./Navigator.min.js'); + +const { app } = require('../app'); + +const { bridge } = require('electron').remote.require('./bridge'); + +async function initialize(dispatch) { + this.wcsTimeoutId_ = null; + + bridge().window().on('resize', function() { + if (this.wcsTimeoutId_) clearTimeout(this.wcsTimeoutId_); + + this.wcsTimeoutId_ = setTimeout(() => { + store.dispatch({ + type: 'WINDOW_CONTENT_SIZE_SET', + size: bridge().windowContentSize(), + }); + this.wcsTimeoutId_ = null; + }, 10); + }); + + // Need to dispatch this to make sure the components are + // displayed at the right size. The windowContentSize is + // also set in the store default state, but at that point + // the window might not be at its final size. + store.dispatch({ + type: 'WINDOW_CONTENT_SIZE_SET', + size: bridge().windowContentSize(), + }); + + store.dispatch({ + type: 'NOTE_VISIBLE_PANES_SET', + panes: Setting.value('noteVisiblePanes'), + }); +} + +class RootComponent extends React.Component { + + async componentDidMount() { + if (this.props.appState == 'starting') { + this.props.dispatch({ + type: 'APP_STATE_SET', + state: 'initializing', + }); + + await initialize(this.props.dispatch); + + this.props.dispatch({ + type: 'APP_STATE_SET', + state: 'ready', + }); + } + } + + render() { + const navigatorStyle = { + width: this.props.size.width, + height: this.props.size.height, + }; + + const screens = { + Main: { screen: MainScreen }, + OneDriveLogin: { screen: OneDriveLoginScreen, title: () => _('OneDrive Login') }, + Import: { screen: ImportScreen, title: () => _('Import') }, + Config: { screen: ConfigScreen, title: () => _('Configuration') }, + }; + + return ( + <Navigator style={navigatorStyle} screens={screens} /> + ); + } + +} + +const mapStateToProps = (state) => { + return { + size: state.windowContentSize, + appState: state.appState, + }; +}; + +const Root = connect(mapStateToProps)(RootComponent); + +const store = app().store(); + +render( + <Provider store={store}> + <Root /> + </Provider>, + document.getElementById('react-root') +) \ No newline at end of file diff --git a/ElectronClient/app/gui/SideBar.jsx b/ElectronClient/app/gui/SideBar.jsx new file mode 100644 index 000000000..8e9a019f5 --- /dev/null +++ b/ElectronClient/app/gui/SideBar.jsx @@ -0,0 +1,295 @@ +const React = require('react'); +const { connect } = require('react-redux'); +const shared = require('lib/components/shared/side-menu-shared.js'); +const { Synchronizer } = require('lib/synchronizer.js'); +const { BaseModel } = require('lib/base-model.js'); +const { Folder } = require('lib/models/folder.js'); +const { Note } = require('lib/models/note.js'); +const { Tag } = require('lib/models/tag.js'); +const { _ } = require('lib/locale.js'); +const { themeStyle } = require('../theme.js'); +const { bridge } = require('electron').remote.require('./bridge'); +const Menu = bridge().Menu; +const MenuItem = bridge().MenuItem; + +class SideBarComponent extends React.Component { + + style() { + const theme = themeStyle(this.props.theme); + + const itemHeight = 25; + + let style = { + root: { + backgroundColor: theme.backgroundColor2, + }, + listItem: { + height: itemHeight, + fontFamily: theme.fontFamily, + fontSize: theme.fontSize, + textDecoration: 'none', + boxSizing: 'border-box', + color: theme.color2, + paddingLeft: 14, + display: 'flex', + alignItems: 'center', + cursor: 'default', + opacity: 0.8, + }, + listItemSelected: { + backgroundColor: theme.selectedColor2, + }, + conflictFolder: { + color: theme.colorError2, + fontWeight: 'bold', + }, + header: { + height: itemHeight * 1.8, + fontFamily: theme.fontFamily, + fontSize: theme.fontSize * 1.3, + textDecoration: 'none', + boxSizing: 'border-box', + color: theme.color2, + paddingLeft: 8, + display: 'flex', + alignItems: 'center', + }, + button: { + padding: 6, + fontFamily: theme.fontFamily, + fontSize: theme.fontSize, + textDecoration: 'none', + boxSizing: 'border-box', + color: theme.color2, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + border: "1px solid rgba(255,255,255,0.2)", + marginTop: 10, + marginLeft: 5, + marginRight: 5, + cursor: 'default', + }, + syncReport: { + fontFamily: theme.fontFamily, + fontSize: Math.round(theme.fontSize * .9), + color: theme.color2, + opacity: .5, + display: 'flex', + alignItems: 'left', + justifyContent: 'top', + flexDirection: 'column', + marginTop: 10, + marginLeft: 5, + marginRight: 5, + minHeight: 70, + }, + }; + + return style; + } + + itemContextMenu(event) { + const itemId = event.target.getAttribute('data-id'); + if (itemId === Folder.conflictFolderId()) return; + + const itemType = Number(event.target.getAttribute('data-type')); + if (!itemId || !itemType) throw new Error('No data on element'); + + let deleteMessage = ''; + if (itemType === BaseModel.TYPE_FOLDER) { + deleteMessage = _('Delete notebook?'); + } else if (itemType === BaseModel.TYPE_TAG) { + deleteMessage = _('Remove this tag from all the notes?'); + } else if (itemType === BaseModel.TYPE_SEARCH) { + deleteMessage = _('Remove this search from the sidebar?'); + } + + const menu = new Menu(); + + menu.append(new MenuItem({label: _('Delete'), click: async () => { + const ok = bridge().showConfirmMessageBox(deleteMessage); + if (!ok) return; + + if (itemType === BaseModel.TYPE_FOLDER) { + await Folder.delete(itemId); + } else if (itemType === BaseModel.TYPE_TAG) { + await Tag.untagAll(itemId); + } else if (itemType === BaseModel.TYPE_SEARCH) { + this.props.dispatch({ + type: 'SEARCH_DELETE', + id: itemId, + }); + } + }})) + + if (itemType === BaseModel.TYPE_FOLDER) { + menu.append(new MenuItem({label: _('Rename'), click: async () => { + this.props.dispatch({ + type: 'WINDOW_COMMAND', + name: 'renameNotebook', + id: itemId, + }); + }})) + } + + menu.popup(bridge().window()); + } + + folderItem_click(folder) { + this.props.dispatch({ + type: 'FOLDER_SELECT', + id: folder ? folder.id : null, + }); + } + + tagItem_click(tag) { + this.props.dispatch({ + type: 'TAG_SELECT', + id: tag ? tag.id : null, + }); + } + + searchItem_click(search) { + this.props.dispatch({ + type: 'SEARCH_SELECT', + id: search ? search.id : null, + }); + } + + async sync_click() { + await shared.synchronize_press(this); + } + + folderItem(folder, selected) { + let style = Object.assign({}, this.style().listItem); + if (selected) style = Object.assign(style, this.style().listItemSelected); + if (folder.id === Folder.conflictFolderId()) style = Object.assign(style, this.style().conflictFolder); + + const onDragOver = (event, folder) => { + if (event.dataTransfer.types.indexOf('text/x-jop-note-ids') >= 0) event.preventDefault(); + } + + const onDrop = async (event, folder) => { + if (event.dataTransfer.types.indexOf('text/x-jop-note-ids') < 0) return; + event.preventDefault(); + + const noteIds = JSON.parse(event.dataTransfer.getData('text/x-jop-note-ids')); + for (let i = 0; i < noteIds.length; i++) { + await Note.moveToFolder(noteIds[i], folder.id); + } + } + + return <a + className="list-item" + onDragOver={(event) => { onDragOver(event, folder) } } + onDrop={(event) => { onDrop(event, folder) } } + href="#" + data-id={folder.id} + data-type={BaseModel.TYPE_FOLDER} + onContextMenu={(event) => this.itemContextMenu(event)} + key={folder.id} + style={style} onClick={() => {this.folderItem_click(folder)}}>{folder.title} + </a> + } + + tagItem(tag, selected) { + let style = Object.assign({}, this.style().listItem); + if (selected) style = Object.assign(style, this.style().listItemSelected); + return <a className="list-item" href="#" data-id={tag.id} data-type={BaseModel.TYPE_TAG} onContextMenu={(event) => this.itemContextMenu(event)} key={tag.id} style={style} onClick={() => {this.tagItem_click(tag)}}>{tag.title}</a> + } + + searchItem(search, selected) { + let style = Object.assign({}, this.style().listItem); + if (selected) style = Object.assign(style, this.style().listItemSelected); + return <a className="list-item" href="#" data-id={search.id} data-type={BaseModel.TYPE_SEARCH} onContextMenu={(event) => this.itemContextMenu(event)} key={search.id} style={style} onClick={() => {this.searchItem_click(search)}}>{search.title}</a> + } + + makeDivider(key) { + return <div style={{height:2, backgroundColor:'blue' }} key={key}></div> + } + + makeHeader(key, label, iconName) { + const style = this.style().header; + const icon = <i style={{fontSize: style.fontSize * 1.2, marginRight: 5}} className={"fa " + iconName}></i> + return <div style={style} key={key}>{icon}{label}</div> + } + + synchronizeButton(type) { + const style = this.style().button; + const iconName = type === 'sync' ? 'fa-refresh' : 'fa-times'; + const label = type === 'sync' ? _('Synchronise') : _('Cancel'); + const icon = <i style={{fontSize: style.fontSize, marginRight: 5}} className={"fa " + iconName}></i> + return <a className="synchronize-button" style={style} href="#" key="sync_button" onClick={() => {this.sync_click()}}>{icon}{label}</a> + } + + render() { + const theme = themeStyle(this.props.theme); + const style = Object.assign({}, this.style().root, this.props.style, { + overflowX: 'hidden', + overflowY: 'auto', + }); + + let items = []; + + items.push(this.makeHeader('folderHeader', _('Notebooks'), 'fa-folder-o')); + + if (this.props.folders.length) { + const folderItems = shared.renderFolders(this.props, this.folderItem.bind(this)); + items = items.concat(folderItems); + } + + items.push(this.makeHeader('tagHeader', _('Tags'), 'fa-tags')); + + if (this.props.tags.length) { + const tagItems = shared.renderTags(this.props, this.tagItem.bind(this)); + + items.push(<div className="tags" key="tag_items">{tagItems}</div>); + } + + if (this.props.searches.length) { + items.push(this.makeHeader('searchHeader', _('Searches'), 'fa-search')); + + const searchItems = shared.renderSearches(this.props, this.searchItem.bind(this)); + + items.push(<div className="searches" key="search_items">{searchItems}</div>); + } + + let lines = Synchronizer.reportToLines(this.props.syncReport); + const syncReportText = []; + for (let i = 0; i < lines.length; i++) { + syncReportText.push(<div key={i}>{lines[i]}</div>); + } + + items.push(this.synchronizeButton(this.props.syncStarted ? 'cancel' : 'sync')); + + items.push(<div style={this.style().syncReport} key='sync_report'>{syncReportText}</div>); + + return ( + <div className="side-bar" style={style}> + {items} + </div> + ); + } + +} + +const mapStateToProps = (state) => { + return { + folders: state.folders, + tags: state.tags, + searches: state.searches, + syncStarted: state.syncStarted, + syncReport: state.syncReport, + selectedFolderId: state.selectedFolderId, + selectedTagId: state.selectedTagId, + selectedSearchId: state.selectedSearchId, + notesParentType: state.notesParentType, + locale: state.settings.locale, + theme: state.settings.theme, + }; +}; + +const SideBar = connect(mapStateToProps)(SideBarComponent); + +module.exports = { SideBar }; \ No newline at end of file diff --git a/ElectronClient/app/gui/note-viewer/highlight/VERSION.txt b/ElectronClient/app/gui/note-viewer/highlight/VERSION.txt new file mode 100644 index 000000000..a2829f95f --- /dev/null +++ b/ElectronClient/app/gui/note-viewer/highlight/VERSION.txt @@ -0,0 +1 @@ +version 9.12.0 \ No newline at end of file diff --git a/ElectronClient/app/gui/note-viewer/highlight/highlight.pack.js b/ElectronClient/app/gui/note-viewer/highlight/highlight.pack.js new file mode 100644 index 000000000..25dd166c8 --- /dev/null +++ b/ElectronClient/app/gui/note-viewer/highlight/highlight.pack.js @@ -0,0 +1,2 @@ +/*! highlight.js v9.12.0 | BSD3 License | git.io/hljslicense */ +!function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(e){function n(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0===t.index}function a(e){return k.test(e)}function i(e){var n,t,r,i,o=e.className+" ";if(o+=e.parentNode?e.parentNode.className:"",t=B.exec(o))return w(t[1])?t[1]:"no-highlight";for(o=o.split(/\s+/),n=0,r=o.length;r>n;n++)if(i=o[n],a(i)||w(i))return i}function o(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3===i.nodeType?a+=i.nodeValue.length:1===i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!==r[0].offset?e[0].offset<r[0].offset?e:r:"start"===r[0].event?e:r:e.length?e:r}function o(e){function r(e){return" "+e.nodeName+'="'+n(e.value).replace('"',""")+'"'}s+="<"+t(e)+E.map.call(e.attributes,r).join("")+">"}function u(e){s+="</"+t(e)+">"}function c(e){("start"===e.event?o:u)(e.node)}for(var l=0,s="",f=[];e.length||r.length;){var g=i();if(s+=n(a.substring(l,g[0].offset)),l=g[0].offset,g===e){f.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g===e&&g.length&&g[0].offset===l);f.reverse().forEach(o)}else"start"===g[0].event?f.push(g[0].node):f.pop(),c(g.splice(0,1)[0])}return s+n(a.substr(l))}function l(e){return e.v&&!e.cached_variants&&(e.cached_variants=e.v.map(function(n){return o(e,{v:null},n)})),e.cached_variants||e.eW&&[o(e)]||[e]}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},u=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");o[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?u("keyword",a.k):x(a.k).forEach(function(e){u(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),null==a.r&&(a.r=1),a.c||(a.c=[]),a.c=Array.prototype.concat.apply([],a.c.map(function(e){return l("self"===e?a:e)})),a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var c=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=c.length?t(c.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){var t,a;for(t=0,a=n.c.length;a>t;t++)if(r(n.c[t].bR,e))return n.c[t]}function u(e,n){if(r(e.eR,n)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?u(e.parent,n):void 0}function c(e,n){return!a&&r(n.iR,e)}function l(e,n){var t=N.cI?n[0].toLowerCase():n[0];return e.k.hasOwnProperty(t)&&e.k[t]}function p(e,n,t,r){var a=r?"":I.classPrefix,i='<span class="'+a,o=t?"":C;return i+=e+'">',i+n+o}function h(){var e,t,r,a;if(!E.k)return n(k);for(a="",t=0,E.lR.lastIndex=0,r=E.lR.exec(k);r;)a+=n(k.substring(t,r.index)),e=l(E,r),e?(B+=e[1],a+=p(e[0],n(r[0]))):a+=n(r[0]),t=E.lR.lastIndex,r=E.lR.exec(k);return a+n(k.substr(t))}function d(){var e="string"==typeof E.sL;if(e&&!y[E.sL])return n(k);var t=e?f(E.sL,k,!0,x[E.sL]):g(k,E.sL.length?E.sL:void 0);return E.r>0&&(B+=t.r),e&&(x[E.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=null!=E.sL?d():h(),k=""}function v(e){L+=e.cN?p(e.cN,"",!0):"",E=Object.create(e,{parent:{value:E}})}function m(e,n){if(k+=e,null==n)return b(),0;var t=o(n,E);if(t)return t.skip?k+=n:(t.eB&&(k+=n),b(),t.rB||t.eB||(k=n)),v(t,n),t.rB?0:n.length;var r=u(E,n);if(r){var a=E;a.skip?k+=n:(a.rE||a.eE||(k+=n),b(),a.eE&&(k=n));do E.cN&&(L+=C),E.skip||(B+=E.r),E=E.parent;while(E!==r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,E))throw new Error('Illegal lexeme "'+n+'" for mode "'+(E.cN||"<unnamed>")+'"');return k+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var R,E=i||N,x={},L="";for(R=E;R!==N;R=R.parent)R.cN&&(L=p(R.cN,"",!0)+L);var k="",B=0;try{for(var M,j,O=0;;){if(E.t.lastIndex=O,M=E.t.exec(t),!M)break;j=m(t.substring(O,M.index),M[0]),O=M.index+j}for(m(t.substr(O)),R=E;R.parent;R=R.parent)R.cN&&(L+=C);return{r:B,value:L,language:e,top:E}}catch(T){if(T.message&&-1!==T.message.indexOf("Illegal"))return{r:0,value:n(t)};throw T}}function g(e,t){t=t||I.languages||x(y);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function p(e){return I.tabReplace||I.useBR?e.replace(M,function(e,n){return I.useBR&&"\n"===e?"<br>":I.tabReplace?n.replace(/\t/g,I.tabReplace):""}):e}function h(e,n,t){var r=n?L[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function d(e){var n,t,r,o,l,s=i(e);a(s)||(I.useBR?(n=document.createElementNS("http://www.w3.org/1999/xhtml","div"),n.innerHTML=e.innerHTML.replace(/\n/g,"").replace(/<br[ \/]*>/g,"\n")):n=e,l=n.textContent,r=s?f(s,l,!0):g(l),t=u(n),t.length&&(o=document.createElementNS("http://www.w3.org/1999/xhtml","div"),o.innerHTML=r.value,r.value=c(t,u(o),l)),r.value=p(r.value),e.innerHTML=r.value,e.className=h(e.className,s,r.language),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function b(e){I=o(I,e)}function v(){if(!v.called){v.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,d)}}function m(){addEventListener("DOMContentLoaded",v,!1),addEventListener("load",v,!1)}function N(n,t){var r=y[n]=t(e);r.aliases&&r.aliases.forEach(function(e){L[e]=n})}function R(){return x(y)}function w(e){return e=(e||"").toLowerCase(),y[e]||y[L[e]]}var E=[],x=Object.keys,y={},L={},k=/^(no-?highlight|plain|text)$/i,B=/\blang(?:uage)?-([\w-]+)\b/i,M=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,C="</span>",I={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};return e.highlight=f,e.highlightAuto=g,e.fixMarkup=p,e.highlightBlock=d,e.configure=b,e.initHighlighting=v,e.initHighlightingOnLoad=m,e.registerLanguage=N,e.listLanguages=R,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("apache",function(e){var r={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"section",b:"</?",e:">"},{cN:"attribute",b:/\w+/,r:0,k:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"meta",b:"\\s\\[",e:"\\]$"},{cN:"variable",b:"[\\$%]\\{",e:"\\}",c:["self",r]},r,e.QSM]}}],i:/\S/}});hljs.registerLanguage("go",function(e){var t={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",literal:"true false iota nil",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{aliases:["golang"],k:t,i:"</",c:[e.CLCM,e.CBCM,{cN:"string",v:[e.QSM,{b:"'",e:"[^\\\\]'"},{b:"`",e:"`"}]},{cN:"number",v:[{b:e.CNR+"[dflsi]",r:1},e.CNM]},{b:/:=/},{cN:"function",bK:"func",e:/\s*\{/,eE:!0,c:[e.TM,{cN:"params",b:/\(/,e:/\)/,k:t,i:/["']/}]}]}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}});hljs.registerLanguage("shell",function(s){return{aliases:["console"],c:[{cN:"meta",b:"^\\s{0,3}[\\w\\d\\[\\]()@-]*[>%$#]",starts:{e:"$",sL:"bash"}}]}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b:/</,e:/(\/\w+|\w+\/)>/,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("ini",function(e){var b={cN:"string",c:[e.BE],v:[{b:"'''",e:"'''",r:10},{b:'"""',e:'"""',r:10},{b:'"',e:'"'},{b:"'",e:"'"}]};return{aliases:["toml"],cI:!0,i:/\S/,c:[e.C(";","$"),e.HCM,{cN:"section",b:/^\s*\[+/,e:/\]+/},{b:/^[a-z0-9\[\]_-]+\s*=\s*/,e:"$",rB:!0,c:[{cN:"attr",b:/[a-z0-9\[\]_-]+/},{b:/=/,eW:!0,r:0,c:[{cN:"literal",b:/\bon|off|true|false|yes|no\b/},{cN:"variable",v:[{b:/\$[\w\d"][\w\d_]*/},{b:/\$\{(.*?)}/}]},b,{cN:"number",b:/([\+\-]+)?[\d]+_[\d_]+/},e.NM]}]}]}});hljs.registerLanguage("coffeescript",function(e){var c={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super yield import export from as default await then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",built_in:"npm require console print module global window document"},n="[A-Za-z$_][0-9A-Za-z$_]*",r={cN:"subst",b:/#\{/,e:/}/,k:c},i=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,r]},{b:/"/,e:/"/,c:[e.BE,r]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[r,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{b:"@"+n},{sL:"javascript",eB:!0,eE:!0,v:[{b:"```",e:"```"},{b:"`",e:"`"}]}];r.c=i;var s=e.inherit(e.TM,{b:n}),t="(\\(.*\\))?\\s*\\B[-=]>",o={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:c,c:["self"].concat(i)}]};return{aliases:["coffee","cson","iced"],k:c,i:/\/\*/,c:i.concat([e.C("###","###"),e.HCM,{cN:"function",b:"^\\s*"+n+"\\s*=\\s*"+t,e:"[-=]>",rB:!0,c:[s,o]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:t,e:"[-=]>",rB:!0,c:[o]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[s]},s]},{b:n+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("ruby",function(e){var b="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",r={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},c={cN:"doctag",b:"@[A-Za-z]+"},a={b:"#<",e:">"},s=[e.C("#","$",{c:[c]}),e.C("^\\=begin","^\\=end",{c:[c],r:10}),e.C("^__END__","\\n$")],n={cN:"subst",b:"#\\{",e:"}",k:r},t={cN:"string",c:[e.BE,n],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{b:/<<(-?)\w+$/,e:/^\s*\w+$/}]},i={cN:"params",b:"\\(",e:"\\)",endsParent:!0,k:r},d=[t,a,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<\\s*",c:[{b:"("+e.IR+"::)?"+e.IR}]}].concat(s)},{cN:"function",bK:"def",e:"$|;",c:[e.inherit(e.TM,{b:b}),i].concat(s)},{b:e.IR+"::"},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":(?!\\s)",c:[t,{b:b}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{cN:"params",b:/\|/,e:/\|/,k:r},{b:"("+e.RSR+"|unless)\\s*",k:"unless",c:[a,{cN:"regexp",c:[e.BE,n],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}].concat(s),r:0}].concat(s);n.c=d,i.c=d;var l="[>?]>",o="[\\w#]+\\(\\w+\\):\\d+:\\d+>",u="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",w=[{b:/^\s*=>/,starts:{e:"$",c:d}},{cN:"meta",b:"^("+l+"|"+o+"|"+u+")",starts:{e:"$",c:d}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:r,i:/\/\*/,c:s.concat(w).concat(d)}});hljs.registerLanguage("sql",function(e){var t=e.C("--","$");return{cI:!0,i:/[<>{}*#]/,c:[{bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke comment",e:/;/,eW:!0,l:/[\w\.]+/,k:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage("java",function(e){var a="[À-ʸa-zA-Z_$][À-ʸa-zA-Z_$0-9]*",t=a+"(<"+a+"(\\s*,\\s*"+a+")*>)?",r="false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",s="\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",c={cN:"number",b:s,r:0};return{aliases:["jsp"],k:r,i:/<\/|#/,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw return else",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:r,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},c,{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("perl",function(e){var t="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",r={cN:"subst",b:"[$@]\\{",e:"\\}",k:t},s={b:"->{",e:"}"},n={v:[{b:/\$\d/},{b:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{b:/[\$%@][^\s\w{]/,r:0}]},i=[e.BE,r,n],o=[n,e.HCM,e.C("^\\=\\w","\\=cut",{eW:!0}),s,{cN:"string",c:i,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[e.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[e.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+e.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[e.HCM,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[e.BE],r:0}]},{cN:"function",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",eE:!0,r:5,c:[e.TM]},{b:"-\\w\\b",r:0},{b:"^__DATA__$",e:"^__END__$",sL:"mojolicious",c:[{b:"^@@.*",e:"$",cN:"comment"}]}];return r.c=o,s.c=o,{aliases:["pl","pm"],l:/[\w\.]+/,k:t,c:o}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/</,r:0,c:[{cN:"attr",b:e,r:0},{b:/=\s*/,r:0,c:[{cN:"string",endsParent:!0,v:[{b:/"/,e:/"/},{b:/'/,e:/'/},{b:/[^\s"'=<>`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist"],cI:!0,c:[{cN:"meta",b:"<!DOCTYPE",e:">",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("<!--","-->",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"<style(?=\\s|>|$)",e:">",k:{name:"style"},c:[t],starts:{e:"</style>",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"<script(?=\\s|>|$)",e:">",k:{name:"script"},c:[t],starts:{e:"</script>",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"</?",e:"/?>",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[{b:'(u8?|U)?L?"',e:'"',i:"\\n",c:[t.BE]},{b:'(u8?|U)?R"',e:'"',c:[t.BE]},{b:"'\\\\?.",e:"'",i:"."}]},s={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},i={cN:"meta",b:/#\s*[a-z]+\b/,e:/$/,k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},c:[{b:/\\\n/,r:0},t.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:/<[^\n>]*>/,e:/$/,i:"\\n"},t.CLCM,t.CBCM]},a=t.IR+"\\s*\\(",c={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},n=[e,t.CLCM,t.CBCM,s,r];return{aliases:["c","cc","h","c++","h++","hpp"],k:c,i:"</",c:n.concat([i,{b:"\\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\\s*<",e:">",k:c,c:["self",e]},{b:t.IR+"::",k:c},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:c,c:n.concat([{b:/\(/,e:/\)/,k:c,c:n.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+t.IR+"[\\*&\\s]+)+"+a,rB:!0,e:/[{;=]/,eE:!0,k:c,i:/[^\w\s\*&]/,c:[{b:a,rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:c,r:0,c:[t.CLCM,t.CBCM,r,s,e]},t.CLCM,t.CBCM,i]},{cN:"class",bK:"class struct",e:/[{;:]/,c:[{b:/</,e:/>/,c:["self"]},t.TM]}]),exports:{preprocessor:i,strings:r,k:c}}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("cs",function(e){var i={keyword:"abstract as base bool break byte case catch char checked const continue decimal default delegate do double enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long nameof object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual void volatile while add alias ascending async await by descending dynamic equals from get global group into join let on orderby partial remove select set value var where yield",literal:"null false true"},t={cN:"string",b:'@"',e:'"',c:[{b:'""'}]},r=e.inherit(t,{i:/\n/}),a={cN:"subst",b:"{",e:"}",k:i},c=e.inherit(a,{i:/\n/}),n={cN:"string",b:/\$"/,e:'"',i:/\n/,c:[{b:"{{"},{b:"}}"},e.BE,c]},s={cN:"string",b:/\$@"/,e:'"',c:[{b:"{{"},{b:"}}"},{b:'""'},a]},o=e.inherit(s,{i:/\n/,c:[{b:"{{"},{b:"}}"},{b:'""'},c]});a.c=[s,n,t,e.ASM,e.QSM,e.CNM,e.CBCM],c.c=[o,n,r,e.ASM,e.QSM,e.CNM,e.inherit(e.CBCM,{i:/\n/})];var l={v:[s,n,t,e.ASM,e.QSM]},b=e.IR+"(<"+e.IR+"(\\s*,\\s*"+e.IR+")*>)?(\\[\\])?";return{aliases:["csharp"],k:i,i:/::/,c:[e.C("///","$",{rB:!0,c:[{cN:"doctag",v:[{b:"///",r:0},{b:"<!--|-->"},{b:"</?",e:">"}]}]}),e.CLCM,e.CBCM,{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},l,e.CNM,{bK:"class interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"namespace",e:/[{;=]/,i:/[^\s:]/,c:[e.inherit(e.TM,{b:"[a-zA-Z](\\.?\\w)*"}),e.CLCM,e.CBCM]},{cN:"meta",b:"^\\s*\\[",eB:!0,e:"\\]",eE:!0,c:[{cN:"meta-string",b:/"/,e:/"/}]},{bK:"new return throw await else",r:0},{cN:"function",b:"("+b+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:i,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:i,r:0,c:[l,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s+{",rB:!0,e:"{",c:[{cN:"section",b:e.UIR}],r:0},{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"attribute",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:/^\[[^\n]+\]:/,rB:!0,c:[{cN:"symbol",b:/\[/,e:/\]/,eB:!0,eE:!0},{cN:"link",b:/:\s*/,e:/$/,eB:!0}]}]}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("python",function(e){var r={keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},b={cN:"meta",b:/^(>>>|\.\.\.) /},c={cN:"subst",b:/\{/,e:/\}/,k:r,i:/#/},a={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[b],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[b],r:10},{b:/(fr|rf|f)'''/,e:/'''/,c:[b,c]},{b:/(fr|rf|f)"""/,e:/"""/,c:[b,c]},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},{b:/(fr|rf|f)'/,e:/'/,c:[c]},{b:/(fr|rf|f)"/,e:/"/,c:[c]},e.ASM,e.QSM]},s={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},i={cN:"params",b:/\(/,e:/\)/,c:["self",b,s,a]};return c.c=[a,s,b],{aliases:["py","gyp"],k:r,i:/(<\/|->|\?)|=>/,c:[b,s,a,e.HCM,{v:[{cN:"function",bK:"def"},{cN:"class",bK:"class"}],e:/:/,i:/[${=;\n,]/,c:[e.UTM,i,{b:/->/,eW:!0,k:"None"}]},{cN:"meta",b:/^[\t ]*@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("objectivec",function(e){var t={cN:"built_in",b:"\\b(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)\\w+"},_={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},i=/[a-zA-Z@][a-zA-Z0-9_]*/,n="@interface @class @protocol @implementation";return{aliases:["mm","objc","obj-c"],k:_,l:i,i:"</",c:[t,e.CLCM,e.CBCM,e.CNM,e.QSM,{cN:"string",v:[{b:'@"',e:'"',i:"\\n",c:[e.BE]},{b:"'",e:"[^\\\\]'",i:"[^\\\\][^']"}]},{cN:"meta",b:"#",e:"$",c:[{cN:"meta-string",v:[{b:'"',e:'"'},{b:"<",e:">"}]}]},{cN:"class",b:"("+n.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:n,l:i,c:[e.UTM]},{b:"\\."+e.UIR,r:0}]}});hljs.registerLanguage("php",function(e){var c={b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},i={cN:"meta",b:/<\?(php)?|\?>/},t={cN:"string",c:[e.BE,i],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},a={v:[e.BNM,e.CNM]};return{aliases:["php3","php4","php5","php6"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.HCM,e.C("//","$",{c:[i]}),e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:/<<<['"]?\w+['"]?$/,e:/^\w+;?$/,c:[e.BE,{cN:"subst",v:[{b:/\$\w+/},{b:/\{\$/,e:/\}/}]}]},i,{cN:"keyword",b:/\$this\b/},c,{b:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",c,e.CBCM,t,a]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},t,a]}});hljs.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/={3,}/,e:/$/},{b:/^\-{3}/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+{3}/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}});hljs.registerLanguage("makefile",function(e){var i={cN:"variable",v:[{b:"\\$\\("+e.UIR+"\\)",c:[e.BE]},{b:/\$[@%<?\^\+\*]/}]},r={cN:"string",b:/"/,e:/"/,c:[e.BE,i]},a={cN:"variable",b:/\$\([\w-]+\s/,e:/\)/,k:{built_in:"subst patsubst strip findstring filter filter-out sort word wordlist firstword lastword dir notdir suffix basename addsuffix addprefix join wildcard realpath abspath error warning shell origin flavor foreach if or and call eval file value"},c:[i]},n={b:"^"+e.UIR+"\\s*[:+?]?=",i:"\\n",rB:!0,c:[{b:"^"+e.UIR,e:"[:+?]?=",eE:!0}]},t={cN:"meta",b:/^\.PHONY:/,e:/$/,k:{"meta-keyword":".PHONY"},l:/[\.\w]+/},l={cN:"section",b:/^[^\s]+:/,e:/$/,c:[i]};return{aliases:["mk","mak"],k:"define endef undefine ifdef ifndef ifeq ifneq else endif include -include sinclude override export unexport private vpath",l:/[\w-]+/,c:[e.HCM,i,r,a,n,t,l]}}); \ No newline at end of file diff --git a/ElectronClient/app/gui/note-viewer/highlight/styles/atom-one-light.css b/ElectronClient/app/gui/note-viewer/highlight/styles/atom-one-light.css new file mode 100644 index 000000000..d5bd1d2a9 --- /dev/null +++ b/ElectronClient/app/gui/note-viewer/highlight/styles/atom-one-light.css @@ -0,0 +1,96 @@ +/* + +Atom One Light by Daniel Gamage +Original One Light Syntax theme from https://github.com/atom/one-light-syntax + +base: #fafafa +mono-1: #383a42 +mono-2: #686b77 +mono-3: #a0a1a7 +hue-1: #0184bb +hue-2: #4078f2 +hue-3: #a626a4 +hue-4: #50a14f +hue-5: #e45649 +hue-5-2: #c91243 +hue-6: #986801 +hue-6-2: #c18401 + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #383a42; + background: #fafafa; +} + +.hljs-comment, +.hljs-quote { + color: #a0a1a7; + font-style: italic; +} + +.hljs-doctag, +.hljs-keyword, +.hljs-formula { + color: #a626a4; +} + +.hljs-section, +.hljs-name, +.hljs-selector-tag, +.hljs-deletion, +.hljs-subst { + color: #e45649; +} + +.hljs-literal { + color: #0184bb; +} + +.hljs-string, +.hljs-regexp, +.hljs-addition, +.hljs-attribute, +.hljs-meta-string { + color: #50a14f; +} + +.hljs-built_in, +.hljs-class .hljs-title { + color: #c18401; +} + +.hljs-attr, +.hljs-variable, +.hljs-template-variable, +.hljs-type, +.hljs-selector-class, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-number { + color: #986801; +} + +.hljs-symbol, +.hljs-bullet, +.hljs-link, +.hljs-meta, +.hljs-selector-id, +.hljs-title { + color: #4078f2; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +.hljs-link { + text-decoration: underline; +} diff --git a/ElectronClient/app/gui/note-viewer/index.html b/ElectronClient/app/gui/note-viewer/index.html new file mode 100644 index 000000000..2f1a5969f --- /dev/null +++ b/ElectronClient/app/gui/note-viewer/index.html @@ -0,0 +1,125 @@ +<style> +body { + overflow: hidden; +} + +#content { + overflow-y: auto; + height: 100%; + padding-left: 10px; + padding-right: 10px; +} +</style> + +<div id="hlScriptContainer"></div> +<div id="content" ondragstart="return false;" ondrop="return false;"></div> + +<script> +const { ipcRenderer } = require('electron'); +const contentElement = document.getElementById('content'); + + +// ---------------------------------------------------------------------- +// Handle dynamically loading HLJS when a code element is present +// ---------------------------------------------------------------------- + +let hljsScriptAdded = false; +let hljsLoaded = false; + +function loadHljs(callback) { + hljsScriptAdded = true; + + const script = document.createElement('script'); + script.onload = function () { + hljsLoaded = true; + applyHljs(); + }; + script.src = 'highlight/highlight.pack.js'; + document.getElementById('hlScriptContainer').appendChild(script); + + const link = document.createElement('link'); + link.rel = 'stylesheet'; + // https://ace.c9.io/build/kitchen-sink.html + // https://highlightjs.org/static/demo/ + link.href = 'highlight/styles/atom-one-light.css'; + document.getElementById('hlScriptContainer').appendChild(link); +} + +function loadAndApplyHljs() { + var codeElements = document.getElementsByClassName('code'); + if (!codeElements.length) return; + + if (!hljsScriptAdded) { + this.loadHljs(); + return; + } + + // If HLJS is not loaded yet, no need to do anything. When it loads + // it will automatically apply the style to all the code elements. + if (hljsLoaded) applyHljs(codeElements); +} + +function applyHljs(codeElements) { + if (typeof codeElements === 'undefined') codeElements = document.getElementsByClassName('code'); + + for (var i = 0; i < codeElements.length; i++) { + hljs.highlightBlock(codeElements[i]); + } +} + +// ---------------------------------------------------------------------- +// / Handle dynamically loading HLJS when a code element is present +// ---------------------------------------------------------------------- + +ipcRenderer.on('setHtml', (event, html) => { + contentElement.innerHTML = html; + + loadAndApplyHljs(); + + // Remove the bullet from "ul" for checkbox lists and extra padding + const checkboxes = document.getElementsByClassName('checkbox'); + for (let i = 0; i < checkboxes.length; i++) { + const cb = checkboxes[i]; + const ul = cb.parentElement.parentElement; + if (!ul) { + console.warn('Unexpected layout for checkbox'); + continue; + } + ul.style.listStyleType = 'none'; + ul.style.paddingLeft = 0; + } +}); + +let ignoreNextScroll = false; +ipcRenderer.on('setPercentScroll', (event, percent) => { + ignoreNextScroll = true; + contentElement.scrollTop = percent * maxScrollTop(); +}); + +function maxScrollTop() { + return Math.max(0, contentElement.scrollHeight - contentElement.clientHeight); +} + +contentElement.addEventListener('scroll', function(e) { + if (ignoreNextScroll) { + ignoreNextScroll = false; + return; + } + const m = maxScrollTop(); + ipcRenderer.sendToHost('percentScroll', m ? contentElement.scrollTop / m : 0); +}); + +// Disable drag and drop otherwise it's possible to drop a URL +// on it and it will open in the view as a website. +document.addEventListener('drop', function(e) { + e.preventDefault(); + e.stopPropagation(); +}); +document.addEventListener('dragover', function(e) { + e.preventDefault(); + e.stopPropagation(); +}); +document.addEventListener('dragover', function(e) { + e.preventDefault(); +}); +</script> \ No newline at end of file diff --git a/ElectronClient/app/index.html b/ElectronClient/app/index.html new file mode 100644 index 000000000..ea72068d5 --- /dev/null +++ b/ElectronClient/app/index.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="UTF-8"> + <title>Joplin + + + + +
+ + + + \ No newline at end of file diff --git a/ElectronClient/app/locales/en_GB.json b/ElectronClient/app/locales/en_GB.json new file mode 100644 index 000000000..ca9be6581 --- /dev/null +++ b/ElectronClient/app/locales/en_GB.json @@ -0,0 +1 @@ +{"Give focus to next pane":"","Give focus to previous pane":"","Enter command line mode":"","Exit command line mode":"","Edit the selected note":"","Cancel the current command.":"","Exit the application.":"","Delete the currently selected note or notebook.":"","To delete a tag, untag the associated notes.":"","Please select the note or notebook to be deleted first.":"","Set a to-do as completed / not completed":"","[t]oggle [c]onsole between maximized/minimized/hidden/visible.":"","Search":"","[t]oggle note [m]etadata.":"","[M]ake a new [n]ote":"","[M]ake a new [t]odo":"","[M]ake a new note[b]ook":"","Copy ([Y]ank) the [n]ote to a notebook.":"","Move the note to a notebook.":"","Press Ctrl+D or type \"exit\" to exit the application":"","More than one item match \"%s\". Please narrow down your query.":"","No notebook selected.":"","No notebook has been specified.":"","Y":"","n":"","N":"","y":"","Cancelling background synchronisation... Please wait.":"","The command \"%s\" is only available in GUI mode":"","Missing required argument: %s":"","%s: %s":"","Your choice: ":"","Invalid answer: %s":"","Attaches the given file to the note.":"","Cannot find \"%s\".":"","Displays the given note.":"","Displays the complete information about note.":"","Gets or sets a config value. If [value] is not provided, it will show the value of [name]. If neither [name] nor [value] is provided, it will list the current configuration.":"","Also displays unset and hidden config variables.":"","%s = %s (%s)":"","%s = %s":"","Duplicates the notes matching to [notebook]. If no notebook is specified the note is duplicated in the current notebook.":"","Marks a to-do as done.":"","Note is not a to-do: \"%s\"":"","Edit note.":"","No text editor is defined. Please set it using `config editor `":"","No active notebook.":"","Note does not exist: \"%s\". Create it?":"","Starting to edit note. Close the editor to get back to the prompt.":"","Note has been saved.":"","Exits the application.":"","Exports Joplin data to the given directory. By default, it will export the complete database including notebooks, notes, tags and resources.":"","Exports only the given note.":"","Exports only the given notebook.":"","Displays a geolocation URL for the note.":"","Displays usage information.":"","Shortcuts are not available in CLI mode.":"","Type `help [command]` for more information about a command.":"","The possible commands are:":"","In any command, a note or notebook can be refered to by title or ID, or using the shortcuts `$n` or `$b` for, respectively, the currently selected note or notebook. `$c` can be used to refer to the currently selected item.":"","To move from one pane to another, press Tab or Shift+Tab.":"","Use the arrows and page up/down to scroll the lists and text areas (including this console).":"","To maximise/minimise the console, press \"TC\".":"","To enter command line mode, press \":\"":"","To exit command line mode, press ESCAPE":"","For the complete list of available keyboard shortcuts, type `help shortcuts`":"","Imports an Evernote notebook file (.enex file).":"","Do not ask for confirmation.":"","File \"%s\" will be imported into existing notebook \"%s\". Continue?":"","New notebook \"%s\" will be created and file \"%s\" will be imported into it. Continue?":"","Found: %d.":"","Created: %d.":"","Updated: %d.":"","Skipped: %d.":"","Resources: %d.":"","Tagged: %d.":"","Importing notes...":"","The notes have been imported: %s":"","Displays the notes in the current notebook. Use `ls /` to display the list of notebooks.":"","Displays only the first top notes.":"","Sorts the item by (eg. title, updated_time, created_time).":"","Reverses the sorting order.":"","Displays only the items of the specific type(s). Can be `n` for notes, `t` for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the to-dos, while `-ttd` would display notes and to-dos.":"","Either \"text\" or \"json\"":"","Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, TODO_CHECKED (for to-dos), TITLE":"","Please select a notebook first.":"","Creates a new notebook.":"","Creates a new note.":"","Notes can only be created within a notebook.":"","Creates a new to-do.":"","Moves the notes matching to [notebook].":"","Renames the given (note or notebook) to .":"","Deletes the given notebook.":"","Deletes the notebook without asking for confirmation.":"","Delete notebook \"%s\"?":"","Deletes the notes matching .":"","Deletes the notes without asking for confirmation.":"","%d notes match this pattern. Delete them?":"","Delete note?":"","Searches for the given in all the notes.":"","Sets the property of the given to the given [value].":"","Displays summary about the notes and notebooks.":"","Synchronises with remote storage.":"","Sync to provided target (defaults to sync.target config value)":"","Synchronisation is already in progress.":"","Lock file is already being hold. If you know that no synchronisation is taking place, you may delete the lock file at \"%s\" and resume the operation.":"","Authentication was not completed (did not receive an authentication token).":"","Synchronisation target: %s (%s)":"","Cannot initialize synchroniser.":"","Starting synchronisation...":"","Cancelling... Please wait.":""," can be \"add\", \"remove\" or \"list\" to assign or remove [tag] from [note], or to list the notes associated with [tag]. The command `tag list` can be used to list all the tags.":"","Invalid command: \"%s\"":""," can either be \"toggle\" or \"clear\". Use \"toggle\" to toggle the given to-do between completed and uncompleted state (If the target is a regular note it will be converted to a to-do). Use \"clear\" to convert the to-do back to a regular note.":"","Marks a to-do as non-completed.":"","Switches to [notebook] - all further operations will happen within this notebook.":"","Displays version information":"","%s %s (%s)":"","Enum":"","Type: %s.":"","Possible values: %s.":"","Default: %s":"","Possible keys/values:":"","Fatal error:":"","The application has been authorised - you may now close this browser tab.":"","The application has been successfully authorised.":"","Please open the following URL in your browser to authenticate the application. The application will create a directory in \"Apps/Joplin\" and will only read and write files in this directory. It will have no access to any files outside this directory nor to any other personal data. No data will be shared with any third party.":"","Search:":"","File":"","New note":"","New to-do":"","New notebook":"","Import Evernote notes":"","Evernote Export Files":"","Quit":"","Edit":"","Copy":"","Cut":"","Paste":"","Search in all the notes":"","Tools":"","Options":"","Help":"","Website and documentation":"","About Joplin":"","%s %s (%s, %s)":"","OK":"","Cancel":"","Back":"","New notebook \"%s\" will be created and file \"%s\" will be imported into it":"","Please create a notebook first.":"","Note title:":"","Please create a notebook first":"","To-do title:":"","Notebook title:":"","Add or remove tags:":"","Separate each tag by a comma.":"","Rename notebook:":"","Layout":"","Add or remove tags":"","Switch between note and to-do type":"","Delete":"","Delete notes?":"","No notes in here. Create one by clicking on \"New note\".":"","Unsupported link or message: %s":"","Attach file":"","Refresh":"","OneDrive Login":"","Import":"","Configuration":"","Delete notebook?":"","Remove this tag from all the notes?":"","Remove this search from the sidebar?":"","Rename":"","Synchronise":"","Notebooks":"","Tags":"","Searches":"","Usage: %s":"","Unknown flag: %s":"","File system":"","OneDrive":"","OneDrive Dev (For testing only)":"","Unknown log level: %s":"","Unknown level ID: %s":"","Cannot refresh token: authentication data is missing. Starting the synchronisation again may fix the problem.":"","Cannot access %s":"","Created local items: %d.":"","Updated local items: %d.":"","Created remote items: %d.":"","Updated remote items: %d.":"","Deleted local items: %d.":"","Deleted remote items: %d.":"","State: \"%s\".":"","Cancelling...":"","Completed: %s":"","Synchronisation is already in progress. State: %s":"","Conflicts":"","A notebook with this title already exists: \"%s\"":"","Notebooks cannot be named \"%s\", which is a reserved title.":"","Untitled":"","This note does not have geolocation information.":"","Cannot copy note to \"%s\" notebook":"","Cannot move note to \"%s\" notebook":"","File system synchronisation target directory":"","The path to synchronise with when file system synchronisation is enabled. See `sync.target`.":"","Text editor":"","The editor that will be used to open a note. If none is provided it will try to auto-detect the default editor.":"","Language":"","Theme":"","Light":"","Dark":"","Show uncompleted todos on top of the lists":"","Save geo-location with notes":"","Synchronisation interval":"","Disabled":"","%d minutes":"","%d hour":"","%d hours":"","Automatically update the application":"","Show advanced options":"","Synchronisation target":"","The target to synchonise to. If synchronising with the file system, set `sync.2.path` to specify the target directory.":"","Invalid option value: \"%s\". Possible values are: %s.":"","Sync status (synced items / total items)":"","%s: %d/%d":"","Total: %d/%d":"","Conflicted: %d":"","To delete: %d":"","Folders":"","%s: %d notes":"","There are currently no notes. Create one by clicking on the (+) button.":"","Delete these notes?":"","Log":"","Status":"","Export Debug Report":"","Move to notebook...":"","Move %d notes to notebook \"%s\"?":"","Cancel synchronisation":"","The notebook could not be saved: %s":"","Edit notebook":"","This note has been modified:":"","Save changes":"","Discard changes":"","Unsupported image type: %s":"","Attach image":"","Attach any other file":"","Delete note":"","Convert to regular note":"","Convert to todo":"","Hide metadata":"","Show metadata":"","View location on map":"","Delete notebook":"","Login with OneDrive":"","Click on the (+) button to create a new note or notebook. Click on the side menu to access your existing notebooks.":"","You currently have no notebook. Create one by clicking on (+) button.":"","Welcome":""} \ No newline at end of file diff --git a/ElectronClient/app/locales/fr_FR.json b/ElectronClient/app/locales/fr_FR.json new file mode 100644 index 000000000..689871c80 --- /dev/null +++ b/ElectronClient/app/locales/fr_FR.json @@ -0,0 +1 @@ +{"Give focus to next pane":"Activer le volet suivant","Give focus to previous pane":"Activer le volet précédent","Enter command line mode":"Démarrer le mode de ligne de commande","Exit command line mode":"Sortir du mode de ligne de commande","Edit the selected note":"Éditer la note sélectionnée","Cancel the current command.":"Annuler la commande en cours.","Exit the application.":"Quitter le logiciel.","Delete the currently selected note or notebook.":"Supprimer la note ou carnet sélectionné.","To delete a tag, untag the associated notes.":"Pour supprimer une vignette, enlever là des notes associées.","Please select the note or notebook to be deleted first.":"Veuillez d'abord sélectionner un carnet.","Set a to-do as completed / not completed":"Marquer une tâches comme complétée / non-complétée","[t]oggle [c]onsole between maximized/minimized/hidden/visible.":"Maximiser, minimiser, cacher ou rendre visible la console.","Search":"Chercher","[t]oggle note [m]etadata.":"Afficher/Cacher les métadonnées des notes.","[M]ake a new [n]ote":"Créer une nouvelle note","[M]ake a new [t]odo":"Créer une nouvelle tâche","[M]ake a new note[b]ook":"Créer un nouveau carnet","Copy ([Y]ank) the [n]ote to a notebook.":"Copier la note dans un autre carnet.","Move the note to a notebook.":"Déplacer la note vers un carnet.","Press Ctrl+D or type \"exit\" to exit the application":"Appuyez sur Ctrl+D ou tapez \"exit\" pour sortir du logiciel","More than one item match \"%s\". Please narrow down your query.":"Plus d'un objet correspond à \"%s\". Veuillez préciser votre requête.","No notebook selected.":"Aucun carnet n'est sélectionné.","No notebook has been specified.":"Aucun carnet n'est spécifié.","Y":"O","n":"n","N":"N","y":"o","Cancelling background synchronisation... Please wait.":"Annulation de la synchronisation... Veuillez patienter.","The command \"%s\" is only available in GUI mode":"La commande \"%s\" est disponible uniquement en mode d'interface graphique","Missing required argument: %s":"Paramètre requis manquant : %s","%s: %s":"%s : %s","Your choice: ":"Votre choix : ","Invalid answer: %s":"Réponse invalide : %s","Attaches the given file to the note.":"Joindre le fichier fourni à la note.","Cannot find \"%s\".":"Impossible de trouver \"%s\".","Displays the given note.":"Affiche la note.","Displays the complete information about note.":"Affiche tous les détails de la note.","Gets or sets a config value. If [value] is not provided, it will show the value of [name]. If neither [name] nor [value] is provided, it will list the current configuration.":"Obtient ou modifie une valeur de configuration. Si la [valeur] n'est pas fournie, la valeur de [nom] est affichée. Si ni le [nom] ni la [valeur] ne sont fournis, la configuration complète est affichée.","Also displays unset and hidden config variables.":"Afficher également les variables cachées.","%s = %s (%s)":"%s = %s (%s)","%s = %s":"%s = %s","Duplicates the notes matching to [notebook]. If no notebook is specified the note is duplicated in the current notebook.":"Copier les notes correspondant à vers [carnet]. Si aucun carnet n'est spécifié, la note est dupliquée sur place.","Marks a to-do as done.":"Marquer la tâche comme complétée.","Note is not a to-do: \"%s\"":"La note n'est pas une tâche : \"%s\"","Edit note.":"Éditer la note.","No text editor is defined. Please set it using `config editor `":"Aucun éditeur de texte n'est défini. Veuillez le définir en utilisant la commande `config editor `","No active notebook.":"Aucun carnet actif.","Note does not exist: \"%s\". Create it?":"Cette note n'existe pas : \"%s\". La créer ?","Starting to edit note. Close the editor to get back to the prompt.":"Édition de la note en cours. Fermez l'éditeur de texte pour retourner à l'invite de commande.","Note has been saved.":"La note a été enregistrée.","Exits the application.":"Quitter le logiciel.","Exports Joplin data to the given directory. By default, it will export the complete database including notebooks, notes, tags and resources.":"Exporter les données de Joplin vers le dossier fourni. Par défaut, la base de donnée complète sera exportée, y compris les carnets, notes, tags et resources.","Exports only the given note.":"Exporter uniquement la note spécifiée.","Exports only the given notebook.":"Exporter uniquement le carnet spécifié.","Displays a geolocation URL for the note.":"Afficher l'URL de l'emplacement de la note.","Displays usage information.":"Affiche les informations d'utilisation.","Shortcuts are not available in CLI mode.":"Les raccourcis ne sont pas disponible en mode de ligne de commande.","Type `help [command]` for more information about a command.":"Tapez `help [command]` pour plus d'information sur une commande.","The possible commands are:":"Les commandes possibles sont :","In any command, a note or notebook can be refered to by title or ID, or using the shortcuts `$n` or `$b` for, respectively, the currently selected note or notebook. `$c` can be used to refer to the currently selected item.":"Dans une commande, une note ou carnet peut être référé par titre ou identifiant, ou en utilisant les raccourcis `$n` et `$b` pour, respectivement, la note sélectionnée et le carnet sélectionné. `$c` peut être utilisé pour faire référence à l'objet sélectionné en cours.","To move from one pane to another, press Tab or Shift+Tab.":"Pour aller d'un volet à l'autre, pressez Tab ou Maj+Tab.","Use the arrows and page up/down to scroll the lists and text areas (including this console).":"Utilisez les touches fléchées et page précédente/suivante pour faire défiler les listes et zones de texte (y compris cette console).","To maximise/minimise the console, press \"TC\".":"Pour maximiser ou minimiser la console, pressez \"TC\".","To enter command line mode, press \":\"":"Pour démarrer le mode ligne de commande, pressez \":\"","To exit command line mode, press ESCAPE":"Pour sortir du mode ligne de commande, pressez ECHAP","For the complete list of available keyboard shortcuts, type `help shortcuts`":"Pour la liste complète des raccourcis disponibles, tapez `help shortcuts`","Imports an Evernote notebook file (.enex file).":"Importer un carnet Evernote (fichier .enex).","Do not ask for confirmation.":"Ne pas demander de confirmation.","File \"%s\" will be imported into existing notebook \"%s\". Continue?":"Le fichier \"%s\" va être importé dans le carnet existant \"%s\". Continuer ?","New notebook \"%s\" will be created and file \"%s\" will be imported into it. Continue?":"Un nouveau carnet \"%s\" va être créé et le fichier \"%s\" va être importé dedans. Continuer ?","Found: %d.":"Trouvés : %d.","Created: %d.":"Créés : %d.","Updated: %d.":"Mis à jour : %d.","Skipped: %d.":"Ignorés : %d.","Resources: %d.":"Ressources : %d.","Tagged: %d.":"Étiquettes : %d.","Importing notes...":"Importation des notes...","The notes have been imported: %s":"Les notes ont été importées : %s","Displays the notes in the current notebook. Use `ls /` to display the list of notebooks.":"Affiche les notes dans le carnet. Utilisez `ls /` pour afficher la liste des carnets.","Displays only the first top notes.":"Affiche uniquement les premières notes.","Sorts the item by (eg. title, updated_time, created_time).":"Trier les notes par (par exemple, title, updated_time, created_time).","Reverses the sorting order.":"Inverser l'ordre.","Displays only the items of the specific type(s). Can be `n` for notes, `t` for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the to-dos, while `-ttd` would display notes and to-dos.":"Affiche uniquement les notes du ou des types spécifiés. Le type peut-être `n` pour les notes, `t` pour les tâches (par exemple, `-tt` affiche uniquement les tâches, tandis que `-ttd` affiche les notes et les tâches).","Either \"text\" or \"json\"":"Soit \"text\" soit \"json\"","Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, TODO_CHECKED (for to-dos), TITLE":"Utilise le format de liste longue. Le format est ID, NOMBRE_DE_NOTES (pour les carnets), DATE, TACHE_TERMINE (pour les tâches), TITRE","Please select a notebook first.":"Veuillez d'abord sélectionner un carnet.","Creates a new notebook.":"Créer un carnet.","Creates a new note.":"Créer une note.","Notes can only be created within a notebook.":"Les notes ne peuvent être créées que dans un carnet.","Creates a new to-do.":"Créer une nouvelle tâche.","Moves the notes matching to [notebook].":"Déplacer les notes correspondant à vers [notebook].","Renames the given (note or notebook) to .":"Renommer l'objet (note ou carnet) en .","Deletes the given notebook.":"Supprimer le carnet.","Deletes the notebook without asking for confirmation.":"Supprimer le carnet sans demander la confirmation.","Delete notebook \"%s\"?":"Supprimer le carnet \"%s\" ?","Deletes the notes matching .":"Supprimer les notes correspondants à .","Deletes the notes without asking for confirmation.":"Supprimer les notes sans demander la confirmation.","%d notes match this pattern. Delete them?":"%d notes correspondent à ce motif. Les supprimer ?","Delete note?":"Supprimer la note ?","Searches for the given in all the notes.":"Chercher le motif dans toutes les notes.","Sets the property of the given to the given [value].":"Assigner la valeur [value] à la propriété de la donnée.","Displays summary about the notes and notebooks.":"Afficher un résumé des notes et carnets.","Synchronises with remote storage.":"Synchroniser les notes et carnets.","Sync to provided target (defaults to sync.target config value)":"Synchroniser avec la cible donnée (par défaut, la valeur de configuration `sync.target`).","Synchronisation is already in progress.":"La synchronisation est déjà en cours.","Lock file is already being hold. If you know that no synchronisation is taking place, you may delete the lock file at \"%s\" and resume the operation.":"La synchronisation est déjà en cours ou ne s'est pas interrompue correctement. Si vous savez qu'aucune autre synchronisation est en cours, vous pouvez supprimer le fichier \"%s\" pour reprendre l'opération.","Authentication was not completed (did not receive an authentication token).":"Impossible d'autoriser le logiciel (jeton d'identification non-reçu).","Synchronisation target: %s (%s)":"Cible de la synchronisation : %s (%s)","Cannot initialize synchroniser.":"Impossible d'initialiser la synchronisation.","Starting synchronisation...":"Commencement de la synchronisation...","Cancelling... Please wait.":"Annulation... Veuillez attendre."," can be \"add\", \"remove\" or \"list\" to assign or remove [tag] from [note], or to list the notes associated with [tag]. The command `tag list` can be used to list all the tags.":" peut être \"add\", \"remove\" ou \"list\" pour assigner ou enlever l'étiquette [tag] de la [note], our pour lister les notes associées avec l'étiquette [tag]. La commande `tag list` peut être utilisée pour lister les étiquettes.","Invalid command: \"%s\"":"Commande invalide : \"%s\""," can either be \"toggle\" or \"clear\". Use \"toggle\" to toggle the given to-do between completed and uncompleted state (If the target is a regular note it will be converted to a to-do). Use \"clear\" to convert the to-do back to a regular note.":"Gère le status des tâches. peut être \"toggle\" ou \"clear\". Utilisez \"toggle\" pour basculer la tâche entre le status terminé et non-terminé (Si la cible est une note, elle sera convertie en tâche). Utilisez \"clear\" pour convertir la tâche en note.","Marks a to-do as non-completed.":"Marquer une tâche comme non-complétée.","Switches to [notebook] - all further operations will happen within this notebook.":"Changer de carnet - toutes les opérations à venir se feront dans ce carnet.","Displays version information":"Affiche les informations de version","%s %s (%s)":"%s %s (%s)","Enum":"Enum","Type: %s.":"Type : %s.","Possible values: %s.":"Valeurs possibles : %s.","Default: %s":"Défaut : %s","Possible keys/values:":"Clefs/Valeurs possibles :","Fatal error:":"Erreur fatale :","The application has been authorised - you may now close this browser tab.":"Le logiciel a été autorisé. Vous pouvez maintenant fermer cet onglet.","The application has been successfully authorised.":"Le logiciel a été autorisé.","Please open the following URL in your browser to authenticate the application. The application will create a directory in \"Apps/Joplin\" and will only read and write files in this directory. It will have no access to any files outside this directory nor to any other personal data. No data will be shared with any third party.":"Veuillez ouvrir le lien ci-dessous dans votre navigateur pour authentifier le logiciel. Joplin va créer un répertoire \"Apps/Joplin\" et lire/écrira des fichiers uniquement dans ce répertoire. Le logiciel n'aura pas d'accès à aucun fichier en dehors de ce répertoire, ni à d'autres données personnelles. Aucune donnée ne sera partagé avec aucun tier.","Search:":"Recherche :","File":"Fichier","New note":"Nouvelle note","New to-do":"Nouvelle tâche","New notebook":"Nouveau carnet","Import Evernote notes":"Importer notes d'Evernote","Evernote Export Files":"Fichiers d'export Evernote","Quit":"Quitter","Edit":"Édition","Copy":"Copier","Cut":"Couper","Paste":"Coller","Search in all the notes":"Chercher dans toutes les notes","Tools":"Outils","Options":"Options","Help":"Aide","Website and documentation":"Documentation en ligne","About Joplin":"A propos de Joplin","%s %s (%s, %s)":"%s %s (%s, %s)","OK":"OK","Cancel":"Annulation","Back":"Retour","New notebook \"%s\" will be created and file \"%s\" will be imported into it":"Un nouveau carnet \"%s\" va être créé et le fichier \"%s\" va être importé dedans","Please create a notebook first.":"Veuillez d'abord sélectionner un carnet.","Note title:":"Titre de la note :","Please create a notebook first":"Veuillez d'abord créer un carnet d'abord","To-do title:":"Titre de la tâche :","Notebook title:":"Titre du carnet :","Add or remove tags:":"Modifier les étiquettes :","Separate each tag by a comma.":"Séparez chaque étiquette par une virgule.","Rename notebook:":"Renommer le carnet :","Layout":"Disposition","Add or remove tags":"Gérer les étiquettes","Switch between note and to-do type":"Alterner entre note et tâche","Delete":"Supprimer","Delete notes?":"Supprimer les notes ?","No notes in here. Create one by clicking on \"New note\".":"Pas de notes ici. Créez-en une en pressant le bouton \"Nouvelle note\".","Unsupported link or message: %s":"Lien ou message non géré : %s","Attach file":"Attacher un fichier","Refresh":"Rafraîchir","OneDrive Login":"Connexion OneDrive","Import":"Importer","Configuration":"Configuration","Delete notebook?":"Supprimer le carnet ?","Remove this tag from all the notes?":"Enlever cette étiquette de toutes les notes ?","Remove this search from the sidebar?":"Enlever cette recherche de la barre latérale ?","Rename":"Renommer","Synchronise":"Synchroniser","Notebooks":"Carnets","Tags":"Étiquettes","Searches":"Recherches","Usage: %s":"Utilisation : %s","Unknown flag: %s":"Paramètre inconnu : %s","File system":"Système de fichier","OneDrive":"OneDrive","OneDrive Dev (For testing only)":"OneDrive Dév (Pour tester uniquement)","Unknown log level: %s":"Paramètre inconnu : %s","Unknown level ID: %s":"Paramètre inconnu : %s","Cannot refresh token: authentication data is missing. Starting the synchronisation again may fix the problem.":"Impossible de rafraîchir la connexion à OneDrive. Démarrez la synchronisation à nouveau pour corriger le problème.","Cannot access %s":"Impossible d'accéder à %s","Created local items: %d.":"Objets créés localement : %d.","Updated local items: %d.":"Objets mis à jour localement : %d.","Created remote items: %d.":"Objets distants créés : %d.","Updated remote items: %d.":"Objets distants mis à jour : %d.","Deleted local items: %d.":"Objets supprimés localement : %d.","Deleted remote items: %d.":"Objets distants supprimés : %d.","State: \"%s\".":"État : \"%s\".","Cancelling...":"Annulation...","Completed: %s":"Terminé : %s","Synchronisation is already in progress. State: %s":"La synchronisation est déjà en cours. État : %s","Conflicts":"Conflits","A notebook with this title already exists: \"%s\"":"Un carnet avec ce titre existe déjà : \"%s\"","Notebooks cannot be named \"%s\", which is a reserved title.":"Les carnets ne peuvent être nommés \"%s\" car c'est un nom réservé.","Untitled":"Sans titre","This note does not have geolocation information.":"Cette note n'a pas d'information d'emplacement.","Cannot copy note to \"%s\" notebook":"Impossible de copier la note vers le carnet \"%s\"","Cannot move note to \"%s\" notebook":"Impossible de déplacer la note vers le carnet \"%s\"","File system synchronisation target directory":"Cible de la synchronisation sur le disque dur","The path to synchronise with when file system synchronisation is enabled. See `sync.target`.":"Le chemin du répertoire avec lequel synchroniser lorsque la synchronisation par système de fichier est activée. Voir `sync.target`.","Text editor":"Éditeur de texte","The editor that will be used to open a note. If none is provided it will try to auto-detect the default editor.":"L'éditeur de texte pour ouvrir et modifier les notes. Si aucun n'est spécifié, il sera détecté automatiquement.","Language":"Langue","Theme":"Apparence","Light":"Clair","Dark":"Sombre","Show uncompleted todos on top of the lists":"Tâches non-terminées en haut des listes","Save geo-location with notes":"Enregistrer l'emplacement avec les notes","Synchronisation interval":"Intervalle de synchronisation","Disabled":"Désactivé","%d minutes":"%d minutes","%d hour":"%d heure","%d hours":"%d heures","Automatically update the application":"Mettre à jour le logiciel automatiquement","Show advanced options":"Montrer les options avancées","Synchronisation target":"Cible de la synchronisation","The target to synchonise to. If synchronising with the file system, set `sync.2.path` to specify the target directory.":"La cible avec laquelle synchroniser. Pour synchroniser avec le système de fichier, veuillez spécifier le répertoire avec `sync.2.path`.","Invalid option value: \"%s\". Possible values are: %s.":"Option invalide: \"%s\". Les valeurs possibles sont : %s.","Sync status (synced items / total items)":"Status de la synchronisation (objets synchro. / total)","%s: %d/%d":"%s: %d/%d","Total: %d/%d":"Total : %d/%d","Conflicted: %d":"Conflits : %d","To delete: %d":"A supprimer : %d","Folders":"Carnets","%s: %d notes":"%s : %d notes","There are currently no notes. Create one by clicking on the (+) button.":"Ce carnet ne contient aucune note. Créez-en une en appuyant sur le bouton (+).","Delete these notes?":"Supprimer ces notes ?","Log":"Journal","Status":"État","Export Debug Report":"Exporter rapport de débogage","Move to notebook...":"Déplacer la note vers carnet...","Move %d notes to notebook \"%s\"?":"Déplacer %d notes vers carnet \"%s\" ?","Cancel synchronisation":"Annuler synchronisation","The notebook could not be saved: %s":"Ce carnet n'a pas pu être sauvegardé : %s","Edit notebook":"Éditer le carnet","This note has been modified:":"Cette note a été modifiée :","Save changes":"Enregistrer les changements","Discard changes":"Ignorer les changements","Unsupported image type: %s":"Type d'image non géré : %s","Attach image":"Joindre une image ou photo","Attach any other file":"Joindre un fichier","Delete note":"Supprimer la note","Convert to regular note":"Convertir en note","Convert to todo":"Convertir en tâche","Hide metadata":"Cacher les métadonnées","Show metadata":"Afficher les métadonnées","View location on map":"Voir l'emplacement sur la carte","Delete notebook":"Supprimer le carnet","Login with OneDrive":"Se connecter à OneDrive","Click on the (+) button to create a new note or notebook. Click on the side menu to access your existing notebooks.":"Appuyez sur le bouton (+) pour créer une nouvelle note ou carnet. Ouvrez le menu latéral pour accéder à vos carnets.","You currently have no notebook. Create one by clicking on (+) button.":"Vous n'avez pour l'instant pas de carnets. Créez-en un en pressant le bouton (+).","Welcome":"Bienvenue"} \ No newline at end of file diff --git a/ElectronClient/app/locales/index.js b/ElectronClient/app/locales/index.js new file mode 100644 index 000000000..86d824b8a --- /dev/null +++ b/ElectronClient/app/locales/index.js @@ -0,0 +1,4 @@ +var locales = {}; +locales['en_GB'] = require('./en_GB.json'); +locales['fr_FR'] = require('./fr_FR.json'); +module.exports = { locales: locales }; \ No newline at end of file diff --git a/ElectronClient/app/main-html.js b/ElectronClient/app/main-html.js new file mode 100644 index 000000000..5d0121644 --- /dev/null +++ b/ElectronClient/app/main-html.js @@ -0,0 +1,54 @@ +// This is the initialization for the Electron RENDERER process + +// Make it possible to require("/lib/...") without specifying full path +require('app-module-path').addPath(__dirname); + +const { app } = require('./app.js'); +const { Folder } = require('lib/models/folder.js'); +const { Resource } = require('lib/models/resource.js'); +const { BaseItem } = require('lib/models/base-item.js'); +const { Note } = require('lib/models/note.js'); +const { Tag } = require('lib/models/tag.js'); +const { NoteTag } = require('lib/models/note-tag.js'); +const { Setting } = require('lib/models/setting.js'); +const { Logger } = require('lib/logger.js'); +const { FsDriverNode } = require('lib/fs-driver-node.js'); +const { shimInit } = require('lib/shim-init-node.js'); +const { bridge } = require('electron').remote.require('./bridge'); + +const fsDriver = new FsDriverNode(); +Logger.fsDriver_ = fsDriver; +Resource.fsDriver_ = fsDriver; + +// That's not good, but it's to avoid circular dependency issues +// in the BaseItem class. +BaseItem.loadClass('Note', Note); +BaseItem.loadClass('Folder', Folder); +BaseItem.loadClass('Resource', Resource); +BaseItem.loadClass('Tag', Tag); +BaseItem.loadClass('NoteTag', NoteTag); + +Setting.setConstant('appId', 'net.cozic.joplin-desktop'); +Setting.setConstant('appType', 'desktop'); + +// Disable drag and drop of links inside application (which would +// open it as if the whole app was a browser) +document.addEventListener('dragover', event => event.preventDefault()); +document.addEventListener('drop', event => event.preventDefault()); + +// Disable middle-click (which would open a new browser window, but we don't want this) +document.addEventListener('auxclick', event => event.preventDefault()); + +// Each link (rendered as a button or list item) has its own custom click event +// so disable the default. In particular this will disable Ctrl+Clicking a link +// which would open a new browser window. +document.addEventListener('click', (event) => event.preventDefault()); + +shimInit(); + +app().start(bridge().processArgv()).then(() => { + require('./gui/Root.min.js'); +}).catch((error) => { + console.error('Fatal error:'); + console.error(error); +}); \ No newline at end of file diff --git a/ElectronClient/app/main.js b/ElectronClient/app/main.js new file mode 100644 index 000000000..08e2140c3 --- /dev/null +++ b/ElectronClient/app/main.js @@ -0,0 +1,38 @@ +// This is the basic initialization for the Electron MAIN process + +// Make it possible to require("/lib/...") without specifying full path +require('app-module-path').addPath(__dirname); + +const electronApp = require('electron').app; +const { ElectronAppWrapper } = require('./ElectronAppWrapper'); +const { initBridge } = require('./bridge'); +const { Logger } = require('lib/logger.js'); +const { FsDriverNode } = require('lib/fs-driver-node.js'); + +process.on('unhandledRejection', (reason, p) => { + console.error('Unhandled promise rejection', p, 'reason:', reason); + process.exit(1); +}); + +// Flags are parsed properly in BaseApplication, however it's better to have +// the env as early as possible to enable debugging capabilities. +function envFromArgs(args) { + if (!args) return 'prod'; + const envIndex = args.indexOf('--env'); + const devIndex = args.indexOf('dev'); + if (envIndex === devIndex - 1) return 'dev'; + return 'prod'; +} + +Logger.fsDriver_ = new FsDriverNode(); + +const env = envFromArgs(process.argv); + +const wrapper = new ElectronAppWrapper(electronApp, env); + +initBridge(wrapper); + +wrapper.start().catch((error) => { + console.error('Electron App fatal error:'); + console.error(error); +}); \ No newline at end of file diff --git a/ElectronClient/app/package-lock.json b/ElectronClient/app/package-lock.json new file mode 100644 index 000000000..c055dcca8 --- /dev/null +++ b/ElectronClient/app/package-lock.json @@ -0,0 +1,5358 @@ +{ + "name": "Joplin", + "version": "0.10.25", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "7zip-bin": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-2.2.7.tgz", + "integrity": "sha512-+rr4OgeTNrLuJAf09o3USdttEYiXvZshWMkhD6wR9v1ieXH0JM1Q2yT41/cJuJcqiPpSXlM/g3aR+Y5MWQdr0Q==", + "dev": true, + "requires": { + "7zip-bin-win": "2.1.1" + } + }, + "7zip-bin-win": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/7zip-bin-win/-/7zip-bin-win-2.1.1.tgz", + "integrity": "sha512-6VGEW7PXGroTsoI2QW3b0ea95HJmbVBHvfANKLLMzSzFA1zKqVX5ybNuhmeGpf6vA0x8FJTt6twpprDANsY5WQ==", + "optional": true + }, + "@types/node": { + "version": "7.0.46", + "resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.46.tgz", + "integrity": "sha512-u+JAi1KtmaUoU/EHJkxoiuvzyo91FCE41Z9TZWWcOUU3P8oUdlDLdrGzCGWySPgbRMD17B0B+1aaJLYI9egQ6A==", + "dev": true + }, + "ajv": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz", + "integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "app-module-path": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", + "integrity": "sha1-ZBqlXft9am8KgUHEucCqULbCTdU=" + }, + "app-package-builder": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/app-package-builder/-/app-package-builder-1.5.0.tgz", + "integrity": "sha512-CmmmXq543Ru7TEcAQShmmI9Z0NgKZ54KOR3BGM+LTEw/v2VjgCQ5qrkkoCA+0LaYgJfPFg/40PGMHnDaAZ6g4w==", + "dev": true, + "requires": { + "bluebird-lst": "1.0.5", + "builder-util": "3.2.2", + "builder-util-runtime": "3.2.0", + "fs-extra-p": "4.4.4", + "int64-buffer": "0.1.9", + "rabin-bindings": "1.7.3" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "dev": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "requires": { + "sprintf-js": "1.0.3" + }, + "dependencies": { + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + } + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "optional": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true, + "optional": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + }, + "asar-integrity": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asar-integrity/-/asar-integrity-0.2.3.tgz", + "integrity": "sha512-c+oMuxlpKRDv9Kv6WdjbnkySfSYATAmW+cvy8NIdMg9twY9RMvSdvOoPssroWlTpSra1qX9vLew2ROpV4jQm7w==", + "dev": true, + "requires": { + "bluebird-lst": "1.0.5", + "fs-extra-p": "4.4.4" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", + "dev": true, + "optional": true + }, + "async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-polyfill": "6.26.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "chokidar": "1.7.0", + "commander": "2.11.0", + "convert-source-map": "1.5.0", + "fs-readdir-recursive": "1.1.0", + "glob": "7.1.2", + "lodash": "4.17.4", + "output-file-sync": "1.1.2", + "path-is-absolute": "1.0.1", + "slash": "1.0.0", + "source-map": "0.5.7", + "v8flags": "2.1.1" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "dev": true, + "requires": { + "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.9", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.8", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "babel-generator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", + "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "dev": true, + "requires": { + "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-react-jsx": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", + "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "esutils": "2.0.2" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-flow": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", + "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", + "dev": true + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", + "dev": true + }, + "babel-plugin-transform-flow-strip-types": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", + "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", + "dev": true, + "requires": { + "babel-plugin-syntax-flow": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-display-name": { + "version": "6.25.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", + "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", + "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", + "dev": true, + "requires": { + "babel-helper-builder-react-jsx": "6.26.0", + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx-self": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", + "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-react-jsx-source": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", + "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-runtime": "6.26.0" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.5.1", + "regenerator-runtime": "0.10.5" + }, + "dependencies": { + "core-js": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", + "dev": true + }, + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", + "dev": true + } + } + }, + "babel-preset-flow": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", + "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", + "dev": true, + "requires": { + "babel-plugin-transform-flow-strip-types": "6.22.0" + } + }, + "babel-preset-react": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", + "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", + "dev": true, + "requires": { + "babel-plugin-syntax-jsx": "6.18.0", + "babel-plugin-transform-react-display-name": "6.25.0", + "babel-plugin-transform-react-jsx": "6.24.1", + "babel-plugin-transform-react-jsx-self": "6.22.0", + "babel-plugin-transform-react-jsx-source": "6.22.0", + "babel-preset-flow": "6.23.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.1", + "home-or-tmp": "2.0.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + }, + "dependencies": { + "core-js": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", + "dev": true + } + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "2.5.1", + "regenerator-runtime": "0.11.0" + }, + "dependencies": { + "core-js": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=", + "dev": true + } + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "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": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "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.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", + "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "binary-extensions": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", + "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=", + "dev": true, + "optional": true + }, + "bindings": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==", + "dev": true + }, + "bl": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.1.tgz", + "integrity": "sha1-ysMo977kVzDUBLaSID/LWQ4XLV4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "bluebird-lst": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.5.tgz", + "integrity": "sha512-Ey0bDNys5qpYPhZ/oQ9vOEvD0TYQDTILMXWP2iGfvMg7rSDde+oV4aQQgqRH+CvBFNz2BSDQnPGMUl6LKBUUQA==", + "requires": { + "bluebird": "3.5.1" + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + }, + "boxen": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.2.2.tgz", + "integrity": "sha1-Px1AMsMP/qnUsCwyLq8up0HcvOU=", + "dev": true, + "requires": { + "ansi-align": "2.0.0", + "camelcase": "4.1.0", + "chalk": "2.3.0", + "cli-boxes": "1.0.0", + "string-width": "2.1.1", + "term-size": "1.2.0", + "widest-line": "1.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "brace": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/brace/-/brace-0.10.0.tgz", + "integrity": "sha1-7e9OubCSi6HuX3F//BV3SabdXXY=", + "requires": { + "w3c-blob": "0.0.1" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "optional": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "builder-util": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-3.2.2.tgz", + "integrity": "sha512-4t/EtpYYp5wNaNlI4cgKbHEY/oNtnKtuEn201DNcJlgLkoV8RrwSOo6RJbDOKY+RTf0IVmbEZ2ZHbyy2/KGKRQ==", + "dev": true, + "requires": { + "7zip-bin": "2.2.7", + "bluebird-lst": "1.0.5", + "builder-util-runtime": "3.2.0", + "chalk": "2.3.0", + "debug": "3.1.0", + "fs-extra-p": "4.4.4", + "ini": "1.3.4", + "is-ci": "1.0.10", + "js-yaml": "3.10.0", + "lazy-val": "1.0.2", + "node-emoji": "1.8.1", + "semver": "5.4.1", + "source-map-support": "0.5.0", + "stat-mode": "0.2.2", + "temp-file": "2.0.3", + "tunnel-agent": "0.6.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", + "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==", + "dev": true, + "requires": { + "source-map": "0.6.1" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "builder-util-runtime": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-3.2.0.tgz", + "integrity": "sha512-VRvyyLiZZSBjcUTqEsHlBJSK0s6uVQChO7kbmVeU6QmSJ7TtsotNQELO6lbahwZMAQ4Z/haCKhlLBDdhW+3aqA==", + "dev": true, + "requires": { + "bluebird-lst": "1.0.5", + "debug": "3.1.0", + "fs-extra-p": "4.4.4", + "sax": "1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "caw": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/caw/-/caw-2.0.1.tgz", + "integrity": "sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==", + "requires": { + "get-proxy": "2.1.0", + "isurl": "1.0.0", + "tunnel-agent": "0.6.0", + "url-to-options": "1.0.1" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "dev": true, + "optional": true, + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "chownr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.0.1.tgz", + "integrity": "sha1-4qdQQqlVGQi+vSW4Uj1fl2nXkYE=" + }, + "chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", + "dev": true + }, + "ci-info": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.1.1.tgz", + "integrity": "sha512-vHDDF/bP9RYpTWtUhpJRhCFdvvp3iDWvEbuDbWgvjUrNGV1MXJrE0MPcwGtEled04m61iwdBLUIHZtDgzWS4ZQ==", + "dev": true + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "color": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color/-/color-2.0.1.tgz", + "integrity": "sha512-ubUCVVKfT7r2w2D3qtHakj8mbmKms+tThR8gI8zEYCbUBl8/voqFGt3kgBqGwXAopgXybnkuOq+qMYCRrp4cXw==", + "requires": { + "color-convert": "1.9.1", + "color-string": "1.5.2" + } + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.2.tgz", + "integrity": "sha1-JuRYFLw8mny9Z1FkikFDRRSnc6k=", + "requires": { + "color-name": "1.1.3", + "simple-swizzle": "0.2.2" + } + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + } + }, + "config-chain": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", + "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "requires": { + "ini": "1.3.4", + "proto-list": "1.2.4" + } + }, + "configstore": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.1.tgz", + "integrity": "sha512-5oNkD/L++l0O6xGXxb1EWS7SivtjfGQlRyxJsYgE0Z495/L81e2h4/d3r969hoPXuFItzNOKMtsXgYG4c7dYvw==", + "dev": true, + "requires": { + "dot-prop": "4.2.0", + "graceful-fs": "4.1.11", + "make-dir": "1.1.0", + "unique-string": "1.0.0", + "write-file-atomic": "2.3.0", + "xdg-basedir": "3.0.0" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "core-js": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "4.1.1", + "shebang-command": "1.2.0", + "which": "1.3.0" + } + }, + "crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "dev": true, + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "1.0.0" + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + }, + "deep-extend": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true + }, + "deep-is": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.2.tgz", + "integrity": "sha1-nO1l6gvAsJ9CptecGxkD+dkTzBg=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "dev": true + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "detect-libc": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-0.2.0.tgz", + "integrity": "sha1-R/31ZzSKF+wl/L8LnkRjSKdvn7U=" + }, + "dmg-builder": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-2.1.6.tgz", + "integrity": "sha512-5gYVdJJPnATbnMAv/ufMd2qqbb8wWLyl77am1EKUL+5ZZjCkujps1inHcq8+s+G/iJJqGn1ko4I7RBvhd2AV/w==", + "dev": true, + "requires": { + "bluebird-lst": "1.0.5", + "builder-util": "3.2.2", + "debug": "3.1.0", + "fs-extra-p": "4.4.4", + "iconv-lite": "0.4.19", + "js-yaml": "3.10.0", + "parse-color": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "1.0.1" + } + }, + "dotenv": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", + "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=", + "dev": true + }, + "dotenv-expand": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-4.0.1.tgz", + "integrity": "sha1-aP3cFWGBTgoQlkERBX/xOM7X16g=", + "dev": true + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "ejs": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.5.7.tgz", + "integrity": "sha1-zIcsFoiArjxxiXYv1f/ACJbJUYo=", + "dev": true + }, + "electron": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/electron/-/electron-1.7.9.tgz", + "integrity": "sha1-rdVOn4+D7QL2UZ7BATX2mLGTNs8=", + "dev": true, + "requires": { + "@types/node": "7.0.46", + "electron-download": "3.3.0", + "extract-zip": "1.6.6" + } + }, + "electron-builder": { + "version": "19.45.4", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-19.45.4.tgz", + "integrity": "sha512-WuhPBFFU/rdx9ehwS8tOnZfvzTuip7UzZCRZVQy0Bimypv9ZQ65WuCAx8MSy4gLDQ1et63Vrl+fUvtXGQIZI8g==", + "dev": true, + "requires": { + "7zip-bin": "2.2.7", + "app-package-builder": "1.5.0", + "asar-integrity": "0.2.3", + "async-exit-hook": "2.0.1", + "bluebird-lst": "1.0.5", + "builder-util": "3.2.2", + "builder-util-runtime": "3.2.0", + "chalk": "2.3.0", + "chromium-pickle-js": "0.2.0", + "debug": "3.1.0", + "dmg-builder": "2.1.6", + "ejs": "2.5.7", + "electron-download-tf": "4.3.4", + "electron-osx-sign": "0.4.7", + "electron-publish": "19.45.0", + "fs-extra-p": "4.4.4", + "hosted-git-info": "2.5.0", + "is-ci": "1.0.10", + "isbinaryfile": "3.0.2", + "js-yaml": "3.10.0", + "lazy-val": "1.0.2", + "minimatch": "3.0.4", + "normalize-package-data": "2.4.0", + "plist": "2.1.0", + "read-config-file": "1.2.0", + "sanitize-filename": "1.6.1", + "semver": "5.4.1", + "temp-file": "2.0.3", + "update-notifier": "2.3.0", + "yargs": "10.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "electron-download-tf": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/electron-download-tf/-/electron-download-tf-4.3.4.tgz", + "integrity": "sha512-SQYDGMLpTgty1bx3NycuDb7dNPzktVSdK2sqPZjyRocauq/uN/V4S2lcpFVLupaHhKlD8zozm9fTpm5UdohvTg==", + "dev": true, + "requires": { + "debug": "3.1.0", + "env-paths": "1.0.0", + "fs-extra": "4.0.2", + "minimist": "1.2.0", + "nugget": "2.0.1", + "path-exists": "3.0.0", + "rc": "1.2.2", + "semver": "5.4.1", + "sumchecker": "2.0.2" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "sumchecker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", + "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", + "dev": true, + "requires": { + "debug": "2.6.9" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "electron-context-menu": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/electron-context-menu/-/electron-context-menu-0.9.1.tgz", + "integrity": "sha1-7U3yDAgEkcPJlqv8s2MVmUajgFg=", + "requires": { + "electron-dl": "1.10.0", + "electron-is-dev": "0.1.2" + } + }, + "electron-dl": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/electron-dl/-/electron-dl-1.10.0.tgz", + "integrity": "sha1-+UQWBkBW/G8qhq5JhhTJNSaJCvk=", + "requires": { + "ext-name": "5.0.0", + "pupa": "1.0.0", + "unused-filename": "1.0.0" + } + }, + "electron-download": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-3.3.0.tgz", + "integrity": "sha1-LP1U1pZsAZxNSa1l++Zcyc3vaMg=", + "dev": true, + "requires": { + "debug": "2.6.9", + "fs-extra": "0.30.0", + "home-path": "1.0.5", + "minimist": "1.2.0", + "nugget": "2.0.1", + "path-exists": "2.1.0", + "rc": "1.2.2", + "semver": "5.4.1", + "sumchecker": "1.3.1" + }, + "dependencies": { + "fs-extra": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", + "integrity": "sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1", + "path-is-absolute": "1.0.1", + "rimraf": "2.6.2" + } + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } + } + }, + "electron-is-dev": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-0.1.2.tgz", + "integrity": "sha1-ihBD4ys6HaHD9VPc4oznZCRhZ+M=" + }, + "electron-log": { + "version": "2.2.11", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-2.2.11.tgz", + "integrity": "sha512-e+DHJkLJoaawDxyy9i2SMIViG/GV12DUE3T9a6yMdFp695c2u/kWYUZbUy31RzgX9uC/JuewXrO54tXdANgRRQ==" + }, + "electron-osx-sign": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.7.tgz", + "integrity": "sha1-HXVkeoJ0jqzUi+pwYW7IP/rePuU=", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "compare-version": "0.1.2", + "debug": "2.6.9", + "isbinaryfile": "3.0.2", + "minimist": "1.2.0", + "plist": "2.1.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "electron-publish": { + "version": "19.45.0", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-19.45.0.tgz", + "integrity": "sha512-hubOvL3bvgDoITy0hgh+FSbC2Nx1OYDeE4ipzSnEEa6xzjS9svROxUiyyPncbL9O1E+VreJTDyNWaYsYaUg8jw==", + "dev": true, + "requires": { + "bluebird-lst": "1.0.5", + "builder-util": "3.2.2", + "builder-util-runtime": "3.2.0", + "chalk": "2.3.0", + "fs-extra-p": "4.4.4", + "mime": "2.0.3" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "electron-updater": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-2.16.1.tgz", + "integrity": "sha512-QBsCxYocnZcoDhTGEBO4NtNMC0daZ6UghB8BauuotaZFD5l0MRDsyBuGILAL03CvNmxJ3kOViCxCvCKU7V5mgg==", + "requires": { + "bluebird-lst": "1.0.5", + "builder-util-runtime": "3.1.0", + "electron-is-dev": "0.3.0", + "fs-extra-p": "4.4.4", + "js-yaml": "3.10.0", + "lazy-val": "1.0.2", + "lodash.isequal": "4.5.0", + "semver": "5.4.1", + "source-map-support": "0.5.0" + }, + "dependencies": { + "builder-util-runtime": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-3.1.0.tgz", + "integrity": "sha512-O1CkL1lF8xv5TWclrfefx+QZSE47/MXOUOLgNQKTcL8fOGsna4501ehQPSHJWs/MuErUXInQbkaTnjxGC3fxRA==", + "requires": { + "bluebird-lst": "1.0.5", + "debug": "3.1.0", + "fs-extra-p": "4.4.4", + "sax": "1.2.4" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "electron-is-dev": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/electron-is-dev/-/electron-is-dev-0.3.0.tgz", + "integrity": "sha1-FOb9pcaOnk7L7/nM8DfL18BcWv4=" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-support": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz", + "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==", + "requires": { + "source-map": "0.6.1" + } + } + } + }, + "electron-window-state": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/electron-window-state/-/electron-window-state-4.1.1.tgz", + "integrity": "sha1-azT9wxs4UU3+yLfI97XUrdtnYy0=", + "requires": { + "deep-equal": "1.0.1", + "jsonfile": "2.4.0", + "mkdirp": "0.5.1" + }, + "dependencies": { + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "requires": { + "graceful-fs": "4.1.11" + } + } + } + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "0.4.19" + } + }, + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" + }, + "env-paths": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", + "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=", + "dev": true + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + } + } + }, + "es6-promise": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.1.1.tgz", + "integrity": "sha512-OaU1hHjgJf+b0NzsxCg7NdIYERD6Hy/PEmFLTjw+b65scuisG3Kt4QoTvJ66BBkPZ581gr0kpoVzKnxniM8nng==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "5.1.0", + "get-stream": "3.0.0", + "is-stream": "1.1.0", + "npm-run-path": "2.0.2", + "p-finally": "1.0.0", + "signal-exit": "3.0.2", + "strip-eof": "1.0.0" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "optional": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "optional": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "expand-template": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.0.tgz", + "integrity": "sha512-kkjwkMqj0h4w/sb32ERCDxCQkREMCAgS39DscDnSwDsbxnwwM1BTZySdC3Bn1lhY7vL08n9GoO/fVTynjDgRyQ==", + "dev": true + }, + "ext-list": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/ext-list/-/ext-list-2.2.2.tgz", + "integrity": "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA==", + "requires": { + "mime-db": "1.31.0" + } + }, + "ext-name": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ext-name/-/ext-name-5.0.0.tgz", + "integrity": "sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ==", + "requires": { + "ext-list": "2.2.2", + "sort-keys-length": "1.0.1" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "optional": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extract-zip": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.6.tgz", + "integrity": "sha1-EpDt6NINCHK0Kf0/NRyhKOxe+Fw=", + "dev": true, + "requires": { + "concat-stream": "1.6.0", + "debug": "2.6.9", + "mkdirp": "0.5.0", + "yauzl": "2.4.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fbjs": { + "version": "0.8.16", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.16.tgz", + "integrity": "sha1-XmdDL1UNxBtXK/VYR7ispk5TN9s=", + "requires": { + "core-js": "1.2.7", + "isomorphic-fetch": "2.2.1", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "promise": "7.3.1", + "setimmediate": "1.0.5", + "ua-parser-js": "0.7.17" + }, + "dependencies": { + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "requires": { + "asap": "2.0.6" + } + } + } + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "1.2.0" + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "optional": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + } + } + }, + "follow-redirects": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.2.5.tgz", + "integrity": "sha512-lMhwQTryFbG+wYsAIEKC1Kf5IGDlVNnONRogIBllh7LLoV7pNIxW0z9fhjRar9NBql+hd2Y49KboVVNxf6GEfg==", + "requires": { + "debug": "2.6.9" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "optional": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "optional": true, + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + } + }, + "fs-extra-p": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/fs-extra-p/-/fs-extra-p-4.4.4.tgz", + "integrity": "sha512-zHsMNJWhXD184QfHKEIFSQSgAFNV7v9J+Nt2XpaLZp2nTz6WxZNV+R4G2uYeGeLTMaKvUZiqGKrH/4iFCupcUA==", + "requires": { + "bluebird-lst": "1.0.5", + "fs-extra": "4.0.2" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "dev": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "dev": true + }, + "get-proxy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-2.1.0.tgz", + "integrity": "sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw==", + "requires": { + "npm-conf": "1.1.3" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "1.0.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "optional": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "global-dirs": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.0.tgz", + "integrity": "sha1-ENNAOeDfBCcuJizyQiT3IJQ0308=", + "dev": true, + "requires": { + "ini": "1.3.4" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "got": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", + "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "dev": true, + "requires": { + "create-error-class": "3.0.2", + "duplexer3": "0.1.4", + "get-stream": "3.0.0", + "is-redirect": "1.0.0", + "is-retry-allowed": "1.1.0", + "is-stream": "1.1.0", + "lowercase-keys": "1.0.0", + "safe-buffer": "5.1.1", + "timed-out": "4.0.1", + "unzip-response": "2.0.1", + "url-parse-lax": "1.0.0" + }, + "dependencies": { + "unzip-response": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", + "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", + "dev": true + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "dev": true, + "requires": { + "ajv": "5.3.0", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "has-symbol-support-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-symbol-support-x/-/has-symbol-support-x-1.4.1.tgz", + "integrity": "sha512-JkaetveU7hFbqnAC1EV1sF4rlojU2D4Usc5CmS69l6NfmPDnpnFUegzFg33eDkkpNCxZ0mQp65HwUDrNFS/8MA==" + }, + "has-to-string-tag-x": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz", + "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", + "requires": { + "has-symbol-support-x": "1.4.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "dev": true + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "dev": true, + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" + } + }, + "highlight.js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.12.0.tgz", + "integrity": "sha1-5tnb5Xy+/mB1HwKvM2GVhwyQwB4=" + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", + "dev": true + }, + "hoist-non-react-statics": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz", + "integrity": "sha1-ND24TGAYxlB3iJgkATWhQg7iLOA=" + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "home-path": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/home-path/-/home-path-1.0.5.tgz", + "integrity": "sha1-eIspgVsS1Tus9XVkhHbm+QQdEz8=", + "dev": true + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "dev": true + }, + "html-entities": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", + "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=" + }, + "int64-buffer": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/int64-buffer/-/int64-buffer-0.1.9.tgz", + "integrity": "sha1-ngOdoEOyT3ixlrKD4EZT716ZD2E=", + "dev": true + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-arrayish": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.1.tgz", + "integrity": "sha1-wt/DhquqDD4zxI2z/ocFnmkGXv0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "1.10.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-ci": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.0.10.tgz", + "integrity": "sha1-9zkzayYyNlBhqdSCcM1WrjNpMY4=", + "dev": true, + "requires": { + "ci-info": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true, + "optional": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "optional": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "optional": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "0.1.0", + "is-path-inside": "1.0.0" + } + }, + "is-npm": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", + "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", + "dev": true + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "is-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.1.tgz", + "integrity": "sha1-iVJojF7C/9awPsyF52ngKQMINHA=" + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=" + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true, + "optional": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true, + "optional": true + }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is2": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/is2/-/is2-0.0.9.tgz", + "integrity": "sha1-EZVW0dFlGkG6EFr4AyZ8gLKZ9ik=", + "requires": { + "deep-is": "0.1.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "optional": true, + "requires": { + "isarray": "1.0.0" + } + }, + "isomorphic-fetch": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "requires": { + "node-fetch": "1.7.3", + "whatwg-fetch": "2.0.3" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "isurl": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isurl/-/isurl-1.0.0.tgz", + "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", + "requires": { + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jssha": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/jssha/-/jssha-2.3.1.tgz", + "integrity": "sha1-FHshJTaQNcpLL30hDcU58Amz3po=" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "latest-version": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", + "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "dev": true, + "requires": { + "package-json": "4.0.1" + } + }, + "lazy-val": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.2.tgz", + "integrity": "sha512-2BaSu6qVnicKdWQPysrffZVFAKcPcZQ/q2YyeSjAxWaJlvCvKSrkcvsSHlleeIfA//fW2goTcYDTy2cBLN7+PQ==" + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "1.0.0" + } + }, + "levenshtein": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/levenshtein/-/levenshtein-1.0.5.tgz", + "integrity": "sha1-ORFzepy1baNF0Aj1V4LG8TiXm6M=" + }, + "linkify-it": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.0.3.tgz", + "integrity": "sha1-2UpGSPmxwXnWT6lykSaL22zpQ08=", + "requires": { + "uc.micro": "1.0.3" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash-es": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", + "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=", + "dev": true + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "requires": { + "js-tokens": "3.0.2" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "lowercase-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.0.tgz", + "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=", + "dev": true + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "dev": true, + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + }, + "dependencies": { + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } + }, + "make-dir": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", + "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "dev": true, + "requires": { + "pify": "3.0.0" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "markdown-it": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.0.tgz", + "integrity": "sha512-tNuOCCfunY5v5uhcO2AUMArvKAyKMygX8tfup/JrgnsDqcCATQsAExBq7o5Ml9iMmO82bk6jYNLj6khcrl0JGA==", + "requires": { + "argparse": "1.0.9", + "entities": "1.1.1", + "linkify-it": "2.0.3", + "mdurl": "1.0.1", + "uc.micro": "1.0.3" + } + }, + "marked": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.6.tgz", + "integrity": "sha1-ssbGGPzOzk74bE/Gy4p8v1rtqNc=" + }, + "md5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", + "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", + "requires": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "1.1.6" + } + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=" + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mime": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.0.3.tgz", + "integrity": "sha512-TrpAd/vX3xaLPDgVRm6JkZwLR0KHfukMdU2wTEbqMDdCnY6Yo3mE+mjs9YE6oMNw2QRfXVeBEYpmpO94BIqiug==" + }, + "mime-db": { + "version": "1.31.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.31.0.tgz", + "integrity": "sha512-oB3w9lx50CMd6nfonoV5rBRUbJtjMifUHaFb5MfzjC8ksAIfVjT0BsX46SjjqBz7n9JGTrTX3paIeLSK+rS5fQ==" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + }, + "dependencies": { + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + } + } + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "mimic-response": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.0.tgz", + "integrity": "sha1-3z02Uqc/3ta5sLJBRub9BSNTRY4=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "minipass": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.2.1.tgz", + "integrity": "sha512-u1aUllxPJUI07cOqzR7reGmQxmCqlH88uIIsf6XZFEWgw7gXKpJdR+5R9Y3KEDmWYkdIz9wXZs3C0jOPxejk/Q==", + "requires": { + "yallist": "3.0.2" + } + }, + "minizlib": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.0.4.tgz", + "integrity": "sha512-sN4U9tIJtBRwKbwgFh9qJfrPIQ/GGTRr1MGqkgOeMTLy8/lM0FcWU//FqlnZ3Vb7gJ+Mxh3FOg1EklibdajbaQ==", + "requires": { + "minipass": "2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "modify-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/modify-filename/-/modify-filename-1.1.0.tgz", + "integrity": "sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE=" + }, + "moment": { + "version": "2.19.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.2.tgz", + "integrity": "sha512-Rf6jiHPEfxp9+dlzxPTmRHbvoFXsh2L/U8hOupUMpnuecHQmI6cF6lUbJl3QqKPko1u6ujO+FxtcajLVfLpAtA==" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + }, + "node-abi": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.1.2.tgz", + "integrity": "sha512-hmUtb8m75RSi7N+zZLYqe75XDvZB+6LyTBPkj2DConvNgQet2e3BIqEwe1LLvqMrfyjabuT5ZOrTioLCH1HTdA==", + "dev": true, + "requires": { + "semver": "5.4.1" + } + }, + "node-emoji": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.8.1.tgz", + "integrity": "sha512-+ktMAh1Jwas+TnGodfCfjUbJKoANqPaJFN0z0iqh41eqD8dvguNzcitVSBSVK1pidz0AqGbLKcoVuVLRVZ/aVg==", + "dev": true, + "requires": { + "lodash.toarray": "4.4.0" + } + }, + "node-fetch": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "requires": { + "encoding": "0.1.12", + "is-stream": "1.1.0" + } + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npm-conf": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", + "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", + "requires": { + "config-chain": "1.1.11", + "pify": "3.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "2.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dev": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "nugget": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", + "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=", + "dev": true, + "requires": { + "debug": "2.6.9", + "minimist": "1.2.0", + "pretty-bytes": "1.0.4", + "progress-stream": "1.2.0", + "request": "2.83.0", + "single-line-log": "1.1.2", + "throttleit": "0.0.2" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha1-KKaq50KN0sOpLz2V8hM13SBOAzY=", + "dev": true + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "optional": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "dev": true, + "requires": { + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.1.0.tgz", + "integrity": "sha1-sH/y2aXYi+yAYDWJWiurZqJ5iLw=", + "dev": true + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.1.0" + } + }, + "package-json": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", + "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "dev": true, + "requires": { + "got": "6.7.1", + "registry-auth-token": "3.3.1", + "registry-url": "3.1.0", + "semver": "5.4.1" + } + }, + "parse-color": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", + "integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=", + "dev": true, + "requires": { + "color-convert": "0.5.3" + }, + "dependencies": { + "color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=", + "dev": true + } + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "optional": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "plist": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz", + "integrity": "sha1-V8zbeggh3yGDEhejytVOPhRqECU=", + "dev": true, + "requires": { + "base64-js": "1.2.0", + "xmlbuilder": "8.2.2", + "xmldom": "0.1.27" + } + }, + "prebuild-install": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-2.3.0.tgz", + "integrity": "sha512-gzjq2oHB8oMbzJSsSh9MQ64zrXZGt092/uT4TLZlz2qnrPxpWqp4vYB7LZrDxnlxf5RfbCjkgDI/z0EIVuYzAw==", + "dev": true, + "requires": { + "expand-template": "1.1.0", + "github-from-package": "0.0.0", + "minimist": "1.2.0", + "mkdirp": "0.5.1", + "node-abi": "2.1.2", + "noop-logger": "0.1.1", + "npmlog": "4.1.2", + "os-homedir": "1.0.2", + "pump": "1.0.2", + "rc": "1.2.2", + "simple-get": "1.4.3", + "tar-fs": "1.16.0", + "tunnel-agent": "0.6.0", + "xtend": "4.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "simple-get": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-1.4.3.tgz", + "integrity": "sha1-6XVe2kB+ltpAxeUVjJ6jezO+y+s=", + "dev": true, + "requires": { + "once": "1.4.0", + "unzip-response": "1.0.2", + "xtend": "4.0.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true, + "optional": true + }, + "pretty-bytes": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz", + "integrity": "sha1-CiLoIQYJrTVUL4yNXSFZr/B1HIQ=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "progress-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/progress-stream/-/progress-stream-1.2.0.tgz", + "integrity": "sha1-LNPP6jO6OonJwSHsM0er6asSX3c=", + "dev": true, + "requires": { + "speedometer": "0.1.4", + "through2": "0.2.3" + } + }, + "promise": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.0.1.tgz", + "integrity": "sha1-5F1osAoXZHttpxG/he1u1HII9FA=", + "requires": { + "asap": "2.0.6" + } + }, + "prop-types": { + "version": "15.6.0", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.0.tgz", + "integrity": "sha1-zq8IMCL8RrSjX2nhPvda7Q1jmFY=", + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" + } + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "pump": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.2.tgz", + "integrity": "sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "once": "1.4.0" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "pupa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-1.0.0.tgz", + "integrity": "sha1-mpVopa9+ZXuEYqbp1TKHQ1YM7/Y=" + }, + "q": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "integrity": "sha1-TeLmyzspCIyeTLwDv51C+5bOL3U=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "dev": true + }, + "query-string": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.0.1.tgz", + "integrity": "sha512-aM+MkQClojlNiKkO09tiN2Fv8jM/L7GWIjG2liWeKljlOdOPNWr+bW3KQ+w5V/uKprpezC7fAsAMsJtJ+2rLKA==", + "requires": { + "decode-uri-component": "0.2.0", + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" + } + }, + "rabin-bindings": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/rabin-bindings/-/rabin-bindings-1.7.3.tgz", + "integrity": "sha512-zeVdstq+EWdwQ5JCyuuvOsP2fmGc6993laN+v8eEQsahHwZCy8bt5TefohUpgsetiwQhMMk/o+m/2sYng13Txw==", + "dev": true, + "requires": { + "bindings": "1.3.0", + "nan": "2.7.0", + "prebuild-install": "2.3.0" + } + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "dev": true, + "optional": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "rc": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.2.tgz", + "integrity": "sha1-2M6ctX6NZNnHut2YdsfDTL48cHc=", + "dev": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "react": { + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.1.1.tgz", + "integrity": "sha512-FQfiFfk2z2Fk87OngNJHT05KyC9DOVn8LPeB7ZX+9u5+yU1JK6o5ozRlU3PeOMr0IFkWNvgn9jU8/IhRxR1F0g==", + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "prop-types": "15.6.0" + } + }, + "react-ace": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-5.5.0.tgz", + "integrity": "sha1-N9nCAR23IYTr8nq2/9inmBqAQUI=", + "requires": { + "brace": "0.10.0", + "lodash.get": "4.4.2", + "lodash.isequal": "4.5.0", + "prop-types": "15.6.0" + } + }, + "react-dom": { + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.1.1.tgz", + "integrity": "sha512-q06jiwST8SEPAMIEkAsu7BgynEZtqF87VrTc70XsW7nxVhWEu2Y4MF5UfxxHQO/mNtQHQWP0YcFxmwm9oMrMaQ==", + "requires": { + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "prop-types": "15.6.0" + } + }, + "react-redux": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.6.tgz", + "integrity": "sha512-8taaaGu+J7PMJQDJrk/xiWEYQmdo3mkXw6wPr3K3LxvXis3Fymiq7c13S+Tpls/AyNUAsoONkU81AP0RA6y6Vw==", + "requires": { + "hoist-non-react-statics": "2.3.1", + "invariant": "2.2.2", + "lodash": "4.17.4", + "lodash-es": "4.17.4", + "loose-envify": "1.3.1", + "prop-types": "15.6.0" + } + }, + "read-config-file": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-1.2.0.tgz", + "integrity": "sha512-A1MNfKNIfYV7vXMOQ/CPCuVpCdWoPULu8whmrkKxwN8FUsv6EjwU2SPSNueeTKR6tZPl7+Qeondyb4/pAcoozQ==", + "dev": true, + "requires": { + "ajv": "5.3.0", + "ajv-keywords": "2.1.1", + "bluebird-lst": "1.0.5", + "dotenv": "4.0.0", + "dotenv-expand": "4.0.1", + "fs-extra-p": "4.4.4", + "js-yaml": "3.10.0", + "json5": "0.5.1", + "lazy-val": "1.0.2" + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "redux": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", + "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "requires": { + "lodash": "4.17.4", + "lodash-es": "4.17.4", + "loose-envify": "1.3.1", + "symbol-observable": "1.0.4" + } + }, + "regenerator-runtime": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", + "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==", + "dev": true + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "optional": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "registry-auth-token": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.1.tgz", + "integrity": "sha1-+w0yie4Nmtosu1KvXf5mywcNMAY=", + "dev": true, + "requires": { + "rc": "1.2.2", + "safe-buffer": "5.1.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "1.2.2" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "optional": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "dev": true, + "requires": { + "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": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "sanitize-filename": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", + "integrity": "sha1-YS2hyWRz+gLczaktzVtKsWSmdyo=", + "dev": true, + "requires": { + "truncate-utf8-bytes": "1.0.2" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "5.4.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=", + "dev": true, + "optional": true + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, + "sharp": { + "version": "0.18.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.18.4.tgz", + "integrity": "sha1-/jKcDwaJbCiqJDdt8f/wKuV/LTQ=", + "requires": { + "caw": "2.0.1", + "color": "2.0.1", + "detect-libc": "0.2.0", + "nan": "2.7.0", + "semver": "5.4.1", + "simple-get": "2.7.0", + "tar": "3.2.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "simple-concat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.0.tgz", + "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" + }, + "simple-get": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.7.0.tgz", + "integrity": "sha512-RkE9rGPHcxYZ/baYmgJtOSM63vH0Vyq+ma5TijBcLla41SWlh8t6XYIGMR/oeZcmr+/G8k+zrClkkVrtnQ0esg==", + "requires": { + "decompress-response": "3.3.0", + "once": "1.4.0", + "simple-concat": "1.0.0" + } + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "0.3.1" + } + }, + "single-line-log": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", + "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=", + "dev": true, + "requires": { + "string-width": "1.0.2" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + }, + "sort-keys": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz", + "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", + "requires": { + "is-plain-obj": "1.1.0" + } + }, + "sort-keys-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sort-keys-length/-/sort-keys-length-1.0.1.tgz", + "integrity": "sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg=", + "requires": { + "sort-keys": "1.1.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "speedometer": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/speedometer/-/speedometer-0.1.4.tgz", + "integrity": "sha1-mHbb0qFp0xFUAtSObqYynIgWpQ0=", + "dev": true + }, + "sprintf-js": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.1.tgz", + "integrity": "sha1-Nr54Mgr+WAH2zqPueLblqrlA6gw=" + }, + "sqlite3": { + "version": "3.1.13", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-3.1.13.tgz", + "integrity": "sha512-JxXKPJnkZ6NuHRojq+g2WXWBt3M1G9sjZaYiHEWSTGijDM3cwju/0T2XbWqMXFmPqDgw+iB7zKQvnns4bvzXlw==", + "requires": { + "nan": "2.7.0", + "node-pre-gyp": "0.6.38" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.8", + "bundled": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.3.0", + "bundled": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.4", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsprim": { + "version": "1.4.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "mime-db": { + "version": "1.30.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.17", + "bundled": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "node-pre-gyp": { + "version": "0.6.38", + "bundled": true, + "requires": { + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.2", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.2", + "semver": "5.4.1", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1.1.1", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "readable-stream": { + "version": "2.3.3", + "bundled": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "0.6.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.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "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": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true + }, + "semver": { + "version": "5.4.1", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.1", + "bundled": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "bundled": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "requires": { + "debug": "2.6.9", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.3.3", + "rimraf": "2.6.2", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.3", + "bundled": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "uuid": { + "version": "3.1.0", + "bundled": true + }, + "verror": { + "version": "1.10.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + } + } + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", + "dev": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=" + }, + "string-padding": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-padding/-/string-padding-1.0.2.tgz", + "integrity": "sha1-OqrYVbPpc1xeQS3+chmMz5nH9I4=" + }, + "string-to-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-1.1.0.tgz", + "integrity": "sha1-rPLJ6tHEGOFIUJoS0su0afMzohg=", + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "sumchecker": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-1.3.1.tgz", + "integrity": "sha1-ebs7RFbdBPGOvbwNcDodHa7FEF0=", + "dev": true, + "requires": { + "debug": "2.6.9", + "es6-promise": "4.1.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "symbol-observable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", + "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" + }, + "tar": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-3.2.1.tgz", + "integrity": "sha512-ZSzds1E0IqutvMU8HxjMaU8eB7urw2fGwTq88ukDOVuUIh0656l7/P7LiVPxhO5kS4flcRJQk8USG+cghQbTUQ==", + "requires": { + "chownr": "1.0.1", + "minipass": "2.2.1", + "minizlib": "1.0.4", + "mkdirp": "0.5.1", + "yallist": "3.0.2" + } + }, + "tar-fs": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.0.tgz", + "integrity": "sha512-I9rb6v7mjWLtOfCau9eH5L7sLJyU2BnxtEZRQ5Mt+eRKmf1F0ohXmT/Jc3fr52kDvjJ/HV5MH3soQfPL5bQ0Yg==", + "dev": true, + "requires": { + "chownr": "1.0.1", + "mkdirp": "0.5.1", + "pump": "1.0.2", + "tar-stream": "1.5.5" + } + }, + "tar-stream": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", + "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", + "dev": true, + "requires": { + "bl": "1.2.1", + "end-of-stream": "1.4.0", + "readable-stream": "2.3.3", + "xtend": "4.0.1" + }, + "dependencies": { + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } + }, + "tcp-port-used": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-0.1.2.tgz", + "integrity": "sha1-lFDodoyDtBb9TRpqlEnuzL9JbCk=", + "requires": { + "debug": "0.7.4", + "is2": "0.0.9", + "q": "0.9.7" + }, + "dependencies": { + "debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=" + } + } + }, + "temp-file": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-2.0.3.tgz", + "integrity": "sha512-qN0iNW0DFNmog1BFS8J3rQK4sZRIqqUZJ/zFlFo+0PwE7adUTEpPrQ3toWxwTcDjtGL9HjsQWe8CqMKq1kM7Gw==", + "dev": true, + "requires": { + "async-exit-hook": "2.0.1", + "bluebird-lst": "1.0.5", + "fs-extra-p": "4.4.4", + "lazy-val": "1.0.2" + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "0.7.0" + } + }, + "throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", + "dev": true + }, + "through2": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.2.3.tgz", + "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "xtend": "2.1.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "dev": true, + "requires": { + "utf8-byte-length": "1.0.4" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "ua-parser-js": { + "version": "0.7.17", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", + "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==" + }, + "uc.micro": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz", + "integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI=" + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "1.0.0" + } + }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=" + }, + "unused-filename": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unused-filename/-/unused-filename-1.0.0.tgz", + "integrity": "sha1-00CID3GuIRXrqhMlvvBcxmhEacY=", + "requires": { + "modify-filename": "1.1.0", + "path-exists": "3.0.0" + } + }, + "unzip-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", + "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", + "dev": true + }, + "update-notifier": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.3.0.tgz", + "integrity": "sha1-TognpruRUUCrCTVZ1wFOPruDdFE=", + "dev": true, + "requires": { + "boxen": "1.2.2", + "chalk": "2.3.0", + "configstore": "3.1.1", + "import-lazy": "2.1.0", + "is-installed-globally": "0.1.0", + "is-npm": "1.0.0", + "latest-version": "3.1.0", + "semver-diff": "2.1.0", + "xdg-basedir": "3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "1.0.4" + } + }, + "url-to-options": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/url-to-options/-/url-to-options-1.0.1.tgz", + "integrity": "sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k=" + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "w3c-blob": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/w3c-blob/-/w3c-blob-0.0.1.tgz", + "integrity": "sha1-sM01KhpQ9RVWNCD/1YYflQ8dhbg=" + }, + "whatwg-fetch": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", + "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "dev": true, + "requires": { + "string-width": "1.0.2" + } + }, + "widest-line": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-1.0.0.tgz", + "integrity": "sha1-DAnIXCqUaD0Nfq+O4JfVZL8OEFw=", + "dev": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.3.0.tgz", + "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, + "xmlbuilder": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", + "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=", + "dev": true + }, + "xmldom": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", + "dev": true + }, + "xtend": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.1.2.tgz", + "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=", + "dev": true, + "requires": { + "object-keys": "0.4.0" + } + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + }, + "yargs": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-10.0.3.tgz", + "integrity": "sha512-DqBpQ8NAUX4GyPP/ijDGHsJya4tYqLQrjPr95HNsr1YwL3+daCfvBwg7+gIC6IdJhR2kATh3hb61vjzMWEtjdw==", + "dev": true, + "requires": { + "cliui": "3.2.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "8.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "yargs-parser": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.0.0.tgz", + "integrity": "sha1-IdR2Mw5agieaS4gTRb8GYQLiGcY=", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "1.0.1" + } + } + } +} diff --git a/ElectronClient/app/package.json b/ElectronClient/app/package.json new file mode 100644 index 000000000..e6b0c8331 --- /dev/null +++ b/ElectronClient/app/package.json @@ -0,0 +1,83 @@ +{ + "name": "Joplin", + "version": "0.10.25", + "description": "Joplin for Desktop", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "pack": "node_modules/.bin/electron-builder --dir", + "dist": "node_modules/.bin/electron-builder", + "publish": "build -p always", + "postinstall": "node compile-jsx.js", + "compile": "node compile-jsx.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/laurent22/joplin.git" + }, + "author": "Laurent Cozic", + "license": "MIT", + "bugs": { + "url": "https://github.com/laurent22/joplin/issues" + }, + "build": { + "appId": "net.cozic.joplin-desktop", + "win": { + "icon": "../../Assets/Joplin.ico" + }, + "mac": { + "icon": "../../Assets/macOs.icns", + "asar": false + }, + "linux": { + "asar": false + } + }, + "homepage": "https://github.com/laurent22/joplin#readme", + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-preset-react": "^6.24.1", + "electron": "^1.7.9", + "electron-builder": "^19.45.4" + }, + "optionalDependencies": { + "7zip-bin-mac": "^1.0.1", + "7zip-bin-linux": "^1.0.1", + "7zip-bin-win": "^2.1.1" + }, + "dependencies": { + "app-module-path": "^2.2.0", + "electron-context-menu": "^0.9.1", + "electron-log": "^2.2.11", + "electron-updater": "^2.16.1", + "electron-window-state": "^4.1.1", + "follow-redirects": "^1.2.5", + "form-data": "^2.3.1", + "fs-extra": "^4.0.2", + "highlight.js": "^9.12.0", + "html-entities": "^1.2.1", + "jssha": "^2.3.1", + "levenshtein": "^1.0.5", + "lodash": "^4.17.4", + "markdown-it": "^8.4.0", + "marked": "^0.3.6", + "md5": "^2.2.1", + "mime": "^2.0.3", + "moment": "^2.19.1", + "node-fetch": "^1.7.3", + "promise": "^8.0.1", + "query-string": "^5.0.1", + "react": "^16.0.0", + "react-ace": "^5.5.0", + "react-dom": "^16.0.0", + "react-redux": "^5.0.6", + "redux": "^3.7.2", + "sharp": "^0.18.4", + "sprintf-js": "^1.1.1", + "sqlite3": "^3.1.13", + "string-padding": "^1.0.2", + "string-to-stream": "^1.1.0", + "tcp-port-used": "^0.1.2", + "uuid": "^3.1.0" + } +} diff --git a/ElectronClient/app/style.css b/ElectronClient/app/style.css new file mode 100644 index 000000000..30964f8ad --- /dev/null +++ b/ElectronClient/app/style.css @@ -0,0 +1,60 @@ +body, textarea { + margin: 0; + padding: 0; + border: none; +} + +#react-root { + height: 100%; + overflow: hidden; +} + +/* By default, the Ice Editor displays invalid characters, such as non-breaking spaces + as red boxes, but since those are actually valid characters and common in imported + Evernote data, we hide them here. */ +.ace-chrome .ace_invisible_space { + background-color: transparent !important; + opacity: 0; +} + +.note-list .list-item:hover { + background-color: rgba(0,160,255,0.1) !important; +} + +.side-bar .list-item:hover, +.side-bar .synchronize-button:hover { + background-color: #453E53; +} + +.side-bar .list-item:active, +.side-bar .synchronize-button:active { + background-color: #564B6C; +} + +.header .button:not(.disabled):hover { + background-color: rgba(0,160,255,0.1); + border: 1px solid rgba(0,160,255,0.5); + box-sizing: 'border-box'; +} + +.header .button:not(.disabled):active { + background-color: rgba(0,160,255,0.2); + border: 1px solid rgba(0,160,255,0.7); + box-sizing: 'border-box'; +} + +.header .button { + border: 1px solid rgba(0,160,255,0); +} + +.icon-button:hover { + background-color: rgba(0,0,0,0.05) !important; + border: 1px solid rgba(0,0,0,0.10); + border-radius: 5px; +} + +.icon-button:active { + background-color: rgba(0,0,0,0.10) !important; + border: 1px solid rgba(0,0,0,0.15); + border-radius: 5px; +} \ No newline at end of file diff --git a/ElectronClient/app/theme.js b/ElectronClient/app/theme.js new file mode 100644 index 000000000..d63003599 --- /dev/null +++ b/ElectronClient/app/theme.js @@ -0,0 +1,97 @@ +const { Setting } = require('lib/models/setting.js'); + +const globalStyle = { + fontSize: 12, + fontFamily: 'sans-serif', + margin: 15, // No text and no interactive component should be within this margin + itemMarginTop: 10, + itemMarginBottom: 10, + backgroundColor: "#ffffff", + oddBackgroundColor: "#dddddd", + color: "#222222", // For regular text + colorError: "red", + colorWarn: "#9A5B00", + colorFaded: "#777777", // For less important text + fontSizeSmaller: 14, + dividerColor: "#dddddd", + selectedColor: '#e5e5e5', + disabledOpacity: 0.3, + buttonMinWidth: 50, + buttonMinHeight: 30, + textAreaLineHeight: 17, + + backgroundColor2: "#2B2634", + color2: "#ffffff", + selectedColor2: "#5A4D70", + colorError2: "#ff6c6c", + + headerHeight: 35, + headerButtonHPadding: 6, + + raisedBackgroundColor: "#0080EF", + raisedColor: "#003363", + raisedHighlightedColor: "#ffffff", +}; + +// For WebView - must correspond to the properties above +globalStyle.htmlFontSize = globalStyle.fontSize + 'px'; +globalStyle.htmlColor ='black'; // Note: CSS in WebView component only supports named colors or rgb() notation +globalStyle.htmlBackgroundColor ='white'; +globalStyle.htmlDividerColor = 'rgb(150,150,150)'; +globalStyle.htmlLinkColor ='blue'; +globalStyle.htmlLineHeight ='20px'; + +globalStyle.marginRight = globalStyle.margin; +globalStyle.marginLeft = globalStyle.margin; +globalStyle.marginTop = globalStyle.margin; +globalStyle.marginBottom = globalStyle.margin; +globalStyle.htmlMarginLeft = ((globalStyle.marginLeft / 10) * 0.6).toFixed(2) + 'em'; + +globalStyle.icon = { + color: globalStyle.color, + fontSize: 30, +}; + +globalStyle.lineInput = { + color: globalStyle.color, + backgroundColor: globalStyle.backgroundColor, +}; + +globalStyle.textStyle = { + color: globalStyle.color, + fontFamily: globalStyle.fontFamily, + fontSize: globalStyle.fontSize, +}; + +globalStyle.textStyle2 = Object.assign({}, globalStyle.textStyle, { + color: globalStyle.color2, +}); + +let themeCache_ = {}; + +function themeStyle(theme) { + if (!theme) throw new Error('Theme must be specified'); + if (themeCache_[theme]) return themeCache_[theme]; + + let output = Object.assign({}, globalStyle); + if (theme == Setting.THEME_LIGHT) return output; + + output.backgroundColor = '#1D2024'; + output.color = '#dddddd'; + output.colorFaded = '#777777'; + output.dividerColor = '#555555'; + output.selectedColor = '#333333'; + + output.raisedBackgroundColor = "#0F2051"; + output.raisedColor = "#788BC3"; + output.raisedHighlightedColor = "#ffffff"; + + output.htmlColor = 'rgb(220,220,220)'; + output.htmlBackgroundColor = 'rgb(29,32,36)'; + output.htmlLinkColor = 'rgb(166,166,255)'; + + themeCache_[theme] = output; + return themeCache_[theme]; +} + +module.exports = { themeStyle }; \ No newline at end of file diff --git a/ElectronClient/app/update-readme-download.js b/ElectronClient/app/update-readme-download.js new file mode 100644 index 000000000..5e0bae1ba --- /dev/null +++ b/ElectronClient/app/update-readme-download.js @@ -0,0 +1,93 @@ +'use strict'; + +const fs = require('fs-extra'); +const https = require('https'); +const request = require('request'); + +const url = 'https://api.github.com/repos/laurent22/joplin/releases/latest'; +const readmePath = __dirname + '/../../README.md'; + +async function msleep(ms) { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve(); + }, ms); + }); +} + +async function gitHubLatestRelease() { + return new Promise((resolve, reject) => { + request.get({ + url: url, + json: true, + headers: {'User-Agent': 'Joplin Readme Updater'} + }, (error, response, data) => { + if (error) { + reject(error); + } else if (response.statusCode !== 200) { + console.warn(data); + reject(new Error('Error HTTP ' + response.statusCode)); + } else { + resolve(data); + } + }); + }); +} + +function downloadUrl(release, os) { + if (!release || !release.assets || !release.assets.length) return null; + + for (let i = 0; i < release.assets.length; i++) { + const asset = release.assets[i]; + const name = asset.name; + + if (name.indexOf('.dmg') > 0 && os === 'macos') return asset.browser_download_url; + if (name.indexOf('.exe') > 0 && os === 'windows') return asset.browser_download_url; + if (name.indexOf('.AppImage') > 0 && os === 'linux') return asset.browser_download_url; + } +} + +function readmeContent() { + if (!fs.existsSync(readmePath)) throw new Error('Cannot find ' + readmePath); + return fs.readFileSync(readmePath, 'utf8'); +} + +function setReadmeContent(content) { + if (!fs.existsSync(readmePath)) throw new Error('Cannot find ' + readmePath); + return fs.writeFileSync(readmePath, content); +} + +async function main(argv) { + const waitForVersion = argv.length === 3 ? argv[2] : null; + + if (waitForVersion) console.info('Waiting for version ' + waitForVersion + ' to be released before updating readme...'); + + let release = null; + while (true) { + release = await gitHubLatestRelease(); + if (!waitForVersion) break; + + if (release.tag_name !== waitForVersion) { + await msleep(60000 * 5); + } else { + console.info('Got version ' + waitForVersion); + break; + } + } + + const winUrl = downloadUrl(release, 'windows'); + const macOsUrl = downloadUrl(release, 'macos'); + const linuxUrl = downloadUrl(release, 'linux'); + + let content = readmeContent(); + + if (winUrl) content = content.replace(/(https:\/\/github.com\/laurent22\/joplin\/releases\/download\/.*?\.exe)/, winUrl); + if (macOsUrl) content = content.replace(/(https:\/\/github.com\/laurent22\/joplin\/releases\/download\/.*?\.dmg)/, macOsUrl); + if (linuxUrl) content = content.replace(/(https:\/\/github.com\/laurent22\/joplin\/releases\/download\/.*?\.AppImage)/, linuxUrl); + + setReadmeContent(content); +} + +main(process.argv).catch((error) => { + console.error('Fatal error', error); +}); \ No newline at end of file diff --git a/ElectronClient/build.sh b/ElectronClient/build.sh new file mode 100755 index 000000000..e8b98e524 --- /dev/null +++ b/ElectronClient/build.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +BUILD_DIR="$ROOT_DIR/app" + +rsync -a "$ROOT_DIR/../ReactNativeClient/lib/" "$BUILD_DIR/lib/" + +cd "$BUILD_DIR" +npm run compile + +# for JSX_FILE in "$BUILD_DIR"/gui/*.jsx; do +# JS_FILE="${JSX_FILE::-4}.min.js" +# if [ $JSX_FILE -nt $JS_FILE ]; then +# echo "Compile $JS_FILE..." +# "$ROOT_DIR/app/node_modules/.bin/babel" --presets react "$JSX_FILE" > "$JS_FILE" +# if [[ $? != 0 ]]; then +# exit 1 +# fi +# fi +# done + +# TRANSLATION_BUILD_SCRIPT="$ROOT_DIR/../CliClient/build/build-translation.js" +# if [[ ! -f $TRANSLATION_BUILD_SCRIPT ]]; then +# echo "Build the CLI app first ($TRANSLATION_BUILD_SCRIPT missing)" +# exit 1 +# fi + +# node "$TRANSLATION_BUILD_SCRIPT" --silent \ No newline at end of file diff --git a/ElectronClient/release_version.sh b/ElectronClient/release_version.sh new file mode 100755 index 000000000..0a871381e --- /dev/null +++ b/ElectronClient/release_version.sh @@ -0,0 +1,14 @@ +#!/bin/bash +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +APP_DIR="$ROOT_DIR/app" + +cd "$APP_DIR" +VERSION="$(npm version patch)" +git add -A +git commit -m "Electron release $VERSION" +git tag $VERSION +git push && git push --tags + +echo "Create a draft release at: https://github.com/laurent22/joplin/releases/tag/$VERSION" + +node "$APP_DIR/update-readme-download.js" $VERSION \ No newline at end of file diff --git a/ElectronClient/run-prod.sh b/ElectronClient/run-prod.sh new file mode 100644 index 000000000..69b2c5a3b --- /dev/null +++ b/ElectronClient/run-prod.sh @@ -0,0 +1,6 @@ +#!/bin/bash +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$ROOT_DIR" +./build.sh || exit 1 +cd "$ROOT_DIR/app" +./node_modules/.bin/electron . --log-level debug "$@" \ No newline at end of file diff --git a/ElectronClient/run.sh b/ElectronClient/run.sh new file mode 100755 index 000000000..ca79bff01 --- /dev/null +++ b/ElectronClient/run.sh @@ -0,0 +1,6 @@ +#!/bin/bash +ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +cd "$ROOT_DIR" +./build.sh || exit 1 +cd "$ROOT_DIR/app" +./node_modules/.bin/electron . --env dev --log-level debug --open-dev-tools "$@" \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 000000000..8a147b3e6 --- /dev/null +++ b/README.md @@ -0,0 +1,130 @@ +# Joplin + +Joplin is a free, open source note taking and to-do application, which can handle a large number of notes organised into notebooks. The notes are searchable, can be copied, tagged and modified with your own text editor. + +Notes exported from Evernote via .enex files [can be imported](#importing-notes-from-evernote) into Joplin, including the formatted content (which is converted to markdown), resources (images, attachments, etc.) and complete metadata (geolocation, updated time, created time, etc.). + +The notes can be [synchronised](#synchronisation) with various targets including the file system (for example with a network directory) or with Microsoft OneDrive. When synchronising the notes, notebooks, tags and other metadata are saved to plain text files which can be easily inspected, backed up and moved around. + +Joplin is still under development but is out of Beta and should be suitable for every day use. The UI of the terminal client is built on top of the great [terminal-kit](https://github.com/cronvel/terminal-kit) library, the desktop client using [Electron](https://electronjs.org/), and the Android client front end is done using [React Native](https://facebook.github.io/react-native/). + +
+ +# Installation + +Three types of applications are available: **desktop** (Windows, macOS and Linux), **mobile** (Android and iOS) and for **terminal** (Windows, macOS and Linux). All applications have similar user interfaces and can synchronise with each others. + +## Desktop applications + +Operating System | Download +-----------------|-------- +Windows | Get it on Windows +macOS | Get it on macOS +Linux | Get it on macOS + +## Mobile applications + +Operating System | Download +-----------------|-------- +Android | Get it on Google Play +iOS | Get it on the App Store + +## Terminal application + +On macOS, Linux or Windows (via [WSL](https://msdn.microsoft.com/en-us/commandline/wsl/faq?f=255&MSPPError=-2147217396)), type: + + npm install -g joplin + +To start it, type `joplin`. + +For usage information, please refer to the full [Joplin Terminal Application Documentation](http://joplin.cozic.net/terminal). + +# Features + +- Desktop, mobile and terminal applications. +- Support notes, to-dos, tags and notebooks. +- Offline first, so the entire data is always available on the device even without an internet connection. +- Ability to synchronise with multiple targets, including the file system and OneDrive (Dropbox is planned). +- Synchronises to a plain text format, which can be easily manipulated, backed up, or exported to a different format. +- Plain text notes, which are rendered as markdown in the mobile and desktop application. +- Tag support +- File attachment support (images are displayed, and other files are linked and can be opened in the relevant application). +- Search functionality. +- Geo-location support. +- Supports multiple languages + +# Importing notes from Evernote + +Joplin was designed as a replacement for Evernote and so can import complete Evernote notebooks, as well as notes, tags, resources (attached files) and note metadata (such as author, geo-location, etc.) via ENEX files. In terms of data, the only two things that might slightly differ are: + +- Recognition data - Evernote images, in particular scanned (or photographed) documents have [recognition data](https://en.wikipedia.org/wiki/Optical_character_recognition) associated with them. It is the text that Evernote has been able to recognise in the document. This data is not preserved when the note are imported into Joplin. However, should it become supported in the search tool or other parts of Joplin, it should be possible to regenerate this recognition data since the actual image would still be available. + +- Colour, font sizes and faces - Evernote text is stored as HTML and this is converted to Markdown during the import process. For notes that are mostly plain text or with basic formatting (bold, italic, bullet points, links, etc.) this is a lossless conversion, and the note, once rendered back to HTML should be very similar. Tables are also imported and converted to Markdown tables. For very complex notes, some formatting data might be loss - in particular colours, font sizes and font faces will not be imported. The text itself however is always imported in full regardless of formatting. + +To import Evernote data, follow these steps: + +## Desktop application + +* Open the "File" menu and click "Import Evernote notes" + +This will open a new screen which will display the import progress. The notes will be imported into a new separate notebook (so that, in case of a mistake, the notes are not mixed up with any existing notes). If needed then can then be moved to a different notebook, or the notebook can be renamed, etc. + +## Terminal application + +* First, export your Evernote notebooks to ENEX files as described [here](https://help.evernote.com/hc/en-us/articles/209005557-How-to-back-up-export-and-restore-import-notes-and-notebooks). +* In Joplin, in [command-line mode](/terminal#command-line-mode), type `import-enex /path/to/file.enex`. This will import the notes into a new notebook named after the filename. +* Then repeat the process for each notebook that needs to be imported. + +# Synchronisation + +One of the goals of Joplin was to avoid being tied to any particular company or service, whether it is Evernote, Google or Microsoft. As such the synchronisation is designed without any hard dependency to any particular service. Most of the synchronisation process is done at an abstract level and access to external services, such as OneDrive or Dropbox, is done via lightweight drivers. It is easy to support new services by creating simple drivers that provide a filesystem-like interface, i.e. the ability to read, write, delete and list items. It is also simple to switch from one service to another or to even sync to multiple services at once. Each note, notebook, tags, as well as the relation between items is transmitted as plain text files during synchronisation, which means the data can also be moved to a different application, can be easily backed up, inspected, etc. + +Currently, synchronisation is possible with OneDrive (by default) or the local filesystem. A Dropbox driver will also be available once [this React Native bug](https://github.com/facebook/react-native/issues/14445) is fixed. When syncing with OneDrive, Joplin creates a sub-directory in OneDrive, in /Apps/Joplin and read/write the notes and notebooks from it. The application does not have access to anything outside this directory. + +## Desktop application + +To initiate the synchronisation process, click on the "Synchronise" button in the sidebar. You will be asked to login to OneDrive to authorise the application (simply input your Microsoft credentials - you do not need to register with OneDrive). After that, the application will synchronise in the background whenever it is running, or you can click on "Synchronise" to start a synchronisation manually + +## Terminal application + +To initiate the synchronisation process, type `:sync`. You will be asked to follow a link to authorise the application (simply input your Microsoft credentials - you do not need to register with OneDrive). After that, the application will synchronise in the background whenever it is running. It is possible to also synchronise outside of the user interface by typing `joplin sync` from the terminal. This can be used to setup a cron script to synchronise at regular interval. For example, this would do it every 30 minutes: + + */30 * * * * /path/to/joplin sync + +# Attachments / Resources + +Any kind of file can be attached to a note. In Markdown, links to these files are represented as a simple ID to the resource. In the note viewer, these files, if they are images, will be displayed or, if they are other files (PDF, text files, etc.) they will be displayed as links. Clicking on this link will open the file in the default application. + +# Localisation + +Joplin is currently available in English and French. If you would like to contribute a translation, it is quite straightforward, please follow these steps: + +- [Download Poedit](https://poedit.net/), the translation editor, and install it. +- [Download the file to be translated](https://raw.githubusercontent.com/laurent22/joplin/master/CliClient/locales/joplin.pot). +- In Poedit, open this .pot file, go into the Catalog menu and click Configuration. Change "Country" and "Language" to your own country and language. +- From then you can translate the file. Once it's done, please send the file to [this address](https://raw.githubusercontent.com/laurent22/joplin/master/Assets/Adresse.png) or open a pull request. + +This translation will apply to both the terminal and the Android application. + +# Coming features + +- All: End to end encryption +- Windows: Tray icon +- Desktop apps: Tag auto-complete +- Desktop apps: Dark theme +- Linux: Enable auto-update for desktop app + +# Known bugs + +- Non-alphabetical characters such as Chinese or Arabic might create glitches in the terminal on Windows. This is a limitation of the current Windows console. +- Auto-update is not working in the Linux desktop application. + +# License + +Copyright (c) 2016-2017 Laurent Cozic + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README_desktop.md b/README_desktop.md new file mode 100644 index 000000000..f8d02d3d4 --- /dev/null +++ b/README_desktop.md @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/README_terminal.md b/README_terminal.md new file mode 100644 index 000000000..a2b68bc94 --- /dev/null +++ b/README_terminal.md @@ -0,0 +1,327 @@ +# Joplin + +Joplin is a free, open source note taking and to-do application, which can handle a large number of notes organised into notebooks. The notes are searchable, can be copied, tagged and modified with your own text editor. + +Notes exported from Evernote via .enex files [can be imported](#importing-notes-from-evernote) into Joplin, including the formatted content (which is converted to markdown), resources (images, attachments, etc.) and complete metadata (geolocation, updated time, created time, etc.). + +The notes can be [synchronised](#synchronisation) with various targets including the file system (for example with a network directory) or with Microsoft OneDrive. When synchronising the notes, notebooks, tags and other metadata are saved to plain text files which can be easily inspected, backed up and moved around. + + + +# Installation + +On macOS, Linux or Windows (via [WSL](https://msdn.microsoft.com/en-us/commandline/wsl/faq?f=255&MSPPError=-2147217396)), type: + + npm install -g joplin + +To start it, type `joplin`. + +# Demo + +The demo application shows various Wikipedia articles converted to Markdown and organised into notebooks, as well as an example to-do list, in order to test and demonstrate the application. The demo application and its settings will be installed in a separate directory so as not to interfere with any existing Joplin application. + + npm install -g demo-joplin + +To start it, type `demo-joplin`. + +# Usage + +To start the application type `joplin`. This will open the user interface, which has three main panes: Notebooks, Notes and the text of the current note. There are also additional panels that can be toggled on and off via [shortcuts](#available-shortcuts). + + + +## Input modes + +Joplin user interface is partly based on the text editor Vim and offers two different modes to interact with the notes and notebooks: + +### Normal mode + +Allows moving from one pane to another using the `Tab` and `Shift-Tab` keys, and to select/view notes using the arrow keys. Text area can be scrolled using the arrow keys too. Press `Enter` to edit a note. Various other [shortcuts](#available-shortcuts) are available. + +### Command-line mode + +Press `:` to enter command line mode. From there, the Joplin commands such as `mknote` or `search` are available. See the [full list of commands](#available-commands). + +It is possible to refer to a note or notebook by title or ID. However the simplest way is to refer to the currently selected item using one of these shortcuts: + +Shortcut | Description +---------|------------ +`$n` | Refers to the currently selected note +`$b` | Refers to the currently selected notebook +`$c` | Refers to the currently selected item. For example, if the note list is current active, `$c` will refer to the currently selected note. + +**Examples:** + +Create a new note with title "Wednesday's meeting": + + mknote "Wednesday's meeting" + +Create a new to-do: + + mktodo "Buy bread" + +Move the currently selected note ($n) to the notebook with title "Personal" + + mv $n "Personal" + +Rename the currently selected notebook ($b) to "Something": + + ren $b "Something" + +Attach a local file to the currently selected note ($n): + + ren $n /home/laurent/pictures/Vacation12.jpg + +The configuration can also be changed from command-line mode. For example, to change the current editor to Sublime Text: + + config editor "subl -w" + +## Editing a note + +To edit a note, select it and press `ENTER`. Or, in command-line mode, type `edit $n` to edit the currently selected note, or `edit "Note title"` to edit a particular note. + +## Getting help + +The complete usage information is available from command-line mode, by typing one of these commands: + +Command | Description +--------|------------------- +`help` | General help information +`help shortcuts` | Lists the available shortcuts +`help [command]` | Displays information about a particular command + +If the help is not fully visible, press `Tab` multiple times till the console is in focus and use the arrow keys or page up/down to scroll the text. + +# Importing notes from Evernote + +To import Evernote data, follow these steps: + +* First, export your Evernote notebooks to ENEX files as described [here](https://help.evernote.com/hc/en-us/articles/209005557-How-to-back-up-export-and-restore-import-notes-and-notebooks). +* In Joplin, in [command-line mode](#command-line-mode), type `import-enex /path/to/file.enex`. This will import the notes into a new notebook named after the filename. +* Then repeat the process for each notebook that needs to be imported. + +# Synchronisation + +One of the goals of Joplin was to avoid being tied to any particular company or service, whether it is Evernote, Google or Microsoft. As such the synchronisation is designed without any hard dependency to any particular service. Most of the synchronisation process is done at an abstract level and access to external services, such as OneDrive or Dropbox, is done via lightweight drivers. It is easy to support new services by creating simple drivers that provide a filesystem-like interface, i.e. the ability to read, write, delete and list items. It is also simple to switch from one service to another or to even sync to multiple services at once. Each note, notebook, tags, as well as the relation between items is transmitted as plain text files during synchronisation, which means the data can also be moved to a different application, can be easily backed up, inspected, etc. + +Currently, synchronisation is possible with OneDrive (by default) or the local filesystem. A Dropbox driver will also be available once [this React Native bug](https://github.com/facebook/react-native/issues/14445) is fixed. When syncing with OneDrive, Joplin creates a sub-directory in OneDrive, in /Apps/Joplin and read/write the notes and notebooks from it. The application does not have access to anything outside this directory. + +To initiate the synchronisation process, type `:sync`. You will be asked to follow a link to authorise the application (simply input your Microsoft credentials - you do not need to register with OneDrive). After that, the application will synchronise in the background whenever it is running. It is possible to also synchronise outside of the user interface by typing `joplin sync` from the terminal. This can be used to setup a cron script to synchronise at regular interval. For example, this would do it every 30 minutes: + + */30 * * * * /path/to/joplin sync + +# URLs + +When Ctrl+Clicking a URL, most terminals will open that URL in the default browser. However, one issue, especially with long URLs, is that they can end up like this: + + + +Not only it makes the text hard to read, but the link, being cut in two, will also not be clickable. + +As a solution Joplin tries to start a mini-server in the background and, if successful, all the links will be converted to a much shorter URL: + + + +Since this is still an actual URL, the terminal will still make it clickable. And with shorter URLs, the text is more readable and the links unlikely to be cut. Both resources (files that are attached to notes) and external links are handled in this way. + +# Attachments / Resources + +In Markdown, links to resources are represented as a simple ID to the resource. In order to give access to these resources, they will be, like links, converted to local URLs. Clicking this link will then open a browser, which will handle the file - i.e. display the image, open the PDF file, etc. + +# Available shortcuts + +There are two types of shortcuts: those that manipulate the user interface directly, such as `TAB` to move from one pane to another, and those that are simply shortcuts to actual commands. In a way similar to Vim, these shortcuts are generally a verb followed by an object. For example, typing `mn` ([m]ake [n]ote), is used to create a new note: it will switch the interface to command line mode and pre-fill it with `mknote ""` from where the title of the note can be entered. See below for the full list of shortcuts: + + Tab Give focus to next pane + Shift+Tab Give focus to previous pane + : Enter command line mode + ESC Exit command line mode + ENTER Edit the selected note + Ctrl+C Cancel the current command. + Ctrl+D Exit the application. + DELETE Delete the currently selected note or notebook. + SPACE Set a to-do as completed / not completed + tc [t]oggle [c]onsole between maximized/minimized/hidden/visible. + / Search + tm [t]oggle note [m]etadata. + mn [M]ake a new [n]ote + mt [M]ake a new [t]odo + mb [M]ake a new note[b]ook + yn Copy ([Y]ank) the [n]ote to a notebook. + dn Move the note to a notebook. + +# Available commands + +The following commands are available in [command-line mode](#command-line-mode): + + attach + + Attaches the given file to the note. + + config [name] [value] + + Gets or sets a config value. If [value] is not provided, it will show the + value of [name]. If neither [name] nor [value] is provided, it will list + the current configuration. + + -v, --verbose Also displays unset and hidden config variables. + + Possible keys/values: + + editor Text editor. + The editor that will be used to open a note. If + none is provided it will try to auto-detect the + default editor. + Type: string. + + locale Language. + Type: Enum. + Possible values: en_GB (English), fr_FR (Français). + Default: "en_GB" + + sync.2.path File system synchronisation target directory. + The path to synchronise with when file system + synchronisation is enabled. See `sync.target`. + Type: string. + + sync.interval Synchronisation interval. + Type: Enum. + Possible values: 0 (Disabled), 300 (5 minutes), 600 + (10 minutes), 1800 (30 minutes), 3600 (1 hour), + 43200 (12 hours), 86400 (24 hours). + Default: 300 + + sync.target Synchronisation target. + The target to synchonise to. If synchronising with + the file system, set `sync.2.path` to specify the + target directory. + Type: Enum. + Possible values: 1 (Memory), 2 (File system), 3 + (OneDrive). + Default: 3 + + trackLocation Save geo-location with notes. + Type: bool. + Default: true + + uncompletedTodosOnTop Show uncompleted todos on top of the lists. + Type: bool. + Default: true + + cp [notebook] + + Duplicates the notes matching to [notebook]. If no notebook is + specified the note is duplicated in the current notebook. + + done + + Marks a to-do as done. + + edit + + Edit note. + + exit + + Exits the application. + + export + + Exports Joplin data to the given directory. By default, it will export the + complete database including notebooks, notes, tags and resources. + + --note Exports only the given note. + --notebook Exports only the given notebook. + + geoloc + + Displays a geolocation URL for the note. + + help [command] + + Displays usage information. + + import-enex [notebook] + + Imports an Evernote notebook file (.enex file). + + -f, --force Do not ask for confirmation. + + mkbook + + Creates a new notebook. + + mknote + + Creates a new note. + + mktodo + + Creates a new to-do. + + mv [notebook] + + Moves the notes matching to [notebook]. + + ren + + Renames the given (note or notebook) to . + + rmbook + + Deletes the given notebook. + + -f, --force Deletes the notebook without asking for confirmation. + + rmnote + + Deletes the notes matching . + + -f, --force Deletes the notes without asking for confirmation. + + search [notebook] + + Searches for the given in all the notes. + + status + + Displays summary about the notes and notebooks. + + sync + + Synchronises with remote storage. + + --target Sync to provided target (defaults to sync.target config + value) + --random-failures For debugging purposes. Do not use. + + tag [tag] [note] + + can be "add", "remove" or "list" to assign or remove [tag] + from [note], or to list the notes associated with [tag]. The command `tag + list` can be used to list all the tags. + + todo + + can either be "toggle" or "clear". Use "toggle" to toggle + the given to-do between completed and uncompleted state (If the target is + a regular note it will be converted to a to-do). Use "clear" to convert + the to-do back to a regular note. + + undone + + Marks a to-do as non-completed. + + version + + Displays version information + +# License + +Copyright (c) 2016-2017 Laurent Cozic + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/ReactNativeClient/.gitignore b/ReactNativeClient/.gitignore index f553fa686..bf4a2f063 100644 --- a/ReactNativeClient/.gitignore +++ b/ReactNativeClient/.gitignore @@ -53,6 +53,5 @@ fastlane/Preview.html fastlane/screenshots # This is generated: -locales android/build* android/app/build* diff --git a/ReactNativeClient/android/app/build.gradle b/ReactNativeClient/android/app/build.gradle index 99ae58d88..46e6171c0 100644 --- a/ReactNativeClient/android/app/build.gradle +++ b/ReactNativeClient/android/app/build.gradle @@ -90,8 +90,8 @@ android { applicationId "net.cozic.joplin" minSdkVersion 16 targetSdkVersion 22 - versionCode 46 - versionName "0.9.33" + versionCode 73 + versionName "0.10.58" ndk { abiFilters "armeabi-v7a", "x86" } @@ -137,7 +137,9 @@ android { } dependencies { - compile project(':react-native-image-resizer') + compile project(':react-native-fs') + compile project(':react-native-image-picker') + compile project(':react-native-vector-icons') compile project(':react-native-fs') compile fileTree(dir: "libs", include: ["*.jar"]) compile "com.android.support:appcompat-v7:23.0.1" diff --git a/ReactNativeClient/android/app/src/main/AndroidManifest.xml b/ReactNativeClient/android/app/src/main/AndroidManifest.xml index aec1174cf..1f233c49f 100644 --- a/ReactNativeClient/android/app/src/main/AndroidManifest.xml +++ b/ReactNativeClient/android/app/src/main/AndroidManifest.xml @@ -1,38 +1,37 @@ + xmlns:tools="http://schemas.android.com/tools" + package="net.cozic.joplin" + android:versionCode="2" + android:versionName="0.8.0"> - - - - - + + + + + - + - + - - - - - - - - - - + android:configChanges="keyboard|keyboardHidden|orientation|screenSize" + android:windowSoftInputMode="adjustResize" + android:launchMode="singleInstance"> + + + + + + + + diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/Entypo.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/Entypo.ttf new file mode 100644 index 000000000..1c8f5e910 Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/Entypo.ttf differ diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/EvilIcons.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/EvilIcons.ttf new file mode 100644 index 000000000..b270f9851 Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/EvilIcons.ttf differ diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/Feather.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/Feather.ttf new file mode 100755 index 000000000..244854c54 Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/Feather.ttf differ diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/FontAwesome.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/FontAwesome.ttf new file mode 100644 index 000000000..35acda2fa Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/FontAwesome.ttf differ diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/Foundation.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/Foundation.ttf new file mode 100644 index 000000000..6cce217dd Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/Foundation.ttf differ diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/Ionicons.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/Ionicons.ttf new file mode 100644 index 000000000..307ad889a Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/Ionicons.ttf differ diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf new file mode 100644 index 000000000..69404e3d9 Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf differ diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/MaterialIcons.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/MaterialIcons.ttf new file mode 100644 index 000000000..7015564ad Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/MaterialIcons.ttf differ diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/Octicons.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/Octicons.ttf new file mode 100644 index 000000000..09e2b2d79 Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/Octicons.ttf differ diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/SimpleLineIcons.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/SimpleLineIcons.ttf new file mode 100644 index 000000000..6ecb68683 Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/SimpleLineIcons.ttf differ diff --git a/ReactNativeClient/android/app/src/main/assets/fonts/Zocial.ttf b/ReactNativeClient/android/app/src/main/assets/fonts/Zocial.ttf new file mode 100644 index 000000000..e4ae46c62 Binary files /dev/null and b/ReactNativeClient/android/app/src/main/assets/fonts/Zocial.ttf differ diff --git a/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/MainApplication.java b/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/MainApplication.java index fb453f44a..52ad47124 100644 --- a/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/MainApplication.java +++ b/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/MainApplication.java @@ -3,15 +3,17 @@ package net.cozic.joplin; import android.app.Application; import com.facebook.react.ReactApplication; -import com.rnfs.RNFSPackage; +import com.imagepicker.ImagePickerPackage; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.react.shell.MainReactPackage; import com.facebook.soloader.SoLoader; -import org.pgsqlite.SQLitePluginPackage; -import com.RNFetchBlob.RNFetchBlobPackage; +import com.oblador.vectoricons.VectorIconsPackage; import com.reactnativedocumentpicker.ReactNativeDocumentPicker; +import com.RNFetchBlob.RNFetchBlobPackage; +import com.rnfs.RNFSPackage; import fr.bamlab.rnimageresizer.ImageResizerPackage; +import org.pgsqlite.SQLitePluginPackage; import java.util.Arrays; import java.util.List; @@ -27,12 +29,14 @@ public class MainApplication extends Application implements ReactApplication { @Override protected List getPackages() { return Arrays.asList( - new SQLitePluginPackage(), + new ImageResizerPackage(), new MainReactPackage(), - new RNFSPackage(), - new RNFetchBlobPackage(), + new ImagePickerPackage(), new ReactNativeDocumentPicker(), - new ImageResizerPackage() + new RNFetchBlobPackage(), + new RNFSPackage(), + new SQLitePluginPackage(), + new VectorIconsPackage() ); } }; diff --git a/ReactNativeClient/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/ReactNativeClient/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index dbac3fae8..759717102 100644 Binary files a/ReactNativeClient/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/ReactNativeClient/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/ReactNativeClient/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/ReactNativeClient/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index f5ab076ae..a30aa0644 100644 Binary files a/ReactNativeClient/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/ReactNativeClient/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/ReactNativeClient/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/ReactNativeClient/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index cb1faeb10..a712701b7 100644 Binary files a/ReactNativeClient/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/ReactNativeClient/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/ReactNativeClient/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/ReactNativeClient/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 252c16948..7abacb6e0 100644 Binary files a/ReactNativeClient/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/ReactNativeClient/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/ReactNativeClient/android/settings.gradle b/ReactNativeClient/android/settings.gradle index 1283a6908..a508af91f 100644 --- a/ReactNativeClient/android/settings.gradle +++ b/ReactNativeClient/android/settings.gradle @@ -1,4 +1,10 @@ rootProject.name = 'Joplin' +include ':react-native-fs' +project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android') +include ':react-native-image-picker' +project(':react-native-image-picker').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-picker/android') +include ':react-native-vector-icons' +project(':react-native-vector-icons').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vector-icons/android') include ':react-native-image-resizer' project(':react-native-image-resizer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-image-resizer/android') include ':react-native-fs' diff --git a/ReactNativeClient/build_android.bat b/ReactNativeClient/build_android.bat new file mode 100644 index 000000000..71c155ca3 --- /dev/null +++ b/ReactNativeClient/build_android.bat @@ -0,0 +1,2 @@ +cd android +gradlew.bat installDebug --console plain \ No newline at end of file diff --git a/ReactNativeClient/build_android_prod.bat b/ReactNativeClient/build_android_prod.bat new file mode 100644 index 000000000..e8e04e39d --- /dev/null +++ b/ReactNativeClient/build_android_prod.bat @@ -0,0 +1,9 @@ +@echo off + +rem Clear build dir if permission issue: +rem rmdir /S/Q android\app\build + +setlocal +node ..\Tools\prepare-android-prod-build.js +cd android +gradlew.bat assembleRelease -PbuildDir=build --console plain \ No newline at end of file diff --git a/ReactNativeClient/index.android.js b/ReactNativeClient/index.android.js index 755795182..d0e4f551b 100644 --- a/ReactNativeClient/index.android.js +++ b/ReactNativeClient/index.android.js @@ -1,3 +1,3 @@ -import { main } from './main.js'; +const { main } = require('./main.js'); main(); \ No newline at end of file diff --git a/ReactNativeClient/index.ios.js b/ReactNativeClient/index.ios.js index addb4dcfa..7d03ea719 100644 --- a/ReactNativeClient/index.ios.js +++ b/ReactNativeClient/index.ios.js @@ -1,53 +1,51 @@ -/** - * Sample React Native App - * https://github.com/facebook/react-native - * @flow - */ +const { main } = require('./main.js'); -import React, { Component } from 'react'; -import { - AppRegistry, - StyleSheet, - Text, - View -} from 'react-native'; +main(); -export default class Joplin extends Component { - render() { - return ( - - - Welcome to React Native! - - - To get started, edit index.ios.js - - - Press Cmd+R to reload,{'\n'} - Cmd+D or shake for dev menu - - - ); - } -} +// const React = require('react'); const Component = React.Component; +// import { +// AppRegistry, +// StyleSheet, +// Text, +// View +// } from 'react-native'; -const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: '#F5FCFF', - }, - welcome: { - fontSize: 20, - textAlign: 'center', - margin: 10, - }, - instructions: { - textAlign: 'center', - color: '#333333', - marginBottom: 5, - }, -}); +// module.exports = default class Joplin extends Component {; +// render() { +// return ( +// +// +// Welcome to React Native! +// +// +// To get started, edit index.ios.js +// +// +// Press Cmd+R to reload,{'\n'} +// Cmd+D or shake for dev menu +// +// +// ); +// } +// } -AppRegistry.registerComponent('Joplin', () => Joplin); +// const styles = StyleSheet.create({ +// container: { +// flex: 1, +// justifyContent: 'center', +// alignItems: 'center', +// backgroundColor: '#F5FCFF', +// }, +// welcome: { +// fontSize: 20, +// textAlign: 'center', +// margin: 10, +// }, +// instructions: { +// textAlign: 'center', +// color: '#333333', +// marginBottom: 5, +// }, +// }); + +// AppRegistry.registerComponent('Joplin', () => Joplin); diff --git a/ReactNativeClient/index.js b/ReactNativeClient/index.js new file mode 100644 index 000000000..7d03ea719 --- /dev/null +++ b/ReactNativeClient/index.js @@ -0,0 +1,51 @@ +const { main } = require('./main.js'); + +main(); + +// const React = require('react'); const Component = React.Component; +// import { +// AppRegistry, +// StyleSheet, +// Text, +// View +// } from 'react-native'; + +// module.exports = default class Joplin extends Component {; +// render() { +// return ( +// +// +// Welcome to React Native! +// +// +// To get started, edit index.ios.js +// +// +// Press Cmd+R to reload,{'\n'} +// Cmd+D or shake for dev menu +// +// +// ); +// } +// } + +// const styles = StyleSheet.create({ +// container: { +// flex: 1, +// justifyContent: 'center', +// alignItems: 'center', +// backgroundColor: '#F5FCFF', +// }, +// welcome: { +// fontSize: 20, +// textAlign: 'center', +// margin: 10, +// }, +// instructions: { +// textAlign: 'center', +// color: '#333333', +// marginBottom: 5, +// }, +// }); + +// AppRegistry.registerComponent('Joplin', () => Joplin); diff --git a/ReactNativeClient/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject-tvOS.xcscheme b/ReactNativeClient/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject-tvOS.xcscheme deleted file mode 100644 index 3d2bcca4e..000000000 --- a/ReactNativeClient/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject-tvOS.xcscheme +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ReactNativeClient/ios/AwesomeProject/Images.xcassets/AppIcon.appiconset/Contents.json b/ReactNativeClient/ios/AwesomeProject/Images.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 118c98f74..000000000 --- a/ReactNativeClient/ios/AwesomeProject/Images.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/ReactNativeClient/ios/AwesomeProjectTests/AwesomeProjectTests.m b/ReactNativeClient/ios/AwesomeProjectTests/AwesomeProjectTests.m deleted file mode 100644 index adaaf1071..000000000 --- a/ReactNativeClient/ios/AwesomeProjectTests/AwesomeProjectTests.m +++ /dev/null @@ -1,70 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - */ - -#import -#import - -#import -#import - -#define TIMEOUT_SECONDS 600 -#define TEXT_TO_LOOK_FOR @"Welcome to React Native!" - -@interface AwesomeProjectTests : XCTestCase - -@end - -@implementation AwesomeProjectTests - -- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test -{ - if (test(view)) { - return YES; - } - for (UIView *subview in [view subviews]) { - if ([self findSubviewInView:subview matching:test]) { - return YES; - } - } - return NO; -} - -- (void)testRendersWelcomeScreen -{ - UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; - NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; - BOOL foundElement = NO; - - __block NSString *redboxError = nil; - RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { - if (level >= RCTLogLevelError) { - redboxError = message; - } - }); - - while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { - [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; - [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; - - foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { - if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { - return YES; - } - return NO; - }]; - } - - RCTSetLogFunction(RCTDefaultLogFunction); - - XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); - XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); -} - - -@end diff --git a/ReactNativeClient/ios/AwesomeProjectTests/Info.plist b/ReactNativeClient/ios/AwesomeProjectTests/Info.plist deleted file mode 100644 index 886825ccc..000000000 --- a/ReactNativeClient/ios/AwesomeProjectTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/ReactNativeClient/ios/AwesomeProject-tvOS/Info.plist b/ReactNativeClient/ios/Joplin-tvOS/Info.plist similarity index 100% rename from ReactNativeClient/ios/AwesomeProject-tvOS/Info.plist rename to ReactNativeClient/ios/Joplin-tvOS/Info.plist diff --git a/ReactNativeClient/ios/AwesomeProject-tvOSTests/Info.plist b/ReactNativeClient/ios/Joplin-tvOSTests/Info.plist similarity index 100% rename from ReactNativeClient/ios/AwesomeProject-tvOSTests/Info.plist rename to ReactNativeClient/ios/Joplin-tvOSTests/Info.plist diff --git a/ReactNativeClient/ios/AwesomeProject.xcodeproj/project.pbxproj b/ReactNativeClient/ios/Joplin.xcodeproj/project.pbxproj similarity index 54% rename from ReactNativeClient/ios/AwesomeProject.xcodeproj/project.pbxproj rename to ReactNativeClient/ios/Joplin.xcodeproj/project.pbxproj index d302fe696..c8e385d53 100644 --- a/ReactNativeClient/ios/AwesomeProject.xcodeproj/project.pbxproj +++ b/ReactNativeClient/ios/Joplin.xcodeproj/project.pbxproj @@ -5,13 +5,14 @@ }; objectVersion = 46; objects = { + /* Begin PBXBuildFile section */ 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; - 00E356F31AD99517003FC87E /* AwesomeProjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* AwesomeProjectTests.m */; }; + 0DAD2E67F6A14BDC8250B927 /* libRNDocumentPicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 82214D3345D846709A314868 /* libRNDocumentPicker.a */; }; 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; }; 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; }; 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; }; @@ -19,24 +20,28 @@ 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; - 2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; - 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; - 2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */; }; - 2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */; }; - 2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */; }; - 2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */; }; - 2D02E4C61E0B4AEC006451C7 /* libRCTSettings-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */; }; - 2D02E4C71E0B4AEC006451C7 /* libRCTText-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */; }; - 2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */; }; - 2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3EA31DF850E9000B6D8A /* libReact.a */; }; - 2DCD954D1E0B4F2C00145EB5 /* AwesomeProjectTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* AwesomeProjectTests.m */; }; + 1E71C4672AEC47CE94DFF507 /* Feather.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FD370E24D76E461D960DD85D /* Feather.ttf */; }; + 350318CF7C9E4BD68821EBE9 /* Ionicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = FF411B45E68B4A8CBCC35777 /* Ionicons.ttf */; }; + 5AFCE00CC1414FE6BD618F0D /* MaterialIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 15FD7D2C8F0A445BBA807A9D /* MaterialIcons.ttf */; }; 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */; }; + 725A77EC604947A0AFF12C2B /* libRNFetchBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F5E37D05726A4A08B2EE323A /* libRNFetchBlob.a */; }; + 73F8D08845494D1396B6CD0B /* Entypo.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 1F79F2CD7CED446B986A6252 /* Entypo.ttf */; }; 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; - EA51DDC9EBFC469F8214B3AD /* libRNFS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8E646D13B9444DE81EC441D /* libRNFS.a */; }; - 628436ED66784ABE86A775AE /* libRCTImageResizer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9B8E2583D2B6447DB35F295C /* libRCTImageResizer.a */; }; + 929CA5ABC80E4D398AFC4E44 /* libSQLite.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 87BABCF4ED0A406B9546CCE9 /* libSQLite.a */; }; + A47605BC216B4DB3B3C2ED42 /* FontAwesome.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E2638D52624B477FABB52B8F /* FontAwesome.ttf */; }; + A6F5DFAC928B4DBCADFB5D65 /* Foundation.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 3FFC0F5EFDC54862B1F998DD /* Foundation.ttf */; }; + AA484D3B3E0F4588A7687313 /* libRNFS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F098E1ACCB594C828C851A57 /* libRNFS.a */; }; + ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */; }; + AE6BB3A2FDA34D01864A721A /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 381C047F2739439CB3E6452A /* libRNVectorIcons.a */; }; + AE98927FE9BF483FB24D229F /* libRCTImageResizer.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 508DD20D1EA341CA8F730F22 /* libRCTImageResizer.a */; }; + AF99EEC6C55042F7BFC87583 /* libRNImagePicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 44A39642217548C8ADA91CBA /* libRNImagePicker.a */; }; + C8DD987A30F740F1B8EF6D3D /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = CC3CF4044A914711B8D30D1A /* Zocial.ttf */; }; + E75DD6E04D0441D5BF8EB841 /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C77F905EF22646F39B673572 /* MaterialCommunityIcons.ttf */; }; + E8DD8252C0DD4CF1B53590E9 /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 69B8EE98BFBC4AABA4885BB0 /* SimpleLineIcons.ttf */; }; + EA501DCDCF4745E9B63ECE98 /* Octicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 7D46CBDF8846409890AD7A84 /* Octicons.ttf */; }; + EC11356C90E9419799A2626F /* EvilIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 51BCEC3BC28046C8BB19531F /* EvilIcons.ttf */; }; + FBF57CE2F0F448FA9A8985E2 /* libsqlite3.0.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0EB8BCAEA9AA41CAAE460443 /* libsqlite3.0.tbd */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -75,13 +80,6 @@ remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; remoteInfo = RCTVibration; }; - 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 13B07F861A680F5B00A75B9A; - remoteInfo = AwesomeProject; - }; 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; @@ -103,62 +101,6 @@ remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; remoteInfo = React; }; - 2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 2D02E47A1E0B4A5D006451C7; - remoteInfo = "AwesomeProject-tvOS"; - }; - 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A283A1D9B042B00D4039D; - remoteInfo = "RCTImage-tvOS"; - }; - 3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28471D9B043800D4039D; - remoteInfo = "RCTLinking-tvOS"; - }; - 3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28541D9B044C00D4039D; - remoteInfo = "RCTNetwork-tvOS"; - }; - 3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28611D9B046600D4039D; - remoteInfo = "RCTSettings-tvOS"; - }; - 3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A287B1D9B048500D4039D; - remoteInfo = "RCTText-tvOS"; - }; - 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28881D9B049200D4039D; - remoteInfo = "RCTWebSocket-tvOS"; - }; - 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28131D9B038B00D4039D; - remoteInfo = "React-tvOS"; - }; 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; @@ -166,13 +108,6 @@ remoteGlobalIDString = 3D3C059A1DE3340900C268FA; remoteInfo = yoga; }; - 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D3C06751DE3340C00C268FA; - remoteInfo = "yoga-tvOS"; - }; 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; @@ -180,13 +115,6 @@ remoteGlobalIDString = 3D3CD9251DE5FBEC00167DC4; remoteInfo = cxxreact; }; - 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4; - remoteInfo = "cxxreact-tvOS"; - }; 3DAD3EAC1DF850E9000B6D8A /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; @@ -194,12 +122,82 @@ remoteGlobalIDString = 3D3CD90B1DE5FBD600167DC4; remoteInfo = jschelpers; }; - 3DAD3EAE1DF850E9000B6D8A /* PBXContainerItemProxy */ = { + 4D2A85A91FBCE3AC0028537D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 3DBE0D001F3B181A0099AA32; + remoteInfo = fishhook; + }; + 4D2A85BA1FBCE3AD0028537D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DF1C50EBC11E46A3AF87F80A /* RCTImageResizer.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5D72D2E81C16249000E22EC1; + remoteInfo = RCTImageResizer; + }; + 4D2A85BD1FBCE3AD0028537D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 02C42EA98156482DB00BF86D /* RNDocumentPicker.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E01DD9DB1D2311A600C39062; + remoteInfo = RNDocumentPicker; + }; + 4D2A85C01FBCE3AD0028537D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B8C44254005A4B80AD5CA558 /* RNFetchBlob.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A15C300E1CD25C330074CB35; + remoteInfo = RNFetchBlob; + }; + 4D2A85C41FBCE3AD0028537D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9D8705D0D07C4A098FD912EB /* RNFS.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = F12AFB9B1ADAF8F800E0535D; + remoteInfo = RNFS; + }; + 4D2A85C61FBCE3AD0028537D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 9D8705D0D07C4A098FD912EB /* RNFS.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 6456441F1EB8DA9100672408; + remoteInfo = "RNFS-tvOS"; + }; + 4D2A85C91FBCE3AD0028537D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 711CBD21F0894B83A2D8E234 /* RNVectorIcons.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 5DBEB1501B18CEA900B34395; + remoteInfo = RNVectorIcons; + }; + 4D2A85CC1FBCE3AD0028537D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CCDE9E9AF09B45F391B1C2AF /* SQLite.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E23D7B471ACEFE2A00C59171; + remoteInfo = SQLite; + }; + 4D3A19261FBDDA9400457703 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; proxyType = 2; - remoteGlobalIDString = 3D3CD9181DE5FBD800167DC4; - remoteInfo = "jschelpers-tvOS"; + remoteGlobalIDString = 139D7ECE1E25DB7D00323FB7; + remoteInfo = "third-party"; + }; + 4D3A192A1FBDDA9400457703 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 139D7E881E25C6D100323FB7; + remoteInfo = "double-conversion"; + }; + 4DA7F80C1FC1DA9C00353191 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4716DB8654B431D894F89E1 /* RNImagePicker.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 014A3B5C1C6CF33500B6D375; + remoteInfo = RNImagePicker; }; 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; @@ -208,13 +206,6 @@ remoteGlobalIDString = 134814201AA4EA6300B7C361; remoteInfo = RCTAnimation; }; - 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; - proxyType = 2; - remoteGlobalIDString = 2D2A28201D9B03D100D4039D; - remoteInfo = "RCTAnimation-tvOS"; - }; 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; @@ -229,6 +220,13 @@ remoteGlobalIDString = 58B5119B1A9E6C1200147676; remoteInfo = RCTText; }; + ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 358F4ED71D1E81A9004DF814; + remoteInfo = RCTBlob; + }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ @@ -238,43 +236,56 @@ 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = "../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj"; sourceTree = ""; }; 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = "../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj"; sourceTree = ""; }; 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = "../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj"; sourceTree = ""; }; - 00E356EE1AD99517003FC87E /* AwesomeProjectTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AwesomeProjectTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 00E356F21AD99517003FC87E /* AwesomeProjectTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AwesomeProjectTests.m; sourceTree = ""; }; + 02C42EA98156482DB00BF86D /* RNDocumentPicker.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNDocumentPicker.xcodeproj; path = "../node_modules/react-native-document-picker/ios/RNDocumentPicker.xcodeproj"; sourceTree = ""; }; + 0EB8BCAEA9AA41CAAE460443 /* libsqlite3.0.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.0.tbd; path = usr/lib/libsqlite3.0.tbd; sourceTree = SDKROOT; }; 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = "../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj"; sourceTree = ""; }; 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = "../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj"; sourceTree = ""; }; - 13B07F961A680F5B00A75B9A /* AwesomeProject.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AwesomeProject.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = AwesomeProject/AppDelegate.h; sourceTree = ""; }; - 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = AwesomeProject/AppDelegate.m; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* Joplin.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Joplin.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Joplin/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Joplin/AppDelegate.m; sourceTree = ""; }; 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = AwesomeProject/Images.xcassets; sourceTree = ""; }; - 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = AwesomeProject/Info.plist; sourceTree = ""; }; - 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = AwesomeProject/main.m; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Joplin/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Joplin/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Joplin/main.m; sourceTree = ""; }; 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = "../node_modules/react-native/React/React.xcodeproj"; sourceTree = ""; }; - 2D02E47B1E0B4A5D006451C7 /* AwesomeProject-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "AwesomeProject-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 2D02E4901E0B4A5D006451C7 /* AwesomeProject-tvOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "AwesomeProject-tvOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 15FD7D2C8F0A445BBA807A9D /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = ""; }; + 1F79F2CD7CED446B986A6252 /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Entypo.ttf"; sourceTree = ""; }; + 381C047F2739439CB3E6452A /* libRNVectorIcons.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNVectorIcons.a; sourceTree = ""; }; + 3FFC0F5EFDC54862B1F998DD /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = ""; }; + 44A39642217548C8ADA91CBA /* libRNImagePicker.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNImagePicker.a; sourceTree = ""; }; + 4DA7F7A61FC1196F00353191 /* Joplin.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Joplin.entitlements; path = Joplin/Joplin.entitlements; sourceTree = ""; }; + 508DD20D1EA341CA8F730F22 /* libRCTImageResizer.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTImageResizer.a; sourceTree = ""; }; + 51BCEC3BC28046C8BB19531F /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = ""; }; 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAnimation.xcodeproj; path = "../node_modules/react-native/Libraries/NativeAnimation/RCTAnimation.xcodeproj"; sourceTree = ""; }; + 69B8EE98BFBC4AABA4885BB0 /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf"; sourceTree = ""; }; + 711CBD21F0894B83A2D8E234 /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNVectorIcons.xcodeproj; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = ""; }; 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = "../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj"; sourceTree = ""; }; + 7D46CBDF8846409890AD7A84 /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = ""; }; + 82214D3345D846709A314868 /* libRNDocumentPicker.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNDocumentPicker.a; sourceTree = ""; }; 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = "../node_modules/react-native/Libraries/Text/RCTText.xcodeproj"; sourceTree = ""; }; - 8C2AA97067234408AD5BFD90 /* RNFS.xcodeproj */ = {isa = PBXFileReference; name = "RNFS.xcodeproj"; path = "../node_modules/react-native-fs/RNFS.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; - A8E646D13B9444DE81EC441D /* libRNFS.a */ = {isa = PBXFileReference; name = "libRNFS.a"; path = "libRNFS.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; - 8FB22B82988847ED8E7C0976 /* RCTImageResizer.xcodeproj */ = {isa = PBXFileReference; name = "RCTImageResizer.xcodeproj"; path = "../node_modules/react-native-image-resizer/ios/RCTImageResizer.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; - 9B8E2583D2B6447DB35F295C /* libRCTImageResizer.a */ = {isa = PBXFileReference; name = "libRCTImageResizer.a"; path = "libRCTImageResizer.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; + 87BABCF4ED0A406B9546CCE9 /* libSQLite.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libSQLite.a; sourceTree = ""; }; + 9D8705D0D07C4A098FD912EB /* RNFS.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFS.xcodeproj; path = "../node_modules/react-native-fs/RNFS.xcodeproj"; sourceTree = ""; }; + A4716DB8654B431D894F89E1 /* RNImagePicker.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNImagePicker.xcodeproj; path = "../node_modules/react-native-image-picker/ios/RNImagePicker.xcodeproj"; sourceTree = ""; }; + ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTBlob.xcodeproj; path = "../node_modules/react-native/Libraries/Blob/RCTBlob.xcodeproj"; sourceTree = ""; }; + B8C44254005A4B80AD5CA558 /* RNFetchBlob.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNFetchBlob.xcodeproj; path = "../node_modules/react-native-fetch-blob/ios/RNFetchBlob.xcodeproj"; sourceTree = ""; }; + C77F905EF22646F39B673572 /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialCommunityIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = ""; }; + CC3CF4044A914711B8D30D1A /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = ""; }; + CCDE9E9AF09B45F391B1C2AF /* SQLite.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = SQLite.xcodeproj; path = "../node_modules/react-native-sqlite-storage/src/ios/SQLite.xcodeproj"; sourceTree = ""; }; + DF1C50EBC11E46A3AF87F80A /* RCTImageResizer.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTImageResizer.xcodeproj; path = "../node_modules/react-native-image-resizer/ios/RCTImageResizer.xcodeproj"; sourceTree = ""; }; + E2638D52624B477FABB52B8F /* FontAwesome.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf"; sourceTree = ""; }; + F098E1ACCB594C828C851A57 /* libRNFS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFS.a; sourceTree = ""; }; + F5E37D05726A4A08B2EE323A /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFetchBlob.a; sourceTree = ""; }; + FD370E24D76E461D960DD85D /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = ""; }; + FF411B45E68B4A8CBCC35777 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 00E356EB1AD99517003FC87E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + ADBDB9381DFEBF1600ED6528 /* libRCTBlob.a in Frameworks */, + 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */, 146834051AC3E58100842450 /* libReact.a in Frameworks */, 5E9157361DD0AC6A00FF2AA8 /* libRCTAnimation.a in Frameworks */, 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, @@ -286,30 +297,14 @@ 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */, - EA51DDC9EBFC469F8214B3AD /* libRNFS.a in Frameworks */, - 628436ED66784ABE86A775AE /* libRCTImageResizer.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 2D02E4781E0B4A5D006451C7 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2D02E4C91E0B4AEC006451C7 /* libReact.a in Frameworks */, - 2D02E4C21E0B4AEC006451C7 /* libRCTAnimation-tvOS.a in Frameworks */, - 2D02E4C31E0B4AEC006451C7 /* libRCTImage-tvOS.a in Frameworks */, - 2D02E4C41E0B4AEC006451C7 /* libRCTLinking-tvOS.a in Frameworks */, - 2D02E4C51E0B4AEC006451C7 /* libRCTNetwork-tvOS.a in Frameworks */, - 2D02E4C61E0B4AEC006451C7 /* libRCTSettings-tvOS.a in Frameworks */, - 2D02E4C71E0B4AEC006451C7 /* libRCTText-tvOS.a in Frameworks */, - 2D02E4C81E0B4AEC006451C7 /* libRCTWebSocket-tvOS.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 2D02E48D1E0B4A5D006451C7 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( + 0DAD2E67F6A14BDC8250B927 /* libRNDocumentPicker.a in Frameworks */, + 725A77EC604947A0AFF12C2B /* libRNFetchBlob.a in Frameworks */, + AA484D3B3E0F4588A7687313 /* libRNFS.a in Frameworks */, + AE98927FE9BF483FB24D229F /* libRCTImageResizer.a in Frameworks */, + 929CA5ABC80E4D398AFC4E44 /* libSQLite.a in Frameworks */, + FBF57CE2F0F448FA9A8985E2 /* libsqlite3.0.tbd in Frameworks */, + AE6BB3A2FDA34D01864A721A /* libRNVectorIcons.a in Frameworks */, + AF99EEC6C55042F7BFC87583 /* libRNImagePicker.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -336,7 +331,6 @@ isa = PBXGroup; children = ( 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, - 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */, ); name = Products; sourceTree = ""; @@ -345,7 +339,6 @@ isa = PBXGroup; children = ( 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, - 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */, ); name = Products; sourceTree = ""; @@ -358,28 +351,18 @@ name = Products; sourceTree = ""; }; - 00E356EF1AD99517003FC87E /* AwesomeProjectTests */ = { + 04FA5E9085024E3A9DAF0E03 /* Frameworks */ = { isa = PBXGroup; children = ( - 00E356F21AD99517003FC87E /* AwesomeProjectTests.m */, - 00E356F01AD99517003FC87E /* Supporting Files */, + 0EB8BCAEA9AA41CAAE460443 /* libsqlite3.0.tbd */, ); - path = AwesomeProjectTests; - sourceTree = ""; - }; - 00E356F01AD99517003FC87E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 00E356F11AD99517003FC87E /* Info.plist */, - ); - name = "Supporting Files"; + name = Frameworks; sourceTree = ""; }; 139105B71AF99BAD00B5F7CC /* Products */ = { isa = PBXGroup; children = ( 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */, - 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */, ); name = Products; sourceTree = ""; @@ -388,14 +371,15 @@ isa = PBXGroup; children = ( 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */, - 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */, + 4D2A85AA1FBCE3AC0028537D /* libfishhook.a */, ); name = Products; sourceTree = ""; }; - 13B07FAE1A68108700A75B9A /* AwesomeProject */ = { + 13B07FAE1A68108700A75B9A /* Joplin */ = { isa = PBXGroup; children = ( + 4DA7F7A61FC1196F00353191 /* Joplin.entitlements */, 008F07F21AC5B25A0029DE68 /* main.jsbundle */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 13B07FB01A68108700A75B9A /* AppDelegate.m */, @@ -404,20 +388,89 @@ 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 13B07FB71A68108700A75B9A /* main.m */, ); - name = AwesomeProject; + name = Joplin; sourceTree = ""; }; 146834001AC3E56700842450 /* Products */ = { isa = PBXGroup; children = ( 146834041AC3E56700842450 /* libReact.a */, - 3DAD3EA31DF850E9000B6D8A /* libReact.a */, 3DAD3EA51DF850E9000B6D8A /* libyoga.a */, - 3DAD3EA71DF850E9000B6D8A /* libyoga.a */, 3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */, - 3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */, 3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */, - 3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */, + 4D3A19271FBDDA9400457703 /* libthird-party.a */, + 4D3A192B1FBDDA9400457703 /* libdouble-conversion.a */, + ); + name = Products; + sourceTree = ""; + }; + 4D2A85911FBCE3950028537D /* Recovered References */ = { + isa = PBXGroup; + children = ( + 82214D3345D846709A314868 /* libRNDocumentPicker.a */, + F5E37D05726A4A08B2EE323A /* libRNFetchBlob.a */, + F098E1ACCB594C828C851A57 /* libRNFS.a */, + 508DD20D1EA341CA8F730F22 /* libRCTImageResizer.a */, + 87BABCF4ED0A406B9546CCE9 /* libSQLite.a */, + 381C047F2739439CB3E6452A /* libRNVectorIcons.a */, + 44A39642217548C8ADA91CBA /* libRNImagePicker.a */, + ); + name = "Recovered References"; + sourceTree = ""; + }; + 4D2A85AD1FBCE3AC0028537D /* Products */ = { + isa = PBXGroup; + children = ( + 4D2A85BE1FBCE3AD0028537D /* libRNDocumentPicker.a */, + ); + name = Products; + sourceTree = ""; + }; + 4D2A85AF1FBCE3AC0028537D /* Products */ = { + isa = PBXGroup; + children = ( + 4D2A85C11FBCE3AD0028537D /* libRNFetchBlob.a */, + ); + name = Products; + sourceTree = ""; + }; + 4D2A85B11FBCE3AC0028537D /* Products */ = { + isa = PBXGroup; + children = ( + 4D2A85C51FBCE3AD0028537D /* libRNFS.a */, + 4D2A85C71FBCE3AD0028537D /* libRNFS.a */, + ); + name = Products; + sourceTree = ""; + }; + 4D2A85B31FBCE3AC0028537D /* Products */ = { + isa = PBXGroup; + children = ( + 4D2A85BB1FBCE3AD0028537D /* libRCTImageResizer.a */, + ); + name = Products; + sourceTree = ""; + }; + 4D2A85B51FBCE3AC0028537D /* Products */ = { + isa = PBXGroup; + children = ( + 4D2A85CD1FBCE3AD0028537D /* libSQLite.a */, + ); + name = Products; + sourceTree = ""; + }; + 4D2A85B71FBCE3AC0028537D /* Products */ = { + isa = PBXGroup; + children = ( + 4D2A85CA1FBCE3AD0028537D /* libRNVectorIcons.a */, + ); + name = Products; + sourceTree = ""; + }; + 4DA7F8091FC1DA9C00353191 /* Products */ = { + isa = PBXGroup; + children = ( + 4DA7F80D1FC1DA9C00353191 /* libRNImagePicker.a */, ); name = Products; sourceTree = ""; @@ -426,7 +479,6 @@ isa = PBXGroup; children = ( 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */, - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */, ); name = Products; sourceTree = ""; @@ -435,17 +487,35 @@ isa = PBXGroup; children = ( 78C398B91ACF4ADC00677621 /* libRCTLinking.a */, - 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */, ); name = Products; sourceTree = ""; }; + 7FDFE2A137C24ED08645158D /* Resources */ = { + isa = PBXGroup; + children = ( + 1F79F2CD7CED446B986A6252 /* Entypo.ttf */, + 51BCEC3BC28046C8BB19531F /* EvilIcons.ttf */, + FD370E24D76E461D960DD85D /* Feather.ttf */, + E2638D52624B477FABB52B8F /* FontAwesome.ttf */, + 3FFC0F5EFDC54862B1F998DD /* Foundation.ttf */, + FF411B45E68B4A8CBCC35777 /* Ionicons.ttf */, + C77F905EF22646F39B673572 /* MaterialCommunityIcons.ttf */, + 15FD7D2C8F0A445BBA807A9D /* MaterialIcons.ttf */, + 7D46CBDF8846409890AD7A84 /* Octicons.ttf */, + 69B8EE98BFBC4AABA4885BB0 /* SimpleLineIcons.ttf */, + CC3CF4044A914711B8D30D1A /* Zocial.ttf */, + ); + name = Resources; + sourceTree = ""; + }; 832341AE1AAA6A7D00B99B32 /* Libraries */ = { isa = PBXGroup; children = ( 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */, 146833FF1AC3E56700842450 /* React.xcodeproj */, 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, + ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */, 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */, @@ -454,8 +524,13 @@ 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */, - 8C2AA97067234408AD5BFD90 /* RNFS.xcodeproj */, - 8FB22B82988847ED8E7C0976 /* RCTImageResizer.xcodeproj */, + 02C42EA98156482DB00BF86D /* RNDocumentPicker.xcodeproj */, + B8C44254005A4B80AD5CA558 /* RNFetchBlob.xcodeproj */, + 9D8705D0D07C4A098FD912EB /* RNFS.xcodeproj */, + DF1C50EBC11E46A3AF87F80A /* RCTImageResizer.xcodeproj */, + CCDE9E9AF09B45F391B1C2AF /* SQLite.xcodeproj */, + 711CBD21F0894B83A2D8E234 /* RNVectorIcons.xcodeproj */, + A4716DB8654B431D894F89E1 /* RNImagePicker.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -464,7 +539,6 @@ isa = PBXGroup; children = ( 832341B51AAA6A8300B99B32 /* libRCTText.a */, - 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */, ); name = Products; sourceTree = ""; @@ -472,22 +546,30 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( - 13B07FAE1A68108700A75B9A /* AwesomeProject */, + 13B07FAE1A68108700A75B9A /* Joplin */, 832341AE1AAA6A7D00B99B32 /* Libraries */, - 00E356EF1AD99517003FC87E /* AwesomeProjectTests */, 83CBBA001A601CBA00E9B192 /* Products */, + 04FA5E9085024E3A9DAF0E03 /* Frameworks */, + 7FDFE2A137C24ED08645158D /* Resources */, + 4D2A85911FBCE3950028537D /* Recovered References */, ); indentWidth = 2; sourceTree = ""; tabWidth = 2; + usesTabs = 0; }; 83CBBA001A601CBA00E9B192 /* Products */ = { isa = PBXGroup; children = ( - 13B07F961A680F5B00A75B9A /* AwesomeProject.app */, - 00E356EE1AD99517003FC87E /* AwesomeProjectTests.xctest */, - 2D02E47B1E0B4A5D006451C7 /* AwesomeProject-tvOS.app */, - 2D02E4901E0B4A5D006451C7 /* AwesomeProject-tvOSTests.xctest */, + 13B07F961A680F5B00A75B9A /* Joplin.app */, + ); + name = Products; + sourceTree = ""; + }; + ADBDB9201DFEBF0600ED6528 /* Products */ = { + isa = PBXGroup; + children = ( + ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */, ); name = Products; sourceTree = ""; @@ -495,27 +577,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 00E356ED1AD99517003FC87E /* AwesomeProjectTests */ = { + 13B07F861A680F5B00A75B9A /* Joplin */ = { isa = PBXNativeTarget; - buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "AwesomeProjectTests" */; - buildPhases = ( - 00E356EA1AD99517003FC87E /* Sources */, - 00E356EB1AD99517003FC87E /* Frameworks */, - 00E356EC1AD99517003FC87E /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 00E356F51AD99517003FC87E /* PBXTargetDependency */, - ); - name = AwesomeProjectTests; - productName = AwesomeProjectTests; - productReference = 00E356EE1AD99517003FC87E /* AwesomeProjectTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; - 13B07F861A680F5B00A75B9A /* AwesomeProject */ = { - isa = PBXNativeTarget; - buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "AwesomeProject" */; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Joplin" */; buildPhases = ( 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, @@ -526,47 +590,11 @@ ); dependencies = ( ); - name = AwesomeProject; + name = Joplin; productName = "Hello World"; - productReference = 13B07F961A680F5B00A75B9A /* AwesomeProject.app */; + productReference = 13B07F961A680F5B00A75B9A /* Joplin.app */; productType = "com.apple.product-type.application"; }; - 2D02E47A1E0B4A5D006451C7 /* AwesomeProject-tvOS */ = { - isa = PBXNativeTarget; - buildConfigurationList = 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "AwesomeProject-tvOS" */; - buildPhases = ( - 2D02E4771E0B4A5D006451C7 /* Sources */, - 2D02E4781E0B4A5D006451C7 /* Frameworks */, - 2D02E4791E0B4A5D006451C7 /* Resources */, - 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "AwesomeProject-tvOS"; - productName = "AwesomeProject-tvOS"; - productReference = 2D02E47B1E0B4A5D006451C7 /* AwesomeProject-tvOS.app */; - productType = "com.apple.product-type.application"; - }; - 2D02E48F1E0B4A5D006451C7 /* AwesomeProject-tvOSTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "AwesomeProject-tvOSTests" */; - buildPhases = ( - 2D02E48C1E0B4A5D006451C7 /* Sources */, - 2D02E48D1E0B4A5D006451C7 /* Frameworks */, - 2D02E48E1E0B4A5D006451C7 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */, - ); - name = "AwesomeProject-tvOSTests"; - productName = "AwesomeProject-tvOSTests"; - productReference = 2D02E4901E0B4A5D006451C7 /* AwesomeProject-tvOSTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -576,22 +604,18 @@ LastUpgradeCheck = 610; ORGANIZATIONNAME = Facebook; TargetAttributes = { - 00E356ED1AD99517003FC87E = { - CreatedOnToolsVersion = 6.2; - TestTargetID = 13B07F861A680F5B00A75B9A; - }; - 2D02E47A1E0B4A5D006451C7 = { - CreatedOnToolsVersion = 8.2.1; + 13B07F861A680F5B00A75B9A = { + DevelopmentTeam = A9BXAFS6CT; ProvisioningStyle = Automatic; - }; - 2D02E48F1E0B4A5D006451C7 = { - CreatedOnToolsVersion = 8.2.1; - ProvisioningStyle = Automatic; - TestTargetID = 2D02E47A1E0B4A5D006451C7; + SystemCapabilities = { + com.apple.iCloud = { + enabled = 1; + }; + }; }; }; }; - buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "AwesomeProject" */; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Joplin" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -611,6 +635,10 @@ ProductGroup = 5E91572E1DD0AC6500FF2AA8 /* Products */; ProjectRef = 5E91572D1DD0AC6500FF2AA8 /* RCTAnimation.xcodeproj */; }, + { + ProductGroup = ADBDB9201DFEBF0600ED6528 /* Products */; + ProjectRef = ADBDB91F1DFEBF0600ED6528 /* RCTBlob.xcodeproj */; + }, { ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; @@ -619,6 +647,10 @@ ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; }, + { + ProductGroup = 4D2A85B31FBCE3AC0028537D /* Products */; + ProjectRef = DF1C50EBC11E46A3AF87F80A /* RCTImageResizer.xcodeproj */; + }, { ProductGroup = 78C398B11ACF4ADC00677621 /* Products */; ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */; @@ -647,13 +679,34 @@ ProductGroup = 146834001AC3E56700842450 /* Products */; ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; }, + { + ProductGroup = 4D2A85AD1FBCE3AC0028537D /* Products */; + ProjectRef = 02C42EA98156482DB00BF86D /* RNDocumentPicker.xcodeproj */; + }, + { + ProductGroup = 4D2A85AF1FBCE3AC0028537D /* Products */; + ProjectRef = B8C44254005A4B80AD5CA558 /* RNFetchBlob.xcodeproj */; + }, + { + ProductGroup = 4D2A85B11FBCE3AC0028537D /* Products */; + ProjectRef = 9D8705D0D07C4A098FD912EB /* RNFS.xcodeproj */; + }, + { + ProductGroup = 4DA7F8091FC1DA9C00353191 /* Products */; + ProjectRef = A4716DB8654B431D894F89E1 /* RNImagePicker.xcodeproj */; + }, + { + ProductGroup = 4D2A85B71FBCE3AC0028537D /* Products */; + ProjectRef = 711CBD21F0894B83A2D8E234 /* RNVectorIcons.xcodeproj */; + }, + { + ProductGroup = 4D2A85B51FBCE3AC0028537D /* Products */; + ProjectRef = CCDE9E9AF09B45F391B1C2AF /* SQLite.xcodeproj */; + }, ); projectRoot = ""; targets = ( - 13B07F861A680F5B00A75B9A /* AwesomeProject */, - 00E356ED1AD99517003FC87E /* AwesomeProjectTests */, - 2D02E47A1E0B4A5D006451C7 /* AwesomeProject-tvOS */, - 2D02E48F1E0B4A5D006451C7 /* AwesomeProject-tvOSTests */, + 13B07F861A680F5B00A75B9A /* Joplin */, ); }; /* End PBXProject section */ @@ -715,55 +768,6 @@ remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 3DAD3E841DF850E9000B6D8A /* libRCTImage-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTImage-tvOS.a"; - remoteRef = 3DAD3E831DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E881DF850E9000B6D8A /* libRCTLinking-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTLinking-tvOS.a"; - remoteRef = 3DAD3E871DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E8C1DF850E9000B6D8A /* libRCTNetwork-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTNetwork-tvOS.a"; - remoteRef = 3DAD3E8B1DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E901DF850E9000B6D8A /* libRCTSettings-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTSettings-tvOS.a"; - remoteRef = 3DAD3E8F1DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E941DF850E9000B6D8A /* libRCTText-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTText-tvOS.a"; - remoteRef = 3DAD3E931DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3E991DF850E9000B6D8A /* libRCTWebSocket-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTWebSocket-tvOS.a"; - remoteRef = 3DAD3E981DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; - 3DAD3EA31DF850E9000B6D8A /* libReact.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libReact.a; - remoteRef = 3DAD3EA21DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 3DAD3EA51DF850E9000B6D8A /* libyoga.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -771,13 +775,6 @@ remoteRef = 3DAD3EA41DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 3DAD3EA71DF850E9000B6D8A /* libyoga.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libyoga.a; - remoteRef = 3DAD3EA61DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 3DAD3EA91DF850E9000B6D8A /* libcxxreact.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -785,13 +782,6 @@ remoteRef = 3DAD3EA81DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 3DAD3EAB1DF850E9000B6D8A /* libcxxreact.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = libcxxreact.a; - remoteRef = 3DAD3EAA1DF850E9000B6D8A /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -799,11 +789,81 @@ remoteRef = 3DAD3EAC1DF850E9000B6D8A /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 3DAD3EAF1DF850E9000B6D8A /* libjschelpers.a */ = { + 4D2A85AA1FBCE3AC0028537D /* libfishhook.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; - path = libjschelpers.a; - remoteRef = 3DAD3EAE1DF850E9000B6D8A /* PBXContainerItemProxy */; + path = libfishhook.a; + remoteRef = 4D2A85A91FBCE3AC0028537D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4D2A85BB1FBCE3AD0028537D /* libRCTImageResizer.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTImageResizer.a; + remoteRef = 4D2A85BA1FBCE3AD0028537D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4D2A85BE1FBCE3AD0028537D /* libRNDocumentPicker.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNDocumentPicker.a; + remoteRef = 4D2A85BD1FBCE3AD0028537D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4D2A85C11FBCE3AD0028537D /* libRNFetchBlob.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNFetchBlob.a; + remoteRef = 4D2A85C01FBCE3AD0028537D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4D2A85C51FBCE3AD0028537D /* libRNFS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNFS.a; + remoteRef = 4D2A85C41FBCE3AD0028537D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4D2A85C71FBCE3AD0028537D /* libRNFS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNFS.a; + remoteRef = 4D2A85C61FBCE3AD0028537D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4D2A85CA1FBCE3AD0028537D /* libRNVectorIcons.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNVectorIcons.a; + remoteRef = 4D2A85C91FBCE3AD0028537D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4D2A85CD1FBCE3AD0028537D /* libSQLite.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libSQLite.a; + remoteRef = 4D2A85CC1FBCE3AD0028537D /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4D3A19271FBDDA9400457703 /* libthird-party.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libthird-party.a"; + remoteRef = 4D3A19261FBDDA9400457703 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4D3A192B1FBDDA9400457703 /* libdouble-conversion.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libdouble-conversion.a"; + remoteRef = 4D3A192A1FBDDA9400457703 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 4DA7F80D1FC1DA9C00353191 /* libRNImagePicker.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNImagePicker.a; + remoteRef = 4DA7F80C1FC1DA9C00353191 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; 5E9157331DD0AC6500FF2AA8 /* libRCTAnimation.a */ = { @@ -813,13 +873,6 @@ remoteRef = 5E9157321DD0AC6500FF2AA8 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; - 5E9157351DD0AC6500FF2AA8 /* libRCTAnimation-tvOS.a */ = { - isa = PBXReferenceProxy; - fileType = archive.ar; - path = "libRCTAnimation-tvOS.a"; - remoteRef = 5E9157341DD0AC6500FF2AA8 /* PBXContainerItemProxy */; - sourceTree = BUILT_PRODUCTS_DIR; - }; 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -834,37 +887,33 @@ remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + ADBDB9271DFEBF0700ED6528 /* libRCTBlob.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRCTBlob.a; + remoteRef = ADBDB9261DFEBF0700ED6528 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ - 00E356EC1AD99517003FC87E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 13B07F8E1A680F5B00A75B9A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 2D02E4791E0B4A5D006451C7 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2D02E4BD1E0B4A84006451C7 /* Images.xcassets in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 2D02E48E1E0B4A5D006451C7 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( + 73F8D08845494D1396B6CD0B /* Entypo.ttf in Resources */, + EC11356C90E9419799A2626F /* EvilIcons.ttf in Resources */, + 1E71C4672AEC47CE94DFF507 /* Feather.ttf in Resources */, + A47605BC216B4DB3B3C2ED42 /* FontAwesome.ttf in Resources */, + A6F5DFAC928B4DBCADFB5D65 /* Foundation.ttf in Resources */, + 350318CF7C9E4BD68821EBE9 /* Ionicons.ttf in Resources */, + E75DD6E04D0441D5BF8EB841 /* MaterialCommunityIcons.ttf in Resources */, + 5AFCE00CC1414FE6BD618F0D /* MaterialIcons.ttf in Resources */, + EA501DCDCF4745E9B63ECE98 /* Octicons.ttf in Resources */, + E8DD8252C0DD4CF1B53590E9 /* SimpleLineIcons.ttf in Resources */, + C8DD987A30F740F1B8EF6D3D /* Zocial.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -883,33 +932,11 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh"; - }; - 2D02E4CB1E0B4B27006451C7 /* Bundle React Native Code And Images */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Bundle React Native Code And Images"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh"; + shellScript = "export NODE_BINARY=node\n../node_modules/react-native/scripts/react-native-xcode.sh"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - 00E356EA1AD99517003FC87E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 00E356F31AD99517003FC87E /* AwesomeProjectTests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 13B07F871A680F5B00A75B9A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -919,38 +946,8 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 2D02E4771E0B4A5D006451C7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2D02E4BF1E0B4AB3006451C7 /* main.m in Sources */, - 2D02E4BC1E0B4A80006451C7 /* AppDelegate.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 2D02E48C1E0B4A5D006451C7 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 2DCD954D1E0B4F2C00145EB5 /* AwesomeProjectTests.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXTargetDependency section */ - 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 13B07F861A680F5B00A75B9A /* AwesomeProject */; - targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; - }; - 2D02E4921E0B4A5D006451C7 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 2D02E47A1E0B4A5D006451C7 /* AwesomeProject-tvOS */; - targetProxy = 2D02E4911E0B4A5D006451C7 /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - /* Begin PBXVariantGroup section */ 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { isa = PBXVariantGroup; @@ -958,89 +955,45 @@ 13B07FB21A68108700A75B9A /* Base */, ); name = LaunchScreen.xib; - path = AwesomeProject; + path = Joplin; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - 00E356F61AD99517003FC87E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = AwesomeProjectTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AwesomeProject.app/AwesomeProject"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-fs/**", - "$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", - ); - }; - name = Debug; - }; - 00E356F71AD99517003FC87E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - COPY_PHASE_STRIP = NO; - INFOPLIST_FILE = AwesomeProjectTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AwesomeProject.app/AwesomeProject"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-fs/**", - "$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", - ); - }; - name = Release; - }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEAD_CODE_STRIPPING = NO; - INFOPLIST_FILE = AwesomeProject/Info.plist; + DEVELOPMENT_TEAM = A9BXAFS6CT; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../node_modules/react-native-document-picker/ios/RNDocumentPicker", + "$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**", + "$(SRCROOT)/../node_modules/react-native-fs/**", + "$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer", + "$(SRCROOT)/../node_modules/react-native-sqlite-storage/src/ios", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", + "$(SRCROOT)..\node_modules\neact-native-image-pickerios", + ); + INFOPLIST_FILE = Joplin/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); - PRODUCT_NAME = AwesomeProject; + PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin; + PRODUCT_NAME = Joplin; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-fs/**", - "$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", - ); }; name = Debug; }; @@ -1048,145 +1001,34 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - INFOPLIST_FILE = AwesomeProject/Info.plist; + DEVELOPMENT_TEAM = A9BXAFS6CT; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../node_modules/react-native-document-picker/ios/RNDocumentPicker", + "$(SRCROOT)/../node_modules/react-native-fetch-blob/ios/**", + "$(SRCROOT)/../node_modules/react-native-fs/**", + "$(SRCROOT)/../node_modules/react-native-image-resizer/ios/RCTImageResizer", + "$(SRCROOT)/../node_modules/react-native-sqlite-storage/src/ios", + "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", + "$(SRCROOT)..\node_modules\neact-native-image-pickerios", + ); + INFOPLIST_FILE = Joplin/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; OTHER_LDFLAGS = ( "$(inherited)", "-ObjC", "-lc++", ); - PRODUCT_NAME = AwesomeProject; + PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin; + PRODUCT_NAME = Joplin; + PROVISIONING_PROFILE = ""; + PROVISIONING_PROFILE_SPECIFIER = ""; + TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-fs/**", - "$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", - ); - }; - name = Release; - }; - 2D02E4971E0B4A5E006451C7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_TESTABILITY = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "AwesomeProject-tvOS/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.AwesomeProject-tvOS"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.2; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-fs/**", - "$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", - ); - }; - name = Debug; - }; - 2D02E4981E0B4A5E006451C7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; - ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "AwesomeProject-tvOS/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - OTHER_LDFLAGS = ( - "-ObjC", - "-lc++", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.AwesomeProject-tvOS"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - TARGETED_DEVICE_FAMILY = 3; - TVOS_DEPLOYMENT_TARGET = 9.2; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - ); - HEADER_SEARCH_PATHS = ( - "$(inherited)", - "$(SRCROOT)/../node_modules/react-native-fs/**", - "$(SRCROOT)\..\node_modules\react-native-image-resizer\ios\RCTImageResizer", - ); - }; - name = Release; - }; - 2D02E4991E0B4A5E006451C7 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_TESTABILITY = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "AwesomeProject-tvOSTests/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.AwesomeProject-tvOSTests"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AwesomeProject-tvOS.app/AwesomeProject-tvOS"; - TVOS_DEPLOYMENT_TARGET = 10.1; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - ); - }; - name = Debug; - }; - 2D02E49A1E0B4A5E006451C7 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - CLANG_ANALYZER_NONNULL = YES; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "AwesomeProject-tvOSTests/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.AwesomeProject-tvOSTests"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = appletvos; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AwesomeProject-tvOS.app/AwesomeProject-tvOS"; - TVOS_DEPLOYMENT_TARGET = 10.1; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - "\"$(SRCROOT)/$(TARGET_NAME)\"", - ); }; name = Release; }; @@ -1269,16 +1111,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "AwesomeProjectTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 00E356F61AD99517003FC87E /* Debug */, - 00E356F71AD99517003FC87E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "AwesomeProject" */ = { + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Joplin" */ = { isa = XCConfigurationList; buildConfigurations = ( 13B07F941A680F5B00A75B9A /* Debug */, @@ -1287,25 +1120,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 2D02E4BA1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "AwesomeProject-tvOS" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2D02E4971E0B4A5E006451C7 /* Debug */, - 2D02E4981E0B4A5E006451C7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 2D02E4BB1E0B4A5E006451C7 /* Build configuration list for PBXNativeTarget "AwesomeProject-tvOSTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 2D02E4991E0B4A5E006451C7 /* Debug */, - 2D02E49A1E0B4A5E006451C7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "AwesomeProject" */ = { + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Joplin" */ = { isa = XCConfigurationList; buildConfigurations = ( 83CBBA201A601CBA00E9B192 /* Debug */, diff --git a/ReactNativeClient/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject.xcscheme b/ReactNativeClient/ios/Joplin.xcodeproj/xcshareddata/xcschemes/Joplin.xcscheme similarity index 71% rename from ReactNativeClient/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject.xcscheme rename to ReactNativeClient/ios/Joplin.xcodeproj/xcshareddata/xcschemes/Joplin.xcscheme index 847af7251..72d260a18 100644 --- a/ReactNativeClient/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject.xcscheme +++ b/ReactNativeClient/ios/Joplin.xcodeproj/xcshareddata/xcschemes/Joplin.xcscheme @@ -29,23 +29,23 @@ + BuildableName = "Joplin.app" + BlueprintName = "Joplin" + ReferencedContainer = "container:Joplin.xcodeproj"> + buildForAnalyzing = "NO"> + BuildableName = "JoplinTests.xctest" + BlueprintName = "JoplinTests" + ReferencedContainer = "container:Joplin.xcodeproj"> @@ -54,26 +54,17 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" shouldUseLaunchSchemeArgsEnv = "YES"> - - - - + BuildableName = "Joplin.app" + BlueprintName = "Joplin" + ReferencedContainer = "container:Joplin.xcodeproj"> @@ -83,6 +74,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" @@ -94,9 +86,9 @@ + BuildableName = "Joplin.app" + BlueprintName = "Joplin" + ReferencedContainer = "container:Joplin.xcodeproj"> @@ -113,9 +105,9 @@ + BuildableName = "Joplin.app" + BlueprintName = "Joplin" + ReferencedContainer = "container:Joplin.xcodeproj"> diff --git a/ReactNativeClient/ios/AwesomeProject/AppDelegate.h b/ReactNativeClient/ios/Joplin/AppDelegate.h similarity index 100% rename from ReactNativeClient/ios/AwesomeProject/AppDelegate.h rename to ReactNativeClient/ios/Joplin/AppDelegate.h diff --git a/ReactNativeClient/ios/AwesomeProject/AppDelegate.m b/ReactNativeClient/ios/Joplin/AppDelegate.m similarity index 94% rename from ReactNativeClient/ios/AwesomeProject/AppDelegate.m rename to ReactNativeClient/ios/Joplin/AppDelegate.m index 0041b3927..9d5f8f2c3 100644 --- a/ReactNativeClient/ios/AwesomeProject/AppDelegate.m +++ b/ReactNativeClient/ios/Joplin/AppDelegate.m @@ -18,10 +18,10 @@ { NSURL *jsCodeLocation; - jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; + jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation - moduleName:@"AwesomeProject" + moduleName:@"Joplin" initialProperties:nil launchOptions:launchOptions]; rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; diff --git a/ReactNativeClient/ios/AwesomeProject/Base.lproj/LaunchScreen.xib b/ReactNativeClient/ios/Joplin/Base.lproj/LaunchScreen.xib similarity index 93% rename from ReactNativeClient/ios/AwesomeProject/Base.lproj/LaunchScreen.xib rename to ReactNativeClient/ios/Joplin/Base.lproj/LaunchScreen.xib index 44ef61b60..69f76a339 100644 --- a/ReactNativeClient/ios/AwesomeProject/Base.lproj/LaunchScreen.xib +++ b/ReactNativeClient/ios/Joplin/Base.lproj/LaunchScreen.xib @@ -18,7 +18,7 @@ -