chrome-devtools-frontend 1.0.945677 → 1.0.947377

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. package/.eslintrc.js +1 -0
  2. package/config/gni/all_devtools_files.gni +0 -14
  3. package/config/gni/devtools_grd_files.gni +4 -42
  4. package/front_end/.eslintrc.js +5 -1
  5. package/front_end/core/host/InspectorFrontendHost.ts +0 -3
  6. package/front_end/core/host/InspectorFrontendHostAPI.ts +0 -1
  7. package/front_end/core/host/UserMetrics.ts +0 -22
  8. package/front_end/core/i18n/locales/en-US.json +33 -27
  9. package/front_end/core/i18n/locales/en-XL.json +33 -27
  10. package/front_end/core/root/Runtime.ts +0 -5
  11. package/front_end/core/sdk/AccessibilityModel.ts +0 -2
  12. package/front_end/core/sdk/CSSProperty.ts +16 -11
  13. package/front_end/core/sdk/CSSRule.ts +0 -2
  14. package/front_end/core/sdk/Cookie.ts +1 -5
  15. package/front_end/core/sdk/EmulationModel.ts +0 -2
  16. package/front_end/core/sdk/HeapProfilerModel.ts +0 -2
  17. package/front_end/core/sdk/NetworkManager.ts +0 -3
  18. package/front_end/core/sdk/Resource.ts +0 -3
  19. package/front_end/core/sdk/ResourceTreeModel.ts +0 -3
  20. package/front_end/core/sdk/ServiceWorkerManager.ts +0 -2
  21. package/front_end/core/sdk/sdk-meta.ts +20 -8
  22. package/front_end/devtools_compatibility.js +1 -8
  23. package/front_end/entrypoints/devtools_app/devtools_app.js +3 -0
  24. package/front_end/entrypoints/devtools_app/devtools_app.json +1 -3
  25. package/front_end/entrypoints/formatter_worker/CSSFormatter.ts +1 -3
  26. package/front_end/entrypoints/formatter_worker/FormatterActions.ts +0 -2
  27. package/front_end/entrypoints/formatter_worker/FormatterWorker.ts +0 -120
  28. package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +1 -11
  29. package/front_end/entrypoints/formatter_worker/formatter_worker.ts +5 -0
  30. package/front_end/entrypoints/inspector/{inspector.js → inspector.ts} +0 -3
  31. package/front_end/entrypoints/js_app/js_app.js +3 -0
  32. package/front_end/entrypoints/js_app/js_app.json +1 -2
  33. package/front_end/entrypoints/main/MainImpl.ts +0 -6
  34. package/front_end/entrypoints/ndb_app/ndb_app.js +3 -0
  35. package/front_end/entrypoints/ndb_app/ndb_app.json +1 -2
  36. package/front_end/entrypoints/{node_main → node_app}/NodeConnectionsPanel.ts +1 -1
  37. package/front_end/entrypoints/{node_main → node_app}/NodeMain.ts +2 -4
  38. package/front_end/entrypoints/{node_main → node_app}/nodeConnectionsPanel.css +0 -0
  39. package/front_end/entrypoints/node_app/node_app.ts +81 -0
  40. package/front_end/entrypoints/shell/shell.js +18 -1
  41. package/front_end/entrypoints/worker_app/{worker_app.js → worker_app.ts} +8 -2
  42. package/front_end/generated/InspectorBackendCommands.js +5 -1
  43. package/front_end/generated/protocol.d.ts +12 -0
  44. package/front_end/legacy_test_runner/sources_test_runner/sources_test_runner.js +0 -1
  45. package/front_end/models/bindings/CompilerScriptMapping.ts +0 -1
  46. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +4 -11
  47. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +1 -1
  48. package/front_end/models/bindings/ResourceMapping.ts +1 -1
  49. package/front_end/models/bindings/SASSSourceMapping.ts +0 -1
  50. package/front_end/models/emulation/DeviceModeModel.ts +0 -2
  51. package/front_end/models/formatter/FormatterWorkerPool.ts +0 -18
  52. package/front_end/models/issues_manager/CorsIssue.ts +8 -0
  53. package/front_end/models/text_utils/CodeMirrorUtils.ts +6 -51
  54. package/front_end/models/text_utils/TextUtils.ts +1 -2
  55. package/front_end/models/text_utils/text_utils-legacy.ts +0 -5
  56. package/front_end/panels/animation/AnimationTimeline.ts +0 -2
  57. package/front_end/panels/animation/AnimationUI.ts +0 -2
  58. package/front_end/panels/application/ApplicationPanelSidebar.ts +2 -4
  59. package/front_end/panels/application/BackForwardCacheStrings.ts +1 -0
  60. package/front_end/panels/css_overview/CSSOverviewModel.ts +0 -2
  61. package/front_end/panels/css_overview/CSSOverviewPanel.ts +0 -7
  62. package/front_end/panels/css_overview/CSSOverviewProcessingView.ts +0 -2
  63. package/front_end/panels/elements/ColorSwatchPopoverIcon.ts +0 -11
  64. package/front_end/panels/elements/StylesSidebarPane.ts +0 -1
  65. package/front_end/panels/elements/elementsTreeOutline.css +0 -13
  66. package/front_end/panels/emulation/DeviceModeToolbar.ts +0 -16
  67. package/front_end/panels/issues/CorsIssueDetailsView.ts +6 -2
  68. package/front_end/panels/lighthouse/lighthouse-meta.ts +0 -3
  69. package/front_end/panels/network/NetworkConfigView.ts +10 -0
  70. package/front_end/panels/network/NetworkItemView.ts +3 -0
  71. package/front_end/panels/network/networkConfigView.css +5 -0
  72. package/front_end/panels/profiler/profilesPanel.css +1 -1
  73. package/front_end/panels/search/SearchView.ts +24 -4
  74. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +6 -4
  75. package/front_end/panels/settings/emulation/components/userAgentClientHintsForm.css +0 -12
  76. package/front_end/panels/sources/CSSPlugin.ts +3 -0
  77. package/front_end/panels/sources/CoveragePlugin.ts +2 -0
  78. package/front_end/panels/sources/DebuggerPlugin.ts +35 -7
  79. package/front_end/panels/sources/JavaScriptCompilerPlugin.ts +3 -0
  80. package/front_end/panels/sources/ProfilePlugin.ts +3 -0
  81. package/front_end/panels/sources/UISourceCodeFrame.ts +11 -2
  82. package/front_end/panels/sources/sourcesView.css +0 -130
  83. package/front_end/panels/timeline/TimelineTreeView.ts +1 -0
  84. package/front_end/third_party/codemirror/codemirror-tsconfig.json +1 -25
  85. package/front_end/third_party/codemirror.next/chunk/codemirror.js +1 -1
  86. package/front_end/third_party/codemirror.next/chunk/cpp.js +1 -2
  87. package/front_end/third_party/codemirror.next/chunk/java.js +1 -2
  88. package/front_end/third_party/codemirror.next/chunk/json.js +1 -2
  89. package/front_end/third_party/codemirror.next/chunk/markdown.js +1 -2
  90. package/front_end/third_party/codemirror.next/chunk/php.js +1 -2
  91. package/front_end/third_party/codemirror.next/chunk/python.js +1 -2
  92. package/front_end/third_party/codemirror.next/chunk/wast.js +1 -2
  93. package/front_end/third_party/codemirror.next/chunk/xml.js +1 -2
  94. package/front_end/third_party/codemirror.next/codemirror.next.d.ts +1486 -1423
  95. package/front_end/third_party/codemirror.next/codemirror.next.js +1 -2
  96. package/front_end/third_party/codemirror.next/package.json +10 -9
  97. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +168 -164
  98. package/front_end/third_party/lighthouse/locales/ar-XB.json +0 -3
  99. package/front_end/third_party/lighthouse/locales/ar.json +0 -3
  100. package/front_end/third_party/lighthouse/locales/bg.json +17 -20
  101. package/front_end/third_party/lighthouse/locales/ca.json +0 -3
  102. package/front_end/third_party/lighthouse/locales/cs.json +0 -3
  103. package/front_end/third_party/lighthouse/locales/da.json +16 -19
  104. package/front_end/third_party/lighthouse/locales/de.json +0 -3
  105. package/front_end/third_party/lighthouse/locales/el.json +0 -3
  106. package/front_end/third_party/lighthouse/locales/en-GB.json +19 -22
  107. package/front_end/third_party/lighthouse/locales/en-US.json +33 -3
  108. package/front_end/third_party/lighthouse/locales/en-XA.json +0 -3
  109. package/front_end/third_party/lighthouse/locales/en-XL.json +33 -3
  110. package/front_end/third_party/lighthouse/locales/es-419.json +17 -20
  111. package/front_end/third_party/lighthouse/locales/es.json +0 -3
  112. package/front_end/third_party/lighthouse/locales/fi.json +16 -19
  113. package/front_end/third_party/lighthouse/locales/fil.json +33 -36
  114. package/front_end/third_party/lighthouse/locales/fr.json +16 -19
  115. package/front_end/third_party/lighthouse/locales/he.json +16 -19
  116. package/front_end/third_party/lighthouse/locales/hi.json +0 -3
  117. package/front_end/third_party/lighthouse/locales/hr.json +16 -19
  118. package/front_end/third_party/lighthouse/locales/hu.json +16 -19
  119. package/front_end/third_party/lighthouse/locales/id.json +16 -19
  120. package/front_end/third_party/lighthouse/locales/it.json +37 -40
  121. package/front_end/third_party/lighthouse/locales/ja.json +16 -19
  122. package/front_end/third_party/lighthouse/locales/ko.json +16 -19
  123. package/front_end/third_party/lighthouse/locales/lt.json +17 -20
  124. package/front_end/third_party/lighthouse/locales/lv.json +0 -3
  125. package/front_end/third_party/lighthouse/locales/nl.json +16 -19
  126. package/front_end/third_party/lighthouse/locales/no.json +17 -20
  127. package/front_end/third_party/lighthouse/locales/pl.json +16 -19
  128. package/front_end/third_party/lighthouse/locales/pt-PT.json +37 -40
  129. package/front_end/third_party/lighthouse/locales/pt.json +16 -19
  130. package/front_end/third_party/lighthouse/locales/ro.json +0 -3
  131. package/front_end/third_party/lighthouse/locales/ru.json +16 -19
  132. package/front_end/third_party/lighthouse/locales/sk.json +0 -3
  133. package/front_end/third_party/lighthouse/locales/sl.json +0 -3
  134. package/front_end/third_party/lighthouse/locales/sr-Latn.json +16 -19
  135. package/front_end/third_party/lighthouse/locales/sr.json +16 -19
  136. package/front_end/third_party/lighthouse/locales/sv.json +17 -20
  137. package/front_end/third_party/lighthouse/locales/ta.json +0 -3
  138. package/front_end/third_party/lighthouse/locales/te.json +0 -3
  139. package/front_end/third_party/lighthouse/locales/th.json +0 -3
  140. package/front_end/third_party/lighthouse/locales/tr.json +0 -3
  141. package/front_end/third_party/lighthouse/locales/uk.json +17 -20
  142. package/front_end/third_party/lighthouse/locales/vi.json +0 -3
  143. package/front_end/third_party/lighthouse/locales/zh-HK.json +0 -3
  144. package/front_end/third_party/lighthouse/locales/zh-TW.json +0 -3
  145. package/front_end/third_party/lighthouse/locales/zh.json +0 -3
  146. package/front_end/third_party/lighthouse/report/bundle.d.ts +63 -61
  147. package/front_end/third_party/lighthouse/report/bundle.js +36 -7
  148. package/front_end/third_party/lighthouse/report-assets/report-generator.js +205 -192
  149. package/front_end/ui/components/linear_memory_inspector/LinearMemoryValueInterpreter.ts +0 -8
  150. package/front_end/ui/components/text_editor/config.ts +8 -7
  151. package/front_end/ui/components/text_editor/javascript.ts +28 -10
  152. package/front_end/ui/components/text_editor/theme.ts +1 -0
  153. package/front_end/ui/legacy/InspectorView.ts +10 -0
  154. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +2 -3
  155. package/front_end/ui/legacy/components/object_ui/objectPropertiesSection.css +0 -1
  156. package/front_end/ui/legacy/components/object_ui/object_ui-legacy.ts +0 -8
  157. package/front_end/ui/legacy/components/object_ui/object_ui.ts +0 -4
  158. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +40 -29
  159. package/front_end/ui/legacy/inspectorSyntaxHighlight.css +0 -211
  160. package/front_end/ui/legacy/legacy-legacy.ts +0 -6
  161. package/front_end/ui/legacy/legacy.ts +0 -2
  162. package/front_end/ui/legacy/tabbedPane.css +1 -1
  163. package/front_end/ui/legacy/themeColors.css +1 -1
  164. package/package.json +1 -1
  165. package/scripts/check_gn.js +1 -1
  166. package/scripts/eslint_rules/lib/l10n_filename_matches.js +4 -4
  167. package/scripts/eslint_rules/tests/l10n_filename_matches_test.js +4 -0
  168. package/scripts/hosted_mode/server.js +17 -2
  169. package/front_end/entrypoints/inspector/inspector.json +0 -4
  170. package/front_end/entrypoints/node_app/node_app-meta.ts +0 -43
  171. package/front_end/entrypoints/node_app/node_app.js +0 -13
  172. package/front_end/entrypoints/node_app/node_app.json +0 -4
  173. package/front_end/entrypoints/node_main/node_main-meta.ts +0 -48
  174. package/front_end/entrypoints/node_main/node_main.ts +0 -11
  175. package/front_end/entrypoints/shell/shell-meta-files.ts +0 -22
  176. package/front_end/entrypoints/shell/shell.json +0 -5
  177. package/front_end/entrypoints/worker_app/worker_app.json +0 -4
  178. package/front_end/panels/lighthouse/module.json +0 -6
  179. package/front_end/third_party/lighthouse/report-assets/report.d.ts +0 -1
  180. package/front_end/third_party/lighthouse/report-assets/report.js +0 -233
  181. package/front_end/third_party/lighthouse/report-assets/standalone-template.html +0 -38
  182. package/front_end/ui/legacy/TextEditor.ts +0 -82
  183. package/front_end/ui/legacy/components/object_ui/JavaScriptAutocomplete.ts +0 -836
  184. package/front_end/ui/legacy/components/text_editor/CodeMirrorTextEditor.ts +0 -1676
  185. package/front_end/ui/legacy/components/text_editor/TextEditorAutocompleteController.ts +0 -586
  186. package/front_end/ui/legacy/components/text_editor/autocompleteTooltip.css +0 -20
  187. package/front_end/ui/legacy/components/text_editor/cm_modes.ts +0 -23
  188. package/front_end/ui/legacy/components/text_editor/cmdevtools.css +0 -995
  189. package/front_end/ui/legacy/components/text_editor/module.json +0 -7
  190. package/front_end/ui/legacy/components/text_editor/text_editor-legacy.ts +0 -33
  191. package/front_end/ui/legacy/components/text_editor/text_editor.ts +0 -13
