mbeditor 0.1.0

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 (94) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +127 -0
  3. data/app/assets/javascripts/mbeditor/application.js +19 -0
  4. data/app/assets/javascripts/mbeditor/components/CodeReviewPanel.js +202 -0
  5. data/app/assets/javascripts/mbeditor/components/CollapsibleSection.js +71 -0
  6. data/app/assets/javascripts/mbeditor/components/CombinedDiffViewer.js +139 -0
  7. data/app/assets/javascripts/mbeditor/components/CommitGraph.js +65 -0
  8. data/app/assets/javascripts/mbeditor/components/DiffViewer.js +142 -0
  9. data/app/assets/javascripts/mbeditor/components/EditorPanel.js +363 -0
  10. data/app/assets/javascripts/mbeditor/components/FileHistoryPanel.js +112 -0
  11. data/app/assets/javascripts/mbeditor/components/FileTree.js +304 -0
  12. data/app/assets/javascripts/mbeditor/components/GitPanel.js +416 -0
  13. data/app/assets/javascripts/mbeditor/components/MbeditorApp.js +2335 -0
  14. data/app/assets/javascripts/mbeditor/components/QuickOpenDialog.js +118 -0
  15. data/app/assets/javascripts/mbeditor/components/ShortcutHelp.js +186 -0
  16. data/app/assets/javascripts/mbeditor/components/TabBar.js +123 -0
  17. data/app/assets/javascripts/mbeditor/editor_plugins.js +282 -0
  18. data/app/assets/javascripts/mbeditor/editor_store.js +53 -0
  19. data/app/assets/javascripts/mbeditor/file_service.js +77 -0
  20. data/app/assets/javascripts/mbeditor/git_service.js +104 -0
  21. data/app/assets/javascripts/mbeditor/search_service.js +53 -0
  22. data/app/assets/javascripts/mbeditor/tab_manager.js +461 -0
  23. data/app/assets/stylesheets/mbeditor/application.css +705 -0
  24. data/app/assets/stylesheets/mbeditor/editor.css +1264 -0
  25. data/app/controllers/mbeditor/application_controller.rb +10 -0
  26. data/app/controllers/mbeditor/editors_controller.rb +695 -0
  27. data/app/controllers/mbeditor/git_controller.rb +188 -0
  28. data/app/services/mbeditor/git_blame_service.rb +98 -0
  29. data/app/services/mbeditor/git_commit_graph_service.rb +60 -0
  30. data/app/services/mbeditor/git_diff_service.rb +71 -0
  31. data/app/services/mbeditor/git_file_history_service.rb +42 -0
  32. data/app/services/mbeditor/git_service.rb +82 -0
  33. data/app/services/mbeditor/redmine_service.rb +86 -0
  34. data/app/views/layouts/mbeditor/application.html.erb +71 -0
  35. data/app/views/mbeditor/editors/index.html.erb +1 -0
  36. data/config/environments/development.rb +53 -0
  37. data/config/initializers/assets.rb +9 -0
  38. data/config/routes.rb +37 -0
  39. data/lib/mbeditor/configuration.rb +16 -0
  40. data/lib/mbeditor/engine.rb +28 -0
  41. data/lib/mbeditor/version.rb +3 -0
  42. data/lib/mbeditor.rb +19 -0
  43. data/mbeditor.gemspec +30 -0
  44. data/public/min-maps/vs/base/worker/workerMain.js.map +1 -0
  45. data/public/monaco-editor/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
  46. data/public/monaco-editor/vs/base/worker/workerMain.js +31 -0
  47. data/public/monaco-editor/vs/basic-languages/cameligo/cameligo.js +10 -0
  48. data/public/monaco-editor/vs/basic-languages/css/css.js +12 -0
  49. data/public/monaco-editor/vs/basic-languages/dart/dart.js +10 -0
  50. data/public/monaco-editor/vs/basic-languages/flow9/flow9.js +10 -0
  51. data/public/monaco-editor/vs/basic-languages/go/go.js +10 -0
  52. data/public/monaco-editor/vs/basic-languages/handlebars/handlebars.js +440 -0
  53. data/public/monaco-editor/vs/basic-languages/javascript/javascript.js +10 -0
  54. data/public/monaco-editor/vs/basic-languages/markdown/markdown.js +10 -0
  55. data/public/monaco-editor/vs/basic-languages/msdax/msdax.js +10 -0
  56. data/public/monaco-editor/vs/basic-languages/postiats/postiats.js +10 -0
  57. data/public/monaco-editor/vs/basic-languages/pug/pug.js +412 -0
  58. data/public/monaco-editor/vs/basic-languages/restructuredtext/restructuredtext.js +10 -0
  59. data/public/monaco-editor/vs/basic-languages/ruby/ruby.js +10 -0
  60. data/public/monaco-editor/vs/basic-languages/sb/sb.js +10 -0
  61. data/public/monaco-editor/vs/basic-languages/typespec/typespec.js +10 -0
  62. data/public/monaco-editor/vs/basic-languages/yaml/yaml.js +10 -0
  63. data/public/monaco-editor/vs/editor/editor.main.css +8 -0
  64. data/public/monaco-editor/vs/editor/editor.main.js +797 -0
  65. data/public/monaco-editor/vs/language/typescript/tsMode.js +20 -0
  66. data/public/monaco-editor/vs/language/typescript/tsWorker.js +51328 -0
  67. data/public/monaco-editor/vs/loader.js +10 -0
  68. data/public/monaco-editor/vs/nls.messages.de.js +20 -0
  69. data/public/monaco-editor/vs/nls.messages.es.js +20 -0
  70. data/public/monaco-editor/vs/nls.messages.fr.js +18 -0
  71. data/public/monaco-editor/vs/nls.messages.it.js +18 -0
  72. data/public/monaco-editor/vs/nls.messages.ja.js +20 -0
  73. data/public/monaco-editor/vs/nls.messages.ko.js +18 -0
  74. data/public/monaco-editor/vs/nls.messages.ru.js +20 -0
  75. data/public/monaco-editor/vs/nls.messages.zh-cn.js +20 -0
  76. data/public/monaco-editor/vs/nls.messages.zh-tw.js +18 -0
  77. data/public/monaco_worker.js +5 -0
  78. data/vendor/assets/javascripts/axios.min.js +2 -0
  79. data/vendor/assets/javascripts/lodash.min.js +140 -0
  80. data/vendor/assets/javascripts/marked.min.js +6 -0
  81. data/vendor/assets/javascripts/minisearch.min.js +2044 -0
  82. data/vendor/assets/javascripts/prettier-plugin-babel.js +16 -0
  83. data/vendor/assets/javascripts/prettier-plugin-estree.js +35 -0
  84. data/vendor/assets/javascripts/prettier-plugin-html.js +19 -0
  85. data/vendor/assets/javascripts/prettier-plugin-markdown.js +59 -0
  86. data/vendor/assets/javascripts/prettier-plugin-postcss.js +52 -0
  87. data/vendor/assets/javascripts/prettier-standalone.js +37 -0
  88. data/vendor/assets/javascripts/react-dom.min.js +267 -0
  89. data/vendor/assets/javascripts/react.min.js +31 -0
  90. data/vendor/assets/stylesheets/fontawesome.min.css +9 -0
  91. data/vendor/assets/webfonts/fa-brands-400.woff2 +0 -0
  92. data/vendor/assets/webfonts/fa-regular-400.woff2 +0 -0
  93. data/vendor/assets/webfonts/fa-solid-900.woff2 +0 -0
  94. metadata +173 -0
