mbeditor 0.2.2

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 (108) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +116 -0
  3. data/README.md +180 -0
  4. data/app/assets/javascripts/mbeditor/application.js +21 -0
  5. data/app/assets/javascripts/mbeditor/components/CodeReviewPanel.js +202 -0
  6. data/app/assets/javascripts/mbeditor/components/CollapsibleSection.js +71 -0
  7. data/app/assets/javascripts/mbeditor/components/CombinedDiffViewer.js +139 -0
  8. data/app/assets/javascripts/mbeditor/components/CommitGraph.js +65 -0
  9. data/app/assets/javascripts/mbeditor/components/DiffViewer.js +166 -0
  10. data/app/assets/javascripts/mbeditor/components/EditorPanel.js +1139 -0
  11. data/app/assets/javascripts/mbeditor/components/FileHistoryPanel.js +117 -0
  12. data/app/assets/javascripts/mbeditor/components/FileTree.js +339 -0
  13. data/app/assets/javascripts/mbeditor/components/GitPanel.js +501 -0
  14. data/app/assets/javascripts/mbeditor/components/MbeditorApp.js +3108 -0
  15. data/app/assets/javascripts/mbeditor/components/QuickOpenDialog.js +272 -0
  16. data/app/assets/javascripts/mbeditor/components/ShortcutHelp.js +186 -0
  17. data/app/assets/javascripts/mbeditor/components/TabBar.js +238 -0
  18. data/app/assets/javascripts/mbeditor/components/TestResultsPanel.js +150 -0
  19. data/app/assets/javascripts/mbeditor/editor_plugins.js +758 -0
  20. data/app/assets/javascripts/mbeditor/editor_store.js +69 -0
  21. data/app/assets/javascripts/mbeditor/file_icon.js +30 -0
  22. data/app/assets/javascripts/mbeditor/file_service.js +96 -0
  23. data/app/assets/javascripts/mbeditor/git_service.js +104 -0
  24. data/app/assets/javascripts/mbeditor/search_service.js +63 -0
  25. data/app/assets/javascripts/mbeditor/tab_manager.js +485 -0
  26. data/app/assets/stylesheets/mbeditor/application.css +848 -0
  27. data/app/assets/stylesheets/mbeditor/editor.css +2061 -0
  28. data/app/controllers/mbeditor/application_controller.rb +70 -0
  29. data/app/controllers/mbeditor/editors_controller.rb +996 -0
  30. data/app/controllers/mbeditor/git_controller.rb +234 -0
  31. data/app/services/mbeditor/git_blame_service.rb +98 -0
  32. data/app/services/mbeditor/git_commit_graph_service.rb +60 -0
  33. data/app/services/mbeditor/git_diff_service.rb +74 -0
  34. data/app/services/mbeditor/git_file_history_service.rb +42 -0
  35. data/app/services/mbeditor/git_service.rb +95 -0
  36. data/app/services/mbeditor/redmine_service.rb +86 -0
  37. data/app/services/mbeditor/ruby_definition_service.rb +168 -0
  38. data/app/services/mbeditor/test_runner_service.rb +286 -0
  39. data/app/views/layouts/mbeditor/application.html.erb +120 -0
  40. data/app/views/mbeditor/editors/index.html.erb +1 -0
  41. data/config/initializers/assets.rb +9 -0
  42. data/config/routes.rb +44 -0
  43. data/lib/mbeditor/configuration.rb +22 -0
  44. data/lib/mbeditor/engine.rb +37 -0
  45. data/lib/mbeditor/rack/silence_ping_request.rb +56 -0
  46. data/lib/mbeditor/version.rb +3 -0
  47. data/lib/mbeditor.rb +19 -0
  48. data/mbeditor.gemspec +31 -0
  49. data/public/mbeditor-icon.svg +4 -0
  50. data/public/min-maps/vs/base/worker/workerMain.js.map +1 -0
  51. data/public/monaco-editor/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
  52. data/public/monaco-editor/vs/base/worker/workerMain.js +31 -0
  53. data/public/monaco-editor/vs/basic-languages/cameligo/cameligo.js +10 -0
  54. data/public/monaco-editor/vs/basic-languages/css/css.js +12 -0
  55. data/public/monaco-editor/vs/basic-languages/dart/dart.js +10 -0
  56. data/public/monaco-editor/vs/basic-languages/flow9/flow9.js +10 -0
  57. data/public/monaco-editor/vs/basic-languages/go/go.js +10 -0
  58. data/public/monaco-editor/vs/basic-languages/handlebars/handlebars.js +440 -0
  59. data/public/monaco-editor/vs/basic-languages/javascript/javascript.js +10 -0
  60. data/public/monaco-editor/vs/basic-languages/markdown/markdown.js +10 -0
  61. data/public/monaco-editor/vs/basic-languages/msdax/msdax.js +10 -0
  62. data/public/monaco-editor/vs/basic-languages/postiats/postiats.js +10 -0
  63. data/public/monaco-editor/vs/basic-languages/pug/pug.js +412 -0
  64. data/public/monaco-editor/vs/basic-languages/restructuredtext/restructuredtext.js +10 -0
  65. data/public/monaco-editor/vs/basic-languages/ruby/ruby.js +10 -0
  66. data/public/monaco-editor/vs/basic-languages/sb/sb.js +10 -0
  67. data/public/monaco-editor/vs/basic-languages/shell/shell.js +41 -0
  68. data/public/monaco-editor/vs/basic-languages/typescript/typescript.js +10 -0
  69. data/public/monaco-editor/vs/basic-languages/typespec/typespec.js +10 -0
  70. data/public/monaco-editor/vs/basic-languages/yaml/yaml.js +10 -0
  71. data/public/monaco-editor/vs/editor/editor.api.js +6 -0
  72. data/public/monaco-editor/vs/editor/editor.main.css +8 -0
  73. data/public/monaco-editor/vs/editor/editor.main.js +797 -0
  74. data/public/monaco-editor/vs/language/typescript/tsMode.js +20 -0
  75. data/public/monaco-editor/vs/language/typescript/tsWorker.js +51328 -0
  76. data/public/monaco-editor/vs/loader.js +10 -0
  77. data/public/monaco-editor/vs/nls.messages.de.js +20 -0
  78. data/public/monaco-editor/vs/nls.messages.es.js +20 -0
  79. data/public/monaco-editor/vs/nls.messages.fr.js +18 -0
  80. data/public/monaco-editor/vs/nls.messages.it.js +18 -0
  81. data/public/monaco-editor/vs/nls.messages.ja.js +20 -0
  82. data/public/monaco-editor/vs/nls.messages.ko.js +18 -0
  83. data/public/monaco-editor/vs/nls.messages.ru.js +20 -0
  84. data/public/monaco-editor/vs/nls.messages.zh-cn.js +20 -0
  85. data/public/monaco-editor/vs/nls.messages.zh-tw.js +18 -0
  86. data/public/monaco_worker.js +5 -0
  87. data/public/sw.js +8 -0
  88. data/public/ts_worker.js +5 -0
  89. data/vendor/assets/javascripts/axios.min.js +5 -0
  90. data/vendor/assets/javascripts/emmet.js +5452 -0
  91. data/vendor/assets/javascripts/lodash.min.js +136 -0
  92. data/vendor/assets/javascripts/marked.min.js +6 -0
  93. data/vendor/assets/javascripts/minisearch.min.js +2044 -0
  94. data/vendor/assets/javascripts/monaco-themes-bundle.js +10 -0
  95. data/vendor/assets/javascripts/monaco-vim.js +9867 -0
  96. data/vendor/assets/javascripts/prettier-plugin-babel.js +16 -0
  97. data/vendor/assets/javascripts/prettier-plugin-estree.js +35 -0
  98. data/vendor/assets/javascripts/prettier-plugin-html.js +19 -0
  99. data/vendor/assets/javascripts/prettier-plugin-markdown.js +59 -0
  100. data/vendor/assets/javascripts/prettier-plugin-postcss.js +52 -0
  101. data/vendor/assets/javascripts/prettier-standalone.js +37 -0
  102. data/vendor/assets/javascripts/react-dom.min.js +267 -0
  103. data/vendor/assets/javascripts/react.min.js +31 -0
  104. data/vendor/assets/stylesheets/fontawesome.min.css.erb +9 -0
  105. data/vendor/assets/webfonts/fa-brands-400.woff2 +0 -0
  106. data/vendor/assets/webfonts/fa-regular-400.woff2 +0 -0
  107. data/vendor/assets/webfonts/fa-solid-900.woff2 +0 -0
  108. metadata +188 -0
