├── .babelrc ├── .boostnoterc.sample ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github └── FUNDING.yml ├── .gitignore ├── .prettierrc ├── .snapcraft └── travis_snapcraft.cfg ├── .travis.yml ├── .vscode ├── launch.json └── tasks.json ├── FAQ.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── __mocks__ └── electron.js ├── appdmg.json ├── browser ├── components │ ├── CodeEditor.js │ ├── CodeEditor.styl │ ├── ColorPicker.js │ ├── ColorPicker.styl │ ├── MarkdownEditor.js │ ├── MarkdownEditor.styl │ ├── MarkdownPreview.js │ ├── MarkdownSplitEditor.js │ ├── MarkdownSplitEditor.styl │ ├── ModalEscButton.js │ ├── ModalEscButton.styl │ ├── NavToggleButton.js │ ├── NavToggleButton.styl │ ├── NoteItem.js │ ├── NoteItem.styl │ ├── NoteItemSimple.js │ ├── NoteItemSimple.styl │ ├── RealtimeNotification.js │ ├── RealtimeNotification.styl │ ├── SideNavFilter.js │ ├── SideNavFilter.styl │ ├── SnippetTab.js │ ├── SnippetTab.styl │ ├── StorageItem.js │ ├── StorageItem.styl │ ├── StorageList.js │ ├── StorageList.styl │ ├── TagListItem.js │ ├── TagListItem.styl │ ├── TodoListPercentage.js │ ├── TodoListPercentage.styl │ ├── TodoProcess.js │ ├── TodoProcess.styl │ ├── markdown.styl │ └── render │ │ └── MermaidRender.js ├── lib │ ├── CMLanguageList.js │ ├── CSSModules.js │ ├── Languages.js │ ├── Mutable.js │ ├── RcParser.js │ ├── SnippetManager.js │ ├── TextEditorInterface.js │ ├── confirmDeleteNote.js │ ├── consts.js │ ├── context.js │ ├── contextMenuBuilder.js │ ├── convertModeName.js │ ├── customMeta.js │ ├── date-formatter.js │ ├── findNoteTitle.js │ ├── findStorage.js │ ├── getTodoStatus.js │ ├── htmlTextHelper.js │ ├── i18n.js │ ├── keygen.js │ ├── markdown-it-deflist.js │ ├── markdown-it-fence.js │ ├── markdown-it-frontmatter.js │ ├── markdown-it-sanitize-html.js │ ├── markdown-toc-generator.js │ ├── markdown.js │ ├── markdown2.js │ ├── markdownTextHelper.js │ ├── newNote.js │ ├── normalizeEditorFontFamily.js │ ├── search.js │ ├── slugify.js │ ├── spellcheck.js │ ├── turndown.js │ ├── ui-themes.js │ ├── utils.js │ └── wakatime-plugin.js ├── main │ ├── Detail │ │ ├── Detail.styl │ │ ├── DetailVars.styl │ │ ├── FolderSelect.js │ │ ├── FolderSelect.styl │ │ ├── FromUrlButton.js │ │ ├── FromUrlButton.styl │ │ ├── FullscreenButton.js │ │ ├── FullscreenButton.styl │ │ ├── InfoButton.js │ │ ├── InfoButton.styl │ │ ├── InfoPanel.js │ │ ├── InfoPanel.styl │ │ ├── InfoPanelTrashed.js │ │ ├── MarkdownNoteDetail.js │ │ ├── MarkdownNoteDetail.styl │ │ ├── NoteDetailInfo.styl │ │ ├── PermanentDeleteButton.js │ │ ├── RestoreButton.js │ │ ├── RestoreButton.styl │ │ ├── SnippetNoteDetail.js │ │ ├── SnippetNoteDetail.styl │ │ ├── StarButton.js │ │ ├── StarButton.styl │ │ ├── TagSelect.js │ │ ├── TagSelect.styl │ │ ├── ToggleDirectionButton.js │ │ ├── ToggleDirectionButton.styl │ │ ├── ToggleModeButton.js │ │ ├── ToggleModeButton.styl │ │ ├── TrashButton.js │ │ ├── TrashButton.styl │ │ └── index.js │ ├── DevTools │ │ ├── index.dev.js │ │ ├── index.js │ │ └── index.prod.js │ ├── Main.js │ ├── Main.styl │ ├── NewNoteButton │ │ ├── NewNoteButton.styl │ │ └── index.js │ ├── NoteList │ │ ├── NoteList.styl │ │ └── index.js │ ├── SideNav │ │ ├── ListButton.js │ │ ├── PreferenceButton.js │ │ ├── PreferenceButton.styl │ │ ├── SearchButton.js │ │ ├── SearchButton.styl │ │ ├── SideNav.styl │ │ ├── StorageItem.js │ │ ├── StorageItem.styl │ │ ├── SwitchButton.styl │ │ ├── TagButton.js │ │ └── index.js │ ├── StatusBar │ │ ├── StatusBar.styl │ │ └── index.js │ ├── TopBar │ │ ├── TopBar.styl │ │ └── index.js │ ├── global.styl │ ├── index.js │ ├── lib │ │ ├── AwsMobileAnalyticsConfig.js │ │ ├── Commander.js │ │ ├── ConfigManager.js │ │ ├── ThemeManager.js │ │ ├── ZoomManager.js │ │ ├── dataApi │ │ │ ├── addStorage.js │ │ │ ├── attachmentManagement.js │ │ │ ├── copyFile.js │ │ │ ├── createFolder.js │ │ │ ├── createNote.js │ │ │ ├── createNoteFromUrl.js │ │ │ ├── createSnippet.js │ │ │ ├── deleteFolder.js │ │ │ ├── deleteNote.js │ │ │ ├── deleteSnippet.js │ │ │ ├── exportFolder.js │ │ │ ├── exportNote.js │ │ │ ├── exportNoteAs.js │ │ │ ├── exportStorage.js │ │ │ ├── exportTag.js │ │ │ ├── fetchSnippet.js │ │ │ ├── formatHTML.js │ │ │ ├── formatMarkdown.js │ │ │ ├── formatPDF.js │ │ │ ├── getContentFormatter.js │ │ │ ├── getFilename.js │ │ │ ├── index.js │ │ │ ├── init.js │ │ │ ├── migrateFromV5Storage.js │ │ │ ├── migrateFromV6Storage.js │ │ │ ├── moveNote.js │ │ │ ├── removeStorage.js │ │ │ ├── renameStorage.js │ │ │ ├── reorderFolder.js │ │ │ ├── resolveStorageData.js │ │ │ ├── resolveStorageNotes.js │ │ │ ├── toggleStorage.js │ │ │ ├── updateFolder.js │ │ │ ├── updateNote.js │ │ │ └── updateSnippet.js │ │ ├── eventEmitter.js │ │ ├── ipcClient.js │ │ ├── modal.js │ │ ├── notify.js │ │ ├── shortcut.js │ │ └── shortcutManager.js │ ├── modals │ │ ├── CreateFolderModal.js │ │ ├── CreateFolderModal.styl │ │ ├── CreateMarkdownFromURLModal.js │ │ ├── CreateMarkdownFromURLModal.styl │ │ ├── NewNoteModal.js │ │ ├── NewNoteModal.styl │ │ ├── PreferencesModal │ │ │ ├── Blog.js │ │ │ ├── ConfigTab.styl │ │ │ ├── Crowdfunding.js │ │ │ ├── Crowdfunding.styl │ │ │ ├── ExportTab.js │ │ │ ├── FolderItem.js │ │ │ ├── FolderItem.styl │ │ │ ├── FolderList.js │ │ │ ├── FolderList.styl │ │ │ ├── HotkeyTab.js │ │ │ ├── InfoTab.js │ │ │ ├── InfoTab.styl │ │ │ ├── PluginsTab.js │ │ │ ├── PreferencesModal.styl │ │ │ ├── SnippetEditor.js │ │ │ ├── SnippetList.js │ │ │ ├── SnippetTab.js │ │ │ ├── SnippetTab.styl │ │ │ ├── StorageItem.js │ │ │ ├── StorageItem.styl │ │ │ ├── StoragesTab.js │ │ │ ├── StoragesTab.styl │ │ │ ├── Tab.styl │ │ │ ├── UiTab.js │ │ │ └── index.js │ │ ├── RenameFolderModal.js │ │ ├── RenameModal.styl │ │ └── RenameTagModal.js │ └── store.js └── styles │ ├── Detail │ └── TagSelect.styl │ ├── index.styl │ ├── mixins │ ├── alert.styl │ ├── btn.styl │ ├── circle.styl │ ├── fullsize.styl │ ├── input.styl │ ├── marked.styl │ ├── tooltip.styl │ └── util.styl │ ├── shared │ └── btn.styl │ ├── theme │ └── dark.styl │ └── vars.styl ├── contributing.md ├── dev-scripts └── dev.js ├── dictionaries ├── de_DE │ ├── LICENSE │ ├── de_DE.aff │ └── de_DE.dic ├── en_GB │ ├── LICENSE │ ├── en_GB.aff │ └── en_GB.dic └── fr_FR │ ├── fr_FR.aff │ └── fr_FR.dic ├── docs ├── build.md ├── code_style.md ├── de │ ├── build.md │ └── debug.md ├── debug.md ├── fr │ ├── build.md │ └── debug.md ├── jp │ ├── build.md │ └── debug.md ├── ko │ ├── build.md │ └── debug.md ├── pt_BR │ ├── build.md │ └── debug.md ├── ru │ ├── build.md │ └── debug.md ├── zh_CN │ ├── build.md │ └── debug.md └── zh_TW │ └── build.md ├── extra_scripts ├── boost │ └── boostNewLineIndentContinueMarkdownList.js └── codemirror │ ├── addon │ ├── edit │ │ └── closebrackets.js │ └── hyperlink │ │ └── hyperlink.js │ ├── mode │ ├── bfm │ │ ├── bfm.css │ │ └── bfm.js │ └── gfm │ │ └── gfm.js │ └── theme │ └── nord.css ├── gruntfile.js ├── index.js ├── lib ├── ipcServer.js ├── main-app.js ├── main-menu.js ├── main-window.js ├── main.development.html ├── main.production.html └── touchbar-menu.js ├── locales ├── cs.json ├── da.json ├── de.json ├── en.json ├── es-ES.json ├── fa.json ├── fr.json ├── hu.json ├── it.json ├── ja.json ├── ko.json ├── no.json ├── pl.json ├── pt-BR.json ├── pt-PT.json ├── ru.json ├── sq.json ├── th.json ├── tr.json ├── zh-CN.json └── zh-TW.json ├── package.json ├── prettier.config ├── readme.md ├── resources ├── app.icns ├── app.ico ├── app.png ├── boostnote-install.gif ├── boostnote-install.png ├── boostnote-install@2x.png ├── dmg.icns ├── dmg.ico ├── dmg.png ├── favicon.ico ├── finder.png ├── fonts │ ├── KaTeX_AMS-Regular.eot │ ├── KaTeX_AMS-Regular.ttf │ ├── KaTeX_AMS-Regular.woff │ ├── KaTeX_AMS-Regular.woff2 │ ├── KaTeX_Caligraphic-Bold.eot │ ├── KaTeX_Caligraphic-Bold.ttf │ ├── KaTeX_Caligraphic-Bold.woff │ ├── KaTeX_Caligraphic-Bold.woff2 │ ├── KaTeX_Caligraphic-Regular.eot │ ├── KaTeX_Caligraphic-Regular.ttf │ ├── KaTeX_Caligraphic-Regular.woff │ ├── KaTeX_Caligraphic-Regular.woff2 │ ├── KaTeX_Fraktur-Bold.eot │ ├── KaTeX_Fraktur-Bold.ttf │ ├── KaTeX_Fraktur-Bold.woff │ ├── KaTeX_Fraktur-Bold.woff2 │ ├── KaTeX_Fraktur-Regular.eot │ ├── KaTeX_Fraktur-Regular.ttf │ ├── KaTeX_Fraktur-Regular.woff │ ├── KaTeX_Fraktur-Regular.woff2 │ ├── KaTeX_Main-Bold.eot │ ├── KaTeX_Main-Bold.ttf │ ├── KaTeX_Main-Bold.woff │ ├── KaTeX_Main-Bold.woff2 │ ├── KaTeX_Main-Italic.eot │ ├── KaTeX_Main-Italic.ttf │ ├── KaTeX_Main-Italic.woff │ ├── KaTeX_Main-Italic.woff2 │ ├── KaTeX_Main-Regular.eot │ ├── KaTeX_Main-Regular.ttf │ ├── KaTeX_Main-Regular.woff │ ├── KaTeX_Main-Regular.woff2 │ ├── KaTeX_Math-BoldItalic.eot │ ├── KaTeX_Math-BoldItalic.ttf │ ├── KaTeX_Math-BoldItalic.woff │ ├── KaTeX_Math-BoldItalic.woff2 │ ├── KaTeX_Math-Italic.eot │ ├── KaTeX_Math-Italic.ttf │ ├── KaTeX_Math-Italic.woff │ ├── KaTeX_Math-Italic.woff2 │ ├── KaTeX_Math-Regular.eot │ ├── KaTeX_Math-Regular.ttf │ ├── KaTeX_Math-Regular.woff │ ├── KaTeX_Math-Regular.woff2 │ ├── KaTeX_SansSerif-Bold.eot │ ├── KaTeX_SansSerif-Bold.ttf │ ├── KaTeX_SansSerif-Bold.woff │ ├── KaTeX_SansSerif-Bold.woff2 │ ├── KaTeX_SansSerif-Italic.eot │ ├── KaTeX_SansSerif-Italic.ttf │ ├── KaTeX_SansSerif-Italic.woff │ ├── KaTeX_SansSerif-Italic.woff2 │ ├── KaTeX_SansSerif-Regular.eot │ ├── KaTeX_SansSerif-Regular.ttf │ ├── KaTeX_SansSerif-Regular.woff │ ├── KaTeX_SansSerif-Regular.woff2 │ ├── KaTeX_Script-Regular.eot │ ├── KaTeX_Script-Regular.ttf │ ├── KaTeX_Script-Regular.woff │ ├── KaTeX_Script-Regular.woff2 │ ├── KaTeX_Size1-Regular.eot │ ├── KaTeX_Size1-Regular.ttf │ ├── KaTeX_Size1-Regular.woff │ ├── KaTeX_Size1-Regular.woff2 │ ├── KaTeX_Size2-Regular.eot │ ├── KaTeX_Size2-Regular.ttf │ ├── KaTeX_Size2-Regular.woff │ ├── KaTeX_Size2-Regular.woff2 │ ├── KaTeX_Size3-Regular.eot │ ├── KaTeX_Size3-Regular.ttf │ ├── KaTeX_Size3-Regular.woff │ ├── KaTeX_Size3-Regular.woff2 │ ├── KaTeX_Size4-Regular.eot │ ├── KaTeX_Size4-Regular.ttf │ ├── KaTeX_Size4-Regular.woff │ ├── KaTeX_Size4-Regular.woff2 │ ├── KaTeX_Typewriter-Regular.eot │ ├── KaTeX_Typewriter-Regular.ttf │ ├── KaTeX_Typewriter-Regular.woff │ ├── KaTeX_Typewriter-Regular.woff2 │ ├── Lato-Black.ttf │ ├── Lato-Black.woff │ ├── Lato-Black.woff2 │ ├── Lato-Regular.ttf │ ├── Lato-Regular.woff │ ├── Lato-Regular.woff2 │ ├── MaterialIcons-Regular.ttf │ ├── MaterialIcons-Regular.woff │ └── MaterialIcons-Regular.woff2 ├── icon │ ├── icon-all-active.svg │ ├── icon-all.svg │ ├── icon-code-off.svg │ ├── icon-code-on.svg │ ├── icon-column-list.svg │ ├── icon-column.svg │ ├── icon-down.svg │ ├── icon-edit-lock.svg │ ├── icon-edit.svg │ ├── icon-external.svg │ ├── icon-full.svg │ ├── icon-info.svg │ ├── icon-left-to-right.svg │ ├── icon-list-active.svg │ ├── icon-list.svg │ ├── icon-lock.svg │ ├── icon-mode-markdown-off-active.svg │ ├── icon-mode-markdown-off.svg │ ├── icon-mode-split-on-active.svg │ ├── icon-mode-split-on.svg │ ├── icon-newnote.svg │ ├── icon-note-code.svg │ ├── icon-note-text.svg │ ├── icon-plus.svg │ ├── icon-previewoff-off.svg │ ├── icon-previewoff-on.svg │ ├── icon-right-to-left.svg │ ├── icon-right.svg │ ├── icon-search-active.svg │ ├── icon-search.svg │ ├── icon-setting.svg │ ├── icon-sidebar.svg │ ├── icon-star-active.svg │ ├── icon-star-sidenav.svg │ ├── icon-star.svg │ ├── icon-starred.svg │ ├── icon-tag-active.svg │ ├── icon-tag.svg │ ├── icon-trash-active.svg │ ├── icon-trash-sidenav.svg │ ├── icon-trash.svg │ ├── icon-unlock.svg │ ├── icon-up.svg │ ├── icon-x-light.svg │ ├── icon-x.svg │ └── icon-zoom.svg ├── repository │ └── top.png ├── tray-icon-dark.png ├── tray-icon-dark@2x.png ├── tray-icon-default.png ├── tray-icon-default@2x.png ├── tray-icon.png └── tray-icon@2x.png ├── snap ├── gui │ └── boostnote.desktop └── snapcraft.yaml ├── tests ├── .gitignore ├── components │ ├── TagListItem.snapshot.test.js │ └── __snapshots__ │ │ └── TagListItem.snapshot.test.js.snap ├── dataApi │ ├── addStorage.js │ ├── attachmentManagement.test.js │ ├── copyFile.test.js │ ├── createFolder.test.js │ ├── createNote.test.js │ ├── createNoteFromUrl.test.js │ ├── createSnippet.test.js │ ├── deleteFolder.test.js │ ├── deleteNote-test.js │ ├── deleteSnippet-test.js │ ├── exportFolder-test.js │ ├── exportStorage-test.js │ ├── init.js │ ├── migrateFromV6Storage-test.js │ ├── moveNote-test.js │ ├── removeStorage-test.js │ ├── renameStorage-test.js │ ├── reorderFolder-test.js │ ├── toggleStorage-test.js │ ├── updateFolder-test.js │ ├── updateNote-test.js │ └── updateSnippet-test.js ├── date-formatter-test.js ├── fixtures │ ├── TestDummy.js │ └── markdowns.js ├── helpers │ ├── setup-browser-env.js │ └── setup-electron-mock.js ├── jest.js └── lib │ ├── __snapshots__ │ └── markdown.test.js.snap │ ├── boostnoterc │ ├── .boostnoterc.all │ ├── .boostnoterc.invalid │ └── .boostnoterc.valid │ ├── contextMenuBuilder.test.js │ ├── escapeHtmlCharacters.test.js │ ├── find-storage.test.js │ ├── find-title.test.js │ ├── get-todo-status.test.js │ ├── html-text-helper.test.js │ ├── markdown-text-helper.test.js │ ├── markdown-toc-generator.test.js │ ├── markdown.test.js │ ├── normalize-editor-font-family.test.js │ ├── rc-parser.test.js │ ├── search.test.js │ ├── slugify.test.js │ ├── snapshots │ └── markdown-test.js.md │ ├── spellcheck.test.js │ ├── themeManager.test.js │ └── utils.test.js ├── webpack-production.config.js ├── webpack-skeleton.js ├── webpack.config.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react", "es2015"], 3 | "env": { 4 | "development": { 5 | "presets": ["react-hmre"] 6 | }, 7 | "test": { 8 | "presets": ["env" ,"react", "es2015"], 9 | "plugins": [ 10 | [ "babel-plugin-webpack-alias", { "config": "/webpack.config.js" } ] 11 | ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.boostnoterc.sample: -------------------------------------------------------------------------------- 1 | { 2 | "amaEnabled": true, 3 | "editor": { 4 | "fontFamily": "Monaco, Consolas", 5 | "fontSize": "14", 6 | "indentSize": "2", 7 | "indentType": "space", 8 | "keyMap": "vim", 9 | "switchPreview": "BLUR", 10 | "theme": "monokai" 11 | }, 12 | "hotkey": { 13 | "toggleMain": "Cmd + Alt + L" 14 | }, 15 | "isSideNavFolded": false, 16 | "listStyle": "DEFAULT", 17 | "listWidth": 174, 18 | "navWidth": 200, 19 | "preview": { 20 | "codeBlockTheme": "dracula", 21 | "fontFamily": "Lato", 22 | "fontSize": "14", 23 | "lineNumber": true 24 | }, 25 | "sortBy": { 26 | "default": "UPDATED_AT" 27 | }, 28 | "sortTagsBy": "ALPHABETICAL", 29 | "ui": { 30 | "defaultNote": "ALWAYS_ASK", 31 | "disableDirectWrite": false, 32 | "theme": "default" 33 | }, 34 | "zoom": 1 35 | } 36 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: https://EditorConfig.org 2 | 3 | # top-most EditorConfig file 4 | root = true 5 | 6 | # Space indentation 7 | [*] 8 | indent_style = space 9 | indent_size = 2 10 | trim_trailing_whitespace = true 11 | 12 | # The indent size used in the `package.json` file cannot be changed 13 | # https://github.com/npm/npm/pull/3180#issuecomment-16336516 14 | [{*.yml,*.yaml,package.json}] 15 | indent_style = space 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | compiled/ 3 | dist/ 4 | extra_scripts/ -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["standard", "standard-jsx", "plugin:react/recommended", "prettier"], 3 | "plugins": ["react", "prettier"], 4 | "rules": { 5 | "no-useless-escape": 0, 6 | "prefer-const": ["warn", { 7 | "destructuring": "all" 8 | }], 9 | "no-unused-vars": "warn", 10 | "no-undef": "warn", 11 | "no-lone-blocks": "warn", 12 | "react/prop-types": 0, 13 | "react/no-string-refs": 0, 14 | "react/no-find-dom-node": "warn", 15 | "react/no-render-return-value": "warn", 16 | "react/no-deprecated": "warn", 17 | "prettier/prettier": ["error"] 18 | }, 19 | "globals": { 20 | "FileReader": true, 21 | "localStorage": true, 22 | "fetch": true, 23 | "Image": true, 24 | "MutationObserver": true 25 | }, 26 | "env": { 27 | "jest": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | issuehunt: BoostIo/Boostnote 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .env 3 | Desktop.ini 4 | Thumbs.db 5 | node_modules/* 6 | !node_modules/boost 7 | /dist 8 | /compiled 9 | /secret 10 | *.log 11 | .idea 12 | .vscode 13 | package-lock.json 14 | config.json 15 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": false, 4 | "jsxSingleQuote": true 5 | } -------------------------------------------------------------------------------- /.snapcraft/travis_snapcraft.cfg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/.snapcraft/travis_snapcraft.cfg -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 8 4 | script: 5 | - npm run lint && npm run test 6 | - 'if [[ ${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH} = "master" ]]; then npm install -g grunt npm@6.4 && grunt pre-build; fi' 7 | after_success: 8 | - openssl aes-256-cbc -K $encrypted_440d7f9a3c38_key -iv $encrypted_440d7f9a3c38_iv 9 | -in .snapcraft/travis_snapcraft.cfg -out .snapcraft/snapcraft.cfg -d 10 | sudo: required 11 | services: 12 | - docker 13 | deploy: 14 | 'on': 15 | branch: master 16 | provider: script 17 | script: if [ ${TRAVIS_NODE_VERSION} = "stable" ];then docker run -v $(pwd):$(pwd) -t snapcore/snapcraft sh -c "apt update -qq 18 | && cd $(pwd) && snapcraft && snapcraft push *.snap --release edge"; fi 19 | skip_cleanup: true 20 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | 8 | { 9 | "type": "node", 10 | "request": "launch", 11 | "name": "BoostNote Main", 12 | "protocol": "inspector", 13 | "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron", 14 | "runtimeArgs": [ 15 | "--remote-debugging-port=9223", 16 | "--hot", 17 | "${workspaceFolder}/index.js" 18 | ], 19 | "windows": { 20 | "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd" 21 | } 22 | }, 23 | { 24 | "type": "chrome", 25 | "request": "attach", 26 | "name": "BoostNote Renderer", 27 | "port": 9223, 28 | "webRoot": "${workspaceFolder}", 29 | "sourceMapPathOverrides": { 30 | "webpack:///./~/*": "${webRoot}/node_modules/*", 31 | "webpack:///*": "${webRoot}/*" 32 | } 33 | } 34 | ], 35 | "compounds": [ 36 | { 37 | "name": "BostNote All", 38 | "configurations": ["BoostNote Main", "BoostNote Renderer"] 39 | } 40 | ] 41 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "Build Boostnote", 8 | "group": "build", 9 | "type": "npm", 10 | "script": "watch", 11 | "isBackground": true, 12 | "presentation": { 13 | "reveal": "always", 14 | }, 15 | "problemMatcher": { 16 | "pattern":[ 17 | { 18 | "regexp": "^([^\\\\s].*)\\\\((\\\\d+,\\\\d+)\\\\):\\\\s*(.*)$", 19 | "file": 1, 20 | "location": 2, 21 | "message": 3 22 | } 23 | ] 24 | } 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /FAQ.md: -------------------------------------------------------------------------------- 1 | # Frequently Asked Questions 2 | 3 | 4 |
Allowing dangerous HTML tags 5 | 6 | Sometimes it is useful to allow dangerous HTML tags to add interactivity to your notebook. One of the example is to use details/summary as a way to expand/collaps your todo-list. 7 | 8 | * How to enable: 9 | * Go to **Preferences** → **Interface** → **Sanitization** → **Allow dangerous html tags** 10 | * Example note: Multiple todo-list 11 | * Create new notes 12 | * Paste the below code, and you'll see that you can expand/collaps the todo-list, and you can have multiple todo-list in your note. 13 | 14 | ```html 15 |
What I want to do 16 | 17 | - [x] Create an awesome feature X 18 | - [ ] Do my homework 19 | 20 |
21 | ``` 22 | 23 |
24 | 25 | ## Other questions 26 | 27 | You can ask [here][ISSUES] 28 | 29 | [ISSUES]: https://github.com/BoostIO/Boostnote/issues 30 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Current behavior 2 | 3 | 10 | 11 | # Expected behavior 12 | 13 | 16 | 17 | # Steps to reproduce 18 | 19 | 22 | 23 | 1. 24 | 2. 25 | 3. 26 | 27 | # Environment 28 | 29 | - Boostnote version: 30 | - OS version and name: 31 | 32 | 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GPL-3.0 2 | 3 | Boostnote - an open source note-taking app made for programmers just like you. 4 | 5 | Copyright (C) 2017 - 2019 BoostIO 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## Description 8 | 9 | 13 | 14 | ## Issue fixed 15 | 16 | 19 | 20 | 26 | 27 | ## Type of changes 28 | 29 | - :white_circle: Bug fix (Change that fixed an issue) 30 | - :white_circle: Breaking change (Change that can cause existing functionality to change) 31 | - :white_circle: Improvement (Change that improves the code. Maybe performance or development improvement) 32 | - :white_circle: Feature (Change that adds new functionality) 33 | - :white_circle: Documentation change (Change that modifies documentation. Maybe typo fixes) 34 | 35 | ## Checklist: 36 | 37 | - :white_circle: My code follows [the project code style](docs/code_style.md) 38 | - :white_circle: I have written test for my code and it has been tested 39 | - :white_circle: All existing tests have been passed 40 | - :white_circle: I have attached a screenshot/video to visualize my change if possible 41 | - :white_circle: This PR will modify the UI or affects the UX 42 | - :white_circle: This PR will add/update/delete a keybinding 43 | -------------------------------------------------------------------------------- /__mocks__/electron.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | require: jest.genMockFunction(), 3 | match: jest.genMockFunction(), 4 | app: jest.genMockFunction(), 5 | remote: jest.genMockFunction(), 6 | dialog: jest.genMockFunction() 7 | } 8 | -------------------------------------------------------------------------------- /appdmg.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Boostnote", 3 | "icon": "resources/dmg.icns", 4 | "background": "resources/boostnote-install.png", 5 | "icon-size": 80, 6 | "contents": [ 7 | { "x": 448, "y": 344, "type": "link", "path": "/Applications" }, 8 | { "x": 192, "y": 344, "type": "file", "path": "dist/Boostnote-darwin-x64/Boostnote.app" } 9 | ] 10 | 11 | } 12 | -------------------------------------------------------------------------------- /browser/components/CodeEditor.styl: -------------------------------------------------------------------------------- 1 | .codeEditor-typo 2 | text-decoration underline wavy red 3 | 4 | .spellcheck-select 5 | border: none 6 | -------------------------------------------------------------------------------- /browser/components/ColorPicker.styl: -------------------------------------------------------------------------------- 1 | .colorPicker 2 | position fixed 3 | z-index 2 4 | display flex 5 | flex-direction column 6 | 7 | .cover 8 | position fixed 9 | top 0 10 | right 0 11 | bottom 0 12 | left 0 13 | 14 | .footer 15 | display flex 16 | justify-content center 17 | z-index 2 18 | align-items center 19 | & > button + button 20 | margin-left 10px 21 | 22 | .btn-cancel, 23 | .btn-confirm, 24 | .btn-reset 25 | vertical-align middle 26 | height 25px 27 | margin-top 2.5px 28 | border-radius 2px 29 | border none 30 | padding 0 5px 31 | background-color $default-button-background 32 | &:hover 33 | background-color $default-button-background--hover 34 | .btn-confirm 35 | background-color #1EC38B 36 | &:hover 37 | background-color darken(#1EC38B, 25%) 38 | 39 | 40 | -------------------------------------------------------------------------------- /browser/components/MarkdownEditor.styl: -------------------------------------------------------------------------------- 1 | .root 2 | position relative 3 | 4 | .codeEditor 5 | absolute top bottom left right 6 | 7 | .hide 8 | z-index 0 9 | opacity 0 10 | pointer-events none 11 | 12 | .codeEditor--hide 13 | @extend .codeEditor 14 | @extend .hide 15 | 16 | .preview 17 | display block 18 | absolute top bottom left right 19 | background-color white 20 | height 100% 21 | width 100% 22 | 23 | .preview--hide 24 | @extend .preview 25 | @extend .hide 26 | 27 | -------------------------------------------------------------------------------- /browser/components/MarkdownSplitEditor.styl: -------------------------------------------------------------------------------- 1 | .root 2 | width 100% 3 | height 100% 4 | font-size 30px 5 | display flex 6 | flex-wrap wrap 7 | .slider 8 | absolute top bottom 9 | top -2px 10 | width 0 11 | z-index 0 12 | border-left 1px solid $ui-borderColor 13 | .slider-hitbox 14 | absolute top bottom left right 15 | width 7px 16 | left -3px 17 | z-index 10 18 | cursor col-resize 19 | .slider-hoz 20 | absolute left right 21 | .slider-hitbox 22 | absolute left right 23 | width: 100% 24 | height 7px 25 | cursor row-resize 26 | 27 | 28 | apply-theme(theme) 29 | body[data-theme={theme}] 30 | .root 31 | .slider 32 | border-left 1px solid get-theme-var(theme, 'borderColor') 33 | 34 | for theme in 'dark' 'dracula' 'solarized-dark' 35 | apply-theme(theme) 36 | 37 | for theme in $themes 38 | apply-theme(theme) -------------------------------------------------------------------------------- /browser/components/ModalEscButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './ModalEscButton.styl' 5 | 6 | const ModalEscButton = ({ handleEscButtonClick }) => ( 7 | 11 | ) 12 | 13 | ModalEscButton.propTypes = { 14 | handleEscButtonClick: PropTypes.func.isRequired 15 | } 16 | 17 | export default CSSModules(ModalEscButton, styles) 18 | -------------------------------------------------------------------------------- /browser/components/ModalEscButton.styl: -------------------------------------------------------------------------------- 1 | .escButton 2 | height 50px 3 | position absolute 4 | background-color transparent 5 | color $ui-inactive-text-color 6 | border none 7 | top 1px 8 | right 10px 9 | text-align center 10 | width top-bar--height 11 | height top-bar-height 12 | 13 | .esc-mark 14 | font-size 28px 15 | margin-top -5px 16 | margin-bottom -7px -------------------------------------------------------------------------------- /browser/components/NavToggleButton.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Micro component for toggle SideNav 3 | */ 4 | import PropTypes from 'prop-types' 5 | import React from 'react' 6 | import styles from './NavToggleButton.styl' 7 | import CSSModules from 'browser/lib/CSSModules' 8 | 9 | /** 10 | * @param {boolean} isFolded 11 | * @param {Function} handleToggleButtonClick 12 | */ 13 | 14 | const NavToggleButton = ({ isFolded, handleToggleButtonClick }) => ( 15 | 22 | ) 23 | 24 | NavToggleButton.propTypes = { 25 | isFolded: PropTypes.bool.isRequired, 26 | handleToggleButtonClick: PropTypes.func.isRequired 27 | } 28 | 29 | export default CSSModules(NavToggleButton, styles) 30 | -------------------------------------------------------------------------------- /browser/components/NavToggleButton.styl: -------------------------------------------------------------------------------- 1 | .navToggle 2 | navButtonColor() 3 | display block 4 | position absolute 5 | left 5px 6 | bottom 5px 7 | border-radius 16.5px 8 | height 34px 9 | width 34px 10 | line-height 100% 11 | padding 0 12 | &:hover 13 | border: 1px solid #1EC38B; 14 | background-color: alpha(#1EC38B, 30%) 15 | border-radius: 50%; 16 | 17 | body[data-theme="white"] 18 | navWhiteButtonColor() 19 | 20 | apply-theme(theme) 21 | body[data-theme={theme}] 22 | .navToggle:hover 23 | background-color alpha(get-theme-var(theme, 'button--active-backgroundColor'), 20%) 24 | border 1px solid get-theme-var(theme, 'button--active-backgroundColor') 25 | transition 0.15s 26 | color get-theme-var(theme, 'text-color') 27 | 28 | for theme in 'dark' 'dracula' 'solarized-dark' 29 | apply-theme(theme) 30 | 31 | for theme in $themes 32 | apply-theme(theme) -------------------------------------------------------------------------------- /browser/components/RealtimeNotification.styl: -------------------------------------------------------------------------------- 1 | .notification-area 2 | z-index 1000 3 | font-size 12px 4 | position: relative 5 | top: 12px 6 | background-color none 7 | 8 | .notification-link 9 | position absolute 10 | text-decoration none 11 | color #282A36 12 | font-size 14px 13 | border 1px solid #6FA8E6 14 | background-color alpha(#6FA8E6, 0.2) 15 | padding 5px 12px 16 | border-radius 2px 17 | transition 0.2s 18 | &:hover 19 | color #1378BD 20 | 21 | body[data-theme="dark"] 22 | .notification-area 23 | background-color none 24 | 25 | .notification-link 26 | color #fff 27 | border 1px solid alpha(#5CB85C, 0.6) 28 | background-color alpha(#5CB85C, 0.2) 29 | transition 0.2s 30 | &:hover 31 | color #5CB85C 32 | 33 | apply-theme(theme) 34 | body[data-theme={theme}] 35 | .notification-area 36 | background-color none 37 | 38 | .notification-link 39 | color get-theme-var(theme, 'text-color') 40 | border none 41 | background-color get-theme-var(theme, 'button-backgroundColor') 42 | &:hover 43 | color get-theme-var(theme, 'button--hover-color') 44 | 45 | for theme in 'solarized-dark' 'dracula' 46 | apply-theme(theme) 47 | 48 | for theme in $themes 49 | apply-theme(theme) -------------------------------------------------------------------------------- /browser/components/StorageList.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Micro component for showing StorageList 3 | */ 4 | import PropTypes from 'prop-types' 5 | import React from 'react' 6 | import styles from './StorageList.styl' 7 | import CSSModules from 'browser/lib/CSSModules' 8 | 9 | /** 10 | * @param {Array} storageList 11 | */ 12 | 13 | const StorageList = ({ storageList, isFolded }) => ( 14 |
15 | {storageList.length > 0 ? ( 16 | storageList 17 | ) : ( 18 |
No storage mount.
19 | )} 20 |
21 | ) 22 | 23 | StorageList.propTypes = { 24 | storageList: PropTypes.arrayOf(PropTypes.element).isRequired 25 | } 26 | export default CSSModules(StorageList, styles) 27 | -------------------------------------------------------------------------------- /browser/components/StorageList.styl: -------------------------------------------------------------------------------- 1 | .storageList 2 | absolute left right 3 | bottom 37px 4 | top 180px 5 | overflow-y auto 6 | 7 | .storageList-folded 8 | @extend .storageList 9 | width 44px 10 | 11 | .storageList-empty 12 | padding 0 10px 13 | margin-top 15px 14 | line-height 24px 15 | color $ui-inactive-text-color 16 | 17 | body[data-theme="dark"] 18 | .storageList-empty 19 | color $ui-dark-inactive-text-color 20 | 21 | .root-folded 22 | .storageList-empty 23 | white-space nowrap 24 | transform rotate(90deg) 25 | -------------------------------------------------------------------------------- /browser/components/TodoListPercentage.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Percentage of todo achievement. 3 | */ 4 | 5 | import PropTypes from 'prop-types' 6 | import React from 'react' 7 | import CSSModules from 'browser/lib/CSSModules' 8 | import styles from './TodoListPercentage.styl' 9 | 10 | /** 11 | * @param {number} percentageOfTodo 12 | */ 13 | 14 | const TodoListPercentage = ({ percentageOfTodo, onClearCheckboxClick }) => ( 15 |
19 |
20 |
21 |

{percentageOfTodo}%

22 |
23 |
24 |
25 |

onClearCheckboxClick(e)}> 26 | clear 27 |

28 |
29 |
30 | ) 31 | 32 | TodoListPercentage.propTypes = { 33 | percentageOfTodo: PropTypes.number.isRequired, 34 | onClearCheckboxClick: PropTypes.func.isRequired 35 | } 36 | 37 | export default CSSModules(TodoListPercentage, styles) 38 | -------------------------------------------------------------------------------- /browser/components/TodoProcess.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Percentage of todo achievement. 3 | */ 4 | 5 | import PropTypes from 'prop-types' 6 | import React from 'react' 7 | import CSSModules from 'browser/lib/CSSModules' 8 | import styles from './TodoProcess.styl' 9 | 10 | const TodoProcess = ({ 11 | todoStatus: { total: totalTodo, completed: completedTodo } 12 | }) => ( 13 |
0 ? '' : 'none' }} 16 | > 17 |
18 | 19 | {completedTodo} of {totalTodo} 20 |
21 |
22 |
26 |
27 |
28 | ) 29 | 30 | TodoProcess.propTypes = { 31 | todoStatus: PropTypes.exact({ 32 | total: PropTypes.number.isRequired, 33 | completed: PropTypes.number.isRequired 34 | }) 35 | } 36 | 37 | export default CSSModules(TodoProcess, styles) 38 | -------------------------------------------------------------------------------- /browser/components/TodoProcess.styl: -------------------------------------------------------------------------------- 1 | .todo-process 2 | font-size 12px 3 | display flex 4 | padding-top 15px 5 | width 85% 6 | 7 | .todo-process-text 8 | display inline-block 9 | padding-right 10px 10 | white-space nowrap 11 | text-overflow ellipsis 12 | color $ui-inactive-text-color 13 | i 14 | color $ui-inactive-text-color 15 | padding-right 5px 16 | 17 | .todo-process-bar 18 | display inline-block 19 | margin auto 20 | height 4px 21 | border-radius 10px 22 | background-color #DADFE1 23 | border-radius 2px 24 | flex-grow 1 25 | border 1px solid alpha(#6C7A89, 10%) 26 | 27 | .todo-process-bar--inner 28 | height 100% 29 | border-radius 5px 30 | background-color #6C7A89 31 | transition 0.3s 32 | 33 | 34 | body[data-theme="dark"] 35 | .todo-process 36 | color $ui-dark-text-color 37 | 38 | .todo-process-bar 39 | background-color #363A3D 40 | 41 | .todo-process-text 42 | color $ui-inactive-text-color 43 | 44 | .todo-process-bar--inner 45 | background-color: alpha(#939395, 50%) 46 | -------------------------------------------------------------------------------- /browser/lib/CSSModules.js: -------------------------------------------------------------------------------- 1 | import CSSModules from 'react-css-modules' 2 | 3 | export default function(component, styles) { 4 | return CSSModules(component, styles, { handleNotFoundStyleName: 'log' }) 5 | } 6 | -------------------------------------------------------------------------------- /browser/lib/Languages.js: -------------------------------------------------------------------------------- 1 | const languages = [ 2 | { 3 | name: 'Albanian', 4 | locale: 'sq' 5 | }, 6 | { 7 | name: 'Chinese (zh-CN)', 8 | locale: 'zh-CN' 9 | }, 10 | { 11 | name: 'Chinese (zh-TW)', 12 | locale: 'zh-TW' 13 | }, 14 | { 15 | name: 'Czech', 16 | locale: 'cs' 17 | }, 18 | { 19 | name: 'Danish', 20 | locale: 'da' 21 | }, 22 | { 23 | name: 'English', 24 | locale: 'en' 25 | }, 26 | { 27 | name: 'French', 28 | locale: 'fr' 29 | }, 30 | { 31 | name: 'German', 32 | locale: 'de' 33 | }, 34 | { 35 | name: 'Hungarian', 36 | locale: 'hu' 37 | }, 38 | { 39 | name: 'Japanese', 40 | locale: 'ja' 41 | }, 42 | { 43 | name: 'Korean', 44 | locale: 'ko' 45 | }, 46 | { 47 | name: 'Norwegian', 48 | locale: 'no' 49 | }, 50 | { 51 | name: 'Polish', 52 | locale: 'pl' 53 | }, 54 | { 55 | name: 'Portuguese (PT-BR)', 56 | locale: 'pt-BR' 57 | }, 58 | { 59 | name: 'Portuguese (PT-PT)', 60 | locale: 'pt-PT' 61 | }, 62 | { 63 | name: 'Russian', 64 | locale: 'ru' 65 | }, 66 | { 67 | name: 'Spanish', 68 | locale: 'es-ES' 69 | }, 70 | { 71 | name: 'Turkish', 72 | locale: 'tr' 73 | }, 74 | { 75 | name: 'Thai', 76 | locale: 'th' 77 | } 78 | ] 79 | 80 | module.exports = { 81 | getLocales() { 82 | return languages.reduce(function(localeList, locale) { 83 | localeList.push(locale.locale) 84 | return localeList 85 | }, []) 86 | }, 87 | getLanguages() { 88 | return languages 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /browser/lib/RcParser.js: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import sander from 'sander' 3 | 4 | const BOOSTNOTERC = '.boostnoterc' 5 | const homePath = global.process.env.HOME || global.process.env.USERPROFILE 6 | const _boostnotercPath = path.join(homePath, BOOSTNOTERC) 7 | 8 | export function parse(boostnotercPath = _boostnotercPath) { 9 | if (!sander.existsSync(boostnotercPath)) return {} 10 | try { 11 | return JSON.parse(sander.readFileSync(boostnotercPath).toString()) 12 | } catch (e) { 13 | console.warn(e) 14 | console.warn("Your .boostnoterc is broken so it's not used.") 15 | return {} 16 | } 17 | } 18 | 19 | export default { 20 | parse 21 | } 22 | -------------------------------------------------------------------------------- /browser/lib/confirmDeleteNote.js: -------------------------------------------------------------------------------- 1 | import electron from 'electron' 2 | import i18n from 'browser/lib/i18n' 3 | const { remote } = electron 4 | const { dialog } = remote 5 | 6 | export function confirmDeleteNote(confirmDeletion, permanent) { 7 | if (confirmDeletion || permanent) { 8 | const alertConfig = { 9 | type: 'warning', 10 | message: i18n.__('Confirm note deletion'), 11 | detail: i18n.__('This will permanently remove this note.'), 12 | buttons: [i18n.__('Confirm'), i18n.__('Cancel')] 13 | } 14 | 15 | const dialogButtonIndex = dialog.showMessageBox( 16 | remote.getCurrentWindow(), 17 | alertConfig 18 | ) 19 | 20 | return dialogButtonIndex === 0 21 | } 22 | 23 | return true 24 | } 25 | -------------------------------------------------------------------------------- /browser/lib/context.js: -------------------------------------------------------------------------------- 1 | const { remote } = require('electron') 2 | const { Menu, MenuItem } = remote 3 | 4 | function popup(templates) { 5 | const menu = new Menu() 6 | templates.forEach(item => { 7 | menu.append(new MenuItem(item)) 8 | }) 9 | menu.popup(remote.getCurrentWindow()) 10 | } 11 | 12 | const context = { 13 | popup 14 | } 15 | 16 | module.export = context 17 | export default context 18 | -------------------------------------------------------------------------------- /browser/lib/convertModeName.js: -------------------------------------------------------------------------------- 1 | export default function convertModeName(name) { 2 | switch (name) { 3 | case 'ejs': 4 | return 'Embedded Javascript' 5 | case 'html_ruby': 6 | return 'Embedded Ruby' 7 | case 'objectivec': 8 | return 'Objective C' 9 | case 'text': 10 | return 'Plain Text' 11 | default: 12 | return name 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /browser/lib/customMeta.js: -------------------------------------------------------------------------------- 1 | import CodeMirror from 'codemirror' 2 | import 'codemirror-mode-elixir' 3 | 4 | const stylusCodeInfo = CodeMirror.modeInfo.find(info => info.name === 'Stylus') 5 | if (stylusCodeInfo == null) { 6 | CodeMirror.modeInfo.push({ 7 | name: 'Stylus', 8 | mime: 'text/x-styl', 9 | mode: 'stylus', 10 | ext: ['styl'], 11 | alias: ['styl'] 12 | }) 13 | } else { 14 | stylusCodeInfo.alias = ['styl'] 15 | } 16 | CodeMirror.modeInfo.push({ 17 | name: 'Elixir', 18 | mime: 'text/x-elixir', 19 | mode: 'elixir', 20 | ext: ['ex'] 21 | }) 22 | -------------------------------------------------------------------------------- /browser/lib/date-formatter.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Formatting date string. 3 | */ 4 | import moment from 'moment' 5 | 6 | /** 7 | * @description Return date string. For example, 'Sep.9, 2016 12:00'. 8 | * @param {mixed} 9 | * @return {string} 10 | */ 11 | export function formatDate(date) { 12 | const m = moment(date) 13 | if (!m.isValid()) { 14 | throw Error('Invalid argument.') 15 | } 16 | 17 | return m.format('MMM D, gggg H:mm') 18 | } 19 | -------------------------------------------------------------------------------- /browser/lib/findStorage.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash') 2 | 3 | export function findStorage(storageKey) { 4 | const cachedStorageList = JSON.parse(localStorage.getItem('storages')) 5 | if (!_.isArray(cachedStorageList)) 6 | throw new Error("Target storage doesn't exist.") 7 | const storage = _.find(cachedStorageList, { key: storageKey }) 8 | if (storage === undefined) throw new Error("Target storage doesn't exist.") 9 | 10 | return storage 11 | } 12 | 13 | export default { 14 | findStorage 15 | } 16 | -------------------------------------------------------------------------------- /browser/lib/getTodoStatus.js: -------------------------------------------------------------------------------- 1 | export function getTodoStatus(content) { 2 | const splitted = content.split('\n') 3 | let numberOfTodo = 0 4 | let numberOfCompletedTodo = 0 5 | 6 | splitted.forEach(line => { 7 | const trimmedLine = line.trim().replace(/^(>\s*)*/, '') 8 | if (trimmedLine.match(/^[+\-*] \[(\s|x)] ./i)) { 9 | numberOfTodo++ 10 | } 11 | if (trimmedLine.match(/^[+\-*] \[x] ./i)) { 12 | numberOfCompletedTodo++ 13 | } 14 | }) 15 | 16 | return { 17 | total: numberOfTodo, 18 | completed: numberOfCompletedTodo 19 | } 20 | } 21 | 22 | export function getTodoPercentageOfCompleted(content) { 23 | const state = getTodoStatus(content) 24 | return Math.floor((state.completed / state.total) * 100) 25 | } 26 | -------------------------------------------------------------------------------- /browser/lib/htmlTextHelper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Text trimmer for html. 3 | */ 4 | 5 | /** 6 | * @param {string} text 7 | * @return {string} 8 | */ 9 | 10 | export function decodeEntities(text) { 11 | var entities = [ 12 | ['apos', "'"], 13 | ['amp', '&'], 14 | ['lt', '<'], 15 | ['gt', '>'], 16 | ['#63', '\\?'], 17 | ['#36', '\\$'] 18 | ] 19 | 20 | for (var i = 0, max = entities.length; i < max; ++i) { 21 | text = text.replace(new RegExp(`&${entities[i][0]};`, 'g'), entities[i][1]) 22 | } 23 | 24 | return text 25 | } 26 | 27 | export function encodeEntities(text) { 28 | const entities = [ 29 | ["'", 'apos'], 30 | ['<', 'lt'], 31 | ['>', 'gt'], 32 | ['\\?', '#63'], 33 | ['\\$', '#36'] 34 | ] 35 | 36 | entities.forEach(entity => { 37 | text = text.replace(new RegExp(entity[0], 'g'), `&${entity[1]};`) 38 | }) 39 | return text 40 | } 41 | 42 | export default { 43 | decodeEntities, 44 | encodeEntities 45 | } 46 | -------------------------------------------------------------------------------- /browser/lib/i18n.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const { remote } = require('electron') 3 | const { app } = remote 4 | const { getLocales } = require('./Languages.js') 5 | 6 | // load package for localization 7 | const i18n = new (require('i18n-2'))({ 8 | // setup some locales - other locales default to the first locale 9 | locales: getLocales(), 10 | extension: '.json', 11 | directory: 12 | process.env.NODE_ENV === 'production' 13 | ? path.join(app.getAppPath(), './locales') 14 | : path.resolve('./locales'), 15 | devMode: false 16 | }) 17 | 18 | export default i18n 19 | -------------------------------------------------------------------------------- /browser/lib/keygen.js: -------------------------------------------------------------------------------- 1 | const crypto = require('crypto') 2 | const uuidv4 = require('uuid/v4') 3 | 4 | module.exports = function(uuid) { 5 | if (typeof uuid === typeof true && uuid) { 6 | return uuidv4() 7 | } 8 | const length = 10 9 | return crypto.randomBytes(length).toString('hex') 10 | } 11 | -------------------------------------------------------------------------------- /browser/lib/markdown-it-frontmatter.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = function frontMatterPlugin(md) { 4 | function frontmatter(state, startLine, endLine, silent) { 5 | if ( 6 | startLine !== 0 || 7 | state.src.substr(startLine, state.eMarks[0]) !== '---' 8 | ) { 9 | return false 10 | } 11 | 12 | let line = 0 13 | while (++line < state.lineMax) { 14 | if ( 15 | state.src.substring(state.bMarks[line], state.eMarks[line]) === '---' 16 | ) { 17 | state.line = line + 1 18 | 19 | return true 20 | } 21 | } 22 | 23 | return false 24 | } 25 | 26 | md.block.ruler.before('table', 'frontmatter', frontmatter, { 27 | alt: ['paragraph', 'reference', 'blockquote', 'list'] 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /browser/lib/markdown2.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/browser/lib/markdown2.js -------------------------------------------------------------------------------- /browser/lib/markdownTextHelper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Text trimmer for markdown note. 3 | */ 4 | 5 | /** 6 | * @param {string} input 7 | * @return {string} 8 | */ 9 | export function strip(input) { 10 | let output = input 11 | try { 12 | output = output 13 | .replace(/^([\s\t]*)([\*\-\+]|\d+\.)\s+/gm, '$1') 14 | .replace(/\n={2,}/g, '\n') 15 | .replace(/~~/g, '') 16 | .replace(/`{3}.*\n/g, '') 17 | .replace(/<(.*?)>/g, '$1') 18 | .replace(/^[=\-]{2,}\s*$/g, '') 19 | .replace(/\[\^.+?\](: .*?$)?/g, '') 20 | .replace(/\s{0,2}\[.*?\]: .*?$/g, '') 21 | .replace(/!\[.*?\][\[\(].*?[\]\)]/g, '') 22 | .replace(/\[(.*?)\][\[\(].*?[\]\)]/g, '$1') 23 | .replace(/>/g, '') 24 | .replace(/^\s{1,2}\[(.*?)\]: (\S+)( ".*?")?\s*$/g, '') 25 | .replace(/^#{1,6}\s*/gm, '') 26 | .replace(/(`{3,})(.*?)\1/gm, '$2') 27 | .replace(/^-{3,}\s*$/g, '') 28 | .replace(/`(.+?)`/g, '$1') 29 | .replace(/\n{2,}/g, '\n\n') 30 | } catch (e) { 31 | console.error(e) 32 | return input 33 | } 34 | return output 35 | } 36 | 37 | export default { 38 | strip 39 | } 40 | -------------------------------------------------------------------------------- /browser/lib/normalizeEditorFontFamily.js: -------------------------------------------------------------------------------- 1 | import consts from 'browser/lib/consts' 2 | import isString from 'lodash/isString' 3 | 4 | export default function normalizeEditorFontFamily(fontFamily) { 5 | const defaultEditorFontFamily = consts.DEFAULT_EDITOR_FONT_FAMILY 6 | return isString(fontFamily) && fontFamily.length > 0 7 | ? [fontFamily].concat(defaultEditorFontFamily).join(', ') 8 | : defaultEditorFontFamily.join(', ') 9 | } 10 | -------------------------------------------------------------------------------- /browser/lib/search.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash' 2 | 3 | export default function searchFromNotes(notes, search) { 4 | if (search.trim().length === 0) return [] 5 | const searchBlocks = search.split(' ').filter(block => { 6 | return block !== '' 7 | }) 8 | 9 | let foundNotes = notes 10 | searchBlocks.forEach(block => { 11 | foundNotes = findByWordOrTag(foundNotes, block) 12 | }) 13 | return foundNotes 14 | } 15 | 16 | function findByWordOrTag(notes, block) { 17 | let tag = block 18 | if (tag.match(/^#.+/)) { 19 | tag = tag.match(/#(.+)/)[1] 20 | } 21 | const tagRegExp = new RegExp(_.escapeRegExp(tag), 'i') 22 | const wordRegExp = new RegExp(_.escapeRegExp(block), 'i') 23 | return notes.filter(note => { 24 | if (_.isArray(note.tags) && note.tags.some(_tag => _tag.match(tagRegExp))) { 25 | return true 26 | } 27 | if (note.type === 'SNIPPET_NOTE') { 28 | return ( 29 | note.description.match(wordRegExp) || 30 | note.snippets.some(snippet => { 31 | return ( 32 | snippet.name.match(wordRegExp) || snippet.content.match(wordRegExp) 33 | ) 34 | }) 35 | ) 36 | } else if (note.type === 'MARKDOWN_NOTE') { 37 | return note.content.match(wordRegExp) 38 | } 39 | return false 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /browser/lib/slugify.js: -------------------------------------------------------------------------------- 1 | module.exports = function slugify(title) { 2 | const slug = encodeURI( 3 | title 4 | .trim() 5 | .replace(/^\s+/, '') 6 | .replace(/\s+$/, '') 7 | .replace(/\s+/g, '-') 8 | .replace( 9 | /[\]\[\!\'\#\$\%\&\(\)\*\+\,\.\/\:\;\<\=\>\?\@\\\^\{\|\}\~\`]/g, 10 | '' 11 | ) 12 | ) 13 | 14 | return slug 15 | } 16 | -------------------------------------------------------------------------------- /browser/lib/turndown.js: -------------------------------------------------------------------------------- 1 | const TurndownService = require('turndown') 2 | const { gfm } = require('turndown-plugin-gfm') 3 | 4 | export const createTurndownService = function() { 5 | const turndown = new TurndownService() 6 | turndown.use(gfm) 7 | turndown.remove('script') 8 | return turndown 9 | } 10 | -------------------------------------------------------------------------------- /browser/lib/ui-themes.js: -------------------------------------------------------------------------------- 1 | import i18n from 'browser/lib/i18n' 2 | 3 | export default [ 4 | { 5 | name: 'dark', 6 | label: i18n.__('Dark'), 7 | isDark: true 8 | }, 9 | { 10 | name: 'default', 11 | label: i18n.__('Default'), 12 | isDark: false 13 | }, 14 | { 15 | name: 'dracula', 16 | label: i18n.__('Dracula'), 17 | isDark: true 18 | }, 19 | { 20 | name: 'monokai', 21 | label: i18n.__('Monokai'), 22 | isDark: true 23 | }, 24 | { 25 | name: 'nord', 26 | label: i18n.__('Nord'), 27 | isDark: true 28 | }, 29 | { 30 | name: 'solarized-dark', 31 | label: i18n.__('Solarized Dark'), 32 | isDark: true 33 | }, 34 | { 35 | name: 'vulcan', 36 | label: i18n.__('Vulcan'), 37 | isDark: true 38 | }, 39 | { 40 | name: 'white', 41 | label: i18n.__('White'), 42 | isDark: false 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /browser/lib/wakatime-plugin.js: -------------------------------------------------------------------------------- 1 | import config from 'browser/main/lib/ConfigManager' 2 | const exec = require('child_process').exec 3 | const path = require('path') 4 | let lastHeartbeat = 0 5 | 6 | function sendWakatimeHeartBeat( 7 | storagePath, 8 | noteKey, 9 | storageName, 10 | { isWrite, hasFileChanges, isFileChange } 11 | ) { 12 | if ( 13 | config.get().wakatime.isActive && 14 | !!config.get().wakatime.key && 15 | (new Date().getTime() - lastHeartbeat > 120000 || isFileChange) 16 | ) { 17 | const notePath = path.join(storagePath, 'notes', noteKey + '.cson') 18 | 19 | if (!isWrite && !hasFileChanges && !isFileChange) { 20 | return 21 | } 22 | 23 | lastHeartbeat = new Date() 24 | const wakatimeKey = config.get().wakatime.key 25 | if (wakatimeKey) { 26 | exec( 27 | `wakatime --file ${notePath} --project '${storageName}' --key ${wakatimeKey} --plugin Boostnote-wakatime`, 28 | (error, stdOut, stdErr) => { 29 | if (error) { 30 | console.log(error) 31 | lastHeartbeat = 0 32 | } else { 33 | console.log( 34 | 'wakatime', 35 | 'isWrite', 36 | isWrite, 37 | 'hasChanges', 38 | hasFileChanges, 39 | 'isFileChange', 40 | isFileChange 41 | ) 42 | } 43 | } 44 | ) 45 | } 46 | } 47 | } 48 | 49 | export { sendWakatimeHeartBeat } 50 | -------------------------------------------------------------------------------- /browser/main/Detail/Detail.styl: -------------------------------------------------------------------------------- 1 | .root 2 | absolute top bottom right 3 | display flex 4 | align-items center 5 | justify-content center 6 | 7 | .empty 8 | height 320px 9 | display flex 10 | align-items center 11 | 12 | .empty-message 13 | width 100% 14 | font-size 36px 15 | font-weight 600 16 | line-height 56px 17 | text-align center 18 | color $ui-inactive-text-color 19 | 20 | body[data-theme="dark"] 21 | .root 22 | background-color $ui-dark-backgroundColor 23 | border-left 1px solid $ui-dark-borderColor 24 | .empty-message 25 | color $ui-dark-inactive-text-color 26 | 27 | apply-theme(theme) 28 | body[data-theme={theme}] 29 | .root 30 | background-color get-theme-var(theme, 'noteDetail-backgroundColor') 31 | border-left 1px solid get-theme-var(theme, 'borderColor') 32 | .empty-message 33 | color get-theme-var(theme, 'text-color') 34 | 35 | for theme in 'solarized-dark' 'dracula' 36 | apply-theme(theme) 37 | 38 | for theme in $themes 39 | apply-theme(theme) -------------------------------------------------------------------------------- /browser/main/Detail/DetailVars.styl: -------------------------------------------------------------------------------- 1 | /** 2 | * Varibales for note detail space. 3 | */ 4 | 5 | // Margin on the left side and the right side for NoteDetail component. 6 | $note-detail-left-margin = 100px 7 | $note-detail-right-margin = 120px 8 | $snippet-note-detail-left-margin = 60px 9 | $snippet-note-detail-right-margin = 80px 10 | 11 | $note-detail-box-shadow = 2px 0 15px -8px #b1b1b1 inset 12 | -------------------------------------------------------------------------------- /browser/main/Detail/FromUrlButton.styl: -------------------------------------------------------------------------------- 1 | .root 2 | top 45px 3 | topBarButtonRight() 4 | &:hover 5 | transition 0.2s 6 | color alpha($ui-favorite-star-button-color, 0.6) 7 | &:hover .tooltip 8 | opacity 1 9 | 10 | .tooltip 11 | tooltip() 12 | position absolute 13 | pointer-events none 14 | top 50px 15 | right 125px 16 | width 90px 17 | z-index 200 18 | padding 5px 19 | line-height normal 20 | border-radius 2px 21 | opacity 0 22 | transition 0.1s 23 | 24 | .root--active 25 | @extend .root 26 | transition 0.15s 27 | color $ui-favorite-star-button-color 28 | &:hover 29 | transition 0.2s 30 | color alpha($ui-favorite-star-button-color, 0.6) 31 | 32 | .icon 33 | transition transform 0.15s 34 | height 13px 35 | 36 | body[data-theme="dark"] 37 | .root 38 | topBarButtonDark() 39 | &:hover 40 | transition 0.2s 41 | color alpha($ui-favorite-star-button-color, 0.6) 42 | -------------------------------------------------------------------------------- /browser/main/Detail/FullscreenButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './FullscreenButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const OSX = global.process.platform === 'darwin' 8 | const FullscreenButton = ({ onClick }) => { 9 | const hotkey = (OSX ? i18n.__('Command(⌘)') : i18n.__('Ctrl(^)')) + '+B' 10 | return ( 11 | 21 | ) 22 | } 23 | 24 | FullscreenButton.propTypes = { 25 | onClick: PropTypes.func.isRequired 26 | } 27 | 28 | export default CSSModules(FullscreenButton, styles) 29 | -------------------------------------------------------------------------------- /browser/main/Detail/FullscreenButton.styl: -------------------------------------------------------------------------------- 1 | .control-fullScreenButton 2 | top 80px 3 | topBarButtonRight() 4 | &:hover .tooltip 5 | opacity 1 6 | 7 | .tooltip 8 | tooltip() 9 | position absolute 10 | pointer-events none 11 | top 50px 12 | right 70px 13 | z-index 200 14 | padding 5px 15 | line-height normal 16 | border-radius 2px 17 | opacity 0 18 | transition 0.1s 19 | 20 | .tooltip:lang(ja) 21 | @extend .tooltip 22 | right 35px 23 | 24 | body[data-theme="dark"] 25 | .control-fullScreenButton 26 | topBarButtonDark() -------------------------------------------------------------------------------- /browser/main/Detail/InfoButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './InfoButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const InfoButton = ({ onClick }) => ( 8 | 12 | ) 13 | 14 | InfoButton.propTypes = { 15 | onClick: PropTypes.func.isRequired 16 | } 17 | 18 | export default CSSModules(InfoButton, styles) 19 | -------------------------------------------------------------------------------- /browser/main/Detail/InfoButton.styl: -------------------------------------------------------------------------------- 1 | .control-infoButton 2 | top 10px 3 | topBarButtonRight() 4 | &:hover .tooltip 5 | opacity 1 6 | 7 | .tooltip 8 | tooltip() 9 | position absolute 10 | pointer-events none 11 | top 50px 12 | right 20px 13 | z-index 200 14 | padding 5px 15 | line-height normal 16 | border-radius 2px 17 | opacity 0 18 | transition 0.1s 19 | 20 | .infoButton 21 | padding 0px 22 | 23 | body[data-theme="dark"] 24 | .control-infoButton 25 | topBarButtonDark() 26 | -------------------------------------------------------------------------------- /browser/main/Detail/PermanentDeleteButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './TrashButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const PermanentDeleteButton = ({ onClick }) => ( 8 | 12 | ) 13 | 14 | PermanentDeleteButton.propTypes = { 15 | onClick: PropTypes.func.isRequired 16 | } 17 | 18 | export default CSSModules(PermanentDeleteButton, styles) 19 | -------------------------------------------------------------------------------- /browser/main/Detail/RestoreButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './RestoreButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const RestoreButton = ({ onClick }) => ( 8 | 12 | ) 13 | 14 | RestoreButton.propTypes = { 15 | onClick: PropTypes.func.isRequired 16 | } 17 | 18 | export default CSSModules(RestoreButton, styles) 19 | -------------------------------------------------------------------------------- /browser/main/Detail/RestoreButton.styl: -------------------------------------------------------------------------------- 1 | .control-restoreButton 2 | top 115px 3 | topBarButtonRight() 4 | &:hover .tooltip 5 | opacity 1 6 | 7 | .tooltip 8 | tooltip() 9 | position absolute 10 | pointer-events none 11 | top 50px 12 | left 25px 13 | z-index 200 14 | padding 5px 15 | line-height normal 16 | border-radius 2px 17 | opacity 0 18 | transition 0.1s 19 | 20 | body[data-theme="dark"] 21 | .control-restoreButton 22 | topBarButtonDark() 23 | -------------------------------------------------------------------------------- /browser/main/Detail/StarButton.styl: -------------------------------------------------------------------------------- 1 | .root 2 | top 45px 3 | topBarButtonRight() 4 | &:hover 5 | transition 0.2s 6 | color alpha($ui-favorite-star-button-color, 0.6) 7 | &:hover .tooltip 8 | opacity 1 9 | 10 | .tooltip 11 | tooltip() 12 | position absolute 13 | pointer-events none 14 | top 50px 15 | right 115px 16 | width 40px 17 | z-index 200 18 | padding 5px 19 | line-height normal 20 | border-radius 2px 21 | opacity 0 22 | transition 0.1s 23 | 24 | .tooltip:lang(ja) 25 | @extend .tooltip 26 | right 103px 27 | width 70px 28 | 29 | .root--active 30 | @extend .root 31 | transition 0.15s 32 | color $ui-favorite-star-button-color 33 | &:hover 34 | transition 0.2s 35 | color alpha($ui-favorite-star-button-color, 0.6) 36 | 37 | .icon 38 | transition transform 0.15s 39 | 40 | body[data-theme="dark"] 41 | .root 42 | topBarButtonDark() 43 | &:hover 44 | transition 0.2s 45 | color alpha($ui-favorite-star-button-color, 0.6) 46 | -------------------------------------------------------------------------------- /browser/main/Detail/ToggleDirectionButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './ToggleDirectionButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const ToggleDirectionButton = ({ onClick, isRTL }) => ( 8 |
9 |
onClick()}> 10 | 11 |
12 |
onClick()}> 13 | 14 |
15 | 16 | {i18n.__('Toggle Direction')} 17 | 18 |
19 | ) 20 | 21 | ToggleDirectionButton.propTypes = { 22 | onClick: PropTypes.func.isRequired, 23 | isRTL: PropTypes.bool.isRequired 24 | } 25 | 26 | export default CSSModules(ToggleDirectionButton, styles) 27 | -------------------------------------------------------------------------------- /browser/main/Detail/ToggleModeButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './ToggleModeButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const ToggleModeButton = ({ onClick, editorType }) => ( 8 |
9 |
onClick('SPLIT')} 12 | > 13 | 20 |
21 |
onClick('EDITOR_PREVIEW')} 24 | > 25 | 32 |
33 | 34 | {i18n.__('Toggle Mode')} 35 | 36 |
37 | ) 38 | 39 | ToggleModeButton.propTypes = { 40 | onClick: PropTypes.func.isRequired, 41 | editorType: PropTypes.string.isRequired 42 | } 43 | 44 | export default CSSModules(ToggleModeButton, styles) 45 | -------------------------------------------------------------------------------- /browser/main/Detail/TrashButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './TrashButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const TrashButton = ({ onClick }) => ( 8 | 14 | ) 15 | 16 | TrashButton.propTypes = { 17 | onClick: PropTypes.func.isRequired 18 | } 19 | 20 | export default CSSModules(TrashButton, styles) 21 | -------------------------------------------------------------------------------- /browser/main/Detail/TrashButton.styl: -------------------------------------------------------------------------------- 1 | .control-trashButton 2 | top 115px 3 | topBarButtonRight() 4 | &:hover .tooltip 5 | opacity 1 6 | 7 | .tooltip 8 | tooltip() 9 | position absolute 10 | pointer-events none 11 | top 50px 12 | right 50px 13 | z-index 200 14 | padding 5px 15 | line-height normal 16 | border-radius 2px 17 | opacity 0 18 | transition 0.1s 19 | 20 | .tooltip:lang(ja) 21 | @extend .tooltip 22 | right 46px 23 | 24 | .control-trashButton--in-trash 25 | top 60px 26 | topBarButtonRight() 27 | 28 | .trashButton 29 | padding 0px 30 | 31 | body[data-theme="dark"] 32 | .control-trashButton 33 | topBarButtonDark() 34 | -------------------------------------------------------------------------------- /browser/main/DevTools/index.dev.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { createDevTools } from 'redux-devtools' 3 | import LogMonitor from 'redux-devtools-log-monitor' 4 | import DockMonitor from 'redux-devtools-dock-monitor' 5 | 6 | const DevTools = createDevTools( 7 | 12 | 13 | 14 | ) 15 | 16 | export default DevTools 17 | -------------------------------------------------------------------------------- /browser/main/DevTools/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-undef */ 2 | if (process.env.NODE_ENV === 'development') { 3 | // eslint-disable-next-line global-require 4 | module.exports = require('./index.dev').default 5 | } else { 6 | // eslint-disable-next-line global-require 7 | module.exports = require('./index.prod').default 8 | } 9 | -------------------------------------------------------------------------------- /browser/main/DevTools/index.prod.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const DevTools = () =>
4 | DevTools.instrument = () => {} 5 | 6 | export default DevTools 7 | -------------------------------------------------------------------------------- /browser/main/Main.styl: -------------------------------------------------------------------------------- 1 | .root 2 | absolute top left bottom right 3 | 4 | .body 5 | absolute right top bottom 6 | left $sideNav-width 7 | 8 | .body--expanded 9 | @extend .body 10 | left $sideNav--folded-width 11 | 12 | .slider 13 | absolute top bottom 14 | top -2px 15 | width 0 16 | z-index 0 17 | 18 | .slider-right 19 | @extend .slider 20 | width 1px 21 | z-index 0 22 | 23 | .slider--active 24 | @extend .slider 25 | 26 | .slider-right--active 27 | @extend .slider-right 28 | 29 | .slider-hitbox 30 | absolute top bottom left right 31 | width 7px 32 | left -3px 33 | z-index 10 34 | cursor col-resize 35 | 36 | 37 | body[data-theme="dark"] 38 | .root 39 | absolute top left bottom right 40 | 41 | .slider-right 42 | .slider-right--active 43 | box-shadow none 44 | -------------------------------------------------------------------------------- /browser/main/SideNav/ListButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './SwitchButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const ListButton = ({ onClick, isTagActive }) => ( 8 | 21 | ) 22 | 23 | ListButton.propTypes = { 24 | onClick: PropTypes.func.isRequired, 25 | isTagActive: PropTypes.bool.isRequired 26 | } 27 | 28 | export default CSSModules(ListButton, styles) 29 | -------------------------------------------------------------------------------- /browser/main/SideNav/PreferenceButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './PreferenceButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const PreferenceButton = ({ onClick }) => ( 8 | 12 | ) 13 | 14 | PreferenceButton.propTypes = { 15 | onClick: PropTypes.func.isRequired 16 | } 17 | 18 | export default CSSModules(PreferenceButton, styles) 19 | -------------------------------------------------------------------------------- /browser/main/SideNav/PreferenceButton.styl: -------------------------------------------------------------------------------- 1 | .top-menu-preference 2 | navButtonColor() 3 | width 2em 4 | background-color transparent 5 | &:hover 6 | color $ui-button-default--active-backgroundColor 7 | background-color transparent 8 | .tooltip 9 | opacity 1 10 | &:active, &:active:hover 11 | color $ui-button-default--active-backgroundColor 12 | 13 | body[data-theme="white"] 14 | .top-menu-preference 15 | navWhiteButtonColor() 16 | background-color transparent 17 | &:hover 18 | color #0B99F1 19 | background-color transparent 20 | &:active, &:active:hover 21 | color #0B99F1 22 | background-color transparent 23 | 24 | body[data-theme="dark"] 25 | .top-menu-preference 26 | navDarkButtonColor() 27 | background-color transparent 28 | &:active 29 | background-color alpha($ui-dark-button--active-backgroundColor, 20%) 30 | background-color transparent 31 | &:hover 32 | background-color alpha($ui-dark-button--active-backgroundColor, 20%) 33 | background-color transparent 34 | 35 | .tooltip 36 | tooltip() 37 | position absolute 38 | pointer-events none 39 | top 26px 40 | left -20px 41 | z-index 200 42 | padding 5px 43 | line-height normal 44 | border-radius 2px 45 | opacity 0 46 | transition 0.1s 47 | white-space nowrap 48 | -------------------------------------------------------------------------------- /browser/main/SideNav/SearchButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './SearchButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const SearchButton = ({ onClick, isActive }) => ( 8 | 19 | ) 20 | 21 | SearchButton.propTypes = { 22 | onClick: PropTypes.func.isRequired, 23 | isActive: PropTypes.bool 24 | } 25 | 26 | export default CSSModules(SearchButton, styles) 27 | -------------------------------------------------------------------------------- /browser/main/SideNav/SearchButton.styl: -------------------------------------------------------------------------------- 1 | .top-menu-search 2 | navButtonColor() 3 | position relative 4 | margin-right 6px 5 | top 3px 6 | width 2em 7 | background-color transparent 8 | &:hover 9 | color $ui-button-default--active-backgroundColor 10 | background-color transparent 11 | .tooltip 12 | opacity 1 13 | &:active, &:active:hover 14 | color $ui-button-default--active-backgroundColor 15 | 16 | .icon-search 17 | width 16px 18 | 19 | body[data-theme="white"] 20 | .top-menu-search 21 | navWhiteButtonColor() 22 | background-color transparent 23 | &:hover 24 | color #0B99F1 25 | background-color transparent 26 | &:active, &:active:hover 27 | color #0B99F1 28 | background-color transparent 29 | 30 | body[data-theme="dark"] 31 | .top-menu-search 32 | navDarkButtonColor() 33 | background-color transparent 34 | &:active 35 | background-color alpha($ui-dark-button--active-backgroundColor, 20%) 36 | background-color transparent 37 | &:hover 38 | background-color alpha($ui-dark-button--active-backgroundColor, 20%) 39 | background-color transparent 40 | 41 | 42 | 43 | .tooltip 44 | tooltip() 45 | position absolute 46 | pointer-events none 47 | top 26px 48 | left -20px 49 | z-index 200 50 | padding 5px 51 | line-height normal 52 | border-radius 2px 53 | opacity 0 54 | transition 0.1s 55 | white-space nowrap 56 | -------------------------------------------------------------------------------- /browser/main/SideNav/SwitchButton.styl: -------------------------------------------------------------------------------- 1 | .non-active-button 2 | color $ui-inactive-text-color 3 | font-size 16px 4 | border 0 5 | background-color transparent 6 | transition 0.2s 7 | display flex 8 | text-align center 9 | margin-right 4px 10 | position relative 11 | &:hover 12 | color alpha(#239F86, 60%) 13 | .tooltip 14 | opacity 1 15 | 16 | .active-button 17 | @extend .non-active-button 18 | color $ui-button-default--active-backgroundColor 19 | 20 | .tooltip 21 | tooltip() 22 | position absolute 23 | pointer-events none 24 | top 22px 25 | left -2px 26 | z-index 200 27 | padding 5px 28 | line-height normal 29 | border-radius 2px 30 | opacity 0 31 | transition 0.1s 32 | white-space nowrap 33 | 34 | body[data-theme="white"] 35 | .non-active-button 36 | color $ui-inactive-text-color 37 | &:hover 38 | color alpha(#0B99F1, 60%) 39 | 40 | .tag-title 41 | p 42 | color $ui-text-color 43 | 44 | .non-active-button 45 | &:hover 46 | color alpha(#0B99F1, 60%) 47 | 48 | .active-button 49 | @extend .non-active-button 50 | color #0B99F1 51 | 52 | body[data-theme="dark"] 53 | .non-active-button 54 | color alpha($ui-dark-text-color, 60%) 55 | &:hover 56 | color alpha(#0B99F1, 60%) 57 | 58 | .tag-title 59 | p 60 | color alpha($ui-dark-text-color, 60%) -------------------------------------------------------------------------------- /browser/main/SideNav/TagButton.js: -------------------------------------------------------------------------------- 1 | import PropTypes from 'prop-types' 2 | import React from 'react' 3 | import CSSModules from 'browser/lib/CSSModules' 4 | import styles from './SwitchButton.styl' 5 | import i18n from 'browser/lib/i18n' 6 | 7 | const TagButton = ({ onClick, isTagActive }) => ( 8 | 21 | ) 22 | 23 | TagButton.propTypes = { 24 | onClick: PropTypes.func.isRequired, 25 | isTagActive: PropTypes.bool.isRequired 26 | } 27 | 28 | export default CSSModules(TagButton, styles) 29 | -------------------------------------------------------------------------------- /browser/main/lib/Commander.js: -------------------------------------------------------------------------------- 1 | let callees = [] 2 | 3 | function bind(name, el) { 4 | callees.push({ 5 | name: name, 6 | element: el 7 | }) 8 | } 9 | 10 | function release(el) { 11 | callees = callees.filter(callee => callee.element !== el) 12 | } 13 | 14 | function fire(command) { 15 | console.info('COMMAND >>', command) 16 | const splitted = command.split(':') 17 | const target = splitted[0] 18 | const targetCommand = splitted[1] 19 | const targetCallees = callees.filter(callee => callee.name === target) 20 | 21 | targetCallees.forEach(callee => { 22 | callee.element.fire(targetCommand) 23 | }) 24 | } 25 | 26 | export default { 27 | bind, 28 | release, 29 | fire 30 | } 31 | -------------------------------------------------------------------------------- /browser/main/lib/ZoomManager.js: -------------------------------------------------------------------------------- 1 | import ConfigManager from './ConfigManager' 2 | 3 | const electron = require('electron') 4 | const { remote } = electron 5 | 6 | _init() 7 | 8 | function _init() { 9 | setZoom(getZoom(), true) 10 | } 11 | 12 | function _saveZoom(zoomFactor) { 13 | ConfigManager.set({ zoom: zoomFactor }) 14 | } 15 | 16 | function setZoom(zoomFactor, noSave = false) { 17 | if (!noSave) _saveZoom(zoomFactor) 18 | remote.getCurrentWebContents().setZoomFactor(zoomFactor) 19 | } 20 | 21 | function getZoom() { 22 | const config = ConfigManager.get() 23 | 24 | return config.zoom 25 | } 26 | 27 | export default { 28 | setZoom, 29 | getZoom 30 | } 31 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/copyFile.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import fx from 'fs-extra' 3 | import path from 'path' 4 | 5 | /** 6 | * @description Copy a file from source to destination 7 | * @param {String} srcPath 8 | * @param {String} dstPath 9 | * @return {Promise} an image path 10 | */ 11 | function copyFile(srcPath, dstPath) { 12 | if (!path.extname(dstPath)) { 13 | dstPath = path.join(dstPath, path.basename(srcPath)) 14 | } 15 | 16 | return new Promise((resolve, reject) => { 17 | const dstFolder = path.dirname(dstPath) 18 | 19 | fx.ensureDirSync(dstFolder) 20 | 21 | const input = fs.createReadStream(decodeURI(srcPath)) 22 | const output = fs.createWriteStream(dstPath) 23 | 24 | output.on('error', reject) 25 | input.on('error', reject) 26 | input.on('end', () => { 27 | resolve(dstPath) 28 | }) 29 | input.pipe(output) 30 | }) 31 | } 32 | 33 | module.exports = copyFile 34 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/createSnippet.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import crypto from 'crypto' 3 | import consts from 'browser/lib/consts' 4 | import fetchSnippet from 'browser/main/lib/dataApi/fetchSnippet' 5 | 6 | function createSnippet(snippetFile) { 7 | return new Promise((resolve, reject) => { 8 | const newSnippet = { 9 | id: crypto.randomBytes(16).toString('hex'), 10 | name: 'Unnamed snippet', 11 | prefix: [], 12 | content: '', 13 | linesHighlighted: [] 14 | } 15 | fetchSnippet(null, snippetFile) 16 | .then(snippets => { 17 | snippets.push(newSnippet) 18 | fs.writeFile( 19 | snippetFile || consts.SNIPPET_FILE, 20 | JSON.stringify(snippets, null, 4), 21 | err => { 22 | if (err) reject(err) 23 | resolve(newSnippet) 24 | } 25 | ) 26 | }) 27 | .catch(err => { 28 | reject(err) 29 | }) 30 | }) 31 | } 32 | 33 | module.exports = createSnippet 34 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/deleteNote.js: -------------------------------------------------------------------------------- 1 | const resolveStorageData = require('./resolveStorageData') 2 | const path = require('path') 3 | const sander = require('sander') 4 | const attachmentManagement = require('./attachmentManagement') 5 | const { findStorage } = require('browser/lib/findStorage') 6 | 7 | function deleteNote(storageKey, noteKey) { 8 | let targetStorage 9 | try { 10 | targetStorage = findStorage(storageKey) 11 | } catch (e) { 12 | return Promise.reject(e) 13 | } 14 | 15 | return resolveStorageData(targetStorage) 16 | .then(function deleteNoteFile(storage) { 17 | const notePath = path.join(storage.path, 'notes', noteKey + '.cson') 18 | 19 | try { 20 | sander.unlinkSync(notePath) 21 | } catch (err) { 22 | console.warn('Failed to delete note cson', err) 23 | } 24 | return { 25 | noteKey, 26 | storageKey 27 | } 28 | }) 29 | .then(function deleteAttachments(storageInfo) { 30 | attachmentManagement.deleteAttachmentFolder( 31 | storageInfo.storageKey, 32 | storageInfo.noteKey 33 | ) 34 | return storageInfo 35 | }) 36 | } 37 | 38 | module.exports = deleteNote 39 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/deleteSnippet.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import consts from 'browser/lib/consts' 3 | import fetchSnippet from 'browser/main/lib/dataApi/fetchSnippet' 4 | 5 | function deleteSnippet(snippet, snippetFile) { 6 | return new Promise((resolve, reject) => { 7 | fetchSnippet(null, snippetFile).then(snippets => { 8 | snippets = snippets.filter( 9 | currentSnippet => currentSnippet.id !== snippet.id 10 | ) 11 | fs.writeFile( 12 | snippetFile || consts.SNIPPET_FILE, 13 | JSON.stringify(snippets, null, 4), 14 | err => { 15 | if (err) reject(err) 16 | resolve(snippet) 17 | } 18 | ) 19 | }) 20 | }) 21 | } 22 | 23 | module.exports = deleteSnippet 24 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/exportNoteAs.js: -------------------------------------------------------------------------------- 1 | import { findStorage } from 'browser/lib/findStorage' 2 | import exportNote from './exportNote' 3 | import getContentFormatter from './getContentFormatter' 4 | 5 | /** 6 | * @param {Object} note 7 | * @param {String} filename 8 | * @param {String} fileType 9 | * @param {Object} config 10 | */ 11 | 12 | function exportNoteAs(note, filename, fileType, config) { 13 | const storage = findStorage(note.storage) 14 | const contentFormatter = getContentFormatter(storage, fileType, config) 15 | 16 | return exportNote(storage.key, note, filename, contentFormatter) 17 | } 18 | 19 | module.exports = exportNoteAs 20 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/exportTag.js: -------------------------------------------------------------------------------- 1 | import exportNoteAs from './exportNoteAs' 2 | import getFilename from './getFilename' 3 | 4 | /** 5 | * @param {Object} data 6 | * @param {String} tag 7 | * @param {String} fileType 8 | * @param {String} exportDir 9 | * @param {Object} config 10 | */ 11 | 12 | function exportTag(data, tag, fileType, exportDir, config) { 13 | const notes = data.noteMap 14 | .map(note => note) 15 | .filter(note => note.tags.indexOf(tag) !== -1) 16 | 17 | const deduplicator = {} 18 | 19 | return Promise.all( 20 | notes.map(note => { 21 | const filename = getFilename(note, fileType, exportDir, deduplicator) 22 | 23 | return exportNoteAs(note, filename, fileType, config) 24 | }) 25 | ) 26 | } 27 | 28 | module.exports = exportTag 29 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/fetchSnippet.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import consts from 'browser/lib/consts' 3 | 4 | function fetchSnippet(id, snippetFile) { 5 | return new Promise((resolve, reject) => { 6 | fs.readFile(snippetFile || consts.SNIPPET_FILE, 'utf8', (err, data) => { 7 | if (err) { 8 | reject(err) 9 | } 10 | const snippets = JSON.parse(data) 11 | if (id) { 12 | const snippet = snippets.find(snippet => { 13 | return snippet.id === id 14 | }) 15 | resolve(snippet) 16 | } 17 | resolve(snippets) 18 | }) 19 | }) 20 | } 21 | 22 | module.exports = fetchSnippet 23 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/formatPDF.js: -------------------------------------------------------------------------------- 1 | import formatHTML from './formatHTML' 2 | import { remote } from 'electron' 3 | 4 | export default function formatPDF(props) { 5 | return function(note, targetPath, exportTasks) { 6 | const printout = new remote.BrowserWindow({ 7 | show: false, 8 | webPreferences: { webSecurity: false, javascript: false } 9 | }) 10 | 11 | printout.loadURL( 12 | 'data:text/html;charset=UTF-8,' + 13 | formatHTML(props)(note, targetPath, exportTasks) 14 | ) 15 | 16 | return new Promise((resolve, reject) => { 17 | printout.webContents.on('did-finish-load', () => { 18 | printout.webContents.printToPDF({}, (err, data) => { 19 | if (err) reject(err) 20 | else resolve(data) 21 | printout.destroy() 22 | }) 23 | }) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/getFilename.js: -------------------------------------------------------------------------------- 1 | import filenamify from 'filenamify' 2 | import i18n from 'browser/lib/i18n' 3 | import path from 'path' 4 | 5 | /** 6 | * @param {Object} note 7 | * @param {String} fileType 8 | * @param {String} directory 9 | * @param {Object} deduplicator 10 | * 11 | * @return {String} 12 | */ 13 | 14 | function getFilename(note, fileType, directory, deduplicator) { 15 | const basename = note.title 16 | ? filenamify(note.title, { replacement: '_' }) 17 | : i18n.__('Untitled') 18 | 19 | if (deduplicator) { 20 | if (deduplicator[basename]) { 21 | const filename = path.join( 22 | directory, 23 | `${basename} (${deduplicator[basename]}).${fileType}` 24 | ) 25 | 26 | ++deduplicator[basename] 27 | 28 | return filename 29 | } else { 30 | deduplicator[basename] = 1 31 | } 32 | } 33 | 34 | return path.join(directory, `${basename}.${fileType}`) 35 | } 36 | 37 | module.exports = getFilename 38 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/index.js: -------------------------------------------------------------------------------- 1 | const dataApi = { 2 | init: require('./init'), 3 | toggleStorage: require('./toggleStorage'), 4 | addStorage: require('./addStorage'), 5 | renameStorage: require('./renameStorage'), 6 | removeStorage: require('./removeStorage'), 7 | createFolder: require('./createFolder'), 8 | updateFolder: require('./updateFolder'), 9 | deleteFolder: require('./deleteFolder'), 10 | reorderFolder: require('./reorderFolder'), 11 | exportFolder: require('./exportFolder'), 12 | exportStorage: require('./exportStorage'), 13 | createNote: require('./createNote'), 14 | createNoteFromUrl: require('./createNoteFromUrl'), 15 | updateNote: require('./updateNote'), 16 | deleteNote: require('./deleteNote'), 17 | moveNote: require('./moveNote'), 18 | exportNoteAs: require('./exportNoteAs'), 19 | migrateFromV5Storage: require('./migrateFromV5Storage'), 20 | createSnippet: require('./createSnippet'), 21 | deleteSnippet: require('./deleteSnippet'), 22 | updateSnippet: require('./updateSnippet'), 23 | fetchSnippet: require('./fetchSnippet'), 24 | exportTag: require('./exportTag'), 25 | getFilename: require('./getFilename'), 26 | 27 | _migrateFromV6Storage: require('./migrateFromV6Storage'), 28 | _resolveStorageData: require('./resolveStorageData'), 29 | _resolveStorageNotes: require('./resolveStorageNotes') 30 | } 31 | 32 | module.exports = dataApi 33 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/removeStorage.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash') 2 | 3 | /** 4 | * @param {String} key 5 | * @return {key} 6 | */ 7 | function removeStorage(key) { 8 | let rawStorages 9 | 10 | try { 11 | rawStorages = JSON.parse(localStorage.getItem('storages')) 12 | if (!_.isArray(rawStorages)) throw new Error('invalid storages') 13 | } catch (e) { 14 | console.warn(e) 15 | rawStorages = [] 16 | } 17 | 18 | rawStorages = rawStorages.filter(function excludeTargetStorage(rawStorage) { 19 | return rawStorage.key !== key 20 | }) 21 | 22 | localStorage.setItem('storages', JSON.stringify(rawStorages)) 23 | 24 | return Promise.resolve({ 25 | storageKey: key 26 | }) 27 | } 28 | 29 | module.exports = removeStorage 30 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/renameStorage.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash') 2 | const resolveStorageData = require('./resolveStorageData') 3 | 4 | /** 5 | * @param {String} key 6 | * @param {String} name 7 | * @return {Object} Storage meta data 8 | */ 9 | function renameStorage(key, name) { 10 | if (!_.isString(name)) 11 | return Promise.reject(new Error('Name must be a string.')) 12 | 13 | let cachedStorageList 14 | try { 15 | cachedStorageList = JSON.parse(localStorage.getItem('storages')) 16 | if (!_.isArray(cachedStorageList)) throw new Error('invalid storages') 17 | } catch (err) { 18 | console.error(err) 19 | return Promise.reject(err) 20 | } 21 | const targetStorage = _.find(cachedStorageList, { key: key }) 22 | if (targetStorage == null) return Promise.reject('Storage') 23 | 24 | targetStorage.name = name 25 | localStorage.setItem('storages', JSON.stringify(cachedStorageList)) 26 | 27 | targetStorage.path 28 | 29 | return resolveStorageData(targetStorage) 30 | } 31 | 32 | module.exports = renameStorage 33 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/reorderFolder.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash') 2 | _.move = require('lodash-move').default 3 | const path = require('path') 4 | const resolveStorageData = require('./resolveStorageData') 5 | const CSON = require('@rokt33r/season') 6 | const { findStorage } = require('browser/lib/findStorage') 7 | 8 | /** 9 | * @param {String} storageKey 10 | * @param {number} oldIndex 11 | * @param {number} newIndex 12 | * 13 | * @return {Object} 14 | * ``` 15 | * { 16 | * storage: Object 17 | * } 18 | * ``` 19 | */ 20 | function reorderFolder(storageKey, oldIndex, newIndex) { 21 | let targetStorage 22 | try { 23 | if (!_.isNumber(oldIndex)) throw new Error('oldIndex must be a number.') 24 | if (!_.isNumber(newIndex)) throw new Error('newIndex must be a number.') 25 | 26 | targetStorage = findStorage(storageKey) 27 | } catch (e) { 28 | return Promise.reject(e) 29 | } 30 | 31 | return resolveStorageData(targetStorage).then(function reorderFolder( 32 | storage 33 | ) { 34 | storage.folders = _.move(storage.folders, oldIndex, newIndex) 35 | CSON.writeFileSync( 36 | path.join(storage.path, 'boostnote.json'), 37 | _.pick(storage, ['folders', 'version']) 38 | ) 39 | 40 | return { 41 | storage 42 | } 43 | }) 44 | } 45 | 46 | module.exports = reorderFolder 47 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/resolveStorageData.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash') 2 | const path = require('path') 3 | const CSON = require('@rokt33r/season') 4 | const migrateFromV6Storage = require('./migrateFromV6Storage') 5 | 6 | function resolveStorageData(storageCache) { 7 | const storage = { 8 | key: storageCache.key, 9 | name: storageCache.name, 10 | type: storageCache.type, 11 | path: storageCache.path, 12 | isOpen: storageCache.isOpen 13 | } 14 | 15 | const boostnoteJSONPath = path.join(storageCache.path, 'boostnote.json') 16 | try { 17 | const jsonData = CSON.readFileSync(boostnoteJSONPath) 18 | if (!_.isArray(jsonData.folders)) 19 | throw new Error('folders should be an array.') 20 | storage.folders = jsonData.folders 21 | storage.version = jsonData.version 22 | } catch (err) { 23 | if (err.code === 'ENOENT') { 24 | console.warn("boostnote.json file doesn't exist the given path") 25 | CSON.writeFileSync(boostnoteJSONPath, { folders: [], version: '1.0' }) 26 | } else { 27 | console.error(err) 28 | } 29 | storage.folders = [] 30 | storage.version = '1.0' 31 | } 32 | 33 | const version = parseInt(storage.version, 10) 34 | if (version >= 1) { 35 | return Promise.resolve(storage) 36 | } 37 | 38 | return migrateFromV6Storage(storage.path).then(() => storage) 39 | } 40 | 41 | module.exports = resolveStorageData 42 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/resolveStorageNotes.js: -------------------------------------------------------------------------------- 1 | const sander = require('sander') 2 | const path = require('path') 3 | const CSON = require('@rokt33r/season') 4 | 5 | function resolveStorageNotes(storage) { 6 | const notesDirPath = path.join(storage.path, 'notes') 7 | let notePathList 8 | try { 9 | notePathList = sander.readdirSync(notesDirPath) 10 | } catch (err) { 11 | if (err.code === 'ENOENT') { 12 | console.error(notesDirPath, " doesn't exist.") 13 | sander.mkdirSync(notesDirPath) 14 | } else { 15 | console.warn('Failed to find note dir', notesDirPath, err) 16 | } 17 | notePathList = [] 18 | } 19 | const notes = notePathList 20 | .filter(function filterOnlyCSONFile(notePath) { 21 | return /\.cson$/.test(notePath) 22 | }) 23 | .map(function parseCSONFile(notePath) { 24 | try { 25 | const data = CSON.readFileSync(path.join(notesDirPath, notePath)) 26 | data.key = path.basename(notePath, '.cson') 27 | data.storage = storage.key 28 | return data 29 | } catch (err) { 30 | console.error(`error on note path: ${notePath}, error: ${err}`) 31 | } 32 | }) 33 | .filter(function filterOnlyNoteObject(noteObj) { 34 | return typeof noteObj === 'object' 35 | }) 36 | 37 | return Promise.resolve(notes) 38 | } 39 | 40 | module.exports = resolveStorageNotes 41 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/toggleStorage.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash') 2 | const resolveStorageData = require('./resolveStorageData') 3 | 4 | /** 5 | * @param {String} key 6 | * @param {Boolean} isOpen 7 | * @return {Object} Storage meta data 8 | */ 9 | function toggleStorage(key, isOpen) { 10 | let cachedStorageList 11 | try { 12 | cachedStorageList = JSON.parse(localStorage.getItem('storages')) 13 | if (!_.isArray(cachedStorageList)) throw new Error('invalid storages') 14 | } catch (err) { 15 | console.error(err) 16 | return Promise.reject(err) 17 | } 18 | const targetStorage = _.find(cachedStorageList, { key: key }) 19 | if (targetStorage == null) return Promise.reject('Storage') 20 | 21 | targetStorage.isOpen = isOpen 22 | localStorage.setItem('storages', JSON.stringify(cachedStorageList)) 23 | 24 | return resolveStorageData(targetStorage) 25 | } 26 | 27 | module.exports = toggleStorage 28 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/updateFolder.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash') 2 | const path = require('path') 3 | const resolveStorageData = require('./resolveStorageData') 4 | const CSON = require('@rokt33r/season') 5 | const { findStorage } = require('browser/lib/findStorage') 6 | 7 | /** 8 | * @param {String} storageKey 9 | * @param {String} folderKey 10 | * @param {Object} input 11 | * ``` 12 | * { 13 | * color: String, 14 | * name: String 15 | * } 16 | * ``` 17 | * 18 | * @return {Object} 19 | * ``` 20 | * { 21 | * storage: Object 22 | * } 23 | * ``` 24 | */ 25 | function updateFolder(storageKey, folderKey, input) { 26 | let targetStorage 27 | try { 28 | if (input == null) throw new Error('No input found.') 29 | if (!_.isString(input.name)) throw new Error('Name must be a string.') 30 | if (!_.isString(input.color)) throw new Error('Color must be a string.') 31 | 32 | targetStorage = findStorage(storageKey) 33 | } catch (e) { 34 | return Promise.reject(e) 35 | } 36 | 37 | return resolveStorageData(targetStorage).then(function updateFolder(storage) { 38 | const targetFolder = _.find(storage.folders, { key: folderKey }) 39 | if (targetFolder == null) throw new Error("Target folder doesn't exist.") 40 | targetFolder.name = input.name 41 | targetFolder.color = input.color 42 | 43 | CSON.writeFileSync( 44 | path.join(storage.path, 'boostnote.json'), 45 | _.pick(storage, ['folders', 'version']) 46 | ) 47 | 48 | return { 49 | storage 50 | } 51 | }) 52 | } 53 | 54 | module.exports = updateFolder 55 | -------------------------------------------------------------------------------- /browser/main/lib/dataApi/updateSnippet.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import consts from 'browser/lib/consts' 3 | 4 | function updateSnippet(snippet, snippetFile) { 5 | return new Promise((resolve, reject) => { 6 | const snippets = JSON.parse( 7 | fs.readFileSync(snippetFile || consts.SNIPPET_FILE, 'utf-8') 8 | ) 9 | 10 | for (let i = 0; i < snippets.length; i++) { 11 | const currentSnippet = snippets[i] 12 | 13 | if (currentSnippet.id === snippet.id) { 14 | if ( 15 | currentSnippet.name === snippet.name && 16 | currentSnippet.prefix === snippet.prefix && 17 | currentSnippet.content === snippet.content && 18 | currentSnippet.linesHighlighted === snippet.linesHighlighted 19 | ) { 20 | // if everything is the same then don't write to disk 21 | resolve(snippets) 22 | } else { 23 | currentSnippet.name = snippet.name 24 | currentSnippet.prefix = snippet.prefix 25 | currentSnippet.content = snippet.content 26 | currentSnippet.linesHighlighted = snippet.linesHighlighted 27 | fs.writeFile( 28 | snippetFile || consts.SNIPPET_FILE, 29 | JSON.stringify(snippets, null, 4), 30 | err => { 31 | if (err) reject(err) 32 | resolve(snippets) 33 | } 34 | ) 35 | } 36 | } 37 | } 38 | }) 39 | } 40 | 41 | module.exports = updateSnippet 42 | -------------------------------------------------------------------------------- /browser/main/lib/eventEmitter.js: -------------------------------------------------------------------------------- 1 | const electron = require('electron') 2 | const { ipcRenderer, remote } = electron 3 | 4 | function on(name, listener) { 5 | ipcRenderer.on(name, listener) 6 | } 7 | 8 | function off(name, listener) { 9 | ipcRenderer.removeListener(name, listener) 10 | } 11 | 12 | function once(name, listener) { 13 | ipcRenderer.once(name, listener) 14 | } 15 | 16 | function emit(name, ...args) { 17 | remote.getCurrentWindow().webContents.send(name, ...args) 18 | } 19 | 20 | export default { 21 | emit, 22 | on, 23 | off, 24 | once 25 | } 26 | -------------------------------------------------------------------------------- /browser/main/lib/ipcClient.js: -------------------------------------------------------------------------------- 1 | import ConfigManager from './ConfigManager' 2 | 3 | const nodeIpc = require('node-ipc') 4 | const { remote, ipcRenderer } = require('electron') 5 | const { app } = remote 6 | const path = require('path') 7 | 8 | nodeIpc.config.id = 'main' 9 | nodeIpc.config.retry = 1500 10 | nodeIpc.config.silent = true 11 | 12 | nodeIpc.connectTo( 13 | 'node', 14 | path.join(app.getPath('userData'), 'boostnote.service'), 15 | function() { 16 | nodeIpc.of.node.on('error', function(err) { 17 | console.error(err) 18 | }) 19 | nodeIpc.of.node.on('connect', function() { 20 | ipcRenderer.send('config-renew', { config: ConfigManager.get() }) 21 | }) 22 | nodeIpc.of.node.on('disconnect', function() { 23 | return 24 | }) 25 | } 26 | ) 27 | 28 | module.exports = nodeIpc 29 | -------------------------------------------------------------------------------- /browser/main/lib/notify.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | function notify(title, options) { 4 | if (process.platform === 'win32') { 5 | options.icon = path.join( 6 | 'file://', 7 | global.__dirname, 8 | '../../resources/app.png' 9 | ) 10 | options.silent = false 11 | } 12 | return new window.Notification(title, options) 13 | } 14 | 15 | export default notify 16 | -------------------------------------------------------------------------------- /browser/main/lib/shortcut.js: -------------------------------------------------------------------------------- 1 | import ee from 'browser/main/lib/eventEmitter' 2 | 3 | module.exports = { 4 | toggleMode: () => { 5 | ee.emit('topbar:togglemodebutton') 6 | }, 7 | toggleDirection: () => { 8 | ee.emit('topbar:toggledirectionbutton') 9 | }, 10 | deleteNote: () => { 11 | ee.emit('hotkey:deletenote') 12 | }, 13 | toggleMenuBar: () => { 14 | ee.emit('menubar:togglemenubar') 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /browser/main/lib/shortcutManager.js: -------------------------------------------------------------------------------- 1 | import Mousetrap from 'mousetrap' 2 | import CM from 'browser/main/lib/ConfigManager' 3 | import ee from 'browser/main/lib/eventEmitter' 4 | import { isObjectEqual } from 'browser/lib/utils' 5 | require('mousetrap-global-bind') 6 | import functions from './shortcut' 7 | 8 | let shortcuts = CM.get().hotkey 9 | 10 | ee.on('config-renew', function() { 11 | // only update if hotkey changed ! 12 | const newHotkey = CM.get().hotkey 13 | if (!isObjectEqual(newHotkey, shortcuts)) { 14 | updateShortcut(newHotkey) 15 | } 16 | }) 17 | 18 | function updateShortcut(newHotkey) { 19 | Mousetrap.reset() 20 | shortcuts = newHotkey 21 | applyShortcuts(newHotkey) 22 | } 23 | 24 | function formatShortcut(shortcut) { 25 | return shortcut.toLowerCase().replace(/ /g, '') 26 | } 27 | 28 | function applyShortcuts(shortcuts) { 29 | for (const shortcut in shortcuts) { 30 | const toggler = formatShortcut(shortcuts[shortcut]) 31 | // only bind if the function for that shortcut exists 32 | if (functions[shortcut]) { 33 | Mousetrap.bindGlobal(toggler, functions[shortcut]) 34 | } 35 | } 36 | } 37 | 38 | applyShortcuts(CM.get().hotkey) 39 | 40 | module.exports = applyShortcuts 41 | -------------------------------------------------------------------------------- /browser/main/modals/PreferencesModal/Crowdfunding.styl: -------------------------------------------------------------------------------- 1 | @import('./ConfigTab') 2 | 3 | p 4 | font-size 16px 5 | line-height 1.4 6 | 7 | .cf-link 8 | height 35px 9 | border-radius 2px 10 | border none 11 | background-color alpha(#1EC38B, 90%) 12 | padding-left 20px 13 | padding-right 20px 14 | &:hover 15 | background-color #1EC38B 16 | transition 0.2s 17 | a 18 | text-decoration none 19 | color white 20 | font-weight 600 21 | font-size 16px 22 | 23 | body[data-theme="dark"] 24 | p 25 | color $ui-dark-text-color 26 | 27 | apply-theme(theme) 28 | body[data-theme={theme}] 29 | .root 30 | color get-theme-var(theme, 'text-color') 31 | p 32 | color get-theme-var(theme, 'text-color') 33 | 34 | for theme in 'solarized-dark' 'dracula' 35 | apply-theme(theme) 36 | 37 | for theme in $themes 38 | apply-theme(theme) -------------------------------------------------------------------------------- /browser/main/modals/PreferencesModal/FolderList.styl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/browser/main/modals/PreferencesModal/FolderList.styl -------------------------------------------------------------------------------- /browser/main/modals/PreferencesModal/Tab.styl: -------------------------------------------------------------------------------- 1 | /** 2 | * Common style for tabs on config modal. 3 | */ 4 | 5 | $tab--input-border-radius = 5px 6 | $tab--button-border-radius = 5px 7 | $tab--button-height = 40px 8 | $tab--button-font-size = 14px 9 | 10 | $tab--dark-text-color = #E5E5E5 11 | 12 | .header 13 | font-size 36px 14 | margin-bottom 60px 15 | 16 | .header--sub 17 | font-size 36px 18 | margin-bottom 20px 19 | 20 | body[data-theme="dark"] 21 | .header 22 | color $tab--dark-text-color 23 | 24 | haveToSave() 25 | color #FFA500 26 | font-size 10px 27 | margin-top 3px -------------------------------------------------------------------------------- /browser/styles/mixins/alert.styl: -------------------------------------------------------------------------------- 1 | alertSuccess() 2 | background-color successBackgroundColor 3 | color successTextColor 4 | 5 | alertError() 6 | background-color errorBackgroundColor 7 | color errorTextColor 8 | 9 | alertInfo() 10 | background-color infoBackgroundColor 11 | color infoTextColor 12 | -------------------------------------------------------------------------------- /browser/styles/mixins/btn.styl: -------------------------------------------------------------------------------- 1 | btnDefault() 2 | border-style solid 3 | border-width 1px 4 | border-color lightButtonColor 5 | background-color transparent 6 | color lightButtonColor 7 | 8 | &:hover, &.hover, &:focus, &.focus 9 | border-color darken(lightButtonColor, 50%) 10 | color darken(lightButtonColor, 50%) 11 | &:active, &.active 12 | border-color darken(brandBorderColor, 10%) 13 | background-color brandColor 14 | color white 15 | &:disabled, &.disabled 16 | opacity 0.6 17 | 18 | btnPrimary() 19 | border-style solid 20 | border-width 1px 21 | border-color brandBorderColor 22 | background-color transparent 23 | color brandColor 24 | &:hover, &.hover, &:focus, &.focus 25 | border-color darken(brandBorderColor, 30%) 26 | color darken(brandColor, 30%) 27 | &:active, &.active 28 | background-color brandColor 29 | color white 30 | &:disabled, &.disabled 31 | opacity 0.6 32 | 33 | btnStripDefault() 34 | border none 35 | background-color transparent 36 | color lightButtonColor 37 | &:hover, &.hover, &:focus, &.focus 38 | color darken(lightButtonColor, 50%) 39 | &:active, &.active 40 | color brandColor 41 | -------------------------------------------------------------------------------- /browser/styles/mixins/circle.styl: -------------------------------------------------------------------------------- 1 | circle() 2 | border-radius 50% 3 | overflow hidden 4 | -------------------------------------------------------------------------------- /browser/styles/mixins/fullsize.styl: -------------------------------------------------------------------------------- 1 | fullsize() 2 | position absolute 3 | top 0 4 | left 0 5 | right 0 6 | bottom 0 7 | -------------------------------------------------------------------------------- /browser/styles/mixins/input.styl: -------------------------------------------------------------------------------- 1 | stripInput() 2 | border none 3 | border-bottom 1px solid borderColor 4 | padding 5px 15px 5 | transition 0.1s 6 | font-size 14px 7 | &:focus, &.focus 8 | border-bottom 1px solid brandBorderColor 9 | outline none 10 | 11 | borderInput() 12 | border solid 1px borderColor 13 | padding 5px 15px 14 | transition 0.1s 15 | font-size 14px 16 | &:focus, &.focus 17 | border-color brandBorderColor 18 | outline none 19 | -------------------------------------------------------------------------------- /browser/styles/mixins/tooltip.styl: -------------------------------------------------------------------------------- 1 | tooltip() 2 | position fixed 3 | z-index popupZIndex 4 | background-color transparentify(invBackgroundColor, 80%) 5 | color invTextColor 6 | padding 6px 15px 7 | font-size 12px 8 | font-weight normal 9 | line-height 20px 10 | white-space nowrap 11 | opacity 0 12 | transition 0.1s 13 | pointer-events none 14 | 15 | -------------------------------------------------------------------------------- /browser/styles/mixins/util.styl: -------------------------------------------------------------------------------- 1 | borderBox() 2 | box-sizing border-box 3 | 4 | noSelect() 5 | -webkit-user-select none 6 | cursor default 7 | -------------------------------------------------------------------------------- /browser/styles/shared/btn.styl: -------------------------------------------------------------------------------- 1 | .btn-primary, .btn-default 2 | border-style solid 3 | border-width 1px 4 | background-image none 5 | height 44px 6 | padding 0 15px 7 | border-radius 5px 8 | box-sizing border-box 9 | font-size 1em 10 | font-family 'Lato' 11 | font-weight 400 12 | transition 0.1s 13 | cursor pointer 14 | margin 0 5px 15 | 16 | .btn-block 17 | display block 18 | width 100% 19 | margin 0 auto 20 | 21 | .btn-square 22 | display inline-block 23 | width 44px 24 | padding 0 25 | border-width 1px 26 | 27 | .btn-sm 28 | height 32px 29 | border-radius 16px 30 | &.btn-square 31 | width 32px 32 | 33 | .btn-primary 34 | border-color brandBorderColor 35 | background-color transparent 36 | color brandColor 37 | &:hover, &.hover, &:focus, &.focus 38 | border-color darken(brandBorderColor, 30%) 39 | color darken(brandColor, 30%) 40 | &:active, &.active 41 | background-color brandColor 42 | color white 43 | 44 | .btn-default 45 | border-color lightButtonColor 46 | background-color transparent 47 | color lightButtonColor 48 | 49 | &:hover, &.hover, &:focus, &.focus 50 | border-color darken(lightButtonColor, 50%) 51 | color darken(lightButtonColor, 50%) 52 | &:active, &.active 53 | border-color darken(brandBorderColor, 10%) 54 | background-color brandColor 55 | color white 56 | -------------------------------------------------------------------------------- /browser/styles/vars.styl: -------------------------------------------------------------------------------- 1 | borderColor = #D0D0D0 // using 2 | highlightenBorderColor = darken(borderColor, 20%) 3 | invBorderColor = #404849 4 | brandBorderColor = #3FB399 5 | 6 | focusBorderColor = #369DCD 7 | 8 | buttonBorderColor = #4C4C4C 9 | 10 | lightButtonColor = #898989 11 | 12 | hoverBackgroundColor= transparentify(#444, 4%) // using 13 | 14 | inactiveTextColor = #888 // using 15 | textColor = #4D4D4D // using 16 | backgroundColor= white 17 | fontSize= 14px // using 18 | 19 | shadowColor= #C5C5C5 20 | 21 | invBackgroundColor = #4C4C4C 22 | invTextColor = white 23 | 24 | btnColor = #888 25 | btnHighlightenColor = #000 26 | 27 | brandColor = #2BAC8F 28 | 29 | popupShadow = 0 0 5px 0 #888 30 | 31 | 32 | tableHeadBgColor = white 33 | tableOddBgColor = #F9F9F9 34 | tableEvenBgColor = white 35 | 36 | facebookColor= #3b5998 37 | githubBtn= #201F1F 38 | 39 | // using 40 | successBackgroundColor= #E0F0D9 41 | successTextColor= #3E753F 42 | errorBackgroundColor= #F2DEDE 43 | errorTextColor= #A64444 44 | infoBackgroundColor= #D9EDF7 45 | infoTextColor= #34708E 46 | 47 | popupZIndex= 500 48 | -------------------------------------------------------------------------------- /docs/jp/build.md: -------------------------------------------------------------------------------- 1 | # Build 2 | 3 | ## 環境 4 | 5 | * npm: 6.x 6 | * node: 8.x 7 | 8 | ## 開発 9 | 10 | Webpack HRMを使います。 11 | Boostnoteの最上位ディレクトリにて以下のコマンドを実行して、 12 | デフォルトの設定の開発環境を起動させます。 13 | 14 | 依存するパッケージをインストールします。 15 | 16 | ``` 17 | $ yarn 18 | ``` 19 | 20 | ビルドして実行します。 21 | 22 | ``` 23 | $ yarn run dev 24 | ``` 25 | 26 | > ### 注意 27 | > 時々、直接リフレッシュをする必要があります。 28 | > 1. コンポーネントのコンストラクタ関数を編集する場合 29 | > 2. 新しいCSSクラスを追加する場合(1.の理由と同じ: CSSクラス名はコンポーネントごとに書きなおされますが、この作業はコンストラクタで行われます。) 30 | 31 | ## 配布 32 | 33 | Gruntを使います。 34 | 実際の配布は`grunt`で実行できます。しかし、これにはCodesignとAuthenticodeを実行するタスクが含まれるので、使用しないでください。 35 | 36 | 代わりに、実行ファイルを作るスクリプトを用意しておきました。 37 | 38 | ``` 39 | grunt pre-build 40 | ``` 41 | 42 | 実行ファイルは`dist`から見つかります。この場合、認証されていないため、自動アップデーターは使えません。 43 | 44 | 必要であれば、この実行ファイルからCodesignやAuthenticodeなどの署名ができます。 45 | 46 | ## ディストリビューション用パッケージ (deb, rpm) 47 | 48 | ディストリビューション用パッケージはLinuxプラットフォーム(Ubuntu や Fedora)上で `grunt build` を実行する事で作成されます。 49 | 50 | > 一つの環境で `.deb` と `.rpm` の両方を作成する事が出来ます。 51 | 52 | 53 | 対応するバージョンの `node` と `npm` をインストールした後、必要なパッケージをインストールします。 54 | 55 | Ubuntu/Debian: 56 | 57 | ``` 58 | $ sudo apt-get install -y rpm fakeroot 59 | ``` 60 | 61 | Fedora: 62 | 63 | ``` 64 | $ sudo dnf install -y dpkg dpkg-dev rpm-build fakeroot 65 | ``` 66 | 67 | `grunt build` を実行します。 68 | 69 | ``` 70 | $ grunt build 71 | ``` 72 | 73 | `.deb` と `.rpm` は `dist` 配下に作成されます。 74 | -------------------------------------------------------------------------------- /docs/jp/debug.md: -------------------------------------------------------------------------------- 1 | # Boostnote(electronアプリケーション)のデバッグ方法について 2 | Boostnoteを作っているelectronはChromiumからできており、開発者は `Developer Tools`をGoogle Chromeと同じように使うことができます。 3 | 4 | Developer Toolsの切り替え方法はこちらです: 5 | ![how_to_toggle_devTools](https://cloud.githubusercontent.com/assets/11307908/24343585/162187e2-127c-11e7-9c01-23578db03ecf.png) 6 | 7 | 実際のデベロッパーツールはこちらです: 8 | ![Developer_Tools](https://cloud.githubusercontent.com/assets/11307908/24343545/eff9f3a6-127b-11e7-94cf-cb67bfda634a.png) 9 | 10 | 何かエラーが起きた場合 `console`にエラーメッセージが表示されます。 11 | 12 | ## デバッグ 13 | 例えば、 `debugger`をコード中にブレークポイントとして挟む方法があります。 14 | 15 | ![debugger](https://cloud.githubusercontent.com/assets/11307908/24343879/9459efea-127d-11e7-9943-f60bf7f66d4a.png) 16 | 17 | ですがこれは一例にしか過ぎません。最もあなたに合うデバッグ方法を見つけた方がいいでしょう。 18 | 19 | ## 参考 20 | * [デバッグに関するGoogle Chromeの公式ドキュメント](https://developer.chrome.com/devtools) 21 | -------------------------------------------------------------------------------- /docs/ru/build.md: -------------------------------------------------------------------------------- 1 | # Сборка 2 | 3 | ## Используемые инструменты 4 | 5 | * npm: 6.x 6 | * node: 8.x 7 | 8 | ## Разработка 9 | 10 | Мы используем Webpack HMR при разработке Boostnote. 11 | Выполнение следующих команд в корне проекта запустит Boostnote с настройками по умолчанию. 12 | 13 | Установите необходимые пакеты с помощью yarn. 14 | 15 | ``` 16 | $ yarn 17 | ``` 18 | 19 | Соберите и запустите. 20 | 21 | ``` 22 | $ yarn run dev 23 | ``` 24 | 25 | > ### Примечание 26 | > В некоторых случаях вам необходимо обновить приложение вручную. 27 | > 1. При редактировании метода конструктора компонента 28 | > 2. При добавлении нового класса CSS (аналогично 1: Класс CSS перезаписывается каждым компонентом. Этот процесс выполняется в методе Constructor.) 29 | 30 | ## Деплой 31 | 32 | Мы используем Grunt для автоматического деплоя. 33 | Вы можете создать задачу, используя `grunt`. Однако мы не рекомендуем этого делать, так как задача по умолчанию включает в себя код и аутентификацию. 34 | 35 | Мы подготовили отдельный скрипт, который просто создает исполняемый файл. 36 | 37 | ``` 38 | grunt pre-build 39 | ``` 40 | 41 | Вы найдете исполняемый файл в папке `dist`. Обратите внимание: автоматическое обновление не будет работать, потому что приложение не подписано. 42 | 43 | Если вам необходимо, вы можете использовать код или аутентификацию с помощью этого исполняемого файла. 44 | 45 | --- 46 | 47 | Special thanks: 48 | Translated by @AlexanderBelkevich 49 | -------------------------------------------------------------------------------- /docs/ru/debug.md: -------------------------------------------------------------------------------- 1 | # Как отладить Boostnote (приложение Electron) 2 | Boostnote - это программа, сделанная с помощью Electron, поэтому она базируется на Chromium. Разработчики могут использовать `Developer Tools` в Google Chrome для отладки. 3 | 4 | Вы можете переключиться в `Developer Tools` следующим образом: 5 | ![how_to_toggle_devTools](https://cloud.githubusercontent.com/assets/11307908/24343585/162187e2-127c-11e7-9c01-23578db03ecf.png) 6 | 7 | `Developer Tools` будет выглядеть следующим образом: 8 | ![Developer_Tools](https://cloud.githubusercontent.com/assets/11307908/24343545/eff9f3a6-127b-11e7-94cf-cb67bfda634a.png) 9 | 10 | Возможные ошибки отображаются во вкладке `console`. 11 | 12 | ## Отладка 13 | Например, вы можете использовать `debugger`, чтобы установить точку остановы следующим образом: 14 | 15 | ![debugger](https://cloud.githubusercontent.com/assets/11307908/24343879/9459efea-127d-11e7-9943-f60bf7f66d4a.png) 16 | 17 | Это всего лишь пример. Вы можете использовать любой свой способ отладки. Тот, который вам будет удобен. 18 | 19 | ## Рекомендации 20 | * [Официальная документация Google Chrome об отладке](https://developer.chrome.com/devtools) 21 | 22 | --- 23 | 24 | Special thanks: 25 | Translated by @AlexanderBelkevich 26 | -------------------------------------------------------------------------------- /docs/zh_CN/build.md: -------------------------------------------------------------------------------- 1 | # 构建Boostnote 2 | 3 | ## 环境 4 | 5 | * npm: 6.x 6 | * node: 8.x 7 | 8 | ## 开发 9 | 10 | 我们使用Webpack HMR来开发Boostnote。 11 | 在代码根目录下运行下列指令可以以默认配置运行Boostnote。 12 | 13 | ### 首先使用yarn安装所需的依赖包。 14 | 15 | ``` 16 | $ yarn 17 | ``` 18 | 19 | ### 接着编译并且运行Boostnote。 20 | 21 | ``` 22 | $ yarn run dev 23 | ``` 24 | 25 | > ### 提示 26 | > 在如下情况中,您可能需要重新运行Boostnote才能应用代码更改 27 | > 1. 当您在修改了一个组件的构造函数的时候When editing a constructor method of a component 28 | > 2. 当您新建了一个CSS类的时候(其实这和第1项是相同的,因为每个CSS类都需在组件的构造函数中被重写) 29 | 30 | ## 部署 31 | 32 | 我们使用Grunt来自动部署Boostnote。 33 | 因为部署需要协同设计(codesign)与验证码(authenticode),所以您可以但我们不建议通过`grunt`来部署。 34 | 所以我们准备了一个脚本文件来生成执行文件。 35 | 36 | ``` 37 | grunt pre-build 38 | ``` 39 | 40 | 接下来您就可以在`dist`目录中找到可执行文件。 41 | 42 | > ### 提示 43 | > 因为此可执行文件并没有被注册,所以自动更新不可用。 44 | > 如果需要,您也可将协同设计(codesign)与验证码(authenticode)使用于这个可执行文件中。 45 | -------------------------------------------------------------------------------- /docs/zh_CN/debug.md: -------------------------------------------------------------------------------- 1 | # 在Boostnote上Debug 2 | 3 | Boostnote基于Electron,所以Boostnote上的开发者工具和Google Chrome相同。 4 | 5 | 您可以像这样或者按下快捷键`Ctrl+Shift+I`打开开发者工具: 6 | ![how_to_toggle_devTools](https://cloud.githubusercontent.com/assets/11307908/24343585/162187e2-127c-11e7-9c01-23578db03ecf.png) 7 | 8 | 开发者工具大概形如这样: 9 | ![Developer_Tools](https://cloud.githubusercontent.com/assets/11307908/24343545/eff9f3a6-127b-11e7-94cf-cb67bfda634a.png) 10 | 11 | 您可以在`console`选项卡中找到运行错误, 12 | 也可以像这样在`debugger`选项卡中设置断点去分步Debug: 13 | ![debugger](https://cloud.githubusercontent.com/assets/11307908/24343879/9459efea-127d-11e7-9943-f60bf7f66d4a.png) 14 | 15 | 关于具体如何使用开发者工具,详见[Chrome 官档](https://developer.chrome.com/devtools)。(如果您在中国大陆,您可能需要一个VPN才能正常访问) 16 | -------------------------------------------------------------------------------- /extra_scripts/codemirror/theme/nord.css: -------------------------------------------------------------------------------- 1 | /* Theme: nord */ 2 | 3 | .cm-s-nord.CodeMirror { color: #d8dee9; } 4 | .cm-s-nord.CodeMirror { background: #2e3440; } 5 | .cm-s-nord .CodeMirror-cursor { color: #d8dee9; border-color: #d8dee9; } 6 | .cm-s-nord .CodeMirror-activeline-background { background: #434c5e52 !important; } 7 | .cm-s-nord .CodeMirror-selected { background: undefined; } 8 | .cm-s-nord .cm-comment { color: #4c566a; } 9 | .cm-s-nord .cm-string { color: #a3be8c; } 10 | .cm-s-nord .cm-string-2 { color: #8fbcbb; } 11 | .cm-s-nord .cm-property { color: #8fbcbb; } 12 | .cm-s-nord .cm-qualifier { color: #8fbcbb; } 13 | .cm-s-nord .cm-tag { color: #81a1c1; } 14 | .cm-s-nord .cm-attribute { color: #8fbcbb; } 15 | .cm-s-nord .cm-number { color: #b48ead; } 16 | .cm-s-nord .cm-keyword { color: #81a1c1; } 17 | .cm-s-nord .cm-operator { color: #81a1c1; } 18 | .cm-s-nord .cm-error { background: #bf616a; color: #d8dee9; } 19 | .cm-s-nord .cm-invalidchar { background: #bf616a; color: #d8dee9; } 20 | .cm-s-nord .cm-variable { color: #d8dee9; } 21 | .cm-s-nord .cm-variable-2 { color: #8fbcbb; } 22 | .cm-s-nord .CodeMirror-gutters { 23 | background: #3b4252; 24 | color: #d8dee9; 25 | } -------------------------------------------------------------------------------- /lib/touchbar-menu.js: -------------------------------------------------------------------------------- 1 | const { TouchBar } = require('electron') 2 | const { TouchBarButton, TouchBarSpacer } = TouchBar 3 | const mainWindow = require('./main-window') 4 | 5 | const allNotes = new TouchBarButton({ 6 | label: '📒', 7 | click: () => { 8 | mainWindow.webContents.send('list:navigate', '/home') 9 | } 10 | }) 11 | 12 | const starredNotes = new TouchBarButton({ 13 | label: '⭐️', 14 | click: () => { 15 | mainWindow.webContents.send('list:navigate', '/starred') 16 | } 17 | }) 18 | 19 | const trash = new TouchBarButton({ 20 | label: '🗑', 21 | click: () => { 22 | mainWindow.webContents.send('list:navigate', '/trashed') 23 | } 24 | }) 25 | 26 | const newNote = new TouchBarButton({ 27 | label: '✎', 28 | click: () => { 29 | mainWindow.webContents.send('list:navigate', '/home') 30 | mainWindow.webContents.send('top:new-note') 31 | } 32 | }) 33 | 34 | module.exports = new TouchBar([ 35 | allNotes, 36 | starredNotes, 37 | trash, 38 | new TouchBarSpacer({ size: 'small' }), 39 | newNote 40 | ]) 41 | -------------------------------------------------------------------------------- /prettier.config: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": false, 4 | "jsxSingleQuote": true 5 | } -------------------------------------------------------------------------------- /resources/app.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/app.icns -------------------------------------------------------------------------------- /resources/app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/app.ico -------------------------------------------------------------------------------- /resources/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/app.png -------------------------------------------------------------------------------- /resources/boostnote-install.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/boostnote-install.gif -------------------------------------------------------------------------------- /resources/boostnote-install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/boostnote-install.png -------------------------------------------------------------------------------- /resources/boostnote-install@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/boostnote-install@2x.png -------------------------------------------------------------------------------- /resources/dmg.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/dmg.icns -------------------------------------------------------------------------------- /resources/dmg.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/dmg.ico -------------------------------------------------------------------------------- /resources/dmg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/dmg.png -------------------------------------------------------------------------------- /resources/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/favicon.ico -------------------------------------------------------------------------------- /resources/finder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/finder.png -------------------------------------------------------------------------------- /resources/fonts/KaTeX_AMS-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_AMS-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_AMS-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_AMS-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_AMS-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_AMS-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_AMS-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_AMS-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Caligraphic-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Caligraphic-Bold.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Caligraphic-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Caligraphic-Bold.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Caligraphic-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Caligraphic-Bold.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Caligraphic-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Caligraphic-Bold.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Caligraphic-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Caligraphic-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Caligraphic-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Caligraphic-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Caligraphic-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Caligraphic-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Caligraphic-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Caligraphic-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Fraktur-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Fraktur-Bold.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Fraktur-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Fraktur-Bold.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Fraktur-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Fraktur-Bold.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Fraktur-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Fraktur-Bold.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Fraktur-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Fraktur-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Fraktur-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Fraktur-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Fraktur-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Fraktur-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Fraktur-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Fraktur-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Bold.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Bold.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Bold.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Bold.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Italic.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Italic.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Italic.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Italic.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Main-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Main-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-BoldItalic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-BoldItalic.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-BoldItalic.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-BoldItalic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-BoldItalic.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-BoldItalic.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-Italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-Italic.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-Italic.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-Italic.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-Italic.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Math-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Math-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Bold.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Bold.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Bold.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Bold.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Bold.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Italic.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Italic.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Italic.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Italic.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_SansSerif-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_SansSerif-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Script-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Script-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Script-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Script-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Script-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Script-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Script-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Script-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size1-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size1-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size1-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size1-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size1-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size1-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size1-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size1-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size2-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size2-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size2-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size2-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size2-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size2-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size2-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size2-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size3-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size3-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size3-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size3-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size3-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size3-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size3-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size3-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size4-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size4-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size4-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size4-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size4-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size4-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Size4-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Size4-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Typewriter-Regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Typewriter-Regular.eot -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Typewriter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Typewriter-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Typewriter-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Typewriter-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/KaTeX_Typewriter-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/KaTeX_Typewriter-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/Lato-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/Lato-Black.ttf -------------------------------------------------------------------------------- /resources/fonts/Lato-Black.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/Lato-Black.woff -------------------------------------------------------------------------------- /resources/fonts/Lato-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/Lato-Black.woff2 -------------------------------------------------------------------------------- /resources/fonts/Lato-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/Lato-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/Lato-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/Lato-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/Lato-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/Lato-Regular.woff2 -------------------------------------------------------------------------------- /resources/fonts/MaterialIcons-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/MaterialIcons-Regular.ttf -------------------------------------------------------------------------------- /resources/fonts/MaterialIcons-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/MaterialIcons-Regular.woff -------------------------------------------------------------------------------- /resources/fonts/MaterialIcons-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/fonts/MaterialIcons-Regular.woff2 -------------------------------------------------------------------------------- /resources/icon/icon-all-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-all 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-all.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-all 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-code-off.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-code-off 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /resources/icon/icon-column-list.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-column-list 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /resources/icon/icon-column.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-column 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-down 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /resources/icon/icon-edit-lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-edit-lock 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /resources/icon/icon-full.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-full 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /resources/icon/icon-info.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-info 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /resources/icon/icon-left-to-right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/icon-list-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-list-active 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /resources/icon/icon-list.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-list 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /resources/icon/icon-lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-lock 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-mode-markdown-off-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-mode-markdown-off 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /resources/icon/icon-mode-markdown-off.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-mode-markdown-off 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /resources/icon/icon-newnote.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-newnote3 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-note-text.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-note-text 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /resources/icon/icon-plus.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-plus 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-previewoff-off.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-previewoff-off 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /resources/icon/icon-previewoff-on.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-previewoff-on 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /resources/icon/icon-right-to-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resources/icon/icon-right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-right 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /resources/icon/icon-search-active.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 11 | 14 | -------------------------------------------------------------------------------- /resources/icon/icon-search.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 11 | 14 | -------------------------------------------------------------------------------- /resources/icon/icon-setting.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-setting 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /resources/icon/icon-sidebar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-sidebar 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-star-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-star-active 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /resources/icon/icon-star-sidenav.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-star-sidenav 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /resources/icon/icon-star.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-star 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-starred.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-starred 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /resources/icon/icon-tag-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-tag-active 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /resources/icon/icon-tag.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-tag 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /resources/icon/icon-trash-active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-trash-active 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-trash-sidenav.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-trash-sidenav 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /resources/icon/icon-trash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-trash 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-unlock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-unlock 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /resources/icon/icon-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-down 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /resources/icon/icon-x-light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | x 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /resources/icon/icon-x.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | x 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /resources/icon/icon-zoom.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | icon-zoom 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /resources/repository/top.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/repository/top.png -------------------------------------------------------------------------------- /resources/tray-icon-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/tray-icon-dark.png -------------------------------------------------------------------------------- /resources/tray-icon-dark@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/tray-icon-dark@2x.png -------------------------------------------------------------------------------- /resources/tray-icon-default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/tray-icon-default.png -------------------------------------------------------------------------------- /resources/tray-icon-default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/tray-icon-default@2x.png -------------------------------------------------------------------------------- /resources/tray-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/tray-icon.png -------------------------------------------------------------------------------- /resources/tray-icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BoostIO/BoostNote-Legacy/789926bc760628ecedbd0051ca96d190a2be234f/resources/tray-icon@2x.png -------------------------------------------------------------------------------- /snap/gui/boostnote.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Name=Boostnote 5 | Comment=A note-taking app for programmers 6 | Exec=$SNAP/etc/boostnote/Boostnote 7 | Icon=resources/app.png 8 | MimeType=image/x-foo; 9 | NotShowIn=KDE; 10 | -------------------------------------------------------------------------------- /snap/snapcraft.yaml: -------------------------------------------------------------------------------- 1 | name: boostnote 2 | version: '0.1' 3 | summary: A note-taking app for programmers 4 | description: | 5 | Boostnote is an open source note-taking app made for programmers just like you. https://boostnote.io 6 | https://github.com/BoostIO/Boostnote 7 | 8 | grade: stable 9 | confinement: strict 10 | 11 | apps: 12 | asmstnote: 13 | command: desktop-launch $SNAP/etc/boostnote/Boostnote 14 | plugs: 15 | - browser-support 16 | - network 17 | - unity7 18 | - gsettings 19 | 20 | parts: 21 | src: 22 | plugin: nodejs 23 | source: . 24 | 25 | deps: 26 | plugin: nil 27 | stage-packages: 28 | - libgconf-2-4 29 | - libnss3 30 | - libxss1 31 | - fontconfig-config 32 | 33 | desktop-integration: 34 | plugin: nil 35 | stage-packages: 36 | - libappindicator1 37 | - libdbusmenu-glib4 38 | - libnotify4 39 | - libunity9 40 | 41 | launcher: 42 | plugin: dump 43 | source: . 44 | stage: 45 | - etc/boostnote 46 | organize: 47 | dist/Boostnote-linux-x64: etc/boostnote 48 | after: [desktop-glib-only] 49 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | sandbox/* 2 | -------------------------------------------------------------------------------- /tests/components/TagListItem.snapshot.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import renderer from 'react-test-renderer' 3 | import TagListItem from 'browser/components/TagListItem' 4 | 5 | it('TagListItem renders correctly', () => { 6 | const tagListItem = renderer.create( 7 | 8 | ) 9 | 10 | expect(tagListItem.toJSON()).toMatchSnapshot() 11 | }) 12 | -------------------------------------------------------------------------------- /tests/components/__snapshots__/TagListItem.snapshot.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`TagListItem renders correctly 1`] = ` 4 |
8 |
11 | 32 |
33 | `; 34 | -------------------------------------------------------------------------------- /tests/dataApi/copyFile.test.js: -------------------------------------------------------------------------------- 1 | const copyFile = require('browser/main/lib/dataApi/copyFile') 2 | 3 | const path = require('path') 4 | const fs = require('fs') 5 | const os = require('os') 6 | const execSync = require('child_process').execSync 7 | const removeDirCommand = os.platform() === 'win32' ? 'rmdir /s /q ' : 'rm -rf ' 8 | 9 | const testFile = 'test.txt' 10 | const srcFolder = path.join(__dirname, '🤔') 11 | const srcPath = path.join(srcFolder, testFile) 12 | const dstFolder = path.join(__dirname, '😇') 13 | const dstPath = path.join(dstFolder, testFile) 14 | 15 | beforeAll(() => { 16 | if (!fs.existsSync(srcFolder)) fs.mkdirSync(srcFolder) 17 | 18 | fs.writeFileSync(srcPath, 'test') 19 | }) 20 | 21 | it('`copyFile` should handle encoded URI on src path', done => { 22 | return copyFile(encodeURI(srcPath), dstPath) 23 | .then(() => { 24 | expect(true).toBe(true) 25 | done() 26 | }) 27 | .catch(() => { 28 | expect(false).toBe(true) 29 | done() 30 | }) 31 | }) 32 | 33 | afterAll(() => { 34 | fs.unlinkSync(srcPath) 35 | fs.unlinkSync(dstPath) 36 | execSync(removeDirCommand + '"' + srcFolder + '"') 37 | execSync(removeDirCommand + '"' + dstFolder + '"') 38 | }) 39 | -------------------------------------------------------------------------------- /tests/dataApi/createFolder.test.js: -------------------------------------------------------------------------------- 1 | const createFolder = require('browser/main/lib/dataApi/createFolder') 2 | 3 | global.document = require('jsdom').jsdom('') 4 | global.window = document.defaultView 5 | global.navigator = window.navigator 6 | 7 | const Storage = require('dom-storage') 8 | const localStorage = (window.localStorage = global.localStorage = new Storage( 9 | null, 10 | { strict: true } 11 | )) 12 | const path = require('path') 13 | const _ = require('lodash') 14 | const TestDummy = require('../fixtures/TestDummy') 15 | const sander = require('sander') 16 | const os = require('os') 17 | const CSON = require('@rokt33r/season') 18 | 19 | const storagePath = path.join(os.tmpdir(), 'test/create-folder') 20 | 21 | let storageContext 22 | 23 | beforeAll(() => { 24 | storageContext = TestDummy.dummyStorage(storagePath) 25 | localStorage.setItem('storages', JSON.stringify([storageContext.cache])) 26 | }) 27 | 28 | it('Create a folder', done => { 29 | const storageKey = storageContext.cache.key 30 | const input = { 31 | name: 'created', 32 | color: '#ff5555' 33 | } 34 | return Promise.resolve() 35 | .then(() => { 36 | return createFolder(storageKey, input) 37 | }) 38 | .then(data => { 39 | expect(_.find(data.storage.folders, input)).not.toBeNull() 40 | const jsonData = CSON.readFileSync( 41 | path.join(data.storage.path, 'boostnote.json') 42 | ) 43 | expect(_.find(jsonData.folders, input)).not.toBeNull() 44 | done() 45 | }) 46 | }) 47 | 48 | afterAll(() => { 49 | localStorage.clear() 50 | sander.rimrafSync(storagePath) 51 | }) 52 | -------------------------------------------------------------------------------- /tests/dataApi/createSnippet.test.js: -------------------------------------------------------------------------------- 1 | const createSnippet = require('browser/main/lib/dataApi/createSnippet') 2 | const sander = require('sander') 3 | const os = require('os') 4 | const path = require('path') 5 | 6 | const snippetFilePath = path.join(os.tmpdir(), 'test', 'create-snippet') 7 | const snippetFile = path.join(snippetFilePath, 'snippets.json') 8 | 9 | beforeEach(() => { 10 | sander.writeFileSync(snippetFile, '[]') 11 | }) 12 | 13 | it('Create a snippet', () => { 14 | return Promise.resolve() 15 | .then(() => Promise.all([createSnippet(snippetFile)])) 16 | .then(function assert(data) { 17 | data = data[0] 18 | const snippets = JSON.parse(sander.readFileSync(snippetFile)) 19 | const snippet = snippets.find( 20 | currentSnippet => currentSnippet.id === data.id 21 | ) 22 | expect(snippet).not.toBeUndefined() 23 | expect(snippet.name).toEqual(data.name) 24 | expect(snippet.prefix).toEqual(data.prefix) 25 | expect(snippet.content).toEqual(data.content) 26 | expect(snippet.linesHighlighted).toEqual(data.linesHighlighted) 27 | }) 28 | }) 29 | 30 | afterAll(() => { 31 | sander.rimrafSync(snippetFilePath) 32 | }) 33 | -------------------------------------------------------------------------------- /tests/dataApi/deleteSnippet-test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava') 2 | const deleteSnippet = require('browser/main/lib/dataApi/deleteSnippet') 3 | const sander = require('sander') 4 | const os = require('os') 5 | const path = require('path') 6 | const crypto = require('crypto') 7 | 8 | const snippetFilePath = path.join(os.tmpdir(), 'test', 'delete-snippet') 9 | const snippetFile = path.join(snippetFilePath, 'snippets.json') 10 | const newSnippet = { 11 | id: crypto.randomBytes(16).toString('hex'), 12 | name: 'Unnamed snippet', 13 | prefix: [], 14 | content: '' 15 | } 16 | 17 | test.beforeEach(t => { 18 | sander.writeFileSync(snippetFile, JSON.stringify([newSnippet])) 19 | }) 20 | 21 | test.serial('Delete a snippet', t => { 22 | return Promise.resolve() 23 | .then(function doTest() { 24 | return Promise.all([deleteSnippet(newSnippet, snippetFile)]) 25 | }) 26 | .then(function assert(data) { 27 | data = data[0] 28 | const snippets = JSON.parse(sander.readFileSync(snippetFile)) 29 | t.is(snippets.length, 0) 30 | }) 31 | }) 32 | 33 | test.after.always(() => { 34 | sander.rimrafSync(snippetFilePath) 35 | }) 36 | -------------------------------------------------------------------------------- /tests/dataApi/removeStorage-test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava') 2 | const removeStorage = require('browser/main/lib/dataApi/removeStorage') 3 | 4 | global.document = require('jsdom').jsdom('') 5 | global.window = document.defaultView 6 | global.navigator = window.navigator 7 | 8 | const Storage = require('dom-storage') 9 | const localStorage = (window.localStorage = global.localStorage = new Storage( 10 | null, 11 | { strict: true } 12 | )) 13 | const path = require('path') 14 | const TestDummy = require('../fixtures/TestDummy') 15 | const sander = require('sander') 16 | const os = require('os') 17 | 18 | const storagePath = path.join(os.tmpdir(), 'test/remove-storage') 19 | 20 | test.beforeEach(t => { 21 | t.context.storage = TestDummy.dummyStorage(storagePath) 22 | localStorage.setItem('storages', JSON.stringify([t.context.storage.cache])) 23 | }) 24 | 25 | test('Remove a storage', t => { 26 | const storageKey = t.context.storage.cache.key 27 | return Promise.resolve() 28 | .then(function doTest() { 29 | return removeStorage(storageKey) 30 | }) 31 | .then(function assert(data) { 32 | t.is(JSON.parse(localStorage.getItem('storages')).length, 0) 33 | }) 34 | }) 35 | 36 | test.after(function after() { 37 | localStorage.clear() 38 | sander.rimrafSync(storagePath) 39 | }) 40 | -------------------------------------------------------------------------------- /tests/dataApi/renameStorage-test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava') 2 | const renameStorage = require('browser/main/lib/dataApi/renameStorage') 3 | 4 | global.document = require('jsdom').jsdom('') 5 | global.window = document.defaultView 6 | global.navigator = window.navigator 7 | 8 | const Storage = require('dom-storage') 9 | const localStorage = (window.localStorage = global.localStorage = new Storage( 10 | null, 11 | { strict: true } 12 | )) 13 | const path = require('path') 14 | const _ = require('lodash') 15 | const TestDummy = require('../fixtures/TestDummy') 16 | const sander = require('sander') 17 | const os = require('os') 18 | 19 | const storagePath = path.join(os.tmpdir(), 'test/rename-storage') 20 | 21 | test.beforeEach(t => { 22 | t.context.storage = TestDummy.dummyStorage(storagePath) 23 | localStorage.setItem('storages', JSON.stringify([t.context.storage.cache])) 24 | }) 25 | 26 | test.serial('Rename a storage', t => { 27 | const storageKey = t.context.storage.cache.key 28 | return Promise.resolve() 29 | .then(function doTest() { 30 | return renameStorage(storageKey, 'changed') 31 | }) 32 | .then(function assert(data) { 33 | const cachedStorageList = JSON.parse(localStorage.getItem('storages')) 34 | t.true(_.find(cachedStorageList, { key: storageKey }).name === 'changed') 35 | }) 36 | }) 37 | 38 | test.after(function after() { 39 | localStorage.clear() 40 | sander.rimrafSync(storagePath) 41 | }) 42 | -------------------------------------------------------------------------------- /tests/dataApi/toggleStorage-test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava') 2 | const toggleStorage = require('browser/main/lib/dataApi/toggleStorage') 3 | 4 | global.document = require('jsdom').jsdom('') 5 | global.window = document.defaultView 6 | global.navigator = window.navigator 7 | 8 | const Storage = require('dom-storage') 9 | const localStorage = (window.localStorage = global.localStorage = new Storage( 10 | null, 11 | { strict: true } 12 | )) 13 | const path = require('path') 14 | const _ = require('lodash') 15 | const TestDummy = require('../fixtures/TestDummy') 16 | const sander = require('sander') 17 | const os = require('os') 18 | 19 | const storagePath = path.join(os.tmpdir(), 'test/toggle-storage') 20 | 21 | test.beforeEach(t => { 22 | t.context.storage = TestDummy.dummyStorage(storagePath) 23 | localStorage.setItem('storages', JSON.stringify([t.context.storage.cache])) 24 | }) 25 | 26 | test.serial('Toggle a storage location', t => { 27 | const storageKey = t.context.storage.cache.key 28 | return Promise.resolve() 29 | .then(function doTest() { 30 | return toggleStorage(storageKey, true) 31 | }) 32 | .then(function assert(data) { 33 | const cachedStorageList = JSON.parse(localStorage.getItem('storages')) 34 | t.true(_.find(cachedStorageList, { key: storageKey }).isOpen === true) 35 | }) 36 | }) 37 | 38 | test.after(function after() { 39 | localStorage.clear() 40 | sander.rimrafSync(storagePath) 41 | }) 42 | -------------------------------------------------------------------------------- /tests/dataApi/updateSnippet-test.js: -------------------------------------------------------------------------------- 1 | const test = require('ava') 2 | const updateSnippet = require('browser/main/lib/dataApi/updateSnippet') 3 | const sander = require('sander') 4 | const os = require('os') 5 | const path = require('path') 6 | const crypto = require('crypto') 7 | 8 | const snippetFilePath = path.join(os.tmpdir(), 'test', 'update-snippet') 9 | const snippetFile = path.join(snippetFilePath, 'snippets.json') 10 | const oldSnippet = { 11 | id: crypto.randomBytes(16).toString('hex'), 12 | name: 'Initial snippet', 13 | prefix: [], 14 | content: '' 15 | } 16 | 17 | const newSnippet = { 18 | id: oldSnippet.id, 19 | name: 'new name', 20 | prefix: ['prefix'], 21 | content: 'new content' 22 | } 23 | 24 | test.beforeEach(t => { 25 | sander.writeFileSync(snippetFile, JSON.stringify([oldSnippet])) 26 | }) 27 | 28 | test.serial('Update a snippet', t => { 29 | return Promise.resolve() 30 | .then(function doTest() { 31 | return Promise.all([updateSnippet(newSnippet, snippetFile)]) 32 | }) 33 | .then(function assert() { 34 | const snippets = JSON.parse(sander.readFileSync(snippetFile)) 35 | const snippet = snippets.find( 36 | currentSnippet => currentSnippet.id === newSnippet.id 37 | ) 38 | t.not(snippet, undefined) 39 | t.is(snippet.name, newSnippet.name) 40 | t.deepEqual(snippet.prefix, newSnippet.prefix) 41 | t.is(snippet.content, newSnippet.content) 42 | }) 43 | }) 44 | 45 | test.after.always(() => { 46 | sander.rimrafSync(snippetFilePath) 47 | }) 48 | -------------------------------------------------------------------------------- /tests/date-formatter-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Unit test for browser/lib/date-formatter.js 3 | */ 4 | const test = require('ava') 5 | const { formatDate } = require('browser/lib/date-formatter') 6 | 7 | test(t => { 8 | t.throws(() => formatDate('invalid argument'), 'Invalid argument.') 9 | }) 10 | -------------------------------------------------------------------------------- /tests/helpers/setup-browser-env.js: -------------------------------------------------------------------------------- 1 | import browserEnv from 'browser-env' 2 | browserEnv(['window', 'document', 'navigator']) 3 | 4 | // for CodeMirror mockup 5 | document.body.createTextRange = function() { 6 | return { 7 | setEnd: function() {}, 8 | setStart: function() {}, 9 | getBoundingClientRect: function() { 10 | return { right: 0 } 11 | }, 12 | getClientRects: function() { 13 | return { 14 | length: 0, 15 | left: 0, 16 | right: 0 17 | } 18 | } 19 | } 20 | } 21 | 22 | window.localStorage = { 23 | // polyfill 24 | getItem() { 25 | return '{}' 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /tests/helpers/setup-electron-mock.js: -------------------------------------------------------------------------------- 1 | import mock from 'mock-require' 2 | 3 | const noop = () => {} 4 | 5 | mock('electron', { 6 | remote: { 7 | app: { 8 | getAppPath: noop, 9 | getPath: noop 10 | } 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /tests/jest.js: -------------------------------------------------------------------------------- 1 | // Here you can mock the libraries connected through direct insertion