@@ -0,0 +1,118 @@
1
+ "use strict";
2
+
3
+ var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; })();
4
+
5
+ var _React = React;
6
+ var useState = _React.useState;
7
+ var useEffect = _React.useEffect;
8
+ var useRef = _React.useRef;
9
+
10
+ var QuickOpenDialog = function QuickOpenDialog(_ref) {
11
+ var onSelect = _ref.onSelect;
12
+ var onClose = _ref.onClose;
13
+
14
+ var _useState = useState("");
15
+
16
+ var _useState2 = _slicedToArray(_useState, 2);
17
+
18
+ var query = _useState2[0];
19
+ var setQuery = _useState2[1];
20
+
21
+ var _useState3 = useState([]);
22
+
23
+ var _useState32 = _slicedToArray(_useState3, 2);
24
+
25
+ var results = _useState32[0];
26
+ var setResults = _useState32[1];
27
+
28
+ var _useState4 = useState(0);
29
+
30
+ var _useState42 = _slicedToArray(_useState4, 2);
31
+
32
+ var selectedIndex = _useState42[0];
33
+ var setSelectedIndex = _useState42[1];
34
+
35
+ var inputRef = useRef(null);
36
+
37
+ useEffect(function () {
38
+ if (inputRef.current) inputRef.current.focus();
39
+ }, []);
40
+
41
+ useEffect(function () {
42
+ var res = SearchService.searchFiles(query);
43
+ setResults(res.slice(0, 20)); // cap at 20
44
+ setSelectedIndex(0);
45
+ }, [query]);
46
+
47
+ var handleKeyDown = function handleKeyDown(e) {
48
+ if (e.key === "Escape") onClose();
49
+ if (e.key === "ArrowDown") setSelectedIndex(function (i) {
50
+ return Math.min(i + 1, results.length - 1);
51
+ });
52
+ if (e.key === "ArrowUp") setSelectedIndex(function (i) {
53
+ return Math.max(i - 1, 0);
54
+ });
55
+ if (e.key === "Enter" && results[selectedIndex]) {
56
+ var res = results[selectedIndex];
57
+ onSelect(res.path, res.name);
58
+ }
59
+ };
60
+
61
+ return React.createElement(
62
+ "div",
63
+ { className: "quick-open-overlay", onClick: onClose },
64
+ React.createElement(
65
+ "div",
66
+ { className: "quick-open-box", onClick: function (e) {
67
+ return e.stopPropagation();
68
+ } },
69
+ React.createElement("input", {
70
+ ref: inputRef,
71
+ type: "text",
72
+ className: "quick-open-input",
73
+ placeholder: "Search files by name (Ctrl+P)...",
74
+ value: query,
75
+ onChange: function (e) {
76
+ return setQuery(e.target.value);
77
+ },
78
+ onKeyDown: handleKeyDown
79
+ }),
80
+ React.createElement(
81
+ "div",
82
+ { className: "quick-open-results" },
83
+ results.map(function (res, i) {
84
+ return React.createElement(
85
+ "div",
86
+ {
87
+ key: res.id,
88
+ className: "quick-open-result " + (i === selectedIndex ? "selected" : ""),
89
+ onClick: function () {
90
+ return onSelect(res.path, res.name);
91
+ },
92
+ onMouseEnter: function () {
93
+ return setSelectedIndex(i);
94
+ }
95
+ },
96
+ React.createElement(
97
+ "div",
98
+ { className: "quick-open-result-name" },
99
+ res.name
100
+ ),
101
+ React.createElement(
102
+ "div",
103
+ { className: "quick-open-result-path" },
104
+ res.path
105
+ )
106
+ );
107
+ }),
108
+ query && results.length === 0 && React.createElement(
109
+ "div",
110
+ { style: { padding: "12px 16px", color: "#666", fontSize: "12px" } },
111
+ "No matching files."
112
+ )
113
+ )
114
+ )
115
+ );
116
+ };
117
+
118
+ window.QuickOpenDialog = QuickOpenDialog;
@@ -0,0 +1,186 @@
1
+ 'use strict';
2
+
3
+ // ShortcutHelp — isolated module.
4
+ // Renders a centred overlay listing all keyboard shortcuts and usage tips.
5
+ // Dismissable with the × button, clicking the backdrop, or Escape.
6
+ // Mount/unmount is controlled entirely by the parent (showHelp state).
7
+
8
+ var ShortcutHelp = function ShortcutHelp(_ref) {
9
+ var onClose = _ref.onClose;
10
+
11
+ var _React = React;
12
+ var useEffect = _React.useEffect;
13
+
14
+ useEffect(function () {
15
+ function onKeyDown(e) {
16
+ if (e.key === 'Escape') onClose();
17
+ }
18
+ window.addEventListener('keydown', onKeyDown);
19
+ return function () { window.removeEventListener('keydown', onKeyDown); };
20
+ }, [onClose]);
21
+
22
+ function Section(props) {
23
+ return React.createElement(
24
+ 'div',
25
+ { className: 'shelp-section' },
26
+ React.createElement('h3', { className: 'shelp-section-title' }, props.title),
27
+ props.children
28
+ );
29
+ }
30
+
31
+ function Row(props) {
32
+ return React.createElement(
33
+ 'tr',
34
+ null,
35
+ React.createElement(
36
+ 'td',
37
+ { className: 'shelp-key' },
38
+ React.createElement('kbd', null, props.keys)
39
+ ),
40
+ React.createElement('td', { className: 'shelp-desc' }, props.desc)
41
+ );
42
+ }
43
+
44
+ function Tips(props) {
45
+ return React.createElement(
46
+ 'ul',
47
+ { className: 'shelp-tips' },
48
+ props.items.map(function (item, i) {
49
+ return React.createElement('li', { key: i }, item);
50
+ })
51
+ );
52
+ }
53
+
54
+ return React.createElement(
55
+ 'div',
56
+ { className: 'shelp-backdrop', onClick: onClose },
57
+ React.createElement(
58
+ 'div',
59
+ {
60
+ className: 'shelp-panel',
61
+ onClick: function (e) { e.stopPropagation(); },
62
+ role: 'dialog',
63
+ 'aria-modal': 'true',
64
+ 'aria-label': 'Keyboard shortcuts and help'
65
+ },
66
+ React.createElement(
67
+ 'div',
68
+ { className: 'shelp-header' },
69
+ React.createElement(
70
+ 'span',
71
+ { className: 'shelp-title' },
72
+ React.createElement('i', { className: 'fas fa-keyboard', style: { marginRight: '8px' } }),
73
+ 'Keyboard Shortcuts & Help'
74
+ ),
75
+ React.createElement(
76
+ 'button',
77
+ { className: 'shelp-close', onClick: onClose, 'aria-label': 'Close help' },
78
+ React.createElement('i', { className: 'fas fa-times' })
79
+ )
80
+ ),
81
+
82
+ React.createElement(
83
+ 'div',
84
+ { className: 'shelp-body' },
85
+
86
+ React.createElement(
87
+ 'div',
88
+ { className: 'shelp-columns' },
89
+
90
+ // Left column
91
+ React.createElement(
92
+ 'div',
93
+ { className: 'shelp-col' },
94
+
95
+ React.createElement(
96
+ Section,
97
+ { title: 'File navigation' },
98
+ React.createElement(
99
+ 'table',
100
+ { className: 'shelp-table' },
101
+ React.createElement(
102
+ 'tbody',
103
+ null,
104
+ React.createElement(Row, { keys: 'Ctrl+P', desc: 'Quick-open any file by name' }),
105
+ React.createElement(Row, { keys: 'Ctrl+S', desc: 'Save the active file' }),
106
+ React.createElement(Row, { keys: 'Escape', desc: 'Close quick-open / context menus' })
107
+ )
108
+ )
109
+ ),
110
+
111
+ React.createElement(
112
+ Section,
113
+ { title: 'Editor actions' },
114
+ React.createElement(
115
+ 'table',
116
+ { className: 'shelp-table' },
117
+ React.createElement(
118
+ 'tbody',
119
+ null,
120
+ React.createElement(Row, { keys: 'Ctrl+Z', desc: 'Undo' }),
121
+ React.createElement(Row, { keys: 'Ctrl+Y', desc: 'Redo' }),
122
+ React.createElement(Row, { keys: 'Ctrl+/', desc: 'Toggle line comment' }),
123
+ React.createElement(Row, { keys: 'Ctrl+D', desc: 'Select next occurrence' }),
124
+ React.createElement(Row, { keys: 'Alt+↑/↓', desc: 'Move line up / down' }),
125
+ React.createElement(Row, { keys: 'Ctrl+Space', desc: 'Trigger autocomplete' })
126
+ )
127
+ )
128
+ )
129
+ ),
130
+
131
+ // Right column
132
+ React.createElement(
133
+ 'div',
134
+ { className: 'shelp-col' },
135
+
136
+ React.createElement(
137
+ Section,
138
+ { title: 'Tabs & panes' },
139
+ React.createElement(
140
+ Tips,
141
+ {
142
+ items: [
143
+ 'Click a file to open a preview tab',
144
+ 'Double-click to pin the tab permanently',
145
+ 'Drag a tab to the right half to create a split pane',
146
+ 'Use × to close a tab, or middle-click'
147
+ ]
148
+ }
149
+ )
150
+ ),
151
+
152
+ React.createElement(
153
+ Section,
154
+ { title: 'Sidebar panels' },
155
+ React.createElement(
156
+ Tips,
157
+ {
158
+ items: [
159
+ 'Explorer — browse files; click to open',
160
+ 'Search — full-text search across all project files',
161
+ 'Git (top-right) — branch info, changed and unpushed files'
162
+ ]
163
+ }
164
+ )
165
+ ),
166
+
167
+ React.createElement(
168
+ Section,
169
+ { title: 'File tree' },
170
+ React.createElement(
171
+ Tips,
172
+ {
173
+ items: [
174
+ 'Right-click a file or folder for rename / delete / new file',
175
+ 'Click a folder to expand or collapse it',
176
+ 'Coloured badges show git status (M modified, A added, D deleted)'
177
+ ]
178
+ }
179
+ )
180
+ )
181
+ )
182
+ )
183
+ )
184
+ )
185
+ );
186
+ };
@@ -0,0 +1,123 @@
1
+ 'use strict';
2
+
3
+ var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
4
+
5
+ var _React = React;
6
+ var useState = _React.useState;
7
+ var useEffect = _React.useEffect;
8
+ var useRef = _React.useRef;
9
+
10
+ var TabBar = function TabBar(_ref) {
11
+ var tabs = _ref.tabs;
12
+ var activeId = _ref.activeId;
13
+ var onSelect = _ref.onSelect;
14
+ var onClose = _ref.onClose;
15
+ var onTabDragStart = _ref.onTabDragStart;
16
+ var onTabDragEnd = _ref.onTabDragEnd;
17
+ var onHardenTab = _ref.onHardenTab;
18
+ var onShowHistory = _ref.onShowHistory;
19
+
20
+ var containerRef = useRef(null);
21
+
22
+ var _useState = useState(null);
23
+
24
+ var _useState2 = _slicedToArray(_useState, 2);
25
+
26
+ var draggingTabId = _useState2[0];
27
+ var setDraggingTabId = _useState2[1];
28
+
29
+ var getTabMarkerClass = function getTabMarkerClass(tab) {
30
+ var tabMarkers = tab.markers || [];
31
+ if (!tabMarkers.length) return '';
32
+
33
+ var hasError = tabMarkers.some(function (marker) {
34
+ var severity = String(marker && marker.severity || '').toLowerCase();
35
+ return severity === 'error' || severity === 'fatal';
36
+ });
37
+ if (hasError) return 'tab-has-error';
38
+
39
+ var hasWarning = tabMarkers.some(function (marker) {
40
+ var severity = String(marker && marker.severity || '').toLowerCase();
41
+ return severity !== 'error' && severity !== 'fatal';
42
+ });
43
+ if (hasWarning) return 'tab-has-warning';
44
+
45
+ return '';
46
+ };
47
+
48
+ // Scroll active tab into view
49
+ useEffect(function () {
50
+ if (containerRef.current) {
51
+ var activeEl = containerRef.current.querySelector('.tab-item.active');
52
+ if (activeEl) {
53
+ activeEl.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
54
+ }
55
+ }
56
+ }, [activeId, tabs]);
57
+
58
+ return React.createElement(
59
+ 'div',
60
+ { className: 'tab-bar', ref: containerRef, onWheel: function (e) {
61
+ if (containerRef.current) {
62
+ containerRef.current.scrollLeft += e.deltaY;
63
+ }
64
+ } },
65
+ tabs.map(function (tab) {
66
+ var isSpecial = tab.isCommitGraph || tab.isDiff || tab.isPreview;
67
+ return React.createElement(
68
+ 'div',
69
+ {
70
+ key: tab.id,
71
+ className: 'tab-item ' + (activeId === tab.id ? 'active' : '') + ' ' + (tab.isSoftOpen ? 'tab-soft' : '') + ' ' + getTabMarkerClass(tab) + ' ' + (draggingTabId === tab.id ? 'dragging' : ''),
72
+ onClick: function () {
73
+ return onSelect(tab.id);
74
+ },
75
+ onDoubleClick: function () {
76
+ if (tab.isSoftOpen && onHardenTab) onHardenTab(tab.id);
77
+ },
78
+ title: tab.path + ' - Drag to move to another pane',
79
+ draggable: true,
80
+ onDragStart: function (e) {
81
+ e.dataTransfer.effectAllowed = 'move';
82
+ e.dataTransfer.setData('application/x-mbeditor-tab', tab.id);
83
+ setDraggingTabId(tab.id);
84
+ if (onTabDragStart) onTabDragStart(tab.id);
85
+ },
86
+ onDragEnd: function () {
87
+ setDraggingTabId(null);
88
+ if (onTabDragEnd) onTabDragEnd();
89
+ },
90
+ onContextMenu: function (e) {
91
+ if (isSpecial) return;
92
+ e.preventDefault();
93
+ if (onShowHistory) onShowHistory(tab.path);
94
+ }
95
+ },
96
+ React.createElement('i', { className: 'tab-item-icon ' + (window.getFileIcon ? window.getFileIcon(tab.name) : 'far fa-file-code') }),
97
+ React.createElement(
98
+ 'div',
99
+ { className: 'tab-item-name' },
100
+ tab.name
101
+ ),
102
+ tab.dirty && React.createElement(
103
+ 'div',
104
+ { className: 'tab-dirty-dot' },
105
+ '●'
106
+ ),
107
+ React.createElement(
108
+ 'div',
109
+ {
110
+ className: 'tab-close',
111
+ onClick: function (e) {
112
+ e.stopPropagation();
113
+ onClose(tab.id);
114
+ }
115
+ },
116
+ React.createElement('i', { className: 'fas fa-times' })
117
+ )
118
+ );
119
+ })
120
+ );
121
+ };
122
+
123
+ window.TabBar = TabBar;