Add back triangles for code folding

With CodeMirror 6 we were using the default CodeMirror styled arrows,
whereas with CodeMirror 5 we had a custom version. After user feedback,
we opted for adding back the original arrows and move the code folding
buttons to the right of the line numbers.

We use the expand/collapsed arrows in various places, but they use the
legacy UI `smallIcons.svg` built with webkit mask images. To avoid
relying on the legacy icons, I opted for using the modern `Icon.ts` by
introducing new arrows for collapsing and expanded. These arrows should
be visually equivalent to the legacy versions. Please see the screenshot
below for the new CodeMirror 6 version.

Image: https://imgur.com/a/jyHQFkc

R=petermueller@chromium.org,yangguo@chromium.org

Fixed: 1299364
Change-Id: Ic8921229c3657fa4ad404d7c38a80ccc192e1319
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/3480038
Reviewed-by: Yang Guo <yangguo@chromium.org>
Commit-Queue: Tim Van der Lippe <tvanderlippe@chromium.org>
diff --git a/config/gni/devtools_grd_files.gni b/config/gni/devtools_grd_files.gni
index f9e8a40..8e6cb3b 100644
--- a/config/gni/devtools_grd_files.gni
+++ b/config/gni/devtools_grd_files.gni
@@ -144,6 +144,8 @@
   "front_end/Images/touchCursor_2x.png",
   "front_end/Images/trash_bin_icon.svg",
   "front_end/Images/treeoutlineTriangles.svg",
+  "front_end/Images/triangle-collapsed.svg",
+  "front_end/Images/triangle-expanded.svg",
   "front_end/Images/warning_icon.svg",
   "front_end/Images/whatsnew.avif",
   "front_end/Tests.js",
diff --git a/config/gni/devtools_image_files.gni b/config/gni/devtools_image_files.gni
index 44d61df..5d1df19 100644
--- a/config/gni/devtools_image_files.gni
+++ b/config/gni/devtools_image_files.gni
@@ -140,6 +140,8 @@
   "three_dots_menu_icon.svg",
   "trash_bin_icon.svg",
   "treeoutlineTriangles.svg",
+  "triangle-collapsed.svg",
+  "triangle-expanded.svg",
   "warning_icon.svg",
 ]
 
diff --git a/front_end/Images/src/triangle-collapsed.svg b/front_end/Images/src/triangle-collapsed.svg
new file mode 100644
index 0000000..56ca9d2
--- /dev/null
+++ b/front_end/Images/src/triangle-collapsed.svg
@@ -0,0 +1 @@
+<svg height="48" viewBox="0 0 48 48" width="48" xmlns="http://www.w3.org/2000/svg"><path d="M 15 10 v 28 l 20 -14 L 15 10" /></svg>
\ No newline at end of file
diff --git a/front_end/Images/src/triangle-expanded.svg b/front_end/Images/src/triangle-expanded.svg
new file mode 100644
index 0000000..65050fc
--- /dev/null
+++ b/front_end/Images/src/triangle-expanded.svg
@@ -0,0 +1 @@
+<svg height="48" viewBox="0 0 48 48" width="48" xmlns="http://www.w3.org/2000/svg"><path d="M 10 10 h 28 l -14 20 L 10 10" /></svg>
\ No newline at end of file
diff --git a/front_end/ui/components/text_editor/config.ts b/front_end/ui/components/text_editor/config.ts
index 66c6eee..7de267a 100644
--- a/front_end/ui/components/text_editor/config.ts
+++ b/front_end/ui/components/text_editor/config.ts
@@ -7,6 +7,7 @@
 import * as WindowBoundsService from '../../../services/window_bounds/window_bounds.js';
 import * as CM from '../../../third_party/codemirror.next/codemirror.next.js';
 import * as CodeHighlighter from '../code_highlighter/code_highlighter.js';
+import * as Icon from '../icon_button/icon_button.js';
 
 import {editorTheme} from './theme.js';
 
@@ -82,7 +83,22 @@
 
 export const bracketMatching = DynamicSetting.bool('textEditorBracketMatching', CM.bracketMatching());
 
-export const codeFolding = DynamicSetting.bool('textEditorCodeFolding', [CM.foldGutter(), CM.keymap.of(CM.foldKeymap)]);
+export const codeFolding = DynamicSetting.bool('textEditorCodeFolding', [
+  CM.foldGutter({
+    markerDOM(open: boolean): HTMLElement {
+      const iconName = open ? 'triangle-expanded' : 'triangle-collapsed';
+      const icon = new Icon.Icon.Icon();
+      icon.data = {
+        iconName,
+        color: 'var(--color-text-secondary)',
+        width: '12px',
+        height: '12px',
+      };
+      return icon;
+    },
+  }),
+  CM.keymap.of(CM.foldKeymap),
+]);
 
 export function guessIndent(doc: CM.Text): string {
   const values: {[indent: string]: number} = Object.create(null);
diff --git a/front_end/ui/legacy/components/source_frame/SourceFrame.ts b/front_end/ui/legacy/components/source_frame/SourceFrame.ts
index 89e0d58..3e0bb19 100644
--- a/front_end/ui/legacy/components/source_frame/SourceFrame.ts
+++ b/front_end/ui/legacy/components/source_frame/SourceFrame.ts
@@ -211,7 +211,7 @@
       TextEditor.Config.sourcesAutocompletion.instance(),
       TextEditor.Config.showWhitespace.instance(),
       TextEditor.Config.allowScrollPastEof.instance(),
-      TextEditor.Config.codeFolding.instance(),
+      CodeMirror.Prec.lowest(TextEditor.Config.codeFolding.instance()),
       TextEditor.Config.autoDetectIndent.instance(),
       sourceFrameTheme,
       CodeMirror.EditorView.domEventHandlers({