Compare commits
1 Commits
command_en
...
v1.0.180
Author | SHA1 | Date | |
---|---|---|---|
|
982a048f2a |
327
.eslintignore
@@ -6,7 +6,6 @@ _releases/
|
||||
Assets/
|
||||
CliClient/build
|
||||
CliClient/locales
|
||||
CliClient/locales-build
|
||||
CliClient/node_modules
|
||||
CliClient/tests-build
|
||||
CliClient/tests/enex_to_md
|
||||
@@ -15,320 +14,42 @@ CliClient/tests/logs
|
||||
CliClient/tests/support
|
||||
CliClient/tests/sync
|
||||
CliClient/tests/tmp
|
||||
Clipper/content_scripts/JSDOMParser.js
|
||||
Clipper/content_scripts/Readability-readerable.js
|
||||
Clipper/content_scripts/Readability.js
|
||||
Clipper/dist
|
||||
Clipper/icons
|
||||
Clipper/popup/build
|
||||
Clipper/popup/config/webpack.config.js
|
||||
Clipper/popup/config/webpack_config_at_eject_time.js
|
||||
Clipper/popup/node_modules
|
||||
Clipper/popup/scripts/build.js
|
||||
Clipper/joplin-webclipper/content_scripts/JSDOMParser.js
|
||||
Clipper/joplin-webclipper/content_scripts/Readability-readerable.js
|
||||
Clipper/joplin-webclipper/content_scripts/Readability.js
|
||||
Clipper/joplin-webclipper/dist
|
||||
Clipper/joplin-webclipper/icons
|
||||
Clipper/joplin-webclipper/popup/build
|
||||
Clipper/joplin-webclipper/popup/node_modules
|
||||
docs/
|
||||
ElectronClient/dist
|
||||
ElectronClient/lib
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/plugins/lists.js
|
||||
ElectronClient/lib/vendor/sjcl-rn.js
|
||||
ElectronClient/lib/vendor/sjcl.js
|
||||
ElectronClient/locales
|
||||
ElectronClient/node_modules
|
||||
ElectronClient/packageInfo.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/supportedLocales.js
|
||||
ElectronClient/app/dist
|
||||
ElectronClient/app/lib
|
||||
ElectronClient/app/lib/vendor/sjcl-rn.js
|
||||
ElectronClient/app/lib/vendor/sjcl.js
|
||||
ElectronClient/app/locales
|
||||
ElectronClient/app/node_modules
|
||||
highlight.pack.js
|
||||
Modules/TinyMCE/JoplinLists/
|
||||
node_modules/
|
||||
ReactNativeClient/android
|
||||
ReactNativeClient/ios
|
||||
ReactNativeClient/lib/joplin-renderer/assets/
|
||||
ReactNativeClient/lib/joplin-renderer/vendor/fountain.min.js
|
||||
ReactNativeClient/lib/rnInjectedJs/
|
||||
ReactNativeClient/lib/vendor/
|
||||
ReactNativeClient/lib/welcomeAssets.js
|
||||
ReactNativeClient/locales
|
||||
ReactNativeClient/node_modules
|
||||
ReactNativeClient/pluginAssets/
|
||||
readme/
|
||||
Server/.git/
|
||||
Server/.github/
|
||||
Server/bin/
|
||||
Server/dist/
|
||||
Server/docs/
|
||||
Server/node_modules/
|
||||
Tools/node_modules
|
||||
Tools/PortableAppsLauncher
|
||||
Modules/TinyMCE/IconPack/postinstall.js
|
||||
Modules/TinyMCE/langs/
|
||||
CliClient/build/
|
||||
Server/.git/
|
||||
Server/.github/
|
||||
Server/docs/
|
||||
Server/dist/
|
||||
Server/bin/
|
||||
Server/node_modules/
|
||||
ElectronClient/app/packageInfo.js
|
||||
ReactNativeClient/pluginAssets/
|
||||
ReactNativeClient/lib/joplin-renderer/vendor/fountain.min.js
|
||||
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
CliClient/app/LinkSelector.js
|
||||
CliClient/app/services/plugins/PluginRunner.js
|
||||
CliClient/tests/InMemoryCache.js
|
||||
CliClient/tests/models_Setting.js
|
||||
CliClient/tests/services_CommandService.js
|
||||
CliClient/tests/services_InteropService.js
|
||||
CliClient/tests/services_PluginService.js
|
||||
CliClient/tests/services_rest_Api.js
|
||||
CliClient/tests/services/plugins/api/JoplinSetting.js
|
||||
CliClient/tests/services/plugins/sandboxProxy.js
|
||||
CliClient/tests/synchronizer_LockHandler.js
|
||||
CliClient/tests/synchronizer_MigrationHandler.js
|
||||
ElectronClient/app.js
|
||||
ElectronClient/bridge.js
|
||||
ElectronClient/commands/copyDevCommand.js
|
||||
ElectronClient/commands/focusElement.js
|
||||
ElectronClient/commands/startExternalEditing.js
|
||||
ElectronClient/commands/stopExternalEditing.js
|
||||
ElectronClient/commands/toggleExternalEditing.js
|
||||
ElectronClient/ElectronAppWrapper.js
|
||||
ElectronClient/global.d.js
|
||||
ElectronClient/gui/Button/Button.js
|
||||
ElectronClient/gui/ConfigScreen/ButtonBar.js
|
||||
ElectronClient/gui/ConfigScreen/ConfigScreen.js
|
||||
ElectronClient/gui/ConfigScreen/SideBar.js
|
||||
ElectronClient/gui/DropboxLoginScreen.js
|
||||
ElectronClient/gui/ErrorBoundary.js
|
||||
ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js
|
||||
ElectronClient/gui/KeymapConfig/ShortcutRecorder.js
|
||||
ElectronClient/gui/KeymapConfig/styles/index.js
|
||||
ElectronClient/gui/KeymapConfig/utils/getLabel.js
|
||||
ElectronClient/gui/KeymapConfig/utils/useCommandStatus.js
|
||||
ElectronClient/gui/KeymapConfig/utils/useKeymap.js
|
||||
ElectronClient/gui/MainScreen/commands/editAlarm.js
|
||||
ElectronClient/gui/MainScreen/commands/exportPdf.js
|
||||
ElectronClient/gui/MainScreen/commands/hideModalMessage.js
|
||||
ElectronClient/gui/MainScreen/commands/moveToFolder.js
|
||||
ElectronClient/gui/MainScreen/commands/newFolder.js
|
||||
ElectronClient/gui/MainScreen/commands/newNote.js
|
||||
ElectronClient/gui/MainScreen/commands/newTodo.js
|
||||
ElectronClient/gui/MainScreen/commands/print.js
|
||||
ElectronClient/gui/MainScreen/commands/renameFolder.js
|
||||
ElectronClient/gui/MainScreen/commands/renameTag.js
|
||||
ElectronClient/gui/MainScreen/commands/search.js
|
||||
ElectronClient/gui/MainScreen/commands/selectTemplate.js
|
||||
ElectronClient/gui/MainScreen/commands/setTags.js
|
||||
ElectronClient/gui/MainScreen/commands/showModalMessage.js
|
||||
ElectronClient/gui/MainScreen/commands/showNoteContentProperties.js
|
||||
ElectronClient/gui/MainScreen/commands/showNoteProperties.js
|
||||
ElectronClient/gui/MainScreen/commands/showShareNoteDialog.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleEditors.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleNoteList.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleSideBar.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleVisiblePanes.js
|
||||
ElectronClient/gui/MainScreen/MainScreen.js
|
||||
ElectronClient/gui/MenuBar.js
|
||||
ElectronClient/gui/MultiNoteActions.js
|
||||
ElectronClient/gui/NoteContentPropertiesDialog.js
|
||||
ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js
|
||||
ElectronClient/gui/NoteEditor/commands/focusElementNoteBody.js
|
||||
ElectronClient/gui/NoteEditor/commands/focusElementNoteTitle.js
|
||||
ElectronClient/gui/NoteEditor/commands/showLocalSearch.js
|
||||
ElectronClient/gui/NoteEditor/commands/showRevisions.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/Editor.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/Toolbar.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinMode.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useKeymap.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useLineSorting.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollUtils.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
ElectronClient/gui/NoteEditor/NoteEditor.js
|
||||
ElectronClient/gui/NoteEditor/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/utils/contextMenu.js
|
||||
ElectronClient/gui/NoteEditor/utils/index.js
|
||||
ElectronClient/gui/NoteEditor/utils/resourceHandling.js
|
||||
ElectronClient/gui/NoteEditor/utils/types.js
|
||||
ElectronClient/gui/NoteEditor/utils/useDropHandler.js
|
||||
ElectronClient/gui/NoteEditor/utils/useFolder.js
|
||||
ElectronClient/gui/NoteEditor/utils/useFormNote.js
|
||||
ElectronClient/gui/NoteEditor/utils/useMarkupToHtml.js
|
||||
ElectronClient/gui/NoteEditor/utils/useMessageHandler.js
|
||||
ElectronClient/gui/NoteEditor/utils/useNoteSearchBar.js
|
||||
ElectronClient/gui/NoteEditor/utils/usePluginServiceRegistration.js
|
||||
ElectronClient/gui/NoteEditor/utils/useSearchMarkers.js
|
||||
ElectronClient/gui/NoteEditor/utils/useWindowCommandHandler.js
|
||||
ElectronClient/gui/NoteList/commands/focusElementNoteList.js
|
||||
ElectronClient/gui/NoteList/NoteList.js
|
||||
ElectronClient/gui/NoteListControls/commands/focusSearch.js
|
||||
ElectronClient/gui/NoteListControls/NoteListControls.js
|
||||
ElectronClient/gui/NoteListItem.js
|
||||
ElectronClient/gui/NoteTextViewer.js
|
||||
ElectronClient/gui/NoteToolbar/NoteToolbar.js
|
||||
ElectronClient/gui/OneDriveLoginScreen.js
|
||||
ElectronClient/gui/ResizableLayout/hooks/useLayoutItemSizes.js
|
||||
ElectronClient/gui/ResizableLayout/hooks/useWindowResizeEvent.js
|
||||
ElectronClient/gui/ResizableLayout/ResizableLayout.js
|
||||
ElectronClient/gui/ResourceScreen.js
|
||||
ElectronClient/gui/Root_UpgradeSyncTarget.js
|
||||
ElectronClient/gui/Root.js
|
||||
ElectronClient/gui/SearchBar/hooks/useSearch.js
|
||||
ElectronClient/gui/SearchBar/SearchBar.js
|
||||
ElectronClient/gui/SearchBar/styles/index.js
|
||||
ElectronClient/gui/ShareNoteDialog.js
|
||||
ElectronClient/gui/SideBar/commands/focusElementSideBar.js
|
||||
ElectronClient/gui/SideBar/SideBar.js
|
||||
ElectronClient/gui/SideBar/styles/index.js
|
||||
ElectronClient/gui/StatusScreen/StatusScreen.js
|
||||
ElectronClient/gui/style/StyledInput.js
|
||||
ElectronClient/gui/style/StyledTextInput.js
|
||||
ElectronClient/gui/ToggleEditorsButton/styles/index.js
|
||||
ElectronClient/gui/ToggleEditorsButton/ToggleEditorsButton.js
|
||||
ElectronClient/gui/ToolbarBase.js
|
||||
ElectronClient/gui/ToolbarButton/styles/index.js
|
||||
ElectronClient/gui/ToolbarButton/ToolbarButton.js
|
||||
ElectronClient/gui/utils/NoteListUtils.js
|
||||
ElectronClient/InteropServiceHelper.js
|
||||
ElectronClient/plugins/GotoAnything.js
|
||||
ElectronClient/services/bridge.js
|
||||
ElectronClient/services/commands/types.js
|
||||
ElectronClient/services/plugins/hooks/useThemeCss.js
|
||||
ElectronClient/services/plugins/hooks/useViewIsReady.js
|
||||
ElectronClient/services/plugins/PlatformImplementation.js
|
||||
ElectronClient/services/plugins/PluginRunner.js
|
||||
ElectronClient/services/plugins/UserWebview.js
|
||||
ElectronClient/services/plugins/UserWebviewDialog.js
|
||||
ElectronClient/services/plugins/UserWebviewDialogButtonBar.js
|
||||
ReactNativeClient/lib/AsyncActionQueue.js
|
||||
ReactNativeClient/lib/BaseApplication.js
|
||||
ReactNativeClient/lib/checkPermissions.js
|
||||
ReactNativeClient/lib/commands/historyBackward.js
|
||||
ReactNativeClient/lib/commands/historyForward.js
|
||||
ReactNativeClient/lib/commands/synchronize.js
|
||||
ReactNativeClient/lib/components/BackButtonDialogBox.js
|
||||
ReactNativeClient/lib/components/CameraView.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnMessage.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnResourceLongPress.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useSource.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/NoteBodyViewer.js
|
||||
ReactNativeClient/lib/components/screens/Note.js
|
||||
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
|
||||
ReactNativeClient/lib/components/SelectDateTimeDialog.js
|
||||
ReactNativeClient/lib/errorUtils.js
|
||||
ReactNativeClient/lib/eventManager.js
|
||||
ReactNativeClient/lib/hooks/useEffectDebugger.js
|
||||
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
|
||||
ReactNativeClient/lib/hooks/usePrevious.js
|
||||
ReactNativeClient/lib/hooks/usePropsDebugger.js
|
||||
ReactNativeClient/lib/InMemoryCache.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/checkbox.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js
|
||||
# Ignore files generated from TypeScript files
|
||||
ElectronClient/app/gui/ShareNoteDialog.js
|
||||
ReactNativeClient/lib/JoplinServerApi.js
|
||||
ReactNativeClient/lib/locale.js
|
||||
ReactNativeClient/lib/Logger.js
|
||||
ReactNativeClient/lib/markdownUtils.js
|
||||
ReactNativeClient/lib/models/Alarm.js
|
||||
ReactNativeClient/lib/models/Setting.js
|
||||
ReactNativeClient/lib/ntpDate.js
|
||||
ReactNativeClient/lib/PoorManIntervals.js
|
||||
ReactNativeClient/lib/reducer.js
|
||||
ReactNativeClient/lib/services/AlarmService.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriver.android.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriver.ios.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriverNode.js
|
||||
ReactNativeClient/lib/services/BaseService.js
|
||||
ReactNativeClient/lib/services/commands/commandsToMarkdownTable.js
|
||||
ReactNativeClient/lib/services/commands/MenuUtils.js
|
||||
ReactNativeClient/lib/services/commands/propsHaveChanged.js
|
||||
ReactNativeClient/lib/services/commands/stateToWhenClauseContext.js
|
||||
ReactNativeClient/lib/services/commands/ToolbarButtonUtils.js
|
||||
ReactNativeClient/lib/services/CommandService.js
|
||||
ReactNativeClient/lib/services/contextkey/contextkey.js
|
||||
ReactNativeClient/lib/services/debug/populateDatabase.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Base.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Custom.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Html.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Jex.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Md.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Raw.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Base.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Custom.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_EnexToHtml.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_EnexToMd.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Jex.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Md.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Raw.js
|
||||
ReactNativeClient/lib/services/interop/InteropService.js
|
||||
ReactNativeClient/lib/services/interop/types.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainService.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.dummy.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.mobile.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.node.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriverBase.js
|
||||
ReactNativeClient/lib/services/KeymapService.js
|
||||
ReactNativeClient/lib/services/plugins/api/Global.js
|
||||
ReactNativeClient/lib/services/plugins/api/Joplin.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinCommands.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinData.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinFilters.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinInterop.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinPlugins.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinSettings.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViews.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsDialogs.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenuItems.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenus.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsPanels.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsToolbarButtons.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinWorkspace.js
|
||||
ReactNativeClient/lib/services/plugins/api/types.js
|
||||
ReactNativeClient/lib/services/plugins/BasePluginRunner.js
|
||||
ReactNativeClient/lib/services/plugins/MenuController.js
|
||||
ReactNativeClient/lib/services/plugins/MenuItemController.js
|
||||
ReactNativeClient/lib/services/plugins/Plugin.js
|
||||
ReactNativeClient/lib/services/plugins/PluginService.js
|
||||
ReactNativeClient/lib/services/plugins/reducer.js
|
||||
ReactNativeClient/lib/services/plugins/sandboxProxy.js
|
||||
ReactNativeClient/lib/services/plugins/ToolbarButtonController.js
|
||||
ReactNativeClient/lib/services/plugins/utils/createViewHandle.js
|
||||
ReactNativeClient/lib/services/plugins/utils/executeSandboxCall.js
|
||||
ReactNativeClient/lib/services/plugins/utils/manifestFromObject.js
|
||||
ReactNativeClient/lib/services/plugins/utils/mapEventHandlersToIds.js
|
||||
ReactNativeClient/lib/services/plugins/utils/types.js
|
||||
ReactNativeClient/lib/services/plugins/ViewController.js
|
||||
ReactNativeClient/lib/services/plugins/WebviewController.js
|
||||
ReactNativeClient/lib/services/ResourceEditWatcher/index.js
|
||||
ReactNativeClient/lib/services/ResourceEditWatcher/reducer.js
|
||||
ReactNativeClient/lib/services/rest/actionApi.desktop.js
|
||||
ReactNativeClient/lib/services/rest/Api.js
|
||||
ReactNativeClient/lib/services/rest/errors.js
|
||||
ReactNativeClient/lib/services/searchengine/filterParser.js
|
||||
ReactNativeClient/lib/services/searchengine/queryBuilder.js
|
||||
ReactNativeClient/lib/services/SettingUtils.js
|
||||
ReactNativeClient/lib/services/synchronizer/gui/useSyncTargetUpgrade.js
|
||||
ReactNativeClient/lib/services/synchronizer/LockHandler.js
|
||||
ReactNativeClient/lib/services/synchronizer/MigrationHandler.js
|
||||
ReactNativeClient/lib/services/synchronizer/migrations/1.js
|
||||
ReactNativeClient/lib/services/synchronizer/migrations/2.js
|
||||
ReactNativeClient/lib/services/synchronizer/utils/types.js
|
||||
ReactNativeClient/lib/services/UndoRedoService.js
|
||||
ReactNativeClient/lib/services/WhenClause.js
|
||||
ReactNativeClient/lib/ShareExtension.js
|
||||
ReactNativeClient/lib/shareHandler.js
|
||||
ReactNativeClient/lib/shim.js
|
||||
ReactNativeClient/lib/Synchronizer.js
|
||||
ReactNativeClient/lib/theme.js
|
||||
ReactNativeClient/lib/themes/aritimDark.js
|
||||
ReactNativeClient/lib/themes/dark.js
|
||||
ReactNativeClient/lib/themes/dracula.js
|
||||
ReactNativeClient/lib/themes/light.js
|
||||
ReactNativeClient/lib/themes/nord.js
|
||||
ReactNativeClient/lib/themes/oledDark.js
|
||||
ReactNativeClient/lib/themes/solarizedDark.js
|
||||
ReactNativeClient/lib/themes/solarizedLight.js
|
||||
ReactNativeClient/lib/themes/type.js
|
||||
ReactNativeClient/lib/uuid.js
|
||||
ReactNativeClient/lib/versionInfo.js
|
||||
ReactNativeClient/PluginAssetsLoader.js
|
||||
ReactNativeClient/setUpQuickActions.js
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
|
137
.eslintrc.js
@@ -4,9 +4,9 @@ module.exports = {
|
||||
'es6': true,
|
||||
'node': true,
|
||||
},
|
||||
'parser': '@typescript-eslint/parser',
|
||||
"parser": "@typescript-eslint/parser",
|
||||
'extends': ['eslint:recommended'],
|
||||
'settings': {
|
||||
"settings": {
|
||||
'react': {
|
||||
'version': '16.12',
|
||||
},
|
||||
@@ -19,10 +19,7 @@ module.exports = {
|
||||
'expect': 'readonly',
|
||||
'describe': 'readonly',
|
||||
'it': 'readonly',
|
||||
'beforeAll': 'readonly',
|
||||
'afterAll': 'readonly',
|
||||
'beforeEach': 'readonly',
|
||||
'afterEach': 'readonly',
|
||||
'jasmine': 'readonly',
|
||||
|
||||
// React Native variables
|
||||
@@ -32,105 +29,69 @@ module.exports = {
|
||||
'browserSupportsPromises_': true,
|
||||
'chrome': 'readonly',
|
||||
'browser': 'readonly',
|
||||
|
||||
'tinymce': 'readonly',
|
||||
},
|
||||
'parserOptions': {
|
||||
'ecmaVersion': 2018,
|
||||
'ecmaFeatures': {
|
||||
'jsx': true,
|
||||
},
|
||||
'sourceType': 'module',
|
||||
"ecmaFeatures": {
|
||||
"jsx": true,
|
||||
},
|
||||
"sourceType": "module",
|
||||
},
|
||||
'rules': {
|
||||
// -------------------------------
|
||||
// Code correctness
|
||||
// -------------------------------
|
||||
'react/jsx-uses-react': 'error',
|
||||
'react/jsx-uses-vars': 'error',
|
||||
'no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }],
|
||||
'@typescript-eslint/no-unused-vars': ['error', { 'argsIgnorePattern': '^_' }],
|
||||
'@typescript-eslint/explicit-member-accessibility': 'off',
|
||||
'no-constant-condition': 0,
|
||||
'no-prototype-builtins': 0,
|
||||
"react/jsx-uses-react": "error",
|
||||
"react/jsx-uses-vars": "error",
|
||||
"no-unused-vars": "error",
|
||||
"no-constant-condition": 0,
|
||||
"no-prototype-builtins": 0,
|
||||
// This error is always a false positive so far since it detects
|
||||
// possible race conditions in contexts where we know it cannot happen.
|
||||
'require-atomic-updates': 0,
|
||||
'prefer-const': ['error'],
|
||||
'no-var': ['error'],
|
||||
'no-new-func': ['error'],
|
||||
'import/prefer-default-export': ['error'],
|
||||
'import/first': ['error'],
|
||||
'no-array-constructor': ['error'],
|
||||
'radix': ['error'],
|
||||
"require-atomic-updates": 0,
|
||||
|
||||
// Warn only for now because fixing everything would take too much
|
||||
// refactoring, but new code should try to stick to it.
|
||||
'complexity': ['warn', { max: 10 }],
|
||||
|
||||
// Checks rules of Hooks
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
// Checks effect dependencies
|
||||
// Disable because of this: https://github.com/facebook/react/issues/16265
|
||||
// "react-hooks/exhaustive-deps": "warn",
|
||||
// -------------------------------
|
||||
// Coding style preferences
|
||||
// -------------------------------
|
||||
"enforce-react-hooks/enforce-react-hooks": 2,
|
||||
|
||||
// -------------------------------
|
||||
// Formatting
|
||||
// -------------------------------
|
||||
'space-in-parens': ['error', 'never'],
|
||||
'space-infix-ops': ['error'],
|
||||
'curly': ['error', 'multi-line', 'consistent'],
|
||||
'semi': ['error', 'always'],
|
||||
'eol-last': ['error', 'always'],
|
||||
'quotes': ['error', 'single'],
|
||||
'indent': ['error', 'tab'],
|
||||
'comma-dangle': ['error', {
|
||||
'arrays': 'always-multiline',
|
||||
'objects': 'always-multiline',
|
||||
'imports': 'always-multiline',
|
||||
'exports': 'always-multiline',
|
||||
'functions': 'never',
|
||||
"space-in-parens": ["error", "never"],
|
||||
"semi": ["error", "always"],
|
||||
"eol-last": ["error", "always"],
|
||||
"quotes": ["error", "single"],
|
||||
"indent": ["error", "tab"],
|
||||
"comma-dangle": ["error", "always-multiline"],
|
||||
"no-trailing-spaces": "error",
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"prefer-template": ["error"],
|
||||
"template-curly-spacing": ["error", "never"],
|
||||
"object-curly-spacing": ["error", "always"],
|
||||
"array-bracket-spacing": ["error", "never"],
|
||||
"key-spacing": ["error", {
|
||||
"beforeColon": false,
|
||||
"afterColon": true,
|
||||
"mode": "strict"
|
||||
}],
|
||||
'no-trailing-spaces': 'error',
|
||||
'linebreak-style': ['error', 'unix'],
|
||||
'prefer-template': ['error'],
|
||||
'template-curly-spacing': ['error', 'never'],
|
||||
'object-curly-spacing': ['error', 'always'],
|
||||
'array-bracket-spacing': ['error', 'never'],
|
||||
'key-spacing': ['error', {
|
||||
'beforeColon': false,
|
||||
'afterColon': true,
|
||||
'mode': 'strict',
|
||||
"block-spacing": ["error"],
|
||||
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
|
||||
"no-spaced-func": ["error"],
|
||||
"func-call-spacing": ["error"],
|
||||
"space-before-function-paren": ["error", {
|
||||
"anonymous": "never",
|
||||
"named": "never",
|
||||
"asyncArrow": "always"
|
||||
}],
|
||||
'block-spacing': ['error'],
|
||||
'brace-style': ['error', '1tbs', { 'allowSingleLine': true }],
|
||||
'no-spaced-func': ['error'],
|
||||
'func-call-spacing': ['error'],
|
||||
'space-before-function-paren': ['error', {
|
||||
'anonymous': 'never',
|
||||
'named': 'never',
|
||||
'asyncArrow': 'always',
|
||||
}],
|
||||
'multiline-comment-style': ['error', 'separate-lines'],
|
||||
'space-before-blocks': 'error',
|
||||
'spaced-comment': ['error', 'always'],
|
||||
'keyword-spacing': ['error', { 'before': true, 'after': true }],
|
||||
"multiline-comment-style": ["error", "separate-lines"],
|
||||
"space-before-blocks": "error",
|
||||
"spaced-comment": ["error", "always"],
|
||||
"keyword-spacing": ["error", { "before": true, "after": true }]
|
||||
},
|
||||
'plugins': [
|
||||
'react',
|
||||
'@typescript-eslint',
|
||||
'react-hooks',
|
||||
'import',
|
||||
"plugins": [
|
||||
"react",
|
||||
"@typescript-eslint",
|
||||
"enforce-react-hooks",
|
||||
],
|
||||
'overrides': [
|
||||
{
|
||||
// enable the rule specifically for TypeScript files
|
||||
'files': ['*.ts', '*.tsx'],
|
||||
'rules': {
|
||||
// Warn only because it would make it difficult to convert JS classes to TypeScript, unless we
|
||||
// make everything public which is not great. New code however should specify member accessibility.
|
||||
'@typescript-eslint/explicit-member-accessibility': ['warn'],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
@@ -1,15 +0,0 @@
|
||||
---
|
||||
name: "\U0001F914 Feature requests and support"
|
||||
about: 'For non-bug issues we recommend using the forum, where you''ll be more likely
|
||||
to get an answer: https://discourse.joplinapp.org/'
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
If this is a feature request or a support query, please note that you'll not get an answer here.
|
||||
|
||||
Instead we recommend using the forum where you'll are a lot more likely to get an answer: https://discourse.joplinapp.org/
|
||||
|
||||
The forum is also the right place to submit a feature request so that it can be discussed by other users.
|
23
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,9 +1,8 @@
|
||||
---
|
||||
name: "\U0001F41B Bug Report"
|
||||
name: "🐛 Bug Report"
|
||||
about: Report a reproducible bug or regression in Joplin.
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
labels: 'bug'
|
||||
|
||||
---
|
||||
|
||||
@@ -20,26 +19,24 @@ assignees: ''
|
||||
|
||||
## Environment
|
||||
|
||||
Joplin version:
|
||||
Platform:
|
||||
OS specifics:
|
||||
|
||||
Joplin version:
|
||||
Platform:
|
||||
OS specifcs:
|
||||
<!--
|
||||
Platform can be one of: macOS, Linux, Windows, Android, iOS, terminal (or a combination)
|
||||
OS specifics: e.g. OS version, Linux distribution, Android/iOS version...
|
||||
OS specifcs: e.g. OS version, Linux distribution, Android/iOS version, ...
|
||||
-->
|
||||
|
||||
## Steps to reproduce
|
||||
## Steps To Reproduce
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
1.
|
||||
2.
|
||||
|
||||
<!--
|
||||
Issues without reproduction steps are likely to stall.
|
||||
-->
|
||||
|
||||
## Describe what you expected to happen
|
||||
Describe what you expected to happen:
|
||||
|
||||
|
||||
|
||||
|
29
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
---
|
||||
name: "🤔 Questions and Help"
|
||||
about: The issue tracker is not for questions. Please ask questions on https://discourse.joplinapp.org/.
|
||||
title: ''
|
||||
labels: 'invalid'
|
||||
|
||||
---
|
||||
|
||||
⚠🚨⛔ The issue tracker is not for questions. ⛔🚨⚠
|
||||
|
||||
As it happens, support requests that are created as issues are likely to be closed. We want to make sure you are able to find the help you seek.
|
||||
|
||||
## Questions and Help
|
||||
|
||||
Please read the [documentation](https://joplinapp.org/) and [FAQ](https://joplinapp.org/faq/) first.
|
||||
|
||||
### https://discourse.joplinapp.org/
|
||||
|
||||
If you have still questions related to Joplin, please open a topic in the [forum](https://discourse.joplinapp.org/).
|
||||
You can use your GitHub credentials to login to the forum.
|
||||
|
||||
## Links
|
||||
|
||||
- Documentation: https://joplinapp.org
|
||||
- FAQ: https://joplinapp.org/faq/
|
||||
- Forum: https://discourse.joplinapp.org
|
||||
- How to enable end-to-end encryption: https://joplinapp.org/e2ee/
|
||||
- API documentation: https://joplinapp.org/api/
|
||||
- How to enable debug mode: https://joplinapp.org/debugging/
|
14
.github/PULL_REQUEST_TEMPLATE
vendored
@@ -2,24 +2,14 @@
|
||||
|
||||
Please prefix the title with the platform you are targetting:
|
||||
|
||||
Here are some examples of good titles:
|
||||
|
||||
- Desktop: Resolves #123: Added new setting to change font
|
||||
- Mobile, Desktop: Fixes #456: Fixed config screen error
|
||||
- All: Resolves #777: Made synchronisation faster
|
||||
|
||||
And here's an explanation of the title format:
|
||||
|
||||
- "Desktop" for the Windows/macOS/Linux app (Electron app)
|
||||
- "Mobile" for the mobile app (or "Android" / "iOS" if the pull request only applies to one of the mobile platforms)
|
||||
- "CLI" for the CLI app
|
||||
|
||||
If it's two platforms, separate them with commas - "Desktop, Mobile" or if it's for all platforms, prefix with "All".
|
||||
|
||||
If it's not related to any platform (such as a translation, change to the documentation, etc.), simply don't add a platform.
|
||||
|
||||
Then please append the issue that you've addressed or fixed. Use "Resolves #123" for new features or improvements and "Fixes #123" for bug fixes.
|
||||
For example: "Desktop: Added new setting to change font", or "Mobile: Fixed config screen error"
|
||||
|
||||
AND PLEASE READ THE GUIDE: https://github.com/laurent22/joplin/blob/dev/CONTRIBUTING.md
|
||||
PLEASE READ THE GUIDE FIRST: https://github.com/laurent22/joplin/blob/master/CONTRIBUTING.md
|
||||
|
||||
-->
|
||||
|
8
.github/stale.yml
vendored
@@ -1,15 +1,17 @@
|
||||
# Configuration for probot-stale - https://github.com/probot/stale
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 30
|
||||
daysUntilStale: 90
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- "good first issue"
|
||||
- "essential"
|
||||
- "essential-reviewed"
|
||||
- "help wanted"
|
||||
- "nice to have"
|
||||
- "upstream"
|
||||
- "backlog"
|
||||
- "high"
|
||||
- "spec"
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
|
284
.gitignore
vendored
@@ -37,292 +37,16 @@ _mydocs
|
||||
Assets/DownloadBadges*.psd
|
||||
node_modules
|
||||
Tools/github_oauth_token.txt
|
||||
CliClient/tests/support/amazon-s3-auth.json
|
||||
_releases
|
||||
ReactNativeClient/lib/csstojs/
|
||||
ReactNativeClient/lib/rnInjectedJs/
|
||||
ElectronClient/gui/note-viewer/fonts/
|
||||
ElectronClient/gui/note-viewer/lib.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/supportedLocales.js
|
||||
Clipper-source/
|
||||
Clipper/joplin-webclipper-source.zip
|
||||
joplin-webclipper-source.zip
|
||||
ElectronClient/app/gui/note-viewer/fonts/
|
||||
ElectronClient/app/gui/note-viewer/lib.js
|
||||
Tools/commit_hook.txt
|
||||
.vscode/*
|
||||
*.map
|
||||
ReactNativeClient/lib/sql-extensions/spellfix.so
|
||||
ReactNativeClient/lib/sql-extensions/spellfix.dylib
|
||||
CliClient/build/
|
||||
plugin_types/
|
||||
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
CliClient/app/LinkSelector.js
|
||||
CliClient/app/services/plugins/PluginRunner.js
|
||||
CliClient/tests/InMemoryCache.js
|
||||
CliClient/tests/models_Setting.js
|
||||
CliClient/tests/services_CommandService.js
|
||||
CliClient/tests/services_InteropService.js
|
||||
CliClient/tests/services_PluginService.js
|
||||
CliClient/tests/services_rest_Api.js
|
||||
CliClient/tests/services/plugins/api/JoplinSetting.js
|
||||
CliClient/tests/services/plugins/sandboxProxy.js
|
||||
CliClient/tests/synchronizer_LockHandler.js
|
||||
CliClient/tests/synchronizer_MigrationHandler.js
|
||||
ElectronClient/app.js
|
||||
ElectronClient/bridge.js
|
||||
ElectronClient/commands/copyDevCommand.js
|
||||
ElectronClient/commands/focusElement.js
|
||||
ElectronClient/commands/startExternalEditing.js
|
||||
ElectronClient/commands/stopExternalEditing.js
|
||||
ElectronClient/commands/toggleExternalEditing.js
|
||||
ElectronClient/ElectronAppWrapper.js
|
||||
ElectronClient/global.d.js
|
||||
ElectronClient/gui/Button/Button.js
|
||||
ElectronClient/gui/ConfigScreen/ButtonBar.js
|
||||
ElectronClient/gui/ConfigScreen/ConfigScreen.js
|
||||
ElectronClient/gui/ConfigScreen/SideBar.js
|
||||
ElectronClient/gui/DropboxLoginScreen.js
|
||||
ElectronClient/gui/ErrorBoundary.js
|
||||
ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js
|
||||
ElectronClient/gui/KeymapConfig/ShortcutRecorder.js
|
||||
ElectronClient/gui/KeymapConfig/styles/index.js
|
||||
ElectronClient/gui/KeymapConfig/utils/getLabel.js
|
||||
ElectronClient/gui/KeymapConfig/utils/useCommandStatus.js
|
||||
ElectronClient/gui/KeymapConfig/utils/useKeymap.js
|
||||
ElectronClient/gui/MainScreen/commands/editAlarm.js
|
||||
ElectronClient/gui/MainScreen/commands/exportPdf.js
|
||||
ElectronClient/gui/MainScreen/commands/hideModalMessage.js
|
||||
ElectronClient/gui/MainScreen/commands/moveToFolder.js
|
||||
ElectronClient/gui/MainScreen/commands/newFolder.js
|
||||
ElectronClient/gui/MainScreen/commands/newNote.js
|
||||
ElectronClient/gui/MainScreen/commands/newTodo.js
|
||||
ElectronClient/gui/MainScreen/commands/print.js
|
||||
ElectronClient/gui/MainScreen/commands/renameFolder.js
|
||||
ElectronClient/gui/MainScreen/commands/renameTag.js
|
||||
ElectronClient/gui/MainScreen/commands/search.js
|
||||
ElectronClient/gui/MainScreen/commands/selectTemplate.js
|
||||
ElectronClient/gui/MainScreen/commands/setTags.js
|
||||
ElectronClient/gui/MainScreen/commands/showModalMessage.js
|
||||
ElectronClient/gui/MainScreen/commands/showNoteContentProperties.js
|
||||
ElectronClient/gui/MainScreen/commands/showNoteProperties.js
|
||||
ElectronClient/gui/MainScreen/commands/showShareNoteDialog.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleEditors.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleNoteList.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleSideBar.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleVisiblePanes.js
|
||||
ElectronClient/gui/MainScreen/MainScreen.js
|
||||
ElectronClient/gui/MenuBar.js
|
||||
ElectronClient/gui/MultiNoteActions.js
|
||||
ElectronClient/gui/NoteContentPropertiesDialog.js
|
||||
ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js
|
||||
ElectronClient/gui/NoteEditor/commands/focusElementNoteBody.js
|
||||
ElectronClient/gui/NoteEditor/commands/focusElementNoteTitle.js
|
||||
ElectronClient/gui/NoteEditor/commands/showLocalSearch.js
|
||||
ElectronClient/gui/NoteEditor/commands/showRevisions.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/Editor.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/Toolbar.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinMode.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useKeymap.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useLineSorting.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollUtils.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
ElectronClient/gui/NoteEditor/NoteEditor.js
|
||||
ElectronClient/gui/NoteEditor/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/utils/contextMenu.js
|
||||
ElectronClient/gui/NoteEditor/utils/index.js
|
||||
ElectronClient/gui/NoteEditor/utils/resourceHandling.js
|
||||
ElectronClient/gui/NoteEditor/utils/types.js
|
||||
ElectronClient/gui/NoteEditor/utils/useDropHandler.js
|
||||
ElectronClient/gui/NoteEditor/utils/useFolder.js
|
||||
ElectronClient/gui/NoteEditor/utils/useFormNote.js
|
||||
ElectronClient/gui/NoteEditor/utils/useMarkupToHtml.js
|
||||
ElectronClient/gui/NoteEditor/utils/useMessageHandler.js
|
||||
ElectronClient/gui/NoteEditor/utils/useNoteSearchBar.js
|
||||
ElectronClient/gui/NoteEditor/utils/usePluginServiceRegistration.js
|
||||
ElectronClient/gui/NoteEditor/utils/useSearchMarkers.js
|
||||
ElectronClient/gui/NoteEditor/utils/useWindowCommandHandler.js
|
||||
ElectronClient/gui/NoteList/commands/focusElementNoteList.js
|
||||
ElectronClient/gui/NoteList/NoteList.js
|
||||
ElectronClient/gui/NoteListControls/commands/focusSearch.js
|
||||
ElectronClient/gui/NoteListControls/NoteListControls.js
|
||||
ElectronClient/gui/NoteListItem.js
|
||||
ElectronClient/gui/NoteTextViewer.js
|
||||
ElectronClient/gui/NoteToolbar/NoteToolbar.js
|
||||
ElectronClient/gui/OneDriveLoginScreen.js
|
||||
ElectronClient/gui/ResizableLayout/hooks/useLayoutItemSizes.js
|
||||
ElectronClient/gui/ResizableLayout/hooks/useWindowResizeEvent.js
|
||||
ElectronClient/gui/ResizableLayout/ResizableLayout.js
|
||||
ElectronClient/gui/ResourceScreen.js
|
||||
ElectronClient/gui/Root_UpgradeSyncTarget.js
|
||||
ElectronClient/gui/Root.js
|
||||
ElectronClient/gui/SearchBar/hooks/useSearch.js
|
||||
ElectronClient/gui/SearchBar/SearchBar.js
|
||||
ElectronClient/gui/SearchBar/styles/index.js
|
||||
ElectronClient/gui/ShareNoteDialog.js
|
||||
ElectronClient/gui/SideBar/commands/focusElementSideBar.js
|
||||
ElectronClient/gui/SideBar/SideBar.js
|
||||
ElectronClient/gui/SideBar/styles/index.js
|
||||
ElectronClient/gui/StatusScreen/StatusScreen.js
|
||||
ElectronClient/gui/style/StyledInput.js
|
||||
ElectronClient/gui/style/StyledTextInput.js
|
||||
ElectronClient/gui/ToggleEditorsButton/styles/index.js
|
||||
ElectronClient/gui/ToggleEditorsButton/ToggleEditorsButton.js
|
||||
ElectronClient/gui/ToolbarBase.js
|
||||
ElectronClient/gui/ToolbarButton/styles/index.js
|
||||
ElectronClient/gui/ToolbarButton/ToolbarButton.js
|
||||
ElectronClient/gui/utils/NoteListUtils.js
|
||||
ElectronClient/InteropServiceHelper.js
|
||||
ElectronClient/plugins/GotoAnything.js
|
||||
ElectronClient/services/bridge.js
|
||||
ElectronClient/services/commands/types.js
|
||||
ElectronClient/services/plugins/hooks/useThemeCss.js
|
||||
ElectronClient/services/plugins/hooks/useViewIsReady.js
|
||||
ElectronClient/services/plugins/PlatformImplementation.js
|
||||
ElectronClient/services/plugins/PluginRunner.js
|
||||
ElectronClient/services/plugins/UserWebview.js
|
||||
ElectronClient/services/plugins/UserWebviewDialog.js
|
||||
ElectronClient/services/plugins/UserWebviewDialogButtonBar.js
|
||||
ReactNativeClient/lib/AsyncActionQueue.js
|
||||
ReactNativeClient/lib/BaseApplication.js
|
||||
ReactNativeClient/lib/checkPermissions.js
|
||||
ReactNativeClient/lib/commands/historyBackward.js
|
||||
ReactNativeClient/lib/commands/historyForward.js
|
||||
ReactNativeClient/lib/commands/synchronize.js
|
||||
ReactNativeClient/lib/components/BackButtonDialogBox.js
|
||||
ReactNativeClient/lib/components/CameraView.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnMessage.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnResourceLongPress.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useSource.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/NoteBodyViewer.js
|
||||
ReactNativeClient/lib/components/screens/Note.js
|
||||
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
|
||||
ReactNativeClient/lib/components/SelectDateTimeDialog.js
|
||||
ReactNativeClient/lib/errorUtils.js
|
||||
ReactNativeClient/lib/eventManager.js
|
||||
ReactNativeClient/lib/hooks/useEffectDebugger.js
|
||||
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
|
||||
ReactNativeClient/lib/hooks/usePrevious.js
|
||||
ReactNativeClient/lib/hooks/usePropsDebugger.js
|
||||
ReactNativeClient/lib/InMemoryCache.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/checkbox.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js
|
||||
# Ignore files generated from TypeScript files
|
||||
ElectronClient/app/gui/ShareNoteDialog.js
|
||||
ReactNativeClient/lib/JoplinServerApi.js
|
||||
ReactNativeClient/lib/locale.js
|
||||
ReactNativeClient/lib/Logger.js
|
||||
ReactNativeClient/lib/markdownUtils.js
|
||||
ReactNativeClient/lib/models/Alarm.js
|
||||
ReactNativeClient/lib/models/Setting.js
|
||||
ReactNativeClient/lib/ntpDate.js
|
||||
ReactNativeClient/lib/PoorManIntervals.js
|
||||
ReactNativeClient/lib/reducer.js
|
||||
ReactNativeClient/lib/services/AlarmService.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriver.android.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriver.ios.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriverNode.js
|
||||
ReactNativeClient/lib/services/BaseService.js
|
||||
ReactNativeClient/lib/services/commands/commandsToMarkdownTable.js
|
||||
ReactNativeClient/lib/services/commands/MenuUtils.js
|
||||
ReactNativeClient/lib/services/commands/propsHaveChanged.js
|
||||
ReactNativeClient/lib/services/commands/stateToWhenClauseContext.js
|
||||
ReactNativeClient/lib/services/commands/ToolbarButtonUtils.js
|
||||
ReactNativeClient/lib/services/CommandService.js
|
||||
ReactNativeClient/lib/services/contextkey/contextkey.js
|
||||
ReactNativeClient/lib/services/debug/populateDatabase.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Base.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Custom.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Html.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Jex.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Md.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Raw.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Base.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Custom.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_EnexToHtml.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_EnexToMd.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Jex.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Md.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Raw.js
|
||||
ReactNativeClient/lib/services/interop/InteropService.js
|
||||
ReactNativeClient/lib/services/interop/types.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainService.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.dummy.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.mobile.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.node.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriverBase.js
|
||||
ReactNativeClient/lib/services/KeymapService.js
|
||||
ReactNativeClient/lib/services/plugins/api/Global.js
|
||||
ReactNativeClient/lib/services/plugins/api/Joplin.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinCommands.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinData.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinFilters.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinInterop.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinPlugins.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinSettings.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViews.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsDialogs.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenuItems.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenus.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsPanels.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsToolbarButtons.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinWorkspace.js
|
||||
ReactNativeClient/lib/services/plugins/api/types.js
|
||||
ReactNativeClient/lib/services/plugins/BasePluginRunner.js
|
||||
ReactNativeClient/lib/services/plugins/MenuController.js
|
||||
ReactNativeClient/lib/services/plugins/MenuItemController.js
|
||||
ReactNativeClient/lib/services/plugins/Plugin.js
|
||||
ReactNativeClient/lib/services/plugins/PluginService.js
|
||||
ReactNativeClient/lib/services/plugins/reducer.js
|
||||
ReactNativeClient/lib/services/plugins/sandboxProxy.js
|
||||
ReactNativeClient/lib/services/plugins/ToolbarButtonController.js
|
||||
ReactNativeClient/lib/services/plugins/utils/createViewHandle.js
|
||||
ReactNativeClient/lib/services/plugins/utils/executeSandboxCall.js
|
||||
ReactNativeClient/lib/services/plugins/utils/manifestFromObject.js
|
||||
ReactNativeClient/lib/services/plugins/utils/mapEventHandlersToIds.js
|
||||
ReactNativeClient/lib/services/plugins/utils/types.js
|
||||
ReactNativeClient/lib/services/plugins/ViewController.js
|
||||
ReactNativeClient/lib/services/plugins/WebviewController.js
|
||||
ReactNativeClient/lib/services/ResourceEditWatcher/index.js
|
||||
ReactNativeClient/lib/services/ResourceEditWatcher/reducer.js
|
||||
ReactNativeClient/lib/services/rest/actionApi.desktop.js
|
||||
ReactNativeClient/lib/services/rest/Api.js
|
||||
ReactNativeClient/lib/services/rest/errors.js
|
||||
ReactNativeClient/lib/services/searchengine/filterParser.js
|
||||
ReactNativeClient/lib/services/searchengine/queryBuilder.js
|
||||
ReactNativeClient/lib/services/SettingUtils.js
|
||||
ReactNativeClient/lib/services/synchronizer/gui/useSyncTargetUpgrade.js
|
||||
ReactNativeClient/lib/services/synchronizer/LockHandler.js
|
||||
ReactNativeClient/lib/services/synchronizer/MigrationHandler.js
|
||||
ReactNativeClient/lib/services/synchronizer/migrations/1.js
|
||||
ReactNativeClient/lib/services/synchronizer/migrations/2.js
|
||||
ReactNativeClient/lib/services/synchronizer/utils/types.js
|
||||
ReactNativeClient/lib/services/UndoRedoService.js
|
||||
ReactNativeClient/lib/services/WhenClause.js
|
||||
ReactNativeClient/lib/ShareExtension.js
|
||||
ReactNativeClient/lib/shareHandler.js
|
||||
ReactNativeClient/lib/shim.js
|
||||
ReactNativeClient/lib/Synchronizer.js
|
||||
ReactNativeClient/lib/theme.js
|
||||
ReactNativeClient/lib/themes/aritimDark.js
|
||||
ReactNativeClient/lib/themes/dark.js
|
||||
ReactNativeClient/lib/themes/dracula.js
|
||||
ReactNativeClient/lib/themes/light.js
|
||||
ReactNativeClient/lib/themes/nord.js
|
||||
ReactNativeClient/lib/themes/oledDark.js
|
||||
ReactNativeClient/lib/themes/solarizedDark.js
|
||||
ReactNativeClient/lib/themes/solarizedLight.js
|
||||
ReactNativeClient/lib/themes/type.js
|
||||
ReactNativeClient/lib/uuid.js
|
||||
ReactNativeClient/lib/versionInfo.js
|
||||
ReactNativeClient/PluginAssetsLoader.js
|
||||
ReactNativeClient/setUpQuickActions.js
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
|
277
.ignore
@@ -1,277 +0,0 @@
|
||||
# This is used by VSCode to ignore patterns during search.
|
||||
# Before they were in joplin.code-workspace, under the `files.exclude` key
|
||||
# but it eventually reached the limit with ENAMETOOLONG error.
|
||||
#
|
||||
# https://github.com/microsoft/vscode/issues/94718
|
||||
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
CliClient/app/LinkSelector.js
|
||||
CliClient/app/services/plugins/PluginRunner.js
|
||||
CliClient/tests/InMemoryCache.js
|
||||
CliClient/tests/models_Setting.js
|
||||
CliClient/tests/services_CommandService.js
|
||||
CliClient/tests/services_InteropService.js
|
||||
CliClient/tests/services_PluginService.js
|
||||
CliClient/tests/services_rest_Api.js
|
||||
CliClient/tests/services/plugins/api/JoplinSetting.js
|
||||
CliClient/tests/services/plugins/sandboxProxy.js
|
||||
CliClient/tests/synchronizer_LockHandler.js
|
||||
CliClient/tests/synchronizer_MigrationHandler.js
|
||||
ElectronClient/app.js
|
||||
ElectronClient/bridge.js
|
||||
ElectronClient/commands/copyDevCommand.js
|
||||
ElectronClient/commands/focusElement.js
|
||||
ElectronClient/commands/startExternalEditing.js
|
||||
ElectronClient/commands/stopExternalEditing.js
|
||||
ElectronClient/commands/toggleExternalEditing.js
|
||||
ElectronClient/ElectronAppWrapper.js
|
||||
ElectronClient/global.d.js
|
||||
ElectronClient/gui/Button/Button.js
|
||||
ElectronClient/gui/ConfigScreen/ButtonBar.js
|
||||
ElectronClient/gui/ConfigScreen/ConfigScreen.js
|
||||
ElectronClient/gui/ConfigScreen/SideBar.js
|
||||
ElectronClient/gui/DropboxLoginScreen.js
|
||||
ElectronClient/gui/ErrorBoundary.js
|
||||
ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js
|
||||
ElectronClient/gui/KeymapConfig/ShortcutRecorder.js
|
||||
ElectronClient/gui/KeymapConfig/styles/index.js
|
||||
ElectronClient/gui/KeymapConfig/utils/getLabel.js
|
||||
ElectronClient/gui/KeymapConfig/utils/useCommandStatus.js
|
||||
ElectronClient/gui/KeymapConfig/utils/useKeymap.js
|
||||
ElectronClient/gui/MainScreen/commands/editAlarm.js
|
||||
ElectronClient/gui/MainScreen/commands/exportPdf.js
|
||||
ElectronClient/gui/MainScreen/commands/hideModalMessage.js
|
||||
ElectronClient/gui/MainScreen/commands/moveToFolder.js
|
||||
ElectronClient/gui/MainScreen/commands/newFolder.js
|
||||
ElectronClient/gui/MainScreen/commands/newNote.js
|
||||
ElectronClient/gui/MainScreen/commands/newTodo.js
|
||||
ElectronClient/gui/MainScreen/commands/print.js
|
||||
ElectronClient/gui/MainScreen/commands/renameFolder.js
|
||||
ElectronClient/gui/MainScreen/commands/renameTag.js
|
||||
ElectronClient/gui/MainScreen/commands/search.js
|
||||
ElectronClient/gui/MainScreen/commands/selectTemplate.js
|
||||
ElectronClient/gui/MainScreen/commands/setTags.js
|
||||
ElectronClient/gui/MainScreen/commands/showModalMessage.js
|
||||
ElectronClient/gui/MainScreen/commands/showNoteContentProperties.js
|
||||
ElectronClient/gui/MainScreen/commands/showNoteProperties.js
|
||||
ElectronClient/gui/MainScreen/commands/showShareNoteDialog.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleEditors.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleNoteList.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleSideBar.js
|
||||
ElectronClient/gui/MainScreen/commands/toggleVisiblePanes.js
|
||||
ElectronClient/gui/MainScreen/MainScreen.js
|
||||
ElectronClient/gui/MenuBar.js
|
||||
ElectronClient/gui/MultiNoteActions.js
|
||||
ElectronClient/gui/NoteContentPropertiesDialog.js
|
||||
ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.js
|
||||
ElectronClient/gui/NoteEditor/commands/focusElementNoteBody.js
|
||||
ElectronClient/gui/NoteEditor/commands/focusElementNoteTitle.js
|
||||
ElectronClient/gui/NoteEditor/commands/showLocalSearch.js
|
||||
ElectronClient/gui/NoteEditor/commands/showRevisions.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/Editor.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/Toolbar.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearch.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinMode.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useKeymap.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useLineSorting.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollUtils.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
|
||||
ElectronClient/gui/NoteEditor/NoteBody/TinyMCE/utils/useScroll.js
|
||||
ElectronClient/gui/NoteEditor/NoteEditor.js
|
||||
ElectronClient/gui/NoteEditor/styles/index.js
|
||||
ElectronClient/gui/NoteEditor/utils/contextMenu.js
|
||||
ElectronClient/gui/NoteEditor/utils/index.js
|
||||
ElectronClient/gui/NoteEditor/utils/resourceHandling.js
|
||||
ElectronClient/gui/NoteEditor/utils/types.js
|
||||
ElectronClient/gui/NoteEditor/utils/useDropHandler.js
|
||||
ElectronClient/gui/NoteEditor/utils/useFolder.js
|
||||
ElectronClient/gui/NoteEditor/utils/useFormNote.js
|
||||
ElectronClient/gui/NoteEditor/utils/useMarkupToHtml.js
|
||||
ElectronClient/gui/NoteEditor/utils/useMessageHandler.js
|
||||
ElectronClient/gui/NoteEditor/utils/useNoteSearchBar.js
|
||||
ElectronClient/gui/NoteEditor/utils/usePluginServiceRegistration.js
|
||||
ElectronClient/gui/NoteEditor/utils/useSearchMarkers.js
|
||||
ElectronClient/gui/NoteEditor/utils/useWindowCommandHandler.js
|
||||
ElectronClient/gui/NoteList/commands/focusElementNoteList.js
|
||||
ElectronClient/gui/NoteList/NoteList.js
|
||||
ElectronClient/gui/NoteListControls/commands/focusSearch.js
|
||||
ElectronClient/gui/NoteListControls/NoteListControls.js
|
||||
ElectronClient/gui/NoteListItem.js
|
||||
ElectronClient/gui/NoteTextViewer.js
|
||||
ElectronClient/gui/NoteToolbar/NoteToolbar.js
|
||||
ElectronClient/gui/OneDriveLoginScreen.js
|
||||
ElectronClient/gui/ResizableLayout/hooks/useLayoutItemSizes.js
|
||||
ElectronClient/gui/ResizableLayout/hooks/useWindowResizeEvent.js
|
||||
ElectronClient/gui/ResizableLayout/ResizableLayout.js
|
||||
ElectronClient/gui/ResourceScreen.js
|
||||
ElectronClient/gui/Root_UpgradeSyncTarget.js
|
||||
ElectronClient/gui/Root.js
|
||||
ElectronClient/gui/SearchBar/hooks/useSearch.js
|
||||
ElectronClient/gui/SearchBar/SearchBar.js
|
||||
ElectronClient/gui/SearchBar/styles/index.js
|
||||
ElectronClient/gui/ShareNoteDialog.js
|
||||
ElectronClient/gui/SideBar/commands/focusElementSideBar.js
|
||||
ElectronClient/gui/SideBar/SideBar.js
|
||||
ElectronClient/gui/SideBar/styles/index.js
|
||||
ElectronClient/gui/StatusScreen/StatusScreen.js
|
||||
ElectronClient/gui/style/StyledInput.js
|
||||
ElectronClient/gui/style/StyledTextInput.js
|
||||
ElectronClient/gui/ToggleEditorsButton/styles/index.js
|
||||
ElectronClient/gui/ToggleEditorsButton/ToggleEditorsButton.js
|
||||
ElectronClient/gui/ToolbarBase.js
|
||||
ElectronClient/gui/ToolbarButton/styles/index.js
|
||||
ElectronClient/gui/ToolbarButton/ToolbarButton.js
|
||||
ElectronClient/gui/utils/NoteListUtils.js
|
||||
ElectronClient/InteropServiceHelper.js
|
||||
ElectronClient/plugins/GotoAnything.js
|
||||
ElectronClient/services/bridge.js
|
||||
ElectronClient/services/commands/types.js
|
||||
ElectronClient/services/plugins/hooks/useThemeCss.js
|
||||
ElectronClient/services/plugins/hooks/useViewIsReady.js
|
||||
ElectronClient/services/plugins/PlatformImplementation.js
|
||||
ElectronClient/services/plugins/PluginRunner.js
|
||||
ElectronClient/services/plugins/UserWebview.js
|
||||
ElectronClient/services/plugins/UserWebviewDialog.js
|
||||
ElectronClient/services/plugins/UserWebviewDialogButtonBar.js
|
||||
ReactNativeClient/lib/AsyncActionQueue.js
|
||||
ReactNativeClient/lib/BaseApplication.js
|
||||
ReactNativeClient/lib/checkPermissions.js
|
||||
ReactNativeClient/lib/commands/historyBackward.js
|
||||
ReactNativeClient/lib/commands/historyForward.js
|
||||
ReactNativeClient/lib/commands/synchronize.js
|
||||
ReactNativeClient/lib/components/BackButtonDialogBox.js
|
||||
ReactNativeClient/lib/components/CameraView.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnMessage.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnResourceLongPress.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useSource.js
|
||||
ReactNativeClient/lib/components/NoteBodyViewer/NoteBodyViewer.js
|
||||
ReactNativeClient/lib/components/screens/Note.js
|
||||
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
|
||||
ReactNativeClient/lib/components/SelectDateTimeDialog.js
|
||||
ReactNativeClient/lib/errorUtils.js
|
||||
ReactNativeClient/lib/eventManager.js
|
||||
ReactNativeClient/lib/hooks/useEffectDebugger.js
|
||||
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
|
||||
ReactNativeClient/lib/hooks/usePrevious.js
|
||||
ReactNativeClient/lib/hooks/usePropsDebugger.js
|
||||
ReactNativeClient/lib/InMemoryCache.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/checkbox.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
|
||||
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/sanitize_html.js
|
||||
ReactNativeClient/lib/JoplinServerApi.js
|
||||
ReactNativeClient/lib/locale.js
|
||||
ReactNativeClient/lib/Logger.js
|
||||
ReactNativeClient/lib/markdownUtils.js
|
||||
ReactNativeClient/lib/models/Alarm.js
|
||||
ReactNativeClient/lib/models/Setting.js
|
||||
ReactNativeClient/lib/ntpDate.js
|
||||
ReactNativeClient/lib/PoorManIntervals.js
|
||||
ReactNativeClient/lib/reducer.js
|
||||
ReactNativeClient/lib/services/AlarmService.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriver.android.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriver.ios.js
|
||||
ReactNativeClient/lib/services/AlarmServiceDriverNode.js
|
||||
ReactNativeClient/lib/services/BaseService.js
|
||||
ReactNativeClient/lib/services/commands/commandsToMarkdownTable.js
|
||||
ReactNativeClient/lib/services/commands/MenuUtils.js
|
||||
ReactNativeClient/lib/services/commands/propsHaveChanged.js
|
||||
ReactNativeClient/lib/services/commands/stateToWhenClauseContext.js
|
||||
ReactNativeClient/lib/services/commands/ToolbarButtonUtils.js
|
||||
ReactNativeClient/lib/services/CommandService.js
|
||||
ReactNativeClient/lib/services/contextkey/contextkey.js
|
||||
ReactNativeClient/lib/services/debug/populateDatabase.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Base.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Custom.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Html.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Jex.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Md.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Exporter_Raw.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Base.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Custom.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_EnexToHtml.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_EnexToMd.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Jex.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Md.js
|
||||
ReactNativeClient/lib/services/interop/InteropService_Importer_Raw.js
|
||||
ReactNativeClient/lib/services/interop/InteropService.js
|
||||
ReactNativeClient/lib/services/interop/types.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainService.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.dummy.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.mobile.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriver.node.js
|
||||
ReactNativeClient/lib/services/keychain/KeychainServiceDriverBase.js
|
||||
ReactNativeClient/lib/services/KeymapService.js
|
||||
ReactNativeClient/lib/services/plugins/api/Global.js
|
||||
ReactNativeClient/lib/services/plugins/api/Joplin.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinCommands.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinData.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinFilters.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinInterop.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinPlugins.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinSettings.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViews.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsDialogs.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenuItems.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenus.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsPanels.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinViewsToolbarButtons.js
|
||||
ReactNativeClient/lib/services/plugins/api/JoplinWorkspace.js
|
||||
ReactNativeClient/lib/services/plugins/api/types.js
|
||||
ReactNativeClient/lib/services/plugins/BasePluginRunner.js
|
||||
ReactNativeClient/lib/services/plugins/MenuController.js
|
||||
ReactNativeClient/lib/services/plugins/MenuItemController.js
|
||||
ReactNativeClient/lib/services/plugins/Plugin.js
|
||||
ReactNativeClient/lib/services/plugins/PluginService.js
|
||||
ReactNativeClient/lib/services/plugins/reducer.js
|
||||
ReactNativeClient/lib/services/plugins/sandboxProxy.js
|
||||
ReactNativeClient/lib/services/plugins/ToolbarButtonController.js
|
||||
ReactNativeClient/lib/services/plugins/utils/createViewHandle.js
|
||||
ReactNativeClient/lib/services/plugins/utils/executeSandboxCall.js
|
||||
ReactNativeClient/lib/services/plugins/utils/manifestFromObject.js
|
||||
ReactNativeClient/lib/services/plugins/utils/mapEventHandlersToIds.js
|
||||
ReactNativeClient/lib/services/plugins/utils/types.js
|
||||
ReactNativeClient/lib/services/plugins/ViewController.js
|
||||
ReactNativeClient/lib/services/plugins/WebviewController.js
|
||||
ReactNativeClient/lib/services/ResourceEditWatcher/index.js
|
||||
ReactNativeClient/lib/services/ResourceEditWatcher/reducer.js
|
||||
ReactNativeClient/lib/services/rest/actionApi.desktop.js
|
||||
ReactNativeClient/lib/services/rest/Api.js
|
||||
ReactNativeClient/lib/services/rest/errors.js
|
||||
ReactNativeClient/lib/services/searchengine/filterParser.js
|
||||
ReactNativeClient/lib/services/searchengine/queryBuilder.js
|
||||
ReactNativeClient/lib/services/SettingUtils.js
|
||||
ReactNativeClient/lib/services/synchronizer/gui/useSyncTargetUpgrade.js
|
||||
ReactNativeClient/lib/services/synchronizer/LockHandler.js
|
||||
ReactNativeClient/lib/services/synchronizer/MigrationHandler.js
|
||||
ReactNativeClient/lib/services/synchronizer/migrations/1.js
|
||||
ReactNativeClient/lib/services/synchronizer/migrations/2.js
|
||||
ReactNativeClient/lib/services/synchronizer/utils/types.js
|
||||
ReactNativeClient/lib/services/UndoRedoService.js
|
||||
ReactNativeClient/lib/services/WhenClause.js
|
||||
ReactNativeClient/lib/ShareExtension.js
|
||||
ReactNativeClient/lib/shareHandler.js
|
||||
ReactNativeClient/lib/shim.js
|
||||
ReactNativeClient/lib/Synchronizer.js
|
||||
ReactNativeClient/lib/theme.js
|
||||
ReactNativeClient/lib/themes/aritimDark.js
|
||||
ReactNativeClient/lib/themes/dark.js
|
||||
ReactNativeClient/lib/themes/dracula.js
|
||||
ReactNativeClient/lib/themes/light.js
|
||||
ReactNativeClient/lib/themes/nord.js
|
||||
ReactNativeClient/lib/themes/oledDark.js
|
||||
ReactNativeClient/lib/themes/solarizedDark.js
|
||||
ReactNativeClient/lib/themes/solarizedLight.js
|
||||
ReactNativeClient/lib/themes/type.js
|
||||
ReactNativeClient/lib/uuid.js
|
||||
ReactNativeClient/lib/versionInfo.js
|
||||
ReactNativeClient/PluginAssetsLoader.js
|
||||
ReactNativeClient/setUpQuickActions.js
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
19
.travis.yml
@@ -9,7 +9,6 @@ rvm: 2.3.3
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- dev
|
||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||
|
||||
matrix:
|
||||
@@ -17,7 +16,7 @@ matrix:
|
||||
- os: osx
|
||||
osx_image: xcode9.0
|
||||
language: node_js
|
||||
node_js: "10"
|
||||
node_js: "8"
|
||||
env:
|
||||
- ELECTRON_CACHE=$HOME/.cache/electron
|
||||
- ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
|
||||
@@ -26,7 +25,7 @@ matrix:
|
||||
sudo: required
|
||||
dist: trusty
|
||||
language: node_js
|
||||
node_js: "10"
|
||||
node_js: "8"
|
||||
env:
|
||||
- ELECTRON_CACHE=$HOME/.cache/electron
|
||||
- ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder
|
||||
@@ -43,8 +42,6 @@ before_install:
|
||||
|
||||
# Silence apt-get update errors (for example when a module doesn't exist) since
|
||||
# otherwise it will make the whole build fails, even though all we need is yarn.
|
||||
|
||||
# libsecret-1-dev is required for keytar - https://github.com/atom/node-keytar
|
||||
- |
|
||||
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install yarn
|
||||
@@ -54,13 +51,16 @@ before_install:
|
||||
sudo apt-get update || true
|
||||
sudo apt-get install -y yarn
|
||||
sudo apt-get install -y gettext
|
||||
sudo apt-get install -y libsecret-1-dev
|
||||
fi
|
||||
|
||||
script:
|
||||
- |
|
||||
# Copy lib
|
||||
rsync -aP --delete ReactNativeClient/lib/ ElectronClient/app/lib/
|
||||
|
||||
# Install tools
|
||||
npm install
|
||||
npm run tsc
|
||||
cd Tools
|
||||
npm install
|
||||
cd ..
|
||||
@@ -70,7 +70,8 @@ script:
|
||||
# and that would break the desktop release.
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
cd CliClient
|
||||
npm run test-ci
|
||||
npm install
|
||||
./run_test.sh
|
||||
testResult=$?
|
||||
if [ $testResult -ne 0 ]; then
|
||||
exit $testResult
|
||||
@@ -112,5 +113,5 @@ script:
|
||||
fi
|
||||
|
||||
# Prepare the Electron app and build it
|
||||
cd ElectronClient
|
||||
USE_HARD_LINKS=false npm run dist
|
||||
cd ElectronClient/app
|
||||
npm install && USE_HARD_LINKS=false yarn dist
|
||||
|
Before Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
@@ -1,109 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="disegno.svg"
|
||||
inkscape:version="1.0rc1 (09960d6, 2020-04-09)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 70 70"
|
||||
height="70"
|
||||
width="70">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="775"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:guide-bbox="true"
|
||||
showguides="true"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:showpageshadow="false"
|
||||
showborder="true"
|
||||
showgrid="false"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="px"
|
||||
inkscape:cy="39.253064"
|
||||
inkscape:cx="25.246811"
|
||||
inkscape:zoom="5.8562241"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
units="px">
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1932"
|
||||
orientation="-1,0"
|
||||
position="12,70" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1934"
|
||||
orientation="-1,0"
|
||||
position="58,70" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1936"
|
||||
orientation="0,1"
|
||||
position="0,58" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1938"
|
||||
orientation="0,1"
|
||||
position="0,12" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide2021"
|
||||
orientation="-1,0"
|
||||
position="35,70" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Livello 1">
|
||||
<path
|
||||
inkscape:transform-center-y="23.027731"
|
||||
inkscape:transform-center-x="-17.510929"
|
||||
id="path30"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.133334;stop-opacity:1"
|
||||
d="M 52.1731,12 H 35.107236 c -0.161294,0 -0.291666,0.130494 -0.291666,0.291543 v 5.419239 c 0,0.182381 0.147678,0.330176 0.330178,0.330176 h 2.339824 c 0.94638,0 1.713811,0.727936 1.795988,1.652976 v 3.715485 2.069989 19.715998 0.139708 h -6.44e-4 c 0.0058,0.206545 -0.0023,0.409658 -0.02244,0.609702 -0.0023,0.02918 -0.0062,0.05801 -0.0097,0.08697 -0.01349,0.116897 -0.02846,0.233161 -0.05114,0.346981 -0.01243,0.06489 -0.02993,0.128044 -0.0455,0.191949 -0.02097,0.08499 -0.0379,0.171342 -0.06401,0.254505 -0.1543,0.493916 -0.39825,0.95202 -0.735666,1.355297 -0.01243,0.01438 -0.02771,0.02761 -0.03998,0.04182 -0.102908,0.119222 -0.210962,0.235367 -0.330548,0.34416 -0.120695,0.109778 -0.248492,0.211819 -0.382795,0.306628 -0.954719,0.676302 -2.23974,0.973854 -3.6755,0.836485 -1.830697,-0.172088 -3.646921,-1.002309 -5.114939,-2.337984 -1.467772,-1.335554 -2.380422,-2.988039 -2.569305,-4.653525 -0.169868,-1.489971 0.276578,-2.801116 1.256197,-3.692426 0.0027,-0.0019 0.005,-0.0037 0.0069,-0.0058 0.0379,-0.03398 0.0796,-0.06379 0.1186,-0.09654 0.701076,-0.58738 1.614951,-0.943313 2.657858,-1.041435 0.01172,-0.0011 0.02306,-0.003 0.03423,-0.0039 0.109777,-0.0097 0.221631,-0.01402 0.334471,-0.01827 0.05899,-0.0019 0.117251,-0.0062 0.177111,-0.0065 0.01986,-2.76e-4 0.03875,-0.0023 0.05864,-0.0023 0.03557,0 0.07248,0.0046 0.108055,0.0051 0.164347,0.0027 0.329933,0.0094 0.498825,0.02379 0.02134,0.0017 0.0417,9.78e-4 0.06365,0.003 0.01562,0.0016 0.03103,0.005 0.04662,0.0065 0.956682,0.09592 1.90392,0.381568 2.802834,0.814406 0.01876,8.39e-4 0.04047,0.0065 0.06759,0.02159 0.274004,0.151353 0.326498,-0.01101 0.334593,-0.118351 v -4.688237 -3.46883 c 0,-0.233653 -0.162519,-0.440321 -0.3904,-0.490484 -4.841795,-1.065597 -9.592336,0.04355 -12.944402,3.09499 -2.928307,2.663747 -4.344811,6.507647 -3.885849,10.545461 0.409535,3.596512 2.255685,7.05173 5.198956,9.730318 2.868698,2.609903 6.521262,4.242028 10.288996,4.596993 0.519184,0.04805 1.040822,0.07283 1.549826,0.07283 3.598351,0 6.937296,-1.233851 9.401735,-3.475688 2.33455,-2.125552 3.732902,-5.044294 3.938097,-8.219619 l 0.01901,-20.825138 h 0.0021 V 19.91155 h 7.7e-4 v -0.09714 c 0.02109,-0.982682 0.822378,-1.773296 1.81046,-1.773296 h 2.339824 c 0.182259,0 0.330177,-0.147802 0.330177,-0.330177 v -5.419299 c -2.1e-5,-0.161046 -0.130406,-0.291543 -0.291686,-0.291543"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
<inkscape:templateinfo>
|
||||
<inkscape:name>SmallTile</inkscape:name>
|
||||
<inkscape:shortdesc>Small tile</inkscape:shortdesc>
|
||||
<inkscape:date>2020-04-15</inkscape:date>
|
||||
</inkscape:templateinfo>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.4 KiB |
@@ -1,109 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
sodipodi:docname="disegno-1.svg"
|
||||
inkscape:version="1.0rc1 (09960d6, 2020-04-09)"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 150 150"
|
||||
height="150"
|
||||
width="150">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="775"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:guide-bbox="true"
|
||||
showguides="true"
|
||||
inkscape:pagecheckerboard="true"
|
||||
inkscape:showpageshadow="false"
|
||||
showborder="true"
|
||||
showgrid="false"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-units="px"
|
||||
inkscape:cy="79.075594"
|
||||
inkscape:cx="91.835957"
|
||||
inkscape:zoom="3.1892627"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
borderopacity="1.0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
id="base"
|
||||
units="px">
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1919"
|
||||
orientation="0,1"
|
||||
position="0,115" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1921"
|
||||
orientation="-1,0"
|
||||
position="25,150" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1923"
|
||||
orientation="-1,0"
|
||||
position="125,150" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide1925"
|
||||
orientation="0,1"
|
||||
position="0,35" />
|
||||
<sodipodi:guide
|
||||
inkscape:color="rgb(0,0,255)"
|
||||
inkscape:locked="false"
|
||||
inkscape:label=""
|
||||
id="guide2879"
|
||||
orientation="-1,0"
|
||||
position="75,150" />
|
||||
</sodipodi:namedview>
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
id="layer1"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="Livello 1">
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 105.30102,35.000001 H 75.621261 c -0.280511,0 -0.507245,0.226946 -0.507245,0.507031 v 9.424762 c 0,0.317185 0.256831,0.574219 0.574223,0.574219 h 4.069258 c 1.645878,0 2.980541,1.265976 3.123457,2.874741 v 6.461712 3.599981 34.288687 0.24297 h -0.0011 c 0.01009,0.359209 -0.004,0.712449 -0.03903,1.060352 -0.004,0.05075 -0.01078,0.100887 -0.01687,0.151252 -0.02346,0.203299 -0.0495,0.405497 -0.08894,0.603445 -0.02162,0.112852 -0.05205,0.222685 -0.07913,0.333824 -0.03647,0.147809 -0.06591,0.297986 -0.111322,0.442618 -0.268348,0.858984 -0.692608,1.655686 -1.279419,2.357038 -0.02162,0.02501 -0.04819,0.04802 -0.06953,0.07273 -0.178971,0.207343 -0.366891,0.409334 -0.574866,0.598539 -0.209904,0.190918 -0.43216,0.368381 -0.66573,0.533266 -1.660381,1.176182 -3.8952,1.693662 -6.392174,1.454752 -3.18382,-0.29928 -6.34247,-1.743142 -8.895544,-4.066054 -2.552647,-2.322703 -4.139864,-5.196589 -4.468356,-8.093086 -0.295423,-2.591254 0.481005,-4.871506 2.18469,-6.42161 0.0047,-0.0033 0.0087,-0.0064 0.012,-0.01009 0.06591,-0.05909 0.138435,-0.110939 0.206261,-0.167895 1.219262,-1.021531 2.80861,-1.640544 4.622361,-1.811191 0.02038,-0.0019 0.0401,-0.0052 0.05953,-0.0068 0.190917,-0.01687 0.385445,-0.02438 0.581689,-0.03177 0.102591,-0.0033 0.203915,-0.01078 0.308019,-0.0113 0.03454,-4.8e-4 0.06739,-0.004 0.101982,-0.004 0.06186,0 0.126053,0.008 0.187922,0.0089 0.285821,0.0047 0.573797,0.01635 0.867522,0.04137 0.03711,0.003 0.07252,0.0017 0.110695,0.0052 0.02717,0.0028 0.05397,0.0087 0.08108,0.0113 1.663794,0.166817 3.311164,0.663596 4.874493,1.416358 0.03263,0.0015 0.07038,0.0113 0.117548,0.03755 0.476528,0.263222 0.567822,-0.01915 0.581901,-0.205828 V 73.11952 67.086773 c 0,-0.406353 -0.282642,-0.765776 -0.678957,-0.853016 -8.420512,-1.853212 -16.682323,0.07574 -22.512002,5.382591 -5.092707,4.632602 -7.556192,11.317645 -6.757997,18.339929 0.712234,6.254803 3.92293,12.263883 9.041661,16.922293 4.989039,4.53896 11.341325,7.37744 17.893905,7.99477 0.902929,0.0836 1.810125,0.12666 2.69535,0.12666 6.258001,0 12.064861,-2.14583 16.350841,-6.04467 4.060086,-3.69661 6.492006,-8.77269 6.848866,-14.294994 l 0.0331,-36.217627 h 0.004 v -9.683497 h 10e-4 v -0.16894 c 0.0367,-1.709012 1.43023,-3.083992 3.148627,-3.083992 h 4.06926 c 0.31697,0 0.57422,-0.257047 0.57422,-0.574221 v -9.424867 c -4e-5,-0.28008 -0.22679,-0.507031 -0.50728,-0.507031"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.133334;stop-opacity:1"
|
||||
id="path30"
|
||||
inkscape:transform-center-x="-30.453831"
|
||||
inkscape:transform-center-y="40.048222" />
|
||||
</g>
|
||||
<inkscape:templateinfo>
|
||||
<inkscape:name>Square150x150Logo</inkscape:name>
|
||||
<inkscape:shortdesc>Medium tile</inkscape:shortdesc>
|
||||
<inkscape:date>2020-04-15</inkscape:date>
|
||||
</inkscape:templateinfo>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 820 B After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
166
BUILD.md
@@ -1,99 +1,117 @@
|
||||
[](https://travis-ci.org/laurent22/joplin) [](https://ci.appveyor.com/project/laurent22/joplin)
|
||||
|
||||
# Building the applications
|
||||
# General information
|
||||
|
||||
Note that all the applications share the same library, which, for historical reasons, is in `ReactNativeClient/lib`. This library is copied to the relevant directories when building each app.
|
||||
- All the applications share the same library, which, for historical reasons, is in ReactNativeClient/lib. This library is copied to the relevant directories when building each app.
|
||||
- In general, most of the backend (anything to do with the database, synchronisation, data import or export, etc.) is shared across all the apps, so when making a change please consider how it will affect all the apps.
|
||||
|
||||
## Required dependencies
|
||||
# TypeScript
|
||||
|
||||
Most of the application is written in JavaScript, however new classes and files should generally be written in [TypeScript](https://www.typescriptlang.org/). Even if you don't write TypeScript code, you will need to build the existing .ts and .tsx files. This is done from the root of the project, by running `npm run tsc`.
|
||||
|
||||
If you are modifying TypeScript code, the best is to have the compiler watch for changes from a terminal. To do so, run `npm run tsc-watch`.
|
||||
|
||||
All TypeScript files are generated next to the .ts or .tsx file. So for example, if there's a file "lib/MyClass.ts", there will be a generated "lib/MyClass.js" next to it. If you create a new TypeScript file, make sure you add the generated .js file to .gitignore. It is implemented that way as it requires minimal changes to integrate TypeScript in the existing JavaScript code base.
|
||||
|
||||
## macOS dependencies
|
||||
|
||||
brew install yarn node
|
||||
echo 'export PATH="/usr/local/opt/gettext/bin:$PATH"' >> ~/.bash_profile
|
||||
source ~/.bash_profile
|
||||
|
||||
## Linux and Windows (WSL) dependencies
|
||||
|
||||
- Install yarn - https://yarnpkg.com/lang/en/docs/install/
|
||||
- Install node 10+ - https://nodejs.org/en/
|
||||
- macOS, Linux: Install rsync - https://nodejs.org/en/
|
||||
- macOS: Install Cocoapods - `brew install cocoapods`
|
||||
- Windows: Install Windows Build Tools - `npm install -g windows-build-tools`
|
||||
- Linux: Install dependencies - `sudo apt install libnss3 libsecret-1-dev`
|
||||
- Install node v10.x (check with `node --version`) - https://nodejs.org/en/
|
||||
- If you get a node-gyp related error you might need to manually install it: `npm install -g node-gyp`
|
||||
|
||||
## Building
|
||||
# Building the tools
|
||||
|
||||
Before doing anything else, from the root of the project, run:
|
||||
Before building any of the applications, you need to build the tools and pre-commit hooks:
|
||||
|
||||
npm install
|
||||
```
|
||||
npm install && cd Tools && npm install && cd ..
|
||||
```
|
||||
|
||||
Then you can test the various applications:
|
||||
# Building the Electron application
|
||||
|
||||
## Testing the desktop application
|
||||
## Linux and macOS
|
||||
|
||||
cd ElectronClient
|
||||
npm start
|
||||
```
|
||||
npm run copyLib
|
||||
npm run tsc
|
||||
cd ElectronClient/app
|
||||
npm install
|
||||
yarn dist
|
||||
```
|
||||
|
||||
You can also run it under WSL 2. To do so, [follow these instructions](https://www.beekeeperstudio.io/blog/building-electron-windows-ubuntu-wsl2) to setup your environment.
|
||||
If there's an error `while loading shared libraries: libgconf-2.so.4: cannot open shared object file: No such file or directory`, run `sudo apt-get install libgconf-2-4`
|
||||
|
||||
## Testing the Terminal application
|
||||
If you get a node-gyp related error you might need to manually install it: `npm install -g node-gyp`.
|
||||
|
||||
cd CliClient
|
||||
npm start
|
||||
If you get the error `libtool: unrecognized option '-static'`, follow the instructions [in this post](https://stackoverflow.com/a/38552393/561309) to use the correct libtool version.
|
||||
|
||||
## Testing the Mobile application
|
||||
That will create the executable file in the `dist` directory.
|
||||
|
||||
From `/ElectronClient` you can also run `run.sh` to run the app for testing.
|
||||
|
||||
## Windows
|
||||
|
||||
Run the following commands on Windows Command prompt running as Administrator:
|
||||
|
||||
```
|
||||
xcopy /C /I /H /R /Y /S ReactNativeClient\lib ElectronClient\app\lib
|
||||
npm run tsc
|
||||
cd ElectronClient\app
|
||||
npm install
|
||||
yarn dist
|
||||
```
|
||||
|
||||
If node-gyp does not works (MSBUILD: error MSB3428: Could not load the Visual C++ component "VCBuild.exe"), you might need to install the `windows-build-tools` using `npm install --global windows-build-tools`.
|
||||
|
||||
If `yarn dist` fails, it may need administrative rights.
|
||||
|
||||
If you get an `error MSB8020: The build tools for v140 cannot be found.` try to run with a different toolset version, eg `npm install --toolset=v141` (See [here](https://github.com/mapbox/node-sqlite3/issues/1124) for more info).
|
||||
|
||||
The [building\_win32\_tips on this page](./readme/building_win32_tips.md) might be helpful.
|
||||
|
||||
## Troubleshooting desktop application
|
||||
|
||||
> The application window doesn't open or is white
|
||||
|
||||
This is an indication that there's an early initialisation error. Try this:
|
||||
|
||||
- In ElectronAppWrapper, set `debugEarlyBugs` to `true`. This will force the window to show up and should open the console next to it, which should display any error.
|
||||
- In more rare cases, an already open instance of Joplin can create strange low-level bugs that will display no error but will result in this white window. A non-dev instance of Joplin, or a dev instance that wasn't properly closed might cause this. So make sure you close everything and try again. Perhaps even other Electron apps running (Skype, Slack, etc.) could cause this?
|
||||
- Also try to delete node_modules and rebuild.
|
||||
- If all else fail, switch your computer off and on again, to make sure you start clean.
|
||||
|
||||
> How to work on the app from Windows?
|
||||
|
||||
You should not use WSL at all because this is a GUI app that lives outside of WSL, and the WSL layer can cause all kind of very hard to debug issues. It can also lock files in node_modules that cannot be unlocked when the app crashes (you need to restart your computer). Likewise, don't run the TypeScript watch command from WSL.
|
||||
|
||||
So everything should be done from a Windows Command prompt running as Administrator. You can use `run.bat` to run the app in dev mode.
|
||||
|
||||
# Building the Mobile application
|
||||
|
||||
First you need to setup React Native to build projects with native code. For this, follow the instructions on the [Get Started](https://facebook.github.io/react-native/docs/getting-started.html) tutorial, in the "React Native CLI Quickstart" tab.
|
||||
|
||||
Then:
|
||||
|
||||
cd ReactNativeClient
|
||||
npm run start-android
|
||||
# Or: npm run start-ios
|
||||
|
||||
To run the iOS application, it might be easier to open the file `ios/Joplin.xcworkspace` on XCode and run the app from there.
|
||||
|
||||
Normally the bundler should start automatically with the application. If it doesn't, run `npm start`.
|
||||
|
||||
## Building the clipper
|
||||
|
||||
cd Clipper/popup
|
||||
npm install
|
||||
npm run watch # To watch for changes
|
||||
|
||||
To test the extension please refer to the relevant pages for each browser: [Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension#Trying_it_out) / [Chrome](https://developer.chrome.com/extensions/faq#faq-dev-01). Please note that the extension in dev mode will only connect to a dev instance of the desktop app (and vice-versa).
|
||||
|
||||
## Watching files
|
||||
|
||||
To make changes to the application, you'll need to rebuild any TypeScript file you've changed, and rebuild the lib. The simplest way to do all this is to watch for changes from the root of the project. Simply run this command, and it should take care of the rest:
|
||||
|
||||
npm run watch
|
||||
|
||||
Running `npm run build` would have the same effect, but without watching.
|
||||
|
||||
## Running an application with additional parameters
|
||||
|
||||
You can specify additional parameters when running the desktop or CLI application. To do so, add `--` to the `npm start` command, followed by your flags. For example:
|
||||
|
||||
npm start -- --profile ~/MyTestProfile
|
||||
|
||||
## TypeScript
|
||||
|
||||
Most of the application is written in JavaScript, however new classes and files should generally be written in [TypeScript](https://www.typescriptlang.org/). All TypeScript files are generated next to the .ts or .tsx file. So for example, if there's a file "lib/MyClass.ts", there will be a generated "lib/MyClass.js" next to it. It is implemented that way as it requires minimal changes to integrate TypeScript in the existing JavaScript code base.
|
||||
|
||||
In the current setup, `tsc` is executed from the root of the project, and will compile everything in CliClient, ElectronClient, etc. This is more convenient to have just one place to compile everything, and it also means there's only one watch command to run. However, one drawback is that TypeScript doesn't find types defined in node_modules folders in sub-directories. For example, if you install `immer` in ElectronClient, then try to use the package, TypeScript will report that it cannot find this module. In theory using `typeRoots`, it should be possible to make it find the right modules but it doesn't seem to work in this case. Currently the workaround is to install any such package at the root of the project. By doing so, TypeScript will find the type definitions and compilation will work. It's not ideal since the module is installed at the root even though it's not used, but for now that will work.
|
||||
|
||||
## Hot reload
|
||||
|
||||
If you'd like to auto-reload the desktop app on changes rather than having to quit and restart it manually each time, you can use [watchman-make](https://facebook.github.io/watchman/docs/watchman-make.html):
|
||||
|
||||
```sh
|
||||
cd ElectronClient
|
||||
watchman-make -p '**/*.js' '**/*.jsx' --run "npm start"
|
||||
```
|
||||
npm run tsc
|
||||
cd ReactNativeClient
|
||||
npm install
|
||||
react-native run-ios
|
||||
# Or: react-native run-android
|
||||
```
|
||||
|
||||
It still requires you to quit the application each time you want it to rebuild, but at least you don't have to re-run `"npm start"` each time. Here's what the workflow loop looks like in practice:
|
||||
# Building the Terminal application
|
||||
|
||||
1. Edit and save files in your text editor.
|
||||
2. Switch to the Electron app and <kbd>cmd</kbd>+<kbd>Q</kbd> to quit it.
|
||||
3. `watchman` immediately restarts the app for you (whereas usually you'd have to switch back to the terminal, type `"npm start"`, and hit enter).
|
||||
```
|
||||
cd CliClient
|
||||
npm install
|
||||
./build.sh
|
||||
```
|
||||
|
||||
# Updating Markdown renderer packages
|
||||
|
||||
The Markdown renderer is located under ReactNativeClient/lib/joplin-renderer. Whenever updating one of its dependencies, such as Mermaid or Katex, please run `npm run buildAssets` to make sure all assets such as fonts or CSS files are deployed correctly.
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
Please read for the [Build Troubleshooting Document](https://github.com/laurent22/joplin/blob/dev/readme/build_troubleshooting.md) for various tips on how to get the build working.
|
||||
Run `run.sh` to start the application for testing.
|
||||
|
@@ -21,13 +21,15 @@ Please check that your request has not already been posted on the forum or the [
|
||||
|
||||
Avoid listing multiple requests in one topic. One topic per request makes it easier to track and discuss it.
|
||||
|
||||
Finally, when submitting a pull request, don't forget to [test your code](#automated-tests).
|
||||
Finally, when submitting a pull request, don't forget to [test your code](#unit-tests).
|
||||
|
||||
# Contributing to Joplin's translation
|
||||
# Contribute to the project
|
||||
|
||||
## Contributing to Joplin's translation
|
||||
|
||||
Joplin is available in multiple languages thanks to the help of its users. You can help translate Joplin to your language or keep it up to date. Please read the documentation about [Localisation](https://joplinapp.org/#localisation).
|
||||
|
||||
# Contributing to Joplin's code
|
||||
## Contributing to Joplin's code
|
||||
|
||||
If you want to start contributing to the project's code, please follow these guidelines before creating a pull request:
|
||||
|
||||
@@ -35,58 +37,43 @@ If you want to start contributing to the project's code, please follow these gui
|
||||
- A good way to easily start contributing is to pick and work on a [good first issue](https://github.com/laurent22/joplin/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22). We try to make these issues as clear as possible and provide basic info on how the code should be changed, and if something is unclear feel free to ask for more information on the issue.
|
||||
- Before adding a new feature, ask about it in the [Github Issue Tracker](https://github.com/laurent22/joplin/issues?utf8=%E2%9C%93&q=is%3Aissue) or the [Joplin Forum](https://discourse.joplinapp.org/), or check if existing discussions exist to make sure the new functionality is desired.
|
||||
- **Changes that will consist in more than 50 lines of code should be discussed the [Joplin Forum](https://discourse.joplinapp.org/)**, so that you don't spend too much time implementing something that might not be accepted.
|
||||
- All the applications share the same backend (database, synchronisation, settings, models, business logic, etc.) so if you change something in the backend in one app, makes sure it still work in the other apps. Usually it does, but keep this in mind.
|
||||
- Pull requests that make many changes using an automated tool, like for spell fixing, styling, etc. will not be accepted. An exception would be if the changes have been discussed in the forum and someone has agreed to review **and test** the pull request.
|
||||
|
||||
Building the apps is relatively easy - please [see the build instructions](https://github.com/laurent22/joplin/blob/dev/BUILD.md) for more details.
|
||||
Building the apps is relatively easy - please [see the build instructions](https://github.com/laurent22/joplin/blob/master/BUILD.md) for more details.
|
||||
|
||||
## Coding style
|
||||
### Coding style
|
||||
|
||||
Coding style is enforced by a pre-commit hook that runs eslint. This hook is installed whenever running `npm install` on any of the application directory. If for some reason the pre-commit hook didn't get installed, you can manually install it by running `npm install` at the root of the repository.
|
||||
|
||||
For new React components, please use [React Hooks](https://reactjs.org/docs/hooks-intro.html). For new code in general, please use TypeScript (unless you are modifying a file that was originally in JavaScript).
|
||||
|
||||
For changes made to the Desktop client that affect the user interface, refer to `ElectronClient/app/theme.js` for all styling information. The goal is to create a consistent user interface to allow for easy navigation of Joplin's various features and improve the overall user experience.
|
||||
### Unit tests
|
||||
|
||||
## Automated tests
|
||||
|
||||
When submitting a pull request for a new feature or a bug fix, please add automated tests for your code whenever possible. Tests in Joplin are divided into **unit tests** and **feature tests**.
|
||||
|
||||
* **Unit tests** are used to test models, services or utility classes - they are relatively low level. Unit tests should be prefixed with the type of class that is being tested - for example "models_Folder" or "services_SearchEngine".
|
||||
|
||||
* **Feature tests** on the other hand are to test higher level functionalities such as interactions with the GUI and how they affect the underlying model. Often these tests would dispatch Redux actions, and inspect how the application state has been changed. The feature tests should be prefixed with "feature_", for example "feature_TagList". There's a good explanation on what qualifies as a feature test in [this post](https://github.com/laurent22/joplin/pull/2819#issuecomment-603502230).
|
||||
When submitting a pull request for a new feature or bug fix, please add unit tests for your code. Unit testing GUI changes is not always possible so it is not required, but any change in a file under /lib for example should be unit tested.
|
||||
|
||||
The tests are under CliClient/tests. To get them running, you first need to build the CLI app:
|
||||
|
||||
```sh
|
||||
npm install
|
||||
cd CliClient
|
||||
```
|
||||
cd CliClient
|
||||
npm i
|
||||
./build.sh
|
||||
|
||||
To run all the test units:
|
||||
|
||||
```sh
|
||||
npm test
|
||||
```
|
||||
./run_test.sh
|
||||
|
||||
To run just one particular file:
|
||||
|
||||
```sh
|
||||
npm test -- --filter=markdownUtils # Don't add the .js extension
|
||||
```
|
||||
./run_test.sh markdownUtils # Don't add the .js extension
|
||||
|
||||
To filter tests. For example, to run all the test units that contain "should handle conflict" in their description:
|
||||
To filter tests:
|
||||
|
||||
```sh
|
||||
npm test -- --filter="should handle conflict"
|
||||
```
|
||||
./run_test.sh "should handle conflict" # Will run all the test units that contain "should handle conflict" in their description
|
||||
|
||||
## About abandoned pull requests
|
||||
|
||||
It happens that a pull request is started but not finished and despite our attempts to contact the contributor, we don't hear from them again.
|
||||
It happens that a pull request is started but not finished and despite our attempts to contact the contributor, we don’t hear from them again.
|
||||
|
||||
In that case we will not merge the pull request, even if only small changes are missing. Our policy is simply to close the pull request. Why? Because an unfinished pull request essentially means giving us work and moving on. We would rather not encourage this behaviour.
|
||||
|
||||
Also, please note that since we have spent time reviewing the pull request and proposing solutions, we reserve the right to re-use that knowledge to create a new pull request, potentially based on your changes.
|
||||
|
||||
We'd much prefer that you complete the pull request though, so we'll be sure to ping you a few times before that!
|
||||
We’d much prefer that you complete the pull request though, so we’ll be sure to ping you a few times before that!
|
||||
|
@@ -1,13 +1,13 @@
|
||||
module.exports = {
|
||||
'overrides': [
|
||||
"overrides": [
|
||||
{
|
||||
'files': ['tests/**/*.js'],
|
||||
"files": ["tests/**/*.js"],
|
||||
'rules': {
|
||||
// Ignore all unused function arguments, because in some
|
||||
// case they are kept to indicate the function signature.
|
||||
'no-unused-vars': ['error', { 'argsIgnorePattern': '.*' }],
|
||||
'@typescript-eslint/no-unused-vars': 0,
|
||||
},
|
||||
"no-unused-vars": ["error", { "argsIgnorePattern": ".*" }],
|
||||
"@typescript-eslint/no-unused-vars": 0,
|
||||
}
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
6
CliClient/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
build/
|
||||
node_modules/
|
||||
app/src
|
||||
tests-build/
|
||||
@@ -19,7 +20,4 @@ tests/sync
|
||||
out.txt
|
||||
linkToLocal.sh
|
||||
yarn-error.log
|
||||
tests/support/dropbox-auth.txt
|
||||
tests/support/nextcloud-auth.json
|
||||
tests/support/onedrive-auth.txt
|
||||
build/
|
||||
tests/support/dropbox-auth.txt
|
@@ -1,134 +0,0 @@
|
||||
const open = require('open');
|
||||
interface LinkStoreEntry {
|
||||
link: string;
|
||||
noteX: number;
|
||||
noteY: number;
|
||||
}
|
||||
|
||||
class LinkSelector {
|
||||
noteId_: string;
|
||||
scrollTop_: number;
|
||||
renderedText_: string;
|
||||
currentLinkIndex_: number;
|
||||
linkStore_: LinkStoreEntry[];
|
||||
linkRegex_: RegExp;
|
||||
|
||||
constructor() {
|
||||
this.noteId_ = null;
|
||||
this.scrollTop_ = null; // used so 'o' won't open unhighlighted link after scrolling
|
||||
this.renderedText_ = null;
|
||||
this.currentLinkIndex_ = null;
|
||||
this.linkStore_ = null;
|
||||
this.linkRegex_ = /http:\/\/[0-9.]+:[0-9]+\/[0-9]+/g;
|
||||
}
|
||||
|
||||
get link(): string | null {
|
||||
if (this.currentLinkIndex_ === null) return null;
|
||||
return this.linkStore_[this.currentLinkIndex_].link;
|
||||
}
|
||||
|
||||
get noteX(): number | null {
|
||||
if (this.currentLinkIndex_ === null) return null;
|
||||
return this.linkStore_[this.currentLinkIndex_].noteX;
|
||||
}
|
||||
|
||||
get noteY(): number | null {
|
||||
if (this.currentLinkIndex_ === null) return null;
|
||||
return this.linkStore_[this.currentLinkIndex_].noteY;
|
||||
}
|
||||
|
||||
findLinks(renderedText: string): LinkStoreEntry[] {
|
||||
const newLinkStore: LinkStoreEntry[] = [];
|
||||
const lines: string[] = renderedText.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const matches = [...lines[i].matchAll(this.linkRegex_)];
|
||||
matches.forEach((_e, n) => {
|
||||
newLinkStore.push(
|
||||
{
|
||||
link: matches[n][0],
|
||||
noteX: matches[n].index,
|
||||
noteY: i,
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
return newLinkStore;
|
||||
}
|
||||
|
||||
updateText(renderedText: string): void {
|
||||
this.currentLinkIndex_ = null;
|
||||
this.renderedText_ = renderedText;
|
||||
this.linkStore_ = this.findLinks(this.renderedText_);
|
||||
}
|
||||
|
||||
updateNote(textWidget: any): void {
|
||||
this.noteId_ = textWidget.noteId;
|
||||
this.scrollTop_ = textWidget.scrollTop_;
|
||||
this.updateText(textWidget.renderedText_);
|
||||
}
|
||||
|
||||
scrollWidget(textWidget: any): void {
|
||||
if (this.currentLinkIndex_ === null) return;
|
||||
|
||||
const noteY = this.linkStore_[this.currentLinkIndex_].noteY;
|
||||
|
||||
let viewBoxMin = textWidget.scrollTop_ + 1;
|
||||
let viewBoxMax = viewBoxMin + textWidget.innerHeight - 2;
|
||||
|
||||
if (noteY < viewBoxMin) {
|
||||
for (; noteY < viewBoxMin; textWidget.pageUp()) {
|
||||
viewBoxMin = textWidget.scrollTop_;
|
||||
viewBoxMax = viewBoxMin + textWidget.innerHeight;
|
||||
}
|
||||
return;
|
||||
|
||||
} else if (noteY > viewBoxMax) {
|
||||
for (; noteY > viewBoxMax; textWidget.pageDown()) {
|
||||
viewBoxMin = textWidget.scrollTop_;
|
||||
viewBoxMax = viewBoxMin + textWidget.innerHeight;
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
changeLink(textWidget: any, offset: number): void | null {
|
||||
if (textWidget.noteId !== this.noteId_) {
|
||||
this.updateNote(textWidget);
|
||||
this.changeLink(textWidget, offset);
|
||||
return;
|
||||
}
|
||||
if (textWidget.renderedText_ !== this.renderedText_) {
|
||||
this.updateText(textWidget.renderedText_);
|
||||
this.changeLink(textWidget, offset);
|
||||
return;
|
||||
}
|
||||
if (textWidget.scrollTop_ !== this.scrollTop_) this.scrollTop_ = textWidget.scrollTop_;
|
||||
|
||||
if (!this.linkStore_.length) return null;
|
||||
|
||||
let offsetMod = (offset + this.currentLinkIndex_) % this.linkStore_.length;
|
||||
|
||||
if (this.currentLinkIndex_ === null) {
|
||||
if (offsetMod < 0) this.currentLinkIndex_ = this.linkStore_.length + offsetMod;
|
||||
else if (!offsetMod) this.currentLinkIndex_ = 0;
|
||||
else this.currentLinkIndex_ = offsetMod - 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (offsetMod < 0) offsetMod = this.linkStore_.length + offsetMod;
|
||||
|
||||
this.currentLinkIndex_ = offsetMod;
|
||||
return;
|
||||
}
|
||||
|
||||
openLink(textWidget: any): void {
|
||||
if (textWidget.noteId !== this.noteId_) return;
|
||||
if (textWidget.renderedText_ !== this.renderedText_) return;
|
||||
if (textWidget.scrollTop_ !== this.scrollTop_) return;
|
||||
open(this.linkStore_[this.currentLinkIndex_].link);
|
||||
}
|
||||
}
|
||||
|
||||
export default LinkSelector;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const Logger = require('lib/Logger').default;
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const { netUtils } = require('lib/net-utils.js');
|
||||
|
||||
const http = require('http');
|
||||
|
@@ -1,17 +1,14 @@
|
||||
const Logger = require('lib/Logger').default;
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const reducer = require('lib/reducer').default;
|
||||
const { defaultState } = require('lib/reducer');
|
||||
const { reducer, defaultState } = require('lib/reducer.js');
|
||||
const { splitCommandString } = require('lib/string-utils.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const shim = require('lib/shim').default;
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Entities = require('html-entities').AllHtmlEntities;
|
||||
const htmlentities = new Entities().encode;
|
||||
|
||||
@@ -35,8 +32,6 @@ const FolderListWidget = require('./gui/FolderListWidget.js');
|
||||
const NoteListWidget = require('./gui/NoteListWidget.js');
|
||||
const StatusBarWidget = require('./gui/StatusBarWidget.js');
|
||||
const ConsoleWidget = require('./gui/ConsoleWidget.js');
|
||||
const LinkSelector = require('./LinkSelector.js').default;
|
||||
|
||||
|
||||
class AppGui {
|
||||
constructor(app, store, keymap) {
|
||||
@@ -78,8 +73,6 @@ class AppGui {
|
||||
this.currentShortcutKeys_ = [];
|
||||
this.lastShortcutKeyTime_ = 0;
|
||||
|
||||
this.linkSelector_ = new LinkSelector();
|
||||
|
||||
// Recurrent sync is setup only when the GUI is started. In
|
||||
// a regular command it's not necessary since the process
|
||||
// exits right away.
|
||||
@@ -141,7 +134,7 @@ class AppGui {
|
||||
const item = folderList.currentItem;
|
||||
|
||||
if (item === '-') {
|
||||
const newIndex = event.currentIndex + (event.previousIndex < event.currentIndex ? +1 : -1);
|
||||
let newIndex = event.currentIndex + (event.previousIndex < event.currentIndex ? +1 : -1);
|
||||
let nextItem = folderList.itemAt(newIndex);
|
||||
if (!nextItem) nextItem = folderList.itemAt(event.previousIndex);
|
||||
|
||||
@@ -193,7 +186,7 @@ class AppGui {
|
||||
borderRightWidth: 1,
|
||||
};
|
||||
noteList.on('currentItemChange', async () => {
|
||||
const note = noteList.currentItem;
|
||||
let note = noteList.currentItem;
|
||||
this.store_.dispatch({
|
||||
type: 'NOTE_SELECT',
|
||||
id: note ? note.id : null,
|
||||
@@ -250,9 +243,9 @@ class AppGui {
|
||||
|
||||
const hLayout = new HLayoutWidget();
|
||||
hLayout.name = 'hLayout';
|
||||
hLayout.addChild(folderList, { type: 'stretch', factor: Setting.value('layout.folderList.factor') });
|
||||
hLayout.addChild(noteList, { type: 'stretch', factor: Setting.value('layout.noteList.factor') });
|
||||
hLayout.addChild(noteLayout, { type: 'stretch', factor: Setting.value('layout.note.factor') });
|
||||
hLayout.addChild(folderList, { type: 'stretch', factor: 1 });
|
||||
hLayout.addChild(noteList, { type: 'stretch', factor: 1 });
|
||||
hLayout.addChild(noteLayout, { type: 'stretch', factor: 2 });
|
||||
|
||||
const vLayout = new VLayoutWidget();
|
||||
vLayout.name = 'vLayout';
|
||||
@@ -345,7 +338,7 @@ class AppGui {
|
||||
|
||||
if (consoleWidget.isMaximized__ === doMaximize) return;
|
||||
|
||||
const constraints = {
|
||||
let constraints = {
|
||||
type: 'stretch',
|
||||
factor: !doMaximize ? 1 : 4,
|
||||
};
|
||||
@@ -422,10 +415,10 @@ class AppGui {
|
||||
async handleModelAction(action) {
|
||||
this.logger().info('Action:', action);
|
||||
|
||||
const state = Object.assign({}, defaultState);
|
||||
let state = Object.assign({}, defaultState);
|
||||
state.notes = this.widget('noteList').items;
|
||||
|
||||
const newState = reducer(state, action);
|
||||
let newState = reducer(state, action);
|
||||
|
||||
if (newState !== state) {
|
||||
this.widget('noteList').items = newState.notes;
|
||||
@@ -461,30 +454,6 @@ class AppGui {
|
||||
} else {
|
||||
this.stdout(_('Please select the note or notebook to be deleted first.'));
|
||||
}
|
||||
} else if (cmd === 'next_link' || cmd === 'previous_link') {
|
||||
const noteText = this.widget('noteText');
|
||||
|
||||
noteText.render();
|
||||
|
||||
if (cmd === 'next_link') this.linkSelector_.changeLink(noteText, 1);
|
||||
else this.linkSelector_.changeLink(noteText, -1);
|
||||
|
||||
this.linkSelector_.scrollWidget(noteText);
|
||||
|
||||
const cursorOffsetX = this.widget('mainWindow').width - noteText.innerWidth - 8;
|
||||
const cursorOffsetY = 1 - noteText.scrollTop_;
|
||||
|
||||
if (this.linkSelector_.link) {
|
||||
this.term_.moveTo(
|
||||
this.linkSelector_.noteX + cursorOffsetX,
|
||||
this.linkSelector_.noteY + cursorOffsetY
|
||||
);
|
||||
shim.setTimeout(() => this.term_.term().inverse(this.linkSelector_.link), 50);
|
||||
}
|
||||
} else if (cmd === 'open_link') {
|
||||
if (this.widget('noteText').hasFocus) {
|
||||
this.linkSelector_.openLink(this.widget('noteText'));
|
||||
}
|
||||
} else if (cmd === 'toggle_console') {
|
||||
if (!this.consoleIsShown()) {
|
||||
this.showConsole();
|
||||
@@ -516,9 +485,9 @@ class AppGui {
|
||||
// this.logger().debug('Got command: ' + cmd);
|
||||
|
||||
try {
|
||||
const note = this.widget('noteList').currentItem;
|
||||
const folder = this.widget('folderList').currentItem;
|
||||
const args = splitCommandString(cmd);
|
||||
let note = this.widget('noteList').currentItem;
|
||||
let folder = this.widget('folderList').currentItem;
|
||||
let args = splitCommandString(cmd);
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] == '$n') {
|
||||
@@ -579,7 +548,7 @@ class AppGui {
|
||||
stdout(text) {
|
||||
if (text === null || text === undefined) return;
|
||||
|
||||
const lines = text.split('\n');
|
||||
let lines = text.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const v = typeof lines[i] === 'object' ? JSON.stringify(lines[i]) : lines[i];
|
||||
this.widget('console').addLine(v);
|
||||
@@ -657,7 +626,7 @@ class AppGui {
|
||||
|
||||
if (link.type === 'item') {
|
||||
const itemId = link.id;
|
||||
const item = await BaseItem.loadItemById(itemId);
|
||||
let item = await BaseItem.loadItemById(itemId);
|
||||
if (!item) throw new Error(`No item with ID ${itemId}`); // Should be nearly impossible
|
||||
|
||||
if (item.type_ === BaseModel.TYPE_RESOURCE) {
|
||||
@@ -781,7 +750,7 @@ class AppGui {
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
const shortcutKey = this.currentShortcutKeys_.join('');
|
||||
const keymapItem = this.keymapItemByKey(shortcutKey);
|
||||
let keymapItem = this.keymapItemByKey(shortcutKey);
|
||||
|
||||
// If this command is an alias to another command, resolve to the actual command
|
||||
|
||||
@@ -797,7 +766,7 @@ class AppGui {
|
||||
if (keymapItem.type === 'function') {
|
||||
this.processFunctionCommand(keymapItem.command);
|
||||
} else if (keymapItem.type === 'prompt') {
|
||||
const promptOptions = {};
|
||||
let promptOptions = {};
|
||||
if ('cursorPosition' in keymapItem) promptOptions.cursorPosition = keymapItem.cursorPosition;
|
||||
const commandString = await statusBar.prompt(keymapItem.command ? keymapItem.command : '', null, promptOptions);
|
||||
this.addCommandToConsole(commandString);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const BaseApplication = require('lib/BaseApplication').default;
|
||||
const { BaseApplication } = require('lib/BaseApplication');
|
||||
const { FoldersScreenUtils } = require('lib/folders-screen-utils.js');
|
||||
const ResourceService = require('lib/services/ResourceService');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
@@ -6,15 +6,14 @@ const Folder = require('lib/models/Folder.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { fileExtension } = require('lib/path-utils.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const fs = require('fs-extra');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
const Cache = require('lib/Cache');
|
||||
const RevisionService = require('lib/services/RevisionService');
|
||||
const shim = require('lib/shim').default;
|
||||
|
||||
class Application extends BaseApplication {
|
||||
constructor() {
|
||||
@@ -48,7 +47,7 @@ class Application extends BaseApplication {
|
||||
}
|
||||
|
||||
async loadItem(type, pattern, options = null) {
|
||||
const output = await this.loadItems(type, pattern, options);
|
||||
let output = await this.loadItems(type, pattern, options);
|
||||
|
||||
if (output.length > 1) {
|
||||
// output.sort((a, b) => { return a.user_updated_time < b.user_updated_time ? +1 : -1; });
|
||||
@@ -145,7 +144,7 @@ class Application extends BaseApplication {
|
||||
if (options.type === 'boolean') {
|
||||
if (answer === null) return false; // Pressed ESCAPE
|
||||
if (!answer) answer = options.answers[0];
|
||||
const positiveIndex = options.booleanAnswerDefault == 'y' ? 0 : 1;
|
||||
let positiveIndex = options.booleanAnswerDefault == 'y' ? 0 : 1;
|
||||
return answer.toLowerCase() === options.answers[positiveIndex].toLowerCase();
|
||||
} else {
|
||||
return answer;
|
||||
@@ -162,7 +161,7 @@ class Application extends BaseApplication {
|
||||
};
|
||||
|
||||
// Give it a few seconds to cancel otherwise exit anyway
|
||||
shim.setTimeout(async () => {
|
||||
setTimeout(async () => {
|
||||
await doExit();
|
||||
}, 5000);
|
||||
|
||||
@@ -182,7 +181,7 @@ class Application extends BaseApplication {
|
||||
const ext = fileExtension(path);
|
||||
if (ext != 'js') return;
|
||||
|
||||
const CommandClass = require(`./${path}`);
|
||||
let CommandClass = require(`./${path}`);
|
||||
let cmd = new CommandClass();
|
||||
if (!cmd.enabled()) return;
|
||||
cmd = this.setupCommand(cmd);
|
||||
@@ -193,8 +192,8 @@ class Application extends BaseApplication {
|
||||
}
|
||||
|
||||
if (uiType !== null) {
|
||||
const temp = [];
|
||||
for (const n in this.commands_) {
|
||||
let temp = [];
|
||||
for (let n in this.commands_) {
|
||||
if (!this.commands_.hasOwnProperty(n)) continue;
|
||||
const c = this.commands_[n];
|
||||
if (!c.supportsUi(uiType)) continue;
|
||||
@@ -208,8 +207,8 @@ class Application extends BaseApplication {
|
||||
|
||||
async commandNames() {
|
||||
const metadata = await this.commandMetadata();
|
||||
const output = [];
|
||||
for (const n in metadata) {
|
||||
let output = [];
|
||||
for (let n in metadata) {
|
||||
if (!metadata.hasOwnProperty(n)) continue;
|
||||
output.push(n);
|
||||
}
|
||||
@@ -228,7 +227,7 @@ class Application extends BaseApplication {
|
||||
const commands = this.commands();
|
||||
|
||||
output = {};
|
||||
for (const n in commands) {
|
||||
for (let n in commands) {
|
||||
if (!commands.hasOwnProperty(n)) continue;
|
||||
const cmd = commands[n];
|
||||
output[n] = cmd.metadata();
|
||||
@@ -252,7 +251,7 @@ class Application extends BaseApplication {
|
||||
CommandClass = require(`${__dirname}/command-${name}.js`);
|
||||
} catch (error) {
|
||||
if (error.message && error.message.indexOf('Cannot find module') >= 0) {
|
||||
const e = new Error(_('No such command: %s', name));
|
||||
let e = new Error(_('No such command: %s', name));
|
||||
e.type = 'notFound';
|
||||
throw e;
|
||||
} else {
|
||||
@@ -325,9 +324,6 @@ class Application extends BaseApplication {
|
||||
{ keys: ['PAGE_DOWN'], type: 'function', command: 'page_down' },
|
||||
{ keys: ['ENTER'], type: 'function', command: 'activate' },
|
||||
{ keys: ['DELETE', 'BACKSPACE'], type: 'function', command: 'delete' },
|
||||
{ keys: ['n'], type: 'function', command: 'next_link' },
|
||||
{ keys: ['b'], type: 'function', command: 'previous_link' },
|
||||
{ keys: ['o'], type: 'function', command: 'open_link' },
|
||||
{ keys: [' '], command: 'todo toggle $n' },
|
||||
{ keys: ['tc'], type: 'function', command: 'toggle_console' },
|
||||
{ keys: ['tm'], type: 'function', command: 'toggle_metadata' },
|
||||
@@ -366,7 +362,7 @@ class Application extends BaseApplication {
|
||||
}
|
||||
|
||||
const output = [];
|
||||
for (const n in itemsByCommand) {
|
||||
for (let n in itemsByCommand) {
|
||||
if (!itemsByCommand.hasOwnProperty(n)) continue;
|
||||
output.push(itemsByCommand[n]);
|
||||
}
|
||||
|
@@ -1,20 +1,20 @@
|
||||
const { app } = require('./app.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
const yargParser = require('yargs-parser');
|
||||
const fs = require('fs-extra');
|
||||
var { app } = require('./app.js');
|
||||
var Note = require('lib/models/Note.js');
|
||||
var Folder = require('lib/models/Folder.js');
|
||||
var Tag = require('lib/models/Tag.js');
|
||||
var { cliUtils } = require('./cli-utils.js');
|
||||
var yargParser = require('yargs-parser');
|
||||
var fs = require('fs-extra');
|
||||
|
||||
async function handleAutocompletionPromise(line) {
|
||||
// Auto-complete the command name
|
||||
const names = await app().commandNames();
|
||||
const words = getArguments(line);
|
||||
let words = getArguments(line);
|
||||
// If there is only one word and it is not already a command name then you
|
||||
// should look for commands it could be
|
||||
if (words.length == 1) {
|
||||
if (names.indexOf(words[0]) === -1) {
|
||||
const x = names.filter(n => n.indexOf(words[0]) === 0);
|
||||
let x = names.filter(n => n.indexOf(words[0]) === 0);
|
||||
if (x.length === 1) {
|
||||
return `${x[0]} `;
|
||||
}
|
||||
@@ -36,8 +36,8 @@ async function handleAutocompletionPromise(line) {
|
||||
}
|
||||
|
||||
// complete an option
|
||||
const next = words.length > 1 ? words[words.length - 1] : '';
|
||||
const l = [];
|
||||
let next = words.length > 1 ? words[words.length - 1] : '';
|
||||
let l = [];
|
||||
if (next[0] === '-') {
|
||||
for (let i = 0; i < metadata.options.length; i++) {
|
||||
const options = metadata.options[i][0].split(' ');
|
||||
@@ -60,7 +60,7 @@ async function handleAutocompletionPromise(line) {
|
||||
if (l.length === 0) {
|
||||
return line;
|
||||
}
|
||||
const ret = l.map(a => toCommandLine(a));
|
||||
let ret = l.map(a => toCommandLine(a));
|
||||
ret.prefix = `${toCommandLine(words.slice(0, -1))} `;
|
||||
return ret;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ async function handleAutocompletionPromise(line) {
|
||||
// words that don't start with a - less one for the command name
|
||||
const positionalArgs = words.filter(a => a.indexOf('-') !== 0).length - 1;
|
||||
|
||||
const cmdUsage = yargParser(metadata.usage)['_'];
|
||||
let cmdUsage = yargParser(metadata.usage)['_'];
|
||||
cmdUsage.splice(0, 1);
|
||||
|
||||
if (cmdUsage.length >= positionalArgs) {
|
||||
@@ -95,29 +95,29 @@ async function handleAutocompletionPromise(line) {
|
||||
}
|
||||
|
||||
if (argName == 'tag') {
|
||||
const tags = await Tag.search({ titlePattern: `${next}*` });
|
||||
let tags = await Tag.search({ titlePattern: `${next}*` });
|
||||
l.push(...tags.map(n => n.title));
|
||||
}
|
||||
|
||||
if (argName == 'file') {
|
||||
const files = await fs.readdir('.');
|
||||
let files = await fs.readdir('.');
|
||||
l.push(...files);
|
||||
}
|
||||
|
||||
if (argName == 'tag-command') {
|
||||
const c = filterList(['add', 'remove', 'list', 'notetags'], next);
|
||||
let c = filterList(['add', 'remove', 'list', 'notetags'], next);
|
||||
l.push(...c);
|
||||
}
|
||||
|
||||
if (argName == 'todo-command') {
|
||||
const c = filterList(['toggle', 'clear'], next);
|
||||
let c = filterList(['toggle', 'clear'], next);
|
||||
l.push(...c);
|
||||
}
|
||||
}
|
||||
if (l.length === 1) {
|
||||
return toCommandLine([...words.slice(0, -1), l[0]]);
|
||||
} else if (l.length > 1) {
|
||||
const ret = l.map(a => toCommandLine(a));
|
||||
let ret = l.map(a => toCommandLine(a));
|
||||
ret.prefix = `${toCommandLine(words.slice(0, -1))} `;
|
||||
return ret;
|
||||
}
|
||||
@@ -155,7 +155,7 @@ function getArguments(line) {
|
||||
let inSingleQuotes = false;
|
||||
let inDoubleQuotes = false;
|
||||
let currentWord = '';
|
||||
const parsed = [];
|
||||
let parsed = [];
|
||||
for (let i = 0; i < line.length; i++) {
|
||||
if (line[i] === '"') {
|
||||
if (inDoubleQuotes) {
|
||||
@@ -192,7 +192,7 @@ function getArguments(line) {
|
||||
return parsed;
|
||||
}
|
||||
function filterList(list, next) {
|
||||
const output = [];
|
||||
let output = [];
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
if (list[i].indexOf(next) !== 0) continue;
|
||||
output.push(list[i]);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
|
||||
class BaseCommand {
|
||||
@@ -50,7 +50,7 @@ class BaseCommand {
|
||||
async cancel() {}
|
||||
|
||||
name() {
|
||||
const r = this.usage().split(' ');
|
||||
let r = this.usage().split(' ');
|
||||
return r[0];
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
const fs = require('fs-extra');
|
||||
const { fileExtension, dirname } = require('lib/path-utils.js');
|
||||
const wrap_ = require('word-wrap');
|
||||
const { languageCode } = require('lib/locale');
|
||||
const { languageCode } = require('lib/locale.js');
|
||||
|
||||
const rootDir = dirname(dirname(__dirname));
|
||||
const MAX_WIDTH = 78;
|
||||
@@ -15,11 +15,11 @@ function wrap(text, indent) {
|
||||
}
|
||||
|
||||
function renderOptions(options) {
|
||||
const output = [];
|
||||
let output = [];
|
||||
const optionColWidth = getOptionColWidth(options);
|
||||
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
const option = options[i];
|
||||
let option = options[i];
|
||||
const flag = option[0];
|
||||
const indent = INDENT + INDENT + ' '.repeat(optionColWidth + 2);
|
||||
|
||||
@@ -33,7 +33,7 @@ function renderOptions(options) {
|
||||
}
|
||||
|
||||
function renderCommand(cmd) {
|
||||
const output = [];
|
||||
let output = [];
|
||||
output.push(INDENT + cmd.usage());
|
||||
output.push('');
|
||||
output.push(wrap(cmd.description(), INDENT + INDENT));
|
||||
@@ -48,14 +48,14 @@ function renderCommand(cmd) {
|
||||
}
|
||||
|
||||
function getCommands() {
|
||||
const output = [];
|
||||
let output = [];
|
||||
fs.readdirSync(__dirname).forEach(path => {
|
||||
if (path.indexOf('command-') !== 0) return;
|
||||
const ext = fileExtension(path);
|
||||
if (ext != 'js') return;
|
||||
|
||||
const CommandClass = require(`./${path}`);
|
||||
const cmd = new CommandClass();
|
||||
let CommandClass = require(`./${path}`);
|
||||
let cmd = new CommandClass();
|
||||
if (!cmd.enabled()) return;
|
||||
if (cmd.hidden()) return;
|
||||
output.push(cmd);
|
||||
@@ -73,7 +73,7 @@ function getOptionColWidth(options) {
|
||||
}
|
||||
|
||||
function getHeader() {
|
||||
const output = [];
|
||||
let output = [];
|
||||
|
||||
output.push('NAME');
|
||||
output.push('');
|
||||
@@ -84,7 +84,7 @@ function getHeader() {
|
||||
output.push('DESCRIPTION');
|
||||
output.push('');
|
||||
|
||||
const description = [];
|
||||
let description = [];
|
||||
description.push('Joplin is a note taking and to-do application, which can handle a large number of notes organised into notebooks.');
|
||||
description.push('The notes are searchable, can be copied, tagged and modified with your own text editor.');
|
||||
description.push('\n\n');
|
||||
@@ -98,7 +98,7 @@ function getHeader() {
|
||||
}
|
||||
|
||||
function getFooter() {
|
||||
const output = [];
|
||||
let output = [];
|
||||
|
||||
output.push('WEBSITE');
|
||||
output.push('');
|
||||
@@ -120,10 +120,10 @@ async function main() {
|
||||
// setLocale('fr_FR');
|
||||
|
||||
const commands = getCommands();
|
||||
const commandBlocks = [];
|
||||
let commandBlocks = [];
|
||||
|
||||
for (let i = 0; i < commands.length; i++) {
|
||||
const cmd = commands[i];
|
||||
let cmd = commands[i];
|
||||
commandBlocks.push(renderCommand(cmd));
|
||||
}
|
||||
|
||||
|
@@ -1,14 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const Logger = require('lib/Logger').default;
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const { dirname } = require('lib/path-utils.js');
|
||||
const { DatabaseDriverNode } = require('lib/database-driver-node.js');
|
||||
const { JoplinDatabase } = require('lib/joplin-database.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { sprintf } = require('sprintf-js');
|
||||
const exec = require('child_process').exec;
|
||||
|
||||
@@ -40,8 +40,8 @@ function createClient(id) {
|
||||
const client = createClient(1);
|
||||
|
||||
function execCommand(client, command) {
|
||||
const exePath = `node ${joplinAppPath}`;
|
||||
const cmd = `${exePath} --update-geolocation-disabled --env dev --profile ${client.profileDir} ${command}`;
|
||||
let exePath = `node ${joplinAppPath}`;
|
||||
let cmd = `${exePath} --update-geolocation-disabled --env dev --profile ${client.profileDir} ${command}`;
|
||||
logger.info(`${client.id}: ${command}`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -129,8 +129,8 @@ testUnits.testCat = async () => {
|
||||
await execCommand(client, 'mkbook nb1');
|
||||
await execCommand(client, 'mknote mynote');
|
||||
|
||||
const folder = await Folder.loadByTitle('nb1');
|
||||
const note = await Note.loadFolderNoteByField(folder.id, 'title', 'mynote');
|
||||
let folder = await Folder.loadByTitle('nb1');
|
||||
let note = await Note.loadFolderNoteByField(folder.id, 'title', 'mynote');
|
||||
|
||||
let r = await execCommand(client, 'cat mynote');
|
||||
assertTrue(r.indexOf('mynote') >= 0);
|
||||
@@ -149,7 +149,7 @@ testUnits.testConfig = async () => {
|
||||
await Setting.load();
|
||||
assertEquals('subl', Setting.value('editor'));
|
||||
|
||||
const r = await execCommand(client, 'config');
|
||||
let r = await execCommand(client, 'config');
|
||||
assertTrue(r.indexOf('editor') >= 0);
|
||||
assertTrue(r.indexOf('subl') >= 0);
|
||||
};
|
||||
@@ -161,14 +161,14 @@ testUnits.testCp = async () => {
|
||||
|
||||
await execCommand(client, 'cp n1');
|
||||
|
||||
const f1 = await Folder.loadByTitle('nb1');
|
||||
const f2 = await Folder.loadByTitle('nb2');
|
||||
let f1 = await Folder.loadByTitle('nb1');
|
||||
let f2 = await Folder.loadByTitle('nb2');
|
||||
let notes = await Note.previews(f1.id);
|
||||
|
||||
assertEquals(2, notes.length);
|
||||
|
||||
await execCommand(client, 'cp n1 nb2');
|
||||
const notesF1 = await Note.previews(f1.id);
|
||||
let notesF1 = await Note.previews(f1.id);
|
||||
assertEquals(2, notesF1.length);
|
||||
notes = await Note.previews(f2.id);
|
||||
assertEquals(1, notes.length);
|
||||
@@ -179,7 +179,7 @@ testUnits.testLs = async () => {
|
||||
await execCommand(client, 'mkbook nb1');
|
||||
await execCommand(client, 'mknote note1');
|
||||
await execCommand(client, 'mknote note2');
|
||||
const r = await execCommand(client, 'ls');
|
||||
let r = await execCommand(client, 'ls');
|
||||
|
||||
assertTrue(r.indexOf('note1') >= 0);
|
||||
assertTrue(r.indexOf('note2') >= 0);
|
||||
@@ -191,8 +191,8 @@ testUnits.testMv = async () => {
|
||||
await execCommand(client, 'mknote n1');
|
||||
await execCommand(client, 'mv n1 nb2');
|
||||
|
||||
const f1 = await Folder.loadByTitle('nb1');
|
||||
const f2 = await Folder.loadByTitle('nb2');
|
||||
let f1 = await Folder.loadByTitle('nb1');
|
||||
let f2 = await Folder.loadByTitle('nb2');
|
||||
let notes1 = await Note.previews(f1.id);
|
||||
let notes2 = await Note.previews(f2.id);
|
||||
|
||||
@@ -218,18 +218,18 @@ async function main() {
|
||||
logger.info(await execCommand(client, 'version'));
|
||||
|
||||
await db.open({ name: `${client.profileDir}/database.sqlite` });
|
||||
BaseModel.setDb(db);
|
||||
BaseModel.db_ = db;
|
||||
await Setting.load();
|
||||
|
||||
let onlyThisTest = 'testMv';
|
||||
onlyThisTest = '';
|
||||
|
||||
for (const n in testUnits) {
|
||||
for (let n in testUnits) {
|
||||
if (!testUnits.hasOwnProperty(n)) continue;
|
||||
if (onlyThisTest && n != onlyThisTest) continue;
|
||||
|
||||
await clearDatabase();
|
||||
const testName = n.substr(4).toLowerCase();
|
||||
let testName = n.substr(4).toLowerCase();
|
||||
process.stdout.write(`${testName}: `);
|
||||
await testUnits[n]();
|
||||
console.info('');
|
||||
|
@@ -1,8 +1,7 @@
|
||||
const yargParser = require('yargs-parser');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const stringPadding = require('string-padding');
|
||||
const Logger = require('lib/Logger').default;
|
||||
|
||||
const cliUtils = {};
|
||||
|
||||
@@ -12,27 +11,27 @@ cliUtils.printArray = function(logFunction, rows) {
|
||||
const ALIGN_LEFT = 0;
|
||||
const ALIGN_RIGHT = 1;
|
||||
|
||||
const colWidths = [];
|
||||
const colAligns = [];
|
||||
let colWidths = [];
|
||||
let colAligns = [];
|
||||
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
const row = rows[i];
|
||||
let row = rows[i];
|
||||
|
||||
for (let j = 0; j < row.length; j++) {
|
||||
const item = row[j];
|
||||
const width = item ? item.toString().length : 0;
|
||||
const align = typeof item == 'number' ? ALIGN_RIGHT : ALIGN_LEFT;
|
||||
let item = row[j];
|
||||
let width = item ? item.toString().length : 0;
|
||||
let align = typeof item == 'number' ? ALIGN_RIGHT : ALIGN_LEFT;
|
||||
if (!colWidths[j] || colWidths[j] < width) colWidths[j] = width;
|
||||
if (colAligns.length <= j) colAligns[j] = align;
|
||||
}
|
||||
}
|
||||
|
||||
for (let row = 0; row < rows.length; row++) {
|
||||
const line = [];
|
||||
let line = [];
|
||||
for (let col = 0; col < colWidths.length; col++) {
|
||||
const item = rows[row][col];
|
||||
const width = colWidths[col];
|
||||
const dir = colAligns[col] == ALIGN_LEFT ? stringPadding.RIGHT : stringPadding.LEFT;
|
||||
let item = rows[row][col];
|
||||
let width = colWidths[col];
|
||||
let dir = colAligns[col] == ALIGN_LEFT ? stringPadding.RIGHT : stringPadding.LEFT;
|
||||
line.push(stringPadding(item, width, ' ', dir));
|
||||
}
|
||||
logFunction(line.join(' '));
|
||||
@@ -40,7 +39,7 @@ cliUtils.printArray = function(logFunction, rows) {
|
||||
};
|
||||
|
||||
cliUtils.parseFlags = function(flags) {
|
||||
const output = {};
|
||||
let output = {};
|
||||
flags = flags.split(',');
|
||||
for (let i = 0; i < flags.length; i++) {
|
||||
let f = flags[i].trim();
|
||||
@@ -77,11 +76,11 @@ cliUtils.parseCommandArg = function(arg) {
|
||||
cliUtils.makeCommandArgs = function(cmd, argv) {
|
||||
let cmdUsage = cmd.usage();
|
||||
cmdUsage = yargParser(cmdUsage);
|
||||
const output = {};
|
||||
let output = {};
|
||||
|
||||
const options = cmd.options();
|
||||
const booleanFlags = [];
|
||||
const aliases = {};
|
||||
let options = cmd.options();
|
||||
let booleanFlags = [];
|
||||
let aliases = {};
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
if (options[i].length != 2) throw new Error(`Invalid options: ${options[i]}`);
|
||||
let flags = options[i][0];
|
||||
@@ -98,7 +97,7 @@ cliUtils.makeCommandArgs = function(cmd, argv) {
|
||||
}
|
||||
}
|
||||
|
||||
const args = yargParser(argv, {
|
||||
let args = yargParser(argv, {
|
||||
boolean: booleanFlags,
|
||||
alias: aliases,
|
||||
string: ['_'],
|
||||
@@ -114,8 +113,8 @@ cliUtils.makeCommandArgs = function(cmd, argv) {
|
||||
}
|
||||
}
|
||||
|
||||
const argOptions = {};
|
||||
for (const key in args) {
|
||||
let argOptions = {};
|
||||
for (let key in args) {
|
||||
if (!args.hasOwnProperty(key)) continue;
|
||||
if (key == '_') continue;
|
||||
argOptions[key] = args[key];
|
||||
@@ -135,7 +134,7 @@ cliUtils.promptMcq = function(message, answers) {
|
||||
});
|
||||
|
||||
message += '\n\n';
|
||||
for (const n in answers) {
|
||||
for (let n in answers) {
|
||||
if (!answers.hasOwnProperty(n)) continue;
|
||||
message += `${_('%s: %s', n, answers[n])}\n`;
|
||||
}
|
||||
@@ -246,17 +245,4 @@ cliUtils.redrawDone = function() {
|
||||
redrawStarted_ = false;
|
||||
};
|
||||
|
||||
cliUtils.stdoutLogger = function(stdout) {
|
||||
const stdoutFn = (...s) => stdout(s.join(' '));
|
||||
|
||||
const logger = new Logger();
|
||||
logger.addTarget('console', { console: {
|
||||
info: stdoutFn,
|
||||
warn: stdoutFn,
|
||||
error: stdoutFn,
|
||||
} });
|
||||
|
||||
return logger;
|
||||
};
|
||||
|
||||
module.exports = { cliUtils };
|
||||
|
@@ -3,7 +3,7 @@ const BaseItem = require('lib/models/BaseItem');
|
||||
const BaseModel = require('lib/BaseModel');
|
||||
const { toTitleCase } = require('lib/string-utils.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const markdownUtils = require('lib/markdownUtils').default;
|
||||
const markdownUtils = require('lib/markdownUtils');
|
||||
const { Database } = require('lib/database.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
@@ -15,10 +15,6 @@ class Command extends BaseCommand {
|
||||
return 'Build the API doc';
|
||||
}
|
||||
|
||||
enabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
createPropertiesTable(tableFields) {
|
||||
const headers = [
|
||||
{ name: 'name', label: 'Name' },
|
||||
@@ -53,9 +49,10 @@ class Command extends BaseCommand {
|
||||
|
||||
const lines = [];
|
||||
|
||||
lines.push('# Joplin Data API');
|
||||
lines.push('# Joplin API');
|
||||
lines.push('');
|
||||
lines.push('This API is available when the clipper server is running. It provides access to the notes, notebooks, tags and other Joplin object via a REST API. Plugins can also access this API even when the clipper server is not running.');
|
||||
|
||||
lines.push('When the Web Clipper service is enabled, Joplin exposes a [REST API](https://en.wikipedia.org/wiki/Representational_state_transfer) which allows third-party applications to access Joplin\'s data and to create, modify or delete notes, notebooks, resources or tags.');
|
||||
lines.push('');
|
||||
lines.push('In order to use it, you\'ll first need to find on which port the service is running. To do so, open the Web Clipper Options in Joplin and if the service is running it should tell you on which port. Normally it runs on port **41184**. If you want to find it programmatically, you may follow this kind of algorithm:');
|
||||
lines.push('');
|
||||
@@ -290,7 +287,7 @@ class Command extends BaseCommand {
|
||||
lines.push('');
|
||||
lines.push('### Creating a note with a specific ID');
|
||||
lines.push('');
|
||||
lines.push('When a new note is created, it is automatically assigned a new unique ID so **normally you do not need to set the ID**. However, if for some reason you want to set it, you can supply it as the `id` property. It needs to be a **32 characters long string** in hexadecimal. **Make sure it is unique**, for example by generating it using whatever GUID function is available in your programming language.');
|
||||
lines.push('When a new note is created, it is automatically assigned a new unique ID so **normally you do not need to set the ID**. However, if for some reason you want to set it, you can supply it as the `id` property. It needs to be a 32 characters long hexadecimal string. **Make sure it is unique**, for example by generating it using whatever GUID function is available in your programming language.');
|
||||
lines.push('');
|
||||
lines.push(' curl --data \'{ "id": "00a87474082744c1a8515da6aa5792d2", "title": "My note with custom ID"}\' http://127.0.0.1:41184/notes');
|
||||
lines.push('');
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const shim = require('lib/shim').default;
|
||||
const { shim } = require('lib/shim.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
@@ -14,9 +14,9 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
const title = args['note'];
|
||||
let title = args['note'];
|
||||
|
||||
const note = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
||||
let note = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
||||
this.encryptionCheck(note);
|
||||
if (!note) throw new Error(_('Cannot find "%s".', title));
|
||||
|
||||
|
@@ -1,8 +1,7 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const BaseItem = require('lib/models/BaseItem.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
@@ -19,22 +18,20 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
const title = args['note'];
|
||||
let title = args['note'];
|
||||
|
||||
const item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
||||
let item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
||||
if (!item) throw new Error(_('Cannot find "%s".', title));
|
||||
|
||||
let content = '';
|
||||
|
||||
if (item.encryption_applied) {
|
||||
content = BaseItem.displayTitle(item);
|
||||
} else {
|
||||
content = args.options.verbose ? await Note.serialize(item) : await Note.serializeForEdit(item);
|
||||
}
|
||||
|
||||
const content = args.options.verbose ? await Note.serialize(item) : await Note.serializeForEdit(item);
|
||||
this.stdout(content);
|
||||
app().gui().showConsole();
|
||||
app().gui().maximizeConsole();
|
||||
|
||||
app()
|
||||
.gui()
|
||||
.showConsole();
|
||||
app()
|
||||
.gui()
|
||||
.maximizeConsole();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { _, setLocale } = require('lib/locale');
|
||||
const { _, setLocale } = require('lib/locale.js');
|
||||
const { app } = require('./app.js');
|
||||
const fs = require('fs-extra');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
@@ -35,7 +35,7 @@ class Command extends BaseCommand {
|
||||
});
|
||||
|
||||
inputStream.on('end', () => {
|
||||
const json = chunks.join('');
|
||||
let json = chunks.join('');
|
||||
let settingsObj;
|
||||
try {
|
||||
settingsObj = JSON.parse(json);
|
||||
@@ -83,7 +83,7 @@ class Command extends BaseCommand {
|
||||
};
|
||||
|
||||
if (isExport || (!isImport && !args.value)) {
|
||||
const keys = Setting.keys(!verbose, 'cli');
|
||||
let keys = Setting.keys(!verbose, 'cli');
|
||||
keys.sort();
|
||||
|
||||
if (isExport) {
|
||||
@@ -124,6 +124,7 @@ class Command extends BaseCommand {
|
||||
|
||||
if (args.name == 'locale') {
|
||||
setLocale(Setting.value('locale'));
|
||||
app().onLocaleChanged();
|
||||
}
|
||||
|
||||
await Setting.saveAll();
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
|
@@ -18,15 +18,15 @@ class Command extends BaseCommand {
|
||||
|
||||
async action() {
|
||||
let items = [];
|
||||
const folders = await Folder.all();
|
||||
let folders = await Folder.all();
|
||||
for (let i = 0; i < folders.length; i++) {
|
||||
const folder = folders[i];
|
||||
const notes = await Note.previews(folder.id);
|
||||
let folder = folders[i];
|
||||
let notes = await Note.previews(folder.id);
|
||||
items.push(folder);
|
||||
items = items.concat(notes);
|
||||
}
|
||||
|
||||
const tags = await Tag.all();
|
||||
let tags = await Tag.all();
|
||||
for (let i = 0; i < tags.length; i++) {
|
||||
tags[i].notes_ = await Tag.noteIds(tags[i].id);
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const EncryptionService = require('lib/services/EncryptionService');
|
||||
const DecryptionWorker = require('lib/services/DecryptionWorker');
|
||||
const BaseItem = require('lib/models/BaseItem');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const shim = require('lib/shim').default;
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { shim } = require('lib/shim');
|
||||
const pathUtils = require('lib/path-utils.js');
|
||||
const imageType = require('image-type');
|
||||
const readChunk = require('read-chunk');
|
||||
@@ -24,11 +24,12 @@ class Command extends BaseCommand {
|
||||
['-p, --password <password>', 'Use this password as master password (For security reasons, it is not recommended to use this option).'],
|
||||
['-v, --verbose', 'More verbose output for the `target-status` command'],
|
||||
['-o, --output <directory>', 'Output directory'],
|
||||
['--retry-failed-items', 'Applies to `decrypt` command - retries decrypting items that previously could not be decrypted.'],
|
||||
];
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
// change-password
|
||||
|
||||
const options = args.options;
|
||||
|
||||
const askForMasterKey = async error => {
|
||||
@@ -38,36 +39,11 @@ class Command extends BaseCommand {
|
||||
this.stdout(_('Operation cancelled'));
|
||||
return false;
|
||||
}
|
||||
Setting.setObjectValue('encryption.passwordCache', masterKeyId, password);
|
||||
Setting.setObjectKey('encryption.passwordCache', masterKeyId, password);
|
||||
await EncryptionService.instance().loadMasterKeysFromSettings();
|
||||
return true;
|
||||
};
|
||||
|
||||
const startDecryption = async () => {
|
||||
this.stdout(_('Starting decryption... Please wait as it may take several minutes depending on how much there is to decrypt.'));
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
const result = await DecryptionWorker.instance().start();
|
||||
const line = [];
|
||||
line.push(_('Decrypted items: %d', result.decryptedItemCount));
|
||||
if (result.skippedItemCount) line.push(_('Skipped items: %d (use --retry-failed-items to retry decrypting them)', result.skippedItemCount));
|
||||
this.stdout(line.join('\n'));
|
||||
break;
|
||||
} catch (error) {
|
||||
if (error.code === 'masterKeyNotLoaded') {
|
||||
const ok = await askForMasterKey(error);
|
||||
if (!ok) return;
|
||||
continue;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
this.stdout(_('Completed decryption.'));
|
||||
};
|
||||
|
||||
if (args.command === 'enable') {
|
||||
const password = options.password ? options.password.toString() : await this.prompt(_('Enter master password:'), { type: 'string', secure: true });
|
||||
if (!password) {
|
||||
@@ -97,8 +73,24 @@ class Command extends BaseCommand {
|
||||
const plainText = await EncryptionService.instance().decryptString(args.path);
|
||||
this.stdout(plainText);
|
||||
} else {
|
||||
if (args.options['retry-failed-items']) await DecryptionWorker.instance().clearDisabledItems();
|
||||
await startDecryption();
|
||||
this.stdout(_('Starting decryption... Please wait as it may take several minutes depending on how much there is to decrypt.'));
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
await DecryptionWorker.instance().start();
|
||||
break;
|
||||
} catch (error) {
|
||||
if (error.code === 'masterKeyNotLoaded') {
|
||||
const ok = await askForMasterKey(error);
|
||||
if (!ok) return;
|
||||
continue;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
this.stdout(_('Completed decryption.'));
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -146,7 +138,7 @@ class Command extends BaseCommand {
|
||||
if (!targetPath) throw new Error('Please specify the sync target path.');
|
||||
|
||||
const dirPaths = function(targetPath) {
|
||||
const paths = [];
|
||||
let paths = [];
|
||||
fs.readdirSync(targetPath).forEach(path => {
|
||||
paths.push(path);
|
||||
});
|
||||
@@ -159,10 +151,10 @@ class Command extends BaseCommand {
|
||||
let encryptedResourceCount = 0;
|
||||
let otherItemCount = 0;
|
||||
|
||||
const encryptedPaths = [];
|
||||
const decryptedPaths = [];
|
||||
let encryptedPaths = [];
|
||||
let decryptedPaths = [];
|
||||
|
||||
const paths = dirPaths(targetPath);
|
||||
let paths = dirPaths(targetPath);
|
||||
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
const path = paths[i];
|
||||
@@ -172,7 +164,7 @@ class Command extends BaseCommand {
|
||||
// this.stdout(fullPath);
|
||||
|
||||
if (path === '.resource') {
|
||||
const resourcePaths = dirPaths(fullPath);
|
||||
let resourcePaths = dirPaths(fullPath);
|
||||
for (let j = 0; j < resourcePaths.length; j++) {
|
||||
const resourcePath = resourcePaths[j];
|
||||
resourceCount++;
|
||||
|
@@ -1,11 +1,11 @@
|
||||
const fs = require('fs-extra');
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { splitCommandString } = require('lib/string-utils.js');
|
||||
const uuid = require('lib/uuid').default;
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
@@ -35,7 +35,7 @@ class Command extends BaseCommand {
|
||||
// Load note or create it if it doesn't exist
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
const title = args['note'];
|
||||
let title = args['note'];
|
||||
|
||||
if (!app().currentFolder()) throw new Error(_('No active notebook.'));
|
||||
let note = await app().loadItem(BaseModel.TYPE_NOTE, title);
|
||||
@@ -91,7 +91,7 @@ class Command extends BaseCommand {
|
||||
|
||||
const updatedContent = await fs.readFile(tempFilePath, 'utf8');
|
||||
if (updatedContent !== originalContent) {
|
||||
const updatedNote = await Note.unserializeForEdit(updatedContent);
|
||||
let updatedNote = await Note.unserializeForEdit(updatedContent);
|
||||
updatedNote.id = note.id;
|
||||
await Note.save(updatedNote);
|
||||
this.stdout(_('Note has been saved.'));
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { ReportService } = require('lib/services/report.js');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const InteropService = require('lib/services/interop/InteropService').default;
|
||||
const InteropService = require('lib/services/InteropService.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
@@ -14,23 +14,21 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
options() {
|
||||
const service = InteropService.instance();
|
||||
const service = new InteropService();
|
||||
const formats = service
|
||||
.modules()
|
||||
.filter(m => m.type === 'exporter' && m.format !== 'html')
|
||||
.filter(m => m.type === 'exporter')
|
||||
.map(m => m.format + (m.description ? ` (${m.description})` : ''));
|
||||
|
||||
return [['--format <format>', _('Destination format: %s', formats.join(', '))], ['--note <note>', _('Exports only the given note.')], ['--notebook <notebook>', _('Exports only the given notebook.')]];
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
const exportOptions = {};
|
||||
let exportOptions = {};
|
||||
exportOptions.path = args.path;
|
||||
|
||||
exportOptions.format = args.options.format ? args.options.format : 'jex';
|
||||
|
||||
if (exportOptions.format === 'html') throw new Error('HTML export is not supported. Please use the desktop application.');
|
||||
|
||||
if (args.options.note) {
|
||||
const notes = await app().loadItems(BaseModel.TYPE_NOTE, args.options.note, { parent: app().currentFolder() });
|
||||
if (!notes.length) throw new Error(_('Cannot find "%s".', args.options.note));
|
||||
@@ -41,7 +39,7 @@ class Command extends BaseCommand {
|
||||
exportOptions.sourceFolderIds = folders.map(n => n.id);
|
||||
}
|
||||
|
||||
const service = InteropService.instance();
|
||||
const service = new InteropService();
|
||||
const result = await service.export(exportOptions);
|
||||
|
||||
result.warnings.map(w => this.stdout(w));
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
||||
@@ -14,9 +14,9 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
const title = args['note'];
|
||||
let title = args['note'];
|
||||
|
||||
const item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
||||
let item = await app().loadItem(BaseModel.TYPE_NOTE, title, { parent: app().currentFolder() });
|
||||
if (!item) throw new Error(_('Cannot find "%s".', title));
|
||||
const url = Note.geolocationUrl(item);
|
||||
this.stdout(url);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { renderCommandHelp } = require('./help-utils.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
@@ -15,8 +15,8 @@ class Command extends BaseCommand {
|
||||
|
||||
allCommands() {
|
||||
const commands = app().commands(app().uiType());
|
||||
const output = [];
|
||||
for (const n in commands) {
|
||||
let output = [];
|
||||
for (let n in commands) {
|
||||
if (!commands.hasOwnProperty(n)) continue;
|
||||
const command = commands[n];
|
||||
if (command.hidden()) continue;
|
||||
@@ -48,7 +48,7 @@ class Command extends BaseCommand {
|
||||
.gui()
|
||||
.keymap();
|
||||
|
||||
const rows = [];
|
||||
let rows = [];
|
||||
|
||||
for (let i = 0; i < keymap.length; i++) {
|
||||
const item = keymap[i];
|
||||
|
@@ -1,9 +1,9 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const InteropService = require('lib/services/interop/InteropService').default;
|
||||
const InteropService = require('lib/services/InteropService.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
@@ -15,21 +15,17 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
options() {
|
||||
const service = InteropService.instance();
|
||||
const service = new InteropService();
|
||||
const formats = service
|
||||
.modules()
|
||||
.filter(m => m.type === 'importer')
|
||||
.map(m => m.format);
|
||||
|
||||
return [
|
||||
['--format <format>', _('Source format: %s', ['auto'].concat(formats).join(', '))],
|
||||
['-f, --force', _('Do not ask for confirmation.')],
|
||||
['--output-format <output-format>', _('Output format: %s', 'md, html')],
|
||||
];
|
||||
return [['--format <format>', _('Source format: %s', ['auto'].concat(formats).join(', '))], ['-f, --force', _('Do not ask for confirmation.')]];
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
const folder = await app().loadItem(BaseModel.TYPE_FOLDER, args.notebook);
|
||||
let folder = await app().loadItem(BaseModel.TYPE_FOLDER, args.notebook);
|
||||
|
||||
if (args.notebook && !folder) throw new Error(_('Cannot find "%s".', args.notebook));
|
||||
|
||||
@@ -43,7 +39,7 @@ class Command extends BaseCommand {
|
||||
// onProgress/onError supported by Enex import only
|
||||
|
||||
importOptions.onProgress = progressState => {
|
||||
const line = [];
|
||||
let line = [];
|
||||
line.push(_('Found: %d.', progressState.loaded));
|
||||
line.push(_('Created: %d.', progressState.created));
|
||||
if (progressState.updated) line.push(_('Updated: %d.', progressState.updated));
|
||||
@@ -55,15 +51,15 @@ class Command extends BaseCommand {
|
||||
};
|
||||
|
||||
importOptions.onError = error => {
|
||||
const s = error.trace ? error.trace : error.toString();
|
||||
let s = error.trace ? error.trace : error.toString();
|
||||
this.stdout(s);
|
||||
};
|
||||
|
||||
if (args.options.outputFormat) importOptions.outputFormat = args.options.outputFormat;
|
||||
|
||||
app().gui().showConsole();
|
||||
app()
|
||||
.gui()
|
||||
.showConsole();
|
||||
this.stdout(_('Importing notes...'));
|
||||
const service = InteropService.instance();
|
||||
const service = new InteropService();
|
||||
const result = await service.import(importOptions);
|
||||
result.warnings.map(w => this.stdout(w));
|
||||
cliUtils.redrawDone();
|
||||
|
@@ -1,9 +1,9 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const { sprintf } = require('sprintf-js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
@@ -19,26 +19,19 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
enabled() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
options() {
|
||||
return [
|
||||
['-n, --limit <num>', _('Displays only the first top <num> notes.')],
|
||||
['-s, --sort <field>', _('Sorts the item by <field> (eg. title, updated_time, created_time).')],
|
||||
['-r, --reverse', _('Reverses the sorting order.')],
|
||||
['-t, --type <type>', _('Displays only the items of the specific type(s). Can be `n` for notes, `t` for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the to-dos, while `-ttd` would display notes and to-dos.')],
|
||||
['-f, --format <format>', _('Either "text" or "json"')],
|
||||
['-l, --long', _('Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, TODO_CHECKED (for to-dos), TITLE')],
|
||||
];
|
||||
return [['-n, --limit <num>', _('Displays only the first top <num> notes.')], ['-s, --sort <field>', _('Sorts the item by <field> (eg. title, updated_time, created_time).')], ['-r, --reverse', _('Reverses the sorting order.')], ['-t, --type <type>', _('Displays only the items of the specific type(s). Can be `n` for notes, `t` for to-dos, or `nt` for notes and to-dos (eg. `-tt` would display only the to-dos, while `-ttd` would display notes and to-dos.')], ['-f, --format <format>', _('Either "text" or "json"')], ['-l, --long', _('Use long list format. Format is ID, NOTE_COUNT (for notebook), DATE, TODO_CHECKED (for to-dos), TITLE')]];
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
const pattern = args['note-pattern'];
|
||||
let pattern = args['note-pattern'];
|
||||
let items = [];
|
||||
const options = args.options;
|
||||
let options = args.options;
|
||||
|
||||
const queryOptions = {};
|
||||
let queryOptions = {};
|
||||
if (options.limit) queryOptions.limit = options.limit;
|
||||
if (options.sort) {
|
||||
queryOptions.orderBy = options.sort;
|
||||
@@ -70,19 +63,19 @@ class Command extends BaseCommand {
|
||||
} else {
|
||||
let hasTodos = false;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
let item = items[i];
|
||||
if (item.is_todo) {
|
||||
hasTodos = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const seenTitles = [];
|
||||
const rows = [];
|
||||
let seenTitles = [];
|
||||
let rows = [];
|
||||
let shortIdShown = false;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
const row = [];
|
||||
let item = items[i];
|
||||
let row = [];
|
||||
|
||||
if (options.long) {
|
||||
row.push(BaseModel.shortId(item.id));
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
@@ -13,7 +13,7 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
const folder = await Folder.save({ title: args['new-notebook'] }, { userSideValidation: true });
|
||||
let folder = await Folder.save({ title: args['new-notebook'] }, { userSideValidation: true });
|
||||
app().switchCurrentFolder(folder);
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
|
||||
@@ -26,7 +26,7 @@ class Command extends BaseCommand {
|
||||
|
||||
const ok = force ? true : await this.prompt(notes.length > 1 ? _('%d notes match this pattern. Delete them?', notes.length) : _('Delete note?'), { booleanAnswerDefault: 'n' });
|
||||
if (!ok) return;
|
||||
const ids = notes.map(n => n.id);
|
||||
let ids = notes.map(n => n.id);
|
||||
await Note.batchDelete(ids);
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Folder = require('lib/models/Folder.js');
|
||||
const uuid = require('lib/uuid').default;
|
||||
const { uuid } = require('lib/uuid.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
@@ -18,8 +18,8 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
const pattern = args['pattern'];
|
||||
const folderTitle = args['notebook'];
|
||||
let pattern = args['pattern'];
|
||||
let folderTitle = args['notebook'];
|
||||
|
||||
let folder = null;
|
||||
if (folderTitle) {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Logger = require('lib/Logger').default;
|
||||
const shim = require('lib/shim').default;
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const { shim } = require('lib/shim');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
|
||||
@@ -18,8 +18,7 @@ class Command extends BaseCommand {
|
||||
const command = args.command;
|
||||
|
||||
const ClipperServer = require('lib/ClipperServer');
|
||||
ClipperServer.instance().initialize();
|
||||
const stdoutFn = (...s) => this.stdout(s.join(' '));
|
||||
const stdoutFn = (s) => this.stdout(s);
|
||||
const clipperLogger = new Logger();
|
||||
clipperLogger.addTarget('file', { path: `${Setting.value('profileDir')}/log-clipper.txt` });
|
||||
clipperLogger.addTarget('console', { console: {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { Database } = require('lib/database.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
@@ -23,18 +23,18 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
const title = args['note'];
|
||||
const propName = args['name'];
|
||||
let title = args['note'];
|
||||
let propName = args['name'];
|
||||
let propValue = args['value'];
|
||||
if (!propValue) propValue = '';
|
||||
|
||||
const notes = await app().loadItems(BaseModel.TYPE_NOTE, title);
|
||||
let notes = await app().loadItems(BaseModel.TYPE_NOTE, title);
|
||||
if (!notes.length) throw new Error(_('Cannot find "%s".', title));
|
||||
|
||||
for (let i = 0; i < notes.length; i++) {
|
||||
this.encryptionCheck(notes[i]);
|
||||
|
||||
const newNote = {
|
||||
let newNote = {
|
||||
id: notes[i].id,
|
||||
type_: notes[i].type_,
|
||||
};
|
||||
|
@@ -1,7 +1,7 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { _ } = require('lib/locale');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { ReportService } = require('lib/services/report.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
@@ -14,39 +14,30 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
async action() {
|
||||
const service = new ReportService();
|
||||
const report = await service.status(Setting.value('sync.target'));
|
||||
let service = new ReportService();
|
||||
let report = await service.status(Setting.value('sync.target'));
|
||||
|
||||
for (let i = 0; i < report.length; i++) {
|
||||
const section = report[i];
|
||||
let section = report[i];
|
||||
|
||||
if (i > 0) this.stdout('');
|
||||
|
||||
this.stdout(`# ${section.title}`);
|
||||
this.stdout('');
|
||||
|
||||
let canRetryType = '';
|
||||
|
||||
for (const n in section.body) {
|
||||
for (let n in section.body) {
|
||||
if (!section.body.hasOwnProperty(n)) continue;
|
||||
const item = section.body[n];
|
||||
|
||||
if (typeof item === 'object') {
|
||||
canRetryType = item.canRetryType;
|
||||
this.stdout(item.text);
|
||||
} else {
|
||||
this.stdout(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (canRetryType === 'e2ee') {
|
||||
this.stdout('');
|
||||
this.stdout(_('To retry decryption of these items. Run `e2ee decrypt --retry-failed-items`'));
|
||||
let line = section.body[n];
|
||||
this.stdout(line);
|
||||
}
|
||||
}
|
||||
|
||||
app().gui().showConsole();
|
||||
app().gui().maximizeConsole();
|
||||
app()
|
||||
.gui()
|
||||
.showConsole();
|
||||
app()
|
||||
.gui()
|
||||
.maximizeConsole();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,17 +1,16 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { OneDriveApiNodeUtils } = require('lib/onedrive-api-node-utils.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const ResourceFetcher = require('lib/services/ResourceFetcher');
|
||||
const Synchronizer = require('lib/Synchronizer').default;
|
||||
const { Synchronizer } = require('lib/synchronizer.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const { cliUtils } = require('./cli-utils.js');
|
||||
const md5 = require('md5');
|
||||
const locker = require('proper-lockfile');
|
||||
const fs = require('fs-extra');
|
||||
const SyncTargetRegistry = require('lib/SyncTargetRegistry');
|
||||
const MigrationHandler = require('lib/services/synchronizer/MigrationHandler').default;
|
||||
|
||||
class Command extends BaseCommand {
|
||||
constructor() {
|
||||
@@ -30,10 +29,7 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
options() {
|
||||
return [
|
||||
['--target <target>', _('Sync to provided target (defaults to sync.target config value)')],
|
||||
['--upgrade', _('Upgrade the sync target to the latest version.')],
|
||||
];
|
||||
return [['--target <target>', _('Sync to provided target (defaults to sync.target config value)')]];
|
||||
}
|
||||
|
||||
static lockFile(filePath) {
|
||||
@@ -152,8 +148,12 @@ class Command extends BaseCommand {
|
||||
const syncTarget = reg.syncTarget(this.syncTargetId_);
|
||||
|
||||
if (!(await syncTarget.isAuthenticated())) {
|
||||
app().gui().showConsole();
|
||||
app().gui().maximizeConsole();
|
||||
app()
|
||||
.gui()
|
||||
.showConsole();
|
||||
app()
|
||||
.gui()
|
||||
.maximizeConsole();
|
||||
|
||||
const authDone = await this.doAuth();
|
||||
if (!authDone) return cleanUp();
|
||||
@@ -161,9 +161,9 @@ class Command extends BaseCommand {
|
||||
|
||||
const sync = await syncTarget.synchronizer();
|
||||
|
||||
const options = {
|
||||
let options = {
|
||||
onProgress: report => {
|
||||
const lines = Synchronizer.reportToLines(report);
|
||||
let lines = Synchronizer.reportToLines(report);
|
||||
if (lines.length) cliUtils.redraw(lines.join(' '));
|
||||
},
|
||||
onMessage: msg => {
|
||||
@@ -174,35 +174,7 @@ class Command extends BaseCommand {
|
||||
|
||||
this.stdout(_('Synchronisation target: %s (%s)', Setting.enumOptionLabel('sync.target', this.syncTargetId_), this.syncTargetId_));
|
||||
|
||||
if (!sync) throw new Error(_('Cannot initialise synchroniser.'));
|
||||
|
||||
if (args.options.upgrade) {
|
||||
let migrationError = null;
|
||||
|
||||
try {
|
||||
const migrationHandler = new MigrationHandler(
|
||||
sync.api(),
|
||||
sync.lockHandler(),
|
||||
Setting.value('appType'),
|
||||
Setting.value('clientId')
|
||||
);
|
||||
|
||||
migrationHandler.setLogger(cliUtils.stdoutLogger(this.stdout.bind(this)));
|
||||
|
||||
await migrationHandler.upgrade();
|
||||
} catch (error) {
|
||||
migrationError = error;
|
||||
}
|
||||
|
||||
if (!migrationError) {
|
||||
Setting.setValue('sync.upgradeState', Setting.SYNC_UPGRADE_STATE_IDLE);
|
||||
await Setting.saveAll();
|
||||
}
|
||||
|
||||
if (migrationError) throw migrationError;
|
||||
|
||||
return cleanUp();
|
||||
}
|
||||
if (!sync) throw new Error(_('Cannot initialize synchroniser.'));
|
||||
|
||||
this.stdout(_('Starting synchronisation...'));
|
||||
|
||||
@@ -213,7 +185,7 @@ class Command extends BaseCommand {
|
||||
options.context = context;
|
||||
|
||||
try {
|
||||
const newContext = await sync.start(options);
|
||||
let newContext = await sync.start(options);
|
||||
Setting.setValue(contextKey, JSON.stringify(newContext));
|
||||
} catch (error) {
|
||||
if (error.code == 'alreadyStarted') {
|
||||
@@ -238,12 +210,6 @@ class Command extends BaseCommand {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (Setting.value('sync.upgradeState') > Setting.SYNC_UPGRADE_STATE_IDLE) {
|
||||
this.stdout(`/!\\ ${_('Sync target must be upgraded! Run `%s` to proceed.', 'sync --upgrade')}`);
|
||||
app().gui().showConsole();
|
||||
app().gui().maximizeConsole();
|
||||
}
|
||||
|
||||
cleanUp();
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
@@ -20,7 +20,7 @@ class Command extends BaseCommand {
|
||||
|
||||
async action(args) {
|
||||
let tag = null;
|
||||
const options = args.options;
|
||||
let options = args.options;
|
||||
|
||||
if (args.tag) tag = await app().loadItem(BaseModel.TYPE_TAG, args.tag);
|
||||
let notes = [];
|
||||
@@ -46,7 +46,7 @@ class Command extends BaseCommand {
|
||||
}
|
||||
} else if (command == 'list') {
|
||||
if (tag) {
|
||||
const notes = await Tag.notes(tag.id);
|
||||
let notes = await Tag.notes(tag.id);
|
||||
notes.map(note => {
|
||||
let line = '';
|
||||
if (options.long) {
|
||||
@@ -70,7 +70,7 @@ class Command extends BaseCommand {
|
||||
this.stdout(line);
|
||||
});
|
||||
} else {
|
||||
const tags = await Tag.all();
|
||||
let tags = await Tag.all();
|
||||
tags.map(tag => {
|
||||
this.stdout(tag.title);
|
||||
});
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const Note = require('lib/models/Note.js');
|
||||
const { time } = require('lib/time-utils.js');
|
||||
|
@@ -1,5 +1,5 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
const CommandDone = require('./command-done.js');
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const { app } = require('./app.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
@@ -17,7 +17,7 @@ class Command extends BaseCommand {
|
||||
}
|
||||
|
||||
async action(args) {
|
||||
const folder = await app().loadItem(BaseModel.TYPE_FOLDER, args['notebook']);
|
||||
let folder = await app().loadItem(BaseModel.TYPE_FOLDER, args['notebook']);
|
||||
if (!folder) throw new Error(_('Cannot find "%s".', args['notebook']));
|
||||
app().switchCurrentFolder(folder);
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { BaseCommand } = require('./base-command.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { _ } = require('lib/locale');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
class Command extends BaseCommand {
|
||||
usage() {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { time } = require('lib/time-utils.js');
|
||||
const Logger = require('lib/Logger').default;
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const { dirname } = require('lib/path-utils.js');
|
||||
const { FsDriverNode } = require('./fs-driver-node.js');
|
||||
@@ -12,7 +12,7 @@ const fs = require('fs-extra');
|
||||
const baseDir = `${dirname(__dirname)}/tests/fuzzing`;
|
||||
const syncDir = `${baseDir}/sync`;
|
||||
const joplinAppPath = `${__dirname}/main.js`;
|
||||
const syncDurations = [];
|
||||
let syncDurations = [];
|
||||
|
||||
const fsDriver = new FsDriverNode();
|
||||
Logger.fsDriver_ = fsDriver;
|
||||
@@ -34,10 +34,10 @@ function createClient(id) {
|
||||
}
|
||||
|
||||
async function createClients() {
|
||||
const output = [];
|
||||
const promises = [];
|
||||
let output = [];
|
||||
let promises = [];
|
||||
for (let clientId = 0; clientId < 2; clientId++) {
|
||||
const client = createClient(clientId);
|
||||
let client = createClient(clientId);
|
||||
promises.push(fs.remove(client.profileDir));
|
||||
promises.push(
|
||||
execCommand(client, 'config sync.target 2').then(() => {
|
||||
@@ -2064,8 +2064,8 @@ function randomWord() {
|
||||
}
|
||||
|
||||
function execCommand(client, command, options = {}) {
|
||||
const exePath = `node ${joplinAppPath}`;
|
||||
const cmd = `${exePath} --update-geolocation-disabled --env dev --log-level debug --profile ${client.profileDir} ${command}`;
|
||||
let exePath = `node ${joplinAppPath}`;
|
||||
let cmd = `${exePath} --update-geolocation-disabled --env dev --log-level debug --profile ${client.profileDir} ${command}`;
|
||||
logger.info(`${client.id}: ${command}`);
|
||||
|
||||
if (options.killAfter) {
|
||||
@@ -2073,7 +2073,7 @@ function execCommand(client, command, options = {}) {
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const childProcess = exec(cmd, (error, stdout, stderr) => {
|
||||
let childProcess = exec(cmd, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
if (error.signal == 'SIGTERM') {
|
||||
resolve('Process was killed');
|
||||
@@ -2096,7 +2096,7 @@ function execCommand(client, command, options = {}) {
|
||||
}
|
||||
|
||||
async function clientItems(client) {
|
||||
const itemsJson = await execCommand(client, 'dump');
|
||||
let itemsJson = await execCommand(client, 'dump');
|
||||
try {
|
||||
return JSON.parse(itemsJson);
|
||||
} catch (error) {
|
||||
@@ -2105,7 +2105,7 @@ async function clientItems(client) {
|
||||
}
|
||||
|
||||
function randomTag(items) {
|
||||
const tags = [];
|
||||
let tags = [];
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].type_ != 5) continue;
|
||||
tags.push(items[i]);
|
||||
@@ -2115,7 +2115,7 @@ function randomTag(items) {
|
||||
}
|
||||
|
||||
function randomNote(items) {
|
||||
const notes = [];
|
||||
let notes = [];
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].type_ != 1) continue;
|
||||
notes.push(items[i]);
|
||||
@@ -2125,14 +2125,14 @@ function randomNote(items) {
|
||||
}
|
||||
|
||||
async function execRandomCommand(client) {
|
||||
const possibleCommands = [
|
||||
let possibleCommands = [
|
||||
['mkbook {word}', 40], // CREATE FOLDER
|
||||
['mknote {word}', 70], // CREATE NOTE
|
||||
[
|
||||
async () => {
|
||||
// DELETE RANDOM ITEM
|
||||
const items = await clientItems(client);
|
||||
const item = randomElement(items);
|
||||
let items = await clientItems(client);
|
||||
let item = randomElement(items);
|
||||
if (!item) return;
|
||||
|
||||
if (item.type_ == 1) {
|
||||
@@ -2150,8 +2150,8 @@ async function execRandomCommand(client) {
|
||||
[
|
||||
async () => {
|
||||
// SYNC
|
||||
const avgSyncDuration = averageSyncDuration();
|
||||
const options = {};
|
||||
let avgSyncDuration = averageSyncDuration();
|
||||
let options = {};
|
||||
if (!isNaN(avgSyncDuration)) {
|
||||
if (Math.random() >= 0.5) {
|
||||
options.killAfter = avgSyncDuration * Math.random();
|
||||
@@ -2164,8 +2164,8 @@ async function execRandomCommand(client) {
|
||||
[
|
||||
async () => {
|
||||
// UPDATE RANDOM ITEM
|
||||
const items = await clientItems(client);
|
||||
const item = randomNote(items);
|
||||
let items = await clientItems(client);
|
||||
let item = randomNote(items);
|
||||
if (!item) return;
|
||||
|
||||
return execCommand(client, `set ${item.id} title "${randomWord()}"`);
|
||||
@@ -2175,12 +2175,12 @@ async function execRandomCommand(client) {
|
||||
[
|
||||
async () => {
|
||||
// ADD TAG
|
||||
const items = await clientItems(client);
|
||||
const note = randomNote(items);
|
||||
let items = await clientItems(client);
|
||||
let note = randomNote(items);
|
||||
if (!note) return;
|
||||
|
||||
const tag = randomTag(items);
|
||||
const tagTitle = !tag || Math.random() >= 0.9 ? `tag-${randomWord()}` : tag.title;
|
||||
let tag = randomTag(items);
|
||||
let tagTitle = !tag || Math.random() >= 0.9 ? `tag-${randomWord()}` : tag.title;
|
||||
|
||||
return execCommand(client, `tag add ${tagTitle} ${note.id}`);
|
||||
},
|
||||
@@ -2191,7 +2191,7 @@ async function execRandomCommand(client) {
|
||||
let cmd = null;
|
||||
while (true) {
|
||||
cmd = randomElement(possibleCommands);
|
||||
const r = 1 + Math.floor(Math.random() * 100);
|
||||
let r = 1 + Math.floor(Math.random() * 100);
|
||||
if (r <= cmd[1]) break;
|
||||
}
|
||||
|
||||
@@ -2210,7 +2210,7 @@ function averageSyncDuration() {
|
||||
}
|
||||
|
||||
function randomNextCheckTime() {
|
||||
const output = time.unixMs() + 1000 + Math.random() * 1000 * 120;
|
||||
let output = time.unixMs() + 1000 + Math.random() * 1000 * 120;
|
||||
logger.info(`Next sync check: ${time.unixMsToIso(output)} (${Math.round((output - time.unixMs()) / 1000)} sec.)`);
|
||||
return output;
|
||||
}
|
||||
@@ -2223,11 +2223,11 @@ function findItem(items, itemId) {
|
||||
}
|
||||
|
||||
function compareItems(item1, item2) {
|
||||
const output = [];
|
||||
for (const n in item1) {
|
||||
let output = [];
|
||||
for (let n in item1) {
|
||||
if (!item1.hasOwnProperty(n)) continue;
|
||||
const p1 = item1[n];
|
||||
const p2 = item2[n];
|
||||
let p1 = item1[n];
|
||||
let p2 = item2[n];
|
||||
|
||||
if (n == 'notes_') {
|
||||
p1.sort();
|
||||
@@ -2243,13 +2243,13 @@ function compareItems(item1, item2) {
|
||||
}
|
||||
|
||||
function findMissingItems_(items1, items2) {
|
||||
const output = [];
|
||||
let output = [];
|
||||
|
||||
for (let i = 0; i < items1.length; i++) {
|
||||
const item1 = items1[i];
|
||||
let item1 = items1[i];
|
||||
let found = false;
|
||||
for (let j = 0; j < items2.length; j++) {
|
||||
const item2 = items2[j];
|
||||
let item2 = items2[j];
|
||||
if (item1.id == item2.id) {
|
||||
found = true;
|
||||
break;
|
||||
@@ -2269,33 +2269,33 @@ function findMissingItems(items1, items2) {
|
||||
}
|
||||
|
||||
async function compareClientItems(clientItems) {
|
||||
const itemCounts = [];
|
||||
let itemCounts = [];
|
||||
for (let i = 0; i < clientItems.length; i++) {
|
||||
const items = clientItems[i];
|
||||
let items = clientItems[i];
|
||||
itemCounts.push(items.length);
|
||||
}
|
||||
logger.info(`Item count: ${itemCounts.join(', ')}`);
|
||||
|
||||
const missingItems = findMissingItems(clientItems[0], clientItems[1]);
|
||||
let missingItems = findMissingItems(clientItems[0], clientItems[1]);
|
||||
if (missingItems[0].length || missingItems[1].length) {
|
||||
logger.error('Items are different');
|
||||
logger.error(missingItems);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const differences = [];
|
||||
const items = clientItems[0];
|
||||
let differences = [];
|
||||
let items = clientItems[0];
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item1 = items[i];
|
||||
let item1 = items[i];
|
||||
for (let clientId = 1; clientId < clientItems.length; clientId++) {
|
||||
const item2 = findItem(clientItems[clientId], item1.id);
|
||||
let item2 = findItem(clientItems[clientId], item1.id);
|
||||
if (!item2) {
|
||||
logger.error(`Item not found on client ${clientId}:`);
|
||||
logger.error(item1);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const diff = compareItems(item1, item2);
|
||||
let diff = compareItems(item1, item2);
|
||||
if (diff.length) {
|
||||
differences.push({
|
||||
item1: JSON.stringify(item1),
|
||||
@@ -2315,7 +2315,7 @@ async function compareClientItems(clientItems) {
|
||||
async function main() {
|
||||
await fs.remove(syncDir);
|
||||
|
||||
const clients = await createClients();
|
||||
let clients = await createClients();
|
||||
let clientId = 0;
|
||||
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
@@ -2348,7 +2348,7 @@ async function main() {
|
||||
|
||||
if (state == 'syncCheck') {
|
||||
state = 'waitForSyncCheck';
|
||||
const clientItems = [];
|
||||
let clientItems = [];
|
||||
// Up to 3 sync operations must be performed by each clients in order for them
|
||||
// to be perfectly in sync - in order for each items to send their changes
|
||||
// and get those from the other clients, and to also get changes that are
|
||||
@@ -2356,12 +2356,12 @@ async function main() {
|
||||
// with another one).
|
||||
for (let loopCount = 0; loopCount < 3; loopCount++) {
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
const beforeTime = time.unixMs();
|
||||
let beforeTime = time.unixMs();
|
||||
await execCommand(clients[i], 'sync');
|
||||
syncDurations.push(time.unixMs() - beforeTime);
|
||||
if (syncDurations.length > 20) syncDurations.splice(0, 1);
|
||||
if (loopCount === 2) {
|
||||
const dump = await execCommand(clients[i], 'dump');
|
||||
let dump = await execCommand(clients[i], 'dump');
|
||||
clientItems[i] = JSON.parse(dump);
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@ const Folder = require('lib/models/Folder.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const BaseModel = require('lib/BaseModel.js');
|
||||
const ListWidget = require('tkwidgets/ListWidget.js');
|
||||
const _ = require('lib/locale')._;
|
||||
const _ = require('lib/locale.js')._;
|
||||
|
||||
class FolderListWidget extends ListWidget {
|
||||
constructor() {
|
||||
@@ -20,7 +20,7 @@ class FolderListWidget extends ListWidget {
|
||||
this.trimItemTitle = false;
|
||||
|
||||
this.itemRenderer = item => {
|
||||
const output = [];
|
||||
let output = [];
|
||||
if (item === '-') {
|
||||
output.push('-'.repeat(this.innerWidth));
|
||||
} else if (item.type_ === Folder.modelType()) {
|
||||
@@ -40,7 +40,7 @@ class FolderListWidget extends ListWidget {
|
||||
let output = 0;
|
||||
while (true) {
|
||||
const folder = BaseModel.byId(folders, folderId);
|
||||
if (!folder || !folder.parent_id) return output;
|
||||
if (!folder.parent_id) return output;
|
||||
output++;
|
||||
folderId = folder.parent_id;
|
||||
}
|
||||
@@ -121,7 +121,7 @@ class FolderListWidget extends ListWidget {
|
||||
|
||||
folderHasChildren_(folders, folderId) {
|
||||
for (let i = 0; i < folders.length; i++) {
|
||||
const folder = folders[i];
|
||||
let folder = folders[i];
|
||||
if (folder.parent_id === folderId) return true;
|
||||
}
|
||||
return false;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const Note = require('lib/models/Note.js');
|
||||
const TextWidget = require('tkwidgets/TextWidget.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
class NoteWidget extends TextWidget {
|
||||
constructor() {
|
||||
@@ -46,8 +46,6 @@ class NoteWidget extends TextWidget {
|
||||
|
||||
if (this.note_ && this.note_.encryption_applied) {
|
||||
this.text = _('One or more items are currently encrypted and you may need to supply a master password. To do so please type `e2ee decrypt`. If you have already supplied the password, the encrypted items are being decrypted in the background and will be available soon.');
|
||||
this.text += '\n\n';
|
||||
this.text += _('You may also type `status` for more information.');
|
||||
} else {
|
||||
this.text = this.note_ ? `${this.note_.title}\n\n${this.note_.body}` : '';
|
||||
}
|
||||
|
@@ -106,7 +106,7 @@ class StatusBarWidget extends BaseWidget {
|
||||
|
||||
const isSecurePrompt = !!this.promptState_.secure;
|
||||
|
||||
const options = {
|
||||
let options = {
|
||||
cancelable: true,
|
||||
history: this.history,
|
||||
default: this.promptState_.initialText,
|
||||
|
@@ -1,16 +1,16 @@
|
||||
const { wrap } = require('lib/string-utils.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { _ } = require('lib/locale');
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const { _ } = require('lib/locale.js');
|
||||
|
||||
const MAX_WIDTH = 78;
|
||||
const INDENT = ' ';
|
||||
|
||||
function renderTwoColumnData(options, baseIndent, width) {
|
||||
const output = [];
|
||||
let output = [];
|
||||
const optionColWidth = getOptionColWidth(options);
|
||||
|
||||
for (let i = 0; i < options.length; i++) {
|
||||
const option = options[i];
|
||||
let option = options[i];
|
||||
const flag = option[0];
|
||||
const indent = baseIndent + INDENT + ' '.repeat(optionColWidth + 2);
|
||||
|
||||
@@ -28,7 +28,7 @@ function renderCommandHelp(cmd, width = null) {
|
||||
|
||||
const baseIndent = '';
|
||||
|
||||
const output = [];
|
||||
let output = [];
|
||||
output.push(baseIndent + cmd.usage());
|
||||
output.push('');
|
||||
output.push(wrap(cmd.description(), baseIndent + INDENT, width));
|
||||
@@ -42,7 +42,7 @@ function renderCommandHelp(cmd, width = null) {
|
||||
|
||||
if (cmd.name() === 'config') {
|
||||
const renderMetadata = md => {
|
||||
const desc = [];
|
||||
let desc = [];
|
||||
|
||||
if (md.label) {
|
||||
let label = md.label();
|
||||
@@ -77,7 +77,7 @@ function renderCommandHelp(cmd, width = null) {
|
||||
output.push(_('Possible keys/values:'));
|
||||
output.push('');
|
||||
|
||||
const keysValues = [];
|
||||
let keysValues = [];
|
||||
const keys = Setting.keys(true, 'cli');
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
if (keysValues.length) keysValues.push(['', '']);
|
||||
|
@@ -21,17 +21,14 @@ const Note = require('lib/models/Note.js');
|
||||
const Tag = require('lib/models/Tag.js');
|
||||
const NoteTag = require('lib/models/NoteTag.js');
|
||||
const MasterKey = require('lib/models/MasterKey');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const Setting = require('lib/models/Setting.js');
|
||||
const Revision = require('lib/models/Revision.js');
|
||||
const Logger = require('lib/Logger').default;
|
||||
const { Logger } = require('lib/logger.js');
|
||||
const { FsDriverNode } = require('lib/fs-driver-node.js');
|
||||
const { shimInit } = require('lib/shim-init-node.js');
|
||||
const { _ } = require('lib/locale');
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { FileApiDriverLocal } = require('lib/file-api-driver-local.js');
|
||||
const EncryptionService = require('lib/services/EncryptionService');
|
||||
const envFromArgs = require('lib/envFromArgs');
|
||||
|
||||
const env = envFromArgs(process.argv);
|
||||
|
||||
const fsDriver = new FsDriverNode();
|
||||
Logger.fsDriver_ = fsDriver;
|
||||
@@ -49,7 +46,7 @@ BaseItem.loadClass('NoteTag', NoteTag);
|
||||
BaseItem.loadClass('MasterKey', MasterKey);
|
||||
BaseItem.loadClass('Revision', Revision);
|
||||
|
||||
Setting.setConstant('appId', `net.cozic.joplin${env === 'dev' ? 'dev' : ''}-cli`);
|
||||
Setting.setConstant('appId', 'net.cozic.joplin-cli');
|
||||
Setting.setConstant('appType', 'cli');
|
||||
|
||||
shimInit();
|
||||
@@ -57,7 +54,7 @@ shimInit();
|
||||
const application = app();
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
const rl = require('readline').createInterface({
|
||||
var rl = require('readline').createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
|
@@ -1,68 +0,0 @@
|
||||
import * as vm from 'vm';
|
||||
import Plugin from 'lib/services/plugins/Plugin';
|
||||
import sandboxProxy from 'lib/services/plugins/sandboxProxy';
|
||||
import BasePluginRunner from 'lib/services/plugins/BasePluginRunner';
|
||||
import executeSandboxCall from 'lib/services/plugins/utils/executeSandboxCall';
|
||||
import Global from 'lib/services/plugins/api/Global';
|
||||
import mapEventHandlersToIds, { EventHandlers } from 'lib/services/plugins/utils/mapEventHandlersToIds';
|
||||
|
||||
function createConsoleWrapper(pluginId:string) {
|
||||
const wrapper:any = {};
|
||||
|
||||
for (const n in console) {
|
||||
if (!console.hasOwnProperty(n)) continue;
|
||||
wrapper[n] = (...args:any[]) => {
|
||||
const newArgs = args.slice();
|
||||
newArgs.splice(0, 0, `Plugin "${pluginId}":`);
|
||||
return (console as any)[n](...newArgs);
|
||||
};
|
||||
}
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
// The CLI plugin runner is more complex than it needs to be because it more or less emulates
|
||||
// how it would work in a multi-process architecture, as in the desktop app (and probably how
|
||||
// it would work in the mobile app too). This is mainly to allow doing integration testing.
|
||||
//
|
||||
// For example, all plugin calls go through a proxy, however they could made directly since
|
||||
// the plugin script is running within the same process as the main app.
|
||||
|
||||
export default class PluginRunner extends BasePluginRunner {
|
||||
|
||||
private eventHandlers_:EventHandlers = {};
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.eventHandler = this.eventHandler.bind(this);
|
||||
}
|
||||
|
||||
private async eventHandler(eventHandlerId:string, args:any[]) {
|
||||
const cb = this.eventHandlers_[eventHandlerId];
|
||||
return cb(...args);
|
||||
}
|
||||
|
||||
private newSandboxProxy(pluginId:string, sandbox:Global) {
|
||||
const target = async (path:string, args:any[]) => {
|
||||
return executeSandboxCall(pluginId, sandbox, `joplin.${path}`, mapEventHandlersToIds(args, this.eventHandlers_), this.eventHandler);
|
||||
};
|
||||
|
||||
return {
|
||||
joplin: sandboxProxy(target),
|
||||
console: createConsoleWrapper(pluginId),
|
||||
};
|
||||
}
|
||||
|
||||
async run(plugin:Plugin, sandbox:Global) {
|
||||
const vmSandbox = vm.createContext(this.newSandboxProxy(plugin.id, sandbox));
|
||||
|
||||
try {
|
||||
vm.runInContext(plugin.scriptText, vmSandbox);
|
||||
} catch (error) {
|
||||
this.logger().error(`In plugin ${plugin.id}:`, error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
npm run build && NODE_PATH=build node build/build-doc.js
|
||||
./build.sh && NODE_PATH=build node build/build-doc.js
|
16
CliClient/build.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/bash
|
||||
|
||||
ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
BUILD_DIR="$ROOT_DIR/build"
|
||||
|
||||
rsync -a --exclude "node_modules/" "$ROOT_DIR/app/" "$BUILD_DIR/"
|
||||
rsync -a --delete "$ROOT_DIR/../ReactNativeClient/lib/" "$BUILD_DIR/lib/"
|
||||
rsync -a --delete "$ROOT_DIR/../ReactNativeClient/locales/" "$BUILD_DIR/locales/"
|
||||
cp "$ROOT_DIR/package.json" "$BUILD_DIR"
|
||||
|
||||
# Don't add TypeScript here or make it silent as output of Cli app must be clean
|
||||
# cd $ROOT_DIR/..
|
||||
# npm run tsc
|
||||
# cd $ROOT_DIR
|
||||
|
||||
chmod 755 "$BUILD_DIR/main.js"
|
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
npm run build && NODE_PATH="build/" node build/cli-integration-tests.js
|
||||
./build.sh && NODE_PATH="build/" node build/cli-integration-tests.js
|
@@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
npm run build && NODE_PATH="build/" node build/fuzzing.js
|
||||
./build.sh && NODE_PATH="build/" node build/fuzzing.js
|
@@ -1,73 +0,0 @@
|
||||
const gulp = require('gulp');
|
||||
const fs = require('fs-extra');
|
||||
const utils = require('../Tools/gulp/utils');
|
||||
const tasks = {
|
||||
compileExtensions: {
|
||||
fn: require('../Tools/gulp/tasks/compileExtensions.js'),
|
||||
},
|
||||
copyLib: require('../Tools/gulp/tasks/copyLib'),
|
||||
tsc: require('../Tools/gulp/tasks/tsc'),
|
||||
updateIgnoredTypeScriptBuild: require('../Tools/gulp/tasks/updateIgnoredTypeScriptBuild'),
|
||||
};
|
||||
|
||||
tasks.prepareBuild = {
|
||||
fn: async () => {
|
||||
const buildDir = `${__dirname}/build`;
|
||||
await utils.copyDir(`${__dirname}/app`, buildDir, {
|
||||
excluded: ['node_modules'],
|
||||
});
|
||||
await utils.copyDir(`${__dirname}/locales-build`, `${buildDir}/locales`);
|
||||
await utils.copyDir(`${__dirname}/../patches`, `${buildDir}/patches`);
|
||||
await tasks.copyLib.fn();
|
||||
await utils.copyFile(`${__dirname}/package.json`, `${buildDir}/package.json`);
|
||||
await utils.copyFile(`${__dirname}/package-lock.json`, `${buildDir}/package-lock.json`);
|
||||
await utils.copyFile(`${__dirname}/gulpfile.js`, `${buildDir}/gulpfile.js`);
|
||||
|
||||
const packageRaw = await fs.readFile(`${buildDir}/package.json`);
|
||||
const package = JSON.parse(packageRaw.toString());
|
||||
package.scripts.postinstall = 'patch-package';
|
||||
await fs.writeFile(`${buildDir}/package.json`, JSON.stringify(package, null, 2), 'utf8');
|
||||
|
||||
fs.chmodSync(`${buildDir}/main.js`, 0o755);
|
||||
},
|
||||
};
|
||||
|
||||
tasks.prepareTestBuild = {
|
||||
fn: async () => {
|
||||
const testBuildDir = `${__dirname}/tests-build`;
|
||||
|
||||
await utils.copyDir(`${__dirname}/tests`, testBuildDir, {
|
||||
excluded: [
|
||||
'lib/',
|
||||
'locales/',
|
||||
'node_modules/',
|
||||
'*.ts',
|
||||
'*.tsx',
|
||||
],
|
||||
});
|
||||
|
||||
const rootDir = utils.rootDir();
|
||||
|
||||
await utils.copyDir(`${rootDir}/ReactNativeClient/lib`, `${testBuildDir}/lib`, {
|
||||
excluded: [
|
||||
`${rootDir}/ReactNativeClient/lib/joplin-renderer/node_modules`,
|
||||
],
|
||||
});
|
||||
await utils.copyDir(`${rootDir}/ReactNativeClient/locales`, `${testBuildDir}/locales`);
|
||||
await fs.mkdirp(`${testBuildDir}/data`);
|
||||
},
|
||||
};
|
||||
|
||||
utils.registerGulpTasks(gulp, tasks);
|
||||
|
||||
gulp.task('build', gulp.series([
|
||||
'prepareBuild',
|
||||
'compileExtensions',
|
||||
'copyLib',
|
||||
]));
|
||||
|
||||
gulp.task('buildTests', gulp.series([
|
||||
'prepareTestBuild',
|
||||
'compileExtensions',
|
||||
'copyLib',
|
||||
]));
|