@@ -0,0 +1,139 @@
1
+ 'use strict';
2
+
3
+ // Renders the raw unified diff text produced by `git diff` for multiple files.
4
+ // Each line is colored (green = addition, red = deletion, blue = hunk header,
5
+ // dimmed = file header) giving a VS Code "Open Changes" style read-only view.
6
+ var CombinedDiffViewer = function CombinedDiffViewer(_ref) {
7
+ var diffText = _ref.diffText;
8
+ var label = _ref.label;
9
+ var isLoading = _ref.isLoading;
10
+
11
+ var containerRef = React.useRef(null);
12
+
13
+ // Track which file sections are collapsed. Key = "diff --git …" header line.
14
+ var _us = React.useState({});
15
+ var collapsed = _us[0]; var setCollapsed = _us[1];
16
+
17
+ if (isLoading) {
18
+ return React.createElement(
19
+ 'div',
20
+ { className: 'combined-diff-viewer combined-diff-loading-wrap' },
21
+ React.createElement('span', { className: 'combined-diff-loading-msg' }, 'Loading\u2026')
22
+ );
23
+ }
24
+
25
+ if (!diffText || !diffText.trim()) {
26
+ return React.createElement(
27
+ 'div',
28
+ { className: 'combined-diff-viewer combined-diff-empty' },
29
+ React.createElement('i', { className: 'fas fa-check-circle', style: { marginRight: 8, color: '#89d185' } }),
30
+ 'No changes.'
31
+ );
32
+ }
33
+
34
+ // Split the raw diff into per-file segments, each starting at "diff --git".
35
+ var segments = [];
36
+ var current = null;
37
+ diffText.split('\n').forEach(function (line) {
38
+ if (line.startsWith('diff --git ')) {
39
+ if (current) segments.push(current);
40
+ current = { header: line, lines: [line] };
41
+ } else if (current) {
42
+ current.lines.push(line);
43
+ }
44
+ });
45
+ if (current) segments.push(current);
46
+
47
+ // Extract a clean display path from the "diff --git a/foo b/foo" header
48
+ function extractPath(headerLine) {
49
+ var m = headerLine.match(/^diff --git a\/(.+) b\/(.+)$/);
50
+ return m ? m[2] : headerLine.replace('diff --git ', '');
51
+ }
52
+
53
+ function renderSegment(seg, si) {
54
+ var filePath = extractPath(seg.header);
55
+ var parts = filePath.split('/');
56
+ var fileName = parts.pop();
57
+ var fileDir = parts.join('/');
58
+
59
+ var isCollapsed = !!collapsed[si];
60
+
61
+ var lineNodes = [];
62
+ var inHunk = false;
63
+ seg.lines.forEach(function (line, li) {
64
+ // Skip the boring "diff --git / index / --- / +++" boilerplate at the top
65
+ if (li === 0) return; // "diff --git" — shown in header
66
+ if (line.startsWith('index ') || line.startsWith('old mode') || line.startsWith('new mode') || line.startsWith('new file') || line.startsWith('deleted file') || line.startsWith('Binary') || line.startsWith('rename ')) {
67
+ lineNodes.push(React.createElement('div', { key: li, className: 'cdiff-line cdiff-meta' }, line));
68
+ return;
69
+ }
70
+ if (line.startsWith('--- ') || line.startsWith('+++ ')) {
71
+ lineNodes.push(React.createElement('div', { key: li, className: 'cdiff-line cdiff-file-header' }, line));
72
+ inHunk = false;
73
+ return;
74
+ }
75
+ if (line.startsWith('@@')) {
76
+ inHunk = true;
77
+ lineNodes.push(React.createElement('div', { key: li, className: 'cdiff-line cdiff-hunk' }, line));
78
+ return;
79
+ }
80
+ if (!inHunk) return;
81
+ var cls = 'cdiff-line';
82
+ if (line.startsWith('+')) cls += ' cdiff-add';
83
+ else if (line.startsWith('-')) cls += ' cdiff-del';
84
+ else cls += ' cdiff-ctx';
85
+ lineNodes.push(React.createElement('div', { key: li, className: cls }, line || '\u00a0'));
86
+ });
87
+
88
+ return React.createElement(
89
+ 'div',
90
+ { key: si, className: 'cdiff-file-segment' },
91
+ // File header bar
92
+ React.createElement(
93
+ 'div',
94
+ {
95
+ className: 'cdiff-file-bar',
96
+ onClick: function () {
97
+ setCollapsed(function (prev) {
98
+ var next = Object.assign({}, prev);
99
+ next[si] = !prev[si];
100
+ return next;
101
+ });
102
+ }
103
+ },
104
+ React.createElement('i', {
105
+ className: 'fas ' + (isCollapsed ? 'fa-chevron-right' : 'fa-chevron-down') + ' cdiff-chevron'
106
+ }),
107
+ React.createElement('i', { className: 'fas fa-file-code cdiff-file-icon' }),
108
+ React.createElement('span', { className: 'cdiff-file-name' }, fileName),
109
+ fileDir ? React.createElement('span', { className: 'cdiff-file-dir' }, fileDir) : null
110
+ ),
111
+ !isCollapsed && React.createElement(
112
+ 'div',
113
+ { className: 'cdiff-file-body' },
114
+ lineNodes
115
+ )
116
+ );
117
+ }
118
+
119
+ return React.createElement(
120
+ 'div',
121
+ { className: 'combined-diff-viewer' },
122
+ // Toolbar
123
+ React.createElement(
124
+ 'div',
125
+ { className: 'combined-diff-toolbar' },
126
+ React.createElement('i', { className: 'fas fa-exchange-alt', style: { color: '#569cd6', marginRight: 8 } }),
127
+ React.createElement('span', { className: 'combined-diff-label' }, label || 'All Changes'),
128
+ React.createElement('span', { className: 'combined-diff-file-count' }, segments.length + ' file' + (segments.length === 1 ? '' : 's'))
129
+ ),
130
+ // Body
131
+ React.createElement(
132
+ 'div',
133
+ { className: 'combined-diff-body', ref: containerRef },
134
+ segments.map(function (seg, si) { return renderSegment(seg, si); })
135
+ )
136
+ );
137
+ };
138
+
139
+ window.CombinedDiffViewer = CombinedDiffViewer;
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ var CommitGraph = function CommitGraph(_ref) {
4
+ var commits = _ref.commits;
5
+ var onSelectCommit = _ref.onSelectCommit;
6
+
7
+ if (!commits || commits.length === 0) {
8
+ return React.createElement(
9
+ 'div',
10
+ { className: 'git-empty' },
11
+ 'No commit history available.'
12
+ );
13
+ }
14
+
15
+ // Very simplified graph rendering for a single branch view.
16
+ // Full cross-branch line rendering in a web UI is complex;
17
+ // here we render a vertical line with dots for each commit.
18
+ return React.createElement(
19
+ 'div',
20
+ { className: 'ide-commit-graph' },
21
+ commits.map(function (commit, idx) {
22
+ var isFirst = idx === 0;
23
+ var isLast = idx === commits.length - 1;
24
+ var dateObj = new Date(commit.date);
25
+ var dateStr = !isNaN(dateObj) ? dateObj.toLocaleString() : commit.date;
26
+ var isLocal = commit.isLocal;
27
+
28
+ return React.createElement(
29
+ 'div',
30
+ {
31
+ key: commit.hash,
32
+ className: 'commit-row ' + (isLocal ? 'commit-local' : ''),
33
+ onClick: function () { return onSelectCommit && onSelectCommit(commit); }
34
+ },
35
+ React.createElement(
36
+ 'div',
37
+ { className: 'commit-graph-col' },
38
+ !isFirst && React.createElement('div', { className: 'commit-line-top' }),
39
+ React.createElement('div', { className: 'commit-dot ' + (isLocal ? 'dot-local' : 'dot-pushed') }),
40
+ !isLast && React.createElement('div', { className: 'commit-line-bottom' })
41
+ ),
42
+ React.createElement(
43
+ 'div',
44
+ { className: 'commit-info-col' },
45
+ React.createElement(
46
+ 'div',
47
+ { className: 'commit-title', title: commit.title },
48
+ commit.title
49
+ ),
50
+ React.createElement(
51
+ 'div',
52
+ { className: 'commit-meta' },
53
+ React.createElement('span', { className: 'commit-hash' }, commit.hash.slice(0, 7)),
54
+ ' \xB7 ',
55
+ commit.author,
56
+ ' \xB7 ',
57
+ dateStr
58
+ )
59
+ )
60
+ );
61
+ })
62
+ );
63
+ };
64
+
65
+ window.CommitGraph = CommitGraph;
@@ -0,0 +1,166 @@
1
+ 'use strict';
2
+
3
+ var DiffViewer = function DiffViewer(_ref) {
4
+ var path = _ref.path;
5
+ var original = _ref.original;
6
+ var modified = _ref.modified;
7
+ var isDark = _ref.isDark;
8
+ var onClose = _ref.onClose;
9
+ var editorPrefs = _ref.editorPrefs || {};
10
+ // If path is a diff:// URI (diff://baseSha..headSha/actual/file.rb), extract
11
+ // just the file path portion for display so the title bar shows a clean name.
12
+ var _rawDisplayPath = _ref.displayPath || path;
13
+ var displayPath = _rawDisplayPath;
14
+ if (!_ref.displayPath && _rawDisplayPath && _rawDisplayPath.indexOf('diff://') === 0) {
15
+ var _rest = _rawDisplayPath.slice(7); // strip 'diff://'
16
+ var _sep = _rest.indexOf('/');
17
+ if (_sep !== -1) displayPath = _rest.slice(_sep + 1);
18
+ }
19
+
20
+ var containerRef = React.useRef(null);
21
+ var editorRef = React.useRef(null);
22
+ var currentChangeRef = React.useRef(-1);
23
+
24
+ React.useEffect(function () {
25
+ if (!window.monaco || !containerRef.current) return;
26
+
27
+ var modelOriginal = window.monaco.editor.createModel(original, getLanguageForPath(displayPath));
28
+ var modelModified = window.monaco.editor.createModel(modified, getLanguageForPath(displayPath));
29
+
30
+ var diffEditor = window.monaco.editor.createDiffEditor(containerRef.current, {
31
+ theme: isDark ? 'vs-dark' : 'vs',
32
+ readOnly: true,
33
+ automaticLayout: true,
34
+ originalEditable: false,
35
+ renderSideBySide: true,
36
+ useInlineViewWhenSpaceIsLimited: false,
37
+ ignoreTrimWhitespace: false,
38
+ minimap: { enabled: false },
39
+ scrollBeyondLastLine: false,
40
+ fontFamily: editorPrefs.fontFamily || "'JetBrains Mono', 'Fira Code', 'Menlo', 'Consolas', monospace",
41
+ fontSize: editorPrefs.fontSize || 13,
42
+ wordWrap: editorPrefs.wordWrap || 'off'
43
+ });
44
+
45
+ diffEditor.setModel({
46
+ original: modelOriginal,
47
+ modified: modelModified
48
+ });
49
+
50
+ editorRef.current = diffEditor;
51
+ currentChangeRef.current = -1;
52
+
53
+ diffEditor.onDidUpdateDiff(function () {
54
+ currentChangeRef.current = -1;
55
+ });
56
+
57
+ return function () {
58
+ if (editorRef.current) {
59
+ editorRef.current.dispose();
60
+ editorRef.current = null;
61
+ }
62
+ modelOriginal.dispose();
63
+ modelModified.dispose();
64
+ };
65
+ // eslint-disable-next-line react-hooks/exhaustive-deps
66
+ }, [original, modified, displayPath, isDark]);
67
+
68
+ // Update font/wrap options live when editorPrefs changes, without recreating the editor
69
+ React.useEffect(function () {
70
+ if (!editorRef.current) return;
71
+ editorRef.current.updateOptions({
72
+ fontFamily: editorPrefs.fontFamily || "'JetBrains Mono', 'Fira Code', 'Menlo', 'Consolas', monospace",
73
+ fontSize: editorPrefs.fontSize || 13,
74
+ wordWrap: editorPrefs.wordWrap || 'off'
75
+ });
76
+ }, [editorPrefs]);
77
+
78
+ var handleNextDiff = function handleNextDiff() {
79
+ if (!editorRef.current) return;
80
+ var changes = editorRef.current.getLineChanges() || [];
81
+ if (!changes.length) return;
82
+ currentChangeRef.current = (currentChangeRef.current + 1) % changes.length;
83
+ var change = changes[currentChangeRef.current];
84
+ editorRef.current.getModifiedEditor().revealLineInCenter(change.modifiedStartLineNumber);
85
+ };
86
+
87
+ var handlePrevDiff = function handlePrevDiff() {
88
+ if (!editorRef.current) return;
89
+ var changes = editorRef.current.getLineChanges() || [];
90
+ if (!changes.length) return;
91
+ currentChangeRef.current = (currentChangeRef.current - 1 + changes.length) % changes.length;
92
+ var change = changes[currentChangeRef.current];
93
+ editorRef.current.getModifiedEditor().revealLineInCenter(change.modifiedStartLineNumber);
94
+ };
95
+
96
+ function getLanguageForPath(filePath) {
97
+ if (!filePath) return 'plaintext';
98
+ var fileName = filePath.split('/').pop().toLowerCase();
99
+ if (fileName === 'gemfile' || fileName === 'gemfile.lock' || fileName === 'rakefile') return 'ruby';
100
+ // Compound extensions — check before single-extension lookup
101
+ if (/\.js\.erb$/.test(fileName)) return 'js-erb';
102
+ if (/\.ts\.erb$/.test(fileName)) return 'typescript';
103
+ if (/\.html\.erb$/.test(fileName)) return 'erb';
104
+ if (/\.html\.haml$/.test(fileName)) return 'haml';
105
+ if (/\.js\.haml$/.test(fileName)) return 'javascript';
106
+ if (/\.css\.erb$/.test(fileName)) return 'css';
107
+ var ext = fileName.split('.').pop();
108
+ var map = {
109
+ 'rb': 'ruby', 'gemspec': 'ruby',
110
+ 'js': 'javascript', 'jsx': 'javascript',
111
+ 'ts': 'typescript', 'tsx': 'typescript',
112
+ 'json': 'json', 'yml': 'yaml', 'yaml': 'yaml',
113
+ 'css': 'css', 'scss': 'css', 'sass': 'css',
114
+ 'html': 'html', 'erb': 'erb', 'haml': 'haml',
115
+ 'xml': 'xml', 'md': 'markdown', 'markdown': 'markdown',
116
+ 'sh': 'shell', 'bash': 'shell', 'zsh': 'shell'
117
+ };
118
+ return map[ext] || 'plaintext';
119
+ }
120
+
121
+ var pathParts = (displayPath || '').split('/');
122
+ var fileName = pathParts.pop() || displayPath || '';
123
+ var fileDir = pathParts.join('/');
124
+
125
+ return React.createElement(
126
+ 'div',
127
+ { className: 'ide-diff-viewer' },
128
+ React.createElement(
129
+ 'div',
130
+ { className: 'ide-diff-toolbar' },
131
+ React.createElement(
132
+ 'div',
133
+ { className: 'ide-diff-title' },
134
+ React.createElement('i', { className: 'fas fa-file-contract' }),
135
+ React.createElement(
136
+ 'div',
137
+ { className: 'ide-diff-title-info', title: displayPath },
138
+ React.createElement('div', { className: 'ide-diff-title-name' }, fileName),
139
+ fileDir ? React.createElement('div', { className: 'ide-diff-title-dir' }, fileDir) : null
140
+ )
141
+ ),
142
+ React.createElement(
143
+ 'div',
144
+ { className: 'ide-diff-actions' },
145
+ onClose && React.createElement(
146
+ 'button',
147
+ { className: 'ide-diff-btn', onClick: onClose, title: 'Close diff (or click × on the tab)' },
148
+ React.createElement('i', { className: 'fas fa-times' })
149
+ ),
150
+ React.createElement(
151
+ 'button',
152
+ { className: 'ide-diff-btn', onClick: handlePrevDiff, title: 'Previous Change' },
153
+ React.createElement('i', { className: 'fas fa-arrow-up' })
154
+ ),
155
+ React.createElement(
156
+ 'button',
157
+ { className: 'ide-diff-btn', onClick: handleNextDiff, title: 'Next Change' },
158
+ React.createElement('i', { className: 'fas fa-arrow-down' })
159
+ )
160
+ )
161
+ ),
162
+ React.createElement('div', { className: 'ide-diff-editor-container', ref: containerRef })
163
+ );
164
+ };
165
+
166
+ window.DiffViewer = DiffViewer;