From 9d3f12d0b7553060e428e7ace9f46b69b310e4d4 Mon Sep 17 00:00:00 2001 From: ADS Merger Date: Wed, 15 Jul 2020 23:51:18 +0000 Subject: [PATCH] Merge from vscode 1b314ab317fbff7d799b21754326b7d849889ceb --- .devcontainer/Dockerfile | 2 +- .devcontainer/README.md | 6 +- .devcontainer/devcontainer.json | 6 +- .vscode/extensions.json | 3 +- .vscode/launch.json | 1 + .vscode/notebooks/api.github-issues | 38 + .vscode/notebooks/inbox.github-issues | 10 +- .vscode/notebooks/my-work.github-issues | 2 +- .vscode/notebooks/verification.github-issues | 55 + .vscode/searches/es6.code-search | 25 +- .vscode/tasks.json | 53 +- .yarnrc | 2 +- build/gulpfile.vscode.js | 26 +- build/gulpfile.vscode.win32.js | 4 +- build/lib/compilation.js | 4 + build/lib/compilation.ts | 6 + build/lib/i18n.js | 7 +- build/lib/i18n.ts | 6 +- build/lib/optimize.js | 7 +- build/lib/optimize.ts | 7 +- build/npm/postinstall.js | 4 +- build/package.json | 4 +- build/win32/code.iss | 7 +- build/win32/i18n/Default.hu.isl | 366 +++++++ build/win32/i18n/Default.isl | 336 ------ build/win32/i18n/Default.ko.isl | 413 +++++--- build/win32/i18n/Default.zh-cn.isl | 603 ++++++----- build/win32/i18n/Default.zh-tw.isl | 553 +++++----- build/win32/i18n/messages.en.isl | 7 + build/yarn.lock | 16 +- cgmanifest.json | 14 +- .../extension-browser.webpack.config.js | 21 + .../extension.webpack.config.js | 2 +- extensions/extension-editing/package.json | 3 +- .../src/extensionEditingBrowserMain.ts | 21 + .../{extension.ts => extensionEditingMain.ts} | 0 extensions/git/package.json | 6 +- extensions/git/src/api/api1.ts | 82 +- extensions/git/src/api/extension.ts | 17 +- extensions/git/src/api/git.d.ts | 6 + extensions/git/src/commands.ts | 178 +--- extensions/git/src/git.ts | 7 +- extensions/git/src/main.ts | 30 +- extensions/git/src/model.ts | 18 +- extensions/git/src/pushError.ts | 12 + extensions/git/src/remoteSource.ts | 133 +++ extensions/git/src/repository.ts | 38 +- extensions/git/src/util.ts | 12 - extensions/git/yarn.lock | 16 +- .../github-authentication/src/extension.ts | 18 +- .../github-authentication/src/github.ts | 9 +- extensions/github-browser/package.json | 9 + extensions/github-browser/src/changeStore.ts | 40 +- extensions/github-browser/src/contextStore.ts | 35 +- extensions/github-browser/src/extension.ts | 63 +- extensions/github-browser/src/fs.ts | 24 +- extensions/github-browser/src/github/api.ts | 93 +- extensions/github-browser/src/github/fs.ts | 4 +- extensions/github-browser/src/iterables.ts | 5 +- extensions/github-browser/src/scm.ts | 23 +- extensions/github-browser/src/statusbar.ts | 99 ++ extensions/github/src/commands.ts | 7 +- extensions/github/src/extension.ts | 44 +- extensions/github/src/publish.ts | 84 +- extensions/github/src/pushErrorHandler.ts | 120 +++ extensions/github/src/typings/git.d.ts | 8 + extensions/github/src/util.ts | 24 + extensions/json/package.json | 6 +- .../syntaxes/markdown.tmLanguage.json | 16 +- .../test/colorize-results/test_md.json | 52 +- .../media/markdown.css | 32 +- .../markdown-language-features/package.json | 18 +- .../src/commands/openDocumentLink.ts | 72 +- .../src/extension.ts | 6 +- .../src/features/documentLinkProvider.ts | 63 +- .../src/features/preview.ts | 46 +- .../src/features/previewManager.ts | 17 +- .../src/markdownExtensions.ts | 2 +- .../src/test/documentLink.test.ts | 145 +++ .../src/test/documentLinkProvider.test.ts | 20 +- .../src/test/test-fixtures/marker.txt | 1 - .../src/test/util.ts | 8 + .../src/util/links.ts | 1 + .../test-workspace/a.md | 4 + .../test-workspace/b.md | 3 + .../test-workspace/sub/c.md | 6 + .../test-workspace/sub/d.md | 0 .../microsoft-authentication/src/AADHelper.ts | 9 +- .../microsoft-authentication/src/extension.ts | 17 +- extensions/package.json | 2 +- .../theme-defaults/themes/hc_black.json | 8 +- .../theme-defaults/themes/light_defaults.json | 5 +- .../vscode-web-playground/src/exampleFiles.ts | 8 +- extensions/vscode-web-playground/src/memfs.ts | 15 +- extensions/xml/package.json | 4 +- extensions/yarn.lock | 8 +- package.json | 20 +- remote/package.json | 8 +- remote/web/package.json | 6 +- remote/web/yarn.lock | 24 +- remote/yarn.lock | 32 +- resources/serverless/code-web.js | 295 ++++-- scripts/test-integration.bat | 5 +- scripts/test-integration.sh | 3 +- src/bootstrap-window.js | 50 +- src/main.js | 3 + src/sql/base/browser/ui/panel/panel.ts | 3 +- .../browser/connectionTreeActions.test.ts | 5 +- .../browser/accountDialog.ts | 12 +- .../bootstrap/browser/bootstrapService.ts | 3 +- .../notebook/browser/models/notebookModel.ts | 3 +- .../notebook/browser/notebookServiceImpl.ts | 3 +- .../services/query/common/queryManagement.ts | 3 +- src/vs/base/browser/markdownRenderer.ts | 9 +- src/vs/base/browser/ui/actionbar/actionbar.ts | 23 +- .../browser/ui/codicons/codicon/codicon.ttf | Bin 60140 -> 60600 bytes .../browser/ui/contextview/contextview.ts | 1 + src/vs/base/browser/ui/inputbox/inputBox.ts | 26 +- src/vs/base/browser/ui/list/listView.ts | 5 +- src/vs/base/browser/ui/list/listWidget.ts | 1 + src/vs/base/browser/ui/menu/menu.ts | 7 +- src/vs/base/browser/ui/menu/menubar.ts | 10 +- .../browser/ui/scrollbar/scrollableElement.ts | 17 +- src/vs/base/browser/ui/tree/abstractTree.ts | 11 +- src/vs/base/common/arrays.ts | 8 + src/vs/base/common/codicons.ts | 4 + src/vs/base/common/errors.ts | 9 + src/vs/base/common/fuzzyScorer.ts | 3 +- src/vs/base/common/htmlContent.ts | 6 +- src/vs/base/common/map.ts | 21 - src/vs/base/common/mime.ts | 29 - src/vs/base/common/performance.js | 17 +- src/vs/base/common/stream.ts | 2 +- src/vs/base/common/types.ts | 4 +- src/vs/base/common/uri.ts | 16 +- src/vs/base/node/processes.ts | 2 +- .../parts/contextmenu/common/contextmenu.ts | 3 +- .../contextmenu/electron-main/contextmenu.ts | 3 +- .../electron-sandbox/contextmenu.ts | 6 +- .../parts/quickinput/browser/quickInput.ts | 9 +- .../parts/sandbox/electron-browser/preload.js | 8 - .../parts/sandbox/electron-sandbox/globals.ts | 10 - src/vs/base/test/common/mime.test.ts | 51 +- .../code/browser/workbench/workbench-dev.html | 9 + src/vs/code/browser/workbench/workbench.html | 8 + src/vs/code/browser/workbench/workbench.ts | 5 + .../issue/issueReporterMain.ts | 23 +- .../processExplorer/processExplorerMain.ts | 635 +++++------ .../contrib/storageDataCleaner.ts | 4 +- .../sharedProcess/sharedProcessMain.ts | 2 +- .../electron-browser/workbench/workbench.js | 35 +- src/vs/code/electron-main/auth.ts | 26 +- src/vs/code/electron-main/main.ts | 4 +- src/vs/code/electron-main/window.ts | 14 +- .../proxy/auth.html | 41 +- src/vs/code/electron-sandbox/proxy/auth.js | 48 + src/vs/css.build.js | 2 +- src/vs/editor/browser/config/configuration.ts | 3 +- src/vs/editor/browser/editorBrowser.ts | 12 + src/vs/editor/browser/editorExtensions.ts | 28 +- src/vs/editor/browser/view/viewImpl.ts | 12 +- .../editor/browser/widget/codeEditorWidget.ts | 15 +- .../editor/browser/widget/diffEditorWidget.ts | 36 +- .../common/config/commonEditorConfig.ts | 5 + src/vs/editor/common/config/editorOptions.ts | 34 +- src/vs/editor/common/model/mirrorTextModel.ts | 8 +- .../pieceTreeTextBuffer/pieceTreeBase.ts | 40 +- src/vs/editor/common/model/textModel.ts | 5 +- src/vs/editor/common/modes.ts | 18 +- .../common/modes/tokenizationRegistry.ts | 7 +- .../common/services/languagesRegistry.ts | 3 +- .../services/markerDecorationsServiceImpl.ts | 8 +- src/vs/editor/contrib/comment/comment.ts | 8 +- .../contrib/comment/lineCommentCommand.ts | 34 +- .../comment/test/lineCommentCommand.test.ts | 111 +- src/vs/editor/contrib/find/findController.ts | 41 +- .../contrib/find/test/findController.test.ts | 164 +-- .../contrib/message/messageController.css | 1 + .../contrib/message/messageController.ts | 5 +- src/vs/editor/contrib/peekView/peekView.ts | 12 +- .../editor/contrib/snippet/snippetSession.ts | 14 +- .../contrib/snippet/snippetVariables.ts | 7 +- .../snippet/test/snippetController2.test.ts | 9 + src/vs/editor/contrib/suggest/suggestModel.ts | 2 +- .../editor/contrib/suggest/suggestWidget.ts | 2 +- .../browser/standaloneCodeEditor.ts | 4 +- src/vs/editor/test/browser/testCodeEditor.ts | 22 +- src/vs/loader.js | 38 +- src/vs/monaco.d.ts | 36 +- .../common/configurationModels.ts | 12 +- .../common/configurationRegistry.ts | 3 +- .../test/common/configurationService.test.ts | 246 +++++ .../test/node/configurationService.test.ts | 304 ------ .../contextkey/browser/contextKeyService.ts | 4 +- .../platform/contextkey/common/contextkey.ts | 1 - src/vs/platform/electron/common/electron.ts | 1 + .../electron-main/electronMainService.ts | 13 +- .../environment/common/environment.ts | 3 + src/vs/platform/environment/node/argv.ts | 2 + .../environment/node/environmentService.ts | 7 +- src/vs/platform/environment/node/stdin.ts | 5 +- .../common/extensionGalleryService.ts | 3 +- .../common/extensionManagement.ts | 11 +- .../common/extensionTipsService.ts | 3 +- .../node/extensionLifecycle.ts | 2 +- .../node/extensionTipsService.ts | 55 +- .../browser/indexedDBFileSystemProvider.ts | 2 - src/vs/platform/files/common/fileService.ts | 18 +- .../common/inMemoryFilesystemProvider.ts | 4 +- .../common/keyValueFileSystemProvider.ts | 3 +- .../diskFileSystemProvider.ts | 2 +- .../files/node/diskFileSystemProvider.ts | 15 +- .../issue/electron-main/issueMainService.ts | 7 +- .../keybinding/common/keybindingResolver.ts | 5 +- .../keybinding/common/keybindingsRegistry.ts | 2 +- src/vs/platform/label/common/label.ts | 22 +- .../launch/electron-main/launchMainService.ts | 2 + src/vs/platform/list/browser/listService.ts | 81 +- .../platform/menubar/electron-main/menubar.ts | 20 +- src/vs/platform/product/common/product.ts | 2 +- .../platform/product/common/productService.ts | 4 +- .../quickinput/browser/pickerQuickAccess.ts | 17 +- .../remote/common/remoteAgentEnvironment.ts | 2 +- .../platform/request/node/requestService.ts | 2 +- .../storage/node/storageMainService.ts | 2 +- .../platform/storage/node/storageService.ts | 6 +- .../storage/test/node/storageService.test.ts | 7 +- .../common/tokenClassificationRegistry.ts | 2 +- .../common/abstractSynchronizer.ts | 337 ++++-- .../userDataSync/common/extensionsMerge.ts | 22 +- .../userDataSync/common/extensionsSync.ts | 230 ++-- .../userDataSync/common/globalStateMerge.ts | 13 +- .../userDataSync/common/globalStateSync.ts | 214 ++-- .../userDataSync/common/keybindingsMerge.ts | 35 +- .../userDataSync/common/keybindingsSync.ts | 181 ++-- .../userDataSync/common/settingsMerge.ts | 18 +- .../userDataSync/common/settingsSync.ts | 212 ++-- .../userDataSync/common/snippetsMerge.ts | 133 +-- .../userDataSync/common/snippetsSync.ts | 449 ++++---- .../userDataSync/common/storageKeys.ts | 3 +- .../common/userDataAutoSyncService.ts | 73 +- .../userDataSync/common/userDataSync.ts | 132 ++- .../userDataSync/common/userDataSyncIpc.ts | 54 +- .../common/userDataSyncService.ts | 373 +++++-- .../common/userDataSyncStoreService.ts | 60 +- .../test/common/snippetsMerge.test.ts | 255 +++-- .../test/common/snippetsSync.test.ts | 257 ++++- .../test/common/synchronizer.test.ts | 186 +++- .../common/userDataAutoSyncService.test.ts | 15 +- .../test/common/userDataSyncClient.ts | 4 +- .../test/common/userDataSyncService.test.ts | 97 +- .../common/userDataSyncStoreService.test.ts | 7 +- .../platform/webview/common/resourceLoader.ts | 21 +- .../webview/common/webviewManagerService.ts | 5 +- .../electron-main/webviewMainService.ts | 12 +- .../electron-main/webviewProtocolProvider.ts | 58 +- src/vs/platform/windows/common/windows.ts | 8 + .../electron-main/windowsMainService.ts | 3 +- .../windows/electron-sandbox/window.ts | 29 + .../platform/workspaces/common/workspaces.ts | 13 +- .../workspacesHistoryMainService.ts | 29 +- .../electron-main/workspacesMainService.ts | 2 +- src/vs/vscode.d.ts | 24 +- src/vs/vscode.proposed.d.ts | 189 +++- .../api/browser/mainThreadAuthentication.ts | 44 +- .../api/browser/mainThreadDebugService.ts | 22 +- .../api/browser/mainThreadDialogs.ts | 30 +- .../api/browser/mainThreadDocuments.ts | 78 +- .../browser/mainThreadDocumentsAndEditors.ts | 7 +- .../workbench/api/browser/mainThreadEditor.ts | 40 +- .../api/browser/mainThreadEditors.ts | 27 +- .../api/browser/mainThreadStatusBar.ts | 4 +- .../workbench/api/browser/mainThreadTask.ts | 63 +- .../api/browser/mainThreadWorkspace.ts | 23 +- .../workbench/api/common/extHost.api.impl.ts | 15 +- .../common/extHost.common.services.ts} | 33 +- .../workbench/api/common/extHost.protocol.ts | 22 +- .../api/common/extHostAuthentication.ts | 70 +- .../api/common/extHostDebugService.ts | 11 +- src/vs/workbench/api/common/extHostDialogs.ts | 4 +- .../api/common/extHostExtensionService.ts | 119 +-- .../workbench/api/common/extHostFileSystem.ts | 58 +- .../api/common/extHostFileSystemConsumer.ts | 74 ++ .../workbench/api/common/extHostNotebook.ts | 4 +- .../workbench/api/common/extHostStatusBar.ts | 5 + .../api/common/extHostStoragePaths.ts | 75 +- src/vs/workbench/api/common/extHostTask.ts | 16 +- .../api/common/extHostTerminalService.ts | 65 +- .../workbench/api/common/extHostTimeline.ts | 4 +- .../workbench/api/common/extHostTreeViews.ts | 11 +- src/vs/workbench/api/common/extHostTypes.ts | 9 +- src/vs/workbench/api/common/extHostWebview.ts | 2 +- .../api/common/menusExtensionPoint.ts | 2 +- .../api/common/shared/workspaceContains.ts | 138 +++ ...t.services.ts => extHost.node.services.ts} | 55 +- .../workbench/api/node/extHostStoragePaths.ts | 80 -- src/vs/workbench/api/node/extHostTask.ts | 11 +- .../api/node/extHostTerminalService.ts | 40 +- .../api/worker/extHost.worker.services.ts | 19 + .../browser/actions/developerActions.ts | 130 ++- .../workbench/browser/actions/helpActions.ts | 279 ++--- .../browser/actions/layoutActions.ts | 124 +-- .../workbench/browser/actions/listCommands.ts | 2 +- .../browser/actions/quickAccessActions.ts | 108 +- src/vs/workbench/browser/contextkeys.ts | 2 +- src/vs/workbench/browser/dnd.ts | 51 +- src/vs/workbench/browser/layout.ts | 5 +- .../parts/activitybar/activitybarActions.ts | 65 +- .../parts/activitybar/activitybarPart.ts | 130 ++- .../workbench/browser/parts/compositeBar.ts | 14 +- .../browser/parts/editor/baseEditor.ts | 27 +- .../parts/editor/breadcrumbsControl.ts | 14 +- .../browser/parts/editor/breadcrumbsModel.ts | 3 +- .../parts/editor/editor.contribution.ts | 9 +- .../browser/parts/editor/editorCommands.ts | 2 +- .../browser/parts/editor/editorPart.ts | 2 +- .../browser/parts/editor/editorStatus.ts | 6 +- .../browser/parts/editor/textDiffEditor.ts | 11 +- .../browser/parts/editor/titleControl.ts | 8 +- .../browser/parts/panel/panelPart.ts | 2 +- .../browser/parts/sidebar/sidebarPart.ts | 45 +- .../browser/parts/statusbar/statusbarPart.ts | 3 + .../browser/parts/titlebar/menubarControl.ts | 6 + .../browser/parts/views/viewsService.ts | 9 +- src/vs/workbench/browser/viewlet.ts | 2 - src/vs/workbench/browser/web.main.ts | 1 - src/vs/workbench/common/resources.ts | 48 +- src/vs/workbench/common/views.ts | 35 +- .../backup/electron-sandbox/backupTracker.ts | 2 +- .../bulkEdit/browser/bulkEdit.contribution.ts | 13 +- .../browser/callHierarchy.contribution.ts | 128 ++- .../browser/callHierarchyPeek.ts | 60 +- .../callHierarchy/common/callHierarchy.ts | 4 +- .../browser/find/simpleFindReplaceWidget.ts | 8 +- .../quickaccess/gotoLineQuickAccess.ts | 38 +- .../quickaccess/gotoSymbolQuickAccess.ts | 8 +- .../contrib/comments/common/commentModel.ts | 7 +- .../customEditor/browser/customEditors.ts | 13 +- .../contrib/debug/browser/callStackView.ts | 27 +- .../contrib/debug/browser/debugService.ts | 16 +- .../contrib/debug/browser/debugSession.ts | 4 +- .../debug/browser/loadedScriptsView.ts | 12 +- .../debug/browser/media/debugViewlet.css | 1 + .../workbench/contrib/debug/browser/repl.ts | 9 +- .../workbench/contrib/debug/common/debug.ts | 8 +- .../contrib/debug/test/common/mockDebug.ts | 2 +- .../browser/configBasedRecommendations.ts | 5 +- .../browser/exeBasedRecommendations.ts | 12 +- .../extensions/browser/extensionEditor.ts | 29 +- .../browser/extensions.contribution.ts | 26 +- .../extensions/browser/extensionsActions.ts | 39 +- .../browser/extensionsDependencyChecker.ts | 3 +- .../browser/media/extensionEditor.css | 7 +- .../runtimeExtensionsEditor.ts | 7 +- .../files/browser/files.contribution.ts | 6 +- .../files/browser/views/explorerView.ts | 2 +- .../files/browser/views/explorerViewer.ts | 2 +- .../issue/electron-browser/issueService.ts | 9 +- .../contrib/logs/common/logs.contribution.ts | 5 +- .../markers/browser/markersFilterOptions.ts | 2 +- .../contrib/notebook/browser/constants.ts | 15 +- .../notebook/browser/contrib/coreActions.ts | 147 ++- .../browser/contrib/find/findController.ts | 50 +- .../notebook/browser/contrib/fold/folding.ts | 18 +- .../browser/contrib/format/formatting.ts | 2 +- .../browser/contrib/status/editorStatus.ts | 19 +- .../browser/contrib/toc/tocProvider.ts | 11 + .../notebook/browser/media/notebook.css | 79 +- .../notebook/browser/notebookBrowser.ts | 18 +- .../notebook/browser/notebookEditor.ts | 32 +- .../notebook/browser/notebookEditorInput.ts | 25 +- .../notebook/browser/notebookEditorWidget.ts | 190 +++- .../notebook/browser/notebookServiceImpl.ts | 12 +- .../notebook/browser/view/notebookCellList.ts | 41 +- .../view/renderers/backLayerWebView.ts | 29 +- .../browser/view/renderers/cellRenderer.ts | 44 +- .../browser/view/renderers/codeCell.ts | 75 +- .../browser/view/renderers/markdownCell.ts | 34 +- .../browser/view/renderers/webviewPreloads.ts | 33 +- .../browser/viewModel/baseCellViewModel.ts | 69 +- .../browser/viewModel/codeCellViewModel.ts | 8 +- .../viewModel/markdownCellViewModel.ts | 10 +- .../browser/viewModel/notebookViewModel.ts | 45 +- .../common/model/notebookCellTextModel.ts | 13 - .../common/model/notebookTextModel.ts | 11 +- .../contrib/notebook/common/notebookCommon.ts | 8 + .../notebook/common/notebookEditorModel.ts | 87 +- .../notebook/common/notebookService.ts | 4 +- .../notebook/test/testNotebookEditor.ts | 7 +- .../contrib/outline/browser/outlinePane.ts | 10 +- .../browser/performance.contribution.ts | 55 + .../perfviewEditor.ts | 4 +- .../performance.contribution.ts | 42 - .../electron-browser/startupProfiler.ts | 2 +- .../electron-browser/startupTimings.ts | 32 +- .../browser/media/settingsEditor2.css | 6 +- .../preferences/browser/preferencesEditor.ts | 15 +- .../preferences/browser/settingsEditor2.ts | 22 +- .../preferences/browser/settingsLayout.ts | 1 + .../preferences/browser/settingsTree.ts | 63 +- .../preferences/browser/settingsWidgets.ts | 34 +- .../common/preferencesContribution.ts | 11 +- .../browser/commandsQuickAccess.ts | 59 +- .../browser/quickAccess.contribution.ts | 22 +- .../quickaccess/browser/viewQuickAccess.ts | 63 +- .../contrib/remote/browser/remote.ts | 15 +- .../contrib/remote/browser/remoteIndicator.ts | 2 +- .../contrib/remote/browser/tunnelView.ts | 9 +- .../contrib/scm/browser/dirtydiffDecorator.ts | 129 ++- .../contrib/scm/browser/media/scm.css | 47 +- .../contrib/scm/browser/scm.contribution.ts | 67 +- .../contrib/scm/browser/scmViewPane.ts | 204 +++- .../search/browser/anythingQuickAccess.ts | 18 +- .../search/browser/patternInputWidget.ts | 4 + .../search/browser/search.contribution.ts | 39 +- .../contrib/search/browser/searchActions.ts | 2 +- .../contrib/search/browser/searchView.ts | 15 +- .../contrib/search/common/queryBuilder.ts | 4 +- .../browser/searchEditor.contribution.ts | 36 +- .../searchEditor/browser/searchEditor.ts | 6 + .../searchEditor/browser/searchEditorInput.ts | 4 +- .../searchEditor/browser/searchEditorModel.ts | 2 +- .../tasks/browser/abstractTaskService.ts | 98 +- .../tasks/browser/task.contribution.ts | 30 +- .../tasks/browser/terminalTaskSystem.ts | 19 +- .../contrib/tasks/common/jsonSchemaCommon.ts | 2 + .../contrib/tasks/common/problemMatcher.ts | 2 +- .../contrib/tasks/common/taskConfiguration.ts | 60 +- .../tasks/common/taskDefinitionRegistry.ts | 13 +- .../contrib/tasks/common/taskService.ts | 5 + .../contrib/tasks/common/taskSystem.ts | 1 + .../workbench/contrib/tasks/common/tasks.ts | 7 +- .../tasks/electron-browser/taskService.ts | 4 + .../tasks/node/processRunnerDetector.ts | 2 +- .../contrib/tasks/node/processTaskSystem.ts | 2 +- .../tasks/test/common/configuration.test.ts | 16 +- .../terminalExternalLinkProviderAdapter.ts | 9 +- .../browser/links/terminalLinkHelpers.ts | 9 +- .../browser/links/terminalLinkManager.ts | 2 +- .../terminal/browser/terminal.contribution.ts | 15 +- .../terminal/browser/terminalConfigHelper.ts | 2 +- .../terminal/browser/terminalService.ts | 30 +- .../contrib/terminal/common/terminal.ts | 3 +- .../terminal/common/terminalConfiguration.ts | 2 +- .../electron-browser/terminalNativeService.ts | 18 +- .../contrib/terminal/node/terminalProcess.ts | 7 +- .../contrib/timeline/browser/timelinePane.ts | 12 +- .../update/browser/update.contribution.ts | 3 +- .../contrib/update/browser/update.ts | 48 +- .../contrib/url/browser/trustedDomains.ts | 2 +- .../contrib/url/browser/url.contribution.ts | 38 +- .../browser/userDataManualSyncView.ts | 452 ++++++++ .../browser/userDataSync.contribution.ts | 4 +- .../userDataSync/browser/userDataSync.ts | 162 +-- .../userDataSync/browser/userDataSyncViews.ts | 134 +-- .../userDataAutoSyncService.ts | 6 +- .../userDataSync.contribution.ts | 5 +- .../contrib/views/browser/treeView.ts | 21 +- .../webview/browser/baseWebviewElement.ts | 26 +- .../browser/dynamicWebviewEditorOverlay.ts | 5 + .../contrib/webview/browser/pre/main.js | 29 +- .../webview/browser/webview.contribution.ts | 82 +- .../contrib/webview/browser/webview.ts | 7 +- .../webview/browser/webviewCommands.ts | 64 +- .../contrib/webview/browser/webviewEditor.ts | 4 +- .../contrib/webview/browser/webviewElement.ts | 6 +- .../browser/webviewWorkbenchService.ts | 3 - .../electron-browser/resourceLoading.ts | 40 +- .../electron-browser/webview.contribution.ts | 56 +- .../electron-browser/webviewCommands.ts | 21 +- .../electron-browser/webviewElement.ts | 11 + .../actions/developerActions.ts | 33 +- .../electron-browser/desktop.main.ts | 7 +- src/vs/workbench/electron-browser/window.ts | 37 +- .../electron-sandbox/actions/windowActions.ts | 19 +- .../parts/titlebar/titlebarPart.ts | 8 +- .../browser/authenticationService.ts | 38 +- .../electron-sandbox/contextmenuService.ts | 13 +- .../browser/abstractFileDialogService.ts | 6 +- .../dialogs/browser/simpleFileDialog.ts | 4 +- .../services/editor/browser/editorService.ts | 6 +- .../services/editor/common/editorOpenWith.ts | 8 +- .../services/editor/common/editorService.ts | 4 +- .../environment/browser/environmentService.ts | 17 +- .../common/extensionManagementService.ts | 9 +- .../common/webExtensionsScannerService.ts | 16 +- .../extensions/browser/extensionService.ts | 3 +- .../extensions/browser/extensionUrlHandler.ts | 46 +- .../browser/webWorkerExtensionHost.ts | 6 +- .../browser/webWorkerFileSystemProvider.ts | 12 +- .../extensions/common/extensionHostMain.ts | 3 +- .../extensions/common/extensionHostManager.ts | 2 +- .../extensions/common/extensionsRegistry.ts | 4 +- .../extensions/common/remoteExtensionHost.ts | 6 +- .../electron-browser/extensionService.ts | 63 +- .../localProcessExtensionHost.ts | 5 +- .../remoteExtensionManagementIpc.ts | 7 +- .../node/extensionHostProcessSetup.ts | 4 +- .../extensions/worker/extensionHostWorker.ts | 4 +- .../services/history/browser/history.ts | 10 +- .../workbench/services/hover/browser/hover.ts | 2 +- .../keybinding/common/keybindingEditing.ts | 28 +- .../keybindingEditing.test.ts | 10 + .../services/label/common/labelService.ts | 19 +- .../services/label/test/browser/label.test.ts | 75 +- .../preferences/common/preferencesModels.ts | 8 +- .../progress/browser/progressService.ts | 2 +- .../common/remoteAgentEnvironmentChannel.ts | 4 +- .../services/search/common/searchService.ts | 4 +- .../services/search/node/fileSearch.ts | 10 +- .../services/search/node/rawSearchService.ts | 9 +- .../services/search/node/ripgrepFileSearch.ts | 4 +- .../search/node/ripgrepSearchUtils.ts | 7 +- .../search/node/ripgrepTextSearchEngine.ts | 30 +- .../services/search/node/searchService.ts | 2 +- .../services/statusbar/common/statusbar.ts | 6 + .../browser/browserTextFileService.ts | 28 +- .../textfile/browser/textFileService.ts | 154 +-- .../services/textfile/common/encoding.ts | 89 +- .../textfile/common/textFileEditorModel.ts | 6 +- .../services/textfile/common/textfiles.ts | 496 +++++---- .../electron-browser/nativeTextFileService.ts | 113 +- .../browser/browserTextFileService.io.test.ts | 115 ++ .../textfile/test/browser/fixtures/files.ts | 421 ++++++++ .../test/browser/textFileService.test.ts | 33 + .../textFileService.io.test.ts | 146 +-- .../{some_shiftjs.txt => some_shiftjis.txt} | 0 .../nativeTextFileService.io.test.ts | 84 ++ .../test/node/encoding/encoding.test.ts | 42 +- .../node/encoding/fixtures/issue_102202.txt | 983 ++++++++++++++++++ .../test/node/encoding/fixtures/some_gbk.txt | 1 + .../themes/browser/workbenchThemeService.ts | 7 - .../services/timer/browser/timerService.ts | 446 ++++++++ .../timer/electron-browser/timerService.ts | 412 +------- .../userData/common/fileUserDataProvider.ts | 3 +- .../browser/userDataSyncWorkbenchService.ts | 303 +++++- .../userDataSync/common/userDataSync.ts | 39 +- .../electron-browser/userDataSyncService.ts | 131 ++- .../views/browser/viewDescriptorService.ts | 44 +- .../views/common/viewContainerModel.ts | 7 +- .../workspaceEditingService.ts | 4 +- .../browser/api/mainThreadTreeViews.test.ts | 86 ++ .../browser/parts/editor/baseEditor.test.ts | 3 + .../parts/editor/breadcrumbModel.test.ts | 19 +- .../test/browser/workbenchTestServices.ts | 71 +- .../electron-browser/workbenchTestServices.ts | 25 +- src/vs/workbench/workbench.common.main.ts | 3 + src/vs/workbench/workbench.desktop.main.ts | 3 + src/vs/workbench/workbench.web.api.ts | 49 +- src/vs/workbench/workbench.web.main.ts | 2 + test/automation/src/notebook.ts | 4 + .../smoke/src/areas/notebook/notebook.test.ts | 8 + test/unit/browser/renderer.html | 6 +- yarn.lock | 108 +- 554 files changed, 15159 insertions(+), 8223 deletions(-) create mode 100644 .vscode/notebooks/api.github-issues create mode 100644 .vscode/notebooks/verification.github-issues create mode 100644 build/win32/i18n/Default.hu.isl delete mode 100644 build/win32/i18n/Default.isl create mode 100644 extensions/extension-editing/extension-browser.webpack.config.js create mode 100644 extensions/extension-editing/src/extensionEditingBrowserMain.ts rename extensions/extension-editing/src/{extension.ts => extensionEditingMain.ts} (100%) create mode 100644 extensions/git/src/pushError.ts create mode 100644 extensions/git/src/remoteSource.ts create mode 100644 extensions/github-browser/src/statusbar.ts create mode 100644 extensions/github/src/pushErrorHandler.ts create mode 100644 extensions/github/src/util.ts create mode 100644 extensions/markdown-language-features/src/test/documentLink.test.ts delete mode 100644 extensions/markdown-language-features/src/test/test-fixtures/marker.txt create mode 100644 extensions/markdown-language-features/src/test/util.ts create mode 100644 extensions/markdown-language-features/test-workspace/a.md create mode 100644 extensions/markdown-language-features/test-workspace/b.md create mode 100644 extensions/markdown-language-features/test-workspace/sub/c.md create mode 100644 extensions/markdown-language-features/test-workspace/sub/d.md rename src/vs/code/{electron-browser => electron-sandbox}/proxy/auth.html (58%) create mode 100644 src/vs/code/electron-sandbox/proxy/auth.js create mode 100644 src/vs/platform/configuration/test/common/configurationService.test.ts delete mode 100644 src/vs/platform/configuration/test/node/configurationService.test.ts create mode 100644 src/vs/platform/windows/electron-sandbox/window.ts rename src/vs/workbench/{services/extensions/worker/extHost.services.ts => api/common/extHost.common.services.ts} (74%) create mode 100644 src/vs/workbench/api/common/extHostFileSystemConsumer.ts create mode 100644 src/vs/workbench/api/common/shared/workspaceContains.ts rename src/vs/workbench/api/node/{extHost.services.ts => extHost.node.services.ts} (55%) delete mode 100644 src/vs/workbench/api/node/extHostStoragePaths.ts create mode 100644 src/vs/workbench/api/worker/extHost.worker.services.ts create mode 100644 src/vs/workbench/contrib/performance/browser/performance.contribution.ts rename src/vs/workbench/contrib/performance/{electron-browser => browser}/perfviewEditor.ts (99%) create mode 100644 src/vs/workbench/contrib/userDataSync/browser/userDataManualSyncView.ts create mode 100644 src/vs/workbench/services/textfile/test/browser/browserTextFileService.io.test.ts create mode 100644 src/vs/workbench/services/textfile/test/browser/fixtures/files.ts rename src/vs/workbench/services/textfile/test/{electron-browser => common}/textFileService.io.test.ts (82%) rename src/vs/workbench/services/textfile/test/electron-browser/fixtures/{some_shiftjs.txt => some_shiftjis.txt} (100%) create mode 100644 src/vs/workbench/services/textfile/test/electron-browser/nativeTextFileService.io.test.ts create mode 100644 src/vs/workbench/services/textfile/test/node/encoding/fixtures/issue_102202.txt create mode 100644 src/vs/workbench/services/textfile/test/node/encoding/fixtures/some_gbk.txt create mode 100644 src/vs/workbench/services/timer/browser/timerService.ts create mode 100644 src/vs/workbench/test/browser/api/mainThreadTreeViews.test.ts diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index d352b823d0..23c94155f3 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -3,7 +3,7 @@ # Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. #------------------------------------------------------------------------------------------------------------- -FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-10 +FROM mcr.microsoft.com/vscode/devcontainers/typescript-node:0-12 ARG TARGET_DISPLAY=":1" diff --git a/.devcontainer/README.md b/.devcontainer/README.md index 79fdfb487a..e16795062d 100644 --- a/.devcontainer/README.md +++ b/.devcontainer/README.md @@ -6,9 +6,9 @@ This repository includes configuration for a development container for working w ## Quick start - local -1. Install Docker Desktop or Docker on your local machine. (See [docs](https://aka.ms/vscode-remote/containers/getting-started) for additional details.) +1. Install Docker Desktop or Docker for Linux on your local machine. (See [docs](https://aka.ms/vscode-remote/containers/getting-started) for additional details.) -2. [Docker Desktop] If you are not using the new WSL2 Docker Desktop engine, increase the resources allocated to Docker Desktop to at least **4 Cores and 4 GB of RAM (8 GB recommended)**. Right-click on the Docker status bar item, go to **Preferences/Settings > Resources > Advanced** to do so. +2. **Important**: Docker needs at least **4 Cores and 6 GB of RAM (8 GB recommended)** to run full build. If you on macOS, or using the old Hyper-V engine for Windows, update these values for Docker Desktop by right-clicking on the Docker status bar item, going to **Preferences/Settings > Resources > Advanced**. > **Note:** The [Resource Monitor](https://marketplace.visualstudio.com/items?itemName=mutantdino.resourcemonitor) extension is included in the container so you can keep an eye on CPU/Memory in the status bar. @@ -44,7 +44,7 @@ Next: **[Try it out!](#try-it)** 3. Press Ctrl/Cmd + Shift + P and select **Codespaces: Create New Codespace**. -4. Use default settings, select a plan, and then enter the repository URL `https://github.com/microsoft/vscode` (or a branch or PR URL) in the input box when prompted. +4. Use default settings (which should include **Standard** 4 core, 8 GB RAM Codespace), select a plan, and then enter the repository URL `https://github.com/microsoft/vscode` (or a branch or PR URL) in the input box when prompted. 5. After the container is running, open a web browser and go to [http://localhost:6080](http://localhost:6080) or use a [VNC Viewer](https://www.realvnc.com/en/connect/download/viewer/) to connect to `localhost:5901` and enter `vscode` as the password. diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b9f3e6d79b..722bace6df 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -12,7 +12,11 @@ } }, "overrideCommand": false, - "runArgs": ["--init"], + "runArgs": [ + "--init", + // seccomp=unconfined is required for Chrome sandboxing + "--security-opt", "seccomp=unconfined" + ], "settings": { // zsh is also available diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 76f0aeadfa..2cd0a32b9c 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -4,7 +4,6 @@ "recommendations": [ "dbaeumer.vscode-eslint", "EditorConfig.EditorConfig", - "msjsdiag.debugger-for-chrome", - "ms-vscode.vscode-github-issue-notebooks" + "msjsdiag.debugger-for-chrome" ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index 1a19bbf549..04efa7aa70 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -92,6 +92,7 @@ "env": { "VSCODE_EXTHOST_WILL_SEND_SOCKET": null }, + "cleanUp": "wholeBrowser", "breakOnLoad": false, "urlFilter": "*workbench.html*", "runtimeArgs": [ diff --git a/.vscode/notebooks/api.github-issues b/.vscode/notebooks/api.github-issues new file mode 100644 index 0000000000..f36bb39758 --- /dev/null +++ b/.vscode/notebooks/api.github-issues @@ -0,0 +1,38 @@ +[ + { + "kind": 1, + "language": "markdown", + "value": "#### Config", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"July 2020\"", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "### Finalization", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repo $milestone label:api-finalization", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "### Proposals", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repo $milestone is:open label:api-proposal ", + "editable": true + } +] \ No newline at end of file diff --git a/.vscode/notebooks/inbox.github-issues b/.vscode/notebooks/inbox.github-issues index 9edd342251..8931e7b0b3 100644 --- a/.vscode/notebooks/inbox.github-issues +++ b/.vscode/notebooks/inbox.github-issues @@ -2,12 +2,14 @@ { "kind": 1, "language": "markdown", - "value": "##### `Config`: defines the inbox query" + "value": "##### `Config`: defines the inbox query", + "editable": true }, { "kind": 2, "language": "github-issues", - "value": "$inbox=repo:microsoft/vscode is:open no:assignee -label:feature-request -label:testplan-item -label:plan-item " + "value": "$inbox=repo:microsoft/vscode is:open no:assignee -label:feature-request -label:testplan-item -label:plan-item ", + "editable": true }, { "kind": 1, @@ -18,7 +20,7 @@ { "kind": 2, "language": "github-issues", - "value": "$inbox -label:\"needs more info\"", + "value": "$inbox -label:\"needs more info\" -label:emmet", "editable": true }, { @@ -31,6 +33,6 @@ "kind": 2, "language": "github-issues", "value": "$inbox", - "editable": true + "editable": false } ] \ No newline at end of file diff --git a/.vscode/notebooks/my-work.github-issues b/.vscode/notebooks/my-work.github-issues index c6d2309b39..dc6d33365d 100644 --- a/.vscode/notebooks/my-work.github-issues +++ b/.vscode/notebooks/my-work.github-issues @@ -20,7 +20,7 @@ { "kind": 2, "language": "github-issues", - "value": "$repos $milestone assignee:@me is:open\n", + "value": "$repos $milestone assignee:@me is:open", "editable": false }, { diff --git a/.vscode/notebooks/verification.github-issues b/.vscode/notebooks/verification.github-issues new file mode 100644 index 0000000000..6f32df8e07 --- /dev/null +++ b/.vscode/notebooks/verification.github-issues @@ -0,0 +1,55 @@ +[ + { + "kind": 1, + "language": "markdown", + "value": "### Bug Verification Queries\n\nBefore shipping we want to verify _all_ bugs. That means when a bug is fixed we check that the fix actually works. It's always best to start with bugs that you have filed and the proceed with bugs that have been filed from users outside the development team. ", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "#### Config: update list of `repos` and the `milestone`", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repos=repo:microsoft/vscode repo:microsoft/vscode-internalbacklog repo:microsoft/vscode-remote-release repo:microsoft/vscode-js-debug repo:microsoft/vscode-pull-request-github repo:microsoft/vscode-github-issue-notebooks \n$milestone=milestone:\"June 2020\"", + "editable": true + }, + { + "kind": 1, + "language": "markdown", + "value": "### Bugs You Filed", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repos $milestone is:closed -assignee:@me label:bug -label:verified -label:*duplicate author:@me", + "editable": false + }, + { + "kind": 1, + "language": "markdown", + "value": "### Bugs From Outside", + "editable": true + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repos $milestone is:closed -assignee:@me label:bug -label:verified -label:*duplicate -author:@me -assignee:@me label:bug -label:verified -author:@me -author:aeschli -author:alexdima -author:alexr00 -author:bpasero -author:chrisdias -author:chrmarti -author:connor4312 -author:dbaeumer -author:deepak1556 -author:eamodio -author:egamma -author:gregvanl -author:isidorn -author:JacksonKearl -author:joaomoreno -author:jrieken -author:lramos15 -author:lszomoru -author:misolori -author:mjbvz -author:rebornix -author:RMacfarlane -author:roblourens -author:sana-ajani -author:sandy081 -author:sbatten -author:Tyriar -author:weinand", + "editable": false + }, + { + "kind": 1, + "language": "markdown", + "value": "### All" + }, + { + "kind": 2, + "language": "github-issues", + "value": "$repos $milestone is:closed -assignee:@me label:bug -label:verified -label:*duplicate", + "editable": false + } +] \ No newline at end of file diff --git a/.vscode/searches/es6.code-search b/.vscode/searches/es6.code-search index c89264a3cf..9cf8cf0b26 100644 --- a/.vscode/searches/es6.code-search +++ b/.vscode/searches/es6.code-search @@ -2,7 +2,7 @@ # Flags: CaseSensitive WordMatch # ContextLines: 2 -16 results - 5 files +14 results - 4 files src/vs/base/browser/dom.ts: 81 }; @@ -34,24 +34,11 @@ src/vs/base/common/arrays.ts: 420 */ 421 export function first(array: ReadonlyArray, fn: (item: T) => boolean, notFoundValue: T): T; - 560 - 561 /** - 562: * @deprecated ES6: use `Array.find` - 563 */ - 564 export function find(arr: ArrayLike, predicate: (value: T, index: number, arr: ArrayLike) => any): T | undefined { - -src/vs/base/common/map.ts: - 11 - 12 /** - 13: * @deprecated ES6: use `[...SetOrMap.values()]` - 14 */ - 15 export function values(set: Set): V[]; - - 22 - 23 /** - 24: * @deprecated ES6: use `[...map.keys()]` - 25 */ - 26 export function keys(map: Map): K[] { + 569 + 570 /** + 571: * @deprecated ES6: use `Array.find` + 572 */ + 573 export function find(arr: ArrayLike, predicate: (value: T, index: number, arr: ArrayLike) => any): T | undefined { src/vs/base/common/objects.ts: 115 diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 076129b820..42d0ba0f26 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -3,12 +3,8 @@ "tasks": [ { "type": "npm", - "script": "watchd", - "label": "Build VS Code", - "group": { - "kind": "build", - "isDefault": true - }, + "script": "watch-clientd", + "label": "Build VS Code Core", "isBackground": true, "presentation": { "reveal": "never" @@ -31,6 +27,43 @@ } } }, + { + "type": "npm", + "script": "watch-extensionsd", + "label": "Build VS Code Extensions", + "isBackground": true, + "presentation": { + "reveal": "never" + }, + "problemMatcher": { + "owner": "typescript", + "applyTo": "closedDocuments", + "fileLocation": [ + "absolute" + ], + "pattern": { + "regexp": "Error: ([^(]+)\\((\\d+|\\d+,\\d+|\\d+,\\d+,\\d+,\\d+)\\): (.*)$", + "file": 1, + "location": 2, + "message": 3 + }, + "background": { + "beginsPattern": "Starting compilation", + "endsPattern": "Finished compilation" + } + } + }, + { + "label": "Build VS Code", + "dependsOn": [ + "Build VS Code Core", + "Build VS Code Extensions" + ], + "group": { + "kind": "build", + "isDefault": true + } + }, { "type": "npm", "script": "strict-vscode-watch", @@ -55,6 +88,14 @@ }, "problemMatcher": "$tsc" }, + { + "label": "Kill Build VS Code", + "dependsOn": [ + "Kill Build VS Code Core", + "Kill Build VS Code Extensions" + ], + "group": "build" + }, { "type": "npm", "script": "watch-webd", diff --git a/.yarnrc b/.yarnrc index 135e10442a..4c5125d892 100644 --- a/.yarnrc +++ b/.yarnrc @@ -1,3 +1,3 @@ disturl "https://atom.io/download/electron" -target "7.3.2" +target "8.3.3" runtime "electron" diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js index 4c7e36bdc8..06dfe2b783 100644 --- a/build/gulpfile.vscode.js +++ b/build/gulpfile.vscode.js @@ -36,23 +36,6 @@ const { compileBuildTask } = require('./gulpfile.compile'); const { compileExtensionsBuildTask } = require('./gulpfile.extensions'); const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname)); -const baseModules = Object.keys(process.binding('natives')).filter(n => !/^_|\//.test(n)); -const nodeModules = [ // {{SQL CARBON EDIT}} - 'electron', - 'original-fs', - 'rxjs/Observable', - 'rxjs/add/observable/fromPromise', - 'rxjs/Subject', - 'rxjs/Observer', - 'slickgrid/lib/jquery.event.drag-2.3.0', - 'slickgrid/lib/jquery-ui-1.9.2', - 'slickgrid/slick.core', - 'slickgrid/slick.grid', - 'slickgrid/slick.editors', - 'slickgrid/slick.dataview'] - .concat(Object.keys(product.dependencies || {})) - .concat(_.uniq(productionDependencies.map(d => d.name))) - .concat(baseModules); // Build const vscodeEntryPoints = _.flatten([ @@ -75,6 +58,7 @@ const vscodeResources = [ 'out-build/paths.js', 'out-build/vs/**/*.{svg,png,html}', '!out-build/vs/code/browser/**/*.html', + '!out-build/vs/editor/standalone/**/*.svg', 'out-build/vs/base/common/performance.js', 'out-build/vs/base/node/languagePacks.js', 'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh,cpuUsage.sh,ps.sh}', @@ -123,7 +107,7 @@ const optimizeVSCodeTask = task.define('optimize-vscode', task.series( src: 'out-build', entryPoints: vscodeEntryPoints, resources: vscodeResources, - loaderConfig: common.loaderConfig(nodeModules), + loaderConfig: common.loaderConfig(), out: 'out-vscode', bundleInfo: undefined }) @@ -134,12 +118,6 @@ const sourceMappingURLBase = `https://sqlopsbuilds.blob.core.windows.net/sourcem const minifyVSCodeTask = task.define('minify-vscode', task.series( optimizeVSCodeTask, util.rimraf('out-vscode-min'), - () => { - const fullpath = path.join(process.cwd(), 'out-vscode/bootstrap-window.js'); - const contents = fs.readFileSync(fullpath).toString(); - const newContents = contents.replace('[/*BUILD->INSERT_NODE_MODULES*/]', JSON.stringify(nodeModules)); - fs.writeFileSync(fullpath, newContents); - }, common.minifyTask('out-vscode', `${sourceMappingURLBase}/core`) )); gulp.task(minifyVSCodeTask); diff --git a/build/gulpfile.vscode.win32.js b/build/gulpfile.vscode.win32.js index 1e0fd4b09a..c19c69bf8e 100644 --- a/build/gulpfile.vscode.win32.js +++ b/build/gulpfile.vscode.win32.js @@ -94,8 +94,8 @@ function buildWin32Setup(arch, target) { IncompatibleTargetAppId: { 'ia32': product.win32AppId, 'x64': product.win32x64AppId, 'arm64': product.win32arm64AppId }[arch], IncompatibleArchAppId: { 'ia32': x64AppId, 'x64': ia32AppId, 'arm64': ia32AppId }[arch], AppUserId: product.win32AppUserModelId, - ArchitecturesAllowed: { 'ia32': '', 'x64': 'x64', 'arm64': '' }[arch], - ArchitecturesInstallIn64BitMode: { 'ia32': '', 'x64': 'x64', 'arm64': '' }[arch], + ArchitecturesAllowed: { 'ia32': '', 'x64': 'x64', 'arm64': 'arm64' }[arch], + ArchitecturesInstallIn64BitMode: { 'ia32': '', 'x64': 'x64', 'arm64': 'arm64' }[arch], SourceDir: sourcePath, RepoDir: repoPath, OutputDir: outputPath, diff --git a/build/lib/compilation.js b/build/lib/compilation.js index 7a36b15a2e..f8b50731c2 100644 --- a/build/lib/compilation.js +++ b/build/lib/compilation.js @@ -18,6 +18,7 @@ const reporter_1 = require("./reporter"); const util = require("./util"); const fancyLog = require("fancy-log"); const ansiColors = require("ansi-colors"); +const os = require("os"); const watch = require('./watch'); const reporter = reporter_1.createReporter(); function getTypeScriptCompilerOptions(src) { @@ -69,6 +70,9 @@ function createCompile(src, build, emitError) { } function compileTask(src, out, build) { return function () { + if (os.totalmem() < 4000000000) { + throw new Error('compilation requires 4GB of RAM'); + } const compile = createCompile(src, build, true); const srcPipe = gulp.src(`${src}/**`, { base: `${src}` }); let generator = new MonacoGenerator(false); diff --git a/build/lib/compilation.ts b/build/lib/compilation.ts index 6409322743..4f1260b09a 100644 --- a/build/lib/compilation.ts +++ b/build/lib/compilation.ts @@ -18,6 +18,7 @@ import { createReporter } from './reporter'; import * as util from './util'; import * as fancyLog from 'fancy-log'; import * as ansiColors from 'ansi-colors'; +import * as os from 'os'; import ts = require('typescript'); const watch = require('./watch'); @@ -81,6 +82,11 @@ function createCompile(src: string, build: boolean, emitError?: boolean) { export function compileTask(src: string, out: string, build: boolean): () => NodeJS.ReadWriteStream { return function () { + + if (os.totalmem() < 4_000_000_000) { + throw new Error('compilation requires 4GB of RAM'); + } + const compile = createCompile(src, build, true); const srcPipe = gulp.src(`${src}/**`, { base: `${src}` }); let generator = new MonacoGenerator(false); diff --git a/build/lib/i18n.js b/build/lib/i18n.js index 904ef2ab75..b35bf2336b 100644 --- a/build/lib/i18n.js +++ b/build/lib/i18n.js @@ -1147,12 +1147,7 @@ function createIslFile(originalFilePath, messages, language, innoSetup) { if (line.length > 0) { let firstChar = line.charAt(0); if (firstChar === '[' || firstChar === ';') { - if (line === '; *** Inno Setup version 5.5.3+ English messages ***') { - content.push(`; *** Inno Setup version 5.5.3+ ${innoSetup.defaultInfo.name} messages ***`); - } - else { - content.push(line); - } + content.push(line); } else { let sections = line.split('='); diff --git a/build/lib/i18n.ts b/build/lib/i18n.ts index decc7dfd92..38947dd1aa 100644 --- a/build/lib/i18n.ts +++ b/build/lib/i18n.ts @@ -1316,11 +1316,7 @@ function createIslFile(originalFilePath: string, messages: Map, language if (line.length > 0) { let firstChar = line.charAt(0); if (firstChar === '[' || firstChar === ';') { - if (line === '; *** Inno Setup version 5.5.3+ English messages ***') { - content.push(`; *** Inno Setup version 5.5.3+ ${innoSetup.defaultInfo!.name} messages ***`); - } else { - content.push(line); - } + content.push(line); } else { let sections: string[] = line.split('='); let key = sections[0]; diff --git a/build/lib/optimize.js b/build/lib/optimize.js index 19104ca2d3..df7097a9fe 100644 --- a/build/lib/optimize.js +++ b/build/lib/optimize.js @@ -28,14 +28,15 @@ const REPO_ROOT_PATH = path.join(__dirname, '../..'); function log(prefix, message) { fancyLog(ansiColors.cyan('[' + prefix + ']'), message); } -function loaderConfig(emptyPaths) { +function loaderConfig() { const result = { paths: { 'vs': 'out-build/vs', 'sql': 'out-build/sql', - 'vscode': 'empty:' + 'vscode': 'empty:', + 'azdata': 'empty:' // {{SQL CARBON EDIT}} }, - nodeModules: emptyPaths || [] + amdModulesPattern: /^(vs|sql)\// // {{SQL CARBON EDIT}} include sql in regex }; result['vs/css'] = { inlineResources: true }; return result; diff --git a/build/lib/optimize.ts b/build/lib/optimize.ts index b3e1f95759..828fbca507 100644 --- a/build/lib/optimize.ts +++ b/build/lib/optimize.ts @@ -32,14 +32,15 @@ function log(prefix: string, message: string): void { fancyLog(ansiColors.cyan('[' + prefix + ']'), message); } -export function loaderConfig(emptyPaths?: string[]) { +export function loaderConfig() { const result: any = { paths: { 'vs': 'out-build/vs', 'sql': 'out-build/sql', // {{SQL CARBON EDIT}} - 'vscode': 'empty:' + 'vscode': 'empty:', + 'azdata': 'empty:' // {{SQL CARBON EDIT}} }, - nodeModules: emptyPaths || [] + amdModulesPattern: /^(vs|sql)\// // {{SQL CARBON EDIT}} include sql in regex }; result['vs/css'] = { inlineResources: true }; diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js index 9d2734da6d..ff9bb5498b 100644 --- a/build/npm/postinstall.js +++ b/build/npm/postinstall.js @@ -33,7 +33,7 @@ function yarnInstall(location, opts) { yarnInstall('extensions'); // node modules shared by all extensions -if (!(process.platform === 'win32' && process.env['npm_config_arch'] === 'arm64')) { +if (!(process.platform === 'win32' && (process.arch === 'arm64' || process.env['npm_config_arch'] === 'arm64'))) { yarnInstall('remote'); // node modules used by vscode server yarnInstall('remote/web'); // node modules used by vscode web } @@ -73,3 +73,5 @@ yarnInstall('test/automation'); // node modules required for smoketest yarnInstall('test/smoke'); // node modules required for smoketest yarnInstall('test/integration/browser'); // node modules required for integration yarnInstallBuildDependencies(); // node modules for watching, specific to host node version, not electron + +cp.execSync('git config pull.rebase true'); diff --git a/build/package.json b/build/package.json index 09863d4011..044f4c5fa1 100644 --- a/build/package.json +++ b/build/package.json @@ -40,7 +40,7 @@ "gulp-bom": "^1.0.0", "gulp-sourcemaps": "^1.11.0", "gulp-uglify": "^3.0.0", - "iconv-lite-umd": "0.6.5", + "iconv-lite-umd": "0.6.8", "mime": "^1.3.4", "minimatch": "3.0.4", "minimist": "^1.2.3", @@ -49,7 +49,7 @@ "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "terser": "4.3.8", - "typescript": "^4.0.0-dev.20200629", + "typescript": "^4.0.0-dev.20200708", "vsce": "1.48.0", "vscode-telemetry-extractor": "^1.6.0", "xml2js": "^0.4.17" diff --git a/build/win32/code.iss b/build/win32/code.iss index 321f8be01b..81e14a8386 100644 --- a/build/win32/code.iss +++ b/build/win32/code.iss @@ -34,6 +34,7 @@ VersionInfoVersion={#RawVersion} ShowLanguageDialog=auto ArchitecturesAllowed={#ArchitecturesAllowed} ArchitecturesInstallIn64BitMode={#ArchitecturesInstallIn64BitMode} +WizardStyle=modern #ifdef Sign SignTool=esrp @@ -47,7 +48,7 @@ DefaultDirName={pf}\{#DirName} #endif [Languages] -Name: "english"; MessagesFile: "{#RepoDir}\build\win32\i18n\Default.isl,{#RepoDir}\build\win32\i18n\messages.en.isl" {#LocalizedLanguageFile} +Name: "english"; MessagesFile: "compiler:Default.isl,{#RepoDir}\build\win32\i18n\messages.en.isl" {#LocalizedLanguageFile} Name: "german"; MessagesFile: "compiler:Languages\German.isl,{#RepoDir}\build\win32\i18n\messages.de.isl" {#LocalizedLanguageFile("deu")} Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl,{#RepoDir}\build\win32\i18n\messages.es.isl" {#LocalizedLanguageFile("esp")} Name: "french"; MessagesFile: "compiler:Languages\French.isl,{#RepoDir}\build\win32\i18n\messages.fr.isl" {#LocalizedLanguageFile("fra")} @@ -58,7 +59,7 @@ Name: "korean"; MessagesFile: "{#RepoDir}\build\win32\i18n\Default.ko.isl,{#Repo Name: "simplifiedChinese"; MessagesFile: "{#RepoDir}\build\win32\i18n\Default.zh-cn.isl,{#RepoDir}\build\win32\i18n\messages.zh-cn.isl" {#LocalizedLanguageFile("chs")} Name: "traditionalChinese"; MessagesFile: "{#RepoDir}\build\win32\i18n\Default.zh-tw.isl,{#RepoDir}\build\win32\i18n\messages.zh-tw.isl" {#LocalizedLanguageFile("cht")} Name: "brazilianPortuguese"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl,{#RepoDir}\build\win32\i18n\messages.pt-br.isl" {#LocalizedLanguageFile("ptb")} -Name: "hungarian"; MessagesFile: "compiler:Languages\Hungarian.isl,{#RepoDir}\build\win32\i18n\messages.hu.isl" {#LocalizedLanguageFile("hun")} +Name: "hungarian"; MessagesFile: "{#RepoDir}\build\win32\i18n\Default.hu.isl,{#RepoDir}\build\win32\i18n\messages.hu.isl" {#LocalizedLanguageFile("hun")} Name: "turkish"; MessagesFile: "compiler:Languages\Turkish.isl,{#RepoDir}\build\win32\i18n\messages.tr.isl" {#LocalizedLanguageFile("trk")} [InstallDelete] @@ -147,7 +148,7 @@ begin Result := True; #if "user" == InstallTarget - if not WizardSilent() and IsAdminLoggedOn() then begin + if not WizardSilent() and IsAdmin() then begin if MsgBox('This User Installer is not meant to be run as an Administrator. If you would like to install Azure Data Studio for all users in this system, download the System Installer instead from https://docs.microsoft.com/sql/azure-data-studio/download. Are you sure you want to continue?', mbError, MB_OKCANCEL) = IDCANCEL then begin Result := False; end; diff --git a/build/win32/i18n/Default.hu.isl b/build/win32/i18n/Default.hu.isl new file mode 100644 index 0000000000..8c57d20a59 --- /dev/null +++ b/build/win32/i18n/Default.hu.isl @@ -0,0 +1,366 @@ +;Inno Setup version 6.0.3+ Hungarian messages +;Based on the translation of Kornél Pál, kornelpal@gmail.com +;István Szabó, E-mail: istvanszabo890629@gmail.com +; +; To download user-contributed translations of this file, go to: +; http://www.jrsoftware.org/files/istrans/ +; +; Note: When translating this text, do not add periods (.) to the end of +; messages that didn't have them already, because on those messages Inno +; Setup adds the periods automatically (appending a period would result in +; two periods being displayed). + +[LangOptions] +; The following three entries are very important. Be sure to read and +; understand the '[LangOptions] section' topic in the help file. +LanguageName=Magyar +LanguageID=$040E +LanguageCodePage=1250 +; If the language you are translating to requires special font faces or +; sizes, uncomment any of the following entries and change them accordingly. +;DialogFontName= +;DialogFontSize=8 +;WelcomeFontName=Verdana +;WelcomeFontSize=12 +;TitleFontName=Arial CE +;TitleFontSize=29 +;CopyrightFontName=Arial CE +;CopyrightFontSize=8 + +[Messages] + +; *** Application titles +SetupAppTitle=Telepítő +SetupWindowTitle=%1 - Telepítő +UninstallAppTitle=Eltávolító +UninstallAppFullTitle=%1 Eltávolító + +; *** Misc. common +InformationTitle=Információk +ConfirmTitle=Megerősít +ErrorTitle=Hiba + +; *** SetupLdr messages +SetupLdrStartupMessage=%1 telepítve lesz. Szeretné folytatni? +LdrCannotCreateTemp=Átmeneti fájl létrehozása nem lehetséges. A telepítés megszakítva +LdrCannotExecTemp=Fájl futtatása nem lehetséges az átmeneti könyvtárban. A telepítés megszakítva +HelpTextNote= + +; *** Startup error messages +LastErrorMessage=%1.%n%nHiba %2: %3 +SetupFileMissing=A(z) %1 fájl hiányzik a telepítő könyvtárából. Kérem hárítsa el a problémát, vagy szerezzen be egy másik példányt a programból! +SetupFileCorrupt=A telepítési fájlok sérültek. Kérem, szerezzen be új másolatot a programból! +SetupFileCorruptOrWrongVer=A telepítési fájlok sérültek, vagy inkompatibilisek a telepítő ezen verziójával. Hárítsa el a problémát, vagy szerezzen be egy másik példányt a programból! +InvalidParameter=A parancssorba átadott paraméter érvénytelen:%n%n%1 +SetupAlreadyRunning=A Telepítő már fut. +WindowsVersionNotSupported=A program nem támogatja a Windows ezen verzióját. +WindowsServicePackRequired=A program futtatásához %1 Service Pack %2 vagy újabb szükséges. +NotOnThisPlatform=Ez a program nem futtatható %1 alatt. +OnlyOnThisPlatform=Ezt a programot %1 alatt kell futtatni. +OnlyOnTheseArchitectures=A program kizárólag a következő processzor architektúrákhoz tervezett Windows-on telepíthető:%n%n%1 +WinVersionTooLowError=A program futtatásához %1 %2 verziója vagy későbbi szükséges. +WinVersionTooHighError=Ez a program nem telepíthető %1 %2 vagy későbbire. +AdminPrivilegesRequired=Csak rendszergazdai módban telepíthető ez a program. +PowerUserPrivilegesRequired=Csak rendszergazdaként vagy kiemelt felhasználóként telepíthető ez a program. +SetupAppRunningError=A telepítő úgy észlelte %1 jelenleg fut.%n%nZárja be az összes példányt, majd kattintson az 'OK'-ra a folytatáshoz, vagy a 'Mégse'-re a kilépéshez. +UninstallAppRunningError=Az eltávolító úgy észlelte %1 jelenleg fut.%n%nZárja be az összes példányt, majd kattintson az 'OK'-ra a folytatáshoz, vagy a 'Mégse'-re a kilépéshez. + +; *** Startup questions +PrivilegesRequiredOverrideTitle=Telepítési mód kiválasztása +PrivilegesRequiredOverrideInstruction=Válasszon telepítési módot +PrivilegesRequiredOverrideText1=%1 telepíthető az összes felhasználónak (rendszergazdai jogok szükségesek), vagy csak magának. +PrivilegesRequiredOverrideText2=%1 csak magának telepíthető, vagy az összes felhasználónak (rendszergazdai jogok szükségesek). +PrivilegesRequiredOverrideAllUsers=Telepítés &mindenkinek +PrivilegesRequiredOverrideAllUsersRecommended=Telepítés &mindenkinek (ajánlott) +PrivilegesRequiredOverrideCurrentUser=Telepítés csak &nekem +PrivilegesRequiredOverrideCurrentUserRecommended=Telepítés csak &nekem (ajánlott) + +; *** Misc. errors +ErrorCreatingDir=A Telepítő nem tudta létrehozni a(z) "%1" könyvtárat +ErrorTooManyFilesInDir=Nem hozható létre fájl a(z) "%1" könyvtárban, mert az már túl sok fájlt tartalmaz + +; *** Setup common messages +ExitSetupTitle=Kilépés a telepítőből +ExitSetupMessage=A telepítés még folyamatban van. Ha most kilép, a program nem kerül telepítésre.%n%nMásik alkalommal is futtatható a telepítés befejezéséhez%n%nKilép a telepítőből? +AboutSetupMenuItem=&Névjegy... +AboutSetupTitle=Telepítő névjegye +AboutSetupMessage=%1 %2 verzió%n%3%n%nAz %1 honlapja:%n%4 +AboutSetupNote= +TranslatorNote= + +; *** Buttons +ButtonBack=< &Vissza +ButtonNext=&Tovább > +ButtonInstall=&Telepít +ButtonOK=OK +ButtonCancel=Mégse +ButtonYes=&Igen +ButtonYesToAll=&Mindet +ButtonNo=&Nem +ButtonNoToAll=&Egyiket se +ButtonFinish=&Befejezés +ButtonBrowse=&Tallózás... +ButtonWizardBrowse=T&allózás... +ButtonNewFolder=Új &könyvtár + +; *** "Select Language" dialog messages +SelectLanguageTitle=Telepítő nyelvi beállítás +SelectLanguageLabel=Válassza ki a telepítés alatt használt nyelvet. + +; *** Common wizard text +ClickNext=A folytatáshoz kattintson a 'Tovább'-ra, a kilépéshez a 'Mégse'-re. +BeveledLabel= +BrowseDialogTitle=Válasszon könyvtárt +BrowseDialogLabel=Válasszon egy könyvtárat az alábbi listából, majd kattintson az 'OK'-ra. +NewFolderName=Új könyvtár + +; *** "Welcome" wizard page +WelcomeLabel1=Üdvözli a(z) [name] Telepítővarázslója. +WelcomeLabel2=A(z) [name/ver] telepítésre kerül a számítógépén.%n%nAjánlott minden, egyéb futó alkalmazás bezárása a folytatás előtt. + +; *** "Password" wizard page +WizardPassword=Jelszó +PasswordLabel1=Ez a telepítés jelszóval védett. +PasswordLabel3=Kérem adja meg a jelszót, majd kattintson a 'Tovább'-ra. A jelszavak kis- és nagy betű érzékenyek lehetnek. +PasswordEditLabel=&Jelszó: +IncorrectPassword=Az ön által megadott jelszó helytelen. Próbálja újra. + +; *** "License Agreement" wizard page +WizardLicense=Licencszerződés +LicenseLabel=Olvassa el figyelmesen az információkat folytatás előtt. +LicenseLabel3=Kérem, olvassa el az alábbi licencszerződést. A telepítés folytatásához, el kell fogadnia a szerződést. +LicenseAccepted=&Elfogadom a szerződést +LicenseNotAccepted=&Nem fogadom el a szerződést + +; *** "Information" wizard pages +WizardInfoBefore=Információk +InfoBeforeLabel=Olvassa el a következő fontos információkat a folytatás előtt. +InfoBeforeClickLabel=Ha készen áll, kattintson a 'Tovább'-ra. +WizardInfoAfter=Információk +InfoAfterLabel=Olvassa el a következő fontos információkat a folytatás előtt. +InfoAfterClickLabel=Ha készen áll, kattintson a 'Tovább'-ra. + +; *** "User Information" wizard page +WizardUserInfo=Felhasználó adatai +UserInfoDesc=Kérem, adja meg az adatait +UserInfoName=&Felhasználónév: +UserInfoOrg=&Szervezet: +UserInfoSerial=&Sorozatszám: +UserInfoNameRequired=Meg kell adnia egy nevet. + +; *** "Select Destination Location" wizard page +WizardSelectDir=Válasszon célkönyvtárat +SelectDirDesc=Hova települjön a(z) [name]? +SelectDirLabel3=A(z) [name] az alábbi könyvtárba lesz telepítve. +SelectDirBrowseLabel=A folytatáshoz, kattintson a 'Tovább'-ra. Ha másik könyvtárat választana, kattintson a 'Tallózás'-ra. +DiskSpaceGBLabel=At least [gb] GB szabad területre van szükség. +DiskSpaceMBLabel=Legalább [mb] MB szabad területre van szükség. +CannotInstallToNetworkDrive=A Telepítő nem tud hálózati meghajtóra telepíteni. +CannotInstallToUNCPath=A Telepítő nem tud hálózati UNC elérési útra telepíteni. +InvalidPath=Teljes útvonalat adjon meg, a meghajtó betűjelével; például:%n%nC:\Alkalmazás%n%nvagy egy hálózati útvonalat a következő alakban:%n%n\\kiszolgáló\megosztás +InvalidDrive=A kiválasztott meghajtó vagy hálózati megosztás nem létezik vagy nem elérhető. Válasszon egy másikat. +DiskSpaceWarningTitle=Nincs elég szabad terület +DiskSpaceWarning=A Telepítőnek legalább %1 KB szabad lemezterületre van szüksége, viszont a kiválasztott meghajtón csupán %2 KB áll rendelkezésre.%n%nMindenképpen folytatja? +DirNameTooLong=A könyvtár neve vagy az útvonal túl hosszú. +InvalidDirName=A könyvtár neve érvénytelen. +BadDirName32=A könyvtárak nevei ezen karakterek egyikét sem tartalmazhatják:%n%n%1 +DirExistsTitle=A könyvtár már létezik +DirExists=A könyvtár:%n%n%1%n%nmár létezik. Mindenképp ide akar telepíteni? +DirDoesntExistTitle=A könyvtár nem létezik +DirDoesntExist=A könyvtár:%n%n%1%n%nnem létezik. Szeretné létrehozni? + +; *** "Select Components" wizard page +WizardSelectComponents=Összetevők kiválasztása +SelectComponentsDesc=Mely összetevők kerüljenek telepítésre? +SelectComponentsLabel2=Jelölje ki a telepítendő összetevőket; törölje a telepíteni nem kívánt összetevőket. Kattintson a 'Tovább'-ra, ha készen áll a folytatásra. +FullInstallation=Teljes telepítés +; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language) +CompactInstallation=Szokásos telepítés +CustomInstallation=Egyéni telepítés +NoUninstallWarningTitle=Létező összetevő +NoUninstallWarning=A telepítő úgy találta, hogy a következő összetevők már telepítve vannak a számítógépre:%n%n%1%n%nEzen összetevők kijelölésének törlése, nem távolítja el azokat a számítógépről.%n%nMindenképpen folytatja? +ComponentSize1=%1 KB +ComponentSize2=%1 MB +ComponentsDiskSpaceMBLabel=A jelenlegi kijelölés legalább [gb] GB lemezterületet igényel. +ComponentsDiskSpaceMBLabel=A jelenlegi kijelölés legalább [mb] MB lemezterületet igényel. + +; *** "Select Additional Tasks" wizard page +WizardSelectTasks=További feladatok +SelectTasksDesc=Mely kiegészítő feladatok kerüljenek végrehajtásra? +SelectTasksLabel2=Jelölje ki, mely kiegészítő feladatokat hajtsa végre a Telepítő a(z) [name] telepítése során, majd kattintson a 'Tovább'-ra. + +; *** "Select Start Menu Folder" wizard page +WizardSelectProgramGroup=Start Menü könyvtára +SelectStartMenuFolderDesc=Hova helyezze a Telepítő a program parancsikonjait? +SelectStartMenuFolderLabel3=A Telepítő a program parancsikonjait a Start menü következő mappájában fogja létrehozni. +SelectStartMenuFolderBrowseLabel=A folytatáshoz kattintson a 'Tovább'-ra. Ha másik mappát választana, kattintson a 'Tallózás'-ra. +MustEnterGroupName=Meg kell adnia egy mappanevet. +GroupNameTooLong=A könyvtár neve vagy az útvonal túl hosszú. +InvalidGroupName=A könyvtár neve érvénytelen. +BadGroupName=A könyvtárak nevei ezen karakterek egyikét sem tartalmazhatják:%n%n%1 +NoProgramGroupCheck2=&Ne hozzon létre mappát a Start menüben + +; *** "Ready to Install" wizard page +WizardReady=Készen állunk a telepítésre +ReadyLabel1=A Telepítő készen áll, a(z) [name] számítógépre telepítéshez. +ReadyLabel2a=Kattintson a 'Telepítés'-re a folytatáshoz, vagy a "Vissza"-ra a beállítások áttekintéséhez vagy megváltoztatásához. +ReadyLabel2b=Kattintson a 'Telepítés'-re a folytatáshoz. +ReadyMemoUserInfo=Felhasználó adatai: +ReadyMemoDir=Telepítés célkönyvtára: +ReadyMemoType=Telepítés típusa: +ReadyMemoComponents=Választott összetevők: +ReadyMemoGroup=Start menü mappája: +ReadyMemoTasks=Kiegészítő feladatok: + +; *** "Preparing to Install" wizard page +WizardPreparing=Felkészülés a telepítésre +PreparingDesc=A Telepítő felkészül a(z) [name] számítógépre történő telepítéshez. +PreviousInstallNotCompleted=gy korábbi program telepítése/eltávolítása nem fejeződött be. Újra kell indítania a számítógépét a másik telepítés befejezéséhez.%n%nA számítógépe újraindítása után ismét futtassa a Telepítőt a(z) [name] telepítésének befejezéséhez. +CannotContinue=A telepítés nem folytatható. A kilépéshez kattintson a 'Mégse'-re +ApplicationsFound=A következő alkalmazások olyan fájlokat használnak, amelyeket a Telepítőnek frissíteni kell. Ajánlott, hogy engedélyezze a Telepítőnek ezen alkalmazások automatikus bezárását. +ApplicationsFound2=A következő alkalmazások olyan fájlokat használnak, amelyeket a Telepítőnek frissíteni kell. Ajánlott, hogy engedélyezze a Telepítőnek ezen alkalmazások automatikus bezárását. A telepítés befejezése után a Telepítő megkísérli az alkalmazások újraindítását. +CloseApplications=&Alkalmazások automatikus bezárása +DontCloseApplications=&Ne zárja be az alkalmazásokat +ErrorCloseApplications=A Telepítő nem tudott minden alkalmazást automatikusan bezárni. A folytatás előtt ajánlott minden, a Telepítő által frissítendő fájlokat használó alkalmazást bezárni. +PrepareToInstallNeedsRestart=A telepítőnek újra kell indítania a számítógépet. Újraindítást követően, futtassa újból a telepítőt, a [name] telepítésének befejezéséhez .%n%nÚjra szeretné indítani most a számítógépet? + +; *** "Installing" wizard page +WizardInstalling=Telepítés +InstallingLabel=Kérem várjon, amíg a(z) [name] telepítése zajlik. + +; *** "Setup Completed" wizard page +FinishedHeadingLabel=A(z) [name] telepítésének befejezése +FinishedLabelNoIcons=A Telepítő végzett a(z) [name] telepítésével. +FinishedLabel=A Telepítő végzett a(z) [name] telepítésével. Az alkalmazást a létrehozott ikonok kiválasztásával indíthatja. +ClickFinish=Kattintson a 'Befejezés'-re a kilépéshez. +FinishedRestartLabel=A(z) [name] telepítésének befejezéséhez újra kell indítani a számítógépet. Újraindítja most? +FinishedRestartMessage=A(z) [name] telepítésének befejezéséhez, a Telepítőnek újra kell indítani a számítógépet.%n%nÚjraindítja most? +ShowReadmeCheck=Igen, szeretném elolvasni a FONTOS fájlt +YesRadio=&Igen, újraindítás most +NoRadio=&Nem, később indítom újra +; used for example as 'Run MyProg.exe' +RunEntryExec=%1 futtatása +; used for example as 'View Readme.txt' +RunEntryShellExec=%1 megtekintése + +; *** "Setup Needs the Next Disk" stuff +ChangeDiskTitle=A Telepítőnek szüksége van a következő lemezre +SelectDiskLabel2=Helyezze be a(z) %1. lemezt és kattintson az 'OK'-ra.%n%nHa a fájlok a lemez egy a megjelenítettől különböző mappájában találhatók, írja be a helyes útvonalat vagy kattintson a 'Tallózás'-ra. +PathLabel=Ú&tvonal: +FileNotInDir2=A(z) "%1" fájl nem található a következő helyen: "%2". Helyezze be a megfelelő lemezt vagy válasszon egy másik mappát. +SelectDirectoryLabel=Adja meg a következő lemez helyét. + +; *** Installation phase messages +SetupAborted=A telepítés nem fejeződött be.%n%nHárítsa el a hibát és futtassa újból a Telepítőt. +AbortRetryIgnoreSelectAction=Válasszon műveletet +AbortRetryIgnoreRetry=&Újra +AbortRetryIgnoreIgnore=&Hiba elvetése és folytatás +AbortRetryIgnoreCancel=Telepítés megszakítása + +; *** Installation status messages +StatusClosingApplications=Alkalmazások bezárása... +StatusCreateDirs=Könyvtárak létrehozása... +StatusExtractFiles=Fájlok kibontása... +StatusCreateIcons=Parancsikonok létrehozása... +StatusCreateIniEntries=INI bejegyzések létrehozása... +StatusCreateRegistryEntries=Rendszerleíró bejegyzések létrehozása... +StatusRegisterFiles=Fájlok regisztrálása... +StatusSavingUninstall=Eltávolító információk mentése... +StatusRunProgram=Telepítés befejezése... +StatusRestartingApplications=Alkalmazások újraindítása... +StatusRollback=Változtatások visszavonása... + +; *** Misc. errors +ErrorInternal2=Belső hiba: %1 +ErrorFunctionFailedNoCode=Sikertelen %1 +ErrorFunctionFailed=Sikertelen %1; kód: %2 +ErrorFunctionFailedWithMessage=Sikertelen %1; kód: %2.%n%3 +ErrorExecutingProgram=Nem hajtható végre a fájl:%n%1 + +; *** Registry errors +ErrorRegOpenKey=Nem nyitható meg a rendszerleíró kulcs:%n%1\%2 +ErrorRegCreateKey=Nem hozható létre a rendszerleíró kulcs:%n%1\%2 +ErrorRegWriteKey=Nem módosítható a rendszerleíró kulcs:%n%1\%2 + +; *** INI errors +ErrorIniEntry=Bejegyzés létrehozása sikertelen a következő INI fájlban: "%1". + +; *** File copying errors +FileAbortRetryIgnoreSkipNotRecommended=&Fájl kihagyása (nem ajánlott) +FileAbortRetryIgnoreIgnoreNotRecommended=&Hiba elvetése és folytatás (nem ajánlott) +SourceIsCorrupted=A forrásfájl megsérült +SourceDoesntExist=A(z) "%1" forrásfájl nem létezik +ExistingFileReadOnly2=A fájl csak olvashatóként van jelölve. +ExistingFileReadOnlyRetry=Csak &olvasható tulajdonság eltávolítása és újra próbálkozás +ExistingFileReadOnlyKeepExisting=&Létező fájl megtartása +ErrorReadingExistingDest=Hiba lépett fel a fájl olvasása közben: +FileExists=A fájl már létezik.%n%nFelül kívánja írni? +ExistingFileNewer=A létező fájl újabb a telepítésre kerülőnél. Ajánlott a létező fájl megtartása.%n%nMeg kívánja tartani a létező fájlt? +ErrorChangingAttr=Hiba lépett fel a fájl attribútumának módosítása közben: +ErrorCreatingTemp=Hiba lépett fel a fájl telepítési könyvtárban történő létrehozása közben: +ErrorReadingSource=Hiba lépett fel a forrásfájl olvasása közben: +ErrorCopying=Hiba lépett fel a fájl másolása közben: +ErrorReplacingExistingFile=Hiba lépett fel a létező fájl cseréje közben: +ErrorRestartReplace=A fájl cseréje az újraindítás után sikertelen volt: +ErrorRenamingTemp=Hiba lépett fel fájl telepítési könyvtárban történő átnevezése közben: +ErrorRegisterServer=Nem lehet regisztrálni a DLL-t/OCX-et: %1 +ErrorRegSvr32Failed=Sikertelen RegSvr32. A visszaadott kód: %1 +ErrorRegisterTypeLib=Nem lehet regisztrálni a típustárat: %1 + +; *** Uninstall display name markings +; used for example as 'My Program (32-bit)' +UninstallDisplayNameMark=%1 (%2) +; used for example as 'My Program (32-bit, All users)' +UninstallDisplayNameMarks=%1 (%2, %3) +UninstallDisplayNameMark32Bit=32-bit +UninstallDisplayNameMark64Bit=64-bit +UninstallDisplayNameMarkAllUsers=Minden felhasználó +UninstallDisplayNameMarkCurrentUser=Jelenlegi felhasználó + +; *** Post-installation errors +ErrorOpeningReadme=Hiba lépett fel a FONTOS fájl megnyitása közben. +ErrorRestartingComputer=A Telepítő nem tudta újraindítani a számítógépet. Indítsa újra kézileg. + +; *** Uninstaller messages +UninstallNotFound=A(z) "%1" fájl nem létezik. Nem távolítható el. +UninstallOpenError=A(z) "%1" fájl nem nyitható meg. Nem távolítható el. +UninstallUnsupportedVer=A(z) "%1" eltávolítási naplófájl formátumát nem tudja felismerni az eltávolító jelen verziója. Az eltávolítás nem folytatható +UninstallUnknownEntry=Egy ismeretlen bejegyzés (%1) található az eltávolítási naplófájlban +ConfirmUninstall=Biztosan el kívánja távolítani a(z) %1 programot és minden összetevőjét? +UninstallOnlyOnWin64=Ezt a telepítést csak 64-bites Windowson lehet eltávolítani. +OnlyAdminCanUninstall=Ezt a telepítést csak adminisztrációs jogokkal rendelkező felhasználó távolíthatja el. +UninstallStatusLabel=Legyen türelemmel, amíg a(z) %1 számítógépéről történő eltávolítása befejeződik. +UninstalledAll=A(z) %1 sikeresen el lett távolítva a számítógépről. +UninstalledMost=A(z) %1 eltávolítása befejeződött.%n%nNéhány elemet nem lehetett eltávolítani. Törölje kézileg. +UninstalledAndNeedsRestart=A(z) %1 eltávolításának befejezéséhez újra kell indítania a számítógépét.%n%nÚjraindítja most? +UninstallDataCorrupted=A(z) "%1" fájl sérült. Nem távolítható el. + +; *** Uninstallation phase messages +ConfirmDeleteSharedFileTitle=Törli a megosztott fájlt? +ConfirmDeleteSharedFile2=A rendszer azt jelzi, hogy a következő megosztott fájlra már nincs szüksége egyetlen programnak sem. Eltávolítja a megosztott fájlt?%n%nHa más programok még mindig használják a megosztott fájlt, akkor az eltávolítása után lehet, hogy nem fognak megfelelően működni. Ha bizonytalan, válassza a Nemet. A fájl megtartása nem okoz problémát a rendszerben. +SharedFileNameLabel=Fájlnév: +SharedFileLocationLabel=Helye: +WizardUninstalling=Eltávolítás állapota +StatusUninstalling=%1 eltávolítása... + +; *** Shutdown block reasons +ShutdownBlockReasonInstallingApp=%1 telepítése. +ShutdownBlockReasonUninstallingApp=%1 eltávolítása. + +; The custom messages below aren't used by Setup itself, but if you make +; use of them in your scripts, you'll want to translate them. + +[CustomMessages] + +NameAndVersion=%1, verzió: %2 +AdditionalIcons=További parancsikonok: +CreateDesktopIcon=&Asztali ikon létrehozása +CreateQuickLaunchIcon=&Gyorsindító parancsikon létrehozása +ProgramOnTheWeb=%1 az interneten +UninstallProgram=Eltávolítás - %1 +LaunchProgram=Indítás %1 +AssocFileExtension=A(z) %1 &társítása a(z) %2 fájlkiterjesztéssel +AssocingFileExtension=A(z) %1 társítása a(z) %2 fájlkiterjesztéssel... +AutoStartProgramGroupDescription=Indítópult: +AutoStartProgram=%1 automatikus indítása +AddonHostProgramNotFound=A(z) %1 nem található a kiválasztott könyvtárban.%n%nMindenképpen folytatja? diff --git a/build/win32/i18n/Default.isl b/build/win32/i18n/Default.isl deleted file mode 100644 index 370da6b37c..0000000000 --- a/build/win32/i18n/Default.isl +++ /dev/null @@ -1,336 +0,0 @@ -; *** Inno Setup version 5.5.3+ English messages *** -; -; To download user-contributed translations of this file, go to: -; http://www.jrsoftware.org/files/istrans/ -; -; Note: When translating this text, do not add periods (.) to the end of -; messages that didn't have them already, because on those messages Inno -; Setup adds the periods automatically (appending a period would result in -; two periods being displayed). - -[LangOptions] -; The following three entries are very important. Be sure to read and -; understand the '[LangOptions] section' topic in the help file. -LanguageName=English -LanguageID=$0409 -LanguageCodePage=0 -; If the language you are translating to requires special font faces or -; sizes, uncomment any of the following entries and change them accordingly. -;DialogFontName= -;DialogFontSize=8 -;WelcomeFontName=Verdana -;WelcomeFontSize=12 -;TitleFontName=Arial -;TitleFontSize=29 -;CopyrightFontName=Arial -;CopyrightFontSize=8 - -[Messages] - -; *** Application titles -SetupAppTitle=Setup -SetupWindowTitle=Setup - %1 -UninstallAppTitle=Uninstall -UninstallAppFullTitle=%1 Uninstall - -; *** Misc. common -InformationTitle=Information -ConfirmTitle=Confirm -ErrorTitle=Error - -; *** SetupLdr messages -SetupLdrStartupMessage=This will install %1. Do you wish to continue? -LdrCannotCreateTemp=Unable to create a temporary file. Setup aborted -LdrCannotExecTemp=Unable to execute file in the temporary directory. Setup aborted - -; *** Startup error messages -LastErrorMessage=%1.%n%nError %2: %3 -SetupFileMissing=The file %1 is missing from the installation directory. Please correct the problem or obtain a new copy of the program. -SetupFileCorrupt=The setup files are corrupted. Please obtain a new copy of the program. -SetupFileCorruptOrWrongVer=The setup files are corrupted, or are incompatible with this version of Setup. Please correct the problem or obtain a new copy of the program. -InvalidParameter=An invalid parameter was passed on the command line:%n%n%1 -SetupAlreadyRunning=Setup is already running. -WindowsVersionNotSupported=This program does not support the version of Windows your computer is running. -WindowsServicePackRequired=This program requires %1 Service Pack %2 or later. -NotOnThisPlatform=This program will not run on %1. -OnlyOnThisPlatform=This program must be run on %1. -OnlyOnTheseArchitectures=This program can only be installed on versions of Windows designed for the following processor architectures:%n%n%1 -MissingWOW64APIs=The version of Windows you are running does not include functionality required by Setup to perform a 64-bit installation. To correct this problem, please install Service Pack %1. -WinVersionTooLowError=This program requires %1 version %2 or later. -WinVersionTooHighError=This program cannot be installed on %1 version %2 or later. -AdminPrivilegesRequired=You must be logged in as an administrator when installing this program. -PowerUserPrivilegesRequired=You must be logged in as an administrator or as a member of the Power Users group when installing this program. -SetupAppRunningError=Setup has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit. -UninstallAppRunningError=Uninstall has detected that %1 is currently running.%n%nPlease close all instances of it now, then click OK to continue, or Cancel to exit. - -; *** Misc. errors -ErrorCreatingDir=Setup was unable to create the directory "%1" -ErrorTooManyFilesInDir=Unable to create a file in the directory "%1" because it contains too many files - -; *** Setup common messages -ExitSetupTitle=Exit Setup -ExitSetupMessage=Setup is not complete. If you exit now, the program will not be installed.%n%nYou may run Setup again at another time to complete the installation.%n%nExit Setup? -AboutSetupMenuItem=&About Setup... -AboutSetupTitle=About Setup -AboutSetupMessage=%1 version %2%n%3%n%n%1 home page:%n%4 -AboutSetupNote= -TranslatorNote= - -; *** Buttons -ButtonBack=< &Back -ButtonNext=&Next > -ButtonInstall=&Install -ButtonOK=OK -ButtonCancel=Cancel -ButtonYes=&Yes -ButtonYesToAll=Yes to &All -ButtonNo=&No -ButtonNoToAll=N&o to All -ButtonFinish=&Finish -ButtonBrowse=&Browse... -ButtonWizardBrowse=B&rowse... -ButtonNewFolder=&Make New Folder - -; *** "Select Language" dialog messages -SelectLanguageTitle=Select Setup Language -SelectLanguageLabel=Select the language to use during the installation: - -; *** Common wizard text -ClickNext=Click Next to continue, or Cancel to exit Setup. -BeveledLabel= -BrowseDialogTitle=Browse For Folder -BrowseDialogLabel=Select a folder in the list below, then click OK. -NewFolderName=New Folder - -; *** "Welcome" wizard page -WelcomeLabel1=Welcome to the [name] Setup Wizard -WelcomeLabel2=This will install [name/ver] on your computer.%n%nIt is recommended that you close all other applications before continuing. - -; *** "Password" wizard page -WizardPassword=Password -PasswordLabel1=This installation is password protected. -PasswordLabel3=Please provide the password, then click Next to continue. Passwords are case-sensitive. -PasswordEditLabel=&Password: -IncorrectPassword=The password you entered is not correct. Please try again. - -; *** "License Agreement" wizard page -WizardLicense=License Agreement -LicenseLabel=Please read the following important information before continuing. -LicenseLabel3=Please read the following License Agreement. You must accept the terms of this agreement before continuing with the installation. -LicenseAccepted=I &accept the agreement -LicenseNotAccepted=I &do not accept the agreement - -; *** "Information" wizard pages -WizardInfoBefore=Information -InfoBeforeLabel=Please read the following important information before continuing. -InfoBeforeClickLabel=When you are ready to continue with Setup, click Next. -WizardInfoAfter=Information -InfoAfterLabel=Please read the following important information before continuing. -InfoAfterClickLabel=When you are ready to continue with Setup, click Next. - -; *** "User Information" wizard page -WizardUserInfo=User Information -UserInfoDesc=Please enter your information. -UserInfoName=&User Name: -UserInfoOrg=&Organization: -UserInfoSerial=&Serial Number: -UserInfoNameRequired=You must enter a name. - -; *** "Select Destination Location" wizard page -WizardSelectDir=Select Destination Location -SelectDirDesc=Where should [name] be installed? -SelectDirLabel3=Setup will install [name] into the following folder. -SelectDirBrowseLabel=To continue, click Next. If you would like to select a different folder, click Browse. -DiskSpaceMBLabel=At least [mb] MB of free disk space is required. -CannotInstallToNetworkDrive=Setup cannot install to a network drive. -CannotInstallToUNCPath=Setup cannot install to a UNC path. -InvalidPath=You must enter a full path with drive letter; for example:%n%nC:\APP%n%nor a UNC path in the form:%n%n\\server\share -InvalidDrive=The drive or UNC share you selected does not exist or is not accessible. Please select another. -DiskSpaceWarningTitle=Not Enough Disk Space -DiskSpaceWarning=Setup requires at least %1 KB of free space to install, but the selected drive only has %2 KB available.%n%nDo you want to continue anyway? -DirNameTooLong=The folder name or path is too long. -InvalidDirName=The folder name is not valid. -BadDirName32=Folder names cannot include any of the following characters:%n%n%1 -DirExistsTitle=Folder Exists -DirExists=The folder:%n%n%1%n%nalready exists. Would you like to install to that folder anyway? -DirDoesntExistTitle=Folder Does Not Exist -DirDoesntExist=The folder:%n%n%1%n%ndoes not exist. Would you like the folder to be created? - -; *** "Select Components" wizard page -WizardSelectComponents=Select Components -SelectComponentsDesc=Which components should be installed? -SelectComponentsLabel2=Select the components you want to install; clear the components you do not want to install. Click Next when you are ready to continue. -FullInstallation=Full installation -; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language) -CompactInstallation=Compact installation -CustomInstallation=Custom installation -NoUninstallWarningTitle=Components Exist -NoUninstallWarning=Setup has detected that the following components are already installed on your computer:%n%n%1%n%nDeselecting these components will not uninstall them.%n%nWould you like to continue anyway? -ComponentSize1=%1 KB -ComponentSize2=%1 MB -ComponentsDiskSpaceMBLabel=Current selection requires at least [mb] MB of disk space. - -; *** "Select Additional Tasks" wizard page -WizardSelectTasks=Select Additional Tasks -SelectTasksDesc=Which additional tasks should be performed? -SelectTasksLabel2=Select the additional tasks you would like Setup to perform while installing [name], then click Next. - -; *** "Select Start Menu Folder" wizard page -WizardSelectProgramGroup=Select Start Menu Folder -SelectStartMenuFolderDesc=Where should Setup place the program's shortcuts? -SelectStartMenuFolderLabel3=Setup will create the program's shortcuts in the following Start Menu folder. -SelectStartMenuFolderBrowseLabel=To continue, click Next. If you would like to select a different folder, click Browse. -MustEnterGroupName=You must enter a folder name. -GroupNameTooLong=The folder name or path is too long. -InvalidGroupName=The folder name is not valid. -BadGroupName=The folder name cannot include any of the following characters:%n%n%1 -NoProgramGroupCheck2=&Don't create a Start Menu folder - -; *** "Ready to Install" wizard page -WizardReady=Ready to Install -ReadyLabel1=Setup is now ready to begin installing [name] on your computer. -ReadyLabel2a=Click Install to continue with the installation, or click Back if you want to review or change any settings. -ReadyLabel2b=Click Install to continue with the installation. -ReadyMemoUserInfo=User information: -ReadyMemoDir=Destination location: -ReadyMemoType=Setup type: -ReadyMemoComponents=Selected components: -ReadyMemoGroup=Start Menu folder: -ReadyMemoTasks=Additional tasks: - -; *** "Preparing to Install" wizard page -WizardPreparing=Preparing to Install -PreparingDesc=Setup is preparing to install [name] on your computer. -PreviousInstallNotCompleted=The installation/removal of a previous program was not completed. You will need to restart your computer to complete that installation.%n%nAfter restarting your computer, run Setup again to complete the installation of [name]. -CannotContinue=Setup cannot continue. Please click Cancel to exit. -ApplicationsFound=The following applications are using files that need to be updated by Setup. It is recommended that you allow Setup to automatically close these applications. -ApplicationsFound2=The following applications are using files that need to be updated by Setup. It is recommended that you allow Setup to automatically close these applications. After the installation has completed, Setup will attempt to restart the applications. -CloseApplications=&Automatically close the applications -DontCloseApplications=&Do not close the applications -ErrorCloseApplications=Setup was unable to automatically close all applications. It is recommended that you close all applications using files that need to be updated by Setup before continuing. - -; *** "Installing" wizard page -WizardInstalling=Installing -InstallingLabel=Please wait while Setup installs [name] on your computer. - -; *** "Setup Completed" wizard page -FinishedHeadingLabel=Completing the [name] Setup Wizard -FinishedLabelNoIcons=Setup has finished installing [name] on your computer. -FinishedLabel=Setup has finished installing [name] on your computer. The application may be launched by selecting the installed icons. -ClickFinish=Click Finish to exit Setup. -FinishedRestartLabel=To complete the installation of [name], Setup must restart your computer. Would you like to restart now? -FinishedRestartMessage=To complete the installation of [name], Setup must restart your computer.%n%nWould you like to restart now? -ShowReadmeCheck=Yes, I would like to view the README file -YesRadio=&Yes, restart the computer now -NoRadio=&No, I will restart the computer later -; used for example as 'Run MyProg.exe' -RunEntryExec=Run %1 -; used for example as 'View Readme.txt' -RunEntryShellExec=View %1 - -; *** "Setup Needs the Next Disk" stuff -ChangeDiskTitle=Setup Needs the Next Disk -SelectDiskLabel2=Please insert Disk %1 and click OK.%n%nIf the files on this disk can be found in a folder other than the one displayed below, enter the correct path or click Browse. -PathLabel=&Path: -FileNotInDir2=The file "%1" could not be located in "%2". Please insert the correct disk or select another folder. -SelectDirectoryLabel=Please specify the location of the next disk. - -; *** Installation phase messages -SetupAborted=Setup was not completed.%n%nPlease correct the problem and run Setup again. -EntryAbortRetryIgnore=Click Retry to try again, Ignore to proceed anyway, or Abort to cancel installation. - -; *** Installation status messages -StatusClosingApplications=Closing applications... -StatusCreateDirs=Creating directories... -StatusExtractFiles=Extracting files... -StatusCreateIcons=Creating shortcuts... -StatusCreateIniEntries=Creating INI entries... -StatusCreateRegistryEntries=Creating registry entries... -StatusRegisterFiles=Registering files... -StatusSavingUninstall=Saving uninstall information... -StatusRunProgram=Finishing installation... -StatusRestartingApplications=Restarting applications... -StatusRollback=Rolling back changes... - -; *** Misc. errors -ErrorInternal2=Internal error: %1 -ErrorFunctionFailedNoCode=%1 failed -ErrorFunctionFailed=%1 failed; code %2 -ErrorFunctionFailedWithMessage=%1 failed; code %2.%n%3 -ErrorExecutingProgram=Unable to execute file:%n%1 - -; *** Registry errors -ErrorRegOpenKey=Error opening registry key:%n%1\%2 -ErrorRegCreateKey=Error creating registry key:%n%1\%2 -ErrorRegWriteKey=Error writing to registry key:%n%1\%2 - -; *** INI errors -ErrorIniEntry=Error creating INI entry in file "%1". - -; *** File copying errors -FileAbortRetryIgnore=Click Retry to try again, Ignore to skip this file (not recommended), or Abort to cancel installation. -FileAbortRetryIgnore2=Click Retry to try again, Ignore to proceed anyway (not recommended), or Abort to cancel installation. -SourceIsCorrupted=The source file is corrupted -SourceDoesntExist=The source file "%1" does not exist -ExistingFileReadOnly=The existing file is marked as read-only.%n%nClick Retry to remove the read-only attribute and try again, Ignore to skip this file, or Abort to cancel installation. -ErrorReadingExistingDest=An error occurred while trying to read the existing file: -FileExists=The file already exists.%n%nWould you like Setup to overwrite it? -ExistingFileNewer=The existing file is newer than the one Setup is trying to install. It is recommended that you keep the existing file.%n%nDo you want to keep the existing file? -ErrorChangingAttr=An error occurred while trying to change the attributes of the existing file: -ErrorCreatingTemp=An error occurred while trying to create a file in the destination directory: -ErrorReadingSource=An error occurred while trying to read the source file: -ErrorCopying=An error occurred while trying to copy a file: -ErrorReplacingExistingFile=An error occurred while trying to replace the existing file: -ErrorRestartReplace=RestartReplace failed: -ErrorRenamingTemp=An error occurred while trying to rename a file in the destination directory: -ErrorRegisterServer=Unable to register the DLL/OCX: %1 -ErrorRegSvr32Failed=RegSvr32 failed with exit code %1 -ErrorRegisterTypeLib=Unable to register the type library: %1 - -; *** Post-installation errors -ErrorOpeningReadme=An error occurred while trying to open the README file. -ErrorRestartingComputer=Setup was unable to restart the computer. Please do this manually. - -; *** Uninstaller messages -UninstallNotFound=File "%1" does not exist. Cannot uninstall. -UninstallOpenError=File "%1" could not be opened. Cannot uninstall -UninstallUnsupportedVer=The uninstall log file "%1" is in a format not recognized by this version of the uninstaller. Cannot uninstall -UninstallUnknownEntry=An unknown entry (%1) was encountered in the uninstall log -ConfirmUninstall=Are you sure you want to completely remove %1? Extensions and settings will not be removed. -UninstallOnlyOnWin64=This installation can only be uninstalled on 64-bit Windows. -OnlyAdminCanUninstall=This installation can only be uninstalled by a user with administrative privileges. -UninstallStatusLabel=Please wait while %1 is removed from your computer. -UninstalledAll=%1 was successfully removed from your computer. -UninstalledMost=%1 uninstall complete.%n%nSome elements could not be removed. These can be removed manually. -UninstalledAndNeedsRestart=To complete the uninstallation of %1, your computer must be restarted.%n%nWould you like to restart now? -UninstallDataCorrupted="%1" file is corrupted. Cannot uninstall - -; *** Uninstallation phase messages -ConfirmDeleteSharedFileTitle=Remove Shared File? -ConfirmDeleteSharedFile2=The system indicates that the following shared file is no longer in use by any programs. Would you like for Uninstall to remove this shared file?%n%nIf any programs are still using this file and it is removed, those programs may not function properly. If you are unsure, choose No. Leaving the file on your system will not cause any harm. -SharedFileNameLabel=File name: -SharedFileLocationLabel=Location: -WizardUninstalling=Uninstall Status -StatusUninstalling=Uninstalling %1... - -; *** Shutdown block reasons -ShutdownBlockReasonInstallingApp=Installing %1. -ShutdownBlockReasonUninstallingApp=Uninstalling %1. - -; The custom messages below aren't used by Setup itself, but if you make -; use of them in your scripts, you'll want to translate them. - -[CustomMessages] - -NameAndVersion=%1 version %2 -AdditionalIcons=Additional icons: -CreateDesktopIcon=Create a &desktop icon -CreateQuickLaunchIcon=Create a &Quick Launch icon -ProgramOnTheWeb=%1 on the Web -UninstallProgram=Uninstall %1 -LaunchProgram=Launch %1 -AssocFileExtension=&Associate %1 with the %2 file extension -AssocingFileExtension=Associating %1 with the %2 file extension... -AutoStartProgramGroupDescription=Startup: -AutoStartProgram=Automatically start %1 -AddonHostProgramNotFound=%1 could not be located in the folder you selected.%n%nDo you want to continue anyway? diff --git a/build/win32/i18n/Default.ko.isl b/build/win32/i18n/Default.ko.isl index a7c38d12b9..0f1b1a7ccf 100644 --- a/build/win32/i18n/Default.ko.isl +++ b/build/win32/i18n/Default.ko.isl @@ -1,12 +1,16 @@ -; *** Inno Setup version 5.5.3+ Korean messages *** -; -; To download user-contributed translations of this file, go to: -; http://www.jrsoftware.org/files/istrans/ +; *** Inno Setup version 6.0.0+ Korean messages *** ; +; ˘Ć 6.0.3+ Translator: SungDong Kim (acroedit@gmail.com) +; ˘Ć 5.5.3+ Translator: Domddol (domddol@gmail.com) +; ˘Ć Translation date: MAR 04, 2014 +; ˘Ć Contributors: Hansoo KIM (iryna7@gmail.com), Woong-Jae An (a183393@hanmail.net) +; ˘Ć Storage: http://www.jrsoftware.org/files/istrans/ +; ˘Ć ŔĚ šřżŞŔş ťőˇÎżî ÇŃąšžî ¸ÂĂăšý ąÔĢŔť ÁŘźöÇŐ´Ď´Ů. ; Note: When translating this text, do not add periods (.) to the end of ; messages that didn't have them already, because on those messages Inno ; Setup adds the periods automatically (appending a period would result in ; two periods being displayed). + [LangOptions] ; The following three entries are very important. Be sure to read and ; understand the '[LangOptions] section' topic in the help file. @@ -23,50 +27,68 @@ LanguageCodePage=949 ;TitleFontSize=29 ;CopyrightFontName=Arial ;CopyrightFontSize=8 + [Messages] + ; *** Application titles SetupAppTitle=źłÄĄ -SetupWindowTitle=źłÄĄ - %1 +SetupWindowTitle=%1 źłÄĄ UninstallAppTitle=ÁŚ°Ĺ UninstallAppFullTitle=%1 ÁŚ°Ĺ + ; *** Misc. common InformationTitle=Á¤ş¸ ConfirmTitle=ČŽŔÎ ErrorTitle=żŔˇů + ; *** SetupLdr messages -SetupLdrStartupMessage=ą×ˇŻ¸é %1ŔĚ(°Ą) źłÄĄľË´Ď´Ů. °čźÓÇϽðڽŔ´Ďąî? -LdrCannotCreateTemp=Ŕӽà ĆÄŔĎŔť ¸¸ľé źö žř˝Ŕ´Ď´Ů. źłÄĄ ÇÁˇÎą×ˇĽŔĚ ÁߴܾǞú˝Ŕ´Ď´Ů. -LdrCannotExecTemp=Ŕӽà ľđˇşĹÍ¸ŽżĄź­ ĆÄŔĎŔť ˝ÇÇŕÇŇ źö žř˝Ŕ´Ď´Ů. źłÄĄ ÇÁˇÎą×ˇĽŔĚ ÁߴܾǞú˝Ŕ´Ď´Ů. +SetupLdrStartupMessage=%1Ŕť(¸Ś) źłÄĄÇŐ´Ď´Ů, °čźÓÇϽðڽŔ´Ďąî? +LdrCannotCreateTemp=Ŕӽà ĆÄŔĎŔť ¸¸ľé źö žř˝Ŕ´Ď´Ů, źłÄĄ¸Ś Áß´ÜÇŐ´Ď´Ů +LdrCannotExecTemp=Ŕӽà Ćú´őŔÇ ĆÄŔĎŔť ˝ÇÇŕÇŇ źö žř˝Ŕ´Ď´Ů, źłÄĄ¸Ś Áß´ÜÇŐ´Ď´Ů +HelpTextNote= + ; *** Startup error messages LastErrorMessage=%1.%n%nżŔˇů %2: %3 -SetupFileMissing=ĆÄŔĎ %1ŔĚ(°Ą) źłÄĄ ľđˇşĹÍ¸ŽżĄź­ ´ŠśôľÇžú˝Ŕ´Ď´Ů. šŽÁŚ¸Ś ÇذáÇĎ°ĹłŞ ÇÁˇÎą×ˇĽŔť ťőˇÎ šŢŔ¸źźżä. -SetupFileCorrupt=źłÄĄ ĆÄŔĎŔĚ źŐťóľÇžú˝Ŕ´Ď´Ů. ÇÁˇÎą×ˇĽŔť ťőˇÎ šŢŔ¸źźżä. -SetupFileCorruptOrWrongVer=źłÄĄ ĆÄŔĎŔĚ źŐťóľÇžú°ĹłŞ ŔĚ šöŔüŔÇ źłÄĄ ÇÁˇÎą×ˇĽ°ú ČŁČŻľÇÁö žĘ˝Ŕ´Ď´Ů. šŽÁŚ¸Ś ÇذáÇĎ°ĹłŞ ÇÁˇÎą×ˇĽŔť ťőˇÎ šŢŔ¸źźżä. -InvalidParameter=¸íˇÉÁŮżĄ Ŕ߸řľČ ¸Ĺ°ł şŻźö°Ą Ŕü´ŢľĘ:%n%n%1 -SetupAlreadyRunning=źłÄĄ ÇÁˇÎą×ˇĽŔĚ ŔĚšĚ ˝ÇÇŕ ÁßŔÔ´Ď´Ů. -WindowsVersionNotSupported=ŔĚ ÇÁˇÎą×ˇĽŔş ÄÄÇťĹÍżĄź­ ˝ÇÇŕ ÁßŔÎ šöŔüŔÇ Windows¸Ś ÁöżřÇĎÁö žĘ˝Ŕ´Ď´Ů. -WindowsServicePackRequired=ŔĚ ÇÁˇÎą×ˇĽŔť źłÄĄÇϡÁ¸é %1 ź­şń˝ş ĆŃ %2 ŔĚťóŔĚ ÇĘżäÇŐ´Ď´Ů. -NotOnThisPlatform=ŔĚ ÇÁˇÎą×ˇĽŔş %1żĄź­ ˝ÇÇŕľÇÁö žĘ˝Ŕ´Ď´Ů. +SetupFileMissing=%1 ĆÄŔĎŔĚ Á¸ŔçÇĎÁö žĘ˝Ŕ´Ď´Ů, šŽÁŚ¸Ś ÇذáÇŘ ş¸°ĹłŞ ťőˇÎżî źłÄĄ ÇÁˇÎą×ˇĽŔť ą¸ÇϽù⠚ٜř´Ď´Ů. +SetupFileCorrupt=źłÄĄ ĆÄŔĎŔĚ źŐťóľÇžú˝Ŕ´Ď´Ů, ťőˇÎżî źłÄĄ ÇÁˇÎą×ˇĽŔť ą¸ÇϽù⠚ٜř´Ď´Ů. +SetupFileCorruptOrWrongVer=źłÄĄ ĆÄŔĎŔÇ źŐťóŔĚ°ĹłŞ ŔĚ źłÄĄ šöŔü°ú ČŁČŻľÇÁö žĘ˝Ŕ´Ď´Ů, šŽÁŚ¸Ś ÇذáÇŘ ş¸°ĹłŞ ťőˇÎżî źłÄĄ ÇÁˇÎą×ˇĽŔť ą¸ÇϽù⠚ٜř´Ď´Ů. +InvalidParameter=Ŕ߸řľČ ¸Ĺ°ł şŻźöŔÔ´Ď´Ů:%n%n%1 +SetupAlreadyRunning=źłÄĄ°Ą ŔĚšĚ ˝ÇÇŕ ÁßŔÔ´Ď´Ů. +WindowsVersionNotSupported=ŔĚ ÇÁˇÎą×ˇĽŔş ąÍÇĎŔÇ Windows šöŔüŔť ÁöżřÇĎÁö žĘ˝Ŕ´Ď´Ů. +WindowsServicePackRequired=ŔĚ ÇÁˇÎą×ˇĽŔť ˝ÇÇŕÇϡÁ¸é %1 sp%2 ŔĚťóŔĚžîžß ÇŐ´Ď´Ů. +NotOnThisPlatform=ŔĚ ÇÁˇÎą×ˇĽŔş %1żĄź­ ŔŰľżÇĎÁö žĘ˝Ŕ´Ď´Ů. OnlyOnThisPlatform=ŔĚ ÇÁˇÎą×ˇĽŔş %1żĄź­ ˝ÇÇŕÇŘžß ÇŐ´Ď´Ů. -OnlyOnTheseArchitectures=ŔĚ ÇÁˇÎą×ˇĽŔş ÇÁˇÎźźź­ žĆŰĹŘĂł %n%n%1żëŔ¸ˇÎ źł°čľČ Windows šöŔüżĄź­¸¸ źłÄĄÇŇ źö ŔÖ˝Ŕ´Ď´Ů. -MissingWOW64APIs=˝ÇÇŕ ÁßŔÎ Windows šöŔüżĄ´Â źłÄĄ ÇÁˇÎą×ˇĽżĄź­ 64şńĆŽ¸Ś źłÄĄÇĎ´Â ľĽ ÇĘżäÇŃ ąâ´ÉŔĚ žř˝Ŕ´Ď´Ů. ŔĚ šŽÁŚ¸Ś ÇذáÇϡÁ¸é ź­şń˝ş ĆŃ %1Ŕť(¸Ś) źłÄĄÇĎźźżä. -WinVersionTooLowError=ŔĚ ÇÁˇÎą×ˇĽŔť źłÄĄÇϡÁ¸é %1 šöŔü %2 ŔĚťóŔĚ ÇĘżäÇŐ´Ď´Ů. -WinVersionTooHighError=ŔĚ ÇÁˇÎą×ˇĽŔş %1 šöŔü %2 Ŕ̝󿥟­´Â źłÄĄÇŇ źö žř˝Ŕ´Ď´Ů. -AdminPrivilegesRequired=ŔĚ ÇÁˇÎą×ˇĽŔť źłÄĄÇŇ ś§´Â °ü¸ŽŔڡΠˇÎą×ŔÎÇŘžß ÇŐ´Ď´Ů. -PowerUserPrivilegesRequired=ŔĚ ÇÁˇÎą×ˇĽŔť źłÄĄÇŇ ś§´Â °ü¸ŽŔÚłŞ °íąŢ ťçżëŔÚ ą×ˇěŔÇ ą¸źşżřŔ¸ˇÎ ˇÎą×ŔÎÇŘžß ÇŐ´Ď´Ů. -SetupAppRunningError=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ %1(ŔĚ)°Ą ÇöŔç ˝ÇÇŕ ÁßŔÓŔť °¨ÁöÇß˝Ŕ´Ď´Ů.%n%nŔĚ Ç׸ńŔÇ ¸đľç ŔνşĹĎ˝ş¸Ś ÁöąÝ ´Ý°í °čźÓÇϡÁ¸é [ČŽŔÎ]Ŕť, ÁžˇáÇϡÁ¸é [ĂëźŇ]¸Ś ĹŹ¸ŻÇĎźźżä. -UninstallAppRunningError=ÁŚ°Ĺ ŔŰž÷żĄź­ %1(ŔĚ)°Ą ÇöŔç ˝ÇÇŕ ÁßŔÓŔť °¨ÁöÇß˝Ŕ´Ď´Ů.%n%nŔĚ Ç׸ńŔÇ ¸đľç ŔνşĹĎ˝ş¸Ś ÁöąÝ ´Ý°í °čźÓÇϡÁ¸é [ČŽŔÎ]Ŕť, ÁžˇáÇϡÁ¸é [ĂëźŇ]¸Ś ĹŹ¸ŻÇĎźźżä. +OnlyOnTheseArchitectures=ŔĚ ÇÁˇÎą×ˇĽŔş žĆˇĄ Ăł¸Ž ą¸ÁśżÍ ČŁČŻľÇ´Â Windows šöŔüżĄ¸¸ źłÄĄÇŇ źö ŔÖ˝Ŕ´Ď´Ů:%n%n%1 +WinVersionTooLowError=ŔĚ ÇÁˇÎą×ˇĽŔş %1 šöŔü %2 ŔĚťóŔĚ ÇĘżäÇŐ´Ď´Ů. +WinVersionTooHighError=ŔĚ ÇÁˇÎą×ˇĽŔş %1 šöŔü %2 Ŕ̝󿥟­ źłÄĄÇŇ źö žř˝Ŕ´Ď´Ů. +AdminPrivilegesRequired=ŔĚ ÇÁˇÎą×ˇĽŔť źłÄĄÇϡÁ¸é °ü¸ŽŔڡΠˇÎą×ŔÎÇŘžß ÇŐ´Ď´Ů. +PowerUserPrivilegesRequired=ŔĚ ÇÁˇÎą×ˇĽŔť źłÄĄÇϡÁ¸é °ü¸ŽŔÚ śÇ´Â °íąŢ ťçżëŔڡΠˇÎą×ŔÎÇŘžß ÇŐ´Ď´Ů. +SetupAppRunningError=ÇöŔç %1ŔĚ(°Ą) ˝ÇÇŕ ÁßŔÔ´Ď´Ů!%n%nÁöąÝ ą×°ÍŔÇ ¸đľç ŔνşĹĎ˝ş¸Ś ´ÝžĆ ÁֽʽÿŔ. ą×ˇą ´ŮŔ˝ °čźÓÇϡÁ¸é "ČŽŔÎ"Ŕť, ÁžˇáÇϡÁ¸é "ĂëźŇ"¸Ś ĹŹ¸ŻÇϽʽÿŔ. +UninstallAppRunningError=ÇöŔç %1ŔĚ(°Ą) ˝ÇÇŕ ÁßŔÔ´Ď´Ů!%n%nÁöąÝ ą×°ÍŔÇ ¸đľç ŔνşĹĎ˝ş¸Ś ´ÝžĆ ÁֽʽÿŔ. ą×ˇą ´ŮŔ˝ °čźÓÇϡÁ¸é "ČŽŔÎ"Ŕť, ÁžˇáÇϡÁ¸é "ĂëźŇ"¸Ś ĹŹ¸ŻÇϽʽÿŔ. + +; *** Startup questions +PrivilegesRequiredOverrideTitle=źłÄĄ ¸đľĺ źąĹĂ +PrivilegesRequiredOverrideInstruction=źłÄĄ ¸đľĺ¸Ś źąĹĂÇŘ ÁֽʽÿŔ +PrivilegesRequiredOverrideText1=%1 Ŕş ¸đľç ťçżëŔÚ(°ü¸ŽŔÚ ąÇÇŃ ÇĘżä) śÇ´Â ÇöŔç ťçżëŔÚżëŔ¸ˇÎ źłÄĄÇŐ´Ď´Ů. +PrivilegesRequiredOverrideText2=%1 Ŕş ÇöŔç ťçżëŔÚ śÇ´Â ¸đľç ťçżëŔÚ(°ü¸ŽŔÚ ąÇÇŃ ÇĘżä) żëŔ¸ˇÎ źłÄĄÇŐ´Ď´Ů. +PrivilegesRequiredOverrideAllUsers=¸đľç ťçżëŔÚżëŔ¸ˇÎ źłÄĄ(&A) +PrivilegesRequiredOverrideAllUsersRecommended=¸đľç ťçżëŔÚżëŔ¸ˇÎ źłÄĄ(&A) (ĂßĂľ) +PrivilegesRequiredOverrideCurrentUser=ÇöŔç ťçżëŔÚżëŔ¸ˇÎ źłÄĄ(&M) +PrivilegesRequiredOverrideCurrentUserRecommended=ÇöŔç ťçżëŔÚżëŔ¸ˇÎ źłÄĄ(&M) (ĂßĂľ) + ; *** Misc. errors -ErrorCreatingDir=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ľđˇşĹÍ¸Ž "%1"Ŕť(¸Ś) ¸¸ľé źö žř˝Ŕ´Ď´Ů. -ErrorTooManyFilesInDir=ľđˇşĹÍ¸Ž "%1"żĄ ĆÄŔĎŔĚ łĘšŤ ¸šŔ¸šÇˇÎ ŔĚ ľđˇşĹÍ¸ŽżĄ ĆÄŔĎŔť ¸¸ľé źö žř˝Ŕ´Ď´Ů. +ErrorCreatingDir="%1" Ćú´ő¸Ś ¸¸ľé źö žř˝Ŕ´Ď´Ů. +ErrorTooManyFilesInDir="%1" Ćú´őżĄ ĆÄŔĎŔĚ łĘšŤ ¸šąâ ś§šŽżĄ ĆÄŔĎŔť ¸¸ľé źö žř˝Ŕ´Ď´Ů. + ; *** Setup common messages -ExitSetupTitle=źłÄĄ Ážˇá -ExitSetupMessage=źłÄĄ°Ą żĎˇáľÇÁö žĘžŇ˝Ŕ´Ď´Ů. ÁöąÝ ÁžˇáÇϸé ÇÁˇÎą×ˇĽŔĚ źłÄĄľÇÁö žĘ˝Ŕ´Ď´Ů.%n%nłŞÁßżĄ źłÄĄ ÇÁˇÎą×ˇĽŔť ´Ů˝Ă ˝ÇÇŕÇĎżŠ źłÄĄ¸Ś łĄłž źö ŔÖ˝Ŕ´Ď´Ů.%n%nźłÄĄ ÇÁˇÎą×ˇĽŔť ÁžˇáÇϽðڽŔ´Ďąî? -AboutSetupMenuItem=źłÄĄ ÇÁˇÎą×ˇĽ Á¤ş¸(&A)... -AboutSetupTitle=źłÄĄ ÇÁˇÎą×ˇĽ Á¤ş¸ -AboutSetupMessage=%1 šöŔü %2%n%3%n%n%1 ȨĆäŔĚÁö:%n%4 +ExitSetupTitle=źłÄĄ żĎˇá +ExitSetupMessage=źłÄĄ°Ą żĎˇáľÇÁö žĘžŇ˝Ŕ´Ď´Ů, żŠąâź­ źłÄĄ¸Ś ÁžˇáÇϸé ÇÁˇÎą×ˇĽŔş źłÄĄľÇÁö žĘ˝Ŕ´Ď´Ů.%n%nźłÄĄ¸Ś żĎˇáÇϡÁ¸é łŞÁßżĄ ´Ů˝Ă źłÄĄ ÇÁˇÎą×ˇĽŔť ˝ÇÇŕÇŘžß ÇŐ´Ď´Ů.%n%ną×ˇĄľľ źłÄĄ¸Ś ÁžˇáÇϽðڽŔ´Ďąî? +AboutSetupMenuItem=źłÄĄ Á¤ş¸(&A)... +AboutSetupTitle=źłÄĄ Á¤ş¸ +AboutSetupMessage=%1 šöŔü %2%n%3%n%n%1 Ȩ ĆäŔĚÁö:%n%4 AboutSetupNote= TranslatorNote= + ; *** Buttons ButtonBack=< ľÚˇÎ(&B) ButtonNext=´ŮŔ˝(&N) > @@ -75,224 +97,271 @@ ButtonOK=ČŽ ButtonCancel=ĂëźŇ ButtonYes=żš(&Y) ButtonYesToAll=¸đľÎ żš(&A) -ButtonNo=žĆ´Ďżä(&N) -ButtonNoToAll=¸đľÎ žĆ´Ďżä(&O) -ButtonFinish=¸śÄ§(&F) +ButtonNo=žĆ´ĎżŔ(&N) +ButtonNoToAll=¸đľÎ žĆ´ĎżŔ(&O) +ButtonFinish=Ážˇá(&F) ButtonBrowse=ĂŁžĆş¸ąâ(&B)... -ButtonWizardBrowse=ĂŁžĆş¸ąâ(&R) +ButtonWizardBrowse=ĂŁžĆş¸ąâ(&R)... ButtonNewFolder=ťő Ćú´ő ¸¸ľéąâ(&M) + ; *** "Select Language" dialog messages SelectLanguageTitle=źłÄĄ žđžî źąĹĂ -SelectLanguageLabel=źłÄĄ ÁßżĄ ťçżëÇŇ žđžî¸Ś źąĹĂÇĎźźżä. +SelectLanguageLabel=źłÄĄżĄ ťçżëÇŇ žđžî¸Ś źąĹĂÇϽʽÿŔ. + ; *** Common wizard text -ClickNext=°čźÓÇϡÁ¸é [´ŮŔ˝]Ŕť ĹŹ¸ŻÇĎ°í źłÄĄ ÇÁˇÎą×ˇĽŔť ÁžˇáÇϡÁ¸é [ĂëźŇ]¸Ś ĹŹ¸ŻÇĎźźżä. +ClickNext=°čźÓÇϡÁ¸é "´ŮŔ˝"Ŕť ĹŹ¸ŻÇĎ°í źłÄĄ¸Ś ÁžˇáÇϡÁ¸é "ĂëźŇ"¸Ś ĹŹ¸ŻÇŐ´Ď´Ů. BeveledLabel= BrowseDialogTitle=Ćú´ő ĂŁžĆş¸ąâ -BrowseDialogLabel=žĆˇĄ ¸ńˇĎżĄź­ Ćú´ő¸Ś źąĹĂÇŃ ´ŮŔ˝ [ČŽŔÎ]Ŕť ĹŹ¸ŻÇĎźźżä. +BrowseDialogLabel=žĆˇĄ ¸ńˇĎżĄź­ Ćú´ő¸Ś źąĹĂÇŃ ´ŮŔ˝ "ČŽŔÎ"Ŕť ĹŹ¸ŻÇŐ´Ď´Ů. NewFolderName=ťő Ćú´ő + ; *** "Welcome" wizard page WelcomeLabel1=[name] źłÄĄ ¸śšýťç ˝ĂŔŰ -WelcomeLabel2=ŔĚ ¸śšýťç´Â ÄÄÇťĹÍżĄ [name/ver]Ŕť(¸Ś) źłÄĄÇŐ´Ď´Ů.%n%n°čźÓÇĎąâ ŔüżĄ ´Ů¸Ľ ¸đľç ŔŔżë ÇÁˇÎą×ˇĽŔť ´Ý´Â °ÍŔĚ ÁÁ˝Ŕ´Ď´Ů. +WelcomeLabel2=ŔĚ ¸śšýťç´Â ąÍÇĎŔÇ ÄÄÇťĹÍżĄ [name/ver]Ŕť(¸Ś) źłÄĄÇŇ °ÍŔÔ´Ď´Ů.%n%nźłÄĄÇĎąâ ŔüżĄ ´Ů¸Ľ ŔŔżëÇÁˇÎą×ˇĽľéŔť ¸đľÎ ´ÝŔ¸˝Ăąâ šŮśř´Ď´Ů. + ; *** "Password" wizard page -WizardPassword=žĎČŁ -PasswordLabel1=ŔĚ źłÄĄ´Â žĎČŁˇÎ ş¸ČŁľÇ°í ŔÖ˝Ŕ´Ď´Ů. -PasswordLabel3=°čźÓÇϡÁ¸é žĎČŁ¸Ś ŔÔˇÂÇŃ ´ŮŔ˝ [´ŮŔ˝]Ŕť ĹŹ¸ŻÇĎźźżä. žĎČŁ´Â ´ëźŇšŽŔÚ¸Ś ą¸şĐÇŐ´Ď´Ů. -PasswordEditLabel=žĎČŁ(&P): -IncorrectPassword=ŔÔˇÂÇŃ žĎČŁ°Ą Ŕ߸řľÇžú˝Ŕ´Ď´Ů. ´Ů˝Ă ˝ĂľľÇĎźźżä. +WizardPassword=şńšĐ šřČŁ +PasswordLabel1=ŔĚ źłÄĄ ¸śšýťç´Â şńšĐ šřČŁˇÎ ş¸ČŁľÇžî ŔÖ˝Ŕ´Ď´Ů. +PasswordLabel3=şńšĐ šřČŁ¸Ś ŔÔˇÂÇϰí "´ŮŔ˝"Ŕť ĹŹ¸ŻÇϽʽÿŔ. şńšĐ šřČŁ´Â ´ëźŇšŽŔÚ¸Ś ą¸şĐÇŘžß ÇŐ´Ď´Ů. +PasswordEditLabel=şńšĐ šřČŁ(&P): +IncorrectPassword=şńšĐ šřČŁ°Ą Á¤ČŽÇĎÁö žĘ˝Ŕ´Ď´Ů, ´Ů˝Ă ŔÔˇÂÇϽʽÿŔ. + ; *** "License Agreement" wizard page WizardLicense=ťçżëąÇ °čžŕ -LicenseLabel=°čźÓÇĎąâ ŔüżĄ ´ŮŔ˝ ÁßżäÇŃ Á¤ş¸¸Ś ŔĐžî ş¸źźżä. -LicenseLabel3=´ŮŔ˝ ťçżëąÇ °čžŕŔť ŔĐžî ÁÖźźżä. źłÄĄ¸Ś °čźÓÇϡÁ¸é ¸ŐŔú ŔĚ °čžŕ Áś°ÇżĄ ľżŔÇÇŘžß ÇŐ´Ď´Ů. -LicenseAccepted=°čžŕżĄ ľżŔÇÇÔ(&A) -LicenseNotAccepted=°čžŕżĄ ľżŔÇ žČ ÇÔ(&D) +LicenseLabel=°čźÓÇĎąâ ŔüżĄ ´ŮŔ˝ŔÇ Áßżä Á¤ş¸¸Ś ŔО˝Ę˝ĂżŔ. +LicenseLabel3=´ŮŔ˝ ťçżëąÇ °čžŕŔť ŔО˝Ę˝ĂżŔ, źłÄĄ¸Ś °čźÓÇϡÁ¸é ŔĚ °čžŕżĄ ľżŔÇÇŘžß ÇŐ´Ď´Ů. +LicenseAccepted=ľżŔÇÇŐ´Ď´Ů(&A) +LicenseNotAccepted=ľżŔÇÇĎÁö žĘ˝Ŕ´Ď´Ů(&D) + ; *** "Information" wizard pages WizardInfoBefore=Á¤ş¸ -InfoBeforeLabel=°čźÓÇĎąâ ŔüżĄ ´ŮŔ˝ ÁßżäÇŃ Á¤ş¸¸Ś ŔĐžî ş¸źźżä. -InfoBeforeClickLabel=źłÄĄ¸Ś °čźÓ ÁřÇŕÇŇ ÁŘşń°Ą ľÇ¸é [´ŮŔ˝]Ŕť ĹŹ¸ŻÇŐ´Ď´Ů. +InfoBeforeLabel=°čźÓÇĎąâ ŔüżĄ ´ŮŔ˝ŔÇ Áßżä Á¤ş¸¸Ś ŔО˝Ę˝ĂżŔ. +InfoBeforeClickLabel=źłÄĄ¸Ś °čźÓÇϡÁ¸é "´ŮŔ˝"Ŕť ĹŹ¸ŻÇϽʽÿŔ. WizardInfoAfter=Á¤ş¸ -InfoAfterLabel=°čźÓÇĎąâ ŔüżĄ ´ŮŔ˝ ÁßżäÇŃ Á¤ş¸¸Ś ŔĐžî ş¸źźżä. -InfoAfterClickLabel=źłÄĄ¸Ś °čźÓ ÁřÇŕÇŇ ÁŘşń°Ą ľÇ¸é [´ŮŔ˝]Ŕť ĹŹ¸ŻÇŐ´Ď´Ů. +InfoAfterLabel=°čźÓÇĎąâ ŔüżĄ ´ŮŔ˝ŔÇ Áßżä Á¤ş¸¸Ś ŔО˝Ę˝ĂżŔ. +InfoAfterClickLabel=źłÄĄ¸Ś °čźÓÇϡÁ¸é "´ŮŔ˝"Ŕť ĹŹ¸ŻÇϽʽÿŔ. + ; *** "User Information" wizard page WizardUserInfo=ťçżëŔÚ Á¤ş¸ -UserInfoDesc=Á¤ş¸¸Ś ŔÔˇÂÇĎźźżä. +UserInfoDesc=ťçżëŔÚ Á¤ş¸¸Ś ŔÔˇÂÇϽʽÿŔ. UserInfoName=ťçżëŔÚ Ŕ̸§(&U): UserInfoOrg=ÁśÁ÷(&O): -UserInfoSerial=Ŕϡà šřČŁ(&S): -UserInfoNameRequired=Ŕ̸§Ŕť ŔÔˇÂÇŘžß ÇŐ´Ď´Ů. +UserInfoSerial=˝Ă¸Žžó šřČŁ(&S): +UserInfoNameRequired=ťçżëŔÚ Ŕ̸§Ŕť ŔÔˇÂÇϽʽÿŔ. + ; *** "Select Destination Location" wizard page -WizardSelectDir=´ëťó Ŕ§ÄĄ źąĹĂ -SelectDirDesc=[name]Ŕť(¸Ś) žîľđżĄ źłÄĄÇϽðڽŔ´Ďąî? -SelectDirLabel3=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ [name]Ŕť(¸Ś) ´ŮŔ˝ Ćú´őżĄ źłÄĄÇŐ´Ď´Ů. -SelectDirBrowseLabel=°čźÓÇϡÁ¸é [´ŮŔ˝]Ŕť ĹŹ¸ŻÇĎźźżä. ´Ů¸Ľ Ćú´ő¸Ś źąĹĂÇϡÁ¸é [ĂŁžĆş¸ąâ]¸Ś ĹŹ¸ŻÇĎźźżä. -DiskSpaceMBLabel=Ŕűžîľľ [mb]MBŔÇ żŠŔŻ ľđ˝şĹŠ °ř°ŁŔĚ ÇĘżäÇŐ´Ď´Ů. -CannotInstallToNetworkDrive=źłÄĄ ÇÁˇÎą×ˇĽŔş ł×ĆŽżöĹŠ ľĺśóŔ̺꿥 źłÄĄÇŇ źö žř˝Ŕ´Ď´Ů. -CannotInstallToUNCPath=źłÄĄ ÇÁˇÎą×ˇĽŔş UNC °ćˇÎżĄ źłÄĄÇŇ źö žř˝Ŕ´Ď´Ů. -InvalidPath=ľĺśóŔĚşę šŽŔÚżÍ ÇÔ˛˛ ŔüĂź °ćˇÎ¸Ś ŔÔˇÂÇŘžß ÇŐ´Ď´Ů. żš:%n%nC:\APP%n%nśÇ´Â ´ŮŔ˝ ÇüĹÂŔÇ UNC °ćˇÎ:%n%n\\server\share -InvalidDrive=źąĹĂÇŃ ľĺśóŔ̺곪 UNC °řŔݰĄ žř°ĹłŞ ŔĚ ľÎ Ç׸ńżĄ ž×źź˝şÇŇ źö žř˝Ŕ´Ď´Ů. ´Ů¸Ľ ľĺśóŔ̺곪 UNC °řŔŻ¸Ś źąĹĂÇĎźźżä. -DiskSpaceWarningTitle=ľđ˝şĹŠ °ř°Ł şÎÁˇ -DiskSpaceWarning=źłÄĄ ÇÁˇÎą×ˇĽŔť źłÄĄÇϡÁ¸é żŠŔŻ źłÄĄ °ř°ŁŔĚ Ŕűžîľľ %1KB°Ą ÇĘżäÇĎÁö¸¸ źąĹĂÇŃ ľĺśóŔĚşęŔÇ °Ążë °ř°ŁŔş %2KBšŰżĄ žř˝Ŕ´Ď´Ů.%n%ną×ˇĄľľ °čźÓÇϽðڽŔ´Ďąî? +WizardSelectDir=źłÄĄ Ŕ§ÄĄ źąĹĂ +SelectDirDesc=[name]ŔÇ źłÄĄ Ŕ§ÄĄ¸Ś źąĹĂÇϽʽÿŔ. +SelectDirLabel3=´ŮŔ˝ Ćú´őżĄ [name]Ŕť(¸Ś) źłÄĄÇŐ´Ď´Ů. +SelectDirBrowseLabel=°čźÓÇϡÁ¸é "´ŮŔ˝"Ŕť, ´Ů¸Ľ Ćú´ő¸Ś źąĹĂÇϡÁ¸é "ĂŁžĆş¸ąâ"¸Ś ĹŹ¸ŻÇϽʽÿŔ. +DiskSpaceGBLabel=ŔĚ ÇÁˇÎą×ˇĽŔş ĂÖźŇ [gb] GBŔÇ ľđ˝şĹŠ żŠŔŻ °ř°ŁŔĚ ÇĘżäÇŐ´Ď´Ů. +DiskSpaceMBLabel=ŔĚ ÇÁˇÎą×ˇĽŔş ĂÖźŇ [mb] MBŔÇ ľđ˝şĹŠ żŠŔŻ °ř°ŁŔĚ ÇĘżäÇŐ´Ď´Ů. +CannotInstallToNetworkDrive=ł×ĆŽżöĹŠ ľĺśóŔ̺꿥 źłÄĄÇŇ źö žř˝Ŕ´Ď´Ů. +CannotInstallToUNCPath=UNC °ćˇÎżĄ źłÄĄÇŇ źö žř˝Ŕ´Ď´Ů. +InvalidPath=ľĺśóŔĚşę šŽŔÚ¸Ś Ć÷ÇÔÇŃ ŔüĂź °ćˇÎ¸Ś ŔÔˇÂÇϽʽÿŔ.%nĄŘ żš: C:\APP %n%nśÇ´Â, UNC Çü˝ÄŔÇ °ćˇÎ¸Ś ŔÔˇÂÇϽʽÿŔ.%nĄŘ żš: \\server\share +InvalidDrive=źąĹĂÇŃ ľĺśóŔĚşę śÇ´Â UNC °řŔݰĄ Á¸ŔçÇĎÁö žĘ°ĹłŞ ž×źź˝şÇŇ źö žř˝Ŕ´Ď´Ů, ´Ů¸Ľ °ćˇÎ¸Ś źąĹĂÇϽʽÿŔ. +DiskSpaceWarningTitle=ľđ˝şĹŠ °ř°ŁŔĚ şÎÁˇÇŐ´Ď´Ů +DiskSpaceWarning=źłÄĄ ˝Ă ĂÖźŇ %1 KB ľđ˝şĹŠ °ř°ŁŔĚ ÇĘżäÇĎÁö¸¸, źąĹĂÇŃ ľĺśóŔĚşęŔÇ żŠŔŻ °ř°ŁŔş %2 KB šŰżĄ žř˝Ŕ´Ď´Ů.%n%ną×ˇĄľľ °čźÓÇϽðڽŔ´Ďąî? DirNameTooLong=Ćú´ő Ŕ̸§ śÇ´Â °ćˇÎ°Ą łĘšŤ ąé´Ď´Ů. -InvalidDirName=Ćú´ő Ŕ̸§ŔĚ Ŕ߸řľÇžú˝Ŕ´Ď´Ů. -BadDirName32=Ćú´ő Ŕ̸§żĄ´Â %n%n%1 šŽŔÚ¸Ś ťçżëÇŇ źö žř˝Ŕ´Ď´Ů. -DirExistsTitle=Ćú´ő ŔÖŔ˝ -DirExists=Ćú´ő %n%n%1%n%nŔĚ(°Ą) ŔĚšĚ ŔÖ˝Ŕ´Ď´Ů. ą×ˇĄľľ ÇŘ´ç Ćú´őżĄ źłÄĄÇϽðڽŔ´Ďąî? -DirDoesntExistTitle=Ćú´ő žřŔ˝ -DirDoesntExist=Ćú´ő %n%n%1%n%nŔĚ(°Ą) žř˝Ŕ´Ď´Ů. Ćú´ő¸Ś ¸¸ľĺ˝Ă°Ú˝Ŕ´Ďąî? +InvalidDirName=Ćú´ő Ŕ̸§ŔĚ ŔŻČżÇĎÁö žĘ˝Ŕ´Ď´Ů. +BadDirName32=Ćú´ő Ŕ̸§Ŕş ´ŮŔ˝ šŽŔÚ¸Ś Ć÷ÇÔÇŇ źö žř˝Ŕ´Ď´Ů:%n%n%1 +DirExistsTitle=Ćú´ő°Ą Á¸ŔçÇŐ´Ď´Ů +DirExists=Ćú´ő %n%n%1%n%nŔĚ(°Ą) ŔĚšĚ Á¸ŔçÇŐ´Ď´Ů, ŔĚ Ćú´őżĄ źłÄĄÇϽðڽŔ´Ďąî? +DirDoesntExistTitle=Ćú´ő°Ą Á¸ŔçÇĎÁö žĘ˝Ŕ´Ď´Ů +DirDoesntExist=Ćú´ő %n%n%1%n%nŔĚ(°Ą) Á¸ŔçÇĎÁö žĘ˝Ŕ´Ď´Ů, ťőˇÎ Ćú´ő¸Ś ¸¸ľĺ˝Ă°Ú˝Ŕ´Ďąî? + ; *** "Select Components" wizard page WizardSelectComponents=ą¸źş żäźŇ źąĹĂ -SelectComponentsDesc=žîś˛ ą¸źş żäźŇ¸Ś źłÄĄÇϽðڽŔ´Ďąî? -SelectComponentsLabel2=źłÄĄÇŇ ą¸źş żäźŇ´Â źąĹĂÇĎ°í źłÄĄÇĎÁö žĘŔť ą¸źş żäźŇ´Â Áöżěźźżä. °čźÓ ÁřÇŕÇŇ ÁŘşń°Ą ľÇ¸é [´ŮŔ˝]Ŕť ĹŹ¸ŻÇĎźźżä. -FullInstallation=ŔüĂź źłÄĄ +SelectComponentsDesc=źłÄĄÇŇ ą¸źş żäźŇ¸Ś źąĹĂÇϽʽÿŔ. +SelectComponentsLabel2=ÇĘżäÇŃ ą¸źş żäźŇ´Â ßŊÇĎ°í şŇÇĘżäÇŃ ą¸źş żäźŇ´Â ßŊ ÇŘÁŚÇŐ´Ď´Ů, °čźÓÇϡÁ¸é "´ŮŔ˝"Ŕť ĹŹ¸ŻÇϽʽÿŔ. +FullInstallation=¸đľÎ źłÄĄ ; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language) -CompactInstallation=Compact źłÄĄ +CompactInstallation=ĂÖźŇ źłÄĄ CustomInstallation=ťçżëŔÚ ÁöÁ¤ źłÄĄ -NoUninstallWarningTitle=ą¸źş żäźŇ°Ą ŔÖŔ˝ -NoUninstallWarning=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ą¸źş żäźŇ %n%n%1%n%nŔĚ(°Ą) ÄÄÇťĹÍżĄ ŔĚšĚ źłÄĄľÇžî ŔÖŔ˝Ŕť °¨ÁöÇß˝Ŕ´Ď´Ů. Ŕ̡ŻÇŃ ą¸źş żäźŇ´Â źąĹĂ ĂëźŇÇŘľľ ÁŚ°ĹľÇÁö žĘ˝Ŕ´Ď´Ů.%n%ną×ˇĄľľ °čźÓÇϽðڽŔ´Ďąî? -ComponentSize1=%1KB -ComponentSize2=%1MB -ComponentsDiskSpaceMBLabel=ÇöŔç źąĹĂŔť Ŕ§ÇŘź­´Â Ŕűžîľľ [mb]MBŔÇ ľđ˝şĹŠ °ř°ŁŔĚ ÇĘżäÇŐ´Ď´Ů. +NoUninstallWarningTitle=ą¸źş żäźŇ°Ą Á¸ŔçÇŐ´Ď´Ů +NoUninstallWarning=´ŮŔ˝ ą¸źş żäźŇ°Ą ŔĚšĚ źłÄĄľÇžî ŔÖ˝Ŕ´Ď´Ů:%n%n%1%n%nŔ§ ą¸źş żäźŇŔť źąĹĂÇĎÁö žĘŔ¸¸é, ÇÁˇÎą×ˇĽ ÁŚ°Ĺ˝Ă ŔĚ ą¸źş żäźŇľéŔş ÁŚ°ĹľÇÁö žĘŔť °Ě´Ď´Ů.%n%ną×ˇĄľľ °čźÓÇϽðڽŔ´Ďąî? +ComponentSize1=%1 KB +ComponentSize2=%1 MB +ComponentsDiskSpaceGBLabel=ÇöŔç źąĹĂŔş ĂÖźŇ [gb] GBŔÇ ľđ˝şĹŠ żŠŔŻ °ř°ŁŔĚ ÇĘżäÇŐ´Ď´Ů. +ComponentsDiskSpaceMBLabel=ÇöŔç źąĹĂŔş ĂÖźŇ [mb] MBŔÇ ľđ˝şĹŠ żŠŔŻ °ř°ŁŔĚ ÇĘżäÇŐ´Ď´Ů. + ; *** "Select Additional Tasks" wizard page WizardSelectTasks=Ăß°Ą ŔŰž÷ źąĹĂ -SelectTasksDesc=žîś˛ ŔŰž÷Ŕť Ăß°ĄˇÎ źöÇŕÇϽðڽŔ´Ďąî? -SelectTasksLabel2=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ [name]Ŕť(¸Ś) źłÄĄÇĎ´Â ľżžČ źöÇŕÇŇ Ăß°Ą ŔŰž÷Ŕť źąĹĂÇŃ ČÄ [´ŮŔ˝]Ŕť ĹŹ¸ŻÇĎźźżä. +SelectTasksDesc=źöÇŕÇŇ Ăß°Ą ŔŰž÷Ŕť źąĹĂÇϽʽÿŔ. +SelectTasksLabel2=[name] źłÄĄ °úÁ¤żĄ Ć÷ÇÔÇŇ Ăß°Ą ŔŰž÷Ŕť źąĹĂÇŃ ČÄ, "´ŮŔ˝"Ŕť ĹŹ¸ŻÇϽʽÿŔ. + ; *** "Select Start Menu Folder" wizard page WizardSelectProgramGroup=˝ĂŔŰ ¸Ţ´ş Ćú´ő źąĹĂ -SelectStartMenuFolderDesc=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ÇÁˇÎą×ˇĽŔÇ šŮˇÎ °Ąąâ¸Ś žîľđżĄ ¸¸ľéľľˇĎ ÇϽðڽŔ´Ďąî? -SelectStartMenuFolderLabel3=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ÇÁˇÎą×ˇĽŔÇ šŮˇÎ °Ąąâ¸Ś ´ŮŔ˝ ˝ĂŔŰ ¸Ţ´ş Ćú´őżĄ ¸¸ľě´Ď´Ů. -SelectStartMenuFolderBrowseLabel=°čźÓÇϡÁ¸é [´ŮŔ˝]Ŕť ĹŹ¸ŻÇĎźźżä. ´Ů¸Ľ Ćú´ő¸Ś źąĹĂÇϡÁ¸é [ĂŁžĆş¸ąâ]¸Ś ĹŹ¸ŻÇĎźźżä. -MustEnterGroupName=Ćú´ő Ŕ̸§Ŕť ŔÔˇÂÇŘžß ÇŐ´Ď´Ů. +SelectStartMenuFolderDesc=žîľđżĄ ÇÁˇÎą×ˇĽ šŮˇÎ°Ąąâ¸Ś Ŕ§ÄĄÇϰڽŔ´Ďąî? +SelectStartMenuFolderLabel3=´ŮŔ˝ ˝ĂŔŰ ¸Ţ´ş Ćú´őżĄ ÇÁˇÎą×ˇĽ šŮˇÎ°Ąąâ¸Ś ¸¸ľě´Ď´Ů. +SelectStartMenuFolderBrowseLabel=°čźÓÇϡÁ¸é "´ŮŔ˝"Ŕť ĹŹ¸ŻÇϰí, ´Ů¸Ľ Ćú´ő¸Ś źąĹĂÇϡÁ¸é "ĂŁžĆş¸ąâ"¸Ś ĹŹ¸ŻÇϽʽÿŔ. +MustEnterGroupName=Ćú´ő Ŕ̸§Ŕť ŔÔˇÂÇϽʽÿŔ. GroupNameTooLong=Ćú´ő Ŕ̸§ śÇ´Â °ćˇÎ°Ą łĘšŤ ąé´Ď´Ů. -InvalidGroupName=Ćú´ő Ŕ̸§ŔĚ Ŕ߸řľÇžú˝Ŕ´Ď´Ů. -BadGroupName=Ćú´ő Ŕ̸§żĄ´Â %n%n%1 šŽŔÚ¸Ś ťçżëÇŇ źö žř˝Ŕ´Ď´Ů. +InvalidGroupName=Ćú´ő Ŕ̸§ŔĚ ŔŻČżÇĎÁö žĘ˝Ŕ´Ď´Ů. +BadGroupName=Ćú´ő Ŕ̸§Ŕş ´ŮŔ˝ šŽŔÚ¸Ś Ć÷ÇÔÇŇ źö žř˝Ŕ´Ď´Ů:%n%n%1 NoProgramGroupCheck2=˝ĂŔŰ ¸Ţ´ş Ćú´ő¸Ś ¸¸ľéÁö žĘŔ˝(&D) + ; *** "Ready to Install" wizard page -WizardReady=źłÄĄ ÁŘşńľĘ -ReadyLabel1=ŔĚÁŚ źłÄĄ ÇÁˇÎą×ˇĽŔĚ ÄÄÇťĹÍżĄ [name] źłÄĄ¸Ś ˝ĂŔŰÇŇ ÁŘşń°Ą ľÇžú˝Ŕ´Ď´Ů. -ReadyLabel2a=źłÄĄ¸Ś °čźÓÇϡÁ¸é [źłÄĄ]¸Ś ĹŹ¸ŻÇϰí, źłÁ¤Ŕť °ËĹäÇĎ°ĹłŞ şŻ°ćÇϡÁ¸é [ľÚˇÎ]¸Ś ĹŹ¸ŻÇĎźźżä. -ReadyLabel2b=źłÄĄ¸Ś °čźÓÇϡÁ¸é [źłÄĄ]¸Ś ĹŹ¸ŻÇĎźźżä. +WizardReady=źłÄĄ ÁŘşń żĎˇá +ReadyLabel1=ąÍÇĎŔÇ ÄÄÇťĹÍżĄ [name]Ŕť(¸Ś) źłÄĄÇŇ ÁŘşń°Ą ľÇžú˝Ŕ´Ď´Ů. +ReadyLabel2a=źłÄĄ¸Ś °čźÓÇϡÁ¸é "źłÄĄ"¸Ś, źłÁ¤Ŕť şŻ°ćÇĎ°ĹłŞ °ËĹäÇϡÁ¸é "ľÚˇÎ"¸Ś ĹŹ¸ŻÇϽʽÿŔ. +ReadyLabel2b=źłÄĄ¸Ś °čźÓÇϡÁ¸é "źłÄĄ"¸Ś ĹŹ¸ŻÇϽʽÿŔ. ReadyMemoUserInfo=ťçżëŔÚ Á¤ş¸: -ReadyMemoDir=´ëťó Ŕ§ÄĄ: +ReadyMemoDir=źłÄĄ Ŕ§ÄĄ: ReadyMemoType=źłÄĄ ŔŻÇü: ReadyMemoComponents=źąĹĂÇŃ ą¸źş żäźŇ: ReadyMemoGroup=˝ĂŔŰ ¸Ţ´ş Ćú´ő: ReadyMemoTasks=Ăß°Ą ŔŰž÷: + ; *** "Preparing to Install" wizard page WizardPreparing=źłÄĄ ÁŘşń Áß -PreparingDesc=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ÄÄÇťĹÍżĄ [name] źłÄĄ¸Ś ÁŘşńÇϰí ŔÖ˝Ŕ´Ď´Ů. -PreviousInstallNotCompleted=ŔĚŔü ÇÁˇÎą×ˇĽŔÇ źłÄĄ/ÁŚ°Ĺ ŔŰž÷ŔĚ żĎˇáľÇÁö žĘžŇ˝Ŕ´Ď´Ů. ÇŘ´ç źłÄĄ¸Ś żĎˇáÇϡÁ¸é ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŘžß ÇŐ´Ď´Ů.%n%nÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŃ ČÄ [name] źłÄĄ¸Ś żĎˇáÇϡÁ¸é źłÄĄ ÇÁˇÎą×ˇĽŔť ´Ů˝Ă ˝ÇÇŕÇĎźźżä. -CannotContinue=źłÄĄ ÇÁˇÎą×ˇĽŔť °čźÓÇŇ źö žř˝Ŕ´Ď´Ů. ÁžˇáÇϡÁ¸é [ĂëźŇ]¸Ś ĹŹ¸ŻÇĎźźżä. -ApplicationsFound=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ž÷ľĽŔĚĆŽÇŘžß ÇĎ´Â ĆÄŔĎŔĚ ´ŮŔ˝ ŔŔżë ÇÁˇÎą×ˇĽżĄ ťçżëľÇ°í ŔÖ˝Ŕ´Ď´Ů. źłÄĄ ÇÁˇÎą×ˇĽżĄź­ Ŕ̡ŻÇŃ ŔŔżë ÇÁˇÎą×ˇĽŔť ŔÚľżŔ¸ˇÎ ´ÝľľˇĎ ÇăżëÇĎ´Â °ÍŔĚ ÁÁ˝Ŕ´Ď´Ů. -ApplicationsFound2=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ž÷ľĽŔĚĆŽÇŘžß ÇĎ´Â ĆÄŔĎŔĚ ´ŮŔ˝ ŔŔżë ÇÁˇÎą×ˇĽżĄ ťçżëľÇ°í ŔÖ˝Ŕ´Ď´Ů. źłÄĄ ÇÁˇÎą×ˇĽżĄź­ Ŕ̡ŻÇŃ ŔŔżë ÇÁˇÎą×ˇĽŔť ŔÚľżŔ¸ˇÎ ´ÝľľˇĎ ÇăżëÇĎ´Â °ÍŔĚ ÁÁ˝Ŕ´Ď´Ů. źłÄĄ°Ą żĎˇáľÇ¸é źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ŔŔżë ÇÁˇÎą×ˇĽŔť ´Ů˝Ă ˝ĂŔŰÇϡÁ°í ˝ĂľľÇŐ´Ď´Ů. -CloseApplications=ŔŔżë ÇÁˇÎą×ˇĽ ŔÚľż ´Ýąâ(&A) -DontCloseApplications=ŔŔżë ÇÁˇÎą×ˇĽŔť ´ÝÁö žĘŔ˝(&D) -ErrorCloseApplications=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ŔϺΠŔŔżë ÇÁˇÎą×ˇĽŔť ŔÚľżŔ¸ˇÎ ´ÝŔť źö žř˝Ŕ´Ď´Ů. °čźÓÇĎąâ ŔüżĄ źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ž÷ľĽŔĚĆŽÇŘžß ÇĎ´Â ĆÄŔĎŔť ťçżëÇĎ´Â ŔŔżë ÇÁˇÎą×ˇĽŔť ¸đľÎ ´Ý´Â °ÍŔĚ ÁÁ˝Ŕ´Ď´Ů. +PreparingDesc=ąÍÇĎŔÇ ÄÄÇťĹÍżĄ [name] źłÄĄ¸Ś ÁŘşńÇĎ´Â ÁßŔÔ´Ď´Ů. +PreviousInstallNotCompleted=ŔĚŔü ÇÁˇÎą×ˇĽŔÇ źłÄĄ/ÁŚ°Ĺ ŔŰž÷ŔĚ żĎˇáľÇÁö žĘžŇ˝Ŕ´Ď´Ů, żĎˇáÇϡÁ¸é ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŘžß ÇŐ´Ď´Ů.%n%nÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŃ ČÄ, źłÄĄ ¸śšýťç¸Ś ´Ů˝Ă ˝ÇÇŕÇĎżŠ [name] źłÄĄ¸Ś żĎˇáÇϽù⠚ٜř´Ď´Ů. +CannotContinue=źłÄĄ¸Ś °čźÓÇŇ źö žř˝Ŕ´Ď´Ů, "ĂëźŇ"¸Ś ĹŹ¸ŻÇĎżŠ źłÄĄ¸Ś ÁžˇáÇϽʽÿŔ. +ApplicationsFound=´ŮŔ˝ ŔŔżëÇÁˇÎą×ˇĽŔĚ źłÄĄ ž÷ľĽŔĚĆŽ°Ą ÇĘżäÇŃ ĆÄŔĎŔť ťçżëÇϰí ŔÖ˝Ŕ´Ď´Ů, źłÄĄ ¸śšýťç°Ą Ŕ̡ą ŔŔżëÇÁˇÎą×ˇĽŔť ŔÚľżŔ¸ˇÎ ÁžˇáÇŇ źö ŔÖľľˇĎ ÇăżëÇϽù⠚ٜř´Ď´Ů. +ApplicationsFound2=´ŮŔ˝ ŔŔżëÇÁˇÎą×ˇĽŔĚ źłÄĄ ž÷ľĽŔĚĆŽ°Ą ÇĘżäÇŃ ĆÄŔĎŔť ťçżëÇϰí ŔÖ˝Ŕ´Ď´Ů, źłÄĄ ¸śšýťç°Ą Ŕ̡ą ŔŔżëÇÁˇÎą×ˇĽŔť ŔÚľżŔ¸ˇÎ ÁžˇáÇŇ źö ŔÖľľˇĎ ÇăżëÇϽù⠚ٜř´Ď´Ů. źłÄĄ°Ą żĎˇáľÇ¸é, źłÄĄ ¸śšýťç´Â ŔĚ ŔŔżëÇÁˇÎą×ˇĽŔĚ ´Ů˝Ă ˝ĂŔ۾ǾľˇĎ ˝ĂľľÇŇ °Ě´Ď´Ů. +CloseApplications=ŔÚľżŔ¸ˇÎ ŔŔżëÇÁˇÎą×ˇĽŔť ÁžˇáÇÔ(&A) +DontCloseApplications=ŔŔżëÇÁˇÎą×ˇĽŔť ÁžˇáÇĎÁö žĘŔ˝(&D) +ErrorCloseApplications=źłÄĄ ¸śšýťç°Ą ŔŔżëÇÁˇÎą×ˇĽŔť ŔÚľżŔ¸ˇÎ ÁžˇáÇŇ źö žř˝Ŕ´Ď´Ů, °čźÓÇĎąâ ŔüżĄ źłÄĄ ž÷ľĽŔĚĆŽ°Ą ÇĘżäÇŃ ĆÄŔĎŔť ťçżëÇϰí ŔÖ´Â ŔŔżëÇÁˇÎą×ˇĽŔť ¸đľÎ ÁžˇáÇϽù⠚ٜř´Ď´Ů. +PrepareToInstallNeedsRestart=źłÄĄ ¸śšýťç´Â ąÍÇĎŔÇ ÄÄÇťĹÍ¸Ś Ŕç˝ĂŔŰÇŘžß ÇŐ´Ď´Ů. [name] źłÄĄ¸Ś żĎˇáÇĎąâ Ŕ§ÇŘ ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŃ ČÄżĄ źłÄĄ ¸śšýťç¸Ś ´Ů˝Ă ˝ÇÇŕÇŘ ÁֽʽÿŔ.%n%nÁöąÝ ´Ů˝Ă ˝ĂŔŰÇϽðڽŔ´Ďąî? + ; *** "Installing" wizard page WizardInstalling=źłÄĄ Áß -InstallingLabel=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ÄÄÇťĹÍżĄ [name]Ŕť(¸Ś) źłÄĄÇĎ´Â ľżžČ ąâ´ŮˇÁ ÁÖźźżä. +InstallingLabel=ąÍÇĎŔÇ ÄÄÇťĹÍżĄ [name]Ŕť(¸Ś) źłÄĄÇĎ´Â Áß... Ŕá˝Ă ąâ´ŮˇÁ ÁֽʽÿŔ. + ; *** "Setup Completed" wizard page -FinishedHeadingLabel=[name] źłÁ¤ ¸śšýťç¸Ś żĎˇáÇĎ´Â Áß -FinishedLabelNoIcons=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ÄÄÇťĹÍżĄ [name]Ŕť(¸Ś) źłÄĄÇß˝Ŕ´Ď´Ů. -FinishedLabel=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ÄÄÇťĹÍżĄ [name]Ŕť(¸Ś) źłÄĄÇß˝Ŕ´Ď´Ů. źłÄĄÇŃ šŮˇÎ °Ąąâ¸Ś źąĹĂÇĎżŠ ÇŘ´ç ŔŔżë ÇÁˇÎą×ˇĽŔť ˝ĂŔŰÇŇ źö ŔÖ˝Ŕ´Ď´Ů. -ClickFinish=źłÄĄ ÇÁˇÎą×ˇĽŔť ÁžˇáÇϡÁ¸é [¸śÄ§]Ŕť ĹŹ¸ŻÇĎźźżä. -FinishedRestartLabel=[name] źłÄĄ¸Ś żĎˇáÇϡÁ¸é źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŘžß ÇŐ´Ď´Ů. ÁöąÝ ´Ů˝Ă ˝ĂŔŰÇϽðڽŔ´Ďąî? -FinishedRestartMessage=[name] źłÄĄ¸Ś żĎˇáÇϡÁ¸é źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŘžß ÇŐ´Ď´Ů.%n%nÁöąÝ ´Ů˝Ă ˝ĂŔŰÇϽðڽŔ´Ďąî? -ShowReadmeCheck=żš, README ĆÄŔĎŔť ş¸°Ú˝Ŕ´Ď´Ů. -YesRadio=żš, ÄÄÇťĹÍ¸Ś ÁöąÝ ´Ů˝Ă ˝ĂŔŰÇϰڽŔ´Ď´Ů(&Y). -NoRadio=žĆ´Ďżä, ÄÄÇťĹÍ¸Ś łŞÁßżĄ ´Ů˝Ă ˝ĂŔŰÇϰڽŔ´Ď´Ů(&N). +FinishedHeadingLabel=[name] źłÄĄ ¸śšýťç żĎˇá +FinishedLabelNoIcons=ąÍÇĎŔÇ ÄÄÇťĹÍżĄ [name]ŔĚ(°Ą) źłÄĄľÇžú˝Ŕ´Ď´Ů. +FinishedLabel=ąÍÇĎŔÇ ÄÄÇťĹÍżĄ [name]ŔĚ(°Ą) źłÄĄľÇžú˝Ŕ´Ď´Ů, ŔŔżëÇÁˇÎą×ˇĽŔş źłÄĄľČ žĆŔĚÄÜŔť źąĹĂÇĎżŠ ˝ĂŔŰÇŇ źö ŔÖ˝Ŕ´Ď´Ů. +ClickFinish=źłÄĄ¸Ś łĄłťˇÁ¸é "Ážˇá"¸Ś ĹŹ¸ŻÇϽʽÿŔ. +FinishedRestartLabel=[name] źłÄĄ¸Ś żĎˇáÇϡÁ¸é, ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŘžß ÇŐ´Ď´Ů. ÁöąÝ ´Ů˝Ă ˝ĂŔŰÇϽðڽŔ´Ďąî? +FinishedRestartMessage=[name] źłÄĄ¸Ś żĎˇáÇϡÁ¸é, ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŘžß ÇŐ´Ď´Ů.%n%nÁöąÝ ´Ů˝Ă ˝ĂŔŰÇϽðڽŔ´Ďąî? +ShowReadmeCheck=żš, README ĆÄŔĎŔť ÇĽ˝ĂÇŐ´Ď´Ů +YesRadio=żš, ÁöąÝ ´Ů˝Ă ˝ĂŔŰÇŐ´Ď´Ů(&Y) +NoRadio=žĆ´ĎżŔ, łŞÁßżĄ ´Ů˝Ă ˝ĂŔŰÇŐ´Ď´Ů(&N) ; used for example as 'Run MyProg.exe' RunEntryExec=%1 ˝ÇÇŕ ; used for example as 'View Readme.txt' -RunEntryShellExec=%1 ş¸ąâ +RunEntryShellExec=%1 ÇĽ˝Ă + ; *** "Setup Needs the Next Disk" stuff -ChangeDiskTitle=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ´ŮŔ˝ ľđ˝şĹаĄ ÇĘżäÇÔ -SelectDiskLabel2=ľđ˝şĹŠ %1Ŕť(¸Ś) ťđŔÔÇŃ ´ŮŔ˝ [ČŽŔÎ]Ŕť ĹŹ¸ŻÇĎźźżä.%n%nŔĚ ľđ˝şĹŠŔÇ ĆÄŔĎŔĚ žĆˇĄ ÇĽ˝ĂľČ Ćú´ő°Ą žĆ´Ń ´Ů¸Ľ Ćú´őżĄ ŔÖŔ¸¸é żĂšŮ¸Ľ °ćˇÎ¸Ś ŔÔˇÂÇĎ°ĹłŞ [ĂŁžĆş¸ąâ]¸Ś ĹŹ¸ŻÇĎźźżä. +ChangeDiskTitle=ľđ˝şĹаĄ ÇĘżäÇŐ´Ď´Ů +SelectDiskLabel2=ľđ˝şĹŠ %1Ŕť(¸Ś) ťđŔÔÇϰí "ČŽŔÎ"Ŕť ĹŹ¸ŻÇϽʽÿŔ.%n%nŔĚ ľđ˝şĹŠ ťóŔÇ ĆÄŔĎŔĚ žĆˇĄ °ćˇÎ°Ą žĆ´Ń °÷żĄ ŔÖ´Â °ćżě, żĂšŮ¸Ľ °ćˇÎ¸Ś ŔÔˇÂÇĎ°ĹłŞ "ĂŁžĆş¸ąâ"¸Ś ĹŹ¸ŻÇϽù⠚ٜř´Ď´Ů. PathLabel=°ćˇÎ(&P): -FileNotInDir2="%2"żĄź­ ĆÄŔĎ "%1"Ŕť(¸Ś) ĂŁŔť źö žř˝Ŕ´Ď´Ů. żĂšŮ¸Ľ ľđ˝şĹŠ¸Ś ťđŔÔÇĎ°ĹłŞ ´Ů¸Ľ Ćú´ő¸Ś źąĹĂÇĎźźżä. -SelectDirectoryLabel=´ŮŔ˝ ľđ˝şĹŠŔÇ Ŕ§ÄĄ¸Ś ÁöÁ¤ÇĎźźżä. +FileNotInDir2=%2żĄ ĆÄŔĎ %1Ŕť(¸Ś) Ŕ§ÄĄÇŇ źö žř˝Ŕ´Ď´Ů, żĂšŮ¸Ľ ľđ˝şĹŠ¸Ś ťđŔÔÇĎ°ĹłŞ ´Ů¸Ľ Ćú´ő¸Ś źąĹĂÇϽʽÿŔ. +SelectDirectoryLabel=´ŮŔ˝ ľđ˝şĹŠŔÇ Ŕ§ÄĄ¸Ś ÁöÁ¤ÇϽʽÿŔ. + ; *** Installation phase messages -SetupAborted=źłÄĄ¸Ś żĎˇáÇĎÁö ¸řÇß˝Ŕ´Ď´Ů.%n%nšŽÁŚ¸Ś ÇذáÇŃ ´ŮŔ˝ źłÄĄ ÇÁˇÎą×ˇĽŔť ´Ů˝Ă ˝ÇÇŕÇĎźźżä. -EntryAbortRetryIgnore=´Ů˝Ă ˝ĂľľÇϡÁ¸é [´Ů˝Ă ˝Ăľľ]¸Ś, ą×ˇĄľľ °čźÓÇϡÁ¸é [šŤ˝Ă]¸Ś, źłÄĄ¸Ś ĂëźŇÇϡÁ¸é [Áß´Ü]Ŕť ĹŹ¸ŻÇĎźźżä. +SetupAborted=źłÄĄ°Ą żĎˇáľÇÁö žĘžŇ˝Ŕ´Ď´Ů.%n%nšŽÁŚ¸Ś ÇذáÇŃ ČÄ, ´Ů˝Ă źłÄĄ¸Ś ˝ĂŔŰÇϽʽÿŔ. +AbortRetryIgnoreSelectAction=ž×źÇŔť źąĹĂÇŘ ÁֽʽÿŔ. +AbortRetryIgnoreRetry=Ŕç˝Ăľľ(&T) +AbortRetryIgnoreIgnore=żŔˇů¸Ś šŤ˝ĂÇϰí ÁřÇŕ(&I) +AbortRetryIgnoreCancel=źłÄĄ ĂëźŇ + ; *** Installation status messages -StatusClosingApplications=ŔŔżë ÇÁˇÎą×ˇĽŔť ´Ý´Â Áß... -StatusCreateDirs=ľđˇşĹÍ¸Ž¸Ś ¸¸ľĺ´Â Áß... +StatusClosingApplications=ŔŔżëÇÁˇÎą×ˇĽŔť ÁžˇáÇĎ´Â Áß... +StatusCreateDirs=Ćú´ő¸Ś ¸¸ľĺ´Â Áß... StatusExtractFiles=ĆÄŔĎŔť ĂßĂâÇĎ´Â Áß... -StatusCreateIcons=šŮˇÎ °Ąąâ¸Ś ¸¸ľĺ´Â Áß... +StatusCreateIcons=šŮˇÎ°Ąąâ¸Ś ťýźşÇĎ´Â Áß... StatusCreateIniEntries=INI Ç׸ńŔť ¸¸ľĺ´Â Áß... StatusCreateRegistryEntries=ˇšÁö˝şĆŽ¸Ž Ç׸ńŔť ¸¸ľĺ´Â Áß... StatusRegisterFiles=ĆÄŔĎŔť ľîˇĎÇĎ´Â Áß... StatusSavingUninstall=ÁŚ°Ĺ Á¤ş¸¸Ś ŔúŔĺÇĎ´Â Áß... StatusRunProgram=źłÄĄ¸Ś żĎˇáÇĎ´Â Áß... -StatusRestartingApplications=ŔŔżë ÇÁˇÎą×ˇĽŔť ´Ů˝Ă ˝ĂŔŰÇĎ´Â Áß... -StatusRollback=şŻ°ć ťçÇ×Ŕť ˇŃšéÇĎ´Â Áß... +StatusRestartingApplications=ŔŔżëÇÁˇÎą×ˇĽŔť ´Ů˝Ă ˝ĂŔŰÇĎ´Â Áß... +StatusRollback=şŻ°ćŔť ĂëźŇÇĎ´Â Áß... + ; *** Misc. errors ErrorInternal2=łťşÎ żŔˇů: %1 ErrorFunctionFailedNoCode=%1 ˝ÇĆĐ -ErrorFunctionFailed=%1 ˝ÇĆĐ, ÄÚľĺ %2 -ErrorFunctionFailedWithMessage=%1 ˝ÇĆĐ, ÄÚľĺ %2.%n%3 -ErrorExecutingProgram=ĆÄŔĎŔť ˝ÇÇŕÇŇ źö žřŔ˝:%n%1 +ErrorFunctionFailed=%1 ˝ÇĆĐ; ÄÚľĺ %2 +ErrorFunctionFailedWithMessage=%1 ˝ÇĆĐ, ÄÚľĺ: %2.%n%3 +ErrorExecutingProgram=ĆÄŔĎ ˝ÇÇŕ żŔˇů:%n%1 + ; *** Registry errors -ErrorRegOpenKey=ˇšÁö˝şĆŽ¸Ž Ĺ°¸Ś żŠ´Â Áß żŔˇů šßťý:%n%1\%2 -ErrorRegCreateKey=ˇšÁö˝şĆŽ¸Ž Ĺ°¸Ś ¸¸ľĺ´Â Áß żŔˇů šßťý:%n%1\%2 -ErrorRegWriteKey=ˇšÁö˝şĆŽ¸Ž Ĺ°żĄ ąâˇĎÇĎ´Â Áß żŔˇů šßťý:%n%1\%2 +ErrorRegOpenKey=ˇšÁö˝şĆŽ¸Ž Ĺ° ż­ąâ żŔˇů:%n%1\%2 +ErrorRegCreateKey=ˇšÁö˝şĆŽ¸Ž Ĺ° ťýźş żŔˇů:%n%1\%2 +ErrorRegWriteKey=ˇšÁö˝şĆŽ¸Ž Ĺ° ž˛ąâ żŔˇů:%n%1\%2 + ; *** INI errors -ErrorIniEntry=ĆÄŔĎ "%1"żĄ INI Ç׸ńŔť ¸¸ľĺ´Â ÁßżĄ żŔˇů°Ą šßťýÇß˝Ŕ´Ď´Ů. +ErrorIniEntry=%1 ĆÄŔĎżĄ INI Ç׸ń ¸¸ľéąâ żŔˇůŔÔ´Ď´Ů. + ; *** File copying errors -FileAbortRetryIgnore=´Ů˝Ă ˝ĂľľÇϡÁ¸é [´Ů˝Ă ˝Ăľľ]¸Ś, ŔĚ ĆÄŔĎŔť °ÇłĘśŮˇÁ¸é [šŤ˝Ă](ąÇŔĺľÇÁö žĘŔ˝)¸Ś, źłÄĄ¸Ś ĂëźŇÇϡÁ¸é [Áß´Ü]Ŕť ĹŹ¸ŻÇĎźźżä. -FileAbortRetryIgnore2=´Ů˝Ă ˝ĂľľÇϡÁ¸é [´Ů˝Ă ˝Ăľľ]¸Ś, ą×ˇĄľľ °čźÓÇϡÁ¸é [šŤ˝Ă](ąÇŔĺľÇÁö žĘŔ˝)¸Ś, źłÄĄ¸Ś ĂëźŇÇϡÁ¸é [Áß´Ü]Ŕť ĹŹ¸ŻÇĎźźżä. -SourceIsCorrupted=żřşť ĆÄŔĎŔĚ źŐťóľÇžú˝Ŕ´Ď´Ů. -SourceDoesntExist=żřşť ĆÄŔĎ "%1"ŔĚ(°Ą) žř˝Ŕ´Ď´Ů. -ExistingFileReadOnly=ąâÁ¸ ĆÄŔĎŔĚ ŔĐąâ ŔüżëŔ¸ˇÎ ÇĽ˝ĂľÇžî ŔÖ˝Ŕ´Ď´Ů.%n%nŔĐąâ Ŕüżë ĆŻźşŔť ÁڰĹÇĎ°í ´Ů˝Ă ˝ĂľľÇϡÁ¸é [´Ů˝Ă ˝Ăľľ]¸Ś, ŔĚ ĆÄŔĎŔť °ÇłĘśŮˇÁ¸é [šŤ˝Ă]¸Ś, źłÄĄ¸Ś ĂëźŇÇϡÁ¸é [Áß´Ü]Ŕť ĹŹ¸ŻÇĎźźżä. -ErrorReadingExistingDest=ąâÁ¸ ĆÄŔĎŔť ŔĐ´Â Áß żŔˇů šßťý: -FileExists=ÇŘ´ç ĆÄŔĎŔĚ ŔĚšĚ ŔÖ˝Ŕ´Ď´Ů.%n%nźłÄĄ ÇÁˇÎą×ˇĽżĄź­ ŔĚ ĆÄŔĎŔť ľ¤žîž˛ľľˇĎ ÇϽðڽŔ´Ďąî? -ExistingFileNewer=ąâÁ¸ ĆÄŔĎŔĚ źłÄĄ ÇÁˇÎą×ˇĽżĄź­ źłÄĄÇϡÁ´Â ĆÄŔĎş¸´Ů ĂÖ˝ĹŔÔ´Ď´Ů. ąâÁ¸ ĆÄŔĎŔť ŔŻÁöÇŇ °ÍŔť ąÇŔĺÇŐ´Ď´Ů.%n%nąâÁ¸ ĆÄŔĎŔť ŔŻÁöÇϽðڽŔ´Ďąî? -ErrorChangingAttr=ąâÁ¸ ĆÄŔĎŔÇ ĆŻźşŔť şŻ°ćÇĎ´Â Áß żŔˇů šßťý: -ErrorCreatingTemp=´ëťó ľđˇşĹÍ¸ŽżĄ ĆÄŔĎŔť ¸¸ľĺ´Â Áß żŔˇů šßťý: -ErrorReadingSource=żřşť ĆÄŔĎŔť ŔĐ´Â Áß żŔˇů šßťý: -ErrorCopying=ĆÄŔĎŔť şšťçÇĎ´Â Áß żŔˇů šßťý: -ErrorReplacingExistingFile=ąâÁ¸ ĆÄŔĎŔť šŮ˛Ů´Â Áß żŔˇů šßťý: +FileAbortRetryIgnoreSkipNotRecommended=ŔĚ ĆÄŔĎŔť °ÇłĘśę(&S) (ąÇŔĺÇĎÁö žĘ˝Ŕ´Ď´Ů) +FileAbortRetryIgnoreIgnoreNotRecommended=żŔˇů¸Ś šŤ˝ĂÇϰí ÁřÇŕ(&I) (ąÇŔĺÇĎÁö žĘ˝Ŕ´Ď´Ů) +SourceIsCorrupted=żřşť ĆÄŔĎŔĚ źŐťóľĘ +SourceDoesntExist=żřşť ĆÄŔĎ %1ŔĚ(°Ą) Á¸ŔçÇĎÁö žĘŔ˝ +ExistingFileReadOnly2=ąâÁ¸ ĆÄŔĎŔş ŔĐąâ ŔüżëŔĚąâś§šŽżĄ ´ëĂźÇŇ źö žř˝Ŕ´Ď´Ů. +ExistingFileReadOnlyRetry=ŔĐąâ Ŕüżë źÓźşŔť ÇŘÁŚÇĎ°í ´Ů˝Ă ˝ĂľľÇϡÁ¸é(&R) +ExistingFileReadOnlyKeepExisting=ąâÁ¸ ĆÄŔĎŔť ŔŻÁö(&K) +ErrorReadingExistingDest=ąâÁ¸ ĆÄŔĎŔť ŔĐ´Â ľżžČ żŔˇů šßťý: +FileExists=ĆÄŔĎŔĚ ŔĚšĚ Á¸ŔçÇŐ´Ď´Ů.%n%nĆÄŔĎŔť ľ¤žîž˛˝Ă°Ú˝Ŕ´Ďąî? +ExistingFileNewer=ąâÁ¸ ĆÄŔĎŔĚ źłÄĄÇϡÁ°í ÇĎ´Â ĆÄŔĎş¸´Ů ťő ĆÄŔĎŔÔ´Ď´Ů, ąâÁ¸ ĆÄŔĎŔť ŔŻÁöÇϽù⠚ٜř´Ď´Ů.%n%nąâÁ¸ ĆÄŔĎŔť ŔŻÁöÇϽðڽŔ´Ďąî? +ErrorChangingAttr=ąâÁ¸ ĆÄŔĎŔÇ źÓźşŔť şŻ°ćÇĎ´Â ľżžČ żŔˇů šßťý: +ErrorCreatingTemp=´ëťó Ćú´őżĄ ĆÄŔĎŔť ¸¸ľĺ´Â ľżžČ żŔˇů šßťý: +ErrorReadingSource=żřşť ĆÄŔĎŔť ŔĐ´Â ľżžČ żŔˇů šßťý: +ErrorCopying=ĆÄŔĎŔť şšťçÇĎ´Â ľżžČ żŔˇů šßťý: +ErrorReplacingExistingFile=ąâÁ¸ ĆÄŔĎŔť ąłĂźÇĎ´Â ľżžČ żŔˇů šßťý: ErrorRestartReplace=RestartReplace ˝ÇĆĐ: -ErrorRenamingTemp=´ëťó ľđˇşĹÍ¸ŽżĄ ŔÖ´Â ĆÄŔĎ Ŕ̸§Ŕť šŮ˛Ů´Â Áß żŔˇů šßťý: -ErrorRegisterServer=DLL/OCX¸Ś ľîˇĎÇŇ źö žřŔ˝: %1 -ErrorRegSvr32Failed=Ážˇá ÄÚľĺ %1°ú(żÍ) ÇÔ˛˛ RegSvr32 ˝ÇĆĐ -ErrorRegisterTypeLib=Çü˝Ä śóŔ̺ꡯ¸Ž¸Ś ľîˇĎÇŇ źö žřŔ˝: %1 +ErrorRenamingTemp=´ëťó Ćú´ő łťŔÇ ĆÄŔĎ Ŕ̸§Ŕť šŮ˛Ů´Â ľżžČ żŔˇů šßťý: +ErrorRegisterServer=DLL/OCX ľîˇĎ ˝ÇĆĐ: %1 +ErrorRegSvr32Failed=RegSvr32°Ą ´ŮŔ˝ Ážˇá ÄÚľĺˇÎ ˝ÇĆĐ: %1 +ErrorRegisterTypeLib=´ŮŔ˝ ŔŻÇüŔÇ śóŔ̺ꡯ¸Ž ľîˇĎżĄ ˝ÇĆĐ: %1 + +; *** Uninstall display name markings +; used for example as 'My Program (32-bit)' +UninstallDisplayNameMark=%1 (%2) +; used for example as 'My Program (32-bit, All users)' +UninstallDisplayNameMarks=%1 (%2, %3) +UninstallDisplayNameMark32Bit=32şńĆŽ +UninstallDisplayNameMark64Bit=64şńĆŽ +UninstallDisplayNameMarkAllUsers=¸đľç ťçżëŔÚ +UninstallDisplayNameMarkCurrentUser=ÇöŔç ťçżëŔÚ + ; *** Post-installation errors -ErrorOpeningReadme=README ĆÄŔĎŔť żŠ´Â ÁßżĄ żŔˇů°Ą šßťýÇß˝Ŕ´Ď´Ů. -ErrorRestartingComputer=źłÄĄ ÇÁˇÎą×ˇĽżĄź­ ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŇ źö žř˝Ŕ´Ď´Ů. źöľżŔ¸ˇÎ ÁřÇŕÇĎźźżä. +ErrorOpeningReadme=README ĆÄŔĎŔť żŠ´Â Áß żŔˇů°Ą šßťýÇß˝Ŕ´Ď´Ů. +ErrorRestartingComputer=ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŇ źö žř˝Ŕ´Ď´Ů, źöľżŔ¸ˇÎ ´Ů˝Ă ˝ĂŔŰÇϽʽÿŔ. + ; *** Uninstaller messages -UninstallNotFound=ĆÄŔĎ "%1"ŔĚ(°Ą) žř˝Ŕ´Ď´Ů. ÁڰĹÇŇ źö žř˝Ŕ´Ď´Ů. -UninstallOpenError=ĆÄŔĎ "%1"Ŕť(¸Ś) ż­ źö žř˝Ŕ´Ď´Ů. ÁڰĹÇŇ źö žř˝Ŕ´Ď´Ů. -UninstallUnsupportedVer=ÁŚ°Ĺ ˇÎą× ĆÄŔĎ "%1"ŔĚ(°Ą) ŔĚ šöŔüŔÇ ÁŚ°Ĺ ÇÁˇÎą×ˇĽżĄź­ ŔνÄÇĎÁö ¸řÇĎ´Â Çü˝ÄŔÔ´Ď´Ů. ÁڰĹÇŇ źö žř˝Ŕ´Ď´Ů. -UninstallUnknownEntry=ÁŚ°Ĺ ˇÎą×żĄź­ žË źö žř´Â Ç׸ń(%1)ŔĚ šß°ßľÇžú˝Ŕ´Ď´Ů. -ConfirmUninstall=%1°ú(żÍ) ÇŘ´ç ą¸źş żäźŇ¸Ś ¸đľÎ żĎŔüČ÷ ÁڰĹÇϽðڽŔ´Ďąî? -UninstallOnlyOnWin64=ŔĚ źłÄĄ´Â 64şńĆŽ WindowsżĄź­¸¸ ÁڰĹÇŇ źö ŔÖ˝Ŕ´Ď´Ů. -OnlyAdminCanUninstall=ŔĚ źłÄĄ´Â °ü¸ŽŔÚ ąÇÇŃŔĚ ŔÖ´Â ťçżëŔÚ¸¸ ÁڰĹÇŇ źö ŔÖ˝Ŕ´Ď´Ů. -UninstallStatusLabel=ÄÄÇťĹÍżĄź­ %1Ŕť(¸Ś) ÁڰĹÇĎ´Â ľżžČ ąâ´ŮˇÁ ÁÖźźżä. -UninstalledAll=ÄÄÇťĹÍżĄź­ %1Ŕť(¸Ś) ÁڰĹÇß˝Ŕ´Ď´Ů. -UninstalledMost=%1 ÁŚ°Ĺ°Ą żĎˇáľÇžú˝Ŕ´Ď´Ů.%n%nŔϺΠżäźŇ´Â ÁڰĹÇŇ źö žř˝Ŕ´Ď´Ů. Ŕ̡ŻÇŃ Ç׸ńŔş źöľżŔ¸ˇÎ ÁڰĹÇŇ źö ŔÖ˝Ŕ´Ď´Ů. -UninstalledAndNeedsRestart=%1 ÁŚ°Ĺ¸Ś żĎˇáÇϡÁ¸é ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŘžß ÇŐ´Ď´Ů.%n%nÁöąÝ ´Ů˝Ă ˝ĂŔŰÇϽðڽŔ´Ďąî? -UninstallDataCorrupted="%1" ĆÄŔĎŔĚ źŐťóľÇžú˝Ŕ´Ď´Ů. ÁڰĹÇŇ źö žř˝Ŕ´Ď´Ů. +UninstallNotFound=ĆÄŔĎ %1ŔĚ(°Ą) Á¸ŔçÇĎÁö žĘąâ ś§šŽżĄ, ÁŚ°Ĺ¸Ś ˝ÇÇŕÇŇ źö žř˝Ŕ´Ď´Ů. +UninstallOpenError=ĆÄŔĎ %1Ŕť(¸Ś) ż­ źö žřąâ ś§šŽżĄ, ÁŚ°Ĺ¸Ś ˝ÇÇŕÇŇ źö žř˝Ŕ´Ď´Ů. +UninstallUnsupportedVer=ťčÁŚ ˇÎą× ĆÄŔĎ "%1"Ŕş(´Â) ŔĚ ťčÁŚ ¸śšýťçˇÎ ŔνÄÇŇ źö žř´Â Çü˝ÄŔĚąâ ś§šŽżĄ, ÁŚ°Ĺ¸Ś ˝ÇÇŕÇŇ źö žř˝Ŕ´Ď´Ů. +UninstallUnknownEntry=žË źö žř´Â Ç׸ń %1ŔĚ(°Ą) ťčÁŚ ˇÎą×żĄ Ć÷ÇԾǞî ŔÖ˝Ŕ´Ď´Ů. +ConfirmUninstall=Á¤¸ť %1żÍ(°ú) ą× ą¸źş żäźŇ¸Ś ¸đľÎ ÁڰĹÇϽðڽŔ´Ďąî? +UninstallOnlyOnWin64=ŔĚ ÇÁˇÎą×ˇĽŔş 64şńĆŽ WindowsżĄź­¸¸ ÁڰĹÇŇ źö ŔÖ˝Ŕ´Ď´Ů. +OnlyAdminCanUninstall=ŔĚ ÇÁˇÎą×ˇĽŔť ÁڰĹÇϡÁ¸é °ü¸ŽŔÚ ąÇÇŃŔĚ ÇĘżäÇŐ´Ď´Ů. +UninstallStatusLabel=ąÍÇĎŔÇ ÄÄÇťĹÍżĄź­ %1Ŕť(¸Ś) ÁڰĹÇĎ´Â Áß... Ŕá˝Ă ąâ´ŮˇÁ ÁֽʽÿŔ. +UninstalledAll=%1ŔĚ(°Ą) źş°řŔűŔ¸ˇÎ ÁŚ°ĹľÇžú˝Ŕ´Ď´Ů! +UninstalledMost=%1 ÁŚ°Ĺ°Ą żĎˇáľÇžú˝Ŕ´Ď´Ů.%n%nŔϺΠżäźŇ´Â ťčÁŚÇŇ źö žřŔ¸´Ď, źöľżŔ¸ˇÎ ÁڰĹÇϽù⠚ٜř´Ď´Ů. +UninstalledAndNeedsRestart=%1ŔÇ ÁŚ°Ĺ¸Ś żĎˇáÇϡÁ¸é, ÄÄÇťĹÍ¸Ś ´Ů˝Ă ˝ĂŔŰÇŘžß ÇŐ´Ď´Ů.%n%nÁöąÝ ´Ů˝Ă ˝ĂŔŰÇϽðڽŔ´Ďąî? +UninstallDataCorrupted=ĆÄŔĎ "%1"ŔĚ(°Ą) źŐťóľÇžúąâ ś§šŽżĄ, ÁŚ°Ĺ¸Ś ˝ÇÇŕÇŇ źö žř˝Ŕ´Ď´Ů. + ; *** Uninstallation phase messages ConfirmDeleteSharedFileTitle=°řŔŻ ĆÄŔĎŔť ÁڰĹÇϽðڽŔ´Ďąî? -ConfirmDeleteSharedFile2=˝Ă˝şĹŰżĄź­´Â ŔĚÁŚ ´ŮŔ˝ °řŔŻ ĆÄŔĎŔť ťçżëÇĎ´Â ÇÁˇÎą×ˇĽŔĚ žř´Â °ÍŔ¸ˇÎ ÇĽ˝ĂľË´Ď´Ů. ÁŚ°Ĺ ŔŰž÷Ŕť ĹëÇŘ ŔĚ °řŔŻ ĆÄŔĎŔť ÁڰĹÇϽðڽŔ´Ďąî?%n%nžĆÁ÷ ŔĚ ĆÄŔĎŔť ťçżëÇĎ´Â ÇÁˇÎą×ˇĽŔĚ ŔÖ´ÂľĽ ŔĚ ĆÄŔĎŔť ÁڰĹÇϸé ÇŘ´ç ÇÁˇÎą×ˇĽŔĚ żĂšŮ¸Ł°Ô ŔŰľżÇĎÁö žĘŔť źö ŔÖ˝Ŕ´Ď´Ů. Ŕß ¸đ¸Ł´Â °ćżě [žĆ´Ďżä]¸Ś źąĹĂÇĎźźżä. ˝Ă˝şĹŰżĄ ĆÄŔĎŔť ą×´ëˇÎ ľÎžîľľ žĆšŤˇą šŽÁڰĄ šßťýÇĎÁö žĘ˝Ŕ´Ď´Ů. +ConfirmDeleteSharedFile2=˝Ă˝şĹŰŔÇ žîś˛ ÇÁˇÎą×ˇĽľľ ´ŮŔ˝ °řŔŻ ĆÄŔĎŔť ťçżëÇĎÁö žĘ˝Ŕ´Ď´Ů, ŔĚ °řŔŻ ĆÄŔĎŔť ťčÁŚÇϽðڽŔ´Ďąî?%n%nŔĚ ĆÄŔĎŔť ´Ů¸Ľ ÇÁˇÎą×ˇĽŔĚ °řŔŻÇϰí ŔÖ´Â ťóĹÂżĄź­ ŔĚ ĆÄŔĎŔť ÁڰĹÇŇ °ćżě, ÇŘ´ç ÇÁˇÎą×ˇĽŔĚ ÁŚ´ëˇÎ ŔŰľżÇĎÁö žĘŔť źö ŔÖŔ¸´Ď, ČŽ˝ĹŔĚ žřŔ¸¸é "žĆ´ĎżŔ"¸Ś źąĹĂÇϟžľ ľË´Ď´Ů. ˝Ă˝şĹŰżĄ ĆÄŔĎŔĚ ł˛žĆ ŔÖžîľľ šŽÁڰĄ ľÇÁř žĘ˝Ŕ´Ď´Ů. SharedFileNameLabel=ĆÄŔĎ Ŕ̸§: SharedFileLocationLabel=Ŕ§ÄĄ: WizardUninstalling=ÁŚ°Ĺ ťóĹ StatusUninstalling=%1Ŕť(¸Ś) ÁڰĹÇĎ´Â Áß... + ; *** Shutdown block reasons ShutdownBlockReasonInstallingApp=%1Ŕť(¸Ś) źłÄĄÇĎ´Â ÁßŔÔ´Ď´Ů. ShutdownBlockReasonUninstallingApp=%1Ŕť(¸Ś) ÁڰĹÇĎ´Â ÁßŔÔ´Ď´Ů. + ; The custom messages below aren't used by Setup itself, but if you make ; use of them in your scripts, you'll want to translate them. + [CustomMessages] + NameAndVersion=%1 šöŔü %2 -AdditionalIcons=Ăß°Ą šŮˇÎ °Ąąâ: -CreateDesktopIcon=šŮĹÁ Č­¸é šŮˇÎ °Ąąâ ¸¸ľéąâ(&D) -CreateQuickLaunchIcon=şü¸Ľ ˝ÇÇŕ šŮˇÎ °Ąąâ ¸¸ľéąâ(&Q) -ProgramOnTheWeb=%1 ŔĽ Á¤ş¸ +AdditionalIcons=žĆŔĚÄÜ Ăß°Ą: +CreateDesktopIcon=šŮĹÁ Č­¸éżĄ šŮˇÎ°Ąąâ ¸¸ľéąâ(&D) +CreateQuickLaunchIcon=şü¸Ľ ˝ÇÇŕ žĆŔĚÄÜ ¸¸ľéąâ(&Q) +ProgramOnTheWeb=%1 ŔĽĆäŔĚÁö UninstallProgram=%1 ÁŚ°Ĺ -LaunchProgram=%1 ˝ĂŔŰ -AssocFileExtension=%1Ŕť(¸Ś) %2 ĆÄŔĎ ČŽŔĺ¸í°ú żŹ°á(&A) -AssocingFileExtension=%1Ŕť(¸Ś) %2 ĆÄŔĎ ČŽŔĺ¸í°ú żŹ°á Áß... +LaunchProgram=%1 ˝ÇÇŕ +AssocFileExtension=ĆÄŔĎ ČŽŔĺŔÚ %2Ŕť(¸Ś) %1żĄ żŹ°áÇŐ´Ď´Ů. +AssocingFileExtension=ĆÄŔĎ ČŽŔĺŔÚ %2Ŕť(¸Ś) %1żĄ żŹ°áÇĎ´Â Áß... AutoStartProgramGroupDescription=˝ĂŔŰ: -AutoStartProgram=%1 ŔÚľż ˝ĂŔŰ -AddonHostProgramNotFound=źąĹĂÇŃ Ćú´őżĄź­ %1Ŕť(¸Ś) ĂŁŔť źö žř˝Ŕ´Ď´Ů.%n%ną×ˇĄľľ °čźÓÇϽðڽŔ´Ďąî? \ No newline at end of file +AutoStartProgram=%1Ŕť(¸Ś) ŔÚľżŔ¸ˇÎ ˝ĂŔŰ +AddonHostProgramNotFound=%1Ŕş(´Â) źąĹĂÇŃ Ćú´őżĄ Ŕ§ÄĄÇŇ źö žř˝Ŕ´Ď´Ů.%n%ną×ˇĄľľ °čźÓÇϽðڽŔ´Ďąî? diff --git a/build/win32/i18n/Default.zh-cn.isl b/build/win32/i18n/Default.zh-cn.isl index e384e83d30..5c5df9a166 100644 --- a/build/win32/i18n/Default.zh-cn.isl +++ b/build/win32/i18n/Default.zh-cn.isl @@ -1,16 +1,17 @@ -; *** Inno Setup version 5.5.3+ Simplified Chinese messages *** +ďťż; *** Inno Setup version 6.0.3+ Chinese Simplified messages *** ; -; To download user-contributed translations of this file, go to: -; http://www.jrsoftware.org/files/istrans/ +; Maintained by Zhenghan Yang +; Email: 847320916@QQ.com +; Translation based on network resource +; The latest Translation is on https://github.com/kira-96/Inno-Setup-Chinese-Simplified-Translation ; -; Note: When translating this text, do not add periods (.) to the end of -; messages that didn't have them already, because on those messages Inno -; Setup adds the periods automatically (appending a period would result in -; two periods being displayed). + [LangOptions] ; The following three entries are very important. Be sure to read and ; understand the '[LangOptions] section' topic in the help file. -LanguageName=Simplified Chinese +LanguageName=简体中文 +; If Language Name display incorrect, uncomment next line +; LanguageName=<7B80><4F53><4E2D><6587> LanguageID=$0804 LanguageCodePage=936 ; If the language you are translating to requires special font faces or @@ -23,276 +24,342 @@ LanguageCodePage=936 ;TitleFontSize=29 ;CopyrightFontName=Arial ;CopyrightFontSize=8 + [Messages] -; *** Application titles -SetupAppTitle=°˛×°łĚĐň -SetupWindowTitle=°˛×°łĚĐň - %1 -UninstallAppTitle=ĐśÔŘ -UninstallAppFullTitle=%1 ĐśÔŘ + +; *** 应用程序标题 +SetupAppTitle=安装 +SetupWindowTitle=安装 - %1 +UninstallAppTitle=卸载 +UninstallAppFullTitle=%1 卸载 + ; *** Misc. common -InformationTitle=ĐĹϢ -ConfirmTitle=ȡČĎ -ErrorTitle=´íÎó +InformationTitle=俥息 +ConfirmTitle=祎莤 +ErrorTitle=错误 + ; *** SetupLdr messages -SetupLdrStartupMessage=Ő⽍°˛×° %1ĄŁĘǡńŇŞźĚĐř? -LdrCannotCreateTemp=Îޡ¨´´˝¨ÁŮĘąÎÄźţĄŁ°˛×°łĚĐňŇŃÖĐÖš -LdrCannotExecTemp=Îޡ¨ÔÚÁŮʹĿŸÖĐÖ´ĐĐÎÄźţĄŁ°˛×°łĚĐňŇŃÖĐÖš -; *** Startup error messages -LastErrorMessage=%1ĄŁ%n%n´íÎó %2: %3 -SetupFileMissing=°˛×°ÄżÂźČąĘ§ÎÄźţ %1ĄŁÇë¸üŐý¸ĂÎĘĚâťňťńČĄ¸ĂÎĘĚâľÄĐÂ¸ąąžĄŁ -SetupFileCorrupt=°˛×°łĚĐňÎÄźţźĐŇŃË𝾥ŁÇëťńČĄ¸ĂłĚĐňľÄĐÂ¸ąąžĄŁ -SetupFileCorruptOrWrongVer=°˛×°łĚĐňÎÄźţźĐŇŃËđťľťňÓë´Ë°˛×°łĚĐň°ćąž˛ťźćČÝĄŁÇë¸üŐý¸ĂÎĘĚâťňťńČĄ¸ĂłĚĐňľÄĐÂ¸ąąžĄŁ -InvalidParameter=ĂüÁîĐĐ %n%n%1 ÉĎ´ŤľÝÁËŇť¸öÎŢЧ˛ÎĘý -SetupAlreadyRunning=°˛×°łĚĐňŇŃÔÚÔËĐĐĄŁ -WindowsVersionNotSupported=´ËłĚĐň˛ťÖ§łÖÄăźĆËăťúŐýÔËĐĐľÄ Windows °ćąžĄŁ -WindowsServicePackRequired=´ËłĚĐňĐčŇŞ %1 ˇţÎń°ü %2 ťň¸ü¸ß°ćąžĄŁ -NotOnThisPlatform=´ËłĚĐň˝Ť˛ťÔÚ %1 ÉĎÔËĐĐĄŁ -OnlyOnThisPlatform=´ËłĚĐňąŘĐëÔÚ %1 ÉĎÔËĐĐĄŁ -OnlyOnTheseArchitectures=´ËłĚĐň˝öżÉ°˛×°ÔÚÎŞŇÔĎ´ŚŔíĆ÷ĚĺĎľ˝áššÉčźĆľÄ Windows °ćąžÉĎ:%n%n%1 -MissingWOW64APIs=ÄăŐýÔËĐĐľÄ Windows °ćąž˛ť°üşŹ°˛×°łĚĐňÖ´ĐĐ 64 Îť°˛×°ËůĐčľÄšŚÄÜĄŁŇ޸üŐý´ËÎĘĚ⣏Ç밲װˇţÎń°ü %1ĄŁ -WinVersionTooLowError=´ËłĚĐňĐčŇŞ %1 °ćąž %2 ťň¸ü¸ß°ćąžĄŁ -WinVersionTooHighError=´ËłĚĐň˛ťÄܰ˛×°ÔÚ %1 °ćąž %2 ťň¸ü¸ßľÄ°ćąžÉĎĄŁ -AdminPrivilegesRequired=ÔÚ°˛×°´ËłĚĐňĘąąŘĐë×÷ÎŞšÜŔíÔąľÇÂźĄŁ -PowerUserPrivilegesRequired=°˛×°´ËłĚĐňĘąąŘĐëŇÔšÜŔíÔąťň Power User ×éłÉÔąÉíˇÝľÇÂźĄŁ -SetupAppRunningError=°˛×°łĚĐňźě˛âľ˝ %1 ľąÇ°ŐýÔÚÔËĐĐĄŁ%n%nÇëÁ˘ź´šŘąŐËüľÄËůÓĐĘľŔýŁŹČťşóľĽť÷Ą°Čˇś¨ĄąŇÔźĚĐřŁŹťňľĽť÷Ą°ČĄĎűĄąŇÔÍËłöĄŁ -UninstallAppRunningError=ĐśÔŘźě˛âľ˝ %1 ľąÇ°ŐýÔÚÔËĐĐĄŁ%n%nÇëÁ˘ź´šŘąŐËüľÄËůÓĐĘľŔýŁŹČťşóľĽť÷Ą°Čˇś¨ĄąŇÔźĚĐřťňľĽť÷Ą°ČĄĎűĄąŇÔÍËłöĄŁ -; *** Misc. errors -ErrorCreatingDir=°˛×°łĚĐňÎޡ¨´´˝¨ÄżÂźĄ°%1Ąą -ErrorTooManyFilesInDir=Îޡ¨ÔÚĿŸĄ°%1ĄąÖĐ´´˝¨ÎÄźţŁŹŇňÎŞËü°üşŹĚŤśŕÎÄźţ -; *** Setup common messages -ExitSetupTitle=ÍËłö°˛×°łĚĐň -ExitSetupMessage=°˛×°łĚĐňδÍęłÉĄŁČçšűÁ˘ź´ÍËłöŁŹ˝Ť˛ťťá°˛×°¸ĂłĚĐňĄŁ%n%nżÉÔÚĆäËűĘąźäÔŮ´ÎÔËĐа˛×°łĚĐňŇÔÍęłÉ°˛×°ĄŁ%n%nĘǡńÍËłö°˛×°łĚĐň? -AboutSetupMenuItem=šŘÓÚ°˛×°łĚĐň(&A)... -AboutSetupTitle=šŘÓÚ°˛×°łĚĐň -AboutSetupMessage=%1 °ćąž %2%n%3%n%n%1 Ö÷Ňł:%n%4 +SetupLdrStartupMessage=现在将安装 %1。您想要继续吗? +LdrCannotCreateTemp=不能创建临时文件。安装中断。 +LdrCannotExecTemp=不能执行临时目录中的文件。安装中断。 +HelpTextNote= + +; *** 启动错误消息 +LastErrorMessage=%1.%n%n错误 %2: %3 +SetupFileMissing=安装目录中的文件 %1 丢失。请修正这个问题或获取一个新的程序副本。 +SetupFileCorrupt=安装文件已损坏。请获取一个新的程序副本。 +SetupFileCorruptOrWrongVer=安装文件已损坏,或是与这个安装程序的版本不兼容。请修正这个问题或获取新的程序副本。 +InvalidParameter=无效的命令行参数: %n%n%1 +SetupAlreadyRunning=安装程序正在运行。 +WindowsVersionNotSupported=这个程序不支持该版本的计算机运行。 +WindowsServicePackRequired=这个程序要求%1服务包%1或更高。 +NotOnThisPlatform=这个程序将不能运行于 %1。 +OnlyOnThisPlatform=这个程序必须运行于 %1。 +OnlyOnTheseArchitectures=这个程序只能在为下列处理器结构设计的 Windows 版本中进行安装:%n%n%1 +WinVersionTooLowError=这个程序需要 %1 版本 %2 或更高。 +WinVersionTooHighError=这个程序不能安装于 %1 版本 %2 或更高。 +AdminPrivilegesRequired=在安装这个程序时您必须以管理员身份登录。 +PowerUserPrivilegesRequired=在安装这个程序时您必须以管理员身份或有权限的用户组身份登录。 +SetupAppRunningError=安装程序发现 %1 当前正在运行。%n%n请先关闭所有运行的窗口,然后单击“确定”继续,或按“取消”退出。 +UninstallAppRunningError=卸载程序发现 %1 当前正在运行。%n%n请先关闭所有运行的窗口,然后单击“确定”继续,或按“取消”退出。 + +; *** 启动问题 +PrivilegesRequiredOverrideTitle=选择安装程序模式 +PrivilegesRequiredOverrideInstruction=选择安装模式 +PrivilegesRequiredOverrideText1=%1 可以为所有用户安装(需要管理员权限),或仅为您安装。 +PrivilegesRequiredOverrideText2=%1 只能为您安装,或为所有用户安装(需要管理员权限)。 +PrivilegesRequiredOverrideAllUsers=为所有用户安装(&A) +PrivilegesRequiredOverrideAllUsersRecommended=为所有用户安装(建议选项)(&A) +PrivilegesRequiredOverrideCurrentUser=只为我安装(&M) +PrivilegesRequiredOverrideCurrentUserRecommended=只为我安装(建议选项)(&M) + +; *** 其它错误 +ErrorCreatingDir=安装程序不能创建目录“%1”。 +ErrorTooManyFilesInDir=不能在目录“%1”中创建文件,因为里面的文件太多 + +; *** 安装程序公共消息 +ExitSetupTitle=退出安装程序 +ExitSetupMessage=安装程序未完成安装。如果您现在退出,您的程序将不能安装。%n%n您可以以后再运行安装程序完成安装。%n%n退出安装程序吗? +AboutSetupMenuItem=关于安装程序(&A)... +AboutSetupTitle=关于安装程序 +AboutSetupMessage=%1 版本 %2%n%3%n%n%1 丝饾:%n%4 AboutSetupNote= TranslatorNote= -; *** Buttons -ButtonBack=< ÉĎŇť˛˝(&B) -ButtonNext=ĎÂŇť˛˝(&N) > -ButtonInstall=°˛×°(&I) -ButtonOK=ȡś¨ -ButtonCancel=ČĄĎű -ButtonYes=ĘÇ(&Y) -ButtonYesToAll=˝ÓĘÜČŤ˛ż(&A) -ButtonNo=ˇń(&N) -ButtonNoToAll=ˇńś¨ČŤ˛ż(&O) -ButtonFinish=ÍęłÉ(&F) -ButtonBrowse=äŻŔŔ(&B)... -ButtonWizardBrowse=äŻŔŔ(&R)... -ButtonNewFolder=Đ½¨ÎÄźţźĐ(&M) -; *** "Select Language" dialog messages -SelectLanguageTitle=ŃĄÔń°˛×°łĚĐňÓďŃÔ -SelectLanguageLabel=ŃĄÔń°˛×°ĘąŇŞĘšÓĂľÄÓďŃÔ: -; *** Common wizard text -ClickNext=ľĽť÷Ą°ĎÂŇť˛˝ĄąŇÔźĚĐřŁŹťňľĽť÷Ą°ČĄĎűĄąŇÔÍËłö°˛×°łĚĐňĄŁ + +; *** 按钮 +ButtonBack=< 上一步(&B) +ButtonNext=下一步(&N) > +ButtonInstall=安装(&I) +ButtonOK=确定 +ButtonCancel=取消 +ButtonYes=是(&Y) +ButtonYesToAll=全是(&A) +ButtonNo=同(&N) +ButtonNoToAll=全否(&O) +ButtonFinish=完成(&F) +ButtonBrowse=浏览(&B)... +ButtonWizardBrowse=浏览(&R)... +ButtonNewFolder=新建文件夹(&M) + +; *** “选择语言”对话框消息 +SelectLanguageTitle=选择安装语言 +SelectLanguageLabel=选择安装时要使用的语言。 + +; *** 公共向导文字 +ClickNext=单击“下一步”继续,或单击“取消”退出安装程序。 BeveledLabel= -BrowseDialogTitle=äŻŔŔ˛éŐŇÎÄźţźĐ -BrowseDialogLabel=ÔÚŇÔĎÂÁĐąíÖĐŃĄÔńŇť¸öÎÄźţźĐŁŹČťşóľĽť÷Ą°Čˇś¨ĄąĄŁ -NewFolderName=Đ½¨ÎÄźţźĐ -; *** "Welcome" wizard page -WelcomeLabel1=ťśÓ­ĘšÓĂ [name] °˛×°Ďňľź -WelcomeLabel2=Ő⽍ÔÚźĆËăťúÉϰ˛×° [name/ver]ĄŁ%n%n˝¨ŇéšŘąŐËůÓĐĆäËűÓŚÓĂłĚĐňÔŮźĚĐřĄŁ -; *** "Password" wizard page -WizardPassword=ĂÜÂë -PasswordLabel1=´Ë°˛×°ĘÜĂÜÂ빣ť¤ĄŁ -PasswordLabel3=ÇëĚᚊĂÜÂ룏ȝşóľĽť÷Ą°ĎÂŇť˛˝ĄąŇÔźĚĐřĄŁĂÜÂëÇřˇÖ´óĐĄĐ´ĄŁ -PasswordEditLabel=ĂÜÂë(&P): -IncorrectPassword=ĘäČëľÄĂÜÂ벝ŐýȡĄŁÇëÖŘĘÔĄŁ -; *** "License Agreement" wizard page -WizardLicense=ĐíżÉĐ­Ňé -LicenseLabel=ÇëÔÚźĚĐř˛Ů×÷ǰÔÄśÁŇÔĎÂÖŘŇŞĐĹϢĄŁ -LicenseLabel3=ÇëÔÄśÁŇÔĎÂĐíżÉĐ­Ň饣ąŘĐë˝ÓĘÜ´ËĐ­ŇéĚőżî˛ĹżÉźĚĐř°˛×°ĄŁ -LicenseAccepted=ÎŇ˝ÓĘÜĐ­Ňé(&A) -LicenseNotAccepted=ÎҲť˝ÓĘÜĐ­Ňé(&D) -; *** "Information" wizard pages -WizardInfoBefore=ĐĹϢ -InfoBeforeLabel=ÇëÔÚźĚĐř˛Ů×÷ǰÔÄśÁŇÔĎÂÖŘŇŞĐĹϢĄŁ -InfoBeforeClickLabel=×źą¸şĂźĚĐř°˛×°şóŁŹľĽť÷Ą°ĎÂŇť˛˝ĄąĄŁ -WizardInfoAfter=ĐĹϢ -InfoAfterLabel=ÇëÔÚźĚĐř˛Ů×÷ǰÔÄśÁŇÔĎÂÖŘŇŞĐĹϢĄŁ -InfoAfterClickLabel=×źą¸şĂźĚĐř°˛×°şóŁŹľĽť÷Ą°ĎÂŇť˛˝ĄąĄŁ -; *** "User Information" wizard page -WizardUserInfo=ÓĂť§ĐĹϢ -UserInfoDesc=ÇëĘäČëÄăľÄĐĹϢĄŁ -UserInfoName=ÓĂť§Ăű(&U): -UserInfoOrg=×éÖŻ(&O): -UserInfoSerial=ĐňÁĐşĹ(&S): -UserInfoNameRequired=ąŘĐëĘäČëĂűłĆĄŁ -; *** "Select Destination Location" wizard page -WizardSelectDir=ŃĄÔńÄżąęÎťÖĂ -SelectDirDesc=ÓŚ˝Ť [name] °˛×°ľ˝ÄÄŔď? -SelectDirLabel3=°˛×°łĚĐňťá˝Ť [name] °˛×°ľ˝ŇÔĎÂÎÄźţźĐĄŁ -SelectDirBrowseLabel=ČôŇŞźĚĐřŁŹľĽť÷Ą°ĎÂŇť˛˝ĄąĄŁČçšűĎëŃĄÔńĆäËűÎÄźţźĐŁŹľĽť÷Ą°äŻŔŔĄąĄŁ -DiskSpaceMBLabel=ĐčŇŞÖÁÉŮ [mb] MB żÉÓĂ´ĹĹ̿՟䥣 -CannotInstallToNetworkDrive=°˛×°łĚĐňÎޡ¨°˛×°ľ˝ÍřÂçÇýśŻĆ÷ĄŁ -CannotInstallToUNCPath=°˛×°łĚĐňÎޡ¨°˛×°ľ˝ UNC ¡žśĄŁ -InvalidPath=ąŘĐëĘäČë´řÇýśŻĆ÷şĹľÄÍęŐű¡žś(ŔýČç:%n%nC:\APP%n%n)ťňŇÔϸńĘ˝ľÄ UNC ¡žś:%n%n\\server\share -InvalidDrive=ËůŃĄÇýśŻĆ÷ťň UNC š˛Ďí˛ť´ćÔÚťň˛ťżÉˇĂÎĘĄŁÇëÁíÍâŃĄÔńĄŁ -DiskSpaceWarningTitle=´ĹĹ̿՟䲝×ă -DiskSpaceWarning=°˛×°łĚĐňĐčŇŞÖÁÉŮ %1 KB żÉÓĂżŐźäŔ´°˛×°ŁŹľŤËůŃĄÇýśŻĆ÷˝öÓĐ %2 KB żÉÓÿ՟䥣%n%nĘǡńČÔŇŞźĚĐř? -DirNameTooLong=ÎÄźţźĐĂűłĆťň¡žśĚŤł¤ĄŁ -InvalidDirName=ÎÄźţźĐĂűłĆÎŢЧĄŁ -BadDirName32=ÎÄźţźĐĂű˛ťÄܰüşŹŇÔĎÂČÎŇť×Öˇű:%n%n%1 -DirExistsTitle=ÎÄźţźĐ´ćÔÚ -DirExists=ÎÄźţźĐ:%n%n%1%n%nŇŃ´ćÔÚĄŁĘǡńČÔŇŞ°˛×°ľ˝¸ĂÎÄźţźĐ? -DirDoesntExistTitle=ÎÄźţźĐ˛ť´ćÔÚ -DirDoesntExist=ÎÄźţźĐ:%n%n%1%n%n˛ť´ćÔÚĄŁĘǡńŇŞ´´˝¨¸ĂÎÄźţźĐ? -; *** "Select Components" wizard page -WizardSelectComponents=ŃĄÔń×éźţ -SelectComponentsDesc=ÓŚ°˛×°ÄÄĐŠ×éźţ? -SelectComponentsLabel2=ŃĄÔńĎŁÍű°˛×°ľÄ×éźţŁťÇĺłý˛ťĎŁÍű°˛×°ľÄ×éźţĄŁ×źą¸žÍĐ÷şóľĽť÷Ą°ĎÂŇť˛˝ĄąŇÔźĚĐřĄŁ -FullInstallation=ÍęČŤ°˛×° +BrowseDialogTitle=浏览文件夹 +BrowseDialogLabel=在下列列表中选择一个文件夹,然后单击“确定”。 +NewFolderName=新建文件夹 + +; *** “欢迎”向导页 +WelcomeLabel1=欢迎使用 [name] 安装向导 +WelcomeLabel2=现在将安装 [name/ver] 到您的电脑中。%n%n推荐您在继续安装前关闭所有其它应用程序。 + +; *** “密码”向导页 +WizardPassword=密码 +PasswordLabel1=这个安装程序有密码保护。 +PasswordLabel3=请输入密码,然后单击“下一步”继续。密码区分大小写。 +PasswordEditLabel=密码(&P): +IncorrectPassword=您输入的密码不正确,请重试。 + +; *** “许可协议”向导页 +WizardLicense=许可协议 +LicenseLabel=继续安装前请阅读下列重要信息。 +LicenseLabel3=请仔细阅读下列许可协议。您在继续安装前必须同意这些协议条款。 +LicenseAccepted=我同意此协议(&A) +LicenseNotAccepted=我不同意此协议(&D) + +; *** “信息”向导页 +WizardInfoBefore=俥息 +InfoBeforeLabel=请在继续安装前阅读下列重要信息。 +InfoBeforeClickLabel=如果您想继续安装,单击“下一步”。 +WizardInfoAfter=俥息 +InfoAfterLabel=请在继续安装前阅读下列重要信息。 +InfoAfterClickLabel=如果您想继续安装,单击“下一步”。 + +; *** “用户信息”向导页 +WizardUserInfo=用户信息 +UserInfoDesc=请输入您的信息。 +UserInfoName=用户名(&U): +UserInfoOrg=组织(&O): +UserInfoSerial=序列号(&S): +UserInfoNameRequired=您必须输入名字。 + +; *** “选择目标目录”向导面 +WizardSelectDir=选择目标位置 +SelectDirDesc=您想将 [name] 安装在什么地方? +SelectDirLabel3=安装程序将安装 [name] 到下列文件夹中。 +SelectDirBrowseLabel=单击“下一步”继续。如果您想选择其它文件夹,单击“浏览”。 +DiskSpaceGBLabel=至少需要有 [gb] GB 的可用磁盘空间。 +DiskSpaceMBLabel=至少需要有 [mb] MB 的可用磁盘空间。 +CannotInstallToNetworkDrive=安装程序无法安装到一个网络驱动器。 +CannotInstallToUNCPath=安装程序无法安装到一个UNC路径。 +InvalidPath=您必须输入一个带驱动器卷标的完整路径,例如:%n%nC:\APP%n%n或下列形式的 UNC 路径:%n%n\\server\share +InvalidDrive=您选定的驱动器或 UNC 共享不存在或不能访问。请选选择其它位置。 +DiskSpaceWarningTitle=没有足够的磁盘空间 +DiskSpaceWarning=安装程序至少需要 %1 KB 的可用空间才能安装,但选定驱动器只有 %2 KB 的可用空间。%n%n您一定要继续吗? +DirNameTooLong=文件夹名或路径太长。 +InvalidDirName=文件夹名是无效的。 +BadDirName32=文件夹名不能包含下列任何字符:%n%n%1 +DirExistsTitle=文件夹存在 +DirExists=文件夹:%n%n%1%n%n已经存在。您一定要安装到这个文件夹中吗? +DirDoesntExistTitle=文件夹不存在 +DirDoesntExist=文件夹:%n%n%1%n%n不存在。您想要创建此目录吗? + +; *** “选择组件”向导页 +WizardSelectComponents=选择组件 +SelectComponentsDesc=您想安装哪些程序的组件? +SelectComponentsLabel2=选择您想要安装的组件;清除您不想安装的组件。然后单击“下一步”继续。 +FullInstallation=完全安装 ; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language) -CompactInstallation=źň˝ŕ°˛×° -CustomInstallation=×Ôś¨Ň尲װ -NoUninstallWarningTitle=×éźţ´ćÔÚ -NoUninstallWarning=°˛×°łĚĐňźě˛âľ˝źĆËăťúÉĎŇѰ˛×°ŇÔĎÂ×éźţ:%n%n%1%n%nČĄĎűŃĄÔńŐâĐŠ×éźţ˝Ť˛ťťáĐśÔŘËüĂÇĄŁ%n%nĘǡńČÔŇŞźĚĐř? +CompactInstallation=简洁安装 +CustomInstallation=自定义安装 +NoUninstallWarningTitle=组件存在 +NoUninstallWarning=安装程序侦测到下列组件已在您的电脑中安装。:%n%n%1%n%n取消选定这些组件将不能卸载它们。%n%n您一定要继续吗? ComponentSize1=%1 KB ComponentSize2=%1 MB -ComponentsDiskSpaceMBLabel=ľąÇ°ŃĄÔńĐčŇŞÖÁÉŮ [mb] MB ´ĹĹ̿՟䥣 -; *** "Select Additional Tasks" wizard page -WizardSelectTasks=ŃĄÔńĆäËűČÎÎń -SelectTasksDesc=ÓŚÖ´ĐĐÄÄĐŠĆäËűČÎÎń? -SelectTasksLabel2=ŃĄÔń°˛×° [name] ʹϣÍű°˛×°łĚĐňŔ´Ö´ĐĐľÄĆäËűČÎÎńŁŹČťşóľĽť÷Ą°ĎÂŇť˛˝ĄąĄŁ -; *** "Select Start Menu Folder" wizard page -WizardSelectProgramGroup=ŃĄÔńżŞĘź˛ËľĽÎÄźţźĐ -SelectStartMenuFolderDesc=°˛×°łĚĐňÓŚ˝ŤłĚĐňľÄżě˝Ýˇ˝Ę˝ˇĹÖĂľ˝ÄÄŔď? -SelectStartMenuFolderLabel3=°˛×°łĚĐň˝ŤÔÚŇÔĎÂżŞĘź˛ËľĽÎÄźţźĐÖĐ´´˝¨¸ĂłĚĐňľÄżě˝Ýˇ˝Ę˝ĄŁ -SelectStartMenuFolderBrowseLabel=ČôŇŞźĚĐřŁŹľĽť÷Ą°ĎÂŇť˛˝ĄąĄŁČçšűĎëŃĄÔńĆäËűÎÄźţźĐŁŹľĽť÷Ą°äŻŔŔĄąĄŁ -MustEnterGroupName=ąŘĐëĘäČëÎÄźţźĐĂűĄŁ -GroupNameTooLong=ÎÄźţźĐĂűłĆťň¡žśĚŤł¤ĄŁ -InvalidGroupName=ÎÄźţźĐĂűłĆÎŢЧĄŁ -BadGroupName=ÎÄźţźĐĂű˛ťÄÜąŁť¤ŇÔĎÂČÎŇť×Öˇű:%n%n%1 -NoProgramGroupCheck2=˛ť´´˝¨żŞĘź˛ËľĽÎÄźţźĐ(&D) -; *** "Ready to Install" wizard page -WizardReady=°˛×°×źą¸žÍĐ÷ -ReadyLabel1=°˛×°łĚĐňĎÖŇŃ×źą¸şĂÔÚźĆËăťúÉϰ˛×° [name]ĄŁ -ReadyLabel2a=ľĽť÷Ą°°˛×°ĄąŇÔźĚĐř°˛×°ŁŹČçĎë˛éż´ťň¸ü¸ÄČÎşÎÉčÖĂÔňľĽť÷"ˇľťŘ"ĄŁ -ReadyLabel2b=ľĽť÷Ą°°˛×°ĄąŇÔźĚĐř°˛×°ĄŁ -ReadyMemoUserInfo=ÓĂť§ĐĹϢ: -ReadyMemoDir=ÄżąęÎťÖĂ: -ReadyMemoType=°˛×°łĚĐňŔŕĐÍ: -ReadyMemoComponents=ËůŃĄ×éźţ: -ReadyMemoGroup=żŞĘź˛ËľĽÎÄźţźĐ: -ReadyMemoTasks=ĆäËűČÎÎń: -; *** "Preparing to Install" wizard page -WizardPreparing=ŐýÔÚ×źą¸°˛×° -PreparingDesc=°˛×°łĚĐňŐýןą¸ÔÚźĆËăťúÉϰ˛×° [name]ĄŁ -PreviousInstallNotCompleted=ÉĎŇť¸öłĚĐňľÄ°˛×°/ÉžłýδÍęłÉĄŁĐčÖŘĆôźĆËăťúŇÔÍęłÉ¸Ă°˛×°ĄŁ%n%nÖŘĆôźĆËăťúşóŁŹÖŘĐÂÔËĐа˛×°łĚĐňŇÔÍęłÉ [name] ľÄ°˛×°ĄŁ -CannotContinue=°˛×°łĚĐňÎޡ¨źĚĐřĄŁÇ뾼ť÷"ČĄĎű"ŇÔÍËłöĄŁ -ApplicationsFound=ŇÔĎÂÓŚÓĂłĚĐňŐýÔÚĘšÓĂĐčҪͨšý°˛×°łĚĐň˝řĐиüĐÂľÄÎÄźţĄŁ˝¨ŇéÔĘĐí°˛×°łĚĐň×ÔśŻšŘąŐŐâĐŠÓŚÓĂłĚĐňĄŁ -ApplicationsFound2=ŇÔĎÂÓŚÓĂłĚĐňŐýÔÚĘšÓĂĐčҪͨšý°˛×°łĚĐň˝řĐиüĐÂľÄÎÄźţĄŁ˝¨ŇéÔĘĐí°˛×°łĚĐň×ÔśŻšŘąŐŐâĐŠÓŚÓĂłĚĐňĄŁÍęłÉ°˛×°şóŁŹ°˛×°łĚĐň˝Ťł˘ĘÔÖŘĆôÓŚÓĂłĚĐňĄŁ -CloseApplications=×ÔśŻšŘąŐÓŚÓĂłĚĐň(&A) -DontCloseApplications=˛ťšŘąŐÓŚÓĂłĚĐň(&D) -ErrorCloseApplications=°˛×°łĚĐňÎޡ¨×ÔśŻšŘąŐËůÓĐÓŚÓĂłĚĐňĄŁ˝¨ŇéÔÚźĚĐř˛Ů×÷֎ǰĎȚعŐËůÓĐĘšÓĂĐčͨšý°˛×°łĚĐň˝řĐиüĐÂľÄÎÄźţľÄÓŚÓĂłĚĐňĄŁ -; *** "Installing" wizard page -WizardInstalling=ŐýÔÚ°˛×° -InstallingLabel=°˛×°łĚĐňŐýÔÚźĆËăťúÉϰ˛×° [name]ŁŹÇëÉÔľČĄŁ -; *** "Setup Completed" wizard page -FinishedHeadingLabel=ÍęłÉ [name] °˛×°Ďňľź -FinishedLabelNoIcons=°˛×°łĚĐňŇŃÔÚźĆËăťúÉĎÍęłÉ°˛×° [name]ĄŁ -FinishedLabel=°˛×°łĚĐňŇŃÔÚźĆËăťúÉĎÍęłÉ°˛×° [name]ĄŁÍ¨šýŃĄÔń°˛×°ľÄżě˝Ýˇ˝Ę˝żÉŇÔĆôśŻ¸ĂÓŚÓĂłĚĐňĄŁ -ClickFinish=ľĽť÷Ą°ÍęłÉĄąŇÔÍËłö°˛×°łĚĐňĄŁ -FinishedRestartLabel=ŇŞÍęłÉ [name] ľÄ°˛×°ŁŹ°˛×°łĚĐňąŘĐëÖŘĆôźĆËăťúĄŁĘǡńŇŞÁ˘ź´ÖŘĆô? -FinishedRestartMessage=ŇŞÍęłÉ [name] ľÄ°˛×°ŁŹ°˛×°łĚĐňąŘĐëÖŘĆôźĆËăťúĄŁ%n%nĘǡńŇŞÁ˘ź´ÖŘĆô? -ShowReadmeCheck=ĘÇŁŹÎŇĎŁÍű˛éż´ README ÎÄźţ -YesRadio=ĘÇŁŹÁ˘ź´ÖŘĆôźĆËăťú(&Y) -NoRadio=ˇńŁŹÎŇ˝ŤÉÔşóÖŘĆôźĆËăťú(&N) -; used for example as 'Run MyProg.exe' -RunEntryExec=ÔËĐĐ %1 -; used for example as 'View Readme.txt' -RunEntryShellExec=˛éż´ %1 -; *** "Setup Needs the Next Disk" stuff -ChangeDiskTitle=°˛×°łĚĐňĐčŇŞĎÂŇť¸ö´ĹĹĚ -SelectDiskLabel2=Çë˛ĺČë´ĹĹĚ %1 ˛˘ľăť÷Ą°Čˇś¨ĄąĄŁ%n%nČçšű´Ë´ĹĹĚÉĎľÄÎÄźţżÉÔÚŇÔĎÂÎÄźţźĐÍâľÄĆäËűÎÄźţźĐÖĐŐŇľ˝ŁŹÇëĘäČëŐýȡ¡žśťňľĽť÷Ą°äŻŔŔĄąĄŁ -PathLabel=¡žś(&P): -FileNotInDir2=ÔÚĄ°%2ĄąÖĐÎޡ¨ś¨ÎťÎÄźţĄ°%1ĄąĄŁÇë˛ĺČëŐýȡľÄ´ĹĹĚťňŃĄÔńĆäËűÎÄźţźĐĄŁ -SelectDirectoryLabel=ÇëÖ¸ś¨ĎÂŇť¸ö´ĹĹĚľÄÎťÖĂĄŁ -; *** Installation phase messages -SetupAborted=°˛×°łĚĐňδÍęłÉĄŁ%n%nÇë¸üŐýÎĘĚⲢÖŘĐÂÔËĐа˛×°łĚĐňĄŁ -EntryAbortRetryIgnore=ľĽť÷Ą°ÖŘĘÔĄąŇÔÔŮ´Îł˘ĘÔŁŹľĽť÷Ą°şöÂÔĄąŇÔźĚĐřŁŹťňľĽť÷Ą°ÖĐÖšĄąŇÔČĄĎű°˛×°ĄŁ -; *** Installation status messages -StatusClosingApplications=ŐýÔښعŐÓŚÓĂłĚĐň... -StatusCreateDirs=ŐýÔÚ´´˝¨ÄżÂź... -StatusExtractFiles=ŐýÔÚ˝âŃšËőÎÄźţ... -StatusCreateIcons=ŐýÔÚ´´˝¨żě˝Ýˇ˝Ę˝... -StatusCreateIniEntries=ŐýÔÚ´´˝¨ INI Ďî... -StatusCreateRegistryEntries=ŐýÔÚ´´˝¨×˘˛áąíĎî... -StatusRegisterFiles=ŐýÔÚע˛áÎÄźţ... -StatusSavingUninstall=ŐýÔÚąŁ´ćĐśÔŘĐĹϢ... -StatusRunProgram=ŐýÔÚÍęłÉ°˛×°... -StatusRestartingApplications=ŐýÔÚÖŘĆôÓŚÓĂłĚĐň... -StatusRollback=ŐýÔÚťŘÍ˸ü¸Ä... -; *** Misc. errors -ErrorInternal2=ÄÚ˛ż´íÎó: %1 -ErrorFunctionFailedNoCode=%1 ʧ°Ü -ErrorFunctionFailed=%1 ʧ°ÜŁť´úÂë %2 -ErrorFunctionFailedWithMessage=%1 ʧ°ÜŁť´úÂë %2ĄŁ%n%3 -ErrorExecutingProgram=Îޡ¨Ö´ĐĐÎÄźţ:%n%1 -; *** Registry errors -ErrorRegOpenKey=´ňżŞ×˘˛áąíĎîĘąłö´í:%n%1\%2 -ErrorRegCreateKey=´´˝¨×˘˛áąíĎîĘąłö´í:%n%1\%2 -ErrorRegWriteKey=Đ´Čëע˛áąíĎîĘąłö´í:%n%1\%2 -; *** INI errors -ErrorIniEntry=ÔÚÎÄźţĄ°%1ĄąÖĐ´´˝¨ INI ĎîĘąłö´íĄŁ -; *** File copying errors -FileAbortRetryIgnore=ľĽť÷Ą°ÖŘĘÔĄąŇÔÔٴβŮ×÷ŁŹľĽť÷Ą°şöÂÔĄąŇÔĚřšý´ËÎÄźţ(˛ť˝¨Ňé´Ë˛Ů×÷)ŁŹťňľĽť÷Ą°ÖĐÖšĄąŇÔČĄĎű°˛×°ĄŁ -FileAbortRetryIgnore2=ľĽť÷Ą°ÖŘĘÔĄąŇÔÔٴβŮ×÷ŁŹľĽť÷Ą°şöÂÔĄąŇÔźĚĐř(˛ť˝¨Ňé´Ë˛Ů×÷)ŁŹťňľĽť÷Ą°ÖĐÖšĄąŇÔČĄĎű°˛×°ĄŁ -SourceIsCorrupted=Ô´ÎÄźţŇŃËđťľ -SourceDoesntExist=Ô´ÎÄźţĄ°%1Ąą˛ť´ćÔÚ -ExistingFileReadOnly=ĎÖÓĐÎÄźţąťąęźÇÎŞÖťśÁ×´ĚŹĄŁ%n%nľĽť÷Ą°ÖŘĘÔĄąŇÔÉžłýÖťśÁĚŘĐÔ˛˘ÖŘĘÔŁŹľĽť÷Ą°şöÂÔĄąŇÔĚřšý´ËÎÄźţŁŹťňľĽť÷Ą°ÖĐÖšĄąŇÔČĄĎű°˛×°ĄŁ -ErrorReadingExistingDest=ł˘ĘÔśÁČĄĎÖÓĐÎÄźţĘąłö´í: -FileExists=¸ĂÎÄźţŇŃ´ćÔÚĄŁ%n%nĘǡńŇŞ°˛×°łĚĐň¸˛¸ÇËü? -ExistingFileNewer=ĎÖÓĐÎÄźţąČ°˛×°łĚĐňŐýł˘ĘÔ°˛×°ľÄÎÄźţ¸üĐÂĄŁ˝¨Ň鹣ÁôĎÖÓĐÎÄźţĄŁ%n%nĘǡńŇŞąŁÁôĎÖÓĐÎÄźţ? -ErrorChangingAttr=ł˘ĘÔ¸ü¸ÄĎÖÓĐÎÄźţĚŘĐÔłö´í: -ErrorCreatingTemp=ł˘ĘÔÔÚÄżąęĿŸ´´˝¨ÎÄźţĘąłö´í: -ErrorReadingSource=ł˘ĘÔśÁČĄÔ´ÎÄźţĘąłö´í: -ErrorCopying=ł˘ĘÔ¸´ÖĆÎÄźţĘąłö´í: -ErrorReplacingExistingFile=ł˘ĘÔĚćťťĎÖÓĐÎÄźţĘąłö´í: -ErrorRestartReplace=RestartReplace ʧ°Ü: -ErrorRenamingTemp=ł˘ĘÔÔÚÄżąęĿŸÖŘĂüĂűÎÄźţĘąłö´í: -ErrorRegisterServer=Îޡ¨×˘˛á DLL/OCX: %1 -ErrorRegSvr32Failed=RegSvr32 ʧ°ÜŁŹÍËłö´úÂëÎŞ %1 -ErrorRegisterTypeLib=Îޡ¨×˘˛áŔŕĐÍżâ: %1 -; *** Post-installation errors -ErrorOpeningReadme=ł˘ĘÔ´ňżŞ README ÎÄźţĘąłö´íĄŁ -ErrorRestartingComputer=°˛×°łĚĐňÎޡ¨ÖŘĆôźĆËăťúĄŁÇëĘÖśŻÖ´Đд˲Ů×÷ĄŁ -; *** Uninstaller messages -UninstallNotFound=ÎÄźţĄ°%1Ąą˛ť´ćÔÚĄŁÎޡ¨°˛×°ĄŁ -UninstallOpenError=Îޡ¨´ňżŞÎÄźţĄ°%1ĄąĄŁÎޡ¨ĐśÔŘ -UninstallUnsupportedVer=ĐśÔŘČŐÖžĄ°%1ĄąľÄ¸ńĘ˝Îޡ¨ąť´Ë°ćąžľÄĐśÔŘłĚĐňĘśąđĄŁÎޡ¨ĐśÔŘ -UninstallUnknownEntry=ĐśÔŘČŐÖžÖС˘ĎÖδ֪ĚőÄż(%1) -ConfirmUninstall=ȡś¨ŇŞłšľ×Éžłý %1 şÍź°ĆäČŤ˛ż×éźţ? -UninstallOnlyOnWin64=˝öżÉÔÚ 64 Îť Windows ÉĎĐśÔش˰˛×°ĄŁ -OnlyAdminCanUninstall=˝öžßÓĐšÜŔíȨĎŢľÄÓĂť§˛ĹżÉĐśÔش˰˛×°ĄŁ -UninstallStatusLabel=Őý´ÓźĆËăťúÉžłý %1ŁŹÇëÉÔľČĄŁ -UninstalledAll=ŇŃłÉšŚ´ÓźĆËăťúÉĎÉžłý %1ĄŁ -UninstalledMost=%1 ĐśÔŘÍęłÉĄŁ%n%nÎޡ¨ÉžłýҝЊԪËŘĄŁżÉ˝ŤĆäĘÖśŻÉžłýĄŁ -UninstalledAndNeedsRestart=ŇŞÍęłÉ %1 ľÄĐśÔŘŁŹąŘĐëÖŘĆôźĆËăťúĄŁ%n%nĘǡńŇŞÁ˘ź´ÖŘĆô? -UninstallDataCorrupted=Ą°%1ĄąÎÄźţŇŃË𝾥ŁÎޡ¨ĐśÔŘ -; *** Uninstallation phase messages -ConfirmDeleteSharedFileTitle=Éžłýš˛ĎíÎÄźţ? -ConfirmDeleteSharedFile2=ϾͳąíĘžŇÔĎš˛ĎíÎÄźţ˛ťÔŮąťČκγĚĐňĘšÓĂĄŁĘǡńŇŞĐśÔŘÉžłý´Ëš˛ĎíÎÄźţ?%n%nČçšűÔÚÓĐłĚĐňČÔÔÚĘšÓĂ´ËÎÄźţśřËüąťÉžłýŁŹÔňłĚĐňżÉÄܲťťáŐýłŁÔËĐĐĄŁČçšű˛ťČˇś¨ŁŹÇëŃĄÔńĄ°ˇńĄąĄŁ˝ŤÎÄźţÁôץϾͳÉϲťťáÔěłÉČÎşÎÎĘĚ⥣ -SharedFileNameLabel=ÎÄźţĂű: -SharedFileLocationLabel=ÎťÖĂ: -WizardUninstalling=ĐśÔŘ×´ĚŹ -StatusUninstalling=ŐýÔÚĐśÔŘ %1... +ComponentsDiskSpaceGBLabel=当前选择的组件至少需要 [gb] GB 的磁盘空间。 +ComponentsDiskSpaceMBLabel=当前选择的组件至少需要 [mb] MB 的磁盘空间。 + +; *** “选择附加任务”向导页 +WizardSelectTasks=选择附加任务 +SelectTasksDesc=您想要安装程序执行哪些附加任务? +SelectTasksLabel2=选择您想要安装程序在安装 [name] 时执行的附加任务,然后单击“下一步”。 + +; *** “选择开始菜单文件夹”向导页 +WizardSelectProgramGroup=选择开始菜单文件夹 +SelectStartMenuFolderDesc=您想在哪里放置程序的快捷方式? +SelectStartMenuFolderLabel3=安装程序现在将在下列开始菜单文件夹中创建程序的快捷方式。 +SelectStartMenuFolderBrowseLabel=单击“下一步”继续。如果您想选择其它文件夹,单击“浏览”。 +MustEnterGroupName=您必须输入一个文件夹名。 +GroupNameTooLong=文件夹名或路径太长。 +InvalidGroupName=文件夹名是无效的。 +BadGroupName=文件夹名不能包含下列任何字符:%n%n%1 +NoProgramGroupCheck2=不创建开始菜单文件夹(&D) + +; *** “准备安装”向导页 +WizardReady=准备安装 +ReadyLabel1=安装程序现在准备开始安装 [name] 到您的电脑中。 +ReadyLabel2a=单击“安装”继续此安装程序。如果您想要回顾或改变设置,请单击“上一步”。 +ReadyLabel2b=单击“安装”继续此安装程序? +ReadyMemoUserInfo=用户信息: +ReadyMemoDir=目标位置: +ReadyMemoType=安装类型: +ReadyMemoComponents=选定组件: +ReadyMemoGroup=开始菜单文件夹: +ReadyMemoTasks=附加任务: + +; *** “正在准备安装”向导页 +WizardPreparing=正在准备安装 +PreparingDesc=安装程序正在准备安装 [name] 到您的电脑中。 +PreviousInstallNotCompleted=先前程序的安装/卸载未完成。您需要重新启动您的电脑才能完成安装。%n%n在重新启动电脑后,再运行安装完成 [name] 的安装。 +CannotContinue=安装程序不能继续。请单击“取消”退出。 +ApplicationsFound=下列应用程序正在使用的文件需要更新设置。它是建议您允许安装程序自动关闭这些应用程序。 +ApplicationsFound2=下列应用程序正在使用的文件需要更新设置。它是建议您允许安装程序自动关闭这些应用程序。安装完成后,安装程序将尝试重新启动应用程序。 +CloseApplications=自动关闭该应用程序(&A) +DontCloseApplications=不要关闭该应用程序(D) +ErrorCloseApplications=安装程序无法自动关闭所有应用程序。在继续之前,我们建议您关闭所有使用需要更新的安装程序文件。 +PrepareToInstallNeedsRestart=安装程序必须重新启动计算机。重新启动计算机后,请再次运行安装程序以完成 [name] 的安装。%n%n是否立即重新启动? + +; *** “正在安装”向导页 +WizardInstalling=正在安装 +InstallingLabel=安装程序正在安装 [name] 到您的电脑中,请稍等。 + +; *** “安装完成”向导页 +FinishedHeadingLabel=[name] 安装完成 +FinishedLabelNoIcons=安装程序已在您的电脑中安装了 [name]。 +FinishedLabel=安装程序已在您的电脑中安装了 [name]。此应用程序可以通过选择安装的快捷方式运行。 +ClickFinish=单击“完成”退出安装程序。 +FinishedRestartLabel=要完成 [name] 的安装,安装程序必须重新启动您的电脑。您想现在重新启动吗? +FinishedRestartMessage=要完成 [name] 的安装,安装程序必须重新启动您的电脑。%n%n您想现在重新启动吗? +ShowReadmeCheck=是,您想查阅自述文件 +YesRadio=是,立即重新启动电脑(&Y) +NoRadio=否,稍后重新启动电脑(&N) +; 用于象“运行 MyProg.exe” +RunEntryExec=运行 %1 +; 用于象“查阅 Readme.txt” +RunEntryShellExec=查阅 %1 + +; *** “安装程序需要下一张磁盘”提示 +ChangeDiskTitle=安装程序需要下一张磁盘 +SelectDiskLabel2=请插入磁盘 %1 并单击“确定”。%n%n如果这个磁盘中的文件不能在不同于下列显示的文件夹中找到,输入正确的路径或单击“浏览”。 +PathLabel=路径(&P): +FileNotInDir2=文件“%1”不能在“%2”定位。请插入正确的磁盘或选择其它文件夹。 +SelectDirectoryLabel=请指定下一张磁盘的位置。 + +; *** 安装状态消息 +SetupAborted=安装程序未完成安装。%n%n请修正这个问题并重新运行安装程序。 +AbortRetryIgnoreSelectAction=选项 +AbortRetryIgnoreRetry=重试(&T) +AbortRetryIgnoreIgnore=忽略错误并继续(&I) +AbortRetryIgnoreCancel=关闭安装程序 + +; *** 安装状态消息 +StatusClosingApplications=正在关闭应用程序... +StatusCreateDirs=正在创建目录... +StatusExtractFiles=正在解压缩文件... +StatusCreateIcons=正在创建快捷方式... +StatusCreateIniEntries=正在创建 INI 条目... +StatusCreateRegistryEntries=正在创建注册表条目... +StatusRegisterFiles=正在注册文件... +StatusSavingUninstall=正在保存卸载信息... +StatusRunProgram=正在完成安装... +StatusRestartingApplications=正在重启应用程序... +StatusRollback=正在撤销更改... + +; *** 其它错误 +ErrorInternal2=内部错误: %1 +ErrorFunctionFailedNoCode=%1 夹贼 +ErrorFunctionFailed=%1 失败;错误代码 %2 +ErrorFunctionFailedWithMessage=%1 失败;错误代码 %2.%n%3 +ErrorExecutingProgram=不能执行文件:%n%1 + +; *** 注册表错误 +ErrorRegOpenKey=打开注册表项时出错:%n%1\%2 +ErrorRegCreateKey=创建注册表项时出错:%n%1\%2 +ErrorRegWriteKey=写入注册表项时出错:%n%1\%2 + +; *** INI 错误 +ErrorIniEntry=在文件“%1”创建 INI 项目错误。 + +; *** 文件复制错误 +FileAbortRetryIgnoreSkipNotRecommended=跳过这个文件 (不推荐)(&S) +FileAbortRetryIgnoreIgnoreNotRecommended=忽略错误并继续 (不推荐)(&I) +SourceIsCorrupted=源文件已损坏 +SourceDoesntExist=源文件“%1”不存在 +ExistingFileReadOnly2=无法替换现有文件,因为它是只读的。 +ExistingFileReadOnlyRetry=移除只读属性并重试(&R) +ExistingFileReadOnlyKeepExisting=保留现有文件(&K) +ErrorReadingExistingDest=尝试读取现有文件时发生一个错误: +FileExists=文件已经存在。%n%n您想要安装程序覆盖它吗? +ExistingFileNewer=现有的文件新与安装程序要安装的文件。推荐您保留现有文件。%n%n您想要保留现有的文件吗? +ErrorChangingAttr=尝试改变下列现有的文件的属性时发生一个错误: +ErrorCreatingTemp=尝试在目标目录创建文件时发生一个错误: +ErrorReadingSource=尝试读取下列源文件时发生一个错误: +ErrorCopying=尝试复制下列文件时发生一个错误: +ErrorReplacingExistingFile=尝试替换现有的文件时发生错误: +ErrorRestartReplace=重启电脑后替换文件失败: +ErrorRenamingTemp=尝试重新命名以下目标目录中的一个文件时发生错误: +ErrorRegisterServer=不能注册 DLL/OCX: %1 +ErrorRegSvr32Failed=RegSvr32 失败;退出代码 %1 +ErrorRegisterTypeLib=不能注册类型库: %1 + +; *** 卸载显示名字标记 +; used for example as 'My Program (32-bit)' +UninstallDisplayNameMark=%1 (%2) +; used for example as 'My Program (32-bit, All users)' +UninstallDisplayNameMarks=%1 (%2, %3) +UninstallDisplayNameMark32Bit=32位 +UninstallDisplayNameMark64Bit=64位 +UninstallDisplayNameMarkAllUsers=所有用户 +UninstallDisplayNameMarkCurrentUser=当前用户 + +; *** 安装后错误 +ErrorOpeningReadme=当尝试打开自述文件时发生一个错误。 +ErrorRestartingComputer=安装程序不能重新启动电脑,请手动重启。 + +; *** 卸载消息 +UninstallNotFound=文件“%1”不存在。不能卸载。 +UninstallOpenError=文件“%1”不能打开。不能卸载。 +UninstallUnsupportedVer=卸载日志文件“%1”有未被这个版本的卸载器承认的格式。不能卸载 +UninstallUnknownEntry=在卸载日志中遇到一个未知的条目 (%1) +ConfirmUninstall=您确认想要完全删除 %1 及它的所有组件吗? +UninstallOnlyOnWin64=这个安装程序只能在 64 位 Windows 中进行卸载。 +OnlyAdminCanUninstall=这个安装的程序只能是有管理员权限的用户才能卸载。 +UninstallStatusLabel=正在从您的电脑中删除 %1,请等待。 +UninstalledAll=%1 已顺利地从您的电脑中删除。 +UninstalledMost=%1 卸载完成。%n%n有一些内容不能被删除。您可以手工删除它们。 +UninstalledAndNeedsRestart=要完成 %1 的卸载,您的电脑必须重新启动。%n%n您现在想重新启动电脑吗? +UninstallDataCorrupted=“%1”文件被破坏,不能卸载 + +; *** 卸载状态消息 +ConfirmDeleteSharedFileTitle=删除共享文件吗? +ConfirmDeleteSharedFile2=系统中包含的下列共享文件已经不被其它程序使用。您想要卸载程序删除这些共享文件吗?%n%n如果这些文件被删除,但还有程序正在使用这些文件,这些程序可能不能正确执行。如果您不能确定,选择“否”。把这些文件保留在系统中以免引起问题。 +SharedFileNameLabel=文件名: +SharedFileLocationLabel=位置: +WizardUninstalling=卸载状态 +StatusUninstalling=正在卸载 %1... + ; *** Shutdown block reasons -ShutdownBlockReasonInstallingApp=ŐýÔÚ°˛×° %1ĄŁ -ShutdownBlockReasonUninstallingApp=ŐýÔÚĐśÔŘ %1ĄŁ +ShutdownBlockReasonInstallingApp=正在安装 %1. +ShutdownBlockReasonUninstallingApp=正在卸载 %1. + ; The custom messages below aren't used by Setup itself, but if you make ; use of them in your scripts, you'll want to translate them. + [CustomMessages] -NameAndVersion=%1 °ćąž %2 -AdditionalIcons=ĆäËűżě˝Ýˇ˝Ę˝: -CreateDesktopIcon=´´˝¨×ŔĂćżě˝Ýˇ˝Ę˝(&D) -CreateQuickLaunchIcon=´´˝¨żěËŮĆôśŻżě˝Ýˇ˝Ę˝(&Q) -ProgramOnTheWeb=Web ÉĎľÄ %1 -UninstallProgram=ĐśÔŘ %1 -LaunchProgram=ĆôśŻ %1 -AssocFileExtension=˝Ť %1 Óë %2 ÎÄźţŔŠŐšĂűšŘÁŞ(&A) -AssocingFileExtension=Őý˝Ť %1 Óë %2 ÎÄźţŔŠŐšĂűšŘÁŞ... -AutoStartProgramGroupDescription=ĆôśŻ: -AutoStartProgram=×ÔśŻĆôśŻ %1 -AddonHostProgramNotFound=Îޡ¨ÔÚËůŃĄÎÄźţźĐÖĐś¨Îť %1ĄŁ%n%nĘǡńČÔŇŞźĚĐř? \ No newline at end of file + +NameAndVersion=%1 版本 %2 +AdditionalIcons=附加快捷方式: +CreateDesktopIcon=创建桌面快捷方式(&D) +CreateQuickLaunchIcon=创建快速运行栏快捷方式(&Q) +ProgramOnTheWeb=%1 网站 +UninstallProgram=卸载 %1 +LaunchProgram=运行 %1 +AssocFileExtension=将 %2 文件扩展名与 %1 建立关联(&A) +AssocingFileExtension=正在将 %2 文件扩展名与 %1 建立关联... +AutoStartProgramGroupDescription=启动组: +AutoStartProgram=自动启动 %1 +AddonHostProgramNotFound=%1无法找到您所选择的文件夹。%n%n您想要继续吗? + diff --git a/build/win32/i18n/Default.zh-tw.isl b/build/win32/i18n/Default.zh-tw.isl index 4746349e19..fb748761f9 100644 --- a/build/win32/i18n/Default.zh-tw.isl +++ b/build/win32/i18n/Default.zh-tw.isl @@ -1,298 +1,359 @@ -; *** Inno Setup version 5.5.3+ Traditional Chinese messages *** +ďťż; *** Inno Setup version 6.0.0+ Chinese Traditional messages *** ; -; To download user-contributed translations of this file, go to: -; http://www.jrsoftware.org/files/istrans/ +; Name: John Wu, mr.johnwu@gmail.com +; Base on 5.5.3+ translations by Samuel Lee, Email: 751555749@qq.com +; Translation based on network resource ; -; Note: When translating this text, do not add periods (.) to the end of -; messages that didn't have them already, because on those messages Inno -; Setup adds the periods automatically (appending a period would result in -; two periods being displayed). + [LangOptions] ; The following three entries are very important. Be sure to read and ; understand the '[LangOptions] section' topic in the help file. -LanguageName=Traditional Chinese +; If Language Name display incorrect, uncomment next line +LanguageName=<7e41><9ad4><4e2d><6587> LanguageID=$0404 -LanguageCodePage=950 +LanguageCodepage=950 ; If the language you are translating to requires special font faces or ; sizes, uncomment any of the following entries and change them accordingly. -;DialogFontName= -;DialogFontSize=8 -;WelcomeFontName=Verdana -;WelcomeFontSize=12 -;TitleFontName=Arial -;TitleFontSize=29 -;CopyrightFontName=Arial -;CopyrightFontSize=8 +DialogFontName=新細明體 +DialogFontSize=9 +TitleFontName=Arial +TitleFontSize=28 +WelcomeFontName=新細明體 +WelcomeFontSize=12 +CopyrightFontName=新細明體 +CopyrightFontSize=9 + [Messages] + ; *** Application titles -SetupAppTitle=Św¸Ëľ{ŚĄ -SetupWindowTitle=Św¸Ëľ{ŚĄ - %1 -UninstallAppTitle=¸Ń°ŁŚw¸Ë -UninstallAppFullTitle=%1 ¸Ń°ŁŚw¸Ë +SetupAppTitle=安裝程式 +SetupWindowTitle=%1 安裝程式 +UninstallAppTitle=解除安裝 +UninstallAppFullTitle=解除安裝 %1 + ; *** Misc. common -InformationTitle=¸ę°T -ConfirmTitle=˝Tť{ -ErrorTitle=żůť~ +InformationTitle=訊息 +ConfirmTitle=確認 +ErrorTitle=錯誤 + ; *** SetupLdr messages -SetupLdrStartupMessage=łoˇ|Św¸Ë %1ĄC­nÄ~ÄňśÜ? -LdrCannotCreateTemp=ľLŞkŤŘĽßźČŚsŔÉĄCŚw¸Ë¤w¤¤¤î -LdrCannotExecTemp=ľLŞk°őŚćźČŚsĽŘżý¤¤ŞşŔɎץCŚw¸Ë¤w¤¤¤î +SetupLdrStartupMessage=這將會安裝 %1。您想要繼續嗎? +LdrCannotCreateTemp=無法建立暫存檔案。安裝程式將會結束。 +LdrCannotExecTemp=無法執行暫存檔案。安裝程式將會結束。 +HelpTextNote= + ; *** Startup error messages -LastErrorMessage=%1ĄC%n%nżůť~ %2: %3 -SetupFileMissing=Św¸ËĽŘżý¤¤ŻĘ¤ÖŔÉŽ× %1ĄC˝Đ­×Ľż°ÝĂDĄAŠÎ­Ťˇs¨úąoľ{ŚĄŞşˇs˝ĆĽťĄC -SetupFileCorrupt=Św¸Ëľ{ŚĄŔɎפwˇlˇ´ĄC˝Đ­Ťˇs¨úąo¸Óľ{ŚĄŞş˝ĆĽťĄC -SetupFileCorruptOrWrongVer=Św¸Ëľ{ŚĄŔɎפwˇlˇ´ĄAŠÎ¤ŁŹŰŽeŠóťPŚšŞŠŞşŚw¸Ëľ{ŚĄĄC˝Đ­×Ľż°ÝĂDĄAŠÎ­Ťˇs¨úąoľ{ŚĄŞşˇs˝ĆĽťĄC -InvalidParameter=ŚbŠRĽOŚC¤WśÇťź¤FľLŽÄŞş°ŃźĆ:%n%n%1 -SetupAlreadyRunning=Św¸Ëľ{ŚĄ¤wŚb°őŚć¤¤ĄC -WindowsVersionNotSupported=Śšľ{ŚĄ¤Ł¤ä´Ššq¸ŁŠŇ°őŚćŞş Windows ŞŠĽťĄC -WindowsServicePackRequired=Śšľ{ŚĄťÝ­n %1 Service Pack %2 ŠÎ§óˇsŞŠĽťĄC -NotOnThisPlatform=Śšľ{ŚĄ¤Łˇ|Śb %1 ¤W°őŚćĄC -OnlyOnThisPlatform=Śšľ{ŚĄĽ˛śˇŚb %1 ¤W°őŚćĄC -OnlyOnTheseArchitectures=Śšľ{ŚĄĽuĽiŚw¸ËŚbąMʰ¤UŚCłB˛zžšŹ[şcł]­pŞş Windows ŞŠĽť¤W:%n%n%1 -MissingWOW64APIs=ąz°őŚćŞş Windows ŞŠĽť¤Ł§tŚw¸Ëľ{ŚĄ°őŚć 64 Śě¤¸Św¸ËŠŇťÝŞşĽ\ŻŕĄC­Y­n­×ĽżŚš°ÝĂDĄA˝ĐŚw¸Ë Service Pack %1ĄC -WinVersionTooLowError=Śšľ{ŚĄťÝ­n %1 ŞŠ %2 ŠÎ§óˇsŞŠĽťĄC -WinVersionTooHighError=Śšľ{ŚĄľLŞkŚw¸ËŚb %1 ŞŠ %2 ŠÎ§óˇsŞŠĽť¤WĄC -AdminPrivilegesRequired=Św¸ËŚšľ{ŚĄŽÉĄAĽ˛śˇĽH¨t˛ÎşŢ˛z­ű¨­¤Ŕľn¤JĄC -PowerUserPrivilegesRequired=ˇíązŚw¸ËŚšľ{ŚĄŽÉĄAĽ˛śˇĽH¨t˛ÎşŢ˛z­űŠÎ Power Users ¸s˛ŐŞşŚ¨­ű¨­¤Ŕľn¤JĄC -SetupAppRunningError=Św¸ËŽÉ°ť´ú¨ě %1 ĽŘŤeĽżŚb°őŚć¤¤ĄC%n%n˝ĐĽß§YĂöłŹ¨äŠŇŚł°őŚć­ÓĹéĄC­Y­nÄ~ÄňĄA˝ĐŤö¤@¤U [˝TŠw]; ­Y­nľ˛§ôĄA˝ĐŤö¤@¤U [¨úŽř]ĄC -UninstallAppRunningError=¸Ń°ŁŚw¸ËŽÉ°ť´ú¨ě %1 ĽŘŤeĽżŚb°őŚć¤¤ĄC%n%n˝ĐĽß§YĂöłŹ¨äŠŇŚł°őŚć­ÓĹéĄC­Y­nÄ~ÄňĄA˝ĐŤö¤@¤U [˝TŠw]; ­Y­nľ˛§ôĄA˝ĐŤö¤@¤U [¨úŽř]ĄC +LastErrorMessage=%1%n%n錯誤 %2: %3 +SetupFileMissing=安裝資料夾中遺失檔案 %1。請修正此問題或重新取得此軟體。 +SetupFileCorrupt=安裝檔案已經損毀。請重新取得此軟體。 +SetupFileCorruptOrWrongVer=安裝檔案已經損毀,或與安裝程式的版本不符。請重新取得此軟體。 +InvalidParameter=某個無效的變量已被傳遞到了命令列:%n%n%1 +SetupAlreadyRunning=安裝程式已經在執行。 +WindowsVersionNotSupported=本安裝程式並不支援目前在電腦所運行的 Windows 版本。 +WindowsServicePackRequired=本安裝程式需要 %1 Service Pack %2 或更新。 +NotOnThisPlatform=這個程式無法在 %1 執行。 +OnlyOnThisPlatform=這個程式必須在 %1 執行。 +OnlyOnTheseArchitectures=這個程式只能在專門為以下處理器架構而設計的 Windows 上安裝:%n%n%1 +WinVersionTooLowError=這個程式必須在 %1 版本 %2 或以上的系統執行。 +WinVersionTooHighError=這個程式無法安裝在 %1 版本 %2 或以上的系統。 +AdminPrivilegesRequired=您必須登入成系統管理員以安裝這個程式。 +PowerUserPrivilegesRequired=您必須登入成具有系統管理員或 Power User 權限的使用者以安裝這個程式。 +SetupAppRunningError=安裝程式偵測到 %1 正在執行。%n%n請關閉該程式後按 [確定] 繼續,或按 [取消] 離開。 +UninstallAppRunningError=解除安裝程式偵測到 %1 正在執行。%n%n請關閉該程式後按 [確定] 繼續,或按 [取消] 離開。 + +; *** Startup questions +PrivilegesRequiredOverrideTitle=選擇安裝程式安裝模式 +PrivilegesRequiredOverrideInstruction=選擇安裝模式 +PrivilegesRequiredOverrideText1=可以為所有使用者安裝 %1 (需要系統管理權限),或是僅為您安裝。 +PrivilegesRequiredOverrideText2=可以僅為您安裝 %1,或是為所有使用者安裝 (需要系統管理權限)。 +PrivilegesRequiredOverrideAllUsers=為所有使用者安裝 (&A) +PrivilegesRequiredOverrideAllUsersRecommended=為所有使用者安裝 (建議選項) (&A) +PrivilegesRequiredOverrideCurrentUser=僅為我安裝 (&M) +PrivilegesRequiredOverrideCurrentUserRecommended=僅為我安裝 (建議選項) (&M) + ; *** Misc. errors -ErrorCreatingDir=Św¸Ëľ{ŚĄľLŞkŤŘĽßĽŘżý "%1" -ErrorTooManyFilesInDir=Ś]ʰĽŘżý "%1" Ľ]§t¤ÓŚhŔɎץAŠŇĽHľLŞkŚb¨ä¤¤ŤŘĽßŔÉŽ× +ErrorCreatingDir=安裝程式無法建立資料夾“%1”。 +ErrorTooManyFilesInDir=無法在資料夾“%1”內建立檔案,因為資料夾內有太多的檔案。 + ; *** Setup common messages -ExitSetupTitle=ľ˛§ôŚw¸Ë -ExitSetupMessage=Św¸ËĽź§šŚ¨ĄC­YĽß§Yľ˛§ôĄAąN¤Łˇ|Św¸Ëľ{ŚĄĄC%n%nązĽiĽHľyŤáŚA°őŚćŚw¸Ëľ{ŚĄ¨Ó§šŚ¨Św¸ËĄC%n%n­nľ˛§ôŚw¸ËśÜ? -AboutSetupMenuItem=ĂöŠóŚw¸Ëľ{ŚĄ(&A)... -AboutSetupTitle=ĂöŠóŚw¸Ëľ{ŚĄ -AboutSetupMessage=%1 ŞŠ %2%n%3%n%n%1 ­ş­ś:%n%4 +ExitSetupTitle=結束安裝程式 +ExitSetupMessage=安裝尚未完成。如果您現在結束安裝程式,這個程式將不會被安裝。%n%n您可以稍後再執行安裝程式以完成安裝程序。您現在要結束安裝程式嗎? +AboutSetupMenuItem=關於安裝程式(&A)... +AboutSetupTitle=關於安裝程式 +AboutSetupMessage=%1 版本 %2%n%3%n%n%1 網址:%n%4 AboutSetupNote= TranslatorNote= + ; *** Buttons -ButtonBack=< ¤W¤@¨B(&B) -ButtonNext=¤U¤@¨B(&N) > -ButtonInstall=Św¸Ë(&I) -ButtonOK=˝TŠw -ButtonCancel=¨úŽř -ButtonYes=ŹO(&Y) -ButtonYesToAll=ĽţłĄŹŇŹO(&A) -ButtonNo=§_(&N) -ButtonNoToAll=ĽţłĄŹŇ§_(&O) -ButtonFinish=§šŚ¨(&F) -ButtonBrowse=ÂsÄý(&B)... -ButtonWizardBrowse=ÂsÄý(&R)... -ButtonNewFolder=ŤŘĽßˇs¸ęŽĆ§¨(&M) +ButtonBack=< 上一步(&B) +ButtonInstall=安裝(&I) +ButtonNext=下一步(&N) > +ButtonOK=確定 +ButtonCancel=取消 +ButtonYes=是(&Y) +ButtonYesToAll=全部皆是(&A) +ButtonNo=同(&N) +ButtonNoToAll=全部皆否(&O) +ButtonFinish=完成(&F) +ButtonBrowse=瀏覽(&B)... +ButtonWizardBrowse=瀏覽(&R)... +ButtonNewFolder=建立新資料夾(&M) + ; *** "Select Language" dialog messages -SelectLanguageTitle=żď¨úŚw¸Ëľ{ŚĄťy¨Ľ -SelectLanguageLabel=żď¨úŚw¸Ë´ÁśĄŠŇ­n¨ĎĽÎŞşťy¨Ľ: +SelectLanguageTitle=選擇安裝語言 +SelectLanguageLabel=選擇在安裝過程中使用的語言: + ; *** Common wizard text -ClickNext=­Y­nÄ~ÄňĄA˝ĐŤö¤@¤U [¤U¤@¨B]; ­Y­nľ˛§ôŚw¸ËĄA˝ĐŤö¤@¤U [¨úŽř]ĄC +ClickNext=按 [下一步] 繼續安裝,或按 [取消] 結束安裝程式。 BeveledLabel= -BrowseDialogTitle=ÂsÄý¸ęŽĆ§¨ -BrowseDialogLabel=˝Đąq¤UŚC˛Młć¤¤żď¨ú¸ęŽĆ§¨ĄAľMŤáŤö¤@¤U [˝TŠw]ĄC -NewFolderName=ˇsźW¸ęŽĆ§¨ +BrowseDialogTitle=瀏覽資料夾 +BrowseDialogLabel=在下面的資料夾列表中選擇一個資料夾,然後按 [確定]。 +NewFolderName=新資料夾 + ; *** "Welcome" wizard page -WelcomeLabel1=ĹwŞď¨ĎĽÎ [name] Św¸ËşëĆF -WelcomeLabel2=łoˇ|ŚbązŞşšq¸Ł¤WŚw¸Ë [name/ver]ĄC%n%nŤŘÄłązĽýĂöłŹŠŇŚł¨äĽLŔłĽÎľ{ŚĄĄAľMŤáŚAÄ~ÄňĄC +WelcomeLabel1=歡迎使用 [name] 安裝程式 +WelcomeLabel2=這個安裝程式將會安裝 [name/ver] 到您的電腦。%n%n我們強烈建議您在安裝過程中關閉其它的應用程式,以避免與安裝程式發生沖突。 + ; *** "Password" wizard page -WizardPassword=ąK˝X -PasswordLabel1=ŚšŚw¸Ë¨üąK˝XŤOĹ@ĄC -PasswordLabel3=˝Đ´Ł¨ŃąK˝XĄAľMŤáŤö¤@¤U [¤U¤@¨B] ĽHÄ~ÄňĄCąK˝X°Ď¤Ŕ¤j¤pźgĄC -PasswordEditLabel=ąK˝X(&P): -IncorrectPassword=żé¤JŞşąK˝X¤ŁĽż˝TĄC˝ĐŚA¸Ő¤@ڏĄC +WizardPassword=密碼 +PasswordLabel1=這個安裝程式具有密碼保護。 +PasswordLabel3=請輸入密碼,然後按 [下一步] 繼續。密碼是區分大小寫的。 +PasswordEditLabel=密碼(&P): +IncorrectPassword=您輸入的密碼不正確,請重新輸入。 + ; *** "License Agreement" wizard page -WizardLicense=ąÂĹvŚXŹů -LicenseLabel=˝ĐĽýž\ĹŞ¤UŚC­Ť­n¸ę°TŚAÄ~ÄňĄC -LicenseLabel3=˝Đž\ĹŞ¤UŚCąÂĹvŚXŹůĄCązĽ˛śˇąľ¨üŚšŚXŹůąř´ÚĄA¤~ŻŕÄ~ÄňŚw¸ËĄC -LicenseAccepted=§Úąľ¨üŚXŹů(&A) -LicenseNotAccepted=§Ú¤Łąľ¨üŚXŹů(&D) +WizardLicense=授權合約 +LicenseLabel=請閱讀以下授權合約。 +LicenseLabel3=請閱讀以下授權合約,您必須接受合約的各項條款才能繼續安裝。 +LicenseAccepted=我同意(&A) +LicenseNotAccepted=我不同意(&D) + ; *** "Information" wizard pages -WizardInfoBefore=¸ę°T -InfoBeforeLabel=˝ĐĽýž\ĹŞ¤UŚC­Ť­n¸ę°TŚAÄ~ÄňĄC -InfoBeforeClickLabel=ˇíązˇÇłĆŚn­nÄ~ÄňŚw¸ËŽÉĄA˝ĐŤö¤@¤U [¤U¤@¨B]ĄC -WizardInfoAfter=¸ę°T -InfoAfterLabel=˝ĐĽýž\ĹŞ¤UŚC­Ť­n¸ę°TŚAÄ~ÄňĄC -InfoAfterClickLabel=ˇíązˇÇłĆŚn­nÄ~ÄňŚw¸ËŽÉĄA˝ĐŤö¤@¤U [¤U¤@¨B]ĄC +WizardInfoBefore=訊息 +InfoBeforeLabel=在繼續安裝之前請閱讀以下重要資訊。 +InfoBeforeClickLabel=當您準備好繼續安裝,請按 [下一步]。 +WizardInfoAfter=訊息 +InfoAfterLabel=在繼續安裝之前請閱讀以下重要資訊。 +InfoAfterClickLabel=當您準備好繼續安裝,請按 [下一步]。 + ; *** "User Information" wizard page -WizardUserInfo=¨ĎĽÎŞĚ¸ę°T -UserInfoDesc=˝Đżé¤JązŞş¸ę°TĄC -UserInfoName=¨ĎĽÎŞĚŚWşŮ(&U): -UserInfoOrg=˛Ő´(&O): -UserInfoSerial=§Ç¸š(&S): -UserInfoNameRequired=Ľ˛śˇżé¤JŚWşŮĄC +WizardUserInfo=使用者資訊 +UserInfoDesc=請輸入您的資料。 +UserInfoName=使用者名稱(&U): +UserInfoOrg=組織(&O): +UserInfoSerial=序號(&S): +UserInfoNameRequired=您必須輸入您的名稱。 + ; *** "Select Destination Location" wizard page -WizardSelectDir=żď¨úĽŘŞşŚaŚě¸m -SelectDirDesc=ŔłąN [name] Św¸ËŚbŚółB? -SelectDirLabel3=Św¸Ëľ{ŚĄˇ|ąN [name] Św¸ËŚb¤UŚC¸ęŽĆ§¨¤¤ĄC -SelectDirBrowseLabel=­Y­nÄ~ÄňĄA˝ĐŤö¤@¤U [¤U¤@¨B]ĄC­YązˇQżď¨ú¤ŁŚPŞş¸ęŽĆ§¨ĄA˝ĐŤö¤@¤U [ÂsÄý]ĄC -DiskSpaceMBLabel=ŚÜ¤ÖśˇŚł [mb] MB ŞşĽiĽÎşĎşĐŞĹśĄĄC -CannotInstallToNetworkDrive=Św¸Ëľ{ŚĄľLŞkŚw¸Ë¨ěşô¸ôşĎşĐž÷ĄC -CannotInstallToUNCPath=Św¸Ëľ{ŚĄľLŞkŚw¸Ë¨ě UNC ¸ôŽ|ĄC -InvalidPath=Ľ˛śˇżé¤JĽ]§tşĎşĐž÷ĽN¸šŞş§šžă¸ôŽ|ĄA¨ŇŚp:%n%nC:\APP%n%nŠÎżé¤J¤UŚCŽćŚĄŞş UNC ¸ôŽ|:%n%n\\ŚřŞAžš\Ś@ĽÎ -InvalidDrive=żď¨úŞşşĎşĐž÷ŠÎ UNC Ś@ĽÎ¤ŁŚsŚbŠÎľLŞkŚs¨úĄC˝Đżď¨ú¨äĽLşĎşĐž÷ŠÎ UNC Ś@ĽÎĄC -DiskSpaceWarningTitle=şĎşĐŞĹśĄ¤Ł¨Ź -DiskSpaceWarning=Św¸Ëľ{ŚĄŚÜ¤ÖťÝ­n %1 KB ŞşĽiĽÎŞĹśĄ¤~ŻŕŚw¸ËĄAŚýŠŇżďşĎşĐž÷ŞşĽiĽÎŞĹśĄĽuŚł %2 KBĄC%n%n¤´­nÄ~ÄňśÜ? -DirNameTooLong=¸ęŽĆ§¨ŚWşŮŠÎ¸ôŽ|šLŞřĄC -InvalidDirName=Śš¸ęŽĆ§¨ŚWşŮľLŽÄĄC -BadDirName32=¸ęŽĆ§¨ŚWşŮ¤ŁąoĽ]§t¤UŚCĽô¤@Śr¤¸:%n%n%1 -DirExistsTitle=¸ęŽĆ§¨¤wŚsŚb -DirExists=¤wŚł¸ęŽĆ§¨ %n%n%1%n%nĄC¤´­nŚw¸Ë¨ě¸Ó¸ęŽĆ§¨śÜ? -DirDoesntExistTitle=¸ęŽĆ§¨¤ŁŚsŚb -DirDoesntExist=¸ęŽĆ§¨ %n%n%1%n%n ¤ŁŚsŚbĄC­nŤŘĽß¸Ó¸ęŽĆ§¨śÜ? +WizardSelectDir=選擇目的資料夾 +SelectDirDesc=選擇安裝程式安裝 [name] 的位置。 +SelectDirLabel3=安裝程式將會把 [name] 安裝到下面的資料夾。 +SelectDirBrowseLabel=按 [下一步] 繼續,如果您想選擇另一個資料夾,請按 [瀏覽]。 +DiskSpaceMBLabel=最少需要 [mb] MB 磁碟空間。 +CannotInstallToNetworkDrive=安裝程式無法安裝於網絡磁碟機。 +CannotInstallToUNCPath=安裝程式無法安裝於 UNC 路徑。 +InvalidPath=您必須輸入完整的路徑名稱及磁碟機代碼。%n%n例如 C:\App 或 UNC 路徑格式 \\伺服器\共用資料夾。 +InvalidDrive=您選取的磁碟機或 UNC 名稱不存在或無法存取,請選擇其他的目的地。 +DiskSpaceWarningTitle=磁碟空間不足 +DiskSpaceWarning=安裝程式需要至少 %1 KB 的磁碟空間,您所選取的磁碟只有 %2 KB 可用空間。%n%n您要繼續安裝嗎? +DirNameTooLong=資料夾名稱或路徑太長。 +InvalidDirName=資料夾名稱不正確。 +BadDirName32=資料夾名稱不得包含以下特殊字元:%n%n%1 +DirExistsTitle=資料夾已經存在 +DirExists=資料夾:%n%n%1%n%n 已經存在。仍要安裝到該資料夾嗎? +DirDoesntExistTitle=資料夾不存在 +DirDoesntExist=資料夾:%n%n%1%n%n 不存在。要建立該資料夾嗎? + ; *** "Select Components" wizard page -WizardSelectComponents=żď¨ú¤¸Ľó -SelectComponentsDesc=ŔłŚw¸Ë­ţ¨Ç¤¸Ľó? -SelectComponentsLabel2=żď¨úąz­nŚw¸ËŞş¤¸Ľó; ˛M°Łąz¤Ł­nŚw¸ËŞş¤¸ĽóĄCˇíązˇÇłĆŚn­nÄ~ÄňŽÉĄA˝ĐŤö¤@¤U [¤U¤@¨B]ĄC -FullInstallation=§šžăŚw¸Ë +WizardSelectComponents=選擇元件 +SelectComponentsDesc=選擇將會被安裝的元件。 +SelectComponentsLabel2=選擇您想要安裝的元件;清除您不想安裝的元件。然後按 [下一步] 繼續安裝。 +FullInstallation=完整安裝 ; if possible don't translate 'Compact' as 'Minimal' (I mean 'Minimal' in your language) -CompactInstallation=şë²Św¸Ë -CustomInstallation=ŚŰ­qŚw¸Ë -NoUninstallWarningTitle=¤wŚłŚš¤¸Ľó -NoUninstallWarning=Św¸Ëľ{ŚĄ°ť´ú¨ěązŞşšq¸Ł¤wŚw¸Ë¤F¤UŚC¤¸Ľó:%n%n%1%n%nąNło¨Ç¤¸Ľó¨úŽřżď¨ú¨Ă¤Łˇ|¨Ď¤¸Ľó¸Ń°ŁŚw¸ËĄC%n%n¤´­nÄ~ÄňśÜ? +CompactInstallation=最小安裝 +CustomInstallation=自訂安裝 +NoUninstallWarningTitle=元件已存在 +NoUninstallWarning=安裝程式偵測到以下元件已經安裝在您的電腦上:%n%n%1%n%n取消選擇這些元件將不會移除它們。%n%n您仍然要繼續嗎? ComponentSize1=%1 KB ComponentSize2=%1 MB -ComponentsDiskSpaceMBLabel=ĽŘŤeŞşżďžÜŚÜ¤ÖťÝ­n [mb] MB ŞşşĎşĐŞĹśĄĄC +ComponentsDiskSpaceMBLabel=目前的選擇需要至少 [mb] MB 磁碟空間。 + ; *** "Select Additional Tasks" wizard page -WizardSelectTasks=żď¨ú¨äĽL¤u§@ -SelectTasksDesc=ÁŮśˇ°őŚć­ţ¨Ç¨äĽL¤u§@? -SelectTasksLabel2=˝Đżď¨úŚw¸Ëľ{ŚĄŚbŚw¸Ë [name] ŽÉĄAśˇĂBĽ~°őŚćŞş¨äĽL¤u§@ĄAľMŤáŤö¤@¤U [¤U¤@¨B]ĄC +WizardSelectTasks=選擇附加的工作 +SelectTasksDesc=選擇要執行的附加工作。 +SelectTasksLabel2=選擇安裝程式在安裝 [name] 時要執行的附加工作,然後按 [下一步]。 + ; *** "Select Start Menu Folder" wizard page -WizardSelectProgramGroup=żď¨ú [ś}Šl] Ľ\ŻŕŞí¸ęŽĆ§¨ -SelectStartMenuFolderDesc=Św¸Ëľ{ŚĄŔłąNľ{ŚĄąśŽ|¸mŠóŚółB? -SelectStartMenuFolderLabel3=Św¸Ëľ{ŚĄąNŚb¤UŚC [ś}Šl] Ľ\ŻŕŞí¸ęŽĆ§¨¤¤ŤŘĽßľ{ŚĄąśŽ|ĄC -SelectStartMenuFolderBrowseLabel=­Y­nÄ~ÄňĄA˝ĐŤö¤@¤U [¤U¤@¨B]ĄC­YązˇQżď¨ú¤ŁŚPŞş¸ęŽĆ§¨ĄA˝ĐŤö¤@¤U [ÂsÄý]ĄC -MustEnterGroupName=Ľ˛śˇżé¤J¸ęŽĆ§¨ŚWşŮĄC -GroupNameTooLong=¸ęŽĆ§¨ŚWşŮŠÎ¸ôŽ|šLŞřĄC -InvalidGroupName=Śš¸ęŽĆ§¨ŚWşŮľLŽÄĄC -BadGroupName=¸ęŽĆ§¨ŚWşŮ¤ŁąoĽ]§t¤UŚCĽô¤@Śr¤¸:%n%n%1 -NoProgramGroupCheck2=¤Ł­nŤŘĽß [ś}Šl] Ľ\ŻŕŞí¸ęŽĆ§¨(&D) +WizardSelectProgramGroup=選擇「開始」功能表的資料夾 +SelectStartMenuFolderDesc=選擇安裝程式建立程式的捷徑的位置。 +SelectStartMenuFolderLabel3=安裝程式將會把程式的捷徑建立在下面的「開始」功能表資料夾。 +SelectStartMenuFolderBrowseLabel=按 [下一步] 繼續,如果您想選擇另一個資料夾,請按 [瀏覽]。 +MustEnterGroupName=您必須輸入一個資料夾的名稱。 +GroupNameTooLong=資料夾名稱或路徑太長。 +InvalidGroupName=資料夾名稱不正確。 +BadGroupName=資料夾名稱不得包含下列字元:%n%n%1 +NoProgramGroupCheck2=不要在「開始」功能表中建立資料夾(&D) + ; *** "Ready to Install" wizard page -WizardReady=¤wĽiś}ŠlŚw¸Ë -ReadyLabel1=Św¸Ëľ{ŚĄ˛{Śb¤wĽiś}ŠląN [name] Św¸Ë¨ěązŞşšq¸Ł¤WĄC -ReadyLabel2a=­Y­nÄ~ÄňŚw¸ËĄA˝ĐŤö¤@¤U [Św¸Ë]; ­Y­nŔËž\ŠÎĹܧóĽôŚół]ŠwĄA˝ĐŤö¤@¤U [¤W¤@¨B]ĄC -ReadyLabel2b=­Y­nÄ~ÄňŚw¸ËĄA˝ĐŤö¤@¤U [Św¸Ë]ĄC -ReadyMemoUserInfo=¨ĎĽÎŞĚ¸ę°T: -ReadyMemoDir=ĽŘŞşŚaŚě¸m: -ReadyMemoType=Św¸ËĂţŤŹ: -ReadyMemoComponents=żď¨úŞş¤¸Ľó: -ReadyMemoGroup=[ś}Šl] Ľ\ŻŕŞí¸ęŽĆ§¨: -ReadyMemoTasks=¨äĽL¤u§@: +WizardReady=準備安裝 +ReadyLabel1=安裝程式將開始安裝 [name] 到您的電腦中。 +ReadyLabel2a=按下 [安裝] 繼續安裝,或按 [上一步] 重新檢視或設定各選項的內容。 +ReadyLabel2b=按下 [安裝] 繼續安裝。 +ReadyMemoUserInfo=使用者資訊 +ReadyMemoDir=目的資料夾: +ReadyMemoType=安裝型態: +ReadyMemoComponents=選擇的元件: +ReadyMemoGroup=「開始」功能表資料夾: +ReadyMemoTasks=附加工作: + ; *** "Preparing to Install" wizard page -WizardPreparing=ĽżŚbˇÇłĆŚw¸Ë -PreparingDesc=Św¸Ëľ{ŚĄĽżŚbˇÇłĆąN [name] Św¸Ë¨ěązŞşšq¸Ł¤WĄC -PreviousInstallNotCompleted=¤W¤@­Óľ{ŚĄŞşŚw¸Ë/˛ž°ŁŠ|Ľź§šŚ¨ĄCĽ˛śˇ­ŤˇsąŇ°Ęšq¸ŁĄA¤~Żŕ§šŚ¨¸ÓŚw¸ËĄC%n%n˝ĐŚb­ŤˇsąŇ°Ęšq¸Ł¤§ŤáĄA­Ťˇs°őŚćŚw¸Ëľ{ŚĄĄAĽH§šŚ¨ [name] ŞşŚw¸ËĄC -CannotContinue=Św¸Ëľ{ŚĄľLŞkÄ~ÄňĄC˝ĐŤö¤@¤U [¨úŽř] ĽHľ˛§ôĄC -ApplicationsFound=Św¸Ëľ{ŚĄĽ˛śˇ§óˇs¤UŚCŔłĽÎľ{ŚĄĽżŚb¨ĎĽÎŞş¤@¨ÇŔɎץCŤŘÄłąz¤šł\Św¸Ëľ{ŚĄŚŰ°ĘĂöłŹło¨ÇŔłĽÎľ{ŚĄĄC -ApplicationsFound2=Św¸Ëľ{ŚĄĽ˛śˇ§óˇs¤UŚCŔłĽÎľ{ŚĄĽżŚb¨ĎĽÎŞş¤@¨ÇŔɎץCŤŘÄłąz¤šł\Św¸Ëľ{ŚĄŚŰ°ĘĂöłŹło¨ÇŔłĽÎľ{ŚĄĄCˇíŚw¸Ë§šŚ¨¤§ŤáĄAŚw¸Ëľ{ŚĄąNˇ|šÁ¸Ő­ŤˇsąŇ°Ęło¨ÇŔłĽÎľ{ŚĄĄC -CloseApplications=ŚŰ°ĘĂöłŹŔłĽÎľ{ŚĄ(&A) -DontCloseApplications=¤Ł­nĂöłŹŔłĽÎľ{ŚĄ(&D) -ErrorCloseApplications=Św¸Ëľ{ŚĄľLŞkŚŰ°ĘĂöłŹŠŇŚłŔłĽÎľ{ŚĄĄCŤŘÄłązĂöłŹŠŇŚłĽżŚb¨ĎĽÎŚw¸Ëľ{ŚĄĽ˛śˇ§óˇs¤§ŔɎתşŔłĽÎľ{ŚĄĄAľMŤáŚAÄ~ÄňĄC +WizardPreparing=準備安裝程式 +PreparingDesc=安裝程式準備將 [name] 安裝到您的電腦上。 +PreviousInstallNotCompleted=先前的安裝/ 解除安裝尚未完成,您必須重新啟動電腦以完成該安裝。%n%n在重新啟動電腦之後,請再執行這個程式來安裝 [name]。 +CannotContinue=安裝程式無法繼續。請按 [取消] 離開。 +ApplicationsFound=下面的應用程式正在使用安裝程式所需要更新的文檔。建議您允許安裝程式自動關閉這些應用程式。 +ApplicationsFound2=下面的應用程式正在使用安裝程式所需要更新的文檔。建議您允許安裝程式自動關閉這些應用程式。當安裝過程結束後,本安裝程式將會嘗試重新開啟該應用程式。 +CloseApplications=關閉應用程式(&A) +DontCloseApplications=不要關閉應用程式 (&D) +ErrorCloseApplications=安裝程式無法自動關閉所有應用程式。建議您在繼續前先關閉所有應用程式使用的檔案。 + ; *** "Installing" wizard page -WizardInstalling=Św¸Ë¤¤ -InstallingLabel=˝Đľy­ÔĄAŚw¸Ëľ{ŚĄĽżŚbąN [name] Św¸Ë¨ěązŞşšq¸Ł¤WĄC +WizardInstalling=正在安裝 +InstallingLabel=請稍候,安裝程式正在將 [name] 安裝到您的電腦上 + ; *** "Setup Completed" wizard page -FinishedHeadingLabel=ĽżŚb§šŚ¨ [name] Św¸ËşëĆF -FinishedLabelNoIcons=Św¸Ëľ{ŚĄ¤w§šŚ¨ązšq¸Ł¤W [name] ŞşŚw¸ËĄC -FinishedLabel=Św¸Ëľ{ŚĄ¤w§šŚ¨ązšq¸Ł¤W [name] ŞşŚw¸ËĄCązĽiĽHżď¨úŠŇŚw¸ËŞşąśŽ|¨ÓąŇ°ĘŔłĽÎľ{ŚĄĄC -ClickFinish=˝ĐŤö¤@¤U [§šŚ¨]ĄAĽHľ˛§ôŚw¸ËĄC -FinishedRestartLabel=Św¸Ëľ{ŚĄĽ˛śˇ­ŤˇsąŇ°ĘązŞşšq¸ŁĄA¤~Żŕ§šŚ¨ [name] ŞşŚw¸ËĄC­nĽß§Y­ŤˇsąŇ°ĘśÜ? -FinishedRestartMessage=Św¸Ëľ{ŚĄĽ˛śˇ­ŤˇsąŇ°ĘązŞşšq¸ŁĄA¤~Żŕ§šŚ¨ [name] ŞşŚw¸ËĄC%n%n­nĽß§Y­ŤˇsąŇ°ĘśÜ? -ShowReadmeCheck=ŹOĄA§Ú­nŔËľřĹŞ§ÚŔÉŽ× -YesRadio=ŹOĄAĽß§Y­ŤˇsąŇ°Ęšq¸Ł(&Y) -NoRadio=§_ĄAľy­ÔŚA­ŤˇsąŇ°Ęšq¸Ł(&N) +FinishedHeadingLabel=安裝完成 +FinishedLabelNoIcons=安裝程式已經將 [name] 安裝在您的電腦上。 +FinishedLabel=安裝程式已經將 [name] 安裝在您的電腦中,您可以選擇程式的圖示來執行該應用程式。 +ClickFinish=按 [完成] 以結束安裝程式。 +FinishedRestartLabel=要完成 [name] 的安裝,安裝程式必須重新啟動您的電腦。您想要現在重新啟動電腦嗎? +FinishedRestartMessage=要完成 [name] 的安裝,安裝程式必須重新啟動您的電腦。%n%n您想要現在重新啟動電腦嗎? +ShowReadmeCheck=是,我要閱讀讀我檔案。 +YesRadio=是,立即重新啟動電腦(&Y) +NoRadio=否,我稍後重新啟動電腦(&N) ; used for example as 'Run MyProg.exe' -RunEntryExec=°őŚć %1 +RunEntryExec=執行 %1 ; used for example as 'View Readme.txt' -RunEntryShellExec=ŔËľř %1 -; *** "Setup Needs the Next Disk" stuff -ChangeDiskTitle=Św¸Ëľ{ŚĄťÝ­n¤U¤@ąişĎ¤ůĄC -SelectDiskLabel2=˝Đ´Ą¤JşĎ¤ů %1ĄAľMŤáŤö¤@¤U [˝TŠw]ĄC%n%n­YŚšşĎ¤ů¤WŞşŔɎ׼iĽHŚb¤UŚCĹăĽÜ¤§¸ęŽĆ§¨ĽHĽ~Şş¸ęŽĆ§¨¤¤§ä¨ěĄA˝Đżé¤JĽż˝TŞş¸ôŽ|ĄAŠÎŤö¤@¤U [ÂsÄý]ĄC -PathLabel=¸ôŽ|(&P): -FileNotInDir2=Śb "%2" ¤¤§ä¤Ł¨ěŔÉŽ× "%1"ĄC˝Đ´Ą¤JĽż˝TŞşşĎ¤ůĄAŠÎżď¨ú¨äĽL¸ęŽĆ§¨ĄC -SelectDirectoryLabel=˝ĐŤüŠw¤U¤@ąişĎ¤ůŞşŚě¸mĄC +RunEntryShellExec=檢視 %1 + +; *** "Setup Needs the Next Disk" +ChangeDiskTitle=安裝程式需要下一張磁片 +SelectDiskLabel2=請插入磁片 %1,然後按 [確定]。%n%n如果檔案不在以下所顯示的資料夾之中,請輸入正確的資料夾名稱或按 [瀏覽] 選取。 +PathLabel=路徑(&P): +FileNotInDir2=檔案“%1”無法在“%2”找到。請插入正確的磁片或選擇其它的資料夾。 +SelectDirectoryLabel=請指定下一張磁片的位置。 + ; *** Installation phase messages -SetupAborted=Św¸ËĽźŚwڍĄC%n%n˝Đ­×Ľż°ÝĂDĄAŚA­Ťˇs°őŚćŚw¸Ëľ{ŚĄĄC -EntryAbortRetryIgnore=­Y­nŚA¸Ő¤@ڏĄA˝ĐŤö¤@¤U [­Ť¸Ő]; ­Y­nÄ~ÄňĄA˝ĐŤö¤@¤U [Šż˛¤]; ­Y­n¨úŽřŚw¸ËĄA˝ĐŤö¤@¤U [¤¤¤î]ĄC +SetupAborted=安裝沒有完成。%n%n請更正問題後重新安裝一次。 +AbortRetryIgnoreSelectAction=選取動作 +AbortRetryIgnoreRetry=請再試一次 (&T) +AbortRetryIgnoreIgnore=略過錯誤並繼續 (&I) +AbortRetryIgnoreCancel=取消安裝 + ; *** Installation status messages -StatusClosingApplications=ĽżŚbĂöłŹŔłĽÎľ{ŚĄ... -StatusCreateDirs=ĽżŚbŤŘĽßĽŘżý... -StatusExtractFiles=ĽżŚb¸ŃŔŁÁYŔÉŽ×... -StatusCreateIcons=ĽżŚbŤŘĽßąśŽ|... -StatusCreateIniEntries=ĽżŚbŤŘĽß INI śľĽŘ... -StatusCreateRegistryEntries=ĽżŚbŤŘĽßľnżýśľĽŘ... -StatusRegisterFiles=ĽżŚbľnżýŔÉŽ×... -StatusSavingUninstall=ĽżŚbŔxŚs¸Ń°ŁŚw¸Ë¸ę°T... -StatusRunProgram=ĽżŚb§šŚ¨Św¸Ë... -StatusRestartingApplications=ĽżŚb­ŤˇsąŇ°ĘŔłĽÎľ{ŚĄ... -StatusRollback=ĽżŚb´_­ěĹܧó... +StatusClosingApplications=正在關閉應用程式... +StatusCreateDirs=正在建立資料夾... +StatusExtractFiles=正在解壓縮檔案... +StatusCreateIcons=正在建立程式集圖示... +StatusCreateIniEntries=寫入 INI 檔案的項目... +StatusCreateRegistryEntries=正在更新系統登錄... +StatusRegisterFiles=正在登錄檔案... +StatusSavingUninstall=儲存解除安裝資訊... +StatusRunProgram=正在完成安裝... +StatusRestartingApplications=正在重新開啟應用程式... +StatusRollback=正在復原變更... + ; *** Misc. errors -ErrorInternal2=¤şłĄżůť~: %1 -ErrorFunctionFailedNoCode=%1 Ľ˘ąŃ -ErrorFunctionFailed=%1 Ľ˘ąŃ; ĽN˝X %2 -ErrorFunctionFailedWithMessage=%1 Ľ˘ąŃ; ĽN˝X %2ĄC%n%3 -ErrorExecutingProgram=ľLŞk°őŚćŔÉŽ×:%n%1 +ErrorInternal2=內部錯誤: %1 +ErrorFunctionFailedNoCode=%1 失敗 +ErrorFunctionFailed=%1 失敗;代碼 %2 +ErrorFunctionFailedWithMessage=%1 失敗;代碼 %2.%n%3 +ErrorExecutingProgram=無法執行檔案:%n%1 + ; *** Registry errors -ErrorRegOpenKey=ś}ąŇľnżýž÷˝XŽÉľoĽÍżůť~:%n%1\%2 -ErrorRegCreateKey=ŤŘĽßľnżýž÷˝XŽÉľoĽÍżůť~:%n%1\%2 -ErrorRegWriteKey=źg¤Jľnżýž÷˝XŽÉľoĽÍżůť~:%n%1\%2 +ErrorRegOpenKey=無法開啟登錄鍵:%n%1\%2 +ErrorRegCreateKey=無法建立登錄項目:%n%1\%2 +ErrorRegWriteKey=無法變更登錄項目:%n%1\%2 + ; *** INI errors -ErrorIniEntry=ŚbŔÉŽ× "%1" ¤¤ŤŘĽß INI śľĽŘŽÉľoĽÍżůť~ĄC +ErrorIniEntry=在檔案“%1”建立 INI 項目錯誤。 + ; *** File copying errors -FileAbortRetryIgnore=­Y­nŚA¸Ő¤@ڏĄA˝ĐŤö¤@¤U [­Ť¸Ő]; ­Y­n˛¤šLŚšŔɎץA˝ĐŤö¤@¤U [Šż˛¤] (¤ŁŤŘÄł¨ĎĽÎ); ­Y­n¨úŽřŚw¸ËĄA˝ĐŤö¤@¤U [¤¤¤î]ĄC -FileAbortRetryIgnore2=­Y­nŚA¸Ő¤@ڏĄA˝ĐŤö¤@¤U [­Ť¸Ő]; ­Y­nÄ~ÄňĄA˝ĐŤö¤@¤U [Šż˛¤] (¤ŁŤŘÄł¨ĎĽÎ); ­Y­n¨úŽřŚw¸ËĄA˝ĐŤö¤@¤U [¤¤¤î]ĄC -SourceIsCorrupted=­ěŠlľ{ŚĄŔɤwˇlˇ´ -SourceDoesntExist=­ěŠlľ{ŚĄŔÉ "%1" ¤ŁŚsŚb -ExistingFileReadOnly=˛{ŚłŔɎפwźĐ°Oʰ°ßĹŞĄC%n%n­Y­n˛ž°Ł°ßĹŞÄÝŠĘĄAľMŤáŚA¸Ő¤@ڏĄA˝ĐŤö¤@¤U [­Ť¸Ő]; ­Y­n˛¤šLŚšŔɎץA˝ĐŤö¤@¤U [Šż˛¤]; ­Y­n¨úŽřŚw¸ËĄA˝ĐŤö¤@¤U [¤¤¤î]ĄC -ErrorReadingExistingDest=šÁ¸ŐĹŞ¨ú˛{ŚłŔɎ׎ɾoĽÍżůť~: -FileExists=¤wŚłŚšŔɎץC%n%n­nĽŃŚw¸Ëľ{ŚĄĽ[ĽHÂĐźgśÜ? -ExistingFileNewer=˛{ŚłŔɎ׸űŚw¸Ëľ{ŚĄšÁ¸ŐŚw¸ËŞşŔɎסsĄCŤŘÄłązŤOŻd˛{ŚłŔɎץC%n%n­nŤOŻd˛{ŚłŞşŔɎלÜ? -ErrorChangingAttr=šÁ¸ŐĹܧó˛{ŚłŔɎתşÄÝŠĘŽÉľoĽÍżůť~: -ErrorCreatingTemp=šÁ¸ŐŚbĽŘŞşŚaĽŘżý¤¤ŤŘĽßŔɎ׎ɾoĽÍżůť~: -ErrorReadingSource=šÁ¸ŐĹŞ¨ú­ěŠlľ{ŚĄŔÉŽÉľoĽÍżůť~: -ErrorCopying=šÁ¸Ő˝ĆťsŔɎ׎ɾoĽÍżůť~: -ErrorReplacingExistingFile=šÁ¸Ő¨úĽN˛{ŚłŔɎ׎ɾoĽÍżůť~: -ErrorRestartReplace=RestartReplace Ľ˘ąŃ: -ErrorRenamingTemp=šÁ¸Ő­ŤˇsŠRŚWĽŘŞşŚaĽŘżý¤¤ŞşŔɎ׎ɾoĽÍżůť~: -ErrorRegisterServer=ľLŞkľnżý DLL/OCX: %1 -ErrorRegSvr32Failed=RegSvr32 Ľ˘ąŃĄAľ˛§ôĽN˝Xʰ %1 -ErrorRegisterTypeLib=ľLŞkľnżýĂţŤŹľ{ŚĄŽw: %1 +FileAbortRetryIgnoreSkipNotRecommended=略過這個檔案 (不建議) (&S) +FileAbortRetryIgnoreIgnoreNotRecommended=略過錯誤並繼續 (不建議) (&I) +SourceDoesntExist=來源檔案“%1”不存在。 +SourceIsCorrupted=來源檔案已經損毀。 +ExistingFileReadOnly2=無法取代現有檔案,因為檔案已標示為唯讀。 +ExistingFileReadOnlyRetry=移除唯讀屬性並重試 (&R) +ExistingFileReadOnlyKeepExisting=保留現有檔案 (&K) +ErrorReadingExistingDest=讀取一個已存在的檔案時發生錯誤: +FileExists=檔案已經存在。%n%n 要讓安裝程式加以覆寫嗎? +ExistingFileNewer=存在的檔案版本比較新,建議您保留目前已存在的檔案。%n%n您要保留目前已存在的檔案嗎? +ErrorChangingAttr=在變更檔案屬性時發生錯誤: +ErrorCreatingTemp=在目的資料夾中建立檔案時發生錯誤: +ErrorReadingSource=讀取原始檔案時發生錯誤: +ErrorCopying=復制檔案時發生錯誤: +ErrorReplacingExistingFile=取代檔案時發生錯誤: +ErrorRestartReplace=重新啟動電腦後取代檔案失敗: +ErrorRenamingTemp=在目的資料夾變更檔案名稱時發生錯誤: +ErrorRegisterServer=無法注冊 DLL/OCX 檔案: %1。 +ErrorRegSvr32Failed=RegSvr32 失敗;退出代碼 %1 +ErrorRegisterTypeLib=無法注冊類型庫: %1。 + +; *** Uninstall display name markings +; used for example as 'My Program (32-bit)' +UninstallDisplayNameMark=%1 (%2) +; used for example as 'My Program (32-bit, All users)' +UninstallDisplayNameMarks=%1 (%2, %3) +UninstallDisplayNameMark32Bit=32-bit +UninstallDisplayNameMark64Bit=64-bit +UninstallDisplayNameMarkAllUsers=所有使用者 +UninstallDisplayNameMarkCurrentUser=目前使用者 + ; *** Post-installation errors -ErrorOpeningReadme=šÁ¸Őś}ąŇĹŞ§ÚŔɎ׎ɾoĽÍżůť~ĄC -ErrorRestartingComputer=Św¸Ëľ{ŚĄľLŞk­ŤˇsąŇ°Ęšq¸ŁĄC˝Đ¤â°Ę°őŚćŚš§@ˇ~ĄC +ErrorOpeningReadme=開啟讀我檔案時發生錯誤。 +ErrorRestartingComputer=安裝程式無法重新啟動電腦,請以手動方式自行重新啟動電腦。 + ; *** Uninstaller messages -UninstallNotFound=¨SŚłŔÉŽ× "%1"ĄCľLŞk¸Ń°ŁŚw¸ËĄC -UninstallOpenError=ľLŞkś}ąŇŔÉŽ× "%1"ĄCľLŞk¸Ń°ŁŚw¸Ë -UninstallUnsupportedVer=ŚšŞŠ¸Ń°ŁŚw¸Ëľ{ŚĄľLŞkżëĂŃ¸Ń°ŁŚw¸Ë°OżýŔÉ "%1" ŞşŽćŚĄĄCľLŞk¸Ń°ŁŚw¸Ë -UninstallUnknownEntry=Śb¸Ń°ŁŚw¸Ë°Ożý¤¤§ä¨ě¤ŁŠúŞşśľĽŘ (%1) -ConfirmUninstall=˝TŠw­n§šĽţ˛ž°Ł %1 ¤Î¨äŠŇŚł¤¸ĽóśÜ? -UninstallOnlyOnWin64=ĽuĽiŚb 64 Śě¤¸ Windows ¤W¸Ń°ŁŚw¸ËŚšŚw¸ËĄC -OnlyAdminCanUninstall=ĽuŚł¨ăłĆ¨t˛ÎşŢ˛zĹv­­Şş¨ĎĽÎŞĚĄA¤~Żŕ¸Ń°ŁŚw¸ËŚšŚw¸ËĄC -UninstallStatusLabel=ĽżŚbąqązŞşšq¸Ł˛ž°Ł %1ĄA˝Đľy­ÔĄC -UninstalledAll=¤wڍĽ\ąqązŞşšq¸Ł˛ž°Ł %1ĄC -UninstalledMost=¸Ń°ŁŚw¸Ë %1 ¤w§šŚ¨ĄC%n%nŚłłĄ¤ŔśľĽŘľLŞk˛ž°ŁĄCązĽiĽH¤â°ĘĽ[ĽH˛ž°ŁĄC -UninstalledAndNeedsRestart=­Y­n§šŚ¨ %1 Şş¸Ń°ŁŚw¸ËĄAĽ˛śˇ­ŤˇsąŇ°ĘązŞşšq¸ŁĄC%n%n­nĽß§Y­ŤˇsąŇ°ĘśÜ? -UninstallDataCorrupted="%1" ŔɎפwˇlˇ´ĄCľLŞk¸Ń°ŁŚw¸Ë +UninstallNotFound=檔案“%1”不存在,無法移除程式。 +UninstallOpenError=無法開啟檔案“%1”,無法移除程式。 +UninstallUnsupportedVer=這個版本的解除安裝程式無法辨識記錄檔 “%1” 之格式,無法解除安裝。 +UninstallUnknownEntry=解除安裝記錄檔中發現未知的記錄 (%1)。 +ConfirmUninstall=您確定要完全移除 %1 及其相關的檔案嗎? +UninstallOnlyOnWin64=這個程式只能在 64 位元的 Windows 上解除安裝。 +OnlyAdminCanUninstall=這個程式要具備系統管理員權限的使用者方可解除安裝。 +UninstallStatusLabel=正在從您的電腦移除 %1 中,請稍候... +UninstalledAll=%1 已經成功從您的電腦中移除。 +UninstalledMost=%1 解除安裝完成。%n%n某些檔案及元件無法移除,您可以自行刪除這些檔案。 +UninstalledAndNeedsRestart=要完成 %1 的解除安裝程序,您必須重新啟動電腦。%n%n您想要現在重新啟動電腦嗎? +UninstallDataCorrupted=檔案“%1”已經損毀,無法解除安裝。 + ; *** Uninstallation phase messages -ConfirmDeleteSharedFileTitle=­n˛ž°ŁŚ@ĽÎŔɎלÜ? -ConfirmDeleteSharedFile2=¨t˛ÎŤüĽX¤wľLĽôŚóľ{ŚĄŚb¨ĎĽÎ¤UŚCŚ@ĽÎŔɎץCąz­n¸Ń°ŁŚw¸ËĄAĽH˛ž°ŁŚšŚ@ĽÎŔɎלÜ?%n%nŚpŚłĽôŚóľ{ŚĄ¤´Śb¨ĎĽÎŚšŔɎ׌ӹN¸ÓŔɎײž°ŁĄAło¨Çľ{ŚĄĽiŻŕľLŞkĽżą`šB§@ĄC­Y¤Ł˝TŠwĄA˝ĐżďžÜ [§_]ĄCąNŔɎ׍OŻdŚb¨t˛Î¤W¨Ă¤Łˇ|łyڍĽôŚó¤Ł¨}źvĹTĄC -SharedFileNameLabel=ŔɎ׌WşŮ: -SharedFileLocationLabel=Śě¸m: -WizardUninstalling=¸Ń°ŁŚw¸ËŞŹşA -StatusUninstalling=ĽżŚb¸Ń°ŁŚw¸Ë %1... +ConfirmDeleteSharedFileTitle=移除共用檔案 +ConfirmDeleteSharedFile2=系統顯示下列共用檔案已不再被任何程式所使用,您要移除這些檔案嗎?%n%n%1%n%n倘若您移除了以上檔案但仍有程式需要使用它們,將造成這些程式無法正常執行,因此您若無法確定請選擇 [同]。保留這些檔案在您的系統中不會造成任何損害。 +SharedFileNameLabel=檔案名稱: +SharedFileLocationLabel=位置: +WizardUninstalling=解除安裝狀態 +StatusUninstalling=正在解除安裝 %1... + ; *** Shutdown block reasons -ShutdownBlockReasonInstallingApp=ĽżŚbŚw¸Ë %1ĄC -ShutdownBlockReasonUninstallingApp=ĽżŚb¸Ń°ŁŚw¸Ë %1ĄC +ShutdownBlockReasonInstallingApp=正在安裝 %1. +ShutdownBlockReasonUninstallingApp=正在解除安裝 %1. + ; The custom messages below aren't used by Setup itself, but if you make ; use of them in your scripts, you'll want to translate them. + [CustomMessages] -NameAndVersion=%1 ŞŠ %2 -AdditionalIcons=¨äĽLąśŽ|: -CreateDesktopIcon=ŤŘĽßŽŕ­ąąśŽ|(&D) -CreateQuickLaunchIcon=ŤŘĽß§ÖłtąŇ°ĘąśŽ|(&Q) -ProgramOnTheWeb=Web ¤WŞş %1 -UninstallProgram=¸Ń°ŁŚw¸Ë %1 -LaunchProgram=ąŇ°Ę %1 -AssocFileExtension=ĂöÁp %1 ťP %2 °ĆŔÉŚW(&A) -AssocingFileExtension=ĽżŚbŤŘĽß %1 ťP %2 °ĆŔÉŚWŞşĂöÁpĄK -AutoStartProgramGroupDescription=ąŇ°Ę: -AutoStartProgram=ŚŰ°ĘąŇ°Ę %1 -AddonHostProgramNotFound=Śbżď¨úŞş¸ęŽĆ§¨¤¤§ä¤Ł¨ě %1ĄC%n%n¤´­nÄ~ÄňśÜ? \ No newline at end of file + +NameAndVersion=%1 版本 %2 +AdditionalIcons=附加圖示: +CreateDesktopIcon=建立桌面圖示(&D) +CreateQuickLaunchIcon=建立快速啟動圖示(&Q) +ProgramOnTheWeb=%1 的網站 +UninstallProgram=解除安裝 %1 +LaunchProgram=啟動 %1 +AssocFileExtension=將 %1 與檔案副檔名 %2 產生關聯(&A) +AssocingFileExtension=正在將 %1 與檔案副檔名 %2 產生關聯... +AutoStartProgramGroupDescription=開啟: +AutoStartProgram=自動開啟 %1 +AddonHostProgramNotFound=%1 無法在您所選的資料夾中找到。%n%n您是否還要繼續? diff --git a/build/win32/i18n/messages.en.isl b/build/win32/i18n/messages.en.isl index 12189c080d..986eba00d3 100644 --- a/build/win32/i18n/messages.en.isl +++ b/build/win32/i18n/messages.en.isl @@ -1,4 +1,11 @@ +[Messages] +FinishedLabel=Setup has finished installing [name] on your computer. The application may be launched by selecting the installed shortcuts. +ConfirmUninstall=Are you sure you want to completely remove %1 and all of its components? + [CustomMessages] +AdditionalIcons=Additional icons: +CreateDesktopIcon=Create a &desktop icon +CreateQuickLaunchIcon=Create a &Quick Launch icon AddContextMenuFiles=Add "Open with %1" action to Windows Explorer file context menu AddContextMenuFolders=Add "Open with %1" action to Windows Explorer directory context menu AssociateWithFiles=Register %1 as an editor for supported file types diff --git a/build/yarn.lock b/build/yarn.lock index 61f64b4f43..a292262675 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -1817,10 +1817,10 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" -iconv-lite-umd@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.5.tgz#6a1f621a3b4d125f72feff813a9839e1ebd6c722" - integrity sha512-WDegH4al+e3n3jTOStRvm+jzDA3JMUQGgzdAsMxAgcgB0Oi72HjfdsoX08ieKsy3rKexXVjWZr41aOIUaCZnMg== +iconv-lite-umd@0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.8.tgz#5ad310ec126b260621471a2d586f7f37b9958ec0" + integrity sha512-zvXJ5gSwMC9JD3wDzH8CoZGc1pbiJn12Tqjk8BXYCnYz3hYL5GRjHW8LEykjXhV9WgNGI4rgpgHcbIiBfrRq6A== iconv-lite@^0.4.4: version "0.4.24" @@ -3539,10 +3539,10 @@ typescript@^3.0.1: resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== -typescript@^4.0.0-dev.20200629: - version "4.0.0-dev.20200629" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.0-dev.20200629.tgz#4631667ebffe3a340beee885a4bebe3a73b6f18e" - integrity sha512-c4DUu7KvTcx4x7V8sBWexYNkCfioiH1huOJL6WFAA8Oot0Gr/+PlKKDBS9fYjsadEv1JI1qboJKobwLQn0kQXw== +typescript@^4.0.0-dev.20200708: + version "4.0.0-dev.20200708" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.0-dev.20200708.tgz#9cf526945590456f34b158b180a6f8a2e0b57306" + integrity sha512-A1brZPJRwkm2pxOSTIOVqLvrhF1swfLvDAgN+jRP/yUWNn+0OqbfunuY/jvRbtkEP4/AWZ+M2P625Y+JDN/j2A== typical@^4.0.0: version "4.0.0" diff --git a/cgmanifest.json b/cgmanifest.json index 25178f2f20..1fb78691e7 100644 --- a/cgmanifest.json +++ b/cgmanifest.json @@ -6,7 +6,7 @@ "git": { "name": "chromium", "repositoryUrl": "https://chromium.googlesource.com/chromium/src", - "commitHash": "e4745133a1d3745f066e068b8033c6a269b59caf" + "commitHash": "052d3b44972e6d94ef40054d46c150b7cdd7a5d8" } }, "licenseDetail": [ @@ -40,7 +40,7 @@ "SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." ], "isOnlyProductionDependency": true, - "version": "78.0.3904.130" + "version": "80.0.3987.165" }, { "component": { @@ -48,11 +48,11 @@ "git": { "name": "nodejs", "repositoryUrl": "https://github.com/nodejs/node", - "commitHash": "787378879acfb212ed4ff824bf9f767a24a5cb43a" + "commitHash": "42cce5a9d0fd905bf4ad7a2528c36572dfb8b5ad" } }, "isOnlyProductionDependency": true, - "version": "12.8.1" + "version": "12.13.0" }, { "component": { @@ -60,12 +60,12 @@ "git": { "name": "electron", "repositoryUrl": "https://github.com/electron/electron", - "commitHash": "5f93e889020d279d5a9cd1ecab080ab467312447" + "commitHash": "87fd06bc96bce8f46ca05b8315657fd230bcac85" } }, "isOnlyProductionDependency": true, "license": "MIT", - "version": "7.3.2" + "version": "8.3.3" }, { "component": { @@ -533,7 +533,7 @@ "git": { "name": "ripgrep", "repositoryUrl": "https://github.com/BurntSushi/ripgrep", - "commitHash": "8a7db1a918e969b85cd933d8ed9fa5285b281ba4" + "commitHash": "973de50c9ef451da2cfcdfa86f2b2711d8d6ff48" } }, "isOnlyProductionDependency": true, diff --git a/extensions/extension-editing/extension-browser.webpack.config.js b/extensions/extension-editing/extension-browser.webpack.config.js new file mode 100644 index 0000000000..5870e94564 --- /dev/null +++ b/extensions/extension-editing/extension-browser.webpack.config.js @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +//@ts-check + +'use strict'; + +const withBrowserDefaults = require('../shared.webpack.config').browser; + +module.exports = withBrowserDefaults({ + context: __dirname, + entry: { + extension: './src/extensionEditingBrowserMain.ts' + }, + output: { + filename: 'extensionEditingBrowserMain.js' + } +}); + diff --git a/extensions/extension-editing/extension.webpack.config.js b/extensions/extension-editing/extension.webpack.config.js index 887933358e..9fcce7e999 100644 --- a/extensions/extension-editing/extension.webpack.config.js +++ b/extensions/extension-editing/extension.webpack.config.js @@ -12,7 +12,7 @@ const withDefaults = require('../shared.webpack.config'); module.exports = withDefaults({ context: __dirname, entry: { - extension: './src/extension.ts', + extension: './src/extensionEditingMain.ts', }, externals: { '../../../product.json': 'commonjs ../../../product.json', diff --git a/extensions/extension-editing/package.json b/extensions/extension-editing/package.json index 75d77925b0..bdd02d870a 100644 --- a/extensions/extension-editing/package.json +++ b/extensions/extension-editing/package.json @@ -13,7 +13,8 @@ "onLanguage:markdown", "onLanguage:typescript" ], - "main": "./out/extension", + "main": "./out/extensionEditingMain", + "browser": "./dist/browser/extensionEditingBrowserMain", "scripts": { "compile": "gulp compile-extension:extension-editing", "watch": "gulp watch-extension:extension-editing" diff --git a/extensions/extension-editing/src/extensionEditingBrowserMain.ts b/extensions/extension-editing/src/extensionEditingBrowserMain.ts new file mode 100644 index 0000000000..fea2db000f --- /dev/null +++ b/extensions/extension-editing/src/extensionEditingBrowserMain.ts @@ -0,0 +1,21 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { PackageDocument } from './packageDocumentHelper'; + +export function activate(context: vscode.ExtensionContext) { + //package.json suggestions + context.subscriptions.push(registerPackageDocumentCompletions()); + +} + +function registerPackageDocumentCompletions(): vscode.Disposable { + return vscode.languages.registerCompletionItemProvider({ language: 'json', pattern: '**/package.json' }, { + provideCompletionItems(document, position, token) { + return new PackageDocument(document).provideCompletionItems(position, token); + } + }); +} diff --git a/extensions/extension-editing/src/extension.ts b/extensions/extension-editing/src/extensionEditingMain.ts similarity index 100% rename from extensions/extension-editing/src/extension.ts rename to extensions/extension-editing/src/extensionEditingMain.ts diff --git a/extensions/git/package.json b/extensions/git/package.json index e5e78fd3d8..e96ef36aba 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -1789,8 +1789,8 @@ "diff" ], "extensions": [ - ".patch", ".diff", + ".patch", ".rej" ], "configuration": "./languages/diff.language-configuration.json" @@ -1878,8 +1878,8 @@ "dependencies": { "byline": "^5.0.0", "file-type": "^7.2.0", - "iconv-lite-umd": "0.6.5", - "jschardet": "2.1.1", + "iconv-lite-umd": "0.6.8", + "jschardet": "2.2.1", "vscode-extension-telemetry": "0.1.1", "vscode-nls": "^4.0.0", "vscode-uri": "^2.0.0", diff --git a/extensions/git/src/api/api1.ts b/extensions/git/src/api/api1.ts index f7326a39f2..5e3a8b69ce 100644 --- a/extensions/git/src/api/api1.ts +++ b/extensions/git/src/api/api1.ts @@ -5,10 +5,12 @@ import { Model } from '../model'; import { Repository as BaseRepository, Resource } from '../repository'; -import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, GitExtension, RefType, RemoteSourceProvider, CredentialsProvider, BranchQuery } from './git'; +import { InputBox, Git, API, Repository, Remote, RepositoryState, Branch, Ref, Submodule, Commit, Change, RepositoryUIState, Status, LogOptions, APIState, CommitOptions, RefType, RemoteSourceProvider, CredentialsProvider, BranchQuery, PushErrorHandler } from './git'; import { Event, SourceControlInputBox, Uri, SourceControl, Disposable, commands } from 'vscode'; import { mapEvent } from '../util'; import { toGitUri } from '../uri'; +import { pickRemoteSource, PickRemoteSourceOptions } from '../remoteSource'; +import { GitExtensionImpl } from './extension'; class ApiInputBox implements InputBox { set value(value: string) { this._inputBox.value = value; } @@ -271,6 +273,10 @@ export class ApiImpl implements API { return this._model.registerCredentialsProvider(provider); } + registerPushErrorHandler(handler: PushErrorHandler): Disposable { + return this._model.registerPushErrorHandler(handler); + } + constructor(private _model: Model) { } } @@ -308,41 +314,51 @@ function getStatus(status: Status): string { return 'UNKNOWN'; } -export function registerAPICommands(extension: GitExtension): Disposable { - return Disposable.from( - commands.registerCommand('git.api.getRepositories', () => { - const api = extension.getAPI(1); - return api.repositories.map(r => r.rootUri.toString()); - }), +export function registerAPICommands(extension: GitExtensionImpl): Disposable { + const disposables: Disposable[] = []; - commands.registerCommand('git.api.getRepositoryState', (uri: string) => { - const api = extension.getAPI(1); - const repository = api.getRepository(Uri.parse(uri)); + disposables.push(commands.registerCommand('git.api.getRepositories', () => { + const api = extension.getAPI(1); + return api.repositories.map(r => r.rootUri.toString()); + })); - if (!repository) { - return null; - } + disposables.push(commands.registerCommand('git.api.getRepositoryState', (uri: string) => { + const api = extension.getAPI(1); + const repository = api.getRepository(Uri.parse(uri)); - const state = repository.state; + if (!repository) { + return null; + } - const ref = (ref: Ref | undefined) => (ref && { ...ref, type: getRefType(ref.type) }); - const change = (change: Change) => ({ - uri: change.uri.toString(), - originalUri: change.originalUri.toString(), - renameUri: change.renameUri?.toString(), - status: getStatus(change.status) - }); + const state = repository.state; - return { - HEAD: ref(state.HEAD), - refs: state.refs.map(ref), - remotes: state.remotes, - submodules: state.submodules, - rebaseCommit: state.rebaseCommit, - mergeChanges: state.mergeChanges.map(change), - indexChanges: state.indexChanges.map(change), - workingTreeChanges: state.workingTreeChanges.map(change) - }; - }) - ); + const ref = (ref: Ref | undefined) => (ref && { ...ref, type: getRefType(ref.type) }); + const change = (change: Change) => ({ + uri: change.uri.toString(), + originalUri: change.originalUri.toString(), + renameUri: change.renameUri?.toString(), + status: getStatus(change.status) + }); + + return { + HEAD: ref(state.HEAD), + refs: state.refs.map(ref), + remotes: state.remotes, + submodules: state.submodules, + rebaseCommit: state.rebaseCommit, + mergeChanges: state.mergeChanges.map(change), + indexChanges: state.indexChanges.map(change), + workingTreeChanges: state.workingTreeChanges.map(change) + }; + })); + + disposables.push(commands.registerCommand('git.api.getRemoteSources', (opts?: PickRemoteSourceOptions) => { + if (!extension.model) { + return; + } + + return pickRemoteSource(extension.model, opts); + })); + + return Disposable.from(...disposables); } diff --git a/extensions/git/src/api/extension.ts b/extensions/git/src/api/extension.ts index b74925145e..73c8638caa 100644 --- a/extensions/git/src/api/extension.ts +++ b/extensions/git/src/api/extension.ts @@ -7,7 +7,6 @@ import { Model } from '../model'; import { GitExtension, Repository, API } from './git'; import { ApiRepository, ApiImpl } from './api1'; import { Event, EventEmitter } from 'vscode'; -import { latchEvent } from '../util'; export function deprecated(_target: any, key: string, descriptor: any): void { if (typeof descriptor.value !== 'function') { @@ -26,17 +25,27 @@ export class GitExtensionImpl implements GitExtension { enabled: boolean = false; private _onDidChangeEnablement = new EventEmitter(); - readonly onDidChangeEnablement: Event = latchEvent(this._onDidChangeEnablement.event); + readonly onDidChangeEnablement: Event = this._onDidChangeEnablement.event; private _model: Model | undefined = undefined; set model(model: Model | undefined) { this._model = model; - this.enabled = !!model; + const enabled = !!model; + + if (this.enabled === enabled) { + return; + } + + this.enabled = enabled; this._onDidChangeEnablement.fire(this.enabled); } + get model(): Model | undefined { + return this._model; + } + constructor(model?: Model) { if (model) { this.enabled = true; @@ -73,4 +82,4 @@ export class GitExtensionImpl implements GitExtension { return new ApiImpl(this._model); } -} \ No newline at end of file +} diff --git a/extensions/git/src/api/git.d.ts b/extensions/git/src/api/git.d.ts index 6f7c8eb674..9593d8bc70 100644 --- a/extensions/git/src/api/git.d.ts +++ b/extensions/git/src/api/git.d.ts @@ -223,6 +223,10 @@ export interface CredentialsProvider { getCredentials(host: Uri): ProviderResult; } +export interface PushErrorHandler { + handlePushError(repository: Repository, remote: Remote, refspec: string, error: Error & { gitErrorCode: GitErrorCodes }): Promise; +} + export type APIState = 'uninitialized' | 'initialized'; export interface API { @@ -239,6 +243,7 @@ export interface API { registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable; registerCredentialsProvider(provider: CredentialsProvider): Disposable; + registerPushErrorHandler(handler: PushErrorHandler): Disposable; } export interface GitExtension { @@ -276,6 +281,7 @@ export const enum GitErrorCodes { CantOpenResource = 'CantOpenResource', GitNotFound = 'GitNotFound', CantCreatePipe = 'CantCreatePipe', + PermissionDenied = 'PermissionDenied', CantAccessRemote = 'CantAccessRemote', RepositoryNotFound = 'RepositoryNotFound', RepositoryIsLocked = 'RepositoryIsLocked', diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts index 4450cc36df..ce80a053fc 100644 --- a/extensions/git/src/commands.ts +++ b/extensions/git/src/commands.ts @@ -6,10 +6,10 @@ import { lstat, Stats } from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env, QuickPick } from 'vscode'; +import { commands, Disposable, LineChange, MessageOptions, OutputChannel, Position, ProgressLocation, QuickPickItem, Range, SourceControlResourceState, TextDocumentShowOptions, TextEditor, Uri, ViewColumn, window, workspace, WorkspaceEdit, WorkspaceFolder, TimelineItem, env } from 'vscode'; import TelemetryReporter from 'vscode-extension-telemetry'; import * as nls from 'vscode-nls'; -import { Branch, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourceProvider, RemoteSource } from './api/git'; +import { Branch, GitErrorCodes, Ref, RefType, Status, CommitOptions, RemoteSourceProvider } from './api/git'; import { ForcePushMode, Git, Stash } from './git'; import { Model } from './model'; import { Repository, Resource, ResourceGroupType } from './repository'; @@ -18,8 +18,8 @@ import { fromGitUri, toGitUri, isGitUri } from './uri'; import { grep, isDescendant, pathEquals } from './util'; import { Log, LogLevel } from './log'; import { GitTimelineItem } from './timelineProvider'; -import { throttle, debounce } from './decorators'; import { ApiRepository } from './api/api1'; +import { pickRemoteSource } from './remoteSource'; const localize = nls.loadMessageBundle(); @@ -240,72 +240,6 @@ interface PushOptions { silent?: boolean; } -async function getQuickPickResult(quickpick: QuickPick): Promise { - const result = await new Promise(c => { - quickpick.onDidAccept(() => c(quickpick.selectedItems[0])); - quickpick.onDidHide(() => c(undefined)); - quickpick.show(); - }); - - quickpick.hide(); - return result; -} - -class RemoteSourceProviderQuickPick { - - private quickpick: QuickPick; - - constructor(private provider: RemoteSourceProvider) { - this.quickpick = window.createQuickPick(); - this.quickpick.ignoreFocusOut = true; - - if (provider.supportsQuery) { - this.quickpick.placeholder = localize('type to search', "Repository name (type to search)"); - this.quickpick.onDidChangeValue(this.onDidChangeValue, this); - } else { - this.quickpick.placeholder = localize('type to filter', "Repository name"); - } - } - - @debounce(300) - onDidChangeValue(): void { - this.query(); - } - - @throttle - async query(): Promise { - this.quickpick.busy = true; - - try { - const remoteSources = await this.provider.getRemoteSources(this.quickpick.value) || []; - - if (remoteSources.length === 0) { - this.quickpick.items = [{ - label: localize('none found', "No remote repositories found."), - alwaysShow: true - }]; - } else { - this.quickpick.items = remoteSources.map(remoteSource => ({ - label: remoteSource.name, - description: remoteSource.description || (typeof remoteSource.url === 'string' ? remoteSource.url : remoteSource.url[0]), - remoteSource - })); - } - } catch (err) { - this.quickpick.items = [{ label: localize('error', "$(error) Error: {0}", err.message), alwaysShow: true }]; - console.error(err); - } finally { - this.quickpick.busy = false; - } - } - - async pick(): Promise { - this.query(); - const result = await getQuickPickResult(this.quickpick); - return result?.remoteSource; - } -} - export class CommandCenter { private disposables: Disposable[]; @@ -527,51 +461,10 @@ export class CommandCenter { @command('git.clone') async clone(url?: string, parentPath?: string): Promise { if (!url) { - const quickpick = window.createQuickPick<(QuickPickItem & { provider?: RemoteSourceProvider, url?: string })>(); - quickpick.ignoreFocusOut = true; - - const providers = this.model.getRemoteProviders() - .map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + localize('clonefrom', "Clone from {0}", provider.name), alwaysShow: true, provider })); - - quickpick.placeholder = providers.length === 0 - ? localize('provide url', "Provide repository URL") - : localize('provide url or pick', "Provide repository URL or pick a repository source."); - - const updatePicks = (value?: string) => { - if (value) { - quickpick.items = [{ - label: localize('repourl', "Clone from URL"), - description: value, - alwaysShow: true, - url: value - }, - ...providers]; - } else { - quickpick.items = providers; - } - }; - - quickpick.onDidChangeValue(updatePicks); - updatePicks(); - - const result = await getQuickPickResult(quickpick); - - if (result) { - if (result.url) { - url = result.url; - } else if (result.provider) { - const quickpick = new RemoteSourceProviderQuickPick(result.provider); - const remote = await quickpick.pick(); - - if (remote) { - if (typeof remote.url === 'string') { - url = remote.url; - } else if (remote.url.length > 0) { - url = await window.showQuickPick(remote.url, { ignoreFocusOut: true, placeHolder: localize('pick url', "Choose a URL to clone from.") }); - } - } - } - } + url = await pickRemoteSource(this.model, { + providerLabel: provider => localize('clonefrom', "Clone from {0}", provider.name), + urlLabel: localize('repourl', "Clone from URL") + }); } if (!url) { @@ -845,7 +738,7 @@ export class CommandCenter { try { document = await workspace.openTextDocument(uri); } catch (error) { - await commands.executeCommand('vscode.open', uri, opts); + await commands.executeCommand('vscode.open', uri, opts); continue; } @@ -858,7 +751,7 @@ export class CommandCenter { const editor = await window.showTextDocument(document, opts); editor.revealRange(previousVisibleRanges[0]); } else { - await window.showTextDocument(document, opts); + await commands.executeCommand('vscode.open', uri, opts); } } } @@ -2146,52 +2039,10 @@ export class CommandCenter { @command('git.addRemote', { repository: true }) async addRemote(repository: Repository): Promise { - const quickpick = window.createQuickPick<(QuickPickItem & { provider?: RemoteSourceProvider, url?: string })>(); - quickpick.ignoreFocusOut = true; - - const providers = this.model.getRemoteProviders() - .map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + localize('addfrom', "Add remote from {0}", provider.name), alwaysShow: true, provider })); - - quickpick.placeholder = providers.length === 0 - ? localize('provide url', "Provide repository URL") - : localize('provide url or pick', "Provide repository URL or pick a repository source."); - - const updatePicks = (value?: string) => { - if (value) { - quickpick.items = [{ - label: localize('addFrom', "Add remote from URL"), - description: value, - alwaysShow: true, - url: value - }, - ...providers]; - } else { - quickpick.items = providers; - } - }; - - quickpick.onDidChangeValue(updatePicks); - updatePicks(); - - const result = await getQuickPickResult(quickpick); - let url: string | undefined; - - if (result) { - if (result.url) { - url = result.url; - } else if (result.provider) { - const quickpick = new RemoteSourceProviderQuickPick(result.provider); - const remote = await quickpick.pick(); - - if (remote) { - if (typeof remote.url === 'string') { - url = remote.url; - } else if (remote.url.length > 0) { - url = await window.showQuickPick(remote.url, { ignoreFocusOut: true, placeHolder: localize('pick url', "Choose a URL to clone from.") }); - } - } - } - } + const url = await pickRemoteSource(this.model, { + providerLabel: provider => localize('addfrom', "Add remote from {0}", provider.name), + urlLabel: localize('addFrom', "Add remote from URL") + }); if (!url) { return; @@ -2533,8 +2384,7 @@ export class CommandCenter { @command('git.timeline.openDiff', { repository: false }) async timelineOpenDiff(item: TimelineItem, uri: Uri | undefined, _source: string) { - // eslint-disable-next-line eqeqeq - if (uri == null || !GitTimelineItem.is(item)) { + if (uri === undefined || uri === null || !GitTimelineItem.is(item)) { return undefined; } diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts index 326bc19e4e..938b81b2f4 100644 --- a/extensions/git/src/git.ts +++ b/extensions/git/src/git.ts @@ -419,7 +419,7 @@ export class Git { } async getRepositoryRoot(repositoryPath: string): Promise { - const result = await this.exec(repositoryPath, ['rev-parse', '--show-toplevel']); + const result = await this.exec(repositoryPath, ['rev-parse', '--show-toplevel'], { log: false }); // Keep trailing spaces which are part of the directory name const repoPath = path.normalize(result.stdout.trimLeft().replace(/[\r\n]+$/, '')); @@ -437,8 +437,7 @@ export class Git { try { const networkPath = await new Promise(resolve => realpath.native(`${letter}:`, { encoding: 'utf8' }, (err, resolvedPath) => - // eslint-disable-next-line eqeqeq - resolve(err != null ? undefined : resolvedPath), + resolve(err !== null ? undefined : resolvedPath), ), ); if (networkPath !== undefined) { @@ -1628,6 +1627,8 @@ export class Repository { err.gitErrorCode = GitErrorCodes.RemoteConnectionError; } else if (/^fatal: The current branch .* has no upstream branch/.test(err.stderr || '')) { err.gitErrorCode = GitErrorCodes.NoUpstreamBranch; + } else if (/Permission.*denied/.test(err.stderr || '')) { + err.gitErrorCode = GitErrorCodes.PermissionDenied; } throw err; diff --git a/extensions/git/src/main.ts b/extensions/git/src/main.ts index 456b485cb7..8102413024 100644 --- a/extensions/git/src/main.ts +++ b/extensions/git/src/main.ts @@ -128,7 +128,7 @@ async function warnAboutMissingGit(): Promise { } }*/ -export async function _activate(context: ExtensionContext): Promise { +export async function _activate(context: ExtensionContext): Promise { const disposables: Disposable[] = []; context.subscriptions.push(new Disposable(() => Disposable.from(...disposables).dispose())); @@ -176,8 +176,7 @@ export async function activate(context: ExtensionContext): Promise return result; } -// @ts-expect-error -async function checkGitVersion(info: IGit): Promise { +async function checkGitv1(info: IGit): Promise { const config = workspace.getConfiguration('git'); const shouldIgnore = config.get('ignoreLegacyWarning') === true; @@ -204,3 +203,28 @@ async function checkGitVersion(info: IGit): Promise { await config.update('ignoreLegacyWarning', true, true); } } + +async function checkGitWindows(info: IGit): Promise { + if (!/^2\.(25|26)\./.test(info.version)) { + return; + } + + const update = localize('updateGit', "Update Git"); + const choice = await window.showWarningMessage( + localize('git2526', "There are known issues with the installed Git {0}. Please update to Git >= 2.27 for the git features to work correctly.", info.version), + update + ); + + if (choice === update) { + commands.executeCommand('vscode.open', Uri.parse('https://git-scm.com/')); + } +} + +// @ts-expect-error +async function checkGitVersion(info: IGit): Promise { + await checkGitv1(info); + + if (process.platform === 'win32') { + await checkGitWindows(info); + } +} diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts index d41e202ebf..8f4e1ac6a3 100644 --- a/extensions/git/src/model.ts +++ b/extensions/git/src/model.ts @@ -12,9 +12,10 @@ import * as path from 'path'; import * as fs from 'fs'; import * as nls from 'vscode-nls'; import { fromGitUri } from './uri'; -import { APIState as State, RemoteSourceProvider, CredentialsProvider } from './api/git'; +import { APIState as State, RemoteSourceProvider, CredentialsProvider, PushErrorHandler } from './api/git'; import { Askpass } from './askpass'; import { IRemoteSourceProviderRegistry } from './remoteProvider'; +import { IPushErrorHandlerRegistry } from './pushError'; const localize = nls.loadMessageBundle(); @@ -46,7 +47,7 @@ interface OpenRepository extends Disposable { repository: Repository; } -export class Model implements IRemoteSourceProviderRegistry { +export class Model implements IRemoteSourceProviderRegistry, IPushErrorHandlerRegistry { private _onDidOpenRepository = new EventEmitter(); readonly onDidOpenRepository: Event = this._onDidOpenRepository.event; @@ -94,6 +95,8 @@ export class Model implements IRemoteSourceProviderRegistry { private _onDidRemoveRemoteSourceProvider = new EventEmitter(); readonly onDidRemoveRemoteSourceProvider = this._onDidRemoveRemoteSourceProvider.event; + private pushErrorHandlers = new Set(); + private disposables: Disposable[] = []; constructor(readonly git: Git, private readonly askpass: Askpass, private globalState: Memento, private outputChannel: OutputChannel) { @@ -269,7 +272,7 @@ export class Model implements IRemoteSourceProviderRegistry { } const dotGit = await this.git.getRepositoryDotGit(repositoryRoot); - const repository = new Repository(this.git.open(repositoryRoot, dotGit), this, this.globalState, this.outputChannel); + const repository = new Repository(this.git.open(repositoryRoot, dotGit), this, this, this.globalState, this.outputChannel); this.open(repository); await repository.status(); @@ -485,6 +488,15 @@ export class Model implements IRemoteSourceProviderRegistry { return [...this.remoteSourceProviders.values()]; } + registerPushErrorHandler(handler: PushErrorHandler): Disposable { + this.pushErrorHandlers.add(handler); + return toDisposable(() => this.pushErrorHandlers.delete(handler)); + } + + getPushErrorHandlers(): PushErrorHandler[] { + return [...this.pushErrorHandlers]; + } + dispose(): void { const openRepositories = [...this.openRepositories]; openRepositories.forEach(r => r.dispose()); diff --git a/extensions/git/src/pushError.ts b/extensions/git/src/pushError.ts new file mode 100644 index 0000000000..ddecb6d7e1 --- /dev/null +++ b/extensions/git/src/pushError.ts @@ -0,0 +1,12 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Disposable } from 'vscode'; +import { PushErrorHandler } from './api/git'; + +export interface IPushErrorHandlerRegistry { + registerPushErrorHandler(provider: PushErrorHandler): Disposable; + getPushErrorHandlers(): PushErrorHandler[]; +} diff --git a/extensions/git/src/remoteSource.ts b/extensions/git/src/remoteSource.ts new file mode 100644 index 0000000000..f8361eb6a2 --- /dev/null +++ b/extensions/git/src/remoteSource.ts @@ -0,0 +1,133 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { QuickPickItem, window, QuickPick } from 'vscode'; +import * as nls from 'vscode-nls'; +import { RemoteSourceProvider, RemoteSource } from './api/git'; +import { Model } from './model'; +import { throttle, debounce } from './decorators'; + +const localize = nls.loadMessageBundle(); + +async function getQuickPickResult(quickpick: QuickPick): Promise { + const result = await new Promise(c => { + quickpick.onDidAccept(() => c(quickpick.selectedItems[0])); + quickpick.onDidHide(() => c(undefined)); + quickpick.show(); + }); + + quickpick.hide(); + return result; +} + +class RemoteSourceProviderQuickPick { + + private quickpick: QuickPick; + + constructor(private provider: RemoteSourceProvider) { + this.quickpick = window.createQuickPick(); + this.quickpick.ignoreFocusOut = true; + + if (provider.supportsQuery) { + this.quickpick.placeholder = localize('type to search', "Repository name (type to search)"); + this.quickpick.onDidChangeValue(this.onDidChangeValue, this); + } else { + this.quickpick.placeholder = localize('type to filter', "Repository name"); + } + } + + @debounce(300) + private onDidChangeValue(): void { + this.query(); + } + + @throttle + private async query(): Promise { + this.quickpick.busy = true; + + try { + const remoteSources = await this.provider.getRemoteSources(this.quickpick.value) || []; + + if (remoteSources.length === 0) { + this.quickpick.items = [{ + label: localize('none found', "No remote repositories found."), + alwaysShow: true + }]; + } else { + this.quickpick.items = remoteSources.map(remoteSource => ({ + label: remoteSource.name, + description: remoteSource.description || (typeof remoteSource.url === 'string' ? remoteSource.url : remoteSource.url[0]), + remoteSource + })); + } + } catch (err) { + this.quickpick.items = [{ label: localize('error', "$(error) Error: {0}", err.message), alwaysShow: true }]; + console.error(err); + } finally { + this.quickpick.busy = false; + } + } + + async pick(): Promise { + this.query(); + const result = await getQuickPickResult(this.quickpick); + return result?.remoteSource; + } +} + +export interface PickRemoteSourceOptions { + readonly providerLabel?: (provider: RemoteSourceProvider) => string; + readonly urlLabel?: string; +} + +export async function pickRemoteSource(model: Model, options: PickRemoteSourceOptions = {}): Promise { + const quickpick = window.createQuickPick<(QuickPickItem & { provider?: RemoteSourceProvider, url?: string })>(); + quickpick.ignoreFocusOut = true; + + const providers = model.getRemoteProviders() + .map(provider => ({ label: (provider.icon ? `$(${provider.icon}) ` : '') + (options.providerLabel ? options.providerLabel(provider) : provider.name), alwaysShow: true, provider })); + + quickpick.placeholder = providers.length === 0 + ? localize('provide url', "Provide repository URL") + : localize('provide url or pick', "Provide repository URL or pick a repository source."); + + const updatePicks = (value?: string) => { + if (value) { + quickpick.items = [{ + label: options.urlLabel ?? localize('url', "URL"), + description: value, + alwaysShow: true, + url: value + }, + ...providers]; + } else { + quickpick.items = providers; + } + }; + + quickpick.onDidChangeValue(updatePicks); + updatePicks(); + + const result = await getQuickPickResult(quickpick); + + if (result) { + if (result.url) { + return result.url; + } else if (result.provider) { + const quickpick = new RemoteSourceProviderQuickPick(result.provider); + const remote = await quickpick.pick(); + + if (remote) { + if (typeof remote.url === 'string') { + return remote.url; + } else if (remote.url.length > 0) { + return await window.showQuickPick(remote.url, { ignoreFocusOut: true, placeHolder: localize('pick url', "Choose a URL to clone from.") }); + } + } + } + } + + return undefined; +} diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts index ea3feabd01..8217d2037e 100644 --- a/extensions/git/src/repository.ts +++ b/extensions/git/src/repository.ts @@ -17,6 +17,8 @@ import { anyEvent, combinedDisposable, debounceEvent, dispose, EmptyDisposable, import { IFileWatcher, watch } from './watch'; import { Log, LogLevel } from './log'; import { IRemoteSourceProviderRegistry } from './remoteProvider'; +import { IPushErrorHandlerRegistry } from './pushError'; +import { ApiRepository } from './api/api1'; const timeout = (millis: number) => new Promise(c => setTimeout(c, millis)); @@ -683,6 +685,7 @@ export class Repository implements Disposable { constructor( private readonly repository: BaseRepository, remoteSourceProviderRegistry: IRemoteSourceProviderRegistry, + private pushErrorHandlerRegistry: IPushErrorHandlerRegistry, globalState: Memento, outputChannel: OutputChannel ) { @@ -865,7 +868,7 @@ export class Repository implements Disposable { } async getInputTemplate(): Promise { - const commitMessage = (await Promise.all([this.repository.getMergeMessage(), this.repository.getSquashMessage()])).find(msg => msg !== undefined); + const commitMessage = (await Promise.all([this.repository.getMergeMessage(), this.repository.getSquashMessage()])).find(msg => !!msg); if (commitMessage) { return commitMessage; @@ -1181,15 +1184,15 @@ export class Repository implements Disposable { branch = `${head.name}:${head.upstream.name}`; } - await this.run(Operation.Push, () => this.repository.push(remote, branch, undefined, undefined, forcePushMode)); + await this.run(Operation.Push, () => this._push(remote, branch, undefined, undefined, forcePushMode)); } async pushTo(remote?: string, name?: string, setUpstream: boolean = false, forcePushMode?: ForcePushMode): Promise { - await this.run(Operation.Push, () => this.repository.push(remote, name, setUpstream, undefined, forcePushMode)); + await this.run(Operation.Push, () => this._push(remote, name, setUpstream, undefined, forcePushMode)); } async pushFollowTags(remote?: string, forcePushMode?: ForcePushMode): Promise { - await this.run(Operation.Push, () => this.repository.push(remote, undefined, false, true, forcePushMode)); + await this.run(Operation.Push, () => this._push(remote, undefined, false, true, forcePushMode)); } async blame(path: string): Promise { @@ -1249,7 +1252,7 @@ export class Repository implements Disposable { const shouldPush = this.HEAD && (typeof this.HEAD.ahead === 'number' ? this.HEAD.ahead > 0 : true); if (shouldPush) { - await this.repository.push(remoteName, pushBranch); + await this._push(remoteName, pushBranch); } }); }); @@ -1411,6 +1414,31 @@ export class Repository implements Disposable { return ignored; } + private async _push(remote?: string, refspec?: string, setUpstream: boolean = false, tags = false, forcePushMode?: ForcePushMode): Promise { + try { + await this.repository.push(remote, refspec, setUpstream, tags, forcePushMode); + } catch (err) { + if (!remote || !refspec) { + throw err; + } + + const repository = new ApiRepository(this); + const remoteObj = repository.state.remotes.find(r => r.name === remote); + + if (!remoteObj) { + throw err; + } + + for (const handler of this.pushErrorHandlerRegistry.getPushErrorHandlers()) { + if (await handler.handlePushError(repository, remoteObj, refspec, err)) { + return; + } + } + + throw err; + } + } + private async run(operation: Operation, runOperation: () => Promise = () => Promise.resolve(null)): Promise { if (this.state !== RepositoryState.Idle) { throw new Error('Repository not initialized'); diff --git a/extensions/git/src/util.ts b/extensions/git/src/util.ts index 221f2a65a2..23e8f9f8b7 100644 --- a/extensions/git/src/util.ts +++ b/extensions/git/src/util.ts @@ -44,18 +44,6 @@ export function filterEvent(event: Event, filter: (e: T) => boolean): Even return (listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables); } -export function latchEvent(event: Event): Event { - let firstCall = true; - let cache: T; - - return filterEvent(event, value => { - let shouldEmit = firstCall || value !== cache; - firstCall = false; - cache = value; - return shouldEmit; - }); -} - export function anyEvent(...events: Event[]): Event { return (listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[]) => { const result = combinedDisposable(events.map(event => event(i => listener.call(thisArgs, i)))); diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock index 35277c4713..b56e76c37a 100644 --- a/extensions/git/yarn.lock +++ b/extensions/git/yarn.lock @@ -425,10 +425,10 @@ https-proxy-agent@^2.2.1: agent-base "^4.3.0" debug "^3.1.0" -iconv-lite-umd@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.5.tgz#6a1f621a3b4d125f72feff813a9839e1ebd6c722" - integrity sha512-WDegH4al+e3n3jTOStRvm+jzDA3JMUQGgzdAsMxAgcgB0Oi72HjfdsoX08ieKsy3rKexXVjWZr41aOIUaCZnMg== +iconv-lite-umd@0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.8.tgz#5ad310ec126b260621471a2d586f7f37b9958ec0" + integrity sha512-zvXJ5gSwMC9JD3wDzH8CoZGc1pbiJn12Tqjk8BXYCnYz3hYL5GRjHW8LEykjXhV9WgNGI4rgpgHcbIiBfrRq6A== inflight@^1.0.4: version "1.0.6" @@ -468,10 +468,10 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= -jschardet@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.1.1.tgz#af6f8fd0b3b0f5d46a8fd9614a4fce490575c184" - integrity sha512-pA5qG9Zwm8CBpGlK/lo2GE9jPxwqRgMV7Lzc/1iaPccw6v4Rhj8Zg2BTyrdmHmxlJojnbLupLeRnaPLsq03x6Q== +jschardet@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.2.1.tgz#03b0264669a90c7a5c436a68c5a7d4e4cb0c9823" + integrity sha512-Ks2JNuUJoc7PGaZ7bVFtSEvOcr0rBq6Q1J5/7+zKWLT+g+4zziL63O0jg7y2jxhzIa1LVsHUbPXrbaWmz9iwDw== json-schema-traverse@^0.4.1: version "0.4.1" diff --git a/extensions/github-authentication/src/extension.ts b/extensions/github-authentication/src/extension.ts index d5c8d203c0..9d4fa10b10 100644 --- a/extensions/github-authentication/src/extension.ts +++ b/extensions/github-authentication/src/extension.ts @@ -24,19 +24,27 @@ export async function activate(context: vscode.ExtensionContext) { vscode.authentication.registerAuthenticationProvider({ id: 'github', - displayName: 'GitHub', + label: 'GitHub', supportsMultipleAccounts: false, onDidChangeSessions: onDidChangeSessions.event, getSessions: () => Promise.resolve(loginService.sessions), login: async (scopeList: string[]) => { try { + /* __GDPR__ + "login" : { } + */ telemetryReporter.sendTelemetryEvent('login'); + const session = await loginService.login(scopeList.sort().join(' ')); Logger.info('Login success!'); onDidChangeSessions.fire({ added: [session.id], removed: [], changed: [] }); return session; } catch (e) { + /* __GDPR__ + "loginFailed" : { } + */ telemetryReporter.sendTelemetryEvent('loginFailed'); + vscode.window.showErrorMessage(`Sign in failed: ${e}`); Logger.error(e); throw e; @@ -44,11 +52,19 @@ export async function activate(context: vscode.ExtensionContext) { }, logout: async (id: string) => { try { + /* __GDPR__ + "logout" : { } + */ telemetryReporter.sendTelemetryEvent('logout'); + await loginService.logout(id); onDidChangeSessions.fire({ added: [], removed: [id], changed: [] }); } catch (e) { + /* __GDPR__ + "logoutFailed" : { } + */ telemetryReporter.sendTelemetryEvent('logoutFailed'); + vscode.window.showErrorMessage(`Sign out failed: ${e}`); Logger.error(e); throw e; diff --git a/extensions/github-authentication/src/github.ts b/extensions/github-authentication/src/github.ts index f86092fbd0..55376dcdfa 100644 --- a/extensions/github-authentication/src/github.ts +++ b/extensions/github-authentication/src/github.ts @@ -14,7 +14,8 @@ export const onDidChangeSessions = new vscode.EventEmitter { const userInfo = await this._githubServer.getUserInfo(token); - return new vscode.AuthenticationSession(uuid(), token, { displayName: userInfo.accountName, id: userInfo.id }, scopes); + return new vscode.AuthenticationSession(uuid(), token, { label: userInfo.accountName, id: userInfo.id }, scopes); } private async setToken(session: vscode.AuthenticationSession): Promise { diff --git a/extensions/github-browser/package.json b/extensions/github-browser/package.json index 6e3c071b70..9938e25ed5 100644 --- a/extensions/github-browser/package.json +++ b/extensions/github-browser/package.json @@ -21,6 +21,11 @@ "main": "./out/extension.js", "contributes": { "commands": [ + { + "command": "githubBrowser.openRepository", + "title": "Open GitHub Repository...", + "category": "GitHub Browser" + }, { "command": "githubBrowser.commit", "title": "Commit", @@ -48,6 +53,10 @@ ], "menus": { "commandPalette": [ + { + "command": "githubBrowser.openRepository", + "when": "config.githubBrowser.openRepository" + }, { "command": "githubBrowser.commit", "when": "false" diff --git a/extensions/github-browser/src/changeStore.ts b/extensions/github-browser/src/changeStore.ts index 26ba7f1071..516eee7c38 100644 --- a/extensions/github-browser/src/changeStore.ts +++ b/extensions/github-browser/src/changeStore.ts @@ -47,31 +47,17 @@ function fromSerialized(operations: StoredOperation): Operation { return { ...operations, uri: Uri.parse(operations.uri) }; } -interface CreatedFileChangeStoreEvent { - type: 'created'; +export interface ChangeStoreEvent { + type: 'created' | 'changed' | 'deleted'; rootUri: Uri; uri: Uri; } -interface ChangedFileChangeStoreEvent { - type: 'changed'; - rootUri: Uri; - uri: Uri; -} - -interface DeletedFileChangeStoreEvent { - type: 'deleted'; - rootUri: Uri; - uri: Uri; -} - -type ChangeStoreEvent = CreatedFileChangeStoreEvent | ChangedFileChangeStoreEvent | DeletedFileChangeStoreEvent; - function toChangeStoreEvent(operation: Operation | StoredOperation, rootUri: Uri, uri?: Uri): ChangeStoreEvent { return { type: operation.type, rootUri: rootUri, - uri: uri ?? (typeof operation.uri === 'string' ? Uri.parse(operation.uri) : operation.uri) + uri: uri ?? (typeof operation.uri === 'string' ? Uri.parse(operation.uri) : operation.uri), }; } @@ -82,6 +68,8 @@ export interface IChangeStore { discard(uri: Uri): Promise; discardAll(rootUri: Uri): Promise; + hasChanges(rootUri: Uri): boolean; + getChanges(rootUri: Uri): Operation[]; getContent(uri: Uri): string | undefined; @@ -116,9 +104,15 @@ export class ChangeStore implements IChangeStore, IWritableChangeStore { await this.saveWorkingOperations(rootUri, undefined); + const events: ChangeStoreEvent[] = []; + for (const operation of operations) { await this.discardWorkingContent(operation.uri); - this._onDidChange.fire(toChangeStoreEvent(operation, rootUri)); + events.push(toChangeStoreEvent(operation, rootUri)); + } + + for (const e of events) { + this._onDidChange.fire(e); } } @@ -143,7 +137,7 @@ export class ChangeStore implements IChangeStore, IWritableChangeStore { this._onDidChange.fire({ type: operation.type === 'created' ? 'deleted' : operation.type === 'deleted' ? 'created' : 'changed', rootUri: rootUri, - uri: uri + uri: uri, }); } @@ -152,9 +146,15 @@ export class ChangeStore implements IChangeStore, IWritableChangeStore { await this.saveWorkingOperations(rootUri, undefined); + const events: ChangeStoreEvent[] = []; + for (const operation of operations) { await this.discardWorkingContent(operation.uri); - this._onDidChange.fire(toChangeStoreEvent(operation, rootUri)); + events.push(toChangeStoreEvent(operation, rootUri)); + } + + for (const e of events) { + this._onDidChange.fire(e); } } diff --git a/extensions/github-browser/src/contextStore.ts b/extensions/github-browser/src/contextStore.ts index f0f418da36..f53d635dd2 100644 --- a/extensions/github-browser/src/contextStore.ts +++ b/extensions/github-browser/src/contextStore.ts @@ -4,9 +4,13 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import { Event, EventEmitter, Memento, Uri } from 'vscode'; +import { Event, EventEmitter, Memento, Uri, workspace } from 'vscode'; -export const contextKeyPrefix = 'github.context|'; +export interface WorkspaceFolderContext { + context: T; + name: string; + folderUri: Uri; +} export class ContextStore { private _onDidChange = new EventEmitter(); @@ -14,23 +18,36 @@ export class ContextStore { return this._onDidChange.event; } - constructor(private readonly memento: Memento, private readonly scheme: string) { } + constructor( + private readonly scheme: string, + private readonly originalScheme: string, + private readonly memento: Memento, + ) { } delete(uri: Uri) { return this.set(uri, undefined); } get(uri: Uri): T | undefined { - return this.memento.get(`${contextKeyPrefix}${uri.toString()}`); + return this.memento.get(`${this.originalScheme}.context|${this.getOriginalResource(uri).toString()}`); } + getForWorkspace(): WorkspaceFolderContext[] { + const folders = workspace.workspaceFolders?.filter(f => f.uri.scheme === this.scheme || f.uri.scheme === this.originalScheme) ?? []; + return folders.map(f => ({ context: this.get(f.uri)!, name: f.name, folderUri: f.uri })).filter(c => c.context !== undefined); + } async set(uri: Uri, context: T | undefined) { - if (uri.scheme !== this.scheme) { - throw new Error(`Invalid context scheme: ${uri.scheme}`); - } - - await this.memento.update(`${contextKeyPrefix}${uri.toString()}`, context); + uri = this.getOriginalResource(uri); + await this.memento.update(`${this.originalScheme}.context|${uri.toString()}`, context); this._onDidChange.fire(uri); } + + getOriginalResource(uri: Uri): Uri { + return uri.with({ scheme: this.originalScheme }); + } + + getWorkspaceResource(uri: Uri): Uri { + return uri.with({ scheme: this.scheme }); + } } diff --git a/extensions/github-browser/src/extension.ts b/extensions/github-browser/src/extension.ts index d0df7d647a..d0f551b0c7 100644 --- a/extensions/github-browser/src/extension.ts +++ b/extensions/github-browser/src/extension.ts @@ -3,48 +3,50 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ExtensionContext, Uri, workspace } from 'vscode'; +import { commands, ExtensionContext, Uri, window, workspace } from 'vscode'; import { ChangeStore } from './changeStore'; import { ContextStore } from './contextStore'; import { VirtualFS } from './fs'; import { GitHubApiContext, GitHubApi } from './github/api'; import { GitHubFS } from './github/fs'; import { VirtualSCM } from './scm'; +import { StatusBar } from './statusbar'; -// const repositoryRegex = /^(?:(?:https:\/\/)?github.com\/)?([^\/]+)\/([^\/]+?)(?:\/|.git|$)/i; +const repositoryRegex = /^(?:(?:https:\/\/)?github.com\/)?([^\/]+)\/([^\/]+?)(?:\/|.git|$)/i; -export function activate(context: ExtensionContext) { - const contextStore = new ContextStore(context.workspaceState, GitHubFS.scheme); +export async function activate(context: ExtensionContext) { + const contextStore = new ContextStore('codespace', GitHubFS.scheme, context.workspaceState); const changeStore = new ChangeStore(context.workspaceState); const githubApi = new GitHubApi(contextStore); const gitHubFS = new GitHubFS(githubApi); - const virtualFS = new VirtualFS('codespace', GitHubFS.scheme, contextStore, changeStore, gitHubFS); + const virtualFS = new VirtualFS('codespace', contextStore, changeStore, gitHubFS); context.subscriptions.push( githubApi, gitHubFS, virtualFS, - new VirtualSCM(GitHubFS.scheme, githubApi, changeStore) + new VirtualSCM(GitHubFS.scheme, githubApi, changeStore), + new StatusBar(contextStore, changeStore), ); - // commands.registerCommand('githubBrowser.openRepository', async () => { - // const value = await window.showInputBox({ - // placeHolder: 'e.g. https://github.com/microsoft/vscode', - // prompt: 'Enter a GitHub repository url', - // validateInput: value => repositoryRegex.test(value) ? undefined : 'Invalid repository url' - // }); + commands.registerCommand('githubBrowser.openRepository', async () => { + const value = await window.showInputBox({ + placeHolder: 'e.g. https://github.com/microsoft/vscode', + prompt: 'Enter a GitHub repository url', + validateInput: value => repositoryRegex.test(value) ? undefined : 'Invalid repository url' + }); - // if (value) { - // const match = repositoryRegex.exec(value); - // if (match) { - // const [, owner, repo] = match; + if (value) { + const match = repositoryRegex.exec(value); + if (match) { + const [, owner, repo] = match; - // const uri = Uri.parse(`codespace://HEAD/${owner}/${repo}`); - // openWorkspace(uri, repo, 'currentWindow'); - // } - // } - // }); + const uri = Uri.parse(`codespace://HEAD/${owner}/${repo}`); + openWorkspace(uri, repo, 'currentWindow'); + } + } + }); } export function getRelativePath(rootUri: Uri, uri: Uri) { @@ -63,11 +65,16 @@ export function isDescendent(folderPath: string, filePath: string) { return folderPath.length === 0 || filePath.startsWith(folderPath.endsWith('/') ? folderPath : `${folderPath}/`); } -// function openWorkspace(uri: Uri, name: string, location: 'currentWindow' | 'newWindow' | 'addToCurrentWorkspace') { -// if (location === 'addToCurrentWorkspace') { -// const count = (workspace.workspaceFolders && workspace.workspaceFolders.length) || 0; -// return workspace.updateWorkspaceFolders(count, 0, { uri: uri, name: name }); -// } +const shaRegex = /^[0-9a-f]{40}$/; +export function isSha(ref: string) { + return shaRegex.test(ref); +} -// return commands.executeCommand('vscode.openFolder', uri, location === 'newWindow'); -// } +function openWorkspace(uri: Uri, name: string, location: 'currentWindow' | 'newWindow' | 'addToCurrentWorkspace') { + if (location === 'addToCurrentWorkspace') { + const count = (workspace.workspaceFolders && workspace.workspaceFolders.length) || 0; + return workspace.updateWorkspaceFolders(count, 0, { uri: uri, name: name }); + } + + return commands.executeCommand('vscode.openFolder', uri, location === 'newWindow'); +} diff --git a/extensions/github-browser/src/fs.ts b/extensions/github-browser/src/fs.ts index cb163c85b2..0a0ca250ee 100644 --- a/extensions/github-browser/src/fs.ts +++ b/extensions/github-browser/src/fs.ts @@ -43,26 +43,22 @@ export class VirtualFS implements FileSystemProvider, FileSearchProvider, TextSe constructor( readonly scheme: string, - private readonly originalScheme: string, - contextStore: ContextStore, + private readonly contextStore: ContextStore, private readonly changeStore: IWritableChangeStore, private readonly fs: FileSystemProvider & FileSearchProvider & TextSearchProvider ) { // TODO@eamodio listen for workspace folder changes - for (const folder of workspace.workspaceFolders ?? []) { - const uri = this.getOriginalResource(folder.uri); - + for (const context of contextStore.getForWorkspace()) { // If we have a saved context, but no longer have any changes, reset the context // We only do this on startup/reload to keep things consistent - if (contextStore.get(uri) !== undefined && !changeStore.hasChanges(folder.uri)) { - contextStore.delete(uri); + if (!changeStore.hasChanges(context.folderUri)) { + console.log('Clear context', context.folderUri.toString()); + contextStore.delete(context.folderUri); } } this.disposable = Disposable.from( - workspace.registerFileSystemProvider(scheme, this, { - isCaseSensitive: true, - }), + workspace.registerFileSystemProvider(scheme, this, { isCaseSensitive: true }), workspace.registerFileSearchProvider(scheme, this), workspace.registerTextSearchProvider(scheme, this), changeStore.onDidChange(e => { @@ -86,11 +82,11 @@ export class VirtualFS implements FileSystemProvider, FileSearchProvider, TextSe } private getOriginalResource(uri: Uri): Uri { - return uri.with({ scheme: this.originalScheme }); + return this.contextStore.getOriginalResource(uri); } - private getVirtualResource(uri: Uri): Uri { - return uri.with({ scheme: this.scheme }); + private getWorkspaceResource(uri: Uri): Uri { + return this.contextStore.getWorkspaceResource(uri); } //#region FileSystemProvider @@ -211,7 +207,7 @@ export class VirtualFS implements FileSystemProvider, FileSearchProvider, TextSe return this.fs.provideTextSearchResults( query, { ...options, folder: this.getOriginalResource(options.folder) }, - { report: (result: TextSearchResult) => progress.report({ ...result, uri: this.getVirtualResource(result.uri) }) }, + { report: (result: TextSearchResult) => progress.report({ ...result, uri: this.getWorkspaceResource(result.uri) }) }, token ); } diff --git a/extensions/github-browser/src/github/api.ts b/extensions/github-browser/src/github/api.ts index 7fffb4a6b7..186eb1a223 100644 --- a/extensions/github-browser/src/github/api.ts +++ b/extensions/github-browser/src/github/api.ts @@ -6,14 +6,16 @@ import { authentication, AuthenticationSession, Disposable, Event, EventEmitter, Range, Uri } from 'vscode'; import { graphql } from '@octokit/graphql'; import { Octokit } from '@octokit/rest'; -import { fromGitHubUri } from './fs'; import { ContextStore } from '../contextStore'; +import { fromGitHubUri } from './fs'; +import { isSha } from '../extension'; import { Iterables } from '../iterables'; -export const shaRegex = /^[0-9a-f]{40}$/; - export interface GitHubApiContext { - sha: string; + requestRef: string; + + branch: string; + sha: string | undefined; timestamp: number; } @@ -73,7 +75,7 @@ export class GitHubApi implements Disposable { if (!providers.includes('github')) { await new Promise(resolve => { authentication.onDidChangeAuthenticationProviders(e => { - if (e.added.includes('github')) { + if (e.added.find(provider => provider.id === 'github')) { resolve(); } }); @@ -110,19 +112,12 @@ export class GitHubApi implements Disposable { } async commit(rootUri: Uri, message: string, operations: CommitOperation[]): Promise { - let { owner, repo, ref } = fromGitHubUri(rootUri); + const { owner, repo } = fromGitHubUri(rootUri); try { - if (ref === undefined || ref === 'HEAD') { - ref = await this.defaultBranchQuery(rootUri); - if (ref === undefined) { - throw new Error('Cannot commit — invalid ref'); - } - } - const context = await this.getContext(rootUri); if (context.sha === undefined) { - throw new Error('Cannot commit — invalid context'); + throw new Error(`Cannot commit to Uri(${rootUri.toString(true)}); Invalid context sha`); } const hasDeletes = operations.some(op => op.type === 'deleted'); @@ -204,14 +199,14 @@ export class GitHubApi implements Disposable { parents: [context.sha] }); - this.updateContext(rootUri, { sha: resp.data.sha, timestamp: Date.now() }); + this.updateContext(rootUri, { ...context, sha: resp.data.sha, timestamp: Date.now() }); // TODO@eamodio need to send a file change for any open files await github.git.updateRef({ owner: owner, repo: repo, - ref: `heads/${ref}`, + ref: `heads/${context.branch}`, sha: resp.data.sha }); @@ -256,7 +251,7 @@ export class GitHubApi implements Disposable { owner: owner, repo: repo, recursive: '1', - tree_sha: context?.sha ?? ref ?? 'HEAD', + tree_sha: context?.sha ?? ref, }); return Iterables.filterMap(resp.data.tree, p => p.type === 'blob' ? p.path : undefined); } catch (ex) { @@ -283,7 +278,7 @@ export class GitHubApi implements Disposable { }>(query, { owner: owner, repo: repo, - path: `${context.sha ?? ref ?? 'HEAD'}:${path}`, + path: `${context.sha ?? ref}:${path}`, }); return rsp?.repository?.object ?? undefined; } catch (ex) { @@ -295,7 +290,7 @@ export class GitHubApi implements Disposable { const { owner, repo, ref } = fromGitHubUri(uri); try { - if (ref === undefined || ref === 'HEAD') { + if (ref === 'HEAD') { const query = `query latest($owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { defaultBranchRef { @@ -322,6 +317,7 @@ export class GitHubApi implements Disposable { oid } } + } }`; const rsp = await this.gqlQuery<{ @@ -345,7 +341,7 @@ export class GitHubApi implements Disposable { const { owner, repo, ref } = fromGitHubUri(uri); // If we have a specific ref, don't try to search, because GitHub search only works against the default branch - if (ref === undefined) { + if (ref !== 'HEAD') { return { matches: [], limitHit: true }; } @@ -436,29 +432,46 @@ export class GitHubApi implements Disposable { private readonly rootUriToContextMap = new Map(); private async getContextCore(rootUri: Uri): Promise { - let context = this.rootUriToContextMap.get(rootUri.toString()); - if (context === undefined) { - const { ref } = fromGitHubUri(rootUri); - if (ref !== undefined && shaRegex.test(ref)) { - context = { sha: ref, timestamp: Date.now() }; - } else { - context = this.context.get(rootUri); - if (context?.sha === undefined) { - const sha = await this.latestCommitQuery(rootUri); - if (sha !== undefined) { - context = { sha: sha, timestamp: Date.now() }; - } else { - context = undefined; - } - } - } + const key = rootUri.toString(); + let context = this.rootUriToContextMap.get(key); - if (context !== undefined) { - this.updateContext(rootUri, context); - } + // Check if we have a cached a context + if (context?.sha !== undefined) { + return context; } - return context ?? { sha: rootUri.authority, timestamp: Date.now() }; + // Check if we have a saved context + context = this.context.get(rootUri); + if (context?.sha !== undefined) { + this.rootUriToContextMap.set(key, context); + + return context; + } + + const { ref } = fromGitHubUri(rootUri); + + // If the requested ref looks like a sha, then use it + if (isSha(ref)) { + context = { requestRef: ref, branch: ref, sha: ref, timestamp: Date.now() }; + } else { + let branch; + if (ref === 'HEAD') { + branch = await this.defaultBranchQuery(rootUri); + if (branch === undefined) { + throw new Error(`Cannot get context for Uri(${rootUri.toString(true)}); unable to get default branch`); + } + } else { + branch = ref; + } + + // Query for the latest sha for the give ref + const sha = await this.latestCommitQuery(rootUri); + context = { requestRef: ref, branch: branch, sha: sha, timestamp: Date.now() }; + } + + this.updateContext(rootUri, context); + + return context; } private updateContext(rootUri: Uri, context: GitHubApiContext) { diff --git a/extensions/github-browser/src/github/fs.ts b/extensions/github-browser/src/github/fs.ts index 9149a69b3a..389f3cc00e 100644 --- a/extensions/github-browser/src/github/fs.ts +++ b/extensions/github-browser/src/github/fs.ts @@ -299,7 +299,7 @@ function typenameToFileType(typename: string | undefined | null) { } } -type RepoInfo = { owner: string; repo: string; path: string | undefined; ref?: string }; +type RepoInfo = { owner: string; repo: string; path: string | undefined; ref: string }; export function fromGitHubUri(uri: Uri): RepoInfo { const [, owner, repo, ...rest] = uri.path.split('/'); @@ -311,7 +311,7 @@ export function fromGitHubUri(uri: Uri): RepoInfo { ref = 'HEAD'; } } - return { owner: owner, repo: repo, path: rest.join('/'), ref: ref }; + return { owner: owner, repo: repo, path: rest.join('/'), ref: ref ?? 'HEAD' }; } function getHashCode(s: string): number { diff --git a/extensions/github-browser/src/iterables.ts b/extensions/github-browser/src/iterables.ts index 0545b2bd70..502750caf9 100644 --- a/extensions/github-browser/src/iterables.ts +++ b/extensions/github-browser/src/iterables.ts @@ -12,8 +12,9 @@ export namespace Iterables { ): Iterable { for (const item of source) { const mapped = predicateMapper(item); - // eslint-disable-next-line eqeqeq - if (mapped != null) { yield mapped; } + if (mapped !== undefined && mapped !== null) { + yield mapped; + } } } diff --git a/extensions/github-browser/src/scm.ts b/extensions/github-browser/src/scm.ts index f1e039dc2c..ce0519d935 100644 --- a/extensions/github-browser/src/scm.ts +++ b/extensions/github-browser/src/scm.ts @@ -32,17 +32,15 @@ export class VirtualSCM implements Disposable { // TODO@eamodio listen for workspace folder changes for (const folder of workspace.workspaceFolders ?? []) { this.createScmProvider(folder.uri, folder.name); + + for (const operation of changeStore.getChanges(folder.uri)) { + this.update(folder.uri, operation.uri); + } } this.disposable = Disposable.from( changeStore.onDidChange(e => this.update(e.rootUri, e.uri)), ); - - for (const { uri } of workspace.workspaceFolders ?? []) { - for (const operation of changeStore.getChanges(uri)) { - this.update(uri, operation.uri); - } - } } dispose() { @@ -50,7 +48,18 @@ export class VirtualSCM implements Disposable { } private registerCommands() { - commands.registerCommand('githubBrowser.commit', (...args: any[]) => this.commitChanges(args[0])); + commands.registerCommand('githubBrowser.commit', (sourceControl: SourceControl | undefined) => { + // TODO@eamodio remove this hack once I figure out why the args are missing + if (sourceControl === undefined && this.providers.length === 1) { + sourceControl = this.providers[0].sourceControl; + } + + if (sourceControl === undefined) { + return; + } + + this.commitChanges(sourceControl); + }); commands.registerCommand('githubBrowser.discardChanges', (resourceState: SourceControlResourceState) => this.discardChanges(resourceState.resourceUri) diff --git a/extensions/github-browser/src/statusbar.ts b/extensions/github-browser/src/statusbar.ts new file mode 100644 index 0000000000..d949a95f7c --- /dev/null +++ b/extensions/github-browser/src/statusbar.ts @@ -0,0 +1,99 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; +import { Disposable, StatusBarAlignment, StatusBarItem, Uri, window, workspace } from 'vscode'; +import { ChangeStoreEvent, IChangeStore } from './changeStore'; +import { GitHubApiContext } from './github/api'; +import { isSha } from './extension'; +import { ContextStore, WorkspaceFolderContext } from './contextStore'; + +export class StatusBar implements Disposable { + private readonly disposable: Disposable; + + private readonly items = new Map(); + + constructor( + private readonly contextStore: ContextStore, + private readonly changeStore: IChangeStore + ) { + this.disposable = Disposable.from( + contextStore.onDidChange(this.onContextsChanged, this), + changeStore.onDidChange(this.onChanged, this) + ); + + for (const context of this.contextStore.getForWorkspace()) { + this.createOrUpdateStatusBarItem(context); + } + } + + dispose() { + this.disposable?.dispose(); + this.items.forEach(i => i.dispose()); + } + + private createOrUpdateStatusBarItem(wc: WorkspaceFolderContext) { + let item = this.items.get(wc.folderUri.toString()); + if (item === undefined) { + item = window.createStatusBarItem({ + id: `githubBrowser.branch:${wc.folderUri.toString()}`, + name: `GitHub Browser: ${wc.name}`, + alignment: StatusBarAlignment.Left, + priority: 1000 + }); + } + + if (isSha(wc.context.branch)) { + item.text = `$(git-commit) ${wc.context.branch.substr(0, 8)}`; + item.tooltip = `${wc.name} \u2022 ${wc.context.branch.substr(0, 8)}`; + } else { + item.text = `$(git-branch) ${wc.context.branch}`; + item.tooltip = `${wc.name} \u2022 ${wc.context.branch}${wc.context.sha ? ` @ ${wc.context.sha?.substr(0, 8)}` : ''}`; + } + + const hasChanges = this.changeStore.hasChanges(wc.folderUri); + if (hasChanges) { + item.text += '*'; + } + + item.show(); + + this.items.set(wc.folderUri.toString(), item); + } + + private onContextsChanged(uri: Uri) { + const folder = workspace.getWorkspaceFolder(this.contextStore.getWorkspaceResource(uri)); + if (folder === undefined) { + return; + } + + const context = this.contextStore.get(uri); + if (context === undefined) { + return; + } + + this.createOrUpdateStatusBarItem({ + context: context, + name: folder.name, + folderUri: folder.uri, + }); + } + + private onChanged(e: ChangeStoreEvent) { + const item = this.items.get(e.rootUri.toString()); + if (item !== undefined) { + const hasChanges = this.changeStore.hasChanges(e.rootUri); + if (hasChanges) { + if (!item.text.endsWith('*')) { + item.text += '*'; + } + } else { + if (item.text.endsWith('*')) { + item.text = item.text.substr(0, item.text.length - 1); + } + } + } + } +} diff --git a/extensions/github/src/commands.ts b/extensions/github/src/commands.ts index 1a3fd851c0..1baf1a85d3 100644 --- a/extensions/github/src/commands.ts +++ b/extensions/github/src/commands.ts @@ -6,9 +6,10 @@ import * as vscode from 'vscode'; import { API as GitAPI } from './typings/git'; import { publishRepository } from './publish'; +import { combinedDisposable } from './util'; -export function registerCommands(gitAPI: GitAPI): vscode.Disposable[] { - const disposables = []; +export function registerCommands(gitAPI: GitAPI): vscode.Disposable { + const disposables: vscode.Disposable[] = []; disposables.push(vscode.commands.registerCommand('github.publish', async () => { try { @@ -18,5 +19,5 @@ export function registerCommands(gitAPI: GitAPI): vscode.Disposable[] { } })); - return disposables; + return combinedDisposable(disposables); } diff --git a/extensions/github/src/extension.ts b/extensions/github/src/extension.ts index ae43f9177f..982468853a 100644 --- a/extensions/github/src/extension.ts +++ b/extensions/github/src/extension.ts @@ -3,23 +3,43 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; +import { Disposable, ExtensionContext, extensions } from 'vscode'; import { GithubRemoteSourceProvider } from './remoteSourceProvider'; import { GitExtension } from './typings/git'; import { registerCommands } from './commands'; import { GithubCredentialProviderManager } from './credentialProvider'; +import { dispose, combinedDisposable } from './util'; +import { GithubPushErrorHandler } from './pushErrorHandler'; -export async function activate(context: vscode.ExtensionContext) { - const gitExtension = vscode.extensions.getExtension('vscode.git')!.exports; +export function activate(context: ExtensionContext): void { + const disposables = new Set(); + context.subscriptions.push(combinedDisposable(disposables)); - try { - const gitAPI = gitExtension.getAPI(1); + const init = () => { + try { + const gitAPI = gitExtension.getAPI(1); - context.subscriptions.push(...registerCommands(gitAPI)); - context.subscriptions.push(gitAPI.registerRemoteSourceProvider(new GithubRemoteSourceProvider(gitAPI))); - context.subscriptions.push(new GithubCredentialProviderManager(gitAPI)); - } catch (err) { - console.error('Could not initialize GitHub extension'); - console.warn(err); - } + disposables.add(registerCommands(gitAPI)); + disposables.add(gitAPI.registerRemoteSourceProvider(new GithubRemoteSourceProvider(gitAPI))); + disposables.add(new GithubCredentialProviderManager(gitAPI)); + disposables.add(gitAPI.registerPushErrorHandler(new GithubPushErrorHandler())); + } catch (err) { + console.error('Could not initialize GitHub extension'); + console.warn(err); + } + }; + + const onDidChangeGitExtensionEnablement = (enabled: boolean) => { + if (!enabled) { + dispose(disposables); + disposables.clear(); + } else { + init(); + } + }; + + + const gitExtension = extensions.getExtension('vscode.git')!.exports; + context.subscriptions.push(gitExtension.onDidChangeEnablement(onDidChangeGitExtensionEnablement)); + onDidChangeGitExtensionEnablement(gitExtension.enabled); } diff --git a/extensions/github/src/publish.ts b/extensions/github/src/publish.ts index fdb3bd90e9..d9ee2cff3b 100644 --- a/extensions/github/src/publish.ts +++ b/extensions/github/src/publish.ts @@ -5,10 +5,10 @@ import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; -import * as path from 'path'; -import { promises as fs } from 'fs'; import { API as GitAPI, Repository } from './typings/git'; import { getOctokit } from './auth'; +import { TextEncoder } from 'util'; +import { basename } from 'path'; const localize = nls.loadMessageBundle(); @@ -28,10 +28,12 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) return; } - let folder: vscode.WorkspaceFolder; + let folder: vscode.Uri; - if (vscode.workspace.workspaceFolders.length === 1) { - folder = vscode.workspace.workspaceFolders[0]; + if (repository) { + folder = repository.rootUri; + } else if (vscode.workspace.workspaceFolders.length === 1) { + folder = vscode.workspace.workspaceFolders[0].uri; } else { const picks = vscode.workspace.workspaceFolders.map(folder => ({ label: folder.name, folder })); const placeHolder = localize('pick folder', "Pick a folder to publish to GitHub"); @@ -41,14 +43,14 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) return; } - folder = pick.folder; + folder = pick.folder.uri; } let quickpick = vscode.window.createQuickPick(); quickpick.ignoreFocusOut = true; quickpick.placeholder = 'Repository Name'; - quickpick.value = folder.name; + quickpick.value = basename(folder.fsPath); quickpick.show(); quickpick.busy = true; @@ -97,37 +99,49 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) return; } - quickpick = vscode.window.createQuickPick(); - quickpick.placeholder = localize('ignore', "Select which files should be included in the repository."); - quickpick.canSelectMany = true; - quickpick.show(); + if (!repository) { + const gitignore = vscode.Uri.joinPath(folder, '.gitignore'); + let shouldGenerateGitignore = false; - try { - quickpick.busy = true; - - const repositoryPath = folder.uri.fsPath; - const currentPath = path.join(repositoryPath); - const children = await fs.readdir(currentPath); - quickpick.items = children.map(name => ({ label: name })); - quickpick.selectedItems = quickpick.items; - quickpick.busy = false; - - const result = await Promise.race([ - new Promise(c => quickpick.onDidAccept(() => c(quickpick.selectedItems))), - new Promise(c => quickpick.onDidHide(() => c(undefined))) - ]); - - if (!result) { - return; + try { + await vscode.workspace.fs.stat(gitignore); + } catch (err) { + shouldGenerateGitignore = true; } - const ignored = new Set(children); - result.forEach(c => ignored.delete(c.label)); + if (shouldGenerateGitignore) { + quickpick = vscode.window.createQuickPick(); + quickpick.placeholder = localize('ignore', "Select which files should be included in the repository."); + quickpick.canSelectMany = true; + quickpick.show(); - const raw = [...ignored].map(i => `/${i}`).join('\n'); - await fs.writeFile(path.join(repositoryPath, '.gitignore'), raw, 'utf8'); - } finally { - quickpick.dispose(); + try { + quickpick.busy = true; + + const children = (await vscode.workspace.fs.readDirectory(folder)).map(([name]) => name); + quickpick.items = children.map(name => ({ label: name })); + quickpick.selectedItems = quickpick.items; + quickpick.busy = false; + + const result = await Promise.race([ + new Promise(c => quickpick.onDidAccept(() => c(quickpick.selectedItems))), + new Promise(c => quickpick.onDidHide(() => c(undefined))) + ]); + + if (!result) { + return; + } + + const ignored = new Set(children); + result.forEach(c => ignored.delete(c.label)); + + const raw = [...ignored].map(i => `/${i}`).join('\n'); + const encoder = new TextEncoder(); + await vscode.workspace.fs.writeFile(gitignore, encoder.encode(raw)); + } finally { + quickpick.dispose(); + } + } } const githubRepository = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, cancellable: false, title: 'Publish to GitHub' }, async progress => { @@ -143,7 +157,7 @@ export async function publishRepository(gitAPI: GitAPI, repository?: Repository) progress.report({ message: 'Creating first commit', increment: 25 }); if (!repository) { - repository = await gitAPI.init(folder.uri) || undefined; + repository = await gitAPI.init(folder) || undefined; if (!repository) { return; diff --git a/extensions/github/src/pushErrorHandler.ts b/extensions/github/src/pushErrorHandler.ts new file mode 100644 index 0000000000..bc585d18b6 --- /dev/null +++ b/extensions/github/src/pushErrorHandler.ts @@ -0,0 +1,120 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { PushErrorHandler, GitErrorCodes, Repository, Remote } from './typings/git'; +import { window, ProgressLocation, commands, Uri } from 'vscode'; +import * as nls from 'vscode-nls'; +import { getOctokit } from './auth'; + +const localize = nls.loadMessageBundle(); + +async function handlePushError(repository: Repository, remote: Remote, refspec: string, owner: string, repo: string): Promise { + const yes = localize('create a fork', "Create Fork"); + const no = localize('no', "No"); + + const answer = await window.showInformationMessage(localize('fork', "You don't have permissions to push to '{0}/{1}' on GitHub. Would you like to create a fork and push to it instead?", owner, repo), yes, no); + + if (answer === no) { + return; + } + + const match = /^([^:]*):([^:]*)$/.exec(refspec); + const localName = match ? match[1] : refspec; + const remoteName = match ? match[2] : refspec; + + const [octokit, ghRepository] = await window.withProgress({ location: ProgressLocation.Notification, cancellable: false, title: localize('create fork', 'Create GitHub fork') }, async progress => { + progress.report({ message: localize('forking', "Forking '{0}/{1}'...", owner, repo), increment: 33 }); + + const octokit = await getOctokit(); + + // Issue: what if the repo already exists? + const res = await octokit.repos.createFork({ owner, repo }); + const ghRepository = res.data; + + progress.report({ message: localize('pushing', "Pushing changes..."), increment: 33 }); + + // Issue: what if there's already an `upstream` repo? + await repository.renameRemote(remote.name, 'upstream'); + + // Issue: what if there's already another `origin` repo? + await repository.addRemote('origin', ghRepository.clone_url); + await repository.fetch('origin', remoteName); + await repository.setBranchUpstream(localName, `origin/${remoteName}`); + await repository.push('origin', localName, true); + + return [octokit, ghRepository]; + }); + + // yield + (async () => { + const openInGitHub = localize('openingithub', "Open In GitHub"); + const createPR = localize('createpr', "Create PR"); + const action = await window.showInformationMessage(localize('done', "The fork '{0}' was successfully created on GitHub.", ghRepository.full_name), openInGitHub, createPR); + + if (action === openInGitHub) { + await commands.executeCommand('vscode.open', Uri.parse(ghRepository.html_url)); + } else if (action === createPR) { + const pr = await window.withProgress({ location: ProgressLocation.Notification, cancellable: false, title: localize('createghpr', "Creating GitHub Pull Request...") }, async _ => { + let title = `Update ${remoteName}`; + const head = repository.state.HEAD?.name; + + if (head) { + const commit = await repository.getCommit(head); + title = commit.message.replace(/\n.*$/m, ''); + } + + const res = await octokit.pulls.create({ + owner, + repo, + title, + head: `${ghRepository.owner.login}:${remoteName}`, + base: remoteName + }); + + await repository.setConfig(`branch.${localName}.remote`, 'upstream'); + await repository.setConfig(`branch.${localName}.merge`, `refs/heads/${remoteName}`); + await repository.setConfig(`branch.${localName}.github-pr-owner-number`, `${owner}#${repo}#${pr.number}`); + + return res.data; + }); + + const openPR = localize('openpr', "Open PR"); + const action = await window.showInformationMessage(localize('donepr', "The PR '{0}/{1}#{2}' was successfully created on GitHub.", owner, repo, pr.number), openPR); + + if (action === openPR) { + await commands.executeCommand('vscode.open', Uri.parse(pr.html_url)); + } + } + })(); +} + +export class GithubPushErrorHandler implements PushErrorHandler { + + async handlePushError(repository: Repository, remote: Remote, refspec: string, error: Error & { gitErrorCode: GitErrorCodes }): Promise { + if (error.gitErrorCode !== GitErrorCodes.PermissionDenied) { + return false; + } + + if (!remote.pushUrl) { + return false; + } + + const match = /^https:\/\/github\.com\/([^/]+)\/([^/]+)\.git/i.exec(remote.pushUrl) + || /^git@github\.com:([^/]+)\/([^/]+)\.git/i.exec(remote.pushUrl); + + if (!match) { + return false; + } + + if (/^:/.test(refspec)) { + return false; + } + + const [, owner, repo] = match; + await handlePushError(repository, remote, refspec, owner, repo); + + return true; + } +} diff --git a/extensions/github/src/typings/git.d.ts b/extensions/github/src/typings/git.d.ts index 2a8d1cdf9b..9593d8bc70 100644 --- a/extensions/github/src/typings/git.d.ts +++ b/extensions/github/src/typings/git.d.ts @@ -134,6 +134,8 @@ export interface CommitOptions { export interface BranchQuery { readonly remote?: boolean; + readonly pattern?: string; + readonly count?: number; readonly contains?: string; } @@ -221,6 +223,10 @@ export interface CredentialsProvider { getCredentials(host: Uri): ProviderResult; } +export interface PushErrorHandler { + handlePushError(repository: Repository, remote: Remote, refspec: string, error: Error & { gitErrorCode: GitErrorCodes }): Promise; +} + export type APIState = 'uninitialized' | 'initialized'; export interface API { @@ -237,6 +243,7 @@ export interface API { registerRemoteSourceProvider(provider: RemoteSourceProvider): Disposable; registerCredentialsProvider(provider: CredentialsProvider): Disposable; + registerPushErrorHandler(handler: PushErrorHandler): Disposable; } export interface GitExtension { @@ -274,6 +281,7 @@ export const enum GitErrorCodes { CantOpenResource = 'CantOpenResource', GitNotFound = 'GitNotFound', CantCreatePipe = 'CantCreatePipe', + PermissionDenied = 'PermissionDenied', CantAccessRemote = 'CantAccessRemote', RepositoryNotFound = 'RepositoryNotFound', RepositoryIsLocked = 'RepositoryIsLocked', diff --git a/extensions/github/src/util.ts b/extensions/github/src/util.ts new file mode 100644 index 0000000000..982ad7f07b --- /dev/null +++ b/extensions/github/src/util.ts @@ -0,0 +1,24 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; + +export function dispose(arg: vscode.Disposable | Iterable): void { + if (arg instanceof vscode.Disposable) { + arg.dispose(); + } else { + for (const disposable of arg) { + disposable.dispose(); + } + } +} + +export function combinedDisposable(disposables: Iterable): vscode.Disposable { + return { + dispose() { + dispose(disposables); + } + }; +} diff --git a/extensions/json/package.json b/extensions/json/package.json index af713956bf..73902a8ec4 100644 --- a/extensions/json/package.json +++ b/extensions/json/package.json @@ -48,14 +48,14 @@ "JSON with Comments" ], "extensions": [ - ".hintrc", - ".babelrc", ".jsonc", ".eslintrc", ".eslintrc.json", ".jsfmtrc", ".jshintrc", - ".swcrc" + ".swcrc", + ".hintrc", + ".babelrc" ], "configuration": "./language-configuration.json" } diff --git a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json index 0df87e91d3..e8feaa75fa 100644 --- a/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json +++ b/extensions/markdown-basics/syntaxes/markdown.tmLanguage.json @@ -4,7 +4,7 @@ "If you want to provide a fix or improvement, please create a pull request against the original repository.", "Once accepted there, we are happy to receive an update request." ], - "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/a7e4475626a505472c76d18e0a1b3cfcf46f9cf9", + "version": "https://github.com/microsoft/vscode-markdown-tm-grammar/commit/4be9cb335581f3559166c319607dac9100103083", "name": "Markdown", "scopeName": "text.html.markdown", "patterns": [ @@ -1963,12 +1963,12 @@ "name": "markup.fenced_code.block.markdown" }, "heading": { - "match": "(?:^|\\G)[ ]{0,3}((#{1,6})\\s+(?=[\\S[^#]]).*?\\s*(#{1,6})?)$\\n?", + "match": "(?:^|\\G)[ ]{0,3}(#{1,6}\\s+(.*?)(\\s+#{1,6})?\\s*)$", "captures": { "1": { "patterns": [ { - "match": "(#{6})\\s+(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "match": "(#{6})\\s+(.*?)(?:\\s+(#+))?\\s*$", "name": "heading.6.markdown", "captures": { "1": { @@ -1983,7 +1983,7 @@ } }, { - "match": "(#{5})\\s+(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "match": "(#{5})\\s+(.*?)(?:\\s+(#+))?\\s*$", "name": "heading.5.markdown", "captures": { "1": { @@ -1998,7 +1998,7 @@ } }, { - "match": "(#{4})\\s+(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "match": "(#{4})\\s+(.*?)(?:\\s+(#+))?\\s*$", "name": "heading.4.markdown", "captures": { "1": { @@ -2013,7 +2013,7 @@ } }, { - "match": "(#{3})\\s+(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "match": "(#{3})\\s+(.*?)(?:\\s+(#+))?\\s*$", "name": "heading.3.markdown", "captures": { "1": { @@ -2028,7 +2028,7 @@ } }, { - "match": "(#{2})\\s+(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "match": "(#{2})\\s+(.*?)(?:\\s+(#+))?\\s*$", "name": "heading.2.markdown", "captures": { "1": { @@ -2043,7 +2043,7 @@ } }, { - "match": "(#{1})\\s+(?=[\\S[^#]])(.*?)\\s*(\\s+#+)?$\\n?", + "match": "(#{1})\\s+(.*?)(?:\\s+(#+))?\\s*$", "name": "heading.1.markdown", "captures": { "1": { diff --git a/extensions/markdown-basics/test/colorize-results/test_md.json b/extensions/markdown-basics/test/colorize-results/test_md.json index 6963f66e79..1fee128741 100644 --- a/extensions/markdown-basics/test/colorize-results/test_md.json +++ b/extensions/markdown-basics/test/colorize-results/test_md.json @@ -33,7 +33,18 @@ } }, { - "c": " #", + "c": " ", + "t": "text.html.markdown markup.heading.markdown heading.1.markdown", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6" + } + }, + { + "c": "#", "t": "text.html.markdown markup.heading.markdown heading.1.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", @@ -77,7 +88,18 @@ } }, { - "c": " ##", + "c": " ", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6" + } + }, + { + "c": "##", "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", @@ -2189,7 +2211,18 @@ } }, { - "c": " ##", + "c": " ", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6" + } + }, + { + "c": "##", "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", @@ -2343,7 +2376,18 @@ } }, { - "c": " ##", + "c": " ", + "t": "text.html.markdown markup.heading.markdown heading.2.markdown", + "r": { + "dark_plus": "markup.heading: #569CD6", + "light_plus": "markup.heading: #800000", + "dark_vs": "markup.heading: #569CD6", + "light_vs": "markup.heading: #800000", + "hc_black": "markup.heading: #6796E6" + } + }, + { + "c": "##", "t": "text.html.markdown markup.heading.markdown heading.2.markdown punctuation.definition.heading.markdown", "r": { "dark_plus": "markup.heading: #569CD6", diff --git a/extensions/markdown-language-features/media/markdown.css b/extensions/markdown-language-features/media/markdown.css index 64414ab281..c10a0198f2 100644 --- a/extensions/markdown-language-features/media/markdown.css +++ b/extensions/markdown-language-features/media/markdown.css @@ -11,6 +11,21 @@ html, body { word-wrap: break-word; } +body { + padding-top: 1em; +} + +/* Reset margin top for elements */ +h1, h2, h3, h4, h5, h6, +p, ol, ul, pre { + margin-top: 0; +} + +h2, h3, h4, h5, h6 { + font-weight: normal; + margin-bottom: 0.2em; +} + #code-csp-warning { position: fixed; top: 0; @@ -112,6 +127,20 @@ textarea:focus { outline-offset: -1px; } +p { + margin-bottom: 1.5em; +} + +/* don't space 2 paragraphs too far apart */ +p + p { + margin-top: -0.8em; +} + +ul, +ol { + margin-bottom: 1.5em; +} + hr { border: 0; height: 2px; @@ -123,9 +152,6 @@ h1 { line-height: 1.2; border-bottom-width: 1px; border-bottom-style: solid; -} - -h1, h2, h3 { font-weight: normal; } diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index becb8ad271..0cdddf075d 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -79,7 +79,7 @@ "editor/title": [ { "command": "markdown.showPreviewToSide", - "when": "editorLangId == markdown", + "when": "editorLangId == markdown && !notebookEditorFocused", "alt": "markdown.showPreview", "group": "navigation" }, @@ -115,23 +115,23 @@ { "command": "markdown.showPreview", "when": "resourceLangId == markdown", - "group": "navigation" + "group": "1_open" } ], "commandPalette": [ { "command": "markdown.showPreview", - "when": "editorLangId == markdown", + "when": "editorLangId == markdown && !notebookEditorFocused", "group": "navigation" }, { "command": "markdown.showPreviewToSide", - "when": "editorLangId == markdown", + "when": "editorLangId == markdown && !notebookEditorFocused", "group": "navigation" }, { "command": "markdown.showLockedPreviewToSide", - "when": "editorLangId == markdown", + "when": "editorLangId == markdown && !notebookEditorFocused", "group": "navigation" }, { @@ -141,7 +141,7 @@ }, { "command": "markdown.showPreviewSecuritySelector", - "when": "editorLangId == markdown" + "when": "editorLangId == markdown && !notebookEditorFocused" }, { "command": "markdown.showPreviewSecuritySelector", @@ -153,7 +153,7 @@ }, { "command": "markdown.preview.refresh", - "when": "editorLangId == markdown" + "when": "editorLangId == markdown && !notebookEditorFocused" }, { "command": "markdown.preview.refresh", @@ -166,13 +166,13 @@ "command": "markdown.showPreview", "key": "shift+ctrl+v", "mac": "shift+cmd+v", - "when": "editorLangId == markdown" + "when": "editorLangId == markdown && !notebookEditorFocused" }, { "command": "markdown.showPreviewToSide", "key": "ctrl+k v", "mac": "cmd+k v", - "when": "editorLangId == markdown" + "when": "editorLangId == markdown && !notebookEditorFocused" } ], "configuration": { diff --git a/extensions/markdown-language-features/src/commands/openDocumentLink.ts b/extensions/markdown-language-features/src/commands/openDocumentLink.ts index 7bc765259b..8b9e50c85d 100644 --- a/extensions/markdown-language-features/src/commands/openDocumentLink.ts +++ b/extensions/markdown-language-features/src/commands/openDocumentLink.ts @@ -13,9 +13,9 @@ import { isMarkdownFile } from '../util/file'; export interface OpenDocumentLinkArgs { - readonly path: string; + readonly path: {}; readonly fragment: string; - readonly fromResource: any; + readonly fromResource: {}; } enum OpenMarkdownLinks { @@ -29,13 +29,22 @@ export class OpenDocumentLinkCommand implements Command { public static createCommandUri( fromResource: vscode.Uri, - path: string, + path: vscode.Uri, fragment: string, ): vscode.Uri { + const toJson = (uri: vscode.Uri) => { + return { + scheme: uri.scheme, + authority: uri.authority, + path: uri.path, + fragment: uri.fragment, + query: uri.query, + }; + }; return vscode.Uri.parse(`command:${OpenDocumentLinkCommand.id}?${encodeURIComponent(JSON.stringify({ - path: encodeURIComponent(path), + path: toJson(path), fragment, - fromResource: encodeURIComponent(fromResource.toString(true)), + fromResource: toJson(fromResource), }))}`); } @@ -43,26 +52,29 @@ export class OpenDocumentLinkCommand implements Command { private readonly engine: MarkdownEngine ) { } - public execute(args: OpenDocumentLinkArgs) { - const fromResource = vscode.Uri.parse(decodeURIComponent(args.fromResource)); - const targetPath = decodeURIComponent(args.path); - const column = this.getViewColumn(fromResource); - return this.tryOpen(targetPath, args, column).catch(() => { - if (targetPath && extname(targetPath) === '') { - return this.tryOpen(targetPath + '.md', args, column); - } - const targetResource = vscode.Uri.file(targetPath); - return Promise.resolve(undefined) - .then(() => vscode.commands.executeCommand('vscode.open', targetResource, column)) - .then(() => undefined); - }); + public async execute(args: OpenDocumentLinkArgs) { + return OpenDocumentLinkCommand.execute(this.engine, args); } - private async tryOpen(path: string, args: OpenDocumentLinkArgs, column: vscode.ViewColumn) { - const resource = vscode.Uri.file(path); + public static async execute(engine: MarkdownEngine, args: OpenDocumentLinkArgs) { + const fromResource = vscode.Uri.parse('').with(args.fromResource); + const targetResource = vscode.Uri.parse('').with(args.path); + const column = this.getViewColumn(fromResource); + try { + return await this.tryOpen(engine, targetResource, args, column); + } catch { + if (extname(targetResource.path) === '') { + return this.tryOpen(engine, targetResource.with({ path: targetResource.path + '.md' }), args, column); + } + await vscode.commands.executeCommand('vscode.open', targetResource, column); + return undefined; + } + } + + private static async tryOpen(engine: MarkdownEngine, resource: vscode.Uri, args: OpenDocumentLinkArgs, column: vscode.ViewColumn) { if (vscode.window.activeTextEditor && isMarkdownFile(vscode.window.activeTextEditor.document)) { - if (!path || vscode.window.activeTextEditor.document.uri.fsPath === resource.fsPath) { - return this.tryRevealLine(vscode.window.activeTextEditor, args.fragment); + if (vscode.window.activeTextEditor.document.uri.fsPath === resource.fsPath) { + return this.tryRevealLine(engine, vscode.window.activeTextEditor, args.fragment); } } @@ -73,10 +85,10 @@ export class OpenDocumentLinkCommand implements Command { return vscode.workspace.openTextDocument(resource) .then(document => vscode.window.showTextDocument(document, column)) - .then(editor => this.tryRevealLine(editor, args.fragment)); + .then(editor => this.tryRevealLine(engine, editor, args.fragment)); } - private getViewColumn(resource: vscode.Uri): vscode.ViewColumn { + private static getViewColumn(resource: vscode.Uri): vscode.ViewColumn { const config = vscode.workspace.getConfiguration('markdown', resource); const openLinks = config.get('links.openLocation', OpenMarkdownLinks.currentGroup); switch (openLinks) { @@ -88,18 +100,22 @@ export class OpenDocumentLinkCommand implements Command { } } - private async tryRevealLine(editor: vscode.TextEditor, fragment?: string) { + private static async tryRevealLine(engine: MarkdownEngine, editor: vscode.TextEditor, fragment?: string) { if (editor && fragment) { - const toc = new TableOfContentsProvider(this.engine, editor.document); + const toc = new TableOfContentsProvider(engine, editor.document); const entry = await toc.lookup(fragment); if (entry) { - return editor.revealRange(new vscode.Range(entry.line, 0, entry.line, 0), vscode.TextEditorRevealType.AtTop); + const lineStart = new vscode.Range(entry.line, 0, entry.line, 0); + editor.selection = new vscode.Selection(lineStart.start, lineStart.end); + return editor.revealRange(lineStart, vscode.TextEditorRevealType.AtTop); } const lineNumberFragment = fragment.match(/^L(\d+)$/i); if (lineNumberFragment) { const line = +lineNumberFragment[1] - 1; if (!isNaN(line)) { - return editor.revealRange(new vscode.Range(line, 0, line, 0), vscode.TextEditorRevealType.AtTop); + const lineStart = new vscode.Range(line, 0, line, 0); + editor.selection = new vscode.Selection(lineStart.start, lineStart.end); + return editor.revealRange(lineStart, vscode.TextEditorRevealType.AtTop); } } } diff --git a/extensions/markdown-language-features/src/extension.ts b/extensions/markdown-language-features/src/extension.ts index 9c3f4b7f81..0317d61698 100644 --- a/extensions/markdown-language-features/src/extension.ts +++ b/extensions/markdown-language-features/src/extension.ts @@ -15,9 +15,9 @@ import MarkdownWorkspaceSymbolProvider from './features/workspaceSymbolProvider' import { Logger } from './logger'; import { MarkdownEngine } from './markdownEngine'; import { getMarkdownExtensionContributions } from './markdownExtensions'; -import { ExtensionContentSecurityPolicyArbiter, PreviewSecuritySelector, ContentSecurityPolicyArbiter } from './security'; -import { loadDefaultTelemetryReporter, TelemetryReporter } from './telemetryReporter'; +import { ContentSecurityPolicyArbiter, ExtensionContentSecurityPolicyArbiter, PreviewSecuritySelector } from './security'; import { githubSlugifier } from './slugify'; +import { loadDefaultTelemetryReporter, TelemetryReporter } from './telemetryReporter'; export function activate(context: vscode.ExtensionContext) { @@ -33,7 +33,7 @@ export function activate(context: vscode.ExtensionContext) { const contentProvider = new MarkdownContentProvider(engine, context, cspArbiter, contributions, logger); const symbolProvider = new MDDocumentSymbolProvider(engine); - const previewManager = new MarkdownPreviewManager(contentProvider, logger, contributions); + const previewManager = new MarkdownPreviewManager(contentProvider, logger, contributions, engine); context.subscriptions.push(previewManager); context.subscriptions.push(registerMarkdownLanguageFeatures(symbolProvider, engine)); diff --git a/extensions/markdown-language-features/src/features/documentLinkProvider.ts b/extensions/markdown-language-features/src/features/documentLinkProvider.ts index e601c59b84..346d9e25ab 100644 --- a/extensions/markdown-language-features/src/features/documentLinkProvider.ts +++ b/extensions/markdown-language-features/src/features/documentLinkProvider.ts @@ -14,8 +14,7 @@ const localize = nls.loadMessageBundle(); function parseLink( document: vscode.TextDocument, link: string, - base: string -): { uri: vscode.Uri, tooltip?: string } { +): { uri: vscode.Uri, tooltip?: string } | undefined { const externalSchemeUri = getUriForLinkWithKnownExternalScheme(link); if (externalSchemeUri) { // Normalize VS Code links to target currently running version @@ -29,24 +28,43 @@ function parseLink( // Use a fake scheme to avoid parse warnings const tempUri = vscode.Uri.parse(`vscode-resource:${link}`); - let resourcePath = tempUri.path; - if (!tempUri.path && document.uri.scheme === 'file') { - resourcePath = document.uri.path; + let resourceUri: vscode.Uri | undefined; + if (!tempUri.path) { + resourceUri = document.uri; } else if (tempUri.path[0] === '/') { - const root = vscode.workspace.getWorkspaceFolder(document.uri); + const root = getWorkspaceFolder(document); if (root) { - resourcePath = path.join(root.uri.fsPath, tempUri.path); + resourceUri = vscode.Uri.joinPath(root, tempUri.path); } } else { - resourcePath = base ? path.join(base, tempUri.path) : tempUri.path; + if (document.uri.scheme === Schemes.untitled) { + const root = getWorkspaceFolder(document); + if (root) { + resourceUri = vscode.Uri.joinPath(root, tempUri.path); + } + } else { + const base = document.uri.with({ path: path.dirname(document.uri.fsPath) }); + resourceUri = vscode.Uri.joinPath(base, tempUri.path); + } } + if (!resourceUri) { + return undefined; + } + + resourceUri = resourceUri.with({ fragment: tempUri.fragment }); + return { - uri: OpenDocumentLinkCommand.createCommandUri(document.uri, resourcePath, tempUri.fragment), + uri: OpenDocumentLinkCommand.createCommandUri(document.uri, resourceUri, tempUri.fragment), tooltip: localize('documentLink.tooltip', 'Follow link') }; } +function getWorkspaceFolder(document: vscode.TextDocument) { + return vscode.workspace.getWorkspaceFolder(document.uri)?.uri + || vscode.workspace.workspaceFolders?.[0]?.uri; +} + function matchAll( pattern: RegExp, text: string @@ -62,7 +80,6 @@ function matchAll( function extractDocumentLink( document: vscode.TextDocument, - base: string, pre: number, link: string, matchIndex: number | undefined @@ -71,11 +88,14 @@ function extractDocumentLink( const linkStart = document.positionAt(offset); const linkEnd = document.positionAt(offset + link.length); try { - const { uri, tooltip } = parseLink(document, link, base); + const linkData = parseLink(document, link); + if (!linkData) { + return undefined; + } const documentLink = new vscode.DocumentLink( new vscode.Range(linkStart, linkEnd), - uri); - documentLink.tooltip = tooltip; + linkData.uri); + documentLink.tooltip = linkData.tooltip; return documentLink; } catch (e) { return undefined; @@ -91,27 +111,25 @@ export default class LinkProvider implements vscode.DocumentLinkProvider { document: vscode.TextDocument, _token: vscode.CancellationToken ): vscode.DocumentLink[] { - const base = document.uri.scheme === 'file' ? path.dirname(document.uri.fsPath) : ''; const text = document.getText(); return [ - ...this.providerInlineLinks(text, document, base), - ...this.provideReferenceLinks(text, document, base) + ...this.providerInlineLinks(text, document), + ...this.provideReferenceLinks(text, document) ]; } private providerInlineLinks( text: string, document: vscode.TextDocument, - base: string ): vscode.DocumentLink[] { const results: vscode.DocumentLink[] = []; for (const match of matchAll(this.linkPattern, text)) { - const matchImage = match[4] && extractDocumentLink(document, base, match[3].length + 1, match[4], match.index); + const matchImage = match[4] && extractDocumentLink(document, match[3].length + 1, match[4], match.index); if (matchImage) { results.push(matchImage); } - const matchLink = extractDocumentLink(document, base, match[1].length, match[5], match.index); + const matchLink = extractDocumentLink(document, match[1].length, match[5], match.index); if (matchLink) { results.push(matchLink); } @@ -122,7 +140,6 @@ export default class LinkProvider implements vscode.DocumentLinkProvider { private provideReferenceLinks( text: string, document: vscode.TextDocument, - base: string ): vscode.DocumentLink[] { const results: vscode.DocumentLink[] = []; @@ -159,8 +176,10 @@ export default class LinkProvider implements vscode.DocumentLinkProvider { for (const definition of definitions.values()) { try { - const { uri } = parseLink(document, definition.link, base); - results.push(new vscode.DocumentLink(definition.linkRange, uri)); + const linkData = parseLink(document, definition.link); + if (linkData) { + results.push(new vscode.DocumentLink(definition.linkRange, linkData.uri)); + } } catch (e) { // noop } diff --git a/extensions/markdown-language-features/src/features/preview.ts b/extensions/markdown-language-features/src/features/preview.ts index 13adb641a6..54296ad5f0 100644 --- a/extensions/markdown-language-features/src/features/preview.ts +++ b/extensions/markdown-language-features/src/features/preview.ts @@ -3,20 +3,20 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as vscode from 'vscode'; import * as path from 'path'; - -import { Logger } from '../logger'; -import { MarkdownContentProvider } from './previewContentProvider'; -import { Disposable } from '../util/dispose'; - +import * as vscode from 'vscode'; import * as nls from 'vscode-nls'; +import { OpenDocumentLinkCommand, resolveLinkToMarkdownFile } from '../commands/openDocumentLink'; +import { Logger } from '../logger'; +import { MarkdownContributionProvider } from '../markdownExtensions'; +import { Disposable } from '../util/dispose'; +import { isMarkdownFile } from '../util/file'; +import { normalizeResource, WebviewResourceProvider } from '../util/resources'; import { getVisibleLine, TopmostLineMonitor } from '../util/topmostLineMonitor'; import { MarkdownPreviewConfigurationManager } from './previewConfig'; -import { MarkdownContributionProvider } from '../markdownExtensions'; -import { isMarkdownFile } from '../util/file'; -import { resolveLinkToMarkdownFile } from '../commands/openDocumentLink'; -import { WebviewResourceProvider, normalizeResource } from '../util/resources'; +import { MarkdownContentProvider } from './previewContentProvider'; +import { MarkdownEngine } from '../markdownEngine'; + const localize = nls.loadMessageBundle(); interface WebviewMessage { @@ -123,6 +123,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { resource: vscode.Uri, startingScroll: StartingScrollLocation | undefined, private readonly delegate: MarkdownPreviewDelegate, + private readonly engine: MarkdownEngine, private readonly _contentProvider: MarkdownContentProvider, private readonly _previewConfigurations: MarkdownPreviewConfigurationManager, private readonly _logger: Logger, @@ -407,7 +408,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider { } } - vscode.commands.executeCommand('_markdown.openDocumentLink', { path: hrefPath, fragment, fromResource: this.resource }); + OpenDocumentLinkCommand.execute(this.engine, { path: hrefPath, fragment, fromResource: this.resource.toJSON() }); } //#region WebviewResourceProvider @@ -452,8 +453,9 @@ export class StaticMarkdownPreview extends Disposable implements ManagedMarkdown previewConfigurations: MarkdownPreviewConfigurationManager, logger: Logger, contributionProvider: MarkdownContributionProvider, + engine: MarkdownEngine, ): StaticMarkdownPreview { - return new StaticMarkdownPreview(webview, resource, contentProvider, previewConfigurations, logger, contributionProvider); + return new StaticMarkdownPreview(webview, resource, contentProvider, previewConfigurations, logger, contributionProvider, engine); } private readonly preview: MarkdownPreview; @@ -465,13 +467,14 @@ export class StaticMarkdownPreview extends Disposable implements ManagedMarkdown private readonly _previewConfigurations: MarkdownPreviewConfigurationManager, logger: Logger, contributionProvider: MarkdownContributionProvider, + engine: MarkdownEngine, ) { super(); this.preview = this._register(new MarkdownPreview(this._webviewPanel, resource, undefined, { getAdditionalState: () => { return {}; }, openPreviewLinkToMarkdownFile: () => { /* todo */ } - }, contentProvider, _previewConfigurations, logger, contributionProvider)); + }, engine, contentProvider, _previewConfigurations, logger, contributionProvider)); this._register(this._webviewPanel.onDidDispose(() => { this.dispose(); @@ -548,9 +551,10 @@ export class DynamicMarkdownPreview extends Disposable implements ManagedMarkdow logger: Logger, topmostLineMonitor: TopmostLineMonitor, contributionProvider: MarkdownContributionProvider, + engine: MarkdownEngine, ): DynamicMarkdownPreview { return new DynamicMarkdownPreview(webview, input, - contentProvider, previewConfigurations, logger, topmostLineMonitor, contributionProvider); + contentProvider, previewConfigurations, logger, topmostLineMonitor, contributionProvider, engine); } public static create( @@ -560,7 +564,8 @@ export class DynamicMarkdownPreview extends Disposable implements ManagedMarkdow previewConfigurations: MarkdownPreviewConfigurationManager, logger: Logger, topmostLineMonitor: TopmostLineMonitor, - contributionProvider: MarkdownContributionProvider + contributionProvider: MarkdownContributionProvider, + engine: MarkdownEngine, ): DynamicMarkdownPreview { const webview = vscode.window.createWebviewPanel( DynamicMarkdownPreview.viewType, @@ -568,7 +573,7 @@ export class DynamicMarkdownPreview extends Disposable implements ManagedMarkdow previewColumn, { enableFindWidget: true, }); return new DynamicMarkdownPreview(webview, input, - contentProvider, previewConfigurations, logger, topmostLineMonitor, contributionProvider); + contentProvider, previewConfigurations, logger, topmostLineMonitor, contributionProvider, engine); } private constructor( @@ -579,6 +584,7 @@ export class DynamicMarkdownPreview extends Disposable implements ManagedMarkdow private readonly _logger: Logger, private readonly _topmostLineMonitor: TopmostLineMonitor, private readonly _contributionProvider: MarkdownContributionProvider, + private readonly _engine: MarkdownEngine, ) { super(); @@ -612,7 +618,12 @@ export class DynamicMarkdownPreview extends Disposable implements ManagedMarkdow })); this._register(vscode.window.onDidChangeActiveTextEditor(editor => { - if (editor && isMarkdownFile(editor.document) && !this._locked && !this._preview.isPreviewOf(editor.document.uri)) { + // Only allow previewing normal text editors which have a viewColumn: See #101514 + if (typeof editor?.viewColumn === 'undefined') { + return; + } + + if (isMarkdownFile(editor.document) && !this._locked && !this._preview.isPreviewOf(editor.document.uri)) { const line = getVisibleLine(editor); this.update(editor.document.uri, line ? new StartingScrollLine(line) : undefined); } @@ -724,6 +735,7 @@ export class DynamicMarkdownPreview extends Disposable implements ManagedMarkdow this.update(link, fragment ? new StartingScrollFragment(fragment) : undefined); } }, + this._engine, this._contentProvider, this._previewConfigurations, this._logger, diff --git a/extensions/markdown-language-features/src/features/previewManager.ts b/extensions/markdown-language-features/src/features/previewManager.ts index c830d0ca12..77d8ef2bc4 100644 --- a/extensions/markdown-language-features/src/features/previewManager.ts +++ b/extensions/markdown-language-features/src/features/previewManager.ts @@ -5,10 +5,11 @@ import * as vscode from 'vscode'; import { Logger } from '../logger'; +import { MarkdownEngine } from '../markdownEngine'; import { MarkdownContributionProvider } from '../markdownExtensions'; -import { disposeAll, Disposable } from '../util/dispose'; +import { Disposable, disposeAll } from '../util/dispose'; import { TopmostLineMonitor } from '../util/topmostLineMonitor'; -import { DynamicMarkdownPreview, StaticMarkdownPreview, ManagedMarkdownPreview } from './preview'; +import { DynamicMarkdownPreview, ManagedMarkdownPreview, StaticMarkdownPreview } from './preview'; import { MarkdownPreviewConfigurationManager } from './previewConfig'; import { MarkdownContentProvider } from './previewContentProvider'; @@ -68,7 +69,8 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview public constructor( private readonly _contentProvider: MarkdownContentProvider, private readonly _logger: Logger, - private readonly _contributions: MarkdownContributionProvider + private readonly _contributions: MarkdownContributionProvider, + private readonly _engine: MarkdownEngine, ) { super(); this._register(vscode.window.registerWebviewPanelSerializer(DynamicMarkdownPreview.viewType, this)); @@ -145,7 +147,8 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview this._previewConfigurations, this._logger, this._topmostLineMonitor, - this._contributions); + this._contributions, + this._engine); this.registerDynamicPreview(preview); } @@ -160,7 +163,8 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview this._contentProvider, this._previewConfigurations, this._logger, - this._contributions); + this._contributions, + this._engine); this.registerStaticPreview(preview); } @@ -179,7 +183,8 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview this._previewConfigurations, this._logger, this._topmostLineMonitor, - this._contributions); + this._contributions, + this._engine); this.setPreviewActiveContext(true); this._activePreview = preview; diff --git a/extensions/markdown-language-features/src/markdownExtensions.ts b/extensions/markdown-language-features/src/markdownExtensions.ts index 073ca3e972..0b55d66793 100644 --- a/extensions/markdown-language-features/src/markdownExtensions.ts +++ b/extensions/markdown-language-features/src/markdownExtensions.ts @@ -70,7 +70,7 @@ export namespace MarkdownContributions { const previewStyles = getContributedStyles(contributions, extension); const previewScripts = getContributedScripts(contributions, extension); - const previewResourceRoots = previewStyles.length || previewScripts.length ? [vscode.Uri.file(extension.extensionPath)] : []; + const previewResourceRoots = previewStyles.length || previewScripts.length ? [extension.extensionUri] : []; const markdownItPlugins = getContributedMarkdownItPlugins(contributions, extension); return { diff --git a/extensions/markdown-language-features/src/test/documentLink.test.ts b/extensions/markdown-language-features/src/test/documentLink.test.ts new file mode 100644 index 0000000000..e86b93cb74 --- /dev/null +++ b/extensions/markdown-language-features/src/test/documentLink.test.ts @@ -0,0 +1,145 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import 'mocha'; +import * as vscode from 'vscode'; +import { joinLines } from './util'; + +const testFileA = workspaceFile('a.md'); + +function workspaceFile(...segments: string[]) { + return vscode.Uri.joinPath(vscode.workspace.workspaceFolders![0].uri, ...segments); +} + +async function getLinksForFile(file: vscode.Uri): Promise { + return (await vscode.commands.executeCommand('vscode.executeLinkProvider', file))!; +} + +suite('Markdown Document links', () => { + + teardown(async () => { + await vscode.commands.executeCommand('workbench.action.closeAllEditors'); + }); + + test('Should navigate to markdown file', async () => { + await withFileContents(testFileA, '[b](b.md)'); + + const [link] = await getLinksForFile(testFileA); + await executeLink(link); + + assertActiveDocumentUri(workspaceFile('b.md')); + }); + + test('Should navigate to markdown file with leading ./', async () => { + await withFileContents(testFileA, '[b](./b.md)'); + + const [link] = await getLinksForFile(testFileA); + await executeLink(link); + + assertActiveDocumentUri(workspaceFile('b.md')); + }); + + test('Should navigate to markdown file with leading /', async () => { + await withFileContents(testFileA, '[b](./b.md)'); + + const [link] = await getLinksForFile(testFileA); + await executeLink(link); + + assertActiveDocumentUri(workspaceFile('b.md')); + }); + + test('Should navigate to markdown file without file extension', async () => { + await withFileContents(testFileA, '[b](b)'); + + const [link] = await getLinksForFile(testFileA); + await executeLink(link); + + assertActiveDocumentUri(workspaceFile('b.md')); + }); + + test('Should navigate to markdown file in directory', async () => { + await withFileContents(testFileA, '[b](sub/c)'); + + const [link] = await getLinksForFile(testFileA); + await executeLink(link); + + assertActiveDocumentUri(workspaceFile('sub', 'c.md')); + }); + + test('Should navigate to fragment by title in file', async () => { + await withFileContents(testFileA, '[b](sub/c#second)'); + + const [link] = await getLinksForFile(testFileA); + await executeLink(link); + + assertActiveDocumentUri(workspaceFile('sub', 'c.md')); + assert.strictEqual(vscode.window.activeTextEditor!.selection.start.line, 1); + }); + + test('Should navigate to fragment by line', async () => { + await withFileContents(testFileA, '[b](sub/c#L2)'); + + const [link] = await getLinksForFile(testFileA); + await executeLink(link); + + assertActiveDocumentUri(workspaceFile('sub', 'c.md')); + assert.strictEqual(vscode.window.activeTextEditor!.selection.start.line, 1); + }); + + test('Should navigate to fragment within current file', async () => { + await withFileContents(testFileA, joinLines( + '[](a#header)', + '[](#header)', + '# Header')); + + const links = await getLinksForFile(testFileA); + { + await executeLink(links[0]); + assertActiveDocumentUri(workspaceFile('a.md')); + assert.strictEqual(vscode.window.activeTextEditor!.selection.start.line, 2); + } + { + await executeLink(links[1]); + assertActiveDocumentUri(workspaceFile('a.md')); + assert.strictEqual(vscode.window.activeTextEditor!.selection.start.line, 2); + } + }); + + test('Should navigate to fragment within current untitled file', async () => { + const testFile = workspaceFile('x.md').with({ scheme: 'untitled' }); + await withFileContents(testFile, joinLines( + '[](#second)', + '# Second')); + + const [link] = await getLinksForFile(testFile); + await executeLink(link); + + assertActiveDocumentUri(testFile); + assert.strictEqual(vscode.window.activeTextEditor!.selection.start.line, 1); + }); +}); + + +function assertActiveDocumentUri(expectedUri: vscode.Uri) { + assert.strictEqual( + vscode.window.activeTextEditor!.document.uri.fsPath, + expectedUri.fsPath + ); +} + +async function withFileContents(file: vscode.Uri, contents: string): Promise { + const document = await vscode.workspace.openTextDocument(file); + const editor = await vscode.window.showTextDocument(document); + await editor.edit(edit => { + edit.replace(new vscode.Range(0, 0, 1000, 0), contents); + }); +} + +async function executeLink(link: vscode.DocumentLink) { + const args = JSON.parse(decodeURIComponent(link.target!.query)); + await vscode.commands.executeCommand(link.target!.path, args); +} + diff --git a/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts b/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts index d1dec19917..c97c8fbeae 100644 --- a/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts +++ b/extensions/markdown-language-features/src/test/documentLinkProvider.test.ts @@ -10,7 +10,7 @@ import LinkProvider from '../features/documentLinkProvider'; import { InMemoryDocument } from './inMemoryDocument'; -const testFileName = vscode.Uri.file('test.md'); +const testFile = vscode.Uri.joinPath(vscode.workspace.workspaceFolders![0].uri, 'x.md'); const noopToken = new class implements vscode.CancellationToken { private _onCancellationRequestedEmitter = new vscode.EventEmitter(); @@ -20,7 +20,7 @@ const noopToken = new class implements vscode.CancellationToken { }; function getLinksForFile(fileContents: string) { - const doc = new InMemoryDocument(testFileName, fileContents); + const doc = new InMemoryDocument(testFile, fileContents); const provider = new LinkProvider(); return provider.provideDocumentLinks(doc, noopToken); } @@ -118,24 +118,24 @@ suite('markdown.DocumentLinkProvider', () => { const links = getLinksForFile('[![alt text](image.jpg)](https://example.com)'); assert.strictEqual(links.length, 2); const [link1, link2] = links; - assertRangeEqual(link1.range, new vscode.Range(0,13,0,22)); - assertRangeEqual(link2.range, new vscode.Range(0,25,0,44)); + assertRangeEqual(link1.range, new vscode.Range(0, 13, 0, 22)); + assertRangeEqual(link2.range, new vscode.Range(0, 25, 0, 44)); } { const links = getLinksForFile('[![a]( whitespace.jpg )]( https://whitespace.com )'); assert.strictEqual(links.length, 2); const [link1, link2] = links; - assertRangeEqual(link1.range, new vscode.Range(0,7,0,21)); - assertRangeEqual(link2.range, new vscode.Range(0,26,0,48)); + assertRangeEqual(link1.range, new vscode.Range(0, 7, 0, 21)); + assertRangeEqual(link2.range, new vscode.Range(0, 26, 0, 48)); } { const links = getLinksForFile('[![a](img1.jpg)](file1.txt) text [![a](img2.jpg)](file2.txt)'); assert.strictEqual(links.length, 4); const [link1, link2, link3, link4] = links; - assertRangeEqual(link1.range, new vscode.Range(0,6,0,14)); - assertRangeEqual(link2.range, new vscode.Range(0,17,0,26)); - assertRangeEqual(link3.range, new vscode.Range(0,39,0,47)); - assertRangeEqual(link4.range, new vscode.Range(0,50,0,59)); + assertRangeEqual(link1.range, new vscode.Range(0, 6, 0, 14)); + assertRangeEqual(link2.range, new vscode.Range(0, 17, 0, 26)); + assertRangeEqual(link3.range, new vscode.Range(0, 39, 0, 47)); + assertRangeEqual(link4.range, new vscode.Range(0, 50, 0, 59)); } }); }); diff --git a/extensions/markdown-language-features/src/test/test-fixtures/marker.txt b/extensions/markdown-language-features/src/test/test-fixtures/marker.txt deleted file mode 100644 index a4c9ad4073..0000000000 --- a/extensions/markdown-language-features/src/test/test-fixtures/marker.txt +++ /dev/null @@ -1 +0,0 @@ -DO NOT DELETE, USED BY INTEGRATION TESTS diff --git a/extensions/markdown-language-features/src/test/util.ts b/extensions/markdown-language-features/src/test/util.ts new file mode 100644 index 0000000000..5fb48ed01f --- /dev/null +++ b/extensions/markdown-language-features/src/test/util.ts @@ -0,0 +1,8 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import * as os from 'os'; + +export const joinLines = (...args: string[]) => + args.join(os.platform() === 'win32' ? '\r\n' : '\n'); diff --git a/extensions/markdown-language-features/src/util/links.ts b/extensions/markdown-language-features/src/util/links.ts index 8cce8221e8..1f74343119 100644 --- a/extensions/markdown-language-features/src/util/links.ts +++ b/extensions/markdown-language-features/src/util/links.ts @@ -9,6 +9,7 @@ export const Schemes = { http: 'http:', https: 'https:', file: 'file:', + untitled: 'untitled', mailto: 'mailto:', data: 'data:', vscode: 'vscode:', diff --git a/extensions/markdown-language-features/test-workspace/a.md b/extensions/markdown-language-features/test-workspace/a.md new file mode 100644 index 0000000000..9d70918067 --- /dev/null +++ b/extensions/markdown-language-features/test-workspace/a.md @@ -0,0 +1,4 @@ +[b](b) +[b](b.md) +[b](./b.md) +[b](/b.md) diff --git a/extensions/markdown-language-features/test-workspace/b.md b/extensions/markdown-language-features/test-workspace/b.md new file mode 100644 index 0000000000..730f53ee6c --- /dev/null +++ b/extensions/markdown-language-features/test-workspace/b.md @@ -0,0 +1,3 @@ +# b + +[](./a) \ No newline at end of file diff --git a/extensions/markdown-language-features/test-workspace/sub/c.md b/extensions/markdown-language-features/test-workspace/sub/c.md new file mode 100644 index 0000000000..f5c9bec43a --- /dev/null +++ b/extensions/markdown-language-features/test-workspace/sub/c.md @@ -0,0 +1,6 @@ +# First +# Second + +[b](/b.md) +[b](../b.md) +[b](./../b.md) diff --git a/extensions/markdown-language-features/test-workspace/sub/d.md b/extensions/markdown-language-features/test-workspace/sub/d.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/extensions/microsoft-authentication/src/AADHelper.ts b/extensions/microsoft-authentication/src/AADHelper.ts index 6fc1013a21..230e720db6 100644 --- a/extensions/microsoft-authentication/src/AADHelper.ts +++ b/extensions/microsoft-authentication/src/AADHelper.ts @@ -26,7 +26,7 @@ interface IToken { refreshToken: string; account: { - displayName: string; + label: string; id: string; }; scope: string; @@ -48,7 +48,8 @@ interface IStoredSession { refreshToken: string; scope: string; // Scopes are alphabetized and joined with a space account: { - displayName: string, + label?: string; + displayName?: string, id: string } } @@ -101,7 +102,7 @@ export class AzureActiveDirectoryService { accessToken: undefined, refreshToken: session.refreshToken, account: { - displayName: session.account.displayName, + label: session.account.label ?? session.account.displayName!, id: session.account.id }, scope: session.scope, @@ -437,7 +438,7 @@ export class AzureActiveDirectoryService { scope, sessionId: existingId || `${claims.tid}/${(claims.oid || (claims.altsecid || '' + claims.ipd || ''))}/${uuid()}`, account: { - displayName: claims.email || claims.unique_name || 'user@example.com', + label: claims.email || claims.unique_name || 'user@example.com', id: `${claims.tid}/${(claims.oid || (claims.altsecid || '' + claims.ipd || ''))}` } }; diff --git a/extensions/microsoft-authentication/src/extension.ts b/extensions/microsoft-authentication/src/extension.ts index 874640c78c..4089548e6f 100644 --- a/extensions/microsoft-authentication/src/extension.ts +++ b/extensions/microsoft-authentication/src/extension.ts @@ -19,27 +19,42 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(vscode.authentication.registerAuthenticationProvider({ id: 'microsoft', - displayName: 'Microsoft', + label: 'Microsoft', supportsMultipleAccounts: true, onDidChangeSessions: onDidChangeSessions.event, getSessions: () => Promise.resolve(loginService.sessions), login: async (scopes: string[]) => { try { + /* __GDPR__ + "login" : { } + */ telemetryReporter.sendTelemetryEvent('login'); + const session = await loginService.login(scopes.sort().join(' ')); onDidChangeSessions.fire({ added: [session.id], removed: [], changed: [] }); return session; } catch (e) { + /* __GDPR__ + "loginFailed" : { } + */ telemetryReporter.sendTelemetryEvent('loginFailed'); + throw e; } }, logout: async (id: string) => { try { + /* __GDPR__ + "logout" : { } + */ telemetryReporter.sendTelemetryEvent('logout'); + await loginService.logout(id); onDidChangeSessions.fire({ added: [], removed: [id], changed: [] }); } catch (e) { + /* __GDPR__ + "logoutFailed" : { } + */ telemetryReporter.sendTelemetryEvent('logoutFailed'); } } diff --git a/extensions/package.json b/extensions/package.json index e54ff1794b..7c668c9744 100644 --- a/extensions/package.json +++ b/extensions/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "description": "Dependencies shared by all extensions", "dependencies": { - "typescript": "3.9.5" + "typescript": "3.9.6" }, "scripts": { "postinstall": "node ./postinstall" diff --git a/extensions/theme-defaults/themes/hc_black.json b/extensions/theme-defaults/themes/hc_black.json index 73309c34b4..436dfa5291 100644 --- a/extensions/theme-defaults/themes/hc_black.json +++ b/extensions/theme-defaults/themes/hc_black.json @@ -122,5 +122,11 @@ "foreground": "#CBEDCB", } } - ] + ], + "semanticTokenColors": { + "newOperator": "#FFFFFF", + "stringLiteral": "#ce9178", + "customLiteral": "#DCDCAA", + "numberLiteral": "#b5cea8", + } } diff --git a/extensions/theme-defaults/themes/light_defaults.json b/extensions/theme-defaults/themes/light_defaults.json index a22dd21b4a..3fad0bc14f 100644 --- a/extensions/theme-defaults/themes/light_defaults.json +++ b/extensions/theme-defaults/themes/light_defaults.json @@ -20,10 +20,9 @@ "statusBarItem.remoteBackground": "#16825D", "sideBarSectionHeader.background": "#0000", "sideBarSectionHeader.border": "#61616130", - "notebook.cellFocusBackground": "#c8ddf150", + "notebook.focusedCellBackground": "#c8ddf150", "notebook.cellBorderColor": "#dae3e9", - "notebook.outputContainerBackgroundColor": "#c8ddf150", - "notebook.focusedCellShadow": "#00315040" + "notebook.outputContainerBackgroundColor": "#c8ddf150" }, "semanticHighlighting": true } diff --git a/extensions/vscode-web-playground/src/exampleFiles.ts b/extensions/vscode-web-playground/src/exampleFiles.ts index f382391bfc..5663067a36 100644 --- a/extensions/vscode-web-playground/src/exampleFiles.ts +++ b/extensions/vscode-web-playground/src/exampleFiles.ts @@ -282,7 +282,7 @@ Or discuss debug adapters on Gitter: You can now 'step through' the 'readme.md' file, set and hit breakpoints, and run into exceptions (if the word exception appears in a line). -![Mock Debug](images/mock-debug.gif) +![Mock Debug](file.jpg) ## Build and Run @@ -302,3 +302,9 @@ export function getImageFile(): Uint8Array { const data = atob(`/9j/4AAQSkZJRgABAQAASABIAAD/2wCEAA4ODg4ODhcODhchFxcXIS0hISEhLTktLS0tLTlFOTk5OTk5RUVFRUVFRUVSUlJSUlJgYGBgYGxsbGxsbGxsbGwBERISGxkbLxkZL3FMP0xxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcf/AABEIAFYAZAMBIgACEQEDEQH/xAB1AAACAwEBAQAAAAAAAAAAAAAABAMFBgIBBxAAAgIBAwMCBQQCAwAAAAAAAQIAAxEEBSESMUFRcRMiIzJhFIGRoQbBQlKxAQEBAQEAAAAAAAAAAAAAAAABAgADEQEBAQADAQEAAAAAAAAAAAAAARESITECQf/aAAwDAQACEQMRAD8A2LEZkLc/bKxbdYEHWoyfEze56zXpqRTTYUyPHiVrY2TVZyMzhFZMg8iYE6jcVXAusY98KMnj2lhRu+4aLoGuTNTYPV5APnyDNyPFp6EY3EsO3kxnVVLZVg8z2tw9YsXkGQpcbGIbxHQzep0vw8Jgc8n28CJJRY30lBwzf1iaa2ku/HmMV01VW/k/6hh0abTDTafpPcTytmckEewjeosAqJEj0yDo6yO/rFLzoGME5nIAXtGSM9uwnjLn8zFECw7QneITMWouR7gj9/Ep94061bjXa32WDGfzOGuCXKy9/wDc0FlFe5aX4OpHJHBHcSfT4w246bWJar6MsCwKnp9DOF0r6XRiu5snvg9hNK217vQeih0tXwzcED895R7voNfWoN9gOT2QH/2T3mHrda3Y+p9ppZuSV/qR0j6r+5ju2oun2ypOwCAASGikISzdySf5lxLsAdRPpIqw91xC/wDHvGbAAh88RnSVCjT9b8E/MYsguerTqWuYKo8k4ESTcttsPSmoQ+zCZPWPbvWqsvLE0IxCL4wPP7xEW7TXeKsvaGABOMdLef2ky7ejevX0tBWy5Qhh6jmS9IIxPm6XazbW69K56M/aeRibnSaqyytWtGCfE0+tazDhrHpCdixT5EJSWD1BPkcjsYxpN21FWEcdu0dG3hl8rIX0YqUgDqkSrq/0+6oyfOOZT7hqxqLMKMk8ARfS0fqGatAR04yCY+u3OpLt38e0rQl0tzsFrc8rxj0lqqDHMzujIXUMGPI4mjS1MTCvG8gRLddYE2811n5nHTJ9RaAsztzZ1AZhlX9fBi0VWgWzbSqahfpWfa/iSnatMuqOpVgVPIHGMzc6erS3aQVOoZSMFTK19i2pTwGA9Axx/E58b+K2M8lP6/Urp6BkA5Y+OPE112nrIFeOw8RMajQ7dWU0iAH8TyrVG0mw8EypMFuk7K9TS5RGJHiEYsuUtmEWO1KO2RGDRSVJzj1MiQhOQIx8QEYK5hGpUUJVc1lTgcDjEe1FPxqGQHBZSMiQqa8/Z38xgOoHB/aIfJNVZrdFqirsVbsfzLXT7+UQLYmcDHBlh/k+g+KP1dOCV+4efcTNbdtGq3CxQiMKyeX7CGqxqtDuK7lYK2BXnAz3JMuNZoPpDAyV5zHNt2bRbcA1S/Pjljyf7jerWxx0V4wQeZgynxrUXoUnIif629GJY595cptr1N9XJYjOfEi1G3LYMLgH1m04qxelrAtnj/qZYIvUPpMcHwYtTT8FzVaMN6+sslqVF6gcQ1sRivPccwjS314+bGYRBnqzws6FhUfL7CQ8gdI7+TDIHHgcSVGBYRznMXfUL2J5ngPUOYCpfM2tiq1tnUpVRnMe0DGtAKyQIw+mU4GJCKmrPy+I6V0lxYYIzxOCtdjZyVIMRqtPsYx8RT37+sdRhsFlHzcyC0J0kmcfqFX5cxC7VAk4OPUQtM+UVtYf7vH8iKP8SnKg5U9xHQwsGV7jxF9QnWACMEcgwlUjT4ZUE+YRRLGRehwciEpLRMAAT6SALlIQkF4kl7HEIQLwuQfac9RPeEJi5H3TruvvmEJo1QOcgGQuvVg+sITM8rDKeDHVItXkQhKgqM6esnJEIQlJf//Z`); return Uint8Array.from([...data].map(x => x.charCodeAt(0))); } + +// encoded from 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя' +export const windows1251File = Uint8Array.from([192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255]); + +// encoded from '中国abc' +export const gbkFile = Uint8Array.from([214, 208, 185, 250, 97, 98, 99]); diff --git a/extensions/vscode-web-playground/src/memfs.ts b/extensions/vscode-web-playground/src/memfs.ts index f3a407443d..b3c4538f9e 100644 --- a/extensions/vscode-web-playground/src/memfs.ts +++ b/extensions/vscode-web-playground/src/memfs.ts @@ -29,7 +29,7 @@ import { Uri, workspace, } from 'vscode'; -import { largeTSFile, getImageFile, debuggableFile } from './exampleFiles'; +import { largeTSFile, getImageFile, debuggableFile, windows1251File, gbkFile } from './exampleFiles'; export class File implements FileStat { @@ -123,6 +123,19 @@ export class MemFS implements FileSystemProvider, FileSearchProvider, TextSearch this.writeFile(Uri.parse(`memfs:/sample-folder/xyz/UPPER.txt`), textEncoder.encode('UPPER'), { create: true, overwrite: true }); this.writeFile(Uri.parse(`memfs:/sample-folder/xyz/upper.txt`), textEncoder.encode('upper'), { create: true, overwrite: true }); this.writeFile(Uri.parse(`memfs:/sample-folder/xyz/def/foo.md`), textEncoder.encode('*MemFS*'), { create: true, overwrite: true }); + + // some files in different encodings + this.createDirectory(Uri.parse(`memfs:/sample-folder/encodings/`)); + this.writeFile( + Uri.parse(`memfs:/sample-folder/encodings/windows1251.txt`), + windows1251File, + { create: true, overwrite: true } + ); + this.writeFile( + Uri.parse(`memfs:/sample-folder/encodings/gbk.txt`), + gbkFile, + { create: true, overwrite: true } + ); } root = new Directory(Uri.parse('memfs:/'), ''); diff --git a/extensions/xml/package.json b/extensions/xml/package.json index 77e36951b7..3e5042df70 100644 --- a/extensions/xml/package.json +++ b/extensions/xml/package.json @@ -23,8 +23,8 @@ ".dita", ".ditamap", ".dtd", - ".ent", - ".mod", + ".ent", + ".mod", ".dtml", ".fsproj", ".fxml", diff --git a/extensions/yarn.lock b/extensions/yarn.lock index e0f5c7c4dd..d41a4ab48b 100644 --- a/extensions/yarn.lock +++ b/extensions/yarn.lock @@ -76,10 +76,10 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -typescript@3.9.5: - version "3.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" - integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== +typescript@3.9.6: + version "3.9.6" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a" + integrity sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw== wrappy@1: version "1.0.2" diff --git a/package.json b/package.json index bfaf2f236a..2ca2543771 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "preinstall": "node build/npm/preinstall.js", "postinstall": "node build/npm/postinstall.js", "compile": "gulp compile --max_old_space_size=4095", - "watch": "gulp watch --max_old_space_size=4095", + "watch": "concurrently \"npm:watch-client\" \"npm:watch-extensions\"", "watchd": "deemon yarn watch", "watch-webd": "deemon yarn watch-web", "kill-watchd": "deemon --kill yarn watch", @@ -22,6 +22,11 @@ "restart-watchd": "deemon --restart yarn watch", "restart-watch-webd": "deemon --restart yarn watch-web", "watch-client": "gulp watch-client --max_old_space_size=4095", + "watch-clientd": "deemon yarn watch-client", + "kill-watch-clientd": "deemon --kill yarn watch-client", + "watch-extensions": "gulp watch-extensions --max_old_space_size=4095", + "watch-extensionsd": "deemon yarn watch-extensions", + "kill-watch-extensionsd": "deemon --kill yarn watch-extensions", "mocha": "mocha test/unit/node/all.js --delay", "precommit": "node build/gulpfile.hygiene.js", "gulp": "gulp --max_old_space_size=8192", @@ -62,9 +67,9 @@ "html-query-plan": "git://github.com/anthonydresser/html-query-plan.git#2.6", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.3", - "iconv-lite-umd": "0.6.5", + "iconv-lite-umd": "0.6.8", "jquery": "3.5.0", - "jschardet": "2.1.1", + "jschardet": "2.2.1", "keytar": "^5.5.0", "minimist": "^1.2.5", "native-is-elevated": "0.4.1", @@ -84,10 +89,10 @@ "vscode-nsfw": "1.2.8", "vscode-oniguruma": "1.3.1", "vscode-proxy-agent": "^0.5.2", - "vscode-ripgrep": "^1.7.0", + "vscode-ripgrep": "^1.8.0", "vscode-sqlite3": "4.0.10", "vscode-textmate": "5.2.0", - "xterm": "4.7.0-beta.3", + "xterm": "4.8.1", "xterm-addon-search": "0.7.0", "xterm-addon-unicode11": "0.2.0", "xterm-addon-webgl": "0.7.0", @@ -124,12 +129,13 @@ "ansi-colors": "^3.2.3", "asar": "^0.14.0", "chromium-pickle-js": "^0.2.0", + "concurrently": "^5.2.0", "copy-webpack-plugin": "^4.5.2", "cson-parser": "^1.3.3", "css-loader": "^3.2.0", "debounce": "^1.0.0", "deemon": "^1.4.0", - "electron": "7.3.2", + "electron": "8.3.3", "eslint": "6.8.0", "eslint-plugin-jsdoc": "^19.1.0", "event-stream": "3.3.4", @@ -157,7 +163,7 @@ "gulp-untar": "^0.0.7", "gulp-vinyl-zip": "^2.1.2", "husky": "^0.13.1", - "innosetup": "5.6.1", + "innosetup": "6.0.5", "is": "^3.1.0", "istanbul-lib-coverage": "^3.0.0", "istanbul-lib-instrument": "^4.0.0", diff --git a/remote/package.json b/remote/package.json index 0892761f3b..363a97d80c 100644 --- a/remote/package.json +++ b/remote/package.json @@ -20,9 +20,9 @@ "html-query-plan": "git://github.com/anthonydresser/html-query-plan.git#2.6", "http-proxy-agent": "^2.1.0", "https-proxy-agent": "^2.2.3", - "iconv-lite-umd": "0.6.5", + "iconv-lite-umd": "0.6.8", "jquery": "3.5.0", - "jschardet": "2.1.1", + "jschardet": "2.2.1", "minimist": "^1.2.5", "native-watchdog": "1.3.0", "ng2-charts": "^1.6.0", @@ -36,9 +36,9 @@ "vscode-nsfw": "1.2.8", "vscode-oniguruma": "1.3.1", "vscode-proxy-agent": "^0.5.2", - "vscode-ripgrep": "^1.7.0", + "vscode-ripgrep": "^1.8.0", "vscode-textmate": "5.2.0", - "xterm": "4.7.0-beta.3", + "xterm": "4.8.1", "xterm-addon-search": "0.7.0", "xterm-addon-unicode11": "0.2.0", "xterm-addon-webgl": "0.7.0", diff --git a/remote/web/package.json b/remote/web/package.json index 8de1ac76b2..cef07e7f5d 100644 --- a/remote/web/package.json +++ b/remote/web/package.json @@ -14,8 +14,8 @@ "ansi_up": "^3.0.0", "chart.js": "^2.6.0", "html-query-plan": "git://github.com/anthonydresser/html-query-plan.git#2.6", - "iconv-lite-umd": "0.6.5", - "jschardet": "2.1.1", + "iconv-lite-umd": "0.6.8", + "jschardet": "2.2.1", "jquery": "3.5.0", "ng2-charts": "^1.6.0", "reflect-metadata": "^0.1.8", @@ -25,7 +25,7 @@ "slickgrid": "github:anthonydresser/SlickGrid#2.3.33", "vscode-oniguruma": "1.3.1", "vscode-textmate": "5.2.0", - "xterm": "4.7.0-beta.3", + "xterm": "4.8.1", "xterm-addon-search": "0.7.0", "xterm-addon-unicode11": "0.2.0", "xterm-addon-webgl": "0.7.0", diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock index 6bc88bb10f..694113201c 100644 --- a/remote/web/yarn.lock +++ b/remote/web/yarn.lock @@ -182,10 +182,10 @@ htmlparser2@^3.10.0: inherits "^2.0.1" readable-stream "^3.1.1" -iconv-lite-umd@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.5.tgz#6a1f621a3b4d125f72feff813a9839e1ebd6c722" - integrity sha512-WDegH4al+e3n3jTOStRvm+jzDA3JMUQGgzdAsMxAgcgB0Oi72HjfdsoX08ieKsy3rKexXVjWZr41aOIUaCZnMg== +iconv-lite-umd@0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.8.tgz#5ad310ec126b260621471a2d586f7f37b9958ec0" + integrity sha512-zvXJ5gSwMC9JD3wDzH8CoZGc1pbiJn12Tqjk8BXYCnYz3hYL5GRjHW8LEykjXhV9WgNGI4rgpgHcbIiBfrRq6A== inherits@^2.0.1, inherits@^2.0.3: version "2.0.4" @@ -197,10 +197,10 @@ jquery@3.5.0: resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.0.tgz#9980b97d9e4194611c36530e7dc46a58d7340fc9" integrity sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ== -jschardet@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.1.1.tgz#af6f8fd0b3b0f5d46a8fd9614a4fce490575c184" - integrity sha512-pA5qG9Zwm8CBpGlK/lo2GE9jPxwqRgMV7Lzc/1iaPccw6v4Rhj8Zg2BTyrdmHmxlJojnbLupLeRnaPLsq03x6Q== +jschardet@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.2.1.tgz#03b0264669a90c7a5c436a68c5a7d4e4cb0c9823" + integrity sha512-Ks2JNuUJoc7PGaZ7bVFtSEvOcr0rBq6Q1J5/7+zKWLT+g+4zziL63O0jg7y2jxhzIa1LVsHUbPXrbaWmz9iwDw== lodash.clonedeep@^4.5.0: version "4.5.0" @@ -378,10 +378,10 @@ xterm-addon-webgl@0.7.0: resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0.tgz#a13732ac937170e53ce02ec91963da042c80614b" integrity sha512-PMWLgccAF31GulCYkQxIA8qwMI4q4UbRi5O/zwMnSJWBozB0yy84lX31ZhJeJhcrlEn1Vpcd+OUGPE8Z1hBjnw== -xterm@4.7.0-beta.3: - version "4.7.0-beta.3" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.7.0-beta.3.tgz#d8997f190430d750201717adf3857f6c8052f149" - integrity sha512-mL9VCB7Ql7KSql2PJmRQYba77mMXlliK9lVKd3XCDqtOYYWjg+CKKeNtFljIrPoiI25nvoqlkrv5dFuuIAR5hA== +xterm@4.8.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.8.1.tgz#155a1729a43e1a89b406524e22c5634339e39ca1" + integrity sha512-ax91ny4tI5eklqIfH79OUSGE2PUX2rGbwONmB6DfqpyhSZO8/cf++sqiaMWEVCMjACyMfnISW7C3gGMoNvNolQ== zone.js@^0.8.4: version "0.8.29" diff --git a/remote/yarn.lock b/remote/yarn.lock index 98809ebf37..0ed3f67039 100644 --- a/remote/yarn.lock +++ b/remote/yarn.lock @@ -376,10 +376,10 @@ https-proxy-agent@^4.0.0: agent-base "5" debug "4" -iconv-lite-umd@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.5.tgz#6a1f621a3b4d125f72feff813a9839e1ebd6c722" - integrity sha512-WDegH4al+e3n3jTOStRvm+jzDA3JMUQGgzdAsMxAgcgB0Oi72HjfdsoX08ieKsy3rKexXVjWZr41aOIUaCZnMg== +iconv-lite-umd@0.6.8: + version "0.6.8" + resolved "https://registry.yarnpkg.com/iconv-lite-umd/-/iconv-lite-umd-0.6.8.tgz#5ad310ec126b260621471a2d586f7f37b9958ec0" + integrity sha512-zvXJ5gSwMC9JD3wDzH8CoZGc1pbiJn12Tqjk8BXYCnYz3hYL5GRjHW8LEykjXhV9WgNGI4rgpgHcbIiBfrRq6A== inherits@^2.0.1, inherits@^2.0.3: version "2.0.4" @@ -420,10 +420,10 @@ jquery@3.5.0: resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.0.tgz#9980b97d9e4194611c36530e7dc46a58d7340fc9" integrity sha512-Xb7SVYMvygPxbFMpTFQiHh1J7HClEaThguL15N/Gg37Lri/qKyhRGZYzHRyLH8Stq3Aow0LsHO2O2ci86fCrNQ== -jschardet@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.1.1.tgz#af6f8fd0b3b0f5d46a8fd9614a4fce490575c184" - integrity sha512-pA5qG9Zwm8CBpGlK/lo2GE9jPxwqRgMV7Lzc/1iaPccw6v4Rhj8Zg2BTyrdmHmxlJojnbLupLeRnaPLsq03x6Q== +jschardet@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-2.2.1.tgz#03b0264669a90c7a5c436a68c5a7d4e4cb0c9823" + integrity sha512-Ks2JNuUJoc7PGaZ7bVFtSEvOcr0rBq6Q1J5/7+zKWLT+g+4zziL63O0jg7y2jxhzIa1LVsHUbPXrbaWmz9iwDw== jsonfile@^4.0.0: version "4.0.0" @@ -736,10 +736,10 @@ vscode-proxy-agent@^0.5.2: https-proxy-agent "^2.2.3" socks-proxy-agent "^4.0.1" -vscode-ripgrep@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.7.0.tgz#ec912e04aa29f7d73bcef04b7576b792f12c9b38" - integrity sha512-sQY/u0ymc9YMiPaSsMmdZSFQ6PTS2UxcGuiQkF7aoIezDxZcGE1sMarqftWEl9wYWYc9hElYm00WpoFgzj1oUg== +vscode-ripgrep@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/vscode-ripgrep/-/vscode-ripgrep-1.8.0.tgz#dfe7c2ae2a2032df8a8108765c2feef73474888a" + integrity sha512-/Q5XtePkTLLi8yplr5ai24pVEymRF62xH9xXrtj35GTaDCJg3zq1s1/L1UqhVbfNDv4OcMBYjyIAt/quEi3d5w== dependencies: https-proxy-agent "^4.0.0" proxy-from-env "^1.1.0" @@ -781,10 +781,10 @@ xterm-addon-webgl@0.7.0: resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0.tgz#a13732ac937170e53ce02ec91963da042c80614b" integrity sha512-PMWLgccAF31GulCYkQxIA8qwMI4q4UbRi5O/zwMnSJWBozB0yy84lX31ZhJeJhcrlEn1Vpcd+OUGPE8Z1hBjnw== -xterm@4.7.0-beta.3: - version "4.7.0-beta.3" - resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.7.0-beta.3.tgz#d8997f190430d750201717adf3857f6c8052f149" - integrity sha512-mL9VCB7Ql7KSql2PJmRQYba77mMXlliK9lVKd3XCDqtOYYWjg+CKKeNtFljIrPoiI25nvoqlkrv5dFuuIAR5hA== +xterm@4.8.1: + version "4.8.1" + resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.8.1.tgz#155a1729a43e1a89b406524e22c5634339e39ca1" + integrity sha512-ax91ny4tI5eklqIfH79OUSGE2PUX2rGbwONmB6DfqpyhSZO8/cf++sqiaMWEVCMjACyMfnISW7C3gGMoNvNolQ== yauzl@^2.9.2: version "2.10.0" diff --git a/resources/serverless/code-web.js b/resources/serverless/code-web.js index bee6ca5b71..998d88b884 100644 --- a/resources/serverless/code-web.js +++ b/resources/serverless/code-web.js @@ -20,32 +20,35 @@ const ansiColors = require('ansi-colors'); const extensions = require('../../build/lib/extensions'); const APP_ROOT = path.join(__dirname, '..', '..'); -const EXTENSIONS_ROOT = path.join(APP_ROOT, 'extensions'); +const BUILTIN_EXTENSIONS_ROOT = path.join(APP_ROOT, 'extensions'); +const BUILTIN_MARKETPLACE_EXTENSIONS_ROOT = path.join(APP_ROOT, '.build', 'builtInExtensions'); const WEB_MAIN = path.join(APP_ROOT, 'src', 'vs', 'code', 'browser', 'workbench', 'workbench-dev.html'); const args = minimist(process.argv, { boolean: [ - 'watch', 'no-launch', - 'help' + 'help', + 'verbose' ], string: [ 'scheme', 'host', 'port', - 'local_port' + 'local_port', + 'extension' ], }); if (args.help) { console.log( 'yarn web [options]\n' + - ' --watch Watch extensions that require browser specific builds\n' + - ' --no-launch Do not open VSCode web in the browser\n' + - ' --scheme Protocol (https or http)\n' + - ' --host Remote host\n' + - ' --port Remote/Local port\n' + - ' --local_port Local port override\n' + + ' --no-launch Do not open VSCode web in the browser\n' + + ' --scheme Protocol (https or http)\n' + + ' --host Remote host\n' + + ' --port Remote/Local port\n' + + ' --local_port Local port override\n' + + ' --extension Path of an extension to include\n' + + ' --verbose Print out more information\n' + ' --help\n' + '[Example]\n' + ' yarn web --scheme https --host example.com --port 8080 --local_port 30000' @@ -61,76 +64,124 @@ const AUTHORITY = process.env.VSCODE_AUTHORITY || `${HOST}:${PORT}`; const exists = (path) => util.promisify(fs.exists)(path); const readFile = (path) => util.promisify(fs.readFile)(path); +const readdir = (path) => util.promisify(fs.readdir)(path); +const readdirWithFileTypes = (path) => util.promisify(fs.readdir)(path, { withFileTypes: true }); -let unbuiltExensions = []; +async function getBuiltInExtensionInfos() { + const extensions = []; + /** @type {Object.} */ + const locations = {}; -async function initialize() { - const builtinExtensions = []; - - const children = await util.promisify(fs.readdir)(EXTENSIONS_ROOT, { withFileTypes: true }); - const folders = children.filter(c => !c.isFile()); - await Promise.all(folders.map(async folder => { - const folderName = folder.name; - const extensionPath = path.join(EXTENSIONS_ROOT, folderName); - - let children = []; - try { - children = await util.promisify(fs.readdir)(extensionPath); - } catch (error) { - console.log(error); - return; - } - - const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0]; - const readmePath = readme ? path.join(extensionPath, readme) : undefined; - const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0]; - const changelogPath = changelog ? path.join(extensionPath, changelog) : undefined; - - const packageJSONPath = path.join(EXTENSIONS_ROOT, folderName, 'package.json'); - if (await exists(packageJSONPath)) { - try { - let packageJSON = JSON.parse((await readFile(packageJSONPath)).toString()); - if (packageJSON.main && !packageJSON.browser) { - return; // unsupported - } - - if (packageJSON.browser) { - packageJSON.main = packageJSON.browser; - - let mainFilePath = path.join(EXTENSIONS_ROOT, folderName, packageJSON.browser); - if (path.extname(mainFilePath) !== '.js') { - mainFilePath += '.js'; - } - if (!await exists(mainFilePath)) { - unbuiltExensions.push(path.relative(EXTENSIONS_ROOT, mainFilePath)); + for (const extensionsRoot of [BUILTIN_EXTENSIONS_ROOT, BUILTIN_MARKETPLACE_EXTENSIONS_ROOT]) { + if (await exists(extensionsRoot)) { + const children = await readdirWithFileTypes(extensionsRoot); + await Promise.all(children.map(async child => { + if (child.isDirectory()) { + const extensionPath = path.join(extensionsRoot, child.name); + const info = await getBuiltInExtensionInfo(extensionPath); + if (info) { + extensions.push(info); + locations[path.basename(extensionPath)] = extensionPath; } } - packageJSON.extensionKind = ['web']; // enable for Web - - const packageNLSPath = path.join(folderName, 'package.nls.json'); - const packageNLSExists = await exists(path.join(EXTENSIONS_ROOT, packageNLSPath)); - if (packageNLSExists) { - packageJSON = extensions.translatePackageJSON(packageJSON, path.join(EXTENSIONS_ROOT, packageNLSPath)); // temporary, until fixed in core - } - builtinExtensions.push({ - extensionPath: folderName, - packageJSON, - packageNLSPath: packageNLSExists ? packageNLSPath : undefined, - readmePath, - changelogPath - }); - } catch (e) { - console.log(e); - } + })); } - })); - if (unbuiltExensions.length) { - fancyLog(`${ansiColors.yellow('Warning')}: Make sure to run ${ansiColors.cyan('yarn gulp watch-web')}\nCould not find the following browser main files: \n${unbuiltExensions.join('\n')}`); } - return builtinExtensions; + return { extensions, locations }; } -const builtinExtensionsPromise = initialize(); +async function getBuiltInExtensionInfo(extensionPath) { + const packageJSON = await getExtensionPackageJSON(extensionPath); + if (!packageJSON) { + return undefined; + } + const builtInExtensionPath = path.basename(extensionPath); + + let children = []; + try { + children = await readdir(extensionPath); + } catch (error) { + console.log(`Can not read extension folder ${extensionPath}: ${error}`); + return; + } + const readme = children.find(child => /^readme(\.txt|\.md|)$/i.test(child)); + const changelog = children.find(child => /^changelog(\.txt|\.md|)$/i.test(child)); + const packageJSONNLS = children.find(child => /^package.nls.json$/i.test(child)); + return { + extensionPath: builtInExtensionPath, + packageJSON, + packageNLSPath: packageJSONNLS ? `${builtInExtensionPath}/${packageJSONNLS}` : undefined, + readmePath: readme ? `${builtInExtensionPath}/${readme}` : undefined, + changelogPath: changelog ? `${builtInExtensionPath}/${changelog}` : undefined + }; +} + +async function getDefaultExtensionInfos() { + const extensions = []; + + /** @type {Object.} */ + const locations = {}; + + let extensionArg = args['extension']; + if (!extensionArg) { + return { extensions, locations } + } + + const extensionPaths = Array.isArray(extensionArg) ? extensionArg : [extensionArg]; + await Promise.all(extensionPaths.map(async extensionPath => { + extensionPath = path.resolve(process.cwd(), extensionPath); + const packageJSON = await getExtensionPackageJSON(extensionPath); + if (packageJSON) { + const extensionId = `${packageJSON.publisher}.${packageJSON.name}`; + extensions.push({ + packageJSON, + extensionLocation: { scheme: SCHEME, authority: AUTHORITY, path: `/extension/${extensionId}` } + }); + locations[extensionId] = extensionPath; + } + })); + return { extensions, locations }; +} + +async function getExtensionPackageJSON(extensionPath) { + + const packageJSONPath = path.join(extensionPath, 'package.json'); + if (await exists(packageJSONPath)) { + try { + let packageJSON = JSON.parse((await readFile(packageJSONPath)).toString()); + if (packageJSON.main && !packageJSON.browser) { + return; // unsupported + } + + if (packageJSON.browser) { + packageJSON.main = packageJSON.browser; + + let mainFilePath = path.join(extensionPath, packageJSON.browser); + if (path.extname(mainFilePath) !== '.js') { + mainFilePath += '.js'; + } + if (!await exists(mainFilePath)) { + fancyLog(`${ansiColors.yellow('Warning')}: Could not find ${mainFilePath}. Use ${ansiColors.cyan('yarn gulp watch-web')} to build the built-in extensions.`); + } + } + packageJSON.extensionKind = ['web']; // enable for Web + + const packageNLSPath = path.join(extensionPath, 'package.nls.json'); + const packageNLSExists = await exists(packageNLSPath); + if (packageNLSExists) { + packageJSON = extensions.translatePackageJSON(packageJSON, packageNLSPath); // temporary, until fixed in core + } + + return packageJSON; + } catch (e) { + console.log(e); + } + } + return undefined; +} + +const builtInExtensionsPromise = getBuiltInExtensionInfos(); +const defaultExtensionsPromise = getDefaultExtensionInfos(); const mapCallbackUriToRequestId = new Map(); @@ -158,9 +209,13 @@ const server = http.createServer((req, res) => { // static requests return handleStatic(req, res, parsedUrl); } - if (/^\/static-extension\//.test(pathname)) { - // static extension requests - return handleStaticExtension(req, res, parsedUrl); + if (/^\/extension\//.test(pathname)) { + // default extension requests + return handleExtension(req, res, parsedUrl); + } + if (/^\/builtin-extension\//.test(pathname)) { + // built-in extension requests + return handleBuiltInExtension(req, res, parsedUrl); } if (pathname === '/') { // main web @@ -211,13 +266,28 @@ function handleStatic(req, res, parsedUrl) { * @param {import('http').ServerResponse} res * @param {import('url').UrlWithParsedQuery} parsedUrl */ -function handleStaticExtension(req, res, parsedUrl) { - - // Strip `/static-extension/` from the path - const relativeFilePath = path.normalize(decodeURIComponent(parsedUrl.pathname.substr('/static-extension/'.length))); - - const filePath = path.join(EXTENSIONS_ROOT, relativeFilePath); +async function handleExtension(req, res, parsedUrl) { + // Strip `/extension/` from the path + const relativePath = decodeURIComponent(parsedUrl.pathname.substr('/extension/'.length)); + const filePath = getExtensionFilePath(relativePath, (await defaultExtensionsPromise).locations); + if (!filePath) { + return serveError(req, res, 400, `Bad request.`); + } + return serveFile(req, res, filePath); +} +/** + * @param {import('http').IncomingMessage} req + * @param {import('http').ServerResponse} res + * @param {import('url').UrlWithParsedQuery} parsedUrl + */ +async function handleBuiltInExtension(req, res, parsedUrl) { + // Strip `/builtin-extension/` from the path + const relativePath = decodeURIComponent(parsedUrl.pathname.substr('/builtin-extension/'.length)); + const filePath = getExtensionFilePath(relativePath, (await builtInExtensionsPromise).locations); + if (!filePath) { + return serveError(req, res, 400, `Bad request.`); + } return serveFile(req, res, filePath); } @@ -232,34 +302,44 @@ async function handleRoot(req, res) { if (match) { const qs = new URLSearchParams(match[1]); - let ghPath = qs.get('gh'); - if (ghPath) { - if (!ghPath.startsWith('/')) { - ghPath = '/' + ghPath; + let gh = qs.get('gh'); + if (gh) { + if (gh.startsWith('/')) { + gh = gh.substr(1); } - folderUri = { scheme: 'github', authority: 'HEAD', path: ghPath }; - } else { - let csPath = qs.get('cs'); - if (csPath) { - if (!csPath.startsWith('/')) { - csPath = '/' + csPath; + const [owner, repo, ...branch] = gh.split('/', 3); + folderUri = { scheme: 'github', authority: branch.join('/') || 'HEAD', path: `/${owner}/${repo}` }; + } else { + let cs = qs.get('cs'); + if (cs) { + if (cs.startsWith('/')) { + cs = cs.substr(1); } - folderUri = { scheme: 'codespace', authority: 'HEAD', path: csPath }; + + const [owner, repo, ...branch] = cs.split('/'); + folderUri = { scheme: 'codespace', authority: branch.join('/') || 'HEAD', path: `/${owner}/${repo}` }; } } } - const builtinExtensions = await builtinExtensionsPromise; + const { extensions: builtInExtensions } = await builtInExtensionsPromise; + const { extensions: staticExtensions } = await defaultExtensionsPromise; + + if (args.verbose) { + fancyLog(`${ansiColors.magenta('BuiltIn extensions')}: ${builtInExtensions.map(e => path.basename(e.extensionPath)).join(', ')}`); + fancyLog(`${ansiColors.magenta('Additional extensions')}: ${staticExtensions.map(e => path.basename(e.extensionLocation.path)).join(', ') || 'None'}`); + } const webConfigJSON = escapeAttribute(JSON.stringify({ folderUri: folderUri, - builtinExtensionsServiceUrl: `${SCHEME}://${AUTHORITY}/static-extension` + staticExtensions, + builtinExtensionsServiceUrl: `${SCHEME}://${AUTHORITY}/builtin-extension` })); - const data = (await util.promisify(fs.readFile)(WEB_MAIN)).toString() + const data = (await readFile(WEB_MAIN)).toString() .replace('{{WORKBENCH_WEB_CONFIGURATION}}', () => webConfigJSON) // use a replace function to avoid that regexp replace patterns ($&, $0, ...) are applied - .replace('{{WORKBENCH_BUILTIN_EXTENSIONS}}', () => escapeAttribute(JSON.stringify(builtinExtensions))) + .replace('{{WORKBENCH_BUILTIN_EXTENSIONS}}', () => escapeAttribute(JSON.stringify(builtInExtensions))) .replace('{{WEBVIEW_ENDPOINT}}', '') .replace('{{REMOTE_USER_DATA_URI}}', ''); @@ -368,6 +448,25 @@ function escapeAttribute(value) { return value.replace(/"/g, '"'); } +/** + * @param {string} relativePath + * @param {Object.} locations + * @returns {string | undefined} +*/ +function getExtensionFilePath(relativePath, locations) { + const firstSlash = relativePath.indexOf('/'); + if (firstSlash === -1) { + return undefined; + } + const extensionId = relativePath.substr(0, firstSlash); + + const extensionPath = locations[extensionId]; + if (!extensionPath) { + return undefined; + } + return path.join(extensionPath, relativePath.substr(firstSlash + 1)); +} + /** * @param {import('http').IncomingMessage} req * @param {import('http').ServerResponse} res @@ -419,10 +518,6 @@ async function serveFile(req, res, filePath, responseHeaders = Object.create(nul // Sanity checks filePath = path.normalize(filePath); // ensure no "." and ".." - if (filePath.indexOf(`${APP_ROOT}${path.sep}`) !== 0) { - // invalid location outside of APP_ROOT - return serveError(req, res, 400, `Bad request.`); - } const stat = await util.promisify(fs.stat)(filePath); diff --git a/scripts/test-integration.bat b/scripts/test-integration.bat index 1dc84176fc..69566719f4 100755 --- a/scripts/test-integration.bat +++ b/scripts/test-integration.bat @@ -49,7 +49,10 @@ REM if %errorlevel% neq 0 exit /b %errorlevel% REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --no-cached-data --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% REM if %errorlevel% neq 0 exit /b %errorlevel% -REM call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\markdown-language-features\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\markdown-language-features --extensionTestsPath=%~dp0\..\extensions\markdown-language-features\out\test --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --no-cached-data --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% . +REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\typescript-language-features\test-workspace --extensionDevelopmentPath=%~dp0\..\extensions\typescript-language-features --extensionTestsPath=%~dp0\..\extensions\typescript-language-features\out\test --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --no-cached-data --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% +REM if %errorlevel% neq 0 exit /b %errorlevel% + +REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\markdown-language-features\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\markdown-language-features --extensionTestsPath=%~dp0\..\extensions\markdown-language-features\out\test --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --no-cached-data --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% REM if %errorlevel% neq 0 exit /b %errorlevel% REM call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\emmet\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --no-cached-data --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% . diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index f92e3c44f1..f57534c448 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -46,8 +46,9 @@ fi # "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR # "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR # "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR +# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/typescript-language-features/test-workspace --extensionDevelopmentPath=$ROOT/extensions/typescript-language-features --extensionTestsPath=$ROOT/extensions/typescript-language-features/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR # "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/emmet/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR -"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $(mktemp -d 2>/dev/null) --enable-proposed-api=vscode.git --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHD +"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $(mktemp -d 2>/dev/null) --enable-proposed-api=vscode.git --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --no-cached-data --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/azurecore/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/azurecore --extensionTestsPath=$ROOT/extensions/azurecore/out/test --no-cached-data --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR diff --git a/src/bootstrap-window.js b/src/bootstrap-window.js index 313a4f8be1..eb23b2f989 100644 --- a/src/bootstrap-window.js +++ b/src/bootstrap-window.js @@ -22,8 +22,6 @@ } }(this, function () { const path = require.__$__nodeRequire('path'); - const webFrame = require.__$__nodeRequire('electron').webFrame; - const ipc = require.__$__nodeRequire('electron').ipcRenderer; const bootstrap = globalThis.MonacoBootstrap; /** @@ -36,7 +34,6 @@ /** * // configuration: INativeWindowConfiguration * @type {{ - * zoomLevel?: number, * extensionDevelopmentPath?: string[], * extensionTestsPath?: string, * userEnv?: { [key: string]: string | undefined }, @@ -45,12 +42,6 @@ * }} */ const configuration = JSON.parse(args['config'] || '{}') || {}; - // Apply zoom level early to avoid glitches - const zoomLevel = configuration.zoomLevel; - if (typeof zoomLevel === 'number' && zoomLevel !== 0) { - webFrame.setZoomLevel(zoomLevel); - } - // Error handler process.on('uncaughtException', function (error) { onUnexpectedError(error, enableDeveloperTools); @@ -96,28 +87,9 @@ const loaderConfig = { baseUrl: `${bootstrap.uriFromPath(configuration.appRoot)}/out`, 'vs/nls': nlsConfig, - nodeModules: [/*BUILD->INSERT_NODE_MODULES*/] + amdModulesPattern: /^(vs|sql)\//, // {{SQL CARBON EDIT}} include sql in regex }; - loaderConfig.nodeModules = loaderConfig.nodeModules.concat([ - '@angular/common', - '@angular/core', - '@angular/forms', - '@angular/platform-browser', - '@angular/platform-browser-dynamic', - '@angular/router', - 'rxjs/Observable', - 'rxjs/add/observable/fromPromise', - 'rxjs/Subject', - 'rxjs/Observer', - 'slickgrid/lib/jquery.event.drag-2.3.0', - 'slickgrid/lib/jquery-ui-1.9.2', - 'slickgrid/slick.core', - 'slickgrid/slick.grid', - 'slickgrid/slick.editors', - 'slickgrid/slick.dataview' - ]); - // cached data config if (configuration.nodeCachedDataDir) { loaderConfig.nodeCachedData = { @@ -178,6 +150,8 @@ * @returns {() => void} */ function registerDeveloperKeybindings(disallowReloadKeybinding) { + const ipcRenderer = globals().ipcRenderer; + const extractKey = function (e) { return [ e.ctrlKey ? 'ctrl-' : '', @@ -196,9 +170,9 @@ let listener = function (e) { const key = extractKey(e); if (key === TOGGLE_DEV_TOOLS_KB || key === TOGGLE_DEV_TOOLS_KB_ALT) { - ipc.send('vscode:toggleDevTools'); + ipcRenderer.send('vscode:toggleDevTools'); } else if (key === RELOAD_KB && !disallowReloadKeybinding) { - ipc.send('vscode:reloadWindow'); + ipcRenderer.send('vscode:reloadWindow'); } }; @@ -218,7 +192,8 @@ */ function onUnexpectedError(error, enableDeveloperTools) { if (enableDeveloperTools) { - ipc.send('vscode:openDevTools'); + const ipcRenderer = globals().ipcRenderer; + ipcRenderer.send('vscode:openDevTools'); } console.error(`[uncaught exception]: ${error}`); @@ -228,7 +203,16 @@ } } + /** + * @return {typeof import('./vs/base/parts/sandbox/electron-sandbox/globals')} + */ + function globals() { + // @ts-ignore (defined in globals.js) + return window.vscode; + } + return { - load + load, + globals }; })); diff --git a/src/main.js b/src/main.js index f6f59aceb0..183f9e072c 100644 --- a/src/main.js +++ b/src/main.js @@ -206,6 +206,8 @@ function configureCommandlineSwitchesSync(cliArgs) { ]; if (process.platform === 'linux') { + + // Force enable screen readers on Linux via this flag SUPPORTED_ELECTRON_SWITCHES.push('force-renderer-accessibility'); } @@ -223,6 +225,7 @@ function configureCommandlineSwitchesSync(cliArgs) { // Append Electron flags to Electron if (SUPPORTED_ELECTRON_SWITCHES.indexOf(argvKey) !== -1) { + // Color profile if (argvKey === 'force-color-profile') { if (argvValue) { diff --git a/src/sql/base/browser/ui/panel/panel.ts b/src/sql/base/browser/ui/panel/panel.ts index b9ba9a6ab4..73fc1814ea 100644 --- a/src/sql/base/browser/ui/panel/panel.ts +++ b/src/sql/base/browser/ui/panel/panel.ts @@ -14,7 +14,6 @@ import { KeyCode } from 'vs/base/common/keyCodes'; import { Disposable, DisposableStore } from 'vs/base/common/lifecycle'; import { Color } from 'vs/base/common/color'; import { isUndefinedOrNull } from 'vs/base/common/types'; -import * as map from 'vs/base/common/map'; import { firstIndex } from 'vs/base/common/arrays'; export interface ITabbedPanelStyles { @@ -285,7 +284,7 @@ export class TabbedPanel extends Disposable { } } if (!this._shownTabId && this._tabMap.size > 0) { - this.showTab(map.values(this._tabMap)[0].tab.identifier); + this.showTab(this._tabMap.values()[0].tab.identifier); } } diff --git a/src/sql/workbench/contrib/objectExplorer/test/browser/connectionTreeActions.test.ts b/src/sql/workbench/contrib/objectExplorer/test/browser/connectionTreeActions.test.ts index 25f9237179..6384b6454a 100644 --- a/src/sql/workbench/contrib/objectExplorer/test/browser/connectionTreeActions.test.ts +++ b/src/sql/workbench/contrib/objectExplorer/test/browser/connectionTreeActions.test.ts @@ -31,7 +31,7 @@ import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/t import { UNSAVED_GROUP_ID, mssqlProviderName } from 'sql/platform/connection/common/constants'; import { $ } from 'vs/base/browser/dom'; import { OEManageConnectionAction } from 'sql/workbench/contrib/dashboard/browser/dashboardActions'; -import { IViewsService, IView, ViewContainerLocation, ViewContainer } from 'vs/workbench/common/views'; +import { IViewsService, IView, ViewContainerLocation, ViewContainer, IViewPaneContainer } from 'vs/workbench/common/views'; import { ConsoleLogService } from 'vs/platform/log/common/log'; import { IProgressIndicator } from 'vs/platform/progress/common/progress'; import { IPaneComposite } from 'vs/workbench/common/panecomposite'; @@ -111,6 +111,9 @@ suite('SQL Connection Tree Action tests', () => { }); const viewsService = new class implements IViewsService { + getActiveViewPaneContainerWithId(viewContainerId: string): IViewPaneContainer { + throw new Error('Method not implemented.'); + } getViewProgressIndicator(id: string): IProgressIndicator { throw new Error('Method not implemented.'); } diff --git a/src/sql/workbench/services/accountManagement/browser/accountDialog.ts b/src/sql/workbench/services/accountManagement/browser/accountDialog.ts index d99ecd278c..8de2cb578a 100644 --- a/src/sql/workbench/services/accountManagement/browser/accountDialog.ts +++ b/src/sql/workbench/services/accountManagement/browser/accountDialog.ts @@ -18,7 +18,6 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { SplitView, Sizing } from 'vs/base/browser/ui/splitview/splitview'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { values } from 'vs/base/common/map'; import * as azdata from 'azdata'; @@ -44,6 +43,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ILayoutService } from 'vs/platform/layout/browser/layoutService'; import { Registry } from 'vs/platform/registry/common/platform'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; +import { Iterable } from 'vs/base/common/iterator'; export const VIEWLET_ID = 'workbench.view.accountpanel'; @@ -219,7 +219,7 @@ export class AccountDialog extends Modal { this._addAccountButton.label = localize('accountDialog.addConnection', "Add an account"); this._register(this._addAccountButton.onDidClick(async () => { - const vals = values(this._providerViewsMap); + const vals = Iterable.consume(this._providerViewsMap.values())[0]; let pickedValue: string; if (vals.length === 0) { @@ -291,8 +291,8 @@ export class AccountDialog extends Modal { private showSplitView() { this._splitViewContainer.hidden = false; this._noaccountViewContainer.hidden = true; - if (values(this._providerViewsMap).length > 0) { - const firstView = values(this._providerViewsMap)[0]; + if (Iterable.consume(this._providerViewsMap.values()).length > 0) { + const firstView = this._providerViewsMap.values()[0]; if (firstView instanceof AccountPanel) { firstView.setSelection([0]); firstView.focus(); @@ -301,7 +301,7 @@ export class AccountDialog extends Modal { } private isEmptyLinkedAccount(): boolean { - for (const provider of values(this._providerViewsMap)) { + for (const provider of this._providerViewsMap.values()) { const listView = provider.view; if (listView && listView.length > 0) { return false; @@ -312,7 +312,7 @@ export class AccountDialog extends Modal { public dispose(): void { super.dispose(); - for (const provider of values(this._providerViewsMap)) { + for (const provider of this._providerViewsMap.values()) { if (provider.addAccountAction) { provider.addAccountAction.dispose(); } diff --git a/src/sql/workbench/services/bootstrap/browser/bootstrapService.ts b/src/sql/workbench/services/bootstrap/browser/bootstrapService.ts index 4b0b57038b..64248c51e5 100644 --- a/src/sql/workbench/services/bootstrap/browser/bootstrapService.ts +++ b/src/sql/workbench/services/bootstrap/browser/bootstrapService.ts @@ -8,7 +8,6 @@ import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { IInstantiationService, _util, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IEditorInput } from 'vs/workbench/common/editor'; import { Trace } from 'vs/platform/instantiation/common/instantiationService'; -import { values } from 'vs/base/common/map'; import { IModuleFactory, IBootstrapParams } from 'sql/workbench/services/bootstrap/common/bootstrapParams'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { ILogService } from 'vs/platform/log/common/log'; @@ -16,7 +15,7 @@ import { ILogService } from 'vs/platform/log/common/log'; const selectorCounter = new Map(); export function providerIterator(service: IInstantiationService): Provider[] { - return Array.from(values(_util.serviceIds)).map(v => { + return Array.from(_util.serviceIds.values()).map(v => { let factory = () => { return (service)._getOrCreateServiceInstance(v, Trace.traceCreation(v)); }; diff --git a/src/sql/workbench/services/notebook/browser/models/notebookModel.ts b/src/sql/workbench/services/notebook/browser/models/notebookModel.ts index 58f678dc2a..fd30ac1e87 100644 --- a/src/sql/workbench/services/notebook/browser/models/notebookModel.ts +++ b/src/sql/workbench/services/notebook/browser/models/notebookModel.ts @@ -22,7 +22,6 @@ import { URI } from 'vs/base/common/uri'; import { ISingleNotebookEditOperation } from 'sql/workbench/api/common/sqlExtHostTypes'; import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile'; import { uriPrefixes } from 'sql/platform/connection/common/utils'; -import { keys } from 'vs/base/common/map'; import { ILogService } from 'vs/platform/log/common/log'; import { getErrorMessage } from 'vs/base/common/errors'; import { find, firstIndex } from 'vs/base/common/arrays'; @@ -213,7 +212,7 @@ export class NotebookModel extends Disposable implements INotebookModel { } public standardKernelsDisplayName(): string[] { - return Array.from(keys(this._kernelDisplayNameToNotebookProviderIds)); + return Array.from(this._kernelDisplayNameToNotebookProviderIds.keys()); } public get inErrorState(): boolean { diff --git a/src/sql/workbench/services/notebook/browser/notebookServiceImpl.ts b/src/sql/workbench/services/notebook/browser/notebookServiceImpl.ts index fc2a570171..8264b27a9a 100644 --- a/src/sql/workbench/services/notebook/browser/notebookServiceImpl.ts +++ b/src/sql/workbench/services/notebook/browser/notebookServiceImpl.ts @@ -27,7 +27,6 @@ import { IQueryManagementService } from 'sql/workbench/services/query/common/que import { ICellModel } from 'sql/workbench/services/notebook/browser/models/modelInterfaces'; import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle'; import { SqlNotebookProvider } from 'sql/workbench/services/notebook/browser/sql/sqlNotebookProvider'; -import { keys } from 'vs/base/common/map'; import { IFileService, IFileStatWithMetadata } from 'vs/platform/files/common/files'; import { Schemas } from 'vs/base/common/network'; import { ILogService } from 'vs/platform/log/common/log'; @@ -269,7 +268,7 @@ export class NotebookService extends Disposable implements INotebookService { } getSupportedFileExtensions(): string[] { - return Array.from(keys(this._fileToProviders)); + return Array.from(this._fileToProviders.keys()); } getProvidersForFileType(fileType: string): string[] { diff --git a/src/sql/workbench/services/query/common/queryManagement.ts b/src/sql/workbench/services/query/common/queryManagement.ts index 1a25b5d687..2d12ca42ab 100644 --- a/src/sql/workbench/services/query/common/queryManagement.ts +++ b/src/sql/workbench/services/query/common/queryManagement.ts @@ -10,7 +10,6 @@ import { IDisposable } from 'vs/base/common/lifecycle'; import * as azdata from 'azdata'; import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys'; import { Event, Emitter } from 'vs/base/common/event'; -import { keys } from 'vs/base/common/map'; import { assign } from 'vs/base/common/objects'; import { IAdsTelemetryService, ITelemetryEventProperties } from 'sql/platform/telemetry/common/telemetry'; import EditQueryRunner from 'sql/workbench/services/editData/common/editQueryRunner'; @@ -175,7 +174,7 @@ export class QueryManagementService implements IQueryManagementService { } public getRegisteredProviders(): string[] { - return Array.from(keys(this._requestHandlers)); + return Array.from(this._requestHandlers.keys()); } private addTelemetry(eventName: string, ownerUri: string, runOptions?: ExecutionPlanOptions): void { diff --git a/src/vs/base/browser/markdownRenderer.ts b/src/vs/base/browser/markdownRenderer.ts index c3909d78ac..7a7093aca6 100644 --- a/src/vs/base/browser/markdownRenderer.ts +++ b/src/vs/base/browser/markdownRenderer.ts @@ -221,10 +221,13 @@ export function renderMarkdown(markdown: IMarkdownString, options: MarkdownRende allowedSchemes.push(Schemas.command); } + // values that are too long will freeze the UI + let value = markdown.value ?? ''; + if (value.length > 100_000) { + value = `${value.substr(0, 100_000)}…`; + } const renderedMarkdown = marked.parse( - markdown.supportThemeIcons - ? markdownEscapeEscapedCodicons(markdown.value || '') - : (markdown.value || ''), + markdown.supportThemeIcons ? markdownEscapeEscapedCodicons(value) : value, markedOptions ); diff --git a/src/vs/base/browser/ui/actionbar/actionbar.ts b/src/vs/base/browser/ui/actionbar/actionbar.ts index 98cca67642..73752865a0 100644 --- a/src/vs/base/browser/ui/actionbar/actionbar.ts +++ b/src/vs/base/browser/ui/actionbar/actionbar.ts @@ -406,6 +406,7 @@ export interface IActionBarOptions { animated?: boolean; triggerKeys?: ActionTrigger; allowContextMenu?: boolean; + preventLoopNavigation?: boolean; } const defaultOptions: IActionBarOptions = { @@ -509,9 +510,9 @@ export class ActionBar extends Disposable implements IActionRunner { let eventHandled = true; if (event.equals(previousKey)) { - this.focusPrevious(); + eventHandled = this.focusPrevious(); } else if (event.equals(nextKey)) { - this.focusNext(); + eventHandled = this.focusNext(); } else if (event.equals(KeyCode.Escape)) { this._onDidCancel.fire(); } else if (this.isTriggerKeyEvent(event)) { @@ -724,7 +725,7 @@ export class ActionBar extends Disposable implements IActionRunner { if (selectFirst && typeof this.focusedItem === 'undefined') { // Focus the first enabled item - this.focusedItem = this.viewItems.length - 1; + this.focusedItem = -1; this.focusNext(); } else { if (index !== undefined) { @@ -735,7 +736,7 @@ export class ActionBar extends Disposable implements IActionRunner { } } - protected focusNext(): void { + protected focusNext(): boolean { if (typeof this.focusedItem === 'undefined') { this.focusedItem = this.viewItems.length - 1; } @@ -744,6 +745,11 @@ export class ActionBar extends Disposable implements IActionRunner { let item: IActionViewItem; do { + if (this.options.preventLoopNavigation && this.focusedItem + 1 >= this.viewItems.length) { + this.focusedItem = startIndex; + return false; + } + this.focusedItem = (this.focusedItem + 1) % this.viewItems.length; item = this.viewItems[this.focusedItem]; } while (this.focusedItem !== startIndex && !item.isEnabled()); @@ -753,9 +759,10 @@ export class ActionBar extends Disposable implements IActionRunner { } this.updateFocus(); + return true; } - protected focusPrevious(): void { + protected focusPrevious(): boolean { if (typeof this.focusedItem === 'undefined') { this.focusedItem = 0; } @@ -767,6 +774,11 @@ export class ActionBar extends Disposable implements IActionRunner { this.focusedItem = this.focusedItem - 1; if (this.focusedItem < 0) { + if (this.options.preventLoopNavigation) { + this.focusedItem = startIndex; + return false; + } + this.focusedItem = this.viewItems.length - 1; } @@ -778,6 +790,7 @@ export class ActionBar extends Disposable implements IActionRunner { } this.updateFocus(true); + return true; } protected updateFocus(fromRight?: boolean, preventScroll?: boolean): void { diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon.ttf b/src/vs/base/browser/ui/codicons/codicon/codicon.ttf index 691a9c3798ab212fc9c17e3dd0479ac2efb31f42..575a779d5dfe54d5c4dadd24032d0170ef45905d 100644 GIT binary patch delta 4941 zcmYM%dwkFJ9tZH(dl#D-yWcN{U6^fbW;eTU7-qQ+qh-u3!^%jaACiQmenoXu>Xb%K zr%WeDIyrKrPN#!zloLtf^C<~QJL0^)-hZ4u9?$Rl_xTsSU-u=lKHBiGauIISq@NJ?e3gzmMdL66Q9{ znbvJvblGy?_-?+yuX*15mSa*I1blS>2)z8*-X0|t5a%BPrziW5xFewO7j*JG=Un5f zUbUD1A8)pM{^)t0=f3c8p5+h!Mk?I#@`h|{J1mjjk9+vK&vgjS_PX^eUauXVxBht= zqaVQMy*xhVA9lI*Pdb>@W}SK8d|+$rHg|?krfUnnh1afccn$|KMHx6?>!?9>o$oBt66*jS?r`5-P#cLBb?fA|wzG zODBoq+xLPuI>3kTq9fl|C-|c?0udC5V1!@*3Q>e&l%d>x!KchM5Q8unLr{Ye7>Q9B zjWMXjIE=>x)L|kf;da#H4m4mYreOwVVm6vE2XiqG&A1D9qXi4F5cgma?!{ugVQ*J?{F61;~dVz;0OGO3-}2a;rbcB;3|H_HT)OXaRWC6;vt^mBfip6 z{G_vVkpKyj5DAw^iI#5CT@ocpk|jlYN~-jhG)b2X=_8qvCH*8@`b&=FNxl?HkrYdb zluDVDNxw#&A?f42I_5HdLViQHaJ)OvjygMEY`71)vhoVIQo-bHT5| z6A_4@PWG8b#pMVyP2m&9 z=}Hn9XDBXKn3;;p7G{>J#V$U$Q*kZB%vRtVGfj%?8)lB;N{5-NxaMKzDXxB)W`$Yq zeVrnPe8jW)3X>UGWE{*6m<5V?0<%ydo$(&U+<{r7FxH*mAK@zC*?o!`1+zpkw_uhk zW*N-=iunfPQp`MpF+*WiDm=vaAmDNi(t{_f6cZT6`6a>m zCRQtnV_c)en{lm@P{wsif*G9)l5}9)pd^g(F(t8#k1L5l9~d`Jh*bi{xrc;@8J|?r ziE*QnD0gG$cZ;0w?G?q60n@5jJYcpdmJyikiUkGcRfY1l$z9e8YYPnPxr0>(=7?gw zfjO#Jd0;+KtU)lJDpn(y&lKwt%;$;~3g!#NS_N}Vv1-8_SFB$!Uplv)2bMCJuM~?K z%n8Nv2IG9^#6k!2wPMMGIjLCuU`{EPL6~n83nI*E#nK4#tzwacIipxET`=GAgjhLY z&MMYWnC}&*>yf9EMxp#u~)#{Q0y8oHx>H__~CD1Ct*EQ>?yDwirod)Q?bv$dMOuM4y?Cg z^MPf$IM{|@eH0rKtgm8gg6*i-q+tCN+ZAjl#l{8euh_z1J1aIb*e(iBGY0Tu^8hwD z*g(Zr2OFf=^k9P(+aGL*Vk3kNRcwi{VT#QWHe9hy!bT`IOxQ@p)(IP>u${NvMl1GH z*cipm3LC4~V`1YIyDeH6BK(fY&XTO4BK6?Kf|)XIoPRT6UoH`n>K8c zV*7?oR?fs{Qxsb|Y){4J4%qc-O;;QTU^5g41GsD-o)BjQ z*uIL>0&J$@+yI-UI6=VnQ=BDWvlXWb*#3(11#FJuqyd|&ICH?}DNY}-`M2=?ALD}p z#gPPdfZ}ihTc|juz!oVEEU?9jqYG?_;t&H{syNQTmMIQ4u;q#)4s3)T3x zdKMl#P;ml+9i%u5!46iOieRf0=Ofr5ijxxTP{o-Ec9`Py1Y4~*N5KwPoTy-Hlrvkw zj!>MkU`Hy>Td<=PCokC1iZdAO7{zG}cC6xD23xB*p}~$*xXCzP2|uTupu~f*&iVd% z5T`IqRO00PBqhF#w=3z$Sg*v7@eU=O87C|0!q}iBfN_eFAjYXmoD^I2F`;`3}t*2U7Z6s;KOcE9Q9!z zQz&p>i|moPlV?vVj{mS56*mH~n-rW&Jf)|etCDA%6}Jhn&noO=bk50Xnf7_b zO$6)~H*cTPI7_iRWBW^ZeotsB^kMU*24G8R3Ak{f=F9Pe_N#d>qwpGFT zinl4reLQ-BYkNRoKvlrpfYkxd1ndad6L2)(bf9nGhQRGX2|+nQD}(k1eID!|oE$tf zxIXx~;6uSzLUKZ?Lr#ZAhE|5Y7M3*Osn_ z5`q(+>z32)bob=$U-wv)Se$q`DLg4PsU>N1(&^;tQo5wHq-^i$(X+ni&R*!1 z-D_QHP3p?jtGye0x2E}})ub&-JDcv2-aY+j`h|?}jGBx+eVY0l>T{!SYTprk7x#TF zvwLP?W>eySaZ$|6Tnr=1k7{FgGK&Id?~1XkO2} z`n=Y>bNOER+4>7|TV9kJQg-wM!3O_B%E~+hREY2(5ReYkPv1E5?R_T_~ z_OjZtHDw3OQ_G(yzh043F}Y$z#s12`%7V(fD_Vc4bW@apR7jl-*lFC4zR1~olvCe^I0*?-&W+Ya7# zeMHqrzmYj3503I0wPaN5sI#N*9Njwl(wMw4%f=iXbA4>}*p{(d$L_C9tX(;-VBC^% z>&I;ww{zTq@fqV6j{kUq$As|{PSs`A&8*uoF~Wc1_=(#m9-eq*Qud^olg#b@x1Xuc zt6$Z&GImpJrx841dB+NZ4KepDZq}Z>jJtcQrb$vgr%i2f JuQd&V{{hxLQAz*+ delta 4663 zcmXxn30zfW8V2y^y{ITE%ViM|71=}u5mZ1#b`fwxR6vw+L8SsEx75swMrLWIV(K_$ zwoGbMjfK;+jX91rPGd7>q^4zNW%hm8YF0)%&+(n{_xqpco(o>R=X~G$zUP$>z1lwT z+7#_s2*?Hi<+JN&He4Q(v=QiZ2?z|GSGRobWA9D~1|ph(*Vom~nOPIoe>Y#_Jf+t1 z4ewJOWBK|Gim9z%yzByB@bf+gI(DdAFni|7cCT|lINx(M)z4hk;F^xN`SVb|5jlTm z{hYr0!gE&xr@QeNd>R%kTAV$n@;q>czu@1x`Hkr8T!{05K-Y=x;#>VPe?(U={_lXZ zzR&ZM|DQLmd0qDUil?37a^B@1{vF9}?kz9Mo|fYh+OhfDPVU}b?KeLUuB-66`6_|w z1MvM0u6LRvy@O>>bExO1;v=EW$GrP=&A$e2dnry9yDS#?nM*s#{+l}>+ujC#wKjW7Hq{M*oN)c z;lb~)6Tio!*oEDA0#9QP_F^BN#dCNbFW^tukC$)&f5yxB3tq$Py!n5{A^Z(T@DCit zKk*KZ;a&V2|G{y*hgN)mlQ@Ob_z-7s79Zmrm(Qp844>l*T*Q~Sgs))HhRgUG-@x-N zuHZ*p#ZS0~U-28RdPtZ=N?(bV7>SiQ=_mbVfDDub zNt8h{Sdt}0hR9GECaIDp88SjLWu#rUN zYG1@0+=dO3#HHegd_0CXVWbz{!hQGw-{Y`&aXG)wh1Th*@4ASatBwm9@QZMc&idQZ zwTI_%z|2xyR4}s@mlsTp;zEO&qi}*bS8?&d%u`&3Ftv&c66Q9A7Uu2B*(>G_g`vzk zz~daaa$)Kf*D%a{#nlY6Kyh8eG$^icm^&5MIt;6XgR359k>dJ?S**AdV3sKE37Dk{ ziClH&E}jrK3d}OaEd#S$!I!y0aT~$ht+=6JRw`~Sn0pjA8O$oh?FQpf+;}jJ3a>I( zJNQHHMi}Q36Za*|y^1>&hV{&WwaojJL@}Ln;{JuXU%|O`>y+>wn+KJ2V6ImZ$lRbL zfLZ-840C-;k$~B%;QXVHC}FuW+Z0PkL-#jFX7Fr}Vljc) zt5{ZG_9+$^m}eDon9fZiKYx#TpIswPLk~`NqLT%EArvtzrp>`A)Hz!+ft;)?t27EbuT_ z6iYqKkBUVf=Bi@(hxtjd5y1Sc*b-oVQEU#}LDzU7_6e9@)y;3#&ey~X1oN9hBlEgq zKY_WS*jZS|6?+V|pxw>+t}#K3IRnCI}m#*bZUcij5IAP_aeA z1}W@j1}nBr*bv1A3fn`mmBNN9HdWX#g?+rdHe9jO!uC|`xv&w6-50i(VjqU>t=N%a z`zZEi*hs}L4ck|-U&FGfIoP>jqZNBNYz%pLU^|D6Rc!3Aaf&S-wx4n)JsYps_F?-g z9AXYo90gzpDh>s(35w$ZY@*_z06R!=WPrye@q{=%zz$ZNBVdyiCkogU#n}ROh~kt1 zJ5+JrfE}hddBCPB&LFU9iqi;ey5d{{JNzbI|5JRCp*XC-j!+z1U^5j57}$}DqYP}8 z;!p#dtvKGm<|v$J<|>Xnuz8BZ4{W~T7zA73-2Vc8`!ATI6lWvYLd7WwcC_NW1Y4vy zIl&eyXYbh(#c2w5jN)7cJ63VRf*q$gYr&3J&eR24syKhaPE?%4V9OL|GT2Fq(;4h! z#W@XjisHluTdp{}!B!|vaj=yNH<(kE2(!w$|2&9OB&I3p#GJ0gn^~=-GxHWDU6{8j z>BgL)q&st_5?|&lCH~CW${E&djgnwz|IgtGNe|{+CC>hwrzDbDtE4aUHYLthx?M>O z^A07k%sM4;%z7pLnDdqNXD)E?{)@AH8k9KO=T0RF%!Nu4nTwPRVlGxPn7KrWvtyPj zadymIN}L_DOvzB@awWrlBA}*asBHci0CN2YJ}_iX%Pj z28BH4LyBWQ>_&xR=ELaY9Kg{Zc9Y^m0PJRk;msYwqLW|b*&~V%2C&-{9}!@;D>(n$ z4kby=m0{7Ie4ah3_y7U>KYWyc-KAidk1IZ2!0uLj(13kH@sR`8xnjhJ4_N1d5g$Wf zpH?``bS@t8(FB$k&+QzXhi9Edp@>yFKcZHzT>330c? zJ=f3Ouc+Vde(mw4@w?(r^dHc_Z9vq3tpi;H3kU8U*p?8I(3G${;ZR~j;)cWniEV=_ zlYElqCOw*TH0kTXp@YW`J~a4DvQKhp^0wsDDejb_6wiv3{V6{Wi68RvP~TzhVP(TM z4!fROn|dtGH?1V?rL?!x+S3cu*QP(2ej@$q@D;-kW|U@B%C#x-Wpm`!62j4@+}jy2Ez_zlN%=QoNT7J zrxZ+?G39W1RQc(O@QQ?rtcuc#Srx}BgDUGPcUNAWx@zk2s!mlURokipFHQ5EmNISO zv}dNrPcNyCs$N=sq~*DY?GY{B8P~VBymcb7i{!RkJiEr#Qg?2FtHqwL>DpY?R{dY1 C%?wrm diff --git a/src/vs/base/browser/ui/contextview/contextview.ts b/src/vs/base/browser/ui/contextview/contextview.ts index f1f6e9c6ac..b09b736630 100644 --- a/src/vs/base/browser/ui/contextview/contextview.ts +++ b/src/vs/base/browser/ui/contextview/contextview.ts @@ -162,6 +162,7 @@ export class ContextView extends Disposable { this.view.className = 'context-view'; this.view.style.top = '0px'; this.view.style.left = '0px'; + this.view.style.position = this.useFixedPosition ? 'fixed' : 'absolute'; DOM.show(this.view); // Render content diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts index f30baff33a..27cc471d62 100644 --- a/src/vs/base/browser/ui/inputbox/inputBox.ts +++ b/src/vs/base/browser/ui/inputbox/inputBox.ts @@ -175,8 +175,8 @@ export class InputBox extends Widget { this.input.setAttribute('autocapitalize', 'off'); this.input.setAttribute('spellcheck', 'false'); - this.onfocus(this.input, () => dom.addClass(this.element, 'synthetic-focus')); - this.onblur(this.input, () => dom.removeClass(this.element, 'synthetic-focus')); + this.onfocus(this.input, () => this.element.classList.add('synthetic-focus')); + this.onblur(this.input, () => this.element.classList.remove('synthetic-focus')); if (this.options.flexibleHeight) { this.maxHeight = typeof this.options.flexibleMaxHeight === 'number' ? this.options.flexibleMaxHeight : Number.POSITIVE_INFINITY; @@ -392,11 +392,11 @@ export class InputBox extends Widget { public showMessage(message: IMessage, force?: boolean): void { this.message = message; - dom.removeClass(this.element, 'idle'); - dom.removeClass(this.element, 'info'); - dom.removeClass(this.element, 'warning'); - dom.removeClass(this.element, 'error'); - dom.addClass(this.element, this.classForType(message.type)); + this.element.classList.remove('idle'); + this.element.classList.remove('info'); + this.element.classList.remove('warning'); + this.element.classList.remove('error'); + this.element.classList.add(this.classForType(message.type)); const styles = this.stylesForType(this.message.type); this.element.style.border = styles.border ? `1px solid ${styles.border}` : ''; @@ -409,10 +409,10 @@ export class InputBox extends Widget { public hideMessage(): void { this.message = null; - dom.removeClass(this.element, 'info'); - dom.removeClass(this.element, 'warning'); - dom.removeClass(this.element, 'error'); - dom.addClass(this.element, 'idle'); + this.element.classList.remove('info'); + this.element.classList.remove('warning'); + this.element.classList.remove('error'); + this.element.classList.add('idle'); this._hideMessage(); this.applyStyles(); @@ -494,7 +494,7 @@ export class InputBox extends Widget { const spanElement = (this.message.formatContent ? renderFormattedText(this.message.content, renderOptions) : renderText(this.message.content, renderOptions)); - dom.addClass(spanElement, this.classForType(this.message.type)); + spanElement.classList.add(this.classForType(this.message.type)); const styles = this.stylesForType(this.message.type); spanElement.style.backgroundColor = styles.background ? styles.background.toString() : ''; @@ -543,7 +543,7 @@ export class InputBox extends Widget { this.validate(); this.updateMirror(); - dom.toggleClass(this.input, 'empty', !this.value); + this.input.classList.toggle('empty', !this.value); if (this.state === 'open' && this.contextViewProvider) { this.contextViewProvider.layout(); diff --git a/src/vs/base/browser/ui/list/listView.ts b/src/vs/base/browser/ui/list/listView.ts index 7941364db9..c2bdc3ba11 100644 --- a/src/vs/base/browser/ui/list/listView.ts +++ b/src/vs/base/browser/ui/list/listView.ts @@ -411,7 +411,6 @@ export class ListView implements ISpliceable, IDisposable { if (this.supportDynamicHeights) { this._rerender(this.lastRenderTop, this.lastRenderHeight); } - return; } splice(start: number, deleteCount: number, elements: T[] = []): T[] { @@ -790,8 +789,8 @@ export class ListView implements ISpliceable, IDisposable { item.dragStartDisposable.dispose(); const renderer = this.renderers.get(item.templateId); - if (renderer && renderer.disposeElement) { - renderer.disposeElement(item.element, index, item.row!.templateData, item.size); + if (item.row && renderer && renderer.disposeElement) { + renderer.disposeElement(item.element, index, item.row.templateData, item.size); } this.cache.release(item.row!); diff --git a/src/vs/base/browser/ui/list/listWidget.ts b/src/vs/base/browser/ui/list/listWidget.ts index b123935448..1374280514 100644 --- a/src/vs/base/browser/ui/list/listWidget.ts +++ b/src/vs/base/browser/ui/list/listWidget.ts @@ -854,6 +854,7 @@ export interface IListOptions { readonly horizontalScrolling?: boolean; readonly additionalScrollHeight?: number; readonly transformOptimization?: boolean; + readonly smoothScrolling?: boolean; } export interface IListStyles { diff --git a/src/vs/base/browser/ui/menu/menu.ts b/src/vs/base/browser/ui/menu/menu.ts index fcf6e34aab..aa54df4c43 100644 --- a/src/vs/base/browser/ui/menu/menu.ts +++ b/src/vs/base/browser/ui/menu/menu.ts @@ -395,10 +395,9 @@ class BaseMenuActionViewItem extends BaseActionViewItem { } this._register(addDisposableListener(this.element, EventType.MOUSE_UP, e => { - if (e.defaultPrevented) { - return; - } - + // removed default prevention as it conflicts + // with BaseActionViewItem #101537 + // add back if issues arise and link new issue EventHelper.stop(e, true); this.onClick(e); })); diff --git a/src/vs/base/browser/ui/menu/menubar.ts b/src/vs/base/browser/ui/menu/menubar.ts index b02c483889..bf14a48e8c 100644 --- a/src/vs/base/browser/ui/menu/menubar.ts +++ b/src/vs/base/browser/ui/menu/menubar.ts @@ -326,7 +326,15 @@ export class MenuBar extends Disposable { let event = new StandardKeyboardEvent(e as KeyboardEvent); let eventHandled = true; - if ((event.equals(KeyCode.DownArrow) || event.equals(KeyCode.Enter) || (this.options.compactMode !== undefined && event.equals(KeyCode.Space))) && !this.isOpen) { + const triggerKeys = [KeyCode.Enter]; + if (this.options.compactMode === undefined) { + triggerKeys.push(KeyCode.DownArrow); + } else { + triggerKeys.push(KeyCode.Space); + triggerKeys.push(this.options.compactMode === Direction.Right ? KeyCode.RightArrow : KeyCode.LeftArrow); + } + + if ((triggerKeys.some(k => event.equals(k)) && !this.isOpen)) { this.focusedMenu = { index: MenuBar.OVERFLOW_INDEX }; this.openedViaKeyboard = true; this.focusState = MenubarState.OPEN; diff --git a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts index 88caef66f0..520db591f4 100644 --- a/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +++ b/src/vs/base/browser/ui/scrollbar/scrollableElement.ts @@ -17,6 +17,7 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as platform from 'vs/base/common/platform'; import { INewScrollDimensions, INewScrollPosition, IScrollDimensions, IScrollPosition, ScrollEvent, Scrollable, ScrollbarVisibility } from 'vs/base/common/scrollable'; +import { getZoomFactor } from 'vs/base/browser/browser'; const HIDE_TIMEOUT = 500; const SCROLL_WHEEL_SENSITIVITY = 50; @@ -130,13 +131,18 @@ export class MouseWheelClassifier { // } } - if (Math.abs(item.deltaX - Math.round(item.deltaX)) > 0 || Math.abs(item.deltaY - Math.round(item.deltaY)) > 0) { + if (!this._isAlmostInt(item.deltaX) || !this._isAlmostInt(item.deltaY)) { // non-integer deltas => indicator that this is not a physical mouse wheel score += 0.25; } return Math.min(Math.max(score, 0), 1); } + + private _isAlmostInt(value: number): boolean { + const delta = Math.abs(Math.round(value) - value); + return (delta < 0.01); + } } export abstract class AbstractScrollableElement extends Widget { @@ -343,10 +349,11 @@ export abstract class AbstractScrollableElement extends Widget { const classifier = MouseWheelClassifier.INSTANCE; if (SCROLL_WHEEL_SMOOTH_SCROLL_ENABLED) { - if (platform.isWindows) { - // On Windows, the incoming delta events are multiplied with the device pixel ratio, - // so to get a better classification, simply undo that. - classifier.accept(Date.now(), e.deltaX / window.devicePixelRatio, e.deltaY / window.devicePixelRatio); + const osZoomFactor = window.devicePixelRatio / getZoomFactor(); + if (platform.isWindows || platform.isLinux) { + // On Windows and Linux, the incoming delta events are multiplied with the OS zoom factor. + // The OS zoom factor can be reverse engineered by using the device pixel ratio and the configured zoom factor into account. + classifier.accept(Date.now(), e.deltaX / osZoomFactor, e.deltaY / osZoomFactor); } else { classifier.accept(Date.now(), e.deltaX, e.deltaY); } diff --git a/src/vs/base/browser/ui/tree/abstractTree.ts b/src/vs/base/browser/ui/tree/abstractTree.ts index 13b707c2fd..d46b93ff42 100644 --- a/src/vs/base/browser/ui/tree/abstractTree.ts +++ b/src/vs/base/browser/ui/tree/abstractTree.ts @@ -951,6 +951,7 @@ export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions { readonly filterOnType?: boolean; readonly smoothScrolling?: boolean; readonly horizontalScrolling?: boolean; + readonly expandOnlyOnDoubleClick?: boolean; } export interface IAbstractTreeOptions extends IAbstractTreeOptionsUpdate, IListOptions { @@ -1094,7 +1095,10 @@ class TreeNodeListMouseController extends MouseController< return super.onViewPointer(e); } - const onTwistie = hasClass(e.browserEvent.target as HTMLElement, 'monaco-tl-twistie'); + const target = e.browserEvent.target as HTMLElement; + const onTwistie = hasClass(target, 'monaco-tl-twistie') + || (hasClass(target, 'monaco-icon-label') && hasClass(target, 'folder-icon') && e.browserEvent.offsetX < 16); + let expandOnlyOnTwistieClick = false; if (typeof this.tree.expandOnlyOnTwistieClick === 'function') { @@ -1107,6 +1111,10 @@ class TreeNodeListMouseController extends MouseController< return super.onViewPointer(e); } + if (this.tree.expandOnlyOnDoubleClick && e.browserEvent.detail !== 2 && !onTwistie) { + return super.onViewPointer(e); + } + if (node.collapsible) { const model = ((this.tree as any).model as ITreeModel); // internal const location = model.getNodeLocation(node); @@ -1244,6 +1252,7 @@ export abstract class AbstractTree implements IDisposable get filterOnType(): boolean { return !!this._options.filterOnType; } get onDidChangeTypeFilterPattern(): Event { return this.typeFilterController ? this.typeFilterController.onDidChangePattern : Event.None; } + get expandOnlyOnDoubleClick(): boolean { return this._options.expandOnlyOnDoubleClick ?? false; } get expandOnlyOnTwistieClick(): boolean | ((e: T) => boolean) { return typeof this._options.expandOnlyOnTwistieClick === 'undefined' ? false : this._options.expandOnlyOnTwistieClick; } private readonly _onDidUpdateOptions = new Emitter>(); diff --git a/src/vs/base/common/arrays.ts b/src/vs/base/common/arrays.ts index 9a7e2d4762..772bd0b824 100644 --- a/src/vs/base/common/arrays.ts +++ b/src/vs/base/common/arrays.ts @@ -591,6 +591,14 @@ export function asArray(x: T | T[]): T[] { return Array.isArray(x) ? x : [x]; } +export function toArray(iterable: IterableIterator): T[] { + const result: T[] = []; + for (let element of iterable) { + result.push(element); + } + return result; +} + export function getRandomElement(arr: T[]): T | undefined { return arr[Math.floor(Math.random() * arr.length)]; } diff --git a/src/vs/base/common/codicons.ts b/src/vs/base/common/codicons.ts index af7c151f0c..496875b922 100644 --- a/src/vs/base/common/codicons.ts +++ b/src/vs/base/common/codicons.ts @@ -52,6 +52,8 @@ export class Codicon { _registry.add(this); } public get classNames() { return 'codicon codicon-' + this.id; } + // classNamesArray is useful for migrating to ES6 classlist + public get classNamesArray() { return ['codicon', 'codicon-' + this.id]; } public get cssSelector() { return '.codicon.codicon-' + this.id; } } @@ -472,6 +474,8 @@ export namespace Codicon { export const stopCircle = new Codicon('stop-circle', { character: '\\eba5' }); export const playCircle = new Codicon('play-circle', { character: '\\eba6' }); export const record = new Codicon('record', { character: '\\eba7' }); + export const debugAltSmall = new Codicon('debug-alt-small', { character: '\\eba8' }); + export const vmConnect = new Codicon('vm-connect', { character: '\\eba9' }); } diff --git a/src/vs/base/common/errors.ts b/src/vs/base/common/errors.ts index 792526cdec..ba5434f2c1 100644 --- a/src/vs/base/common/errors.ts +++ b/src/vs/base/common/errors.ts @@ -203,3 +203,12 @@ export class NotImplementedError extends Error { } } } + +export class NotSupportedError extends Error { + constructor(message?: string) { + super('NotSupported'); + if (message) { + this.message = message; + } + } +} diff --git a/src/vs/base/common/fuzzyScorer.ts b/src/vs/base/common/fuzzyScorer.ts index d2c8abd615..a0b41f5901 100644 --- a/src/vs/base/common/fuzzyScorer.ts +++ b/src/vs/base/common/fuzzyScorer.ts @@ -42,8 +42,7 @@ export function scoreFuzzy(target: string, query: string, queryLower: string, fu // When not searching fuzzy, we require the query to be contained fully // in the target string contiguously. if (!fuzzy) { - const indexOfQueryInTarget = targetLower.indexOf(queryLower); - if (indexOfQueryInTarget === -1) { + if (!targetLower.includes(queryLower)) { // if (DEBUG) { // console.log(`Characters not matching consecutively ${queryLower} within ${targetLower}`); // } diff --git a/src/vs/base/common/htmlContent.ts b/src/vs/base/common/htmlContent.ts index b479cd4fb3..5bc4fc6bf4 100644 --- a/src/vs/base/common/htmlContent.ts +++ b/src/vs/base/common/htmlContent.ts @@ -6,6 +6,7 @@ import { equals } from 'vs/base/common/arrays'; import { UriComponents } from 'vs/base/common/uri'; import { escapeCodicons } from 'vs/base/common/codicons'; +import { illegalArgument } from 'vs/base/common/errors'; export interface IMarkdownString { readonly value: string; @@ -22,6 +23,10 @@ export class MarkdownString implements IMarkdownString { private _value: string = '', isTrustedOrOptions: boolean | { isTrusted?: boolean, supportThemeIcons?: boolean } = false, ) { + if (typeof this._value !== 'string') { + throw illegalArgument('value'); + } + if (typeof isTrustedOrOptions === 'boolean') { this._isTrusted = isTrustedOrOptions; this._supportThemeIcons = false; @@ -30,7 +35,6 @@ export class MarkdownString implements IMarkdownString { this._isTrusted = isTrustedOrOptions.isTrusted ?? false; this._supportThemeIcons = isTrustedOrOptions.supportThemeIcons ?? false; } - } get value() { return this._value; } diff --git a/src/vs/base/common/map.ts b/src/vs/base/common/map.ts index 328cfffe57..80ecca6cd4 100644 --- a/src/vs/base/common/map.ts +++ b/src/vs/base/common/map.ts @@ -9,27 +9,6 @@ import { compareSubstringIgnoreCase, compare, compareSubstring } from 'vs/base/c import { Schemas } from 'vs/base/common/network'; import { isLinux } from 'vs/base/common/platform'; -/** - * @deprecated ES6: use `[...SetOrMap.values()]` - */ -export function values(set: Set): V[]; -export function values(map: Map): V[]; -export function values(forEachable: { forEach(callback: (value: V, ...more: any[]) => any): void }): V[] { - const result: V[] = []; - forEachable.forEach(value => result.push(value)); - return result; -} - -/** - * @deprecated ES6: use `[...map.keys()]` - */ -export function keys(map: Map): K[] { - const result: K[] = []; - map.forEach((_value, key) => result.push(key)); - - return result; -} - export function getOrSet(map: Map, key: K, value: V): V { let result = map.get(key); if (result === undefined) { diff --git a/src/vs/base/common/mime.ts b/src/vs/base/common/mime.ts index 03f3019ac9..54df373e1c 100644 --- a/src/vs/base/common/mime.ts +++ b/src/vs/base/common/mime.ts @@ -5,7 +5,6 @@ import { basename, posix, extname } from 'vs/base/common/path'; import { startsWithUTF8BOM } from 'vs/base/common/strings'; -import { coalesce } from 'vs/base/common/arrays'; import { match } from 'vs/base/common/glob'; import { URI } from 'vs/base/common/uri'; import { Schemas } from 'vs/base/common/network'; @@ -247,34 +246,6 @@ export function isUnspecific(mime: string[] | string): boolean { return mime.length === 1 && isUnspecific(mime[0]); } -/** - * Returns a suggestion for the filename by the following logic: - * 1. If a relevant extension exists and is an actual filename extension (starting with a dot), suggest the prefix appended by the first one. - * 2. Otherwise, if there are other extensions, suggest the first one. - * 3. Otherwise, suggest the prefix. - */ -export function suggestFilename(mode: string | undefined, prefix: string): string { - const extensions = registeredAssociations - .filter(assoc => !assoc.userConfigured && assoc.extension && assoc.id === mode) - .map(assoc => assoc.extension); - - const extensionsWithDotFirst = coalesce(extensions) - .filter(assoc => assoc.startsWith('.')); - - if (extensionsWithDotFirst.length > 0) { - const candidateExtension = extensionsWithDotFirst[0]; - if (prefix.endsWith(candidateExtension)) { - // do not add the prefix if it already exists - // https://github.com/microsoft/vscode/issues/83603 - return prefix; - } - - return prefix + candidateExtension; - } - - return extensions[0] || prefix; -} - interface MapExtToMediaMimes { [index: string]: string; } diff --git a/src/vs/base/common/performance.js b/src/vs/base/common/performance.js index c3891415b0..e1387b65d5 100644 --- a/src/vs/base/common/performance.js +++ b/src/vs/base/common/performance.js @@ -9,22 +9,22 @@ function _factory(sharedObj) { - sharedObj._performanceEntries = sharedObj._performanceEntries || []; + sharedObj.MonacoPerformanceMarks = sharedObj.MonacoPerformanceMarks || []; const _dataLen = 2; const _timeStamp = typeof console.timeStamp === 'function' ? console.timeStamp.bind(console) : () => { }; function importEntries(entries) { - sharedObj._performanceEntries.splice(0, 0, ...entries); + sharedObj.MonacoPerformanceMarks.splice(0, 0, ...entries); } function exportEntries() { - return sharedObj._performanceEntries.slice(0); + return sharedObj.MonacoPerformanceMarks.slice(0); } function getEntries() { const result = []; - const entries = sharedObj._performanceEntries; + const entries = sharedObj.MonacoPerformanceMarks; for (let i = 0; i < entries.length; i += _dataLen) { result.push({ name: entries[i], @@ -35,7 +35,7 @@ function _factory(sharedObj) { } function getDuration(from, to) { - const entries = sharedObj._performanceEntries; + const entries = sharedObj.MonacoPerformanceMarks; let target = to; let endIndex = 0; for (let i = entries.length - _dataLen; i >= 0; i -= _dataLen) { @@ -54,7 +54,7 @@ function _factory(sharedObj) { } function mark(name) { - sharedObj._performanceEntries.push(name, Date.now()); + sharedObj.MonacoPerformanceMarks.push(name, Date.now()); _timeStamp(name); } @@ -73,7 +73,8 @@ function _factory(sharedObj) { // Because we want both instances to use the same perf-data // we store them globally -let sharedObj; +// eslint-disable-next-line no-var +var sharedObj; if (typeof global === 'object') { // nodejs sharedObj = global; @@ -91,5 +92,5 @@ if (typeof define === 'function') { // commonjs module.exports = _factory(sharedObj); } else { - // invalid context... + sharedObj.perf = _factory(sharedObj); } diff --git a/src/vs/base/common/stream.ts b/src/vs/base/common/stream.ts index 331abf973a..d9a90ef5d9 100644 --- a/src/vs/base/common/stream.ts +++ b/src/vs/base/common/stream.ts @@ -474,7 +474,7 @@ export function peekReadable(readable: Readable, reducer: IReducer, max /** * Helper to fully read a T stream into a T. */ -export function consumeStream(stream: ReadableStream, reducer: IReducer): Promise { +export function consumeStream(stream: ReadableStreamEvents, reducer: IReducer): Promise { return new Promise((resolve, reject) => { const chunks: T[] = []; diff --git a/src/vs/base/common/types.ts b/src/vs/base/common/types.ts index 9d6681764e..acd21d9eea 100644 --- a/src/vs/base/common/types.ts +++ b/src/vs/base/common/types.ts @@ -8,7 +8,7 @@ import { URI, UriComponents } from 'vs/base/common/uri'; /** * @returns whether the provided parameter is a JavaScript Array or not. */ -export function isArray(array: any): array is any[] { +export function isArray(array: T | {}): array is T extends readonly any[] ? (unknown extends T ? never : readonly any[]) : any[] { return Array.isArray(array); } @@ -171,7 +171,7 @@ export function validateConstraint(arg: any, constraint: TypeConstraint | undefi if (arg instanceof constraint) { return; } - } catch{ + } catch { // ignore } if (!isUndefinedOrNull(arg) && arg.constructor === constraint) { diff --git a/src/vs/base/common/uri.ts b/src/vs/base/common/uri.ts index 447e47d9ac..3a04006795 100644 --- a/src/vs/base/common/uri.ts +++ b/src/vs/base/common/uri.ts @@ -252,7 +252,7 @@ export class URI implements UriComponents { return this; } - return new _URI(scheme, authority, path, query, fragment); + return new CachingURI(scheme, authority, path, query, fragment); } // ---- parse & validate ------------------------ @@ -266,9 +266,9 @@ export class URI implements UriComponents { static parse(value: string, _strict: boolean = false): URI { const match = _regexp.exec(value); if (!match) { - return new _URI(_empty, _empty, _empty, _empty, _empty); + return new CachingURI(_empty, _empty, _empty, _empty, _empty); } - return new _URI( + return new CachingURI( match[2] || _empty, percentDecode(match[4] || _empty), percentDecode(match[5] || _empty), @@ -323,11 +323,11 @@ export class URI implements UriComponents { } } - return new _URI('file', authority, path, _empty, _empty); + return new CachingURI('file', authority, path, _empty, _empty); } static from(components: { scheme: string; authority?: string; path?: string; query?: string; fragment?: string }): URI { - return new _URI( + return new CachingURI( components.scheme, components.authority, components.path, @@ -388,7 +388,7 @@ export class URI implements UriComponents { } else if (data instanceof URI) { return data; } else { - const result = new _URI(data); + const result = new CachingURI(data); result._formatted = (data).external; result._fsPath = (data)._sep === _pathSepMarker ? (data).fsPath : null; return result; @@ -413,8 +413,8 @@ interface UriState extends UriComponents { const _pathSepMarker = isWindows ? 1 : undefined; -// eslint-disable-next-line @typescript-eslint/naming-convention -class _URI extends URI { +// This class exists so that URI is compatibile with vscode.Uri (API). +class CachingURI extends URI { _formatted: string | null = null; _fsPath: string | null = null; diff --git a/src/vs/base/node/processes.ts b/src/vs/base/node/processes.ts index 5fc3ef43f1..16e3721f0c 100644 --- a/src/vs/base/node/processes.ts +++ b/src/vs/base/node/processes.ts @@ -457,7 +457,7 @@ export namespace win32 { async function fileExists(path: string): Promise { if (await promisify(fs.exists)(path)) { - return !((await promisify(fs.stat)(path)).isDirectory); + return !((await promisify(fs.stat)(path)).isDirectory()); } return false; } diff --git a/src/vs/base/parts/contextmenu/common/contextmenu.ts b/src/vs/base/parts/contextmenu/common/contextmenu.ts index ce3f446359..a5aaa61441 100644 --- a/src/vs/base/parts/contextmenu/common/contextmenu.ts +++ b/src/vs/base/parts/contextmenu/common/contextmenu.ts @@ -36,8 +36,7 @@ export interface IPopupOptions { x?: number; y?: number; positioningItem?: number; - onHide?: () => void; } export const CONTEXT_MENU_CHANNEL = 'vscode:contextmenu'; -export const CONTEXT_MENU_CLOSE_CHANNEL = 'vscode:onCloseContextMenu'; \ No newline at end of file +export const CONTEXT_MENU_CLOSE_CHANNEL = 'vscode:onCloseContextMenu'; diff --git a/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts b/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts index 6d7fc4c11c..a679309536 100644 --- a/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts +++ b/src/vs/base/parts/contextmenu/electron-main/contextmenu.ts @@ -9,9 +9,10 @@ import { ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHANNEL, CONTEXT_MENU_ export function registerContextMenuListener(): void { ipcMain.on(CONTEXT_MENU_CHANNEL, (event: IpcMainEvent, contextMenuId: number, items: ISerializableContextMenuItem[], onClickChannel: string, options?: IPopupOptions) => { const menu = createMenu(event, onClickChannel, items); + const window = BrowserWindow.fromWebContents(event.sender); menu.popup({ - window: BrowserWindow.fromWebContents(event.sender), + window: window ? window : undefined, x: options ? options.x : undefined, y: options ? options.y : undefined, positioningItem: options ? options.positioningItem : undefined, diff --git a/src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts b/src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts index ab14d788a6..0379ab0925 100644 --- a/src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts +++ b/src/vs/base/parts/contextmenu/electron-sandbox/contextmenu.ts @@ -8,7 +8,7 @@ import { IContextMenuItem, ISerializableContextMenuItem, CONTEXT_MENU_CLOSE_CHAN let contextMenuIdPool = 0; -export function popup(items: IContextMenuItem[], options?: IPopupOptions): void { +export function popup(items: IContextMenuItem[], options?: IPopupOptions, onHide?: () => void): void { const processedItems: IContextMenuItem[] = []; const contextMenuId = contextMenuIdPool++; @@ -28,8 +28,8 @@ export function popup(items: IContextMenuItem[], options?: IPopupOptions): void ipcRenderer.removeListener(onClickChannel, onClickChannelHandler); - if (options?.onHide) { - options.onHide(); + if (onHide) { + onHide(); } }); diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts index 361b82f816..a1775a9ac9 100644 --- a/src/vs/base/parts/quickinput/browser/quickInput.ts +++ b/src/vs/base/parts/quickinput/browser/quickInput.ts @@ -1230,10 +1230,10 @@ export class QuickInputController extends Disposable { this.previousFocusElement = e.relatedTarget instanceof HTMLElement ? e.relatedTarget : undefined; }, true)); this._register(focusTracker.onDidBlur(() => { - this.previousFocusElement = undefined; if (!this.getUI().ignoreFocusOut && !this.options.ignoreFocusOut()) { - this.hide(true); + this.hide(); } + this.previousFocusElement = undefined; })); this._register(dom.addDisposableListener(container, dom.EventType.FOCUS, (e: FocusEvent) => { inputBox.setFocus(); @@ -1574,13 +1574,14 @@ export class QuickInputController extends Disposable { } } - hide(focusLost?: boolean) { + hide() { const controller = this.controller; if (controller) { + const focusChanged = !this.ui?.container.contains(document.activeElement); this.controller = null; this.onHideEmitter.fire(); this.getUI().container.style.display = 'none'; - if (!focusLost) { + if (!focusChanged) { if (this.previousFocusElement && this.previousFocusElement.offsetParent) { this.previousFocusElement.focus(); this.previousFocusElement = undefined; diff --git a/src/vs/base/parts/sandbox/electron-browser/preload.js b/src/vs/base/parts/sandbox/electron-browser/preload.js index 47abbf0d02..bb4cec959a 100644 --- a/src/vs/base/parts/sandbox/electron-browser/preload.js +++ b/src/vs/base/parts/sandbox/electron-browser/preload.js @@ -68,14 +68,6 @@ */ webFrame: { - getZoomFactor() { - return webFrame.getZoomFactor(); - }, - - getZoomLevel() { - return webFrame.getZoomLevel(); - }, - /** * @param {number} level */ diff --git a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts index 812e97e3a1..5449340452 100644 --- a/src/vs/base/parts/sandbox/electron-sandbox/globals.ts +++ b/src/vs/base/parts/sandbox/electron-sandbox/globals.ts @@ -43,16 +43,6 @@ export const ipcRenderer = (window as any).vscode.ipcRenderer as { export const webFrame = (window as any).vscode.webFrame as { - /** - * The current zoom factor. - */ - getZoomFactor(): number; - - /** - * The current zoom level. - */ - getZoomLevel(): number; - /** * Changes the zoom level to the specified level. The original size is 0 and each * increment above or below represents zooming 20% larger or smaller to default diff --git a/src/vs/base/test/common/mime.test.ts b/src/vs/base/test/common/mime.test.ts index e7788ae2eb..2a9d335be4 100644 --- a/src/vs/base/test/common/mime.test.ts +++ b/src/vs/base/test/common/mime.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { guessMimeTypes, registerTextMime, suggestFilename } from 'vs/base/common/mime'; +import { guessMimeTypes, registerTextMime } from 'vs/base/common/mime'; import { URI } from 'vs/base/common/uri'; suite('Mime', () => { @@ -126,53 +126,4 @@ suite('Mime', () => { assert.deepEqual(guessMimeTypes(URI.parse(`data:;label:something.data;description:data,`)), ['text/data', 'text/plain']); }); - - test('Filename Suggestion - Suggest prefix only when there are no relevant extensions', () => { - const id = 'plumbus0'; - const mime = `text/${id}`; - for (let extension of ['one', 'two']) { - registerTextMime({ id, mime, extension }); - } - - let suggested = suggestFilename('shleem', 'Untitled-1'); - assert.equal(suggested, 'Untitled-1'); - }); - - test('Filename Suggestion - Suggest prefix with first extension that begins with a dot', () => { - const id = 'plumbus1'; - const mime = `text/${id}`; - for (let extension of ['plumbus', '.shleem', '.gazorpazorp']) { - registerTextMime({ id, mime, extension }); - } - - let suggested = suggestFilename('plumbus1', 'Untitled-1'); - assert.equal(suggested, 'Untitled-1.shleem'); - }); - - test('Filename Suggestion - Suggest first relevant extension when there are none that begin with a dot', () => { - const id = 'plumbus2'; - const mime = `text/${id}`; - for (let extension of ['plumbus', 'shleem', 'gazorpazorp']) { - registerTextMime({ id, mime, extension }); - } - - let suggested = suggestFilename('plumbus2', 'Untitled-1'); - assert.equal(suggested, 'plumbus'); - }); - - test('Filename Suggestion - Should ignore user-configured associations', () => { - registerTextMime({ id: 'plumbus3', mime: 'text/plumbus3', extension: 'plumbus', userConfigured: true }); - registerTextMime({ id: 'plumbus3', mime: 'text/plumbus3', extension: '.shleem', userConfigured: true }); - registerTextMime({ id: 'plumbus3', mime: 'text/plumbus3', extension: '.gazorpazorp', userConfigured: false }); - - let suggested = suggestFilename('plumbus3', 'Untitled-1'); - assert.equal(suggested, 'Untitled-1.gazorpazorp'); - - registerTextMime({ id: 'plumbus4', mime: 'text/plumbus4', extension: 'plumbus', userConfigured: true }); - registerTextMime({ id: 'plumbus4', mime: 'text/plumbus4', extension: '.shleem', userConfigured: true }); - registerTextMime({ id: 'plumbus4', mime: 'text/plumbus4', extension: '.gazorpazorp', userConfigured: true }); - - suggested = suggestFilename('plumbus4', 'Untitled-1'); - assert.equal(suggested, 'Untitled-1'); - }); }); diff --git a/src/vs/code/browser/workbench/workbench-dev.html b/src/vs/code/browser/workbench/workbench-dev.html index 02a8fd68ad..2619d72ac3 100644 --- a/src/vs/code/browser/workbench/workbench-dev.html +++ b/src/vs/code/browser/workbench/workbench-dev.html @@ -2,6 +2,10 @@ + @@ -29,6 +33,7 @@ // NOTE: Changes to inline scripts require update of content security policy self.require = { baseUrl: `${window.location.origin}/static/out`, + recordStats: true, paths: { 'vscode-textmate': `${window.location.origin}/static/remote/web/node_modules/vscode-textmate/release/main`, 'vscode-oniguruma': `${window.location.origin}/static/remote/web/node_modules/vscode-oniguruma/release/main`, @@ -90,7 +95,11 @@ + + @@ -30,6 +34,7 @@ // NOTE: Changes to inline scripts require update of content security policy self.require = { baseUrl: `${window.location.origin}/static/out`, + recordStats: true, paths: { 'vscode-textmate': `${window.location.origin}/static/node_modules/vscode-textmate/release/main`, 'vscode-oniguruma': `${window.location.origin}/static/node_modules/vscode-oniguruma/release/main`, @@ -79,6 +84,9 @@ + diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts index d414140029..adfeed1c32 100644 --- a/src/vs/code/browser/workbench/workbench.ts +++ b/src/vs/code/browser/workbench/workbench.ts @@ -12,6 +12,7 @@ import { request } from 'vs/base/parts/request/browser/request'; import { isFolderToOpen, isWorkspaceToOpen } from 'vs/platform/windows/common/windows'; import { isEqual } from 'vs/base/common/resources'; import { isStandalone } from 'vs/base/browser/browser'; +import { mark } from 'vs/base/common/performance'; interface ICredential { service: string; @@ -277,6 +278,10 @@ class WorkspaceProvider implements IWorkspaceProvider { (function () { + // Mark start of workbench + mark('didLoadWorkbenchMain'); + performance.mark('workbench-start'); + // Find config by checking for DOM const configElement = document.getElementById('vscode-workbench-web-configuration'); const configElementAttribute = configElement ? configElement.getAttribute('data-settings') : undefined; diff --git a/src/vs/code/electron-browser/issue/issueReporterMain.ts b/src/vs/code/electron-browser/issue/issueReporterMain.ts index c86fe478c8..184a195841 100644 --- a/src/vs/code/electron-browser/issue/issueReporterMain.ts +++ b/src/vs/code/electron-browser/issue/issueReporterMain.ts @@ -4,13 +4,13 @@ *--------------------------------------------------------------------------------------------*/ import 'vs/css!./media/issueReporter'; -import { ElectronService, IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; -import { ipcRenderer, webFrame } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded import * as os from 'os'; -import * as browser from 'vs/base/browser/browser'; +import { ElectronService, IElectronService } from 'vs/platform/electron/electron-sandbox/electron'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; +import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window'; import { $, windowOpenNoOpener, addClass } from 'vs/base/browser/dom'; import { Button } from 'vs/base/browser/ui/button/button'; -import 'vs/base/browser/ui/codicons/codiconStyles'; // make sure codicon css is loaded import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel'; import * as collections from 'vs/base/common/collections'; import { debounce } from 'vs/base/common/decorators'; @@ -152,7 +152,7 @@ export class IssueReporter extends Disposable { this.setUpTypes(); this.setEventHandlers(); - this.applyZoom(configuration.data.zoomLevel); + applyZoom(configuration.data.zoomLevel); this.applyStyles(configuration.data.styles); this.handleExtensionData(configuration.data.enabledExtensions); @@ -180,15 +180,6 @@ export class IssueReporter extends Disposable { } } - private applyZoom(zoomLevel: number) { - webFrame.setZoomLevel(zoomLevel); - browser.setZoomFactor(webFrame.getZoomFactor()); - // See https://github.com/Microsoft/vscode/issues/26151 - // Cannot be trusted because the webFrame might take some time - // until it really applies the new zoom level - browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false); - } - private applyStyles(styles: IssueReporterStyles) { const styleTag = document.createElement('style'); const content: string[] = []; @@ -505,12 +496,12 @@ export class IssueReporter extends Disposable { // Cmd/Ctrl + zooms in if (cmdOrCtrlKey && e.keyCode === 187) { - this.applyZoom(webFrame.getZoomLevel() + 1); + zoomIn(); } // Cmd/Ctrl - zooms out if (cmdOrCtrlKey && e.keyCode === 189) { - this.applyZoom(webFrame.getZoomLevel() - 1); + zoomOut(); } // With latest electron upgrade, cmd+a is no longer propagating correctly for inputs in this window on mac diff --git a/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts index 6a4eb290e6..77643c5f7c 100644 --- a/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts +++ b/src/vs/code/electron-browser/processExplorer/processExplorerMain.ts @@ -5,13 +5,12 @@ import 'vs/css!./media/processExplorer'; import { clipboard } from 'electron'; -import { webFrame, ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; -import { repeat } from 'vs/base/common/strings'; import { totalmem } from 'os'; +import { ipcRenderer } from 'vs/base/parts/sandbox/electron-sandbox/globals'; import product from 'vs/platform/product/common/product'; import { localize } from 'vs/nls'; import { ProcessExplorerStyles, ProcessExplorerData } from 'vs/platform/issue/common/issue'; -import * as browser from 'vs/base/browser/browser'; +import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window'; import * as platform from 'vs/base/common/platform'; import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu'; import { popup } from 'vs/base/parts/contextmenu/electron-sandbox/contextmenu'; @@ -20,13 +19,8 @@ import { addDisposableListener, addClass } from 'vs/base/browser/dom'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { isRemoteDiagnosticError, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics'; -let mapPidToWindowTitle = new Map(); - const DEBUG_FLAGS_PATTERN = /\s--(inspect|debug)(-brk|port)?=(\d+)?/; const DEBUG_PORT_PATTERN = /\s--(inspect|debug)-port=(\d+)/; -const listeners = new DisposableStore(); -const collapsedStateCache: Map = new Map(); -let lastRequestTime: number; interface FormattedProcessItem { cpu: number; @@ -37,391 +31,400 @@ interface FormattedProcessItem { cmd: string; } -function getProcessList(rootProcess: ProcessItem, isLocal: boolean): FormattedProcessItem[] { - const processes: FormattedProcessItem[] = []; +class ProcessExplorer { + private lastRequestTime: number; - if (rootProcess) { - getProcessItem(processes, rootProcess, 0, isLocal); + private collapsedStateCache: Map = new Map(); + + private mapPidToWindowTitle = new Map(); + + private listeners = new DisposableStore(); + + constructor(data: ProcessExplorerData) { + this.applyStyles(data.styles); + + // Map window process pids to titles, annotate process names with this when rendering to distinguish between them + ipcRenderer.on('vscode:windowsInfoResponse', (event: unknown, windows: any[]) => { + this.mapPidToWindowTitle = new Map(); + windows.forEach(window => this.mapPidToWindowTitle.set(window.pid, window.title)); + }); + + ipcRenderer.on('vscode:listProcessesResponse', (event: unknown, processRoots: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]) => { + this.updateProcessInfo(processRoots); + this.requestProcessList(0); + }); + + this.lastRequestTime = Date.now(); + ipcRenderer.send('vscode:windowsInfoRequest'); + ipcRenderer.send('vscode:listProcesses'); } - return processes; -} + private getProcessList(rootProcess: ProcessItem, isLocal: boolean): FormattedProcessItem[] { + const processes: FormattedProcessItem[] = []; -function getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, indent: number, isLocal: boolean): void { - const isRoot = (indent === 0); + if (rootProcess) { + this.getProcessItem(processes, rootProcess, 0, isLocal); + } - const MB = 1024 * 1024; - - let name = item.name; - if (isRoot) { - name = isLocal ? `${product.applicationName} main` : 'remote agent'; + return processes; } - if (name === 'window') { - const windowTitle = mapPidToWindowTitle.get(item.pid); - name = windowTitle !== undefined ? `${name} (${mapPidToWindowTitle.get(item.pid)})` : name; + private getProcessItem(processes: FormattedProcessItem[], item: ProcessItem, indent: number, isLocal: boolean): void { + const isRoot = (indent === 0); + + const MB = 1024 * 1024; + + let name = item.name; + if (isRoot) { + name = isLocal ? `${product.applicationName} main` : 'remote agent'; + } + + if (name === 'window') { + const windowTitle = this.mapPidToWindowTitle.get(item.pid); + name = windowTitle !== undefined ? `${name} (${this.mapPidToWindowTitle.get(item.pid)})` : name; + } + + // Format name with indent + const formattedName = isRoot ? name : `${' '.repeat(indent)} ${name}`; + const memory = process.platform === 'win32' ? item.mem : (totalmem() * (item.mem / 100)); + processes.push({ + cpu: item.load, + memory: (memory / MB), + pid: item.pid.toFixed(0), + name, + formattedName, + cmd: item.cmd + }); + + // Recurse into children if any + if (Array.isArray(item.children)) { + item.children.forEach(child => { + if (child) { + this.getProcessItem(processes, child, indent + 1, isLocal); + } + }); + } } - // Format name with indent - const formattedName = isRoot ? name : `${repeat(' ', indent)} ${name}`; - const memory = process.platform === 'win32' ? item.mem : (totalmem() * (item.mem / 100)); - processes.push({ - cpu: item.load, - memory: (memory / MB), - pid: item.pid.toFixed(0), - name, - formattedName, - cmd: item.cmd - }); + private isDebuggable(cmd: string): boolean { + const matches = DEBUG_FLAGS_PATTERN.exec(cmd); + return (matches && matches.length >= 2) || cmd.indexOf('node ') >= 0 || cmd.indexOf('node.exe') >= 0; + } - // Recurse into children if any - if (Array.isArray(item.children)) { - item.children.forEach(child => { - if (child) { - getProcessItem(processes, child, indent + 1, isLocal); + private attachTo(item: FormattedProcessItem) { + const config: any = { + type: 'node', + request: 'attach', + name: `process ${item.pid}` + }; + + let matches = DEBUG_FLAGS_PATTERN.exec(item.cmd); + if (matches && matches.length >= 2) { + // attach via port + if (matches.length === 4 && matches[3]) { + config.port = parseInt(matches[3]); + } + config.protocol = matches[1] === 'debug' ? 'legacy' : 'inspector'; + } else { + // no port -> try to attach via pid (send SIGUSR1) + config.processId = String(item.pid); + } + + // a debug-port=n or inspect-port=n overrides the port + matches = DEBUG_PORT_PATTERN.exec(item.cmd); + if (matches && matches.length === 3) { + // override port + config.port = parseInt(matches[2]); + } + + ipcRenderer.send('vscode:workbenchCommand', { id: 'debug.startFromConfig', from: 'processExplorer', args: [config] }); + } + + private getProcessIdWithHighestProperty(processList: any[], propertyName: string) { + let max = 0; + let maxProcessId; + processList.forEach(process => { + if (process[propertyName] > max) { + max = process[propertyName]; + maxProcessId = process.pid; } }); + + return maxProcessId; } -} -function isDebuggable(cmd: string): boolean { - const matches = DEBUG_FLAGS_PATTERN.exec(cmd); - return (matches && matches.length >= 2) || cmd.indexOf('node ') >= 0 || cmd.indexOf('node.exe') >= 0; -} - -function attachTo(item: FormattedProcessItem) { - const config: any = { - type: 'node', - request: 'attach', - name: `process ${item.pid}` - }; - - let matches = DEBUG_FLAGS_PATTERN.exec(item.cmd); - if (matches && matches.length >= 2) { - // attach via port - if (matches.length === 4 && matches[3]) { - config.port = parseInt(matches[3]); + private updateSectionCollapsedState(shouldExpand: boolean, body: HTMLElement, twistie: HTMLImageElement, sectionName: string) { + if (shouldExpand) { + body.classList.remove('hidden'); + this.collapsedStateCache.set(sectionName, false); + twistie.src = './media/expanded.svg'; + } else { + body.classList.add('hidden'); + this.collapsedStateCache.set(sectionName, true); + twistie.src = './media/collapsed.svg'; } - config.protocol = matches[1] === 'debug' ? 'legacy' : 'inspector'; - } else { - // no port -> try to attach via pid (send SIGUSR1) - config.processId = String(item.pid); } - // a debug-port=n or inspect-port=n overrides the port - matches = DEBUG_PORT_PATTERN.exec(item.cmd); - if (matches && matches.length === 3) { - // override port - config.port = parseInt(matches[2]); - } - - ipcRenderer.send('vscode:workbenchCommand', { id: 'debug.startFromConfig', from: 'processExplorer', args: [config] }); -} - -function getProcessIdWithHighestProperty(processList: any[], propertyName: string) { - let max = 0; - let maxProcessId; - processList.forEach(process => { - if (process[propertyName] > max) { - max = process[propertyName]; - maxProcessId = process.pid; + private renderProcessFetchError(sectionName: string, errorMessage: string) { + const container = document.getElementById('process-list'); + if (!container) { + return; } - }); - return maxProcessId; -} + const body = document.createElement('tbody'); -function updateSectionCollapsedState(shouldExpand: boolean, body: HTMLElement, twistie: HTMLImageElement, sectionName: string) { - if (shouldExpand) { - body.classList.remove('hidden'); - collapsedStateCache.set(sectionName, false); - twistie.src = './media/expanded.svg'; - } else { - body.classList.add('hidden'); - collapsedStateCache.set(sectionName, true); - twistie.src = './media/collapsed.svg'; - } -} + this.renderProcessGroupHeader(sectionName, body, container); -function renderProcessFetchError(sectionName: string, errorMessage: string) { - const container = document.getElementById('process-list'); - if (!container) { - return; + const errorRow = document.createElement('tr'); + const data = document.createElement('td'); + data.textContent = errorMessage; + data.className = 'error'; + data.colSpan = 4; + errorRow.appendChild(data); + + body.appendChild(errorRow); + container.appendChild(body); } - const body = document.createElement('tbody'); + private renderProcessGroupHeader(sectionName: string, body: HTMLElement, container: HTMLElement) { + const headerRow = document.createElement('tr'); + const data = document.createElement('td'); + data.textContent = sectionName; + data.colSpan = 4; + headerRow.appendChild(data); - renderProcessGroupHeader(sectionName, body, container); + const twistie = document.createElement('img'); + this.updateSectionCollapsedState(!this.collapsedStateCache.get(sectionName), body, twistie, sectionName); + data.prepend(twistie); - const errorRow = document.createElement('tr'); - const data = document.createElement('td'); - data.textContent = errorMessage; - data.className = 'error'; - data.colSpan = 4; - errorRow.appendChild(data); - - body.appendChild(errorRow); - container.appendChild(body); -} - -function renderProcessGroupHeader(sectionName: string, body: HTMLElement, container: HTMLElement) { - const headerRow = document.createElement('tr'); - const data = document.createElement('td'); - data.textContent = sectionName; - data.colSpan = 4; - headerRow.appendChild(data); - - const twistie = document.createElement('img'); - updateSectionCollapsedState(!collapsedStateCache.get(sectionName), body, twistie, sectionName); - data.prepend(twistie); - - listeners.add(addDisposableListener(data, 'click', (e) => { - const isHidden = body.classList.contains('hidden'); - updateSectionCollapsedState(isHidden, body, twistie, sectionName); - })); - - container.appendChild(headerRow); -} - -function renderTableSection(sectionName: string, processList: FormattedProcessItem[], renderManySections: boolean, sectionIsLocal: boolean): void { - const container = document.getElementById('process-list'); - if (!container) { - return; - } - - const highestCPUProcess = getProcessIdWithHighestProperty(processList, 'cpu'); - const highestMemoryProcess = getProcessIdWithHighestProperty(processList, 'memory'); - - const body = document.createElement('tbody'); - - if (renderManySections) { - renderProcessGroupHeader(sectionName, body, container); - } - - processList.forEach(p => { - const row = document.createElement('tr'); - row.id = p.pid.toString(); - - const cpu = document.createElement('td'); - p.pid === highestCPUProcess - ? cpu.classList.add('centered', 'highest') - : cpu.classList.add('centered'); - cpu.textContent = p.cpu.toFixed(0); - - const memory = document.createElement('td'); - p.pid === highestMemoryProcess - ? memory.classList.add('centered', 'highest') - : memory.classList.add('centered'); - memory.textContent = p.memory.toFixed(0); - - const pid = document.createElement('td'); - pid.classList.add('centered'); - pid.textContent = p.pid; - - const name = document.createElement('th'); - name.scope = 'row'; - name.classList.add('data'); - name.title = p.cmd; - name.textContent = p.formattedName; - - row.append(cpu, memory, pid, name); - - listeners.add(addDisposableListener(row, 'contextmenu', (e) => { - showContextMenu(e, p, sectionIsLocal); + this.listeners.add(addDisposableListener(data, 'click', (e) => { + const isHidden = body.classList.contains('hidden'); + this.updateSectionCollapsedState(isHidden, body, twistie, sectionName); })); - body.appendChild(row); - }); - - container.appendChild(body); -} - -function updateProcessInfo(processLists: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]): void { - const container = document.getElementById('process-list'); - if (!container) { - return; + container.appendChild(headerRow); } - container.innerHTML = ''; - listeners.clear(); - - const tableHead = document.createElement('thead'); - tableHead.innerHTML = ` - ${localize('cpu', "CPU %")} - ${localize('memory', "Memory (MB)")} - ${localize('pid', "pid")} - ${localize('name', "Name")} - `; - - container.append(tableHead); - - const hasMultipleMachines = Object.keys(processLists).length > 1; - processLists.forEach((remote, i) => { - const isLocal = i === 0; - if (isRemoteDiagnosticError(remote.rootProcess)) { - renderProcessFetchError(remote.name, remote.rootProcess.errorMessage); - } else { - renderTableSection(remote.name, getProcessList(remote.rootProcess, isLocal), hasMultipleMachines, isLocal); + private renderTableSection(sectionName: string, processList: FormattedProcessItem[], renderManySections: boolean, sectionIsLocal: boolean): void { + const container = document.getElementById('process-list'); + if (!container) { + return; } - }); -} -function applyStyles(styles: ProcessExplorerStyles): void { - const styleTag = document.createElement('style'); - const content: string[] = []; + const highestCPUProcess = this.getProcessIdWithHighestProperty(processList, 'cpu'); + const highestMemoryProcess = this.getProcessIdWithHighestProperty(processList, 'memory'); - if (styles.hoverBackground) { - content.push(`tbody > tr:hover, table > tr:hover { background-color: ${styles.hoverBackground}; }`); + const body = document.createElement('tbody'); + + if (renderManySections) { + this.renderProcessGroupHeader(sectionName, body, container); + } + + processList.forEach(p => { + const row = document.createElement('tr'); + row.id = p.pid.toString(); + + const cpu = document.createElement('td'); + p.pid === highestCPUProcess + ? cpu.classList.add('centered', 'highest') + : cpu.classList.add('centered'); + cpu.textContent = p.cpu.toFixed(0); + + const memory = document.createElement('td'); + p.pid === highestMemoryProcess + ? memory.classList.add('centered', 'highest') + : memory.classList.add('centered'); + memory.textContent = p.memory.toFixed(0); + + const pid = document.createElement('td'); + pid.classList.add('centered'); + pid.textContent = p.pid; + + const name = document.createElement('th'); + name.scope = 'row'; + name.classList.add('data'); + name.title = p.cmd; + name.textContent = p.formattedName; + + row.append(cpu, memory, pid, name); + + this.listeners.add(addDisposableListener(row, 'contextmenu', (e) => { + this.showContextMenu(e, p, sectionIsLocal); + })); + + body.appendChild(row); + }); + + container.appendChild(body); } - if (styles.hoverForeground) { - content.push(`tbody > tr:hover, table > tr:hover { color: ${styles.hoverForeground}; }`); + private updateProcessInfo(processLists: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]): void { + const container = document.getElementById('process-list'); + if (!container) { + return; + } + + container.innerHTML = ''; + this.listeners.clear(); + + const tableHead = document.createElement('thead'); + tableHead.innerHTML = ` + ${localize('cpu', "CPU %")} + ${localize('memory', "Memory (MB)")} + ${localize('pid', "pid")} + ${localize('name', "Name")} + `; + + container.append(tableHead); + + const hasMultipleMachines = Object.keys(processLists).length > 1; + processLists.forEach((remote, i) => { + const isLocal = i === 0; + if (isRemoteDiagnosticError(remote.rootProcess)) { + this.renderProcessFetchError(remote.name, remote.rootProcess.errorMessage); + } else { + this.renderTableSection(remote.name, this.getProcessList(remote.rootProcess, isLocal), hasMultipleMachines, isLocal); + } + }); } - if (styles.highlightForeground) { - content.push(`.highest { color: ${styles.highlightForeground}; }`); + private applyStyles(styles: ProcessExplorerStyles): void { + const styleTag = document.createElement('style'); + const content: string[] = []; + + if (styles.hoverBackground) { + content.push(`tbody > tr:hover, table > tr:hover { background-color: ${styles.hoverBackground}; }`); + } + + if (styles.hoverForeground) { + content.push(`tbody > tr:hover, table > tr:hover { color: ${styles.hoverForeground}; }`); + } + + if (styles.highlightForeground) { + content.push(`.highest { color: ${styles.highlightForeground}; }`); + } + + styleTag.innerHTML = content.join('\n'); + if (document.head) { + document.head.appendChild(styleTag); + } + if (styles.color) { + document.body.style.color = styles.color; + } } - styleTag.innerHTML = content.join('\n'); - if (document.head) { - document.head.appendChild(styleTag); - } - if (styles.color) { - document.body.style.color = styles.color; - } -} + private showContextMenu(e: MouseEvent, item: FormattedProcessItem, isLocal: boolean) { + e.preventDefault(); -function applyZoom(zoomLevel: number): void { - webFrame.setZoomLevel(zoomLevel); - browser.setZoomFactor(webFrame.getZoomFactor()); - // See https://github.com/Microsoft/vscode/issues/26151 - // Cannot be trusted because the webFrame might take some time - // until it really applies the new zoom level - browser.setZoomLevel(webFrame.getZoomLevel(), /*isTrusted*/false); -} + const items: IContextMenuItem[] = []; + const pid = Number(item.pid); -function showContextMenu(e: MouseEvent, item: FormattedProcessItem, isLocal: boolean) { - e.preventDefault(); + if (isLocal) { + items.push({ + label: localize('killProcess', "Kill Process"), + click() { + process.kill(pid, 'SIGTERM'); + } + }); - const items: IContextMenuItem[] = []; - const pid = Number(item.pid); + items.push({ + label: localize('forceKillProcess', "Force Kill Process"), + click() { + process.kill(pid, 'SIGKILL'); + } + }); + + items.push({ + type: 'separator' + }); + } - if (isLocal) { items.push({ - label: localize('killProcess', "Kill Process"), + label: localize('copy', "Copy"), click() { - process.kill(pid, 'SIGTERM'); + const row = document.getElementById(pid.toString()); + if (row) { + clipboard.writeText(row.innerText); + } } }); items.push({ - label: localize('forceKillProcess', "Force Kill Process"), + label: localize('copyAll', "Copy All"), click() { - process.kill(pid, 'SIGKILL'); + const processList = document.getElementById('process-list'); + if (processList) { + clipboard.writeText(processList.innerText); + } } }); - items.push({ - type: 'separator' - }); + if (item && isLocal && this.isDebuggable(item.cmd)) { + items.push({ + type: 'separator' + }); + + items.push({ + label: localize('debug', "Debug"), + click: () => { + this.attachTo(item); + } + }); + } + + popup(items); } - items.push({ - label: localize('copy', "Copy"), - click() { - const row = document.getElementById(pid.toString()); - if (row) { - clipboard.writeText(row.innerText); - } - } - }); + private requestProcessList(totalWaitTime: number): void { + setTimeout(() => { + const nextRequestTime = Date.now(); + const waited = totalWaitTime + nextRequestTime - this.lastRequestTime; + this.lastRequestTime = nextRequestTime; - items.push({ - label: localize('copyAll', "Copy All"), - click() { - const processList = document.getElementById('process-list'); - if (processList) { - clipboard.writeText(processList.innerText); + // Wait at least a second between requests. + if (waited > 1000) { + ipcRenderer.send('vscode:windowsInfoRequest'); + ipcRenderer.send('vscode:listProcesses'); + } else { + this.requestProcessList(waited); } - } - }); - - if (item && isLocal && isDebuggable(item.cmd)) { - items.push({ - type: 'separator' - }); - - items.push({ - label: localize('debug', "Debug"), - click() { - attachTo(item); - } - }); + }, 200); } - popup(items); + public dispose() { + this.listeners.dispose(); + } } -function requestProcessList(totalWaitTime: number): void { - setTimeout(() => { - const nextRequestTime = Date.now(); - const waited = totalWaitTime + nextRequestTime - lastRequestTime; - lastRequestTime = nextRequestTime; - // Wait at least a second between requests. - if (waited > 1000) { - ipcRenderer.send('vscode:windowsInfoRequest'); - ipcRenderer.send('vscode:listProcesses'); - } else { - requestProcessList(waited); - } - }, 200); -} - -function createCloseListener(): void { - // Cmd/Ctrl + w closes process explorer - window.addEventListener('keydown', e => { - const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey; - if (cmdOrCtrlKey && e.keyCode === 87) { - ipcRenderer.send('vscode:closeProcessExplorer'); - } - }); -} export function startup(data: ProcessExplorerData): void { const platformClass = platform.isWindows ? 'windows' : platform.isLinux ? 'linux' : 'mac'; addClass(document.body, platformClass); // used by our fonts - - applyStyles(data.styles); applyZoom(data.zoomLevel); - createCloseListener(); - // Map window process pids to titles, annotate process names with this when rendering to distinguish between them - ipcRenderer.on('vscode:windowsInfoResponse', (event: unknown, windows: any[]) => { - mapPidToWindowTitle = new Map(); - windows.forEach(window => mapPidToWindowTitle.set(window.pid, window.title)); - }); - - ipcRenderer.on('vscode:listProcessesResponse', (event: unknown, processRoots: [{ name: string, rootProcess: ProcessItem | IRemoteDiagnosticError }]) => { - updateProcessInfo(processRoots); - requestProcessList(0); - }); - - lastRequestTime = Date.now(); - ipcRenderer.send('vscode:windowsInfoRequest'); - ipcRenderer.send('vscode:listProcesses'); + const processExplorer = new ProcessExplorer(data); document.onkeydown = (e: KeyboardEvent) => { const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey; // Cmd/Ctrl + zooms in if (cmdOrCtrlKey && e.keyCode === 187) { - applyZoom(webFrame.getZoomLevel() + 1); + zoomIn(); } // Cmd/Ctrl - zooms out if (cmdOrCtrlKey && e.keyCode === 189) { - applyZoom(webFrame.getZoomLevel() - 1); + zoomOut(); } }; + + // Cmd/Ctrl + w closes process explorer + window.addEventListener('keydown', e => { + const cmdOrCtrlKey = platform.isMacintosh ? e.metaKey : e.ctrlKey; + if (cmdOrCtrlKey && e.keyCode === 87) { + processExplorer.dispose(); + ipcRenderer.send('vscode:closeProcessExplorer'); + } + }); } diff --git a/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts b/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts index 79b973aef5..f15410f935 100644 --- a/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts +++ b/src/vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner.ts @@ -35,7 +35,7 @@ export class StorageDataCleaner extends Disposable { const emptyWorkspaces = workspaces.emptyWorkspaceInfos.map(info => info.backupFolder); // Read all workspace storage folders that exist - return readdir(this.environmentService.workspaceStorageHome).then(storageFolders => { + return readdir(this.environmentService.workspaceStorageHome.fsPath).then(storageFolders => { const deletes: Promise[] = []; storageFolders.forEach(storageFolder => { @@ -44,7 +44,7 @@ export class StorageDataCleaner extends Disposable { } if (emptyWorkspaces.indexOf(storageFolder) === -1) { - deletes.push(rimraf(join(this.environmentService.workspaceStorageHome, storageFolder))); + deletes.push(rimraf(join(this.environmentService.workspaceStorageHome.fsPath, storageFolder))); } }); diff --git a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts index cda53693a9..a661bb2782 100644 --- a/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts +++ b/src/vs/code/electron-browser/sharedProcess/sharedProcessMain.ts @@ -238,7 +238,7 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat server.registerChannel('userDataSyncAccount', authTokenChannel); const userDataSyncService = accessor.get(IUserDataSyncService); - const userDataSyncChannel = new UserDataSyncChannel(userDataSyncService, logService); + const userDataSyncChannel = new UserDataSyncChannel(server, userDataSyncService, logService); server.registerChannel('userDataSync', userDataSyncChannel); const userDataAutoSync = instantiationService2.createInstance(UserDataAutoSyncService); diff --git a/src/vs/code/electron-browser/workbench/workbench.js b/src/vs/code/electron-browser/workbench/workbench.js index 51e7290dbe..1a190b1046 100644 --- a/src/vs/code/electron-browser/workbench/workbench.js +++ b/src/vs/code/electron-browser/workbench/workbench.js @@ -9,41 +9,33 @@ 'use strict'; const perf = (function () { - let sharedObj; - if (typeof global === 'object') { - // nodejs - sharedObj = global; - } else if (typeof self === 'object') { - // browser - sharedObj = self; - } else { - sharedObj = {}; - } - // @ts-ignore - sharedObj._performanceEntries = sharedObj._performanceEntries || []; + globalThis.MonacoPerformanceMarks = globalThis.MonacoPerformanceMarks || []; return { /** * @param {string} name */ mark(name) { - sharedObj._performanceEntries.push(name, Date.now()); + globalThis.MonacoPerformanceMarks.push(name, Date.now()); } }; })(); perf.mark('renderer/started'); -// Setup shell environment -process['lazyEnv'] = getLazyEnv(); - /** - * @type {{ load: (modules: string[], resultCallback: (result, configuration: object) => any, options: object) => unknown }} + * @type {{ + * load: (modules: string[], resultCallback: (result, configuration: object) => any, options: object) => unknown, + * globals: () => typeof import('../../../base/parts/sandbox/electron-sandbox/globals') + * }} */ const bootstrapWindow = (() => { // @ts-ignore (defined in bootstrap-window.js) return window.MonacoBootstrapWindow; })(); +// Setup shell environment +process['lazyEnv'] = getLazyEnv(); + // Load workbench main JS, CSS and NLS all in parallel. This is an // optimization to prevent a waterfall of loading to happen, because // we know for a fact that workbench.desktop.main will depend on @@ -55,6 +47,8 @@ bootstrapWindow.load([ 'vs/css!vs/workbench/workbench.desktop.main' ], function (workbench, configuration) { + + // Mark start of workbench perf.mark('didLoadWorkbenchMain'); performance.mark('workbench-start'); @@ -183,8 +177,7 @@ function showPartsSplash(configuration) { * @returns {Promise} */ function getLazyEnv() { - - const ipc = require.__$__nodeRequire('electron').ipcRenderer; + const ipcRenderer = bootstrapWindow.globals().ipcRenderer; return new Promise(function (resolve) { const handle = setTimeout(function () { @@ -192,13 +185,13 @@ function getLazyEnv() { console.warn('renderer did not receive lazyEnv in time'); }, 10000); - ipc.once('vscode:acceptShellEnv', function (event, shellEnv) { + ipcRenderer.once('vscode:acceptShellEnv', function (event, shellEnv) { clearTimeout(handle); Object.assign(process.env, shellEnv); // @ts-ignore resolve(process.env); }); - ipc.send('vscode:fetchShellEnv'); + ipcRenderer.send('vscode:fetchShellEnv'); }); } diff --git a/src/vs/code/electron-main/auth.ts b/src/vs/code/electron-main/auth.ts index aaa7fb61bf..95048b0269 100644 --- a/src/vs/code/electron-main/auth.ts +++ b/src/vs/code/electron-main/auth.ts @@ -6,6 +6,7 @@ import { localize } from 'vs/nls'; import { Disposable } from 'vs/base/common/lifecycle'; import { Event } from 'vs/base/common/event'; +import { URI } from 'vs/base/common/uri'; import { BrowserWindow, BrowserWindowConstructorOptions, app, AuthInfo, WebContents, Event as ElectronEvent } from 'electron'; type LoginEvent = { @@ -58,10 +59,12 @@ export class ProxyAuthHandler extends Disposable { show: true, title: 'VS Code', webPreferences: { - nodeIntegration: true, + preload: URI.parse(require.toUrl('vs/base/parts/sandbox/electron-browser/preload.js')).fsPath, enableWebSQL: false, + sandbox: true, + devTools: false, enableRemoteModule: false, - nativeWindowOpen: true + v8CacheOptions: 'bypassHeatCheck' } }; @@ -72,24 +75,27 @@ export class ProxyAuthHandler extends Disposable { } const win = new BrowserWindow(opts); - const config = {}; - const baseUrl = require.toUrl('vs/code/electron-browser/proxy/auth.html'); - const url = `${baseUrl}?config=${encodeURIComponent(JSON.stringify(config))}`; + const url = require.toUrl('vs/code/electron-sandbox/proxy/auth.html'); const proxyUrl = `${authInfo.host}:${authInfo.port}`; const title = localize('authRequire', "Proxy Authentication Required"); const message = localize('proxyauth', "The proxy {0} requires authentication.", proxyUrl); - const data = { title, message }; - const javascript = 'promptForCredentials(' + JSON.stringify(data) + ')'; const onWindowClose = () => cb('', ''); win.on('close', onWindowClose); win.setMenu(null); - win.loadURL(url); - win.webContents.executeJavaScript(javascript, true).then(({ username, password }: Credentials) => { - cb(username, password); + win.webContents.on('did-finish-load', () => { + const data = { title, message }; + win.webContents.send('vscode:openProxyAuthDialog', data); + }); + win.webContents.on('ipc-message', (event, channel, credentials: Credentials) => { + if (channel === 'vscode:proxyAuthResponse') { + const { username, password } = credentials; + cb(username, password); + } win.removeListener('close', onWindowClose); win.close(); }); + win.loadURL(url); } } diff --git a/src/vs/code/electron-main/main.ts b/src/vs/code/electron-main/main.ts index 415107bb19..9a9e1c6376 100644 --- a/src/vs/code/electron-main/main.ts +++ b/src/vs/code/electron-main/main.ts @@ -178,8 +178,8 @@ class CodeMain { environmentService.extensionsPath, environmentService.nodeCachedDataDir, environmentService.logsPath, - environmentService.globalStorageHome, - environmentService.workspaceStorageHome, + environmentService.globalStorageHome.fsPath, + environmentService.workspaceStorageHome.fsPath, environmentService.backupHome.fsPath ].map((path): undefined | Promise => path ? mkdirp(path) : undefined)); diff --git a/src/vs/code/electron-main/window.ts b/src/vs/code/electron-main/window.ts index 45d7886ecf..4ab39785c0 100644 --- a/src/vs/code/electron-main/window.ts +++ b/src/vs/code/electron-main/window.ts @@ -15,7 +15,7 @@ import { ILogService } from 'vs/platform/log/common/log'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { parseArgs, OPTIONS, ParsedArgs } from 'vs/platform/environment/node/argv'; import product from 'vs/platform/product/common/product'; -import { IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility } from 'vs/platform/windows/common/windows'; +import { IWindowSettings, MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility, zoomLevelToZoomFactor } from 'vs/platform/windows/common/windows'; import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; import { isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; import { ICodeWindow, IWindowState, WindowMode } from 'vs/platform/windows/electron-main/windows'; @@ -153,6 +153,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { // in case we are maximized or fullscreen, only show later after the call to maximize/fullscreen (see below) const isFullscreenOrMaximized = (this.windowState.mode === WindowMode.Maximized || this.windowState.mode === WindowMode.Fullscreen); + const windowConfig = this.configurationService.getValue('window'); + const options: BrowserWindowConstructorOptions = { width: this.windowState.width, height: this.windowState.height, @@ -169,7 +171,8 @@ export class CodeWindow extends Disposable implements ICodeWindow { webviewTag: true, enableWebSQL: false, enableRemoteModule: false, - nativeWindowOpen: true + nativeWindowOpen: true, + zoomFactor: zoomLevelToZoomFactor(windowConfig?.zoomLevel) } }; @@ -182,8 +185,6 @@ export class CodeWindow extends Disposable implements ICodeWindow { options.icon = path.join(this.environmentService.appRoot, 'resources/win32/code_150x150.png'); } - const windowConfig = this.configurationService.getValue('window'); - if (isMacintosh && !this.useNativeFullScreen()) { options.fullscreenable = false; // enables simple fullscreen mode } @@ -214,6 +215,11 @@ export class CodeWindow extends Disposable implements ICodeWindow { this._win = new BrowserWindow(options); this._id = this._win.id; + // Open devtools if instructed from command line args + if (this.environmentService.args['open-devtools'] === true) { + this._win.webContents.openDevTools(); + } + if (isMacintosh && useCustomTitleStyle) { this._win.setSheetOffset(22); // offset dialogs by the height of the custom title bar if we have any } diff --git a/src/vs/code/electron-browser/proxy/auth.html b/src/vs/code/electron-sandbox/proxy/auth.html similarity index 58% rename from src/vs/code/electron-browser/proxy/auth.html rename to src/vs/code/electron-sandbox/proxy/auth.html index e5cc351b14..788b68fce7 100644 --- a/src/vs/code/electron-browser/proxy/auth.html +++ b/src/vs/code/electron-sandbox/proxy/auth.html @@ -5,7 +5,7 @@ + content="default-src 'none'; img-src 'self' https: data:; media-src 'none'; child-src 'self'; object-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https:; font-src 'self' https:;">