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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +116 -0
- data/README.md +180 -0
- data/app/assets/javascripts/mbeditor/application.js +21 -0
- data/app/assets/javascripts/mbeditor/components/CodeReviewPanel.js +202 -0
- data/app/assets/javascripts/mbeditor/components/CollapsibleSection.js +71 -0
- data/app/assets/javascripts/mbeditor/components/CombinedDiffViewer.js +139 -0
- data/app/assets/javascripts/mbeditor/components/CommitGraph.js +65 -0
- data/app/assets/javascripts/mbeditor/components/DiffViewer.js +166 -0
- data/app/assets/javascripts/mbeditor/components/EditorPanel.js +1139 -0
- data/app/assets/javascripts/mbeditor/components/FileHistoryPanel.js +117 -0
- data/app/assets/javascripts/mbeditor/components/FileTree.js +339 -0
- data/app/assets/javascripts/mbeditor/components/GitPanel.js +501 -0
- data/app/assets/javascripts/mbeditor/components/MbeditorApp.js +3108 -0
- data/app/assets/javascripts/mbeditor/components/QuickOpenDialog.js +272 -0
- data/app/assets/javascripts/mbeditor/components/ShortcutHelp.js +186 -0
- data/app/assets/javascripts/mbeditor/components/TabBar.js +238 -0
- data/app/assets/javascripts/mbeditor/components/TestResultsPanel.js +150 -0
- data/app/assets/javascripts/mbeditor/editor_plugins.js +758 -0
- data/app/assets/javascripts/mbeditor/editor_store.js +69 -0
- data/app/assets/javascripts/mbeditor/file_icon.js +30 -0
- data/app/assets/javascripts/mbeditor/file_service.js +96 -0
- data/app/assets/javascripts/mbeditor/git_service.js +104 -0
- data/app/assets/javascripts/mbeditor/search_service.js +63 -0
- data/app/assets/javascripts/mbeditor/tab_manager.js +485 -0
- data/app/assets/stylesheets/mbeditor/application.css +848 -0
- data/app/assets/stylesheets/mbeditor/editor.css +2061 -0
- data/app/controllers/mbeditor/application_controller.rb +70 -0
- data/app/controllers/mbeditor/editors_controller.rb +996 -0
- data/app/controllers/mbeditor/git_controller.rb +234 -0
- data/app/services/mbeditor/git_blame_service.rb +98 -0
- data/app/services/mbeditor/git_commit_graph_service.rb +60 -0
- data/app/services/mbeditor/git_diff_service.rb +74 -0
- data/app/services/mbeditor/git_file_history_service.rb +42 -0
- data/app/services/mbeditor/git_service.rb +95 -0
- data/app/services/mbeditor/redmine_service.rb +86 -0
- data/app/services/mbeditor/ruby_definition_service.rb +168 -0
- data/app/services/mbeditor/test_runner_service.rb +286 -0
- data/app/views/layouts/mbeditor/application.html.erb +120 -0
- data/app/views/mbeditor/editors/index.html.erb +1 -0
- data/config/initializers/assets.rb +9 -0
- data/config/routes.rb +44 -0
- data/lib/mbeditor/configuration.rb +22 -0
- data/lib/mbeditor/engine.rb +37 -0
- data/lib/mbeditor/rack/silence_ping_request.rb +56 -0
- data/lib/mbeditor/version.rb +3 -0
- data/lib/mbeditor.rb +19 -0
- data/mbeditor.gemspec +31 -0
- data/public/mbeditor-icon.svg +4 -0
- data/public/min-maps/vs/base/worker/workerMain.js.map +1 -0
- data/public/monaco-editor/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
- data/public/monaco-editor/vs/base/worker/workerMain.js +31 -0
- data/public/monaco-editor/vs/basic-languages/cameligo/cameligo.js +10 -0
- data/public/monaco-editor/vs/basic-languages/css/css.js +12 -0
- data/public/monaco-editor/vs/basic-languages/dart/dart.js +10 -0
- data/public/monaco-editor/vs/basic-languages/flow9/flow9.js +10 -0
- data/public/monaco-editor/vs/basic-languages/go/go.js +10 -0
- data/public/monaco-editor/vs/basic-languages/handlebars/handlebars.js +440 -0
- data/public/monaco-editor/vs/basic-languages/javascript/javascript.js +10 -0
- data/public/monaco-editor/vs/basic-languages/markdown/markdown.js +10 -0
- data/public/monaco-editor/vs/basic-languages/msdax/msdax.js +10 -0
- data/public/monaco-editor/vs/basic-languages/postiats/postiats.js +10 -0
- data/public/monaco-editor/vs/basic-languages/pug/pug.js +412 -0
- data/public/monaco-editor/vs/basic-languages/restructuredtext/restructuredtext.js +10 -0
- data/public/monaco-editor/vs/basic-languages/ruby/ruby.js +10 -0
- data/public/monaco-editor/vs/basic-languages/sb/sb.js +10 -0
- data/public/monaco-editor/vs/basic-languages/shell/shell.js +41 -0
- data/public/monaco-editor/vs/basic-languages/typescript/typescript.js +10 -0
- data/public/monaco-editor/vs/basic-languages/typespec/typespec.js +10 -0
- data/public/monaco-editor/vs/basic-languages/yaml/yaml.js +10 -0
- data/public/monaco-editor/vs/editor/editor.api.js +6 -0
- data/public/monaco-editor/vs/editor/editor.main.css +8 -0
- data/public/monaco-editor/vs/editor/editor.main.js +797 -0
- data/public/monaco-editor/vs/language/typescript/tsMode.js +20 -0
- data/public/monaco-editor/vs/language/typescript/tsWorker.js +51328 -0
- data/public/monaco-editor/vs/loader.js +10 -0
- data/public/monaco-editor/vs/nls.messages.de.js +20 -0
- data/public/monaco-editor/vs/nls.messages.es.js +20 -0
- data/public/monaco-editor/vs/nls.messages.fr.js +18 -0
- data/public/monaco-editor/vs/nls.messages.it.js +18 -0
- data/public/monaco-editor/vs/nls.messages.ja.js +20 -0
- data/public/monaco-editor/vs/nls.messages.ko.js +18 -0
- data/public/monaco-editor/vs/nls.messages.ru.js +20 -0
- data/public/monaco-editor/vs/nls.messages.zh-cn.js +20 -0
- data/public/monaco-editor/vs/nls.messages.zh-tw.js +18 -0
- data/public/monaco_worker.js +5 -0
- data/public/sw.js +8 -0
- data/public/ts_worker.js +5 -0
- data/vendor/assets/javascripts/axios.min.js +5 -0
- data/vendor/assets/javascripts/emmet.js +5452 -0
- data/vendor/assets/javascripts/lodash.min.js +136 -0
- data/vendor/assets/javascripts/marked.min.js +6 -0
- data/vendor/assets/javascripts/minisearch.min.js +2044 -0
- data/vendor/assets/javascripts/monaco-themes-bundle.js +10 -0
- data/vendor/assets/javascripts/monaco-vim.js +9867 -0
- data/vendor/assets/javascripts/prettier-plugin-babel.js +16 -0
- data/vendor/assets/javascripts/prettier-plugin-estree.js +35 -0
- data/vendor/assets/javascripts/prettier-plugin-html.js +19 -0
- data/vendor/assets/javascripts/prettier-plugin-markdown.js +59 -0
- data/vendor/assets/javascripts/prettier-plugin-postcss.js +52 -0
- data/vendor/assets/javascripts/prettier-standalone.js +37 -0
- data/vendor/assets/javascripts/react-dom.min.js +267 -0
- data/vendor/assets/javascripts/react.min.js +31 -0
- data/vendor/assets/stylesheets/fontawesome.min.css.erb +9 -0
- data/vendor/assets/webfonts/fa-brands-400.woff2 +0 -0
- data/vendor/assets/webfonts/fa-regular-400.woff2 +0 -0
- data/vendor/assets/webfonts/fa-solid-900.woff2 +0 -0
- 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;
|