@@ -1,1676 +0,0 @@
1
- /*
2
- * Copyright (C) 2012 Google Inc. All rights reserved.
3
- *
4
- * Redistribution and use in source and binary forms, with or without
5
- * modification, are permitted provided that the following conditions are
6
- * met:
7
- *
8
- * * Redistributions of source code must retain the above copyright
9
- * notice, this list of conditions and the following disclaimer.
10
- * * Redistributions in binary form must reproduce the above
11
- * copyright notice, this list of conditions and the following disclaimer
12
- * in the documentation and/or other materials provided with the
13
- * distribution.
14
- * * Neither the name of Google Inc. nor the names of its
15
- * contributors may be used to endorse or promote products derived from
16
- * this software without specific prior written permission.
17
- *
18
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
- */
30
-
31
- /* eslint-disable @typescript-eslint/no-explicit-any */
32
- /* eslint-disable @typescript-eslint/naming-convention */
33
-
34
- import * as Common from '../../../../core/common/common.js';
35
- import * as Host from '../../../../core/host/host.js';
36
- import * as i18n from '../../../../core/i18n/i18n.js';
37
- import * as Platform from '../../../../core/platform/platform.js';
38
- import * as TextUtils from '../../../../models/text_utils/text_utils.js';
39
- import * as UI from '../../legacy.js';
40
-
41
- import {TextEditorAutocompleteController} from './TextEditorAutocompleteController.js';
42
-
43
- const UIStrings = {
44
- /**
45
- *@description Text in Code Mirror Text Editor of the CodeMirror text editor
46
- */
47
- codeEditor: 'Code editor',
48
- };
49
- const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/text_editor/CodeMirrorTextEditor.ts', UIStrings);
50
- const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
51
-
52
- export interface Token {
53
- startColumn: number;
54
- endColumn: number;
55
- type: string;
56
- }
57
-
58
- export interface Coordinates {
59
- x: number;
60
- y: number;
61
- height: number;
62
- }
63
-
64
- // https://crbug.com/1151919 * = CodeMirror.Editor
65
- const editorToDevtoolsWrapper = new WeakMap<any, CodeMirrorTextEditor>();
66
-
67
- export class CodeMirrorTextEditor extends
68
- Common.ObjectWrapper.eventMixin<UI.TextEditor.EventTypes, typeof UI.Widget.VBox>(UI.Widget.VBox)
69
- implements UI.TextEditor.TextEditor {
70
- private options: UI.TextEditor.Options;
71
- // https://crbug.com/1151919 * = CodeMirror.Editor
72
- private codeMirrorInternal: any;
73
- private readonly codeMirrorElement: HTMLElement;
74
- private shouldClearHistory: boolean;
75
- private lineSeparator: string;
76
- private hasOneLine!: boolean;
77
- // https://crbug.com/1151919 * = CodeMirror.TextMarker
78
- private readonly bookmarkForMarker: WeakMap<any, TextEditorBookMark>;
79
- private readonly selectNextOccurrenceController: SelectNextOccurrenceController;
80
- private readonly decorations: Platform.MapUtilities.Multimap<number, Decoration>;
81
- private needsRefresh: boolean;
82
- private readOnlyInternal: boolean;
83
- private mimeTypeInternal: string;
84
- private placeholderElement: HTMLPreElement|null;
85
- autocompleteController?: TextEditorAutocompleteController;
86
- private highlightedLine?: any;
87
- private clearHighlightTimeout?: number;
88
- private editorSizeInSync?: boolean;
89
- private lastSelectionInternal?: TextUtils.TextRange.TextRange;
90
- private selectionSetScheduled?: boolean;
91
-
92
- constructor(options: UI.TextEditor.Options) {
93
- super();
94
- this.options = options;
95
-
96
- // eslint-disable-next-line no-restricted-syntax -- Should import styles https://crbug.com/1106746
97
- this.registerRequiredCSS('third_party/codemirror/codemirror.css');
98
- // eslint-disable-next-line no-restricted-syntax -- Should import styles https://crbug.com/1106746
99
- this.registerRequiredCSS('ui/legacy/components/text_editor/cmdevtools.css');
100
-
101
- const {indentWithTabs, indentUnit} = CodeMirrorTextEditor.getIndentation(
102
- Common.Settings.Settings.instance().moduleSetting('textEditorIndent').get());
103
- // @ts-ignore TODO(crbug.com/1172300) Properly type this after jsdoc to ts migration
104
- this.codeMirrorInternal = new CodeMirror(this.element, {
105
- screenReaderLabel: options.devtoolsAccessibleName || i18nString(UIStrings.codeEditor),
106
- lineNumbers: options.lineNumbers,
107
- smartIndent: true,
108
- electricChars: true,
109
- indentUnit,
110
- indentWithTabs,
111
- lineWrapping: options.lineWrapping,
112
- lineWiseCopyCut: options.lineWiseCopyCut || false,
113
- pollInterval: Math.pow(2, 31) - 1,
114
- matchBrackets: true,
115
- inputStyle: (options.inputStyle || 'devToolsAccessibleTextArea') as unknown as undefined,
116
- styleSelectedText: true,
117
- styleActiveLine: true,
118
- tabIndex: 0,
119
- });
120
- this.codeMirrorElement = this.element.lastElementChild as HTMLElement;
121
-
122
- editorToDevtoolsWrapper.set(this.codeMirrorInternal, this);
123
-
124
- Common.Settings.Settings.instance()
125
- .moduleSetting('textEditorIndent')
126
- .addChangeListener(this.updateIndentSize.bind(this));
127
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
128
- CodeMirror.keyMap['devtools-common'] = {
129
- 'Left': 'goCharLeft',
130
- 'Right': 'goCharRight',
131
- 'Up': 'goLineUp',
132
- 'Down': 'goLineDown',
133
- 'End': 'goLineEnd',
134
- 'Home': 'goLineStartSmart',
135
- 'PageUp': 'goSmartPageUp',
136
- 'PageDown': 'goSmartPageDown',
137
- 'Delete': 'delCharAfter',
138
- 'Backspace': 'delCharBefore',
139
- 'Tab': 'UserIndent',
140
- 'Shift-Tab': 'indentLessOrPass',
141
- 'Enter': 'newlineAndIndent',
142
- 'Ctrl-Space': 'autocomplete',
143
- 'Esc': 'dismiss',
144
- 'Ctrl-M': 'gotoMatchingBracket',
145
- };
146
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
147
- CodeMirror.keyMap['devtools-pc'] = {
148
- 'Ctrl-A': 'selectAll',
149
- 'Ctrl-Z': 'undoAndReveal',
150
- 'Shift-Ctrl-Z': 'redoAndReveal',
151
- 'Ctrl-Y': 'redo',
152
- 'Ctrl-Home': 'goDocStart',
153
- 'Ctrl-Up': 'goDocStart',
154
- 'Ctrl-End': 'goDocEnd',
155
- 'Ctrl-Down': 'goDocEnd',
156
- 'Ctrl-Left': 'goGroupLeft',
157
- 'Ctrl-Right': 'goGroupRight',
158
- 'Alt-Left': 'moveCamelLeft',
159
- 'Alt-Right': 'moveCamelRight',
160
- 'Shift-Alt-Left': 'selectCamelLeft',
161
- 'Shift-Alt-Right': 'selectCamelRight',
162
- 'Ctrl-Backspace': 'delGroupBefore',
163
- 'Ctrl-Delete': 'delGroupAfter',
164
- 'Ctrl-/': 'toggleComment',
165
- 'Ctrl-D': 'selectNextOccurrence',
166
- 'Ctrl-U': 'undoLastSelection',
167
- fallthrough: 'devtools-common',
168
- };
169
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
170
- CodeMirror.keyMap['devtools-mac'] = {
171
- 'Cmd-A': 'selectAll',
172
- 'Cmd-Z': 'undoAndReveal',
173
- 'Shift-Cmd-Z': 'redoAndReveal',
174
- 'Cmd-Up': 'goDocStart',
175
- 'Cmd-Down': 'goDocEnd',
176
- 'Alt-Left': 'goGroupLeft',
177
- 'Alt-Right': 'goGroupRight',
178
- 'Ctrl-Left': 'moveCamelLeft',
179
- 'Ctrl-Right': 'moveCamelRight',
180
- 'Ctrl-A': 'goLineLeft',
181
- 'Ctrl-E': 'goLineRight',
182
- 'Ctrl-B': 'goCharLeft',
183
- 'Ctrl-F': 'goCharRight',
184
- 'Ctrl-Alt-B': 'goGroupLeft',
185
- 'Ctrl-Alt-F': 'goGroupRight',
186
- 'Ctrl-H': 'delCharBefore',
187
- 'Ctrl-D': 'delCharAfter',
188
- 'Ctrl-K': 'killLine',
189
- 'Ctrl-T': 'transposeChars',
190
- 'Ctrl-P': 'goLineUp',
191
- 'Ctrl-N': 'goLineDown',
192
- 'Shift-Ctrl-Left': 'selectCamelLeft',
193
- 'Shift-Ctrl-Right': 'selectCamelRight',
194
- 'Cmd-Left': 'goLineStartSmart',
195
- 'Cmd-Right': 'goLineEnd',
196
- 'Cmd-Backspace': 'delLineLeft',
197
- 'Alt-Backspace': 'delGroupBefore',
198
- 'Alt-Delete': 'delGroupAfter',
199
- 'Cmd-/': 'toggleComment',
200
- 'Cmd-D': 'selectNextOccurrence',
201
- 'Cmd-U': 'undoLastSelection',
202
- fallthrough: 'devtools-common',
203
- };
204
-
205
- if (options.bracketMatchingSetting) {
206
- options.bracketMatchingSetting.addChangeListener(this.enableBracketMatchingIfNeeded, this);
207
- }
208
- this.enableBracketMatchingIfNeeded();
209
-
210
- this.codeMirrorInternal.setOption('keyMap', Host.Platform.isMac() ? 'devtools-mac' : 'devtools-pc');
211
-
212
- this.codeMirrorInternal.setOption('flattenSpans', false);
213
-
214
- let maxHighlightLength = options.maxHighlightLength;
215
- if (typeof maxHighlightLength !== 'number') {
216
- maxHighlightLength = CodeMirrorTextEditor.maxHighlightLength;
217
- }
218
- this.codeMirrorInternal.setOption('maxHighlightLength', maxHighlightLength);
219
- this.codeMirrorInternal.setOption('mode', null);
220
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
221
- this.codeMirrorInternal.setOption('crudeMeasuringFrom', 1000);
222
-
223
- this.shouldClearHistory = true;
224
- this.lineSeparator = '\n';
225
-
226
- this.bookmarkForMarker = new WeakMap();
227
-
228
- CodeMirrorTextEditor.fixWordMovement(this.codeMirrorInternal);
229
-
230
- this.selectNextOccurrenceController = new SelectNextOccurrenceController(this, this.codeMirrorInternal);
231
-
232
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
233
- this.codeMirrorInternal.on('changes', this.changes.bind(this));
234
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
235
- this.codeMirrorInternal.on('beforeSelectionChange', this.beforeSelectionChange.bind(this));
236
- this.codeMirrorInternal.on('cursorActivity', () => {
237
- this.dispatchEventToListeners(UI.TextEditor.Events.CursorChanged);
238
- });
239
-
240
- this.element.style.overflow = 'hidden';
241
- this.codeMirrorElement.classList.add('source-code');
242
- this.codeMirrorElement.classList.add('fill');
243
-
244
- this.decorations = new Platform.MapUtilities.Multimap();
245
-
246
- this.element.addEventListener('keydown', this.handleKeyDown.bind(this), true);
247
- this.element.addEventListener('keydown', this.handlePostKeyDown.bind(this), false);
248
-
249
- this.needsRefresh = true;
250
-
251
- this.readOnlyInternal = false;
252
-
253
- this.mimeTypeInternal = '';
254
- if (options.mimeType) {
255
- this.setMimeType(options.mimeType);
256
- }
257
- if (options.autoHeight) {
258
- this.codeMirrorInternal.setSize(null, 'auto');
259
- }
260
-
261
- this.placeholderElement = null;
262
- if (options.placeholder) {
263
- this.placeholderElement = document.createElement('pre');
264
- this.placeholderElement.classList.add('placeholder-text');
265
- this.placeholderElement.classList.add('CodeMirror-line-like');
266
- this.placeholderElement.textContent = options.placeholder;
267
- this.updatePlaceholder();
268
- }
269
- }
270
-
271
- // https://crbug.com/1151919 * = CodeMirror.Editor
272
- static getForCodeMirror(codeMirrorEditor: any): CodeMirrorTextEditor {
273
- const wrapper = editorToDevtoolsWrapper.get(codeMirrorEditor);
274
- if (!wrapper) {
275
- throw new Error('CodeMirrorTextEditor not found');
276
- }
277
- return wrapper;
278
- }
279
-
280
- // https://crbug.com/1151919 * = CodeMirror.Editor
281
- static autocompleteCommand(codeMirror: any): void {
282
- const autocompleteController = CodeMirrorTextEditor.getForCodeMirror(codeMirror).autocompleteController;
283
- if (autocompleteController) {
284
- autocompleteController.autocomplete(true);
285
- }
286
- }
287
-
288
- // https://crbug.com/1151919 * = CodeMirror.Editor
289
- static undoLastSelectionCommand(codeMirror: any): void {
290
- CodeMirrorTextEditor.getForCodeMirror(codeMirror).selectNextOccurrenceController.undoLastSelection();
291
- }
292
-
293
- // https://crbug.com/1151919 * = CodeMirror.Editor
294
- static selectNextOccurrenceCommand(codeMirror: any): void {
295
- CodeMirrorTextEditor.getForCodeMirror(codeMirror).selectNextOccurrenceController.selectNextOccurrence();
296
- }
297
-
298
- // https://crbug.com/1151919 * = CodeMirror.Editor
299
- static moveCamelLeftCommand(shift: boolean, codeMirror: any): void {
300
- CodeMirrorTextEditor.getForCodeMirror(codeMirror).doCamelCaseMovement(-1, shift);
301
- }
302
-
303
- // https://crbug.com/1151919 * = CodeMirror.Editor
304
- static moveCamelRightCommand(shift: boolean, codeMirror: any): void {
305
- CodeMirrorTextEditor.getForCodeMirror(codeMirror).doCamelCaseMovement(1, shift);
306
- }
307
-
308
- private static getIndentation(indentationValue: string): {
309
- indentWithTabs: boolean,
310
- indentUnit: number,
311
- } {
312
- const indentWithTabs = /\t/.test(indentationValue);
313
- const indentUnit = indentWithTabs ? 4 : indentationValue.length;
314
- return {indentWithTabs, indentUnit};
315
- }
316
-
317
- static overrideModeWithPrefixedTokens(modeName: string, tokenPrefix: string): void {
318
- const oldModeName = modeName + '-old';
319
- if (CodeMirror.modes[oldModeName]) {
320
- return;
321
- }
322
-
323
- CodeMirror.defineMode(oldModeName, CodeMirror.modes[modeName]);
324
- CodeMirror.defineMode(modeName, modeConstructor);
325
-
326
- // @ts-ignore TODO(crbug.com/1172300) Properly type this after jsdoc to ts migration
327
- function modeConstructor(config: any, parserConfig: any): any {
328
- // TODO(crbug.com/1172300) Properly type this after jsdoc to ts migration
329
- const innerConfig: any = {};
330
- for (const i in parserConfig) {
331
- innerConfig[i] = parserConfig[i];
332
- }
333
- innerConfig.name = oldModeName;
334
- const codeMirrorMode = CodeMirror.getMode(config, innerConfig);
335
- codeMirrorMode.name = modeName;
336
- if (typeof codeMirrorMode.token === 'undefined') {
337
- throw new Error('codeMirrorMode.token was unexpectedly undefined');
338
- }
339
- codeMirrorMode.token = getTokenFunction(codeMirrorMode.token);
340
- return codeMirrorMode;
341
- }
342
-
343
- function getTokenFunction(superToken: (arg0: any, arg1: any) => string | null): (stream: any, state: any) =>
344
- string | null {
345
- function childFunc(stream: any, state: any): string|null {
346
- return tokenOverride(superToken, stream, state);
347
- }
348
-
349
- return childFunc;
350
- }
351
- function tokenOverride(superToken: (arg0: any, arg1: any) => string | null, stream: any, state: any): string|null {
352
- const token = superToken(stream, state);
353
- return token ? tokenPrefix + token.split(/ +/).join(' ' + tokenPrefix) : token;
354
- }
355
- }
356
-
357
- // https://crbug.com/1151919 * = CodeMirror.Editor
358
- private static fixWordMovement(codeMirror: any): void {
359
- // https://crbug.com/1151919 * = CodeMirror.Editor
360
- function moveLeft(shift: boolean, codeMirror: any): void {
361
- codeMirror.setExtending(shift);
362
- const cursor = codeMirror.getCursor('head');
363
- codeMirror.execCommand('goGroupLeft');
364
- const newCursor = codeMirror.getCursor('head');
365
- if (newCursor.ch === 0 && newCursor.line !== 0) {
366
- codeMirror.setExtending(false);
367
- return;
368
- }
369
-
370
- const skippedText = codeMirror.getRange(newCursor, cursor, '#');
371
- if (/^\s+$/.test(skippedText)) {
372
- codeMirror.execCommand('goGroupLeft');
373
- }
374
- codeMirror.setExtending(false);
375
- }
376
-
377
- // https://crbug.com/1151919 * = CodeMirror.Editor
378
- function moveRight(shift: boolean, codeMirror: any): void {
379
- codeMirror.setExtending(shift);
380
- const cursor = codeMirror.getCursor('head');
381
- codeMirror.execCommand('goGroupRight');
382
- const newCursor = codeMirror.getCursor('head');
383
- if (newCursor.ch === 0 && newCursor.line !== 0) {
384
- codeMirror.setExtending(false);
385
- return;
386
- }
387
-
388
- const skippedText = codeMirror.getRange(cursor, newCursor, '#');
389
- if (/^\s+$/.test(skippedText)) {
390
- codeMirror.execCommand('goGroupRight');
391
- }
392
- codeMirror.setExtending(false);
393
- }
394
-
395
- const modifierKey = Host.Platform.isMac() ? 'Alt' : 'Ctrl';
396
- const leftKey = modifierKey + '-Left';
397
- const rightKey = modifierKey + '-Right';
398
- const keyMap: {[key: string]: Function} = {};
399
- keyMap[leftKey] = moveLeft.bind(null, false);
400
- keyMap[rightKey] = moveRight.bind(null, false);
401
- keyMap['Shift-' + leftKey] = moveLeft.bind(null, true);
402
- keyMap['Shift-' + rightKey] = moveRight.bind(null, true);
403
- codeMirror.addKeyMap(keyMap);
404
- }
405
-
406
- // https://crbug.com/1151919 * = CodeMirror.Editor
407
- codeMirror(): any {
408
- // https://crbug.com/1151919 * = CodeMirror.Editor
409
- return /** @type {*} */ this.codeMirrorInternal as any;
410
- }
411
-
412
- widget(): UI.Widget.Widget {
413
- return this;
414
- }
415
-
416
- setPlaceholder(placeholder: string): void {
417
- if (!this.placeholderElement) {
418
- this.placeholderElement = document.createElement('pre');
419
- this.placeholderElement.classList.add('placeholder-text');
420
- this.placeholderElement.classList.add('CodeMirror-line-like');
421
- }
422
- this.placeholderElement.textContent = placeholder || '';
423
- this.updatePlaceholder();
424
- }
425
-
426
- private normalizePositionForOverlappingColumn(lineNumber: number, lineLength: number, charNumber: number): {
427
- lineNumber: number,
428
- columnNumber: number,
429
- } {
430
- const linesCount = this.codeMirrorInternal.lineCount();
431
- let columnNumber: number|0 = charNumber;
432
- if (charNumber < 0 && lineNumber > 0) {
433
- --lineNumber;
434
- columnNumber = this.line(lineNumber).length;
435
- } else if (charNumber >= lineLength && lineNumber < linesCount - 1) {
436
- ++lineNumber;
437
- columnNumber = 0;
438
- } else {
439
- columnNumber = Platform.NumberUtilities.clamp(charNumber, 0, lineLength);
440
- }
441
- return {lineNumber: lineNumber, columnNumber: columnNumber};
442
- }
443
-
444
- private camelCaseMoveFromPosition(lineNumber: number, columnNumber: number, direction: number): {
445
- lineNumber: number,
446
- columnNumber: number,
447
- } {
448
- function valid(charNumber: number, length: number): boolean {
449
- return charNumber >= 0 && charNumber < length;
450
- }
451
-
452
- function isWordStart(text: string, charNumber: number): boolean {
453
- const position = charNumber;
454
- const nextPosition = charNumber + 1;
455
- return valid(position, text.length) && valid(nextPosition, text.length) &&
456
- TextUtils.TextUtils.Utils.isWordChar(text[position]) &&
457
- TextUtils.TextUtils.Utils.isWordChar(text[nextPosition]) &&
458
- TextUtils.TextUtils.Utils.isUpperCase(text[position]) &&
459
- TextUtils.TextUtils.Utils.isLowerCase(text[nextPosition]);
460
- }
461
-
462
- function isWordEnd(text: string, charNumber: number): boolean {
463
- const position = charNumber;
464
- const prevPosition = charNumber - 1;
465
- return valid(position, text.length) && valid(prevPosition, text.length) &&
466
- TextUtils.TextUtils.Utils.isWordChar(text[position]) &&
467
- TextUtils.TextUtils.Utils.isWordChar(text[prevPosition]) &&
468
- TextUtils.TextUtils.Utils.isUpperCase(text[position]) &&
469
- TextUtils.TextUtils.Utils.isLowerCase(text[prevPosition]);
470
- }
471
-
472
- function constrainPosition(lineNumber: number, lineLength: number, columnNumber: number): {
473
- lineNumber: number,
474
- columnNumber: number,
475
- } {
476
- return {lineNumber: lineNumber, columnNumber: Platform.NumberUtilities.clamp(columnNumber, 0, lineLength)};
477
- }
478
-
479
- const text = this.line(lineNumber);
480
- const length = text.length;
481
-
482
- if ((columnNumber === length && direction === 1) || (columnNumber === 0 && direction === -1)) {
483
- return this.normalizePositionForOverlappingColumn(lineNumber, length, columnNumber + direction);
484
- }
485
-
486
- let charNumber = direction === 1 ? columnNumber : columnNumber - 1;
487
-
488
- // Move through initial spaces if any.
489
- while (valid(charNumber, length) && TextUtils.TextUtils.Utils.isSpaceChar(text[charNumber])) {
490
- charNumber += direction;
491
- }
492
- if (!valid(charNumber, length)) {
493
- return constrainPosition(lineNumber, length, charNumber);
494
- }
495
-
496
- if (TextUtils.TextUtils.Utils.isStopChar(text[charNumber])) {
497
- while (valid(charNumber, length) && TextUtils.TextUtils.Utils.isStopChar(text[charNumber])) {
498
- charNumber += direction;
499
- }
500
- if (!valid(charNumber, length)) {
501
- return constrainPosition(lineNumber, length, charNumber);
502
- }
503
- return {lineNumber: lineNumber, columnNumber: direction === -1 ? charNumber + 1 : charNumber};
504
- }
505
-
506
- charNumber += direction;
507
- while (valid(charNumber, length) && !isWordStart(text, charNumber) && !isWordEnd(text, charNumber) &&
508
- TextUtils.TextUtils.Utils.isWordChar(text[charNumber])) {
509
- charNumber += direction;
510
- }
511
-
512
- if (!valid(charNumber, length)) {
513
- return constrainPosition(lineNumber, length, charNumber);
514
- }
515
- if (isWordStart(text, charNumber) || isWordEnd(text, charNumber)) {
516
- return {lineNumber: lineNumber, columnNumber: charNumber};
517
- }
518
-
519
- return {lineNumber: lineNumber, columnNumber: direction === -1 ? charNumber + 1 : charNumber};
520
- }
521
-
522
- private doCamelCaseMovement(direction: number, shift: boolean): void {
523
- const selections = this.selections();
524
- for (let i = 0; i < selections.length; ++i) {
525
- const selection = selections[i];
526
- const move = this.camelCaseMoveFromPosition(selection.endLine, selection.endColumn, direction);
527
- selection.endLine = move.lineNumber;
528
- selection.endColumn = move.columnNumber;
529
- if (!shift) {
530
- selections[i] = selection.collapseToEnd();
531
- }
532
- }
533
- this.setSelections(selections);
534
- }
535
-
536
- dispose(): void {
537
- if (this.options.bracketMatchingSetting) {
538
- this.options.bracketMatchingSetting.removeChangeListener(this.enableBracketMatchingIfNeeded, this);
539
- }
540
- }
541
-
542
- private enableBracketMatchingIfNeeded(): void {
543
- this.codeMirrorInternal.setOption(
544
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
545
- 'autoCloseBrackets',
546
- (this.options.bracketMatchingSetting && this.options.bracketMatchingSetting.get()) ? {explode: false} : false);
547
- }
548
-
549
- wasShown(): void {
550
- if (this.needsRefresh) {
551
- this.refresh();
552
- }
553
- }
554
-
555
- protected refresh(): void {
556
- if (this.isShowing()) {
557
- this.codeMirrorInternal.refresh();
558
- this.needsRefresh = false;
559
- return;
560
- }
561
- this.needsRefresh = true;
562
- }
563
-
564
- willHide(): void {
565
- delete this.editorSizeInSync;
566
- }
567
-
568
- undo(): void {
569
- this.codeMirrorInternal.undo();
570
- }
571
-
572
- redo(): void {
573
- this.codeMirrorInternal.redo();
574
- }
575
-
576
- private handleKeyDown(e: Event): void {
577
- const keyboardEvent = e as KeyboardEvent;
578
- if (keyboardEvent.key === 'Tab' &&
579
- Common.Settings.Settings.instance().moduleSetting('textEditorTabMovesFocus').get()) {
580
- keyboardEvent.consume(false);
581
- return;
582
- }
583
- if (this.autocompleteController && this.autocompleteController.keyDown(keyboardEvent)) {
584
- keyboardEvent.consume(true);
585
- }
586
- }
587
-
588
- private handlePostKeyDown(e: Event): void {
589
- if (e.defaultPrevented) {
590
- e.consume(true);
591
- }
592
- }
593
-
594
- configureAutocomplete(config: UI.TextEditor.AutocompleteConfig|null): void {
595
- if (this.autocompleteController) {
596
- this.autocompleteController.dispose();
597
- delete this.autocompleteController;
598
- }
599
-
600
- if (config) {
601
- this.autocompleteController = new TextEditorAutocompleteController(this, this.codeMirrorInternal, config);
602
- }
603
- }
604
-
605
- cursorPositionToCoordinates(lineNumber: number, column: number): Coordinates|null {
606
- if (lineNumber >= this.codeMirrorInternal.lineCount() || lineNumber < 0 || column < 0 ||
607
- column > this.codeMirrorInternal.getLine(lineNumber).length) {
608
- return null;
609
- }
610
- const metrics = this.codeMirrorInternal.cursorCoords(new CodeMirror.Pos(lineNumber, column));
611
- return {x: metrics.left, y: metrics.top, height: metrics.bottom - metrics.top};
612
- }
613
-
614
- coordinatesToCursorPosition(x: number, y: number): TextUtils.TextRange.TextRange|null {
615
- const element = this.element.ownerDocument.elementFromPoint(x, y);
616
- if (!element || !element.isSelfOrDescendant(this.codeMirrorInternal.getWrapperElement())) {
617
- return null;
618
- }
619
- const gutterBox = this.codeMirrorInternal.getGutterElement().boxInWindow();
620
- if (x >= gutterBox.x && x <= gutterBox.x + gutterBox.width && y >= gutterBox.y &&
621
- y <= gutterBox.y + gutterBox.height) {
622
- return null;
623
- }
624
- const coords = this.codeMirrorInternal.coordsChar({left: x, top: y});
625
- return TextUtils.CodeMirrorUtils.toRange(coords, coords);
626
- }
627
-
628
- visualCoordinates(lineNumber: number, columnNumber: number): {
629
- x: number,
630
- y: number,
631
- } {
632
- const metrics = this.codeMirrorInternal.cursorCoords(new CodeMirror.Pos(lineNumber, columnNumber));
633
- return {x: metrics.left, y: metrics.top};
634
- }
635
-
636
- tokenAtTextPosition(lineNumber: number, columnNumber: number): Token|null {
637
- if (lineNumber < 0 || lineNumber >= this.codeMirrorInternal.lineCount()) {
638
- return null;
639
- }
640
- const token = this.codeMirrorInternal.getTokenAt(new CodeMirror.Pos(lineNumber, (columnNumber || 0) + 1));
641
- if (!token) {
642
- return null;
643
- }
644
- return {startColumn: token.start, endColumn: token.end, type: token.type as string};
645
- }
646
-
647
- isClean(generation: number): boolean {
648
- return this.codeMirrorInternal.isClean(generation);
649
- }
650
-
651
- markClean(): number {
652
- return this.codeMirrorInternal.changeGeneration(true);
653
- }
654
-
655
- private hasLongLines(): boolean {
656
- function lineIterator(lineHandle: {
657
- text: string,
658
- }): boolean {
659
- if (lineHandle.text.length > CodeMirrorTextEditor.LongLineModeLineLengthThreshold) {
660
- hasLongLines = true;
661
- }
662
- return hasLongLines;
663
- }
664
- let hasLongLines = false;
665
- this.codeMirrorInternal.eachLine(lineIterator);
666
- return hasLongLines;
667
- }
668
-
669
- private enableLongLinesMode(): void {
670
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
671
- this.codeMirrorInternal.setOption('styleSelectedText', false);
672
- }
673
-
674
- private disableLongLinesMode(): void {
675
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
676
- this.codeMirrorInternal.setOption('styleSelectedText', true);
677
- }
678
-
679
- private updateIndentSize(updatedValue: {
680
- data: any,
681
- }): void {
682
- const {indentWithTabs, indentUnit} = CodeMirrorTextEditor.getIndentation(updatedValue.data as string);
683
-
684
- this.codeMirrorInternal.setOption('indentUnit', indentUnit);
685
- this.codeMirrorInternal.setOption('indentWithTabs', indentWithTabs);
686
- }
687
-
688
- setMimeType(mimeType: string): void {
689
- this.mimeTypeInternal = mimeType;
690
-
691
- const rewrittenMimeType = this.rewriteMimeType(mimeType);
692
- const modeOption = this.codeMirrorInternal.getOption('mode');
693
- if (modeOption !== rewrittenMimeType) {
694
- this.codeMirrorInternal.setOption('mode', rewrittenMimeType);
695
- }
696
- }
697
-
698
- setHighlightMode(mode: Object): void {
699
- this.mimeTypeInternal = '';
700
- this.codeMirrorInternal.setOption('mode', mode);
701
- }
702
-
703
- protected rewriteMimeType(mimeType: string): string {
704
- // Overridden in SourcesTextEditor
705
- return mimeType;
706
- }
707
-
708
- protected mimeType(): string {
709
- return this.mimeTypeInternal;
710
- }
711
-
712
- setReadOnly(readOnly: boolean): void {
713
- if (this.readOnlyInternal === readOnly) {
714
- return;
715
- }
716
- this.clearPositionHighlight();
717
- this.readOnlyInternal = readOnly;
718
- this.element.classList.toggle('CodeMirror-readonly', readOnly);
719
- this.codeMirrorInternal.setOption('readOnly', readOnly);
720
- }
721
-
722
- readOnly(): boolean {
723
- return Boolean(this.codeMirrorInternal.getOption('readOnly'));
724
- }
725
-
726
- setLineNumberFormatter(formatter: (arg0: number) => string): void {
727
- this.codeMirrorInternal.setOption('lineNumberFormatter', formatter);
728
- }
729
-
730
- addKeyDownHandler(handler: (arg0: KeyboardEvent) => void): void {
731
- this.codeMirrorInternal.on(
732
- 'keydown', /**
733
- * @param {*} CodeMirror
734
- * @param {!KeyboardEvent} event
735
- */
736
- (CodeMirror: any, event: KeyboardEvent) => handler(event));
737
- }
738
-
739
- addBookmark(lineNumber: number, columnNumber: number, element: HTMLElement, type: symbol, insertBefore?: boolean):
740
- TextEditorBookMark {
741
- const marker = this.codeMirrorInternal.setBookmark(
742
- new CodeMirror.Pos(lineNumber, columnNumber), {widget: element, insertLeft: insertBefore});
743
-
744
- const bookmark = new TextEditorBookMark(marker, type, this);
745
- this.bookmarkForMarker.set(marker, bookmark);
746
- this.updateDecorations(lineNumber);
747
- return bookmark;
748
- }
749
-
750
- bookmarks(range: TextUtils.TextRange.TextRange, type?: symbol): TextEditorBookMark[] {
751
- const pos = TextUtils.CodeMirrorUtils.toPos(range);
752
- let markers = this.codeMirrorInternal.findMarksAt(pos.start);
753
- if (!range.isEmpty()) {
754
- const middleMarkers = this.codeMirrorInternal.findMarks(pos.start, pos.end);
755
- const endMarkers = this.codeMirrorInternal.findMarksAt(pos.end);
756
- markers = markers.concat(middleMarkers, endMarkers);
757
- }
758
- const bookmarks: TextEditorBookMark[] = [];
759
- for (let i = 0; i < markers.length; i++) {
760
- const marker = markers[i];
761
- const bookmark = this.bookmarkForMarker.get(marker);
762
- if (bookmark && (!type || bookmark.type() === type)) {
763
- bookmarks.push(bookmark);
764
- }
765
- }
766
- return bookmarks;
767
- }
768
-
769
- focus(): void {
770
- this.codeMirrorInternal.focus();
771
- }
772
-
773
- hasFocus(): boolean {
774
- return this.codeMirrorInternal.hasFocus();
775
- }
776
-
777
- operation(operation: () => any): void {
778
- this.codeMirrorInternal.operation(operation);
779
- }
780
-
781
- scrollLineIntoView(lineNumber: number): void {
782
- this.innerRevealLine(lineNumber, this.codeMirrorInternal.getScrollInfo());
783
- }
784
-
785
- innerRevealLine(lineNumber: number, scrollInfo: {
786
- left: number,
787
- top: number,
788
- width: number,
789
- height: number,
790
- clientWidth: number,
791
- clientHeight: number,
792
- }): void {
793
- const topLine = this.codeMirrorInternal.lineAtHeight(scrollInfo.top, 'local');
794
- const bottomLine = this.codeMirrorInternal.lineAtHeight(scrollInfo.top + scrollInfo.clientHeight, 'local');
795
- const linesPerScreen = bottomLine - topLine + 1;
796
- if (lineNumber < topLine) {
797
- const topLineToReveal = Math.max(lineNumber - (linesPerScreen / 2) + 1, 0) | 0;
798
- this.codeMirrorInternal.scrollIntoView(new CodeMirror.Pos(topLineToReveal, 0));
799
- } else if (lineNumber > bottomLine) {
800
- const bottomLineToReveal = Math.min(lineNumber + (linesPerScreen / 2) - 1, this.linesCount - 1) | 0;
801
- this.codeMirrorInternal.scrollIntoView(new CodeMirror.Pos(bottomLineToReveal, 0));
802
- }
803
- }
804
-
805
- addDecoration(element: HTMLElement, lineNumber: number, startColumn?: number, endColumn?: number): void {
806
- const widget = this.codeMirrorInternal.addLineWidget(lineNumber, element);
807
- let update: (() => void)|null = null;
808
- if (typeof startColumn !== 'undefined') {
809
- if (typeof endColumn === 'undefined') {
810
- endColumn = Infinity;
811
- }
812
- update = this.updateFloatingDecoration.bind(this, element, lineNumber, startColumn, endColumn);
813
- update();
814
- }
815
-
816
- this.decorations.set(lineNumber, {element: element, update: update, widget: widget});
817
- }
818
-
819
- private updateFloatingDecoration(element: HTMLElement, lineNumber: number, startColumn: number, endColumn: number):
820
- void {
821
- const base = this.codeMirrorInternal.cursorCoords(new CodeMirror.Pos(lineNumber, 0), 'page');
822
- const start = this.codeMirrorInternal.cursorCoords(new CodeMirror.Pos(lineNumber, startColumn), 'page');
823
- const end = this.codeMirrorInternal.charCoords(new CodeMirror.Pos(lineNumber, endColumn), 'page');
824
- element.style.width = (end.right - start.left) + 'px';
825
- element.style.left = (start.left - base.left) + 'px';
826
- }
827
-
828
- updateDecorations(lineNumber: number): void {
829
- this.decorations.get(lineNumber).forEach(innerUpdateDecorations);
830
-
831
- function innerUpdateDecorations(decoration: Decoration): void {
832
- if (decoration.update) {
833
- decoration.update();
834
- }
835
- }
836
- }
837
-
838
- removeDecoration(element: Element, lineNumber: number): void {
839
- this.decorations.get(lineNumber).forEach(innerRemoveDecoration.bind(this));
840
-
841
- function innerRemoveDecoration(this: CodeMirrorTextEditor, decoration: Decoration): void {
842
- if (decoration.element !== element) {
843
- return;
844
- }
845
- this.codeMirrorInternal.removeLineWidget(decoration.widget);
846
- this.decorations.delete(lineNumber, decoration);
847
- }
848
- }
849
-
850
- revealPosition(lineNumber: number, columnNumber?: number, shouldHighlight?: boolean): void {
851
- lineNumber = Platform.NumberUtilities.clamp(lineNumber, 0, this.codeMirrorInternal.lineCount() - 1);
852
- if (typeof columnNumber !== 'number') {
853
- columnNumber = 0;
854
- }
855
- columnNumber = Platform.NumberUtilities.clamp(columnNumber, 0, this.codeMirrorInternal.getLine(lineNumber).length);
856
-
857
- this.clearPositionHighlight();
858
- this.highlightedLine = this.codeMirrorInternal.getLineHandle(lineNumber);
859
- if (!this.highlightedLine) {
860
- return;
861
- }
862
- this.scrollLineIntoView(lineNumber);
863
- if (shouldHighlight) {
864
- this.codeMirrorInternal.addLineClass(
865
- this.highlightedLine, null, this.readOnlyInternal ? 'cm-readonly-highlight' : 'cm-highlight');
866
- if (!this.readOnlyInternal) {
867
- this.clearHighlightTimeout = window.setTimeout(this.clearPositionHighlight.bind(this), 2000);
868
- }
869
- }
870
- this.setSelection(TextUtils.TextRange.TextRange.createFromLocation(lineNumber, columnNumber));
871
- }
872
-
873
- clearPositionHighlight(): void {
874
- if (this.clearHighlightTimeout) {
875
- clearTimeout(this.clearHighlightTimeout);
876
- }
877
- delete this.clearHighlightTimeout;
878
-
879
- if (this.highlightedLine) {
880
- this.codeMirrorInternal.removeLineClass(
881
- // @ts-ignore the `null` argument should be a string?
882
- this.highlightedLine, null, this.readOnlyInternal ? 'cm-readonly-highlight' : 'cm-highlight');
883
- }
884
- delete this.highlightedLine;
885
- }
886
-
887
- elementsToRestoreScrollPositionsFor(): Element[] {
888
- return [];
889
- }
890
-
891
- private updatePaddingBottom(width: number, height: number): void {
892
- let newPaddingBottom = 0;
893
- const linesElement = this.codeMirrorElement.getElementsByClassName('CodeMirror-lines')[0] as HTMLElement;
894
-
895
- if (this.options.padBottom) {
896
- const scrollInfo = this.codeMirrorInternal.getScrollInfo();
897
- const lineCount = this.codeMirrorInternal.lineCount();
898
- if (lineCount > 1) {
899
- newPaddingBottom =
900
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
901
- Math.max(
902
- scrollInfo.clientHeight -
903
- this.codeMirrorInternal.getLineHandle(this.codeMirrorInternal.lastLine()).height,
904
- 0);
905
- }
906
- }
907
- const stringPaddingBottomValue = String(newPaddingBottom) + 'px';
908
- if (linesElement.style.paddingBottom !== stringPaddingBottomValue) {
909
- linesElement.style.paddingBottom = stringPaddingBottomValue;
910
- this.codeMirrorInternal.setSize(width, height);
911
- }
912
- }
913
-
914
- toggleScrollPastEof(enableScrolling: boolean): void {
915
- if (this.options.padBottom === enableScrolling) {
916
- return;
917
- }
918
-
919
- this.options.padBottom = enableScrolling;
920
- this.resizeEditor();
921
- }
922
-
923
- private resizeEditor(): void {
924
- const parentElement = this.element.parentElement;
925
- if (!parentElement || !this.isShowing()) {
926
- return;
927
- }
928
- this.codeMirrorInternal.operation(() => {
929
- const scrollLeft = this.codeMirrorInternal.doc.scrollLeft;
930
- const scrollTop = this.codeMirrorInternal.doc.scrollTop;
931
- const width = parentElement.offsetWidth;
932
- const height = parentElement.offsetHeight - this.element.offsetTop;
933
- if (this.options.autoHeight) {
934
- this.codeMirrorInternal.setSize(width, 'auto');
935
- } else {
936
- this.codeMirrorInternal.setSize(width, height);
937
- this.updatePaddingBottom(width, height);
938
- }
939
- this.codeMirrorInternal.scrollTo(scrollLeft, scrollTop);
940
- });
941
- }
942
-
943
- onResize(): void {
944
- if (this.autocompleteController) {
945
- this.autocompleteController.clearAutocomplete();
946
- }
947
- this.resizeEditor();
948
- this.editorSizeInSync = true;
949
- if (this.selectionSetScheduled) {
950
- delete this.selectionSetScheduled;
951
- if (this.lastSelectionInternal) {
952
- this.setSelection(this.lastSelectionInternal);
953
- }
954
- }
955
- }
956
-
957
- editRange(range: TextUtils.TextRange.TextRange, text: string, origin?: string): TextUtils.TextRange.TextRange {
958
- const pos = TextUtils.CodeMirrorUtils.toPos(range);
959
- this.codeMirrorInternal.replaceRange(text, pos.start, pos.end, origin);
960
- const newRange = TextUtils.CodeMirrorUtils.toRange(
961
- pos.start, this.codeMirrorInternal.posFromIndex(this.codeMirrorInternal.indexFromPos(pos.start) + text.length));
962
- this.dispatchEventToListeners(UI.TextEditor.Events.TextChanged, {oldRange: range, newRange: newRange});
963
- return newRange;
964
- }
965
-
966
- clearAutocomplete(): void {
967
- if (this.autocompleteController) {
968
- this.autocompleteController.clearAutocomplete();
969
- }
970
- }
971
-
972
- wordRangeForCursorPosition(lineNumber: number, column: number, isWordChar: (arg0: string) => boolean):
973
- TextUtils.TextRange.TextRange {
974
- const line = this.line(lineNumber);
975
- let wordStart: number = column;
976
- if (column !== 0 && isWordChar(line.charAt(column - 1))) {
977
- wordStart = column - 1;
978
- while (wordStart > 0 && isWordChar(line.charAt(wordStart - 1))) {
979
- --wordStart;
980
- }
981
- }
982
- let wordEnd = column;
983
- while (wordEnd < line.length && isWordChar(line.charAt(wordEnd))) {
984
- ++wordEnd;
985
- }
986
- return new TextUtils.TextRange.TextRange(lineNumber, wordStart, lineNumber, wordEnd);
987
- }
988
-
989
- // https://crbug.com/1151919 first * = CodeMirror.Editor, second * = CodeMirror.EditorChangeLinkedList
990
- private changes(codeMirror: any, changes: any): void {
991
- if (!changes.length) {
992
- return;
993
- }
994
-
995
- this.updatePlaceholder();
996
-
997
- // We do not show "scroll beyond end of file" span for one line documents, so we need to check if "document has one line" changed.
998
- const hasOneLine = this.codeMirrorInternal.lineCount() === 1;
999
- if (hasOneLine !== this.hasOneLine) {
1000
- this.resizeEditor();
1001
- }
1002
- this.hasOneLine = hasOneLine;
1003
-
1004
- this.decorations.valuesArray().forEach(decoration => this.codeMirrorInternal.removeLineWidget(decoration.widget));
1005
- this.decorations.clear();
1006
-
1007
- const edits = [];
1008
- let currentEdit;
1009
-
1010
- for (let changeIndex = 0; changeIndex < changes.length; ++changeIndex) {
1011
- const changeObject = changes[changeIndex];
1012
- const edit = TextUtils.CodeMirrorUtils.changeObjectToEditOperation(changeObject);
1013
- if (currentEdit && edit.oldRange.equal(currentEdit.newRange)) {
1014
- currentEdit.newRange = edit.newRange;
1015
- } else {
1016
- currentEdit = edit;
1017
- edits.push(currentEdit);
1018
- }
1019
- }
1020
-
1021
- for (let i = 0; i < edits.length; i++) {
1022
- this.dispatchEventToListeners(
1023
- UI.TextEditor.Events.TextChanged, {oldRange: edits[i].oldRange, newRange: edits[i].newRange});
1024
- }
1025
- }
1026
-
1027
- // https://crbug.com/1151919 first * = CodeMirror.Editor, second and third * = CodeMirror.Pos
1028
- private beforeSelectionChange(_codeMirror: any, _selection: {
1029
- ranges: Array<{
1030
- head: any,
1031
- anchor: any,
1032
- }>,
1033
- }): void {
1034
- this.selectNextOccurrenceController.selectionWillChange();
1035
- }
1036
-
1037
- scrollToLine(lineNumber: number): void {
1038
- const pos = new CodeMirror.Pos(lineNumber, 0);
1039
- const coords = this.codeMirrorInternal.charCoords(pos, 'local');
1040
- this.codeMirrorInternal.scrollTo(0, coords.top);
1041
- }
1042
-
1043
- firstVisibleLine(): number {
1044
- return this.codeMirrorInternal.lineAtHeight(this.codeMirrorInternal.getScrollInfo().top, 'local');
1045
- }
1046
-
1047
- scrollTop(): number {
1048
- return this.codeMirrorInternal.getScrollInfo().top;
1049
- }
1050
-
1051
- setScrollTop(scrollTop: number): void {
1052
- this.codeMirrorInternal.scrollTo(0, scrollTop);
1053
- }
1054
-
1055
- lastVisibleLine(): number {
1056
- const scrollInfo = this.codeMirrorInternal.getScrollInfo();
1057
- return this.codeMirrorInternal.lineAtHeight(scrollInfo.top + scrollInfo.clientHeight, 'local');
1058
- }
1059
-
1060
- selection(): TextUtils.TextRange.TextRange {
1061
- const start = this.codeMirrorInternal.getCursor('anchor');
1062
- const end = this.codeMirrorInternal.getCursor('head');
1063
-
1064
- return TextUtils.CodeMirrorUtils.toRange(start, end);
1065
- }
1066
-
1067
- selections(): TextUtils.TextRange.TextRange[] {
1068
- const selectionList = this.codeMirrorInternal.listSelections();
1069
- const result = [];
1070
- for (let i = 0; i < selectionList.length; ++i) {
1071
- const selection = selectionList[i];
1072
- result.push(TextUtils.CodeMirrorUtils.toRange(selection.anchor, selection.head));
1073
- }
1074
- return result;
1075
- }
1076
-
1077
- lastSelection(): TextUtils.TextRange.TextRange|null {
1078
- return this.lastSelectionInternal || null;
1079
- }
1080
-
1081
- setSelection(textRange: TextUtils.TextRange.TextRange, dontScroll?: boolean): void {
1082
- this.lastSelectionInternal = textRange;
1083
- if (!this.editorSizeInSync) {
1084
- this.selectionSetScheduled = true;
1085
- return;
1086
- }
1087
- const pos = TextUtils.CodeMirrorUtils.toPos(textRange);
1088
- // https://crbug.com/1151919 both * = CodeMirror.Position
1089
- const startAsPosition = (pos.start as any);
1090
- const endAsPosition = (pos.end as any);
1091
- const scroll = !dontScroll;
1092
- this.codeMirrorInternal.setSelection(startAsPosition, endAsPosition, {scroll});
1093
- }
1094
-
1095
- setSelections(ranges: TextUtils.TextRange.TextRange[], primarySelectionIndex?: number): void {
1096
- const selections = [];
1097
- for (let i = 0; i < ranges.length; ++i) {
1098
- const selection = TextUtils.CodeMirrorUtils.toPos(ranges[i]);
1099
- selections.push({anchor: selection.start, head: selection.end});
1100
- }
1101
- primarySelectionIndex = primarySelectionIndex || 0;
1102
- this.codeMirrorInternal.setSelections(selections, primarySelectionIndex, {scroll: false});
1103
- }
1104
-
1105
- private detectLineSeparator(text: string): void {
1106
- this.lineSeparator = text.indexOf('\r\n') >= 0 ? '\r\n' : '\n';
1107
- }
1108
-
1109
- setText(text: string): void {
1110
- if (text.length > CodeMirrorTextEditor.MaxEditableTextSize) {
1111
- this.configureAutocomplete(null);
1112
- this.setReadOnly(true);
1113
- }
1114
- this.codeMirrorInternal.setValue(text);
1115
- if (this.shouldClearHistory) {
1116
- this.codeMirrorInternal.clearHistory();
1117
- this.shouldClearHistory = false;
1118
- }
1119
- this.detectLineSeparator(text);
1120
-
1121
- if (this.hasLongLines()) {
1122
- this.enableLongLinesMode();
1123
- } else {
1124
- this.disableLongLinesMode();
1125
- }
1126
-
1127
- if (!this.isShowing()) {
1128
- this.refresh();
1129
- }
1130
- }
1131
-
1132
- text(textRange?: TextUtils.TextRange.TextRange): string {
1133
- if (!textRange) {
1134
- return this.codeMirrorInternal.getValue(this.lineSeparator);
1135
- }
1136
- const pos = TextUtils.CodeMirrorUtils.toPos(textRange.normalize());
1137
- return this.codeMirrorInternal.getRange(pos.start, pos.end, this.lineSeparator);
1138
- }
1139
-
1140
- textWithCurrentSuggestion(): string {
1141
- if (!this.autocompleteController) {
1142
- return this.text();
1143
- }
1144
- return this.autocompleteController.textWithCurrentSuggestion();
1145
- }
1146
-
1147
- fullRange(): TextUtils.TextRange.TextRange {
1148
- const lineCount = this.linesCount;
1149
- const lastLine = this.codeMirrorInternal.getLine(lineCount - 1);
1150
- return TextUtils.CodeMirrorUtils.toRange(
1151
- new CodeMirror.Pos(0, 0), new CodeMirror.Pos(lineCount - 1, lastLine.length));
1152
- }
1153
-
1154
- currentLineNumber(): number {
1155
- return this.codeMirrorInternal.getCursor().line;
1156
- }
1157
-
1158
- line(lineNumber: number): string {
1159
- return this.codeMirrorInternal.getLine(lineNumber);
1160
- }
1161
-
1162
- get linesCount(): number {
1163
- return this.codeMirrorInternal.lineCount();
1164
- }
1165
-
1166
- newlineAndIndent(): void {
1167
- this.codeMirrorInternal.execCommand('newlineAndIndent');
1168
- }
1169
-
1170
- textEditorPositionHandle(lineNumber: number, columnNumber: number): TextEditorPositionHandle {
1171
- return new CodeMirrorPositionHandle(this.codeMirrorInternal, new CodeMirror.Pos(lineNumber, columnNumber));
1172
- }
1173
-
1174
- private updatePlaceholder(): void {
1175
- if (!this.placeholderElement) {
1176
- return;
1177
- }
1178
-
1179
- this.placeholderElement.remove();
1180
-
1181
- if (this.linesCount === 1 && !this.line(0)) {
1182
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1183
- this.codeMirrorInternal.display.lineSpace.insertBefore(
1184
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1185
- this.placeholderElement, this.codeMirrorInternal.display.lineSpace.firstChild);
1186
- }
1187
- }
1188
-
1189
- static readonly maxHighlightLength = 1000;
1190
- static readonly LongLineModeLineLengthThreshold = 2000;
1191
- static readonly MaxEditableTextSize = 1024 * 1024 * 10;
1192
- }
1193
-
1194
- CodeMirrorTextEditor.overrideModeWithPrefixedTokens('css', 'css-');
1195
- CodeMirrorTextEditor.overrideModeWithPrefixedTokens('javascript', 'js-');
1196
- CodeMirrorTextEditor.overrideModeWithPrefixedTokens('xml', 'xml-');
1197
-
1198
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1199
- CodeMirror.commands.autocomplete = CodeMirrorTextEditor.autocompleteCommand;
1200
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1201
- CodeMirror.commands.undoLastSelection = CodeMirrorTextEditor.undoLastSelectionCommand;
1202
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1203
- CodeMirror.commands.selectNextOccurrence = CodeMirrorTextEditor.selectNextOccurrenceCommand;
1204
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1205
- CodeMirror.commands.moveCamelLeft = CodeMirrorTextEditor.moveCamelLeftCommand.bind(null, false);
1206
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1207
- CodeMirror.commands.selectCamelLeft = CodeMirrorTextEditor.moveCamelLeftCommand.bind(null, true);
1208
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1209
- CodeMirror.commands.moveCamelRight = CodeMirrorTextEditor.moveCamelRightCommand.bind(null, false);
1210
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1211
- CodeMirror.commands.selectCamelRight = CodeMirrorTextEditor.moveCamelRightCommand.bind(null, true);
1212
-
1213
- // @ts-ignore https://crbug.com/1151919 * = CodeMirror.Editor
1214
- CodeMirror.commands.UserIndent = function(codeMirror: any): void {
1215
- const ranges = codeMirror.listSelections();
1216
- if (ranges.length === 0) {
1217
- return;
1218
- }
1219
-
1220
- if (codeMirror.somethingSelected()) {
1221
- codeMirror.indentSelection('add');
1222
- return;
1223
- }
1224
-
1225
- const indentation = Common.Settings.Settings.instance().moduleSetting('textEditorIndent').get();
1226
- codeMirror.replaceSelection(indentation);
1227
- };
1228
-
1229
- // https://crbug.com/1151919 * = CodeMirror.Editor
1230
- // @ts-ignore TS doesn't find the property even though it's defined in codemirror-legacy.d.ts
1231
- CodeMirror.commands.indentLessOrPass = function(codeMirror: any): Object|undefined {
1232
- const selections = codeMirror.listSelections();
1233
- if (selections.length === 1) {
1234
- const range = TextUtils.CodeMirrorUtils.toRange(selections[0].anchor, selections[0].head);
1235
- if (range.isEmpty() && !/^\s/.test(codeMirror.getLine(range.startLine))) {
1236
- return CodeMirror.Pass;
1237
- }
1238
- }
1239
- codeMirror.execCommand('indentLess');
1240
- return undefined;
1241
- };
1242
-
1243
- // https://crbug.com/1151919 * = CodeMirror.Editor
1244
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1245
- CodeMirror.commands.gotoMatchingBracket = function(codeMirror: any): void {
1246
- const updatedSelections = [];
1247
- const selections = codeMirror.listSelections();
1248
- for (let i = 0; i < selections.length; ++i) {
1249
- const selection = selections[i];
1250
- const cursor = selection.head;
1251
- // @ts-ignore findMatchingBracket types are incorrect
1252
- const matchingBracket = codeMirror.findMatchingBracket(cursor, false, {maxScanLines: 10000});
1253
- let updatedHead = cursor;
1254
- if (matchingBracket && matchingBracket.match) {
1255
- const columnCorrection = CodeMirror.cmpPos(matchingBracket.from, cursor) === 0 ? 1 : 0;
1256
- updatedHead = new CodeMirror.Pos(matchingBracket.to.line, matchingBracket.to.ch + columnCorrection);
1257
- }
1258
- updatedSelections.push({anchor: updatedHead, head: updatedHead});
1259
- }
1260
- codeMirror.setSelections(updatedSelections);
1261
- };
1262
-
1263
- // https://crbug.com/1151919 * = CodeMirror.Editor
1264
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1265
- CodeMirror.commands.undoAndReveal = function(codemirror: any): void {
1266
- const scrollInfo = codemirror.getScrollInfo();
1267
- codemirror.execCommand('undo');
1268
- const cursor = codemirror.getCursor('start');
1269
- CodeMirrorTextEditor.getForCodeMirror(codemirror).innerRevealLine(cursor.line, scrollInfo);
1270
- const autocompleteController = CodeMirrorTextEditor.getForCodeMirror(codemirror).autocompleteController;
1271
- if (autocompleteController) {
1272
- autocompleteController.clearAutocomplete();
1273
- }
1274
- };
1275
-
1276
- // https://crbug.com/1151919 * = CodeMirror.Editor
1277
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1278
- CodeMirror.commands.redoAndReveal = function(codemirror: any): void {
1279
- const scrollInfo = codemirror.getScrollInfo();
1280
- codemirror.execCommand('redo');
1281
- const cursor = codemirror.getCursor('start');
1282
- CodeMirrorTextEditor.getForCodeMirror(codemirror).innerRevealLine(cursor.line, scrollInfo);
1283
- const autocompleteController = CodeMirrorTextEditor.getForCodeMirror(codemirror).autocompleteController;
1284
- if (autocompleteController) {
1285
- autocompleteController.clearAutocomplete();
1286
- }
1287
- };
1288
-
1289
- // https://crbug.com/1151919 * = CodeMirror.Editor
1290
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1291
- CodeMirror.commands.dismiss = function(codemirror: any): Object|undefined {
1292
- const selections = codemirror.listSelections();
1293
- const selection = selections[0];
1294
- if (selections.length === 1) {
1295
- if (TextUtils.CodeMirrorUtils.toRange(selection.anchor, selection.head).isEmpty()) {
1296
- return CodeMirror.Pass;
1297
- }
1298
- codemirror.setSelection(selection.anchor, selection.anchor, {scroll: false});
1299
- CodeMirrorTextEditor.getForCodeMirror(codemirror).scrollLineIntoView(selection.anchor.line);
1300
- return;
1301
- }
1302
-
1303
- codemirror.setSelection(selection.anchor, selection.head, {scroll: false});
1304
- CodeMirrorTextEditor.getForCodeMirror(codemirror).scrollLineIntoView(selection.anchor.line);
1305
- return undefined;
1306
- };
1307
-
1308
- // https://crbug.com/1151919 * = CodeMirror.Editor
1309
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1310
- CodeMirror.commands.goSmartPageUp = function(codemirror: any): Object|undefined {
1311
- if (CodeMirrorTextEditor.getForCodeMirror(codemirror)
1312
- .selection()
1313
- .equal(TextUtils.TextRange.TextRange.createFromLocation(0, 0))) {
1314
- return CodeMirror.Pass;
1315
- }
1316
- codemirror.execCommand('goPageUp');
1317
- return undefined;
1318
- };
1319
-
1320
- // https://crbug.com/1151919 * = CodeMirror.Editor
1321
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1322
- CodeMirror.commands.goSmartPageDown = function(codemirror: any): Object|undefined {
1323
- if (CodeMirrorTextEditor.getForCodeMirror(codemirror)
1324
- .selection()
1325
- .equal(CodeMirrorTextEditor.getForCodeMirror(codemirror).fullRange().collapseToEnd())) {
1326
- return CodeMirror.Pass;
1327
- }
1328
- codemirror.execCommand('goPageDown');
1329
- return undefined;
1330
- };
1331
-
1332
- export class CodeMirrorPositionHandle implements TextEditorPositionHandle {
1333
- private readonly codeMirror: any;
1334
- private readonly lineHandle: any;
1335
- private readonly columnNumber: any;
1336
- // https://crbug.com/1151919 first * = CodeMirror.Editor, second * = CodeMirror.Pos
1337
- constructor(codeMirror: any, pos: any) {
1338
- this.codeMirror = codeMirror;
1339
- this.lineHandle = codeMirror.getLineHandle(pos.line);
1340
- this.columnNumber = pos.ch;
1341
- }
1342
-
1343
- resolve(): {
1344
- lineNumber: number,
1345
- columnNumber: number,
1346
- }|null {
1347
- const lineNumber = this.lineHandle ? this.codeMirror.getLineNumber(this.lineHandle) : null;
1348
- if (typeof lineNumber !== 'number') {
1349
- return null;
1350
- }
1351
- return {lineNumber: lineNumber, columnNumber: this.columnNumber};
1352
- }
1353
-
1354
- equal(argPositionHandle: TextEditorPositionHandle): boolean {
1355
- const positionHandle = argPositionHandle as CodeMirrorPositionHandle;
1356
- return positionHandle.lineHandle === this.lineHandle && positionHandle.columnNumber === this.columnNumber &&
1357
- positionHandle.codeMirror === this.codeMirror;
1358
- }
1359
- }
1360
-
1361
- export class SelectNextOccurrenceController {
1362
- private readonly textEditor: CodeMirrorTextEditor;
1363
- private readonly codeMirror: any;
1364
- private muteSelectionListener?: boolean;
1365
- private fullWordSelection?: boolean;
1366
- // https://crbug.com/1151919 * = CodeMirror.Editor
1367
- constructor(textEditor: CodeMirrorTextEditor, codeMirror: any) {
1368
- this.textEditor = textEditor;
1369
- this.codeMirror = codeMirror;
1370
- }
1371
-
1372
- selectionWillChange(): void {
1373
- if (!this.muteSelectionListener) {
1374
- delete this.fullWordSelection;
1375
- }
1376
- }
1377
-
1378
- private findRange(selections: TextUtils.TextRange.TextRange[], range: TextUtils.TextRange.TextRange): boolean {
1379
- for (let i = 0; i < selections.length; ++i) {
1380
- if (range.equal(selections[i])) {
1381
- return true;
1382
- }
1383
- }
1384
- return false;
1385
- }
1386
-
1387
- undoLastSelection(): void {
1388
- this.muteSelectionListener = true;
1389
- this.codeMirror.execCommand('undoSelection');
1390
- this.muteSelectionListener = false;
1391
- }
1392
-
1393
- selectNextOccurrence(): void {
1394
- const selections = this.textEditor.selections();
1395
- let anyEmptySelection = false;
1396
- for (let i = 0; i < selections.length; ++i) {
1397
- const selection = selections[i];
1398
- anyEmptySelection = anyEmptySelection || selection.isEmpty();
1399
- if (selection.startLine !== selection.endLine) {
1400
- return;
1401
- }
1402
- }
1403
- if (anyEmptySelection) {
1404
- this.expandSelectionsToWords(selections);
1405
- return;
1406
- }
1407
-
1408
- const last = selections[selections.length - 1];
1409
- let next: (TextUtils.TextRange.TextRange|null)|TextUtils.TextRange.TextRange = last;
1410
- do {
1411
- next = next ? this.findNextOccurrence(next, Boolean(this.fullWordSelection)) : null;
1412
- } while (next && this.findRange(selections, next) && !next.equal(last));
1413
-
1414
- if (!next) {
1415
- return;
1416
- }
1417
- selections.push(next);
1418
-
1419
- this.muteSelectionListener = true;
1420
- this.textEditor.setSelections(selections, selections.length - 1);
1421
- delete this.muteSelectionListener;
1422
-
1423
- this.textEditor.scrollLineIntoView(next.startLine);
1424
- }
1425
-
1426
- private expandSelectionsToWords(selections: TextUtils.TextRange.TextRange[]): void {
1427
- const newSelections = [];
1428
- for (let i = 0; i < selections.length; ++i) {
1429
- const selection = selections[i];
1430
- const startRangeWord = this.textEditor.wordRangeForCursorPosition(
1431
- selection.startLine, selection.startColumn, TextUtils.TextUtils.Utils.isWordChar) ||
1432
- TextUtils.TextRange.TextRange.createFromLocation(selection.startLine, selection.startColumn);
1433
- const endRangeWord = this.textEditor.wordRangeForCursorPosition(
1434
- selection.endLine, selection.endColumn, TextUtils.TextUtils.Utils.isWordChar) ||
1435
- TextUtils.TextRange.TextRange.createFromLocation(selection.endLine, selection.endColumn);
1436
- const newSelection = new TextUtils.TextRange.TextRange(
1437
- startRangeWord.startLine, startRangeWord.startColumn, endRangeWord.endLine, endRangeWord.endColumn);
1438
- newSelections.push(newSelection);
1439
- }
1440
- this.textEditor.setSelections(newSelections, newSelections.length - 1);
1441
- this.fullWordSelection = true;
1442
- }
1443
-
1444
- private findNextOccurrence(range: TextUtils.TextRange.TextRange, fullWord: boolean): TextUtils.TextRange.TextRange
1445
- |null {
1446
- range = range.normalize();
1447
- let matchedLineNumber: number|undefined = undefined;
1448
- let matchedColumnNumber: number|undefined = undefined;
1449
- const textToFind = this.textEditor.text(range);
1450
- function findWordInLine(
1451
- wordRegex: RegExp, lineNumber: number, lineText: string, from: number, to: number): boolean {
1452
- if (typeof matchedLineNumber === 'number') {
1453
- return true;
1454
- }
1455
- wordRegex.lastIndex = from;
1456
- const result = wordRegex.exec(lineText);
1457
- if (!result || result.index + textToFind.length > to) {
1458
- return false;
1459
- }
1460
- matchedLineNumber = lineNumber;
1461
- matchedColumnNumber = result.index;
1462
- return true;
1463
- }
1464
-
1465
- let iteratedLineNumber: number;
1466
- // https://crbug.com/1151919 * = CodeMirror.LineHandle
1467
- function lineIterator(regex: RegExp, lineHandle: any): true|undefined {
1468
- if (findWordInLine(regex, iteratedLineNumber++, lineHandle.text, 0, lineHandle.text.length)) {
1469
- return true;
1470
- }
1471
- return undefined;
1472
- }
1473
-
1474
- let regexSource = Platform.StringUtilities.escapeForRegExp(textToFind);
1475
- if (fullWord) {
1476
- regexSource = '\\b' + regexSource + '\\b';
1477
- }
1478
- const wordRegex = new RegExp(regexSource, 'g');
1479
- const currentLineText = this.codeMirror.getLine(range.startLine);
1480
-
1481
- findWordInLine(wordRegex, range.startLine, currentLineText, range.endColumn, currentLineText.length);
1482
- iteratedLineNumber = range.startLine + 1;
1483
- this.codeMirror.eachLine(range.startLine + 1, this.codeMirror.lineCount(), lineIterator.bind(null, wordRegex));
1484
- iteratedLineNumber = 0;
1485
- this.codeMirror.eachLine(0, range.startLine, lineIterator.bind(null, wordRegex));
1486
- findWordInLine(wordRegex, range.startLine, currentLineText, 0, range.startColumn);
1487
-
1488
- if (typeof matchedLineNumber !== 'number' || typeof matchedColumnNumber !== 'number') {
1489
- return null;
1490
- }
1491
- const textToFindLength = textToFind ? textToFind.length : 0;
1492
- return new TextUtils.TextRange.TextRange(
1493
- matchedLineNumber as number, matchedColumnNumber as number, matchedLineNumber as number,
1494
- matchedColumnNumber + textToFindLength);
1495
- }
1496
- }
1497
-
1498
- /**
1499
- * @interface
1500
- */
1501
- export interface TextEditorPositionHandle {
1502
- resolve(): {
1503
- lineNumber: number,
1504
- columnNumber: number,
1505
- }|null;
1506
-
1507
- equal(positionHandle: TextEditorPositionHandle): boolean;
1508
- }
1509
-
1510
- export class TextEditorBookMark {
1511
- private readonly marker: any;
1512
- private readonly typeInternal: symbol;
1513
- private readonly editor: CodeMirrorTextEditor;
1514
- // https://crbug.com/1151919 * = CodeMirror.TextMarker
1515
- constructor(marker: any, type: symbol, editor: CodeMirrorTextEditor) {
1516
- this.marker = marker;
1517
- this.typeInternal = type;
1518
- this.editor = editor;
1519
- }
1520
-
1521
- clear(): void {
1522
- const position = this.marker.find();
1523
- this.marker.clear();
1524
- if (position) {
1525
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1526
- this.editor.updateDecorations(position.line);
1527
- }
1528
- }
1529
-
1530
- refresh(): void {
1531
- this.marker.changed();
1532
- const position = this.marker.find();
1533
- if (position) {
1534
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1535
- this.editor.updateDecorations(position.line);
1536
- }
1537
- }
1538
-
1539
- type(): symbol {
1540
- return this.typeInternal;
1541
- }
1542
-
1543
- position(): TextUtils.TextRange.TextRange|null {
1544
- const pos = this.marker.find();
1545
- // @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
1546
- return pos ? TextUtils.TextRange.TextRange.createFromLocation(pos.line, pos.ch) : null;
1547
- }
1548
- }
1549
- let codeMirrorTextEditorFactoryInstance: CodeMirrorTextEditorFactory;
1550
-
1551
- export class CodeMirrorTextEditorFactory implements UI.TextEditor.TextEditorFactory {
1552
- static instance(opts: {forceNew: boolean|null} = {forceNew: null}): CodeMirrorTextEditorFactory {
1553
- const {forceNew} = opts;
1554
- if (!codeMirrorTextEditorFactoryInstance || forceNew) {
1555
- codeMirrorTextEditorFactoryInstance = new CodeMirrorTextEditorFactory();
1556
- }
1557
-
1558
- return codeMirrorTextEditorFactoryInstance;
1559
- }
1560
- createEditor(options: UI.TextEditor.Options): CodeMirrorTextEditor {
1561
- return new CodeMirrorTextEditor(options);
1562
- }
1563
- }
1564
-
1565
- // CodeMirror uses an offscreen <textarea> to detect input. Due to inconsistencies in the many browsers it supports,
1566
- // it simplifies things by regularly checking if something is in the textarea, adding those characters to the document,
1567
- // and then clearing the textarea. This breaks assistive technology that wants to read from CodeMirror, because the
1568
- // <textarea> that they interact with is constantly empty.
1569
- // Because we target up-to-date Chrome, we can guarantee consistent input events. This lets us leave the current
1570
- // line from the editor in our <textarea>. CodeMirror still expects a mostly empty <textarea>, so we pass CodeMirror a
1571
- // fake <textarea> that only contains the users input.
1572
- // @ts-ignore
1573
- export class DevToolsAccessibleTextArea extends CodeMirror.inputStyles.textarea {
1574
- textarea!: HTMLTextAreaElement;
1575
- contextMenuPending: boolean;
1576
- composing: boolean;
1577
- cm: any;
1578
- prevInput!: string;
1579
-
1580
- // https://crbug.com/1151919 * = CodeMirror.Editor
1581
- constructor(codeMirror: any) {
1582
- super(codeMirror);
1583
- this.cm = codeMirror;
1584
- this.contextMenuPending = false;
1585
- this.composing = false;
1586
- }
1587
-
1588
- init(display: Object): void {
1589
- super.init(display);
1590
- this.textarea.addEventListener('compositionstart', this.onCompositionStart.bind(this));
1591
- }
1592
-
1593
- private onCompositionStart(): void {
1594
- if (this.textarea.selectionEnd === this.textarea.value.length) {
1595
- return;
1596
- }
1597
- // CodeMirror always expects the caret to be at the end of the textarea
1598
- // When in IME composition mode, clip the textarea to how CodeMirror expects it,
1599
- // and then let CodeMirror do it's thing.
1600
- this.textarea.value = this.textarea.value.substring(0, this.textarea.selectionEnd);
1601
- this.textarea.setSelectionRange(this.textarea.value.length, this.textarea.value.length);
1602
- this.prevInput = this.textarea.value;
1603
- }
1604
-
1605
- reset(typing?: boolean): void {
1606
- if (this.textAreaBusy(Boolean(typing))) {
1607
- super.reset(typing);
1608
- return;
1609
- }
1610
-
1611
- // When navigating around the document, keep the current visual line in the textarea.
1612
- const cursor = this.cm.getCursor();
1613
- let start, end;
1614
- if (this.cm.getOption('lineWrapping')) {
1615
- // To get the visual line, compute the leftmost and rightmost character positions.
1616
- const top = this.cm.charCoords(cursor, 'page').top;
1617
- start = this.cm.coordsChar({left: -Infinity, top});
1618
- end = this.cm.coordsChar({left: Infinity, top});
1619
- } else {
1620
- // Limit the line to 1000 characters to prevent lag.
1621
- const offset = Math.floor(cursor.ch / 1000) * 1000;
1622
- start = {ch: offset, line: cursor.line};
1623
- end = {ch: offset + 1000, line: cursor.line};
1624
- }
1625
- this.textarea.value = this.cm.getRange(start, end);
1626
- const caretPosition = cursor.ch - start.ch;
1627
- this.textarea.setSelectionRange(caretPosition, caretPosition);
1628
- this.prevInput = this.textarea.value;
1629
- }
1630
-
1631
- /**
1632
- * If the user is currently typing into the textarea or otherwise
1633
- * modifying it, we don't want to clobber their work.
1634
- */
1635
- protected textAreaBusy(typing: boolean): boolean {
1636
- return typing || this.contextMenuPending || this.composing || this.cm.somethingSelected();
1637
- }
1638
-
1639
- poll(): boolean {
1640
- if (this.contextMenuPending || this.composing) {
1641
- return super.poll();
1642
- }
1643
- const text = this.textarea.value;
1644
- let start = 0;
1645
- const length = Math.min(this.prevInput.length, text.length);
1646
- while (start < length && this.prevInput[start] === text[start]) {
1647
- ++start;
1648
- }
1649
- let end = 0;
1650
- while (end < length - start && this.prevInput[this.prevInput.length - end - 1] === text[text.length - end - 1]) {
1651
- ++end;
1652
- }
1653
-
1654
- // CodeMirror expects the user to be typing into a blank <textarea>.
1655
- // Pass a fake textarea into super.poll that only contains the users input.
1656
- const placeholder = this.textarea;
1657
- this.textarea = document.createElement('textarea');
1658
- this.textarea.value = text.substring(start, text.length - end);
1659
- this.textarea.setSelectionRange(placeholder.selectionStart - start, placeholder.selectionEnd - start);
1660
- this.prevInput = '';
1661
- const result = super.poll();
1662
- this.prevInput = text;
1663
- this.textarea = placeholder;
1664
- return result;
1665
- }
1666
- }
1667
-
1668
- // @ts-ignore
1669
- CodeMirror.inputStyles.devToolsAccessibleTextArea = DevToolsAccessibleTextArea;
1670
-
1671
- export interface Decoration {
1672
- element: Element;
1673
- // https://crbug.com/1151919 * = CodeMirror.LineWidget
1674
- widget: any;
1675
- update: (() => void)|null;
1676
- }