mbeditor 0.3.8 → 0.4.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 +4 -4
- data/CHANGELOG.md +35 -0
- data/app/assets/javascripts/mbeditor/application.js +1 -0
- data/app/assets/javascripts/mbeditor/application_iife_head.js +7 -0
- data/app/assets/javascripts/mbeditor/components/CodeReviewPanel.js +1 -1
- data/app/assets/javascripts/mbeditor/components/EditorPanel.js +213 -11
- data/app/assets/javascripts/mbeditor/components/GitPanel.js +14 -4
- data/app/assets/javascripts/mbeditor/components/MbeditorApp.js +673 -160
- data/app/assets/javascripts/mbeditor/components/QuickOpenDialog.js +41 -1
- data/app/assets/javascripts/mbeditor/components/TabBar.js +3 -2
- data/app/assets/javascripts/mbeditor/editor_plugins.js +21 -0
- data/app/assets/javascripts/mbeditor/editor_store.js +10 -2
- data/app/assets/javascripts/mbeditor/file_service.js +29 -23
- data/app/assets/javascripts/mbeditor/git_service.js +7 -11
- data/app/assets/javascripts/mbeditor/search_service.js +51 -14
- data/app/assets/javascripts/mbeditor/tab_manager.js +3 -3
- data/app/assets/javascripts/mbeditor/websocket_service.js +126 -0
- data/app/assets/stylesheets/mbeditor/editor.css +237 -15
- data/app/channels/mbeditor/editor_channel.rb +79 -0
- data/app/controllers/mbeditor/editors_controller.rb +177 -136
- data/app/controllers/mbeditor/git_controller.rb +5 -40
- data/app/services/mbeditor/git_blame_service.rb +6 -0
- data/app/services/mbeditor/git_commit_graph_service.rb +2 -0
- data/app/services/mbeditor/git_service.rb +97 -28
- data/app/services/mbeditor/redmine_service.rb +7 -0
- data/app/services/mbeditor/ruby_definition_service.rb +23 -2
- data/app/views/layouts/mbeditor/application.html.erb +4 -0
- data/lib/mbeditor/cable_log_filter.rb +28 -0
- data/lib/mbeditor/configuration.rb +7 -1
- data/lib/mbeditor/engine.rb +37 -0
- data/lib/mbeditor/rack/silence_ping_request.rb +4 -1
- data/lib/mbeditor/version.rb +3 -1
- data/lib/mbeditor.rb +2 -0
- metadata +5 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "open3"
|
|
4
|
+
require "timeout"
|
|
4
5
|
|
|
5
6
|
module Mbeditor
|
|
6
7
|
# Shared helpers for running git CLI commands read-only inside a repo.
|
|
@@ -10,16 +11,37 @@ module Mbeditor
|
|
|
10
11
|
module_function
|
|
11
12
|
|
|
12
13
|
# Safe pattern for git ref names (branch, remote/branch, tag).
|
|
13
|
-
#
|
|
14
|
-
# git reflog syntax (e.g. "@{" sequences beyond the trailing "@{u}").
|
|
14
|
+
# Excludes @ to prevent reflog syntax like @{-1} or @{u}.
|
|
15
15
|
SAFE_GIT_REF = %r{\A[\w./-]+\z}
|
|
16
16
|
|
|
17
17
|
# Run an arbitrary git command inside +repo_path+.
|
|
18
18
|
# Returns [stdout, Process::Status]. stderr is captured and discarded to
|
|
19
19
|
# prevent git diagnostic messages from leaking into the Rails server log.
|
|
20
|
+
# Honors config.git_timeout (seconds) when set.
|
|
20
21
|
def run_git(repo_path, *args)
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
timeout_secs = Mbeditor.configuration.git_timeout&.to_i
|
|
23
|
+
out = +""; timed_out = false; exit_status = nil
|
|
24
|
+
|
|
25
|
+
Open3.popen3("git", "-C", repo_path, *args, pgroup: true) do |stdin, stdout, _stderr, wait_thr|
|
|
26
|
+
stdin.close
|
|
27
|
+
|
|
28
|
+
timer = if timeout_secs && timeout_secs > 0
|
|
29
|
+
Thread.new do
|
|
30
|
+
sleep timeout_secs
|
|
31
|
+
timed_out = true
|
|
32
|
+
Process.kill("-KILL", wait_thr.pid)
|
|
33
|
+
rescue Errno::ESRCH
|
|
34
|
+
nil
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
out = stdout.read
|
|
39
|
+
exit_status = wait_thr.value
|
|
40
|
+
timer&.kill
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
raise Timeout::Error, "git timed out after #{timeout_secs}s" if timed_out
|
|
44
|
+
[out, exit_status]
|
|
23
45
|
end
|
|
24
46
|
|
|
25
47
|
# Current branch name, or nil if not in a git repo.
|
|
@@ -51,36 +73,57 @@ module Mbeditor
|
|
|
51
73
|
[parts[0].to_i, parts[1].to_i]
|
|
52
74
|
end
|
|
53
75
|
|
|
76
|
+
# Returns [merge_base_sha, ref_name] of the first candidate base branch found,
|
|
77
|
+
# or [nil, nil] if none can be determined. Candidates are tried in preference
|
|
78
|
+
# order; skips the current branch and refs whose merge-base equals HEAD.
|
|
79
|
+
def find_branch_base(repo_path, current_branch, candidates: nil)
|
|
80
|
+
candidates ||= Mbeditor.configuration.base_branch_candidates
|
|
81
|
+
head_sha_out, = run_git(repo_path, "rev-parse", "HEAD")
|
|
82
|
+
head_sha = head_sha_out.strip
|
|
83
|
+
|
|
84
|
+
candidates.each do |ref|
|
|
85
|
+
short = ref.delete_prefix("origin/")
|
|
86
|
+
next if short == current_branch || ref == current_branch
|
|
87
|
+
|
|
88
|
+
_o, st = run_git(repo_path, "rev-parse", "--verify", "--quiet", ref)
|
|
89
|
+
next unless st.success?
|
|
90
|
+
|
|
91
|
+
base_out, base_st = run_git(repo_path, "merge-base", "HEAD", ref)
|
|
92
|
+
next unless base_st.success?
|
|
93
|
+
|
|
94
|
+
sha = base_out.strip
|
|
95
|
+
next unless sha.match?(/\A[0-9a-f]{40}\z/)
|
|
96
|
+
next if sha == head_sha
|
|
97
|
+
|
|
98
|
+
return [sha, ref]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
[nil, nil]
|
|
102
|
+
rescue StandardError
|
|
103
|
+
[nil, nil]
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Parse `git diff --numstat` output.
|
|
107
|
+
# Returns Hash of path => { added: Integer, removed: Integer }.
|
|
108
|
+
def parse_numstat(output)
|
|
109
|
+
(output || "").lines.each_with_object({}) do |line, map|
|
|
110
|
+
parts = line.strip.split("\t", 3)
|
|
111
|
+
next if parts.length < 3 || parts[0] == "-"
|
|
112
|
+
|
|
113
|
+
map[parts[2].strip] = { added: parts[0].to_i, removed: parts[1].to_i }
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
54
117
|
# Parse compact `git log --pretty=format:%H%x1f%P%x1f%s%x1f%an%x1f%aI%x1e` output.
|
|
55
|
-
# Returns Array of hashes.
|
|
118
|
+
# Returns Array of hashes with string keys.
|
|
56
119
|
def self.parse_git_log_with_parents(raw_output)
|
|
57
|
-
raw_output
|
|
58
|
-
fields = entry.strip.split("\x1f", 5)
|
|
59
|
-
next unless fields.length == 5
|
|
60
|
-
|
|
61
|
-
{
|
|
62
|
-
"hash" => fields[0],
|
|
63
|
-
"parents" => fields[1].split.reject(&:blank?),
|
|
64
|
-
"title" => fields[2],
|
|
65
|
-
"author" => fields[3],
|
|
66
|
-
"date" => fields[4]
|
|
67
|
-
}
|
|
68
|
-
end.compact
|
|
120
|
+
parse_log_entries(raw_output, with_parents: true)
|
|
69
121
|
end
|
|
70
122
|
|
|
71
123
|
# Parse compact `git log --pretty=format:%H%x1f%s%x1f%an%x1f%aI%x1e` output.
|
|
124
|
+
# Returns Array of hashes with string keys.
|
|
72
125
|
def self.parse_git_log(raw_output)
|
|
73
|
-
raw_output
|
|
74
|
-
fields = entry.strip.split("\x1f", 4)
|
|
75
|
-
next unless fields.length == 4
|
|
76
|
-
|
|
77
|
-
{
|
|
78
|
-
"hash" => fields[0],
|
|
79
|
-
"title" => fields[1],
|
|
80
|
-
"author" => fields[2],
|
|
81
|
-
"date" => fields[3]
|
|
82
|
-
}
|
|
83
|
-
end.compact
|
|
126
|
+
parse_log_entries(raw_output, with_parents: false)
|
|
84
127
|
end
|
|
85
128
|
|
|
86
129
|
# Resolve a file path safely within repo_path. Returns full path string or
|
|
@@ -91,5 +134,31 @@ module Mbeditor
|
|
|
91
134
|
full = File.expand_path(relative.to_s, repo_path.to_s)
|
|
92
135
|
full.start_with?(repo_path.to_s + "/") || full == repo_path.to_s ? full : nil
|
|
93
136
|
end
|
|
137
|
+
|
|
138
|
+
def self.parse_log_entries(raw_output, with_parents:)
|
|
139
|
+
field_count = with_parents ? 5 : 4
|
|
140
|
+
raw_output.split("\x1e").filter_map do |entry|
|
|
141
|
+
fields = entry.strip.split("\x1f", field_count)
|
|
142
|
+
next unless fields.length == field_count
|
|
143
|
+
|
|
144
|
+
if with_parents
|
|
145
|
+
{
|
|
146
|
+
"hash" => fields[0],
|
|
147
|
+
"parents" => fields[1].split.reject(&:blank?),
|
|
148
|
+
"title" => fields[2],
|
|
149
|
+
"author" => fields[3],
|
|
150
|
+
"date" => fields[4]
|
|
151
|
+
}
|
|
152
|
+
else
|
|
153
|
+
{
|
|
154
|
+
"hash" => fields[0],
|
|
155
|
+
"title" => fields[1],
|
|
156
|
+
"author" => fields[2],
|
|
157
|
+
"date" => fields[3]
|
|
158
|
+
}
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
private_class_method :parse_log_entries
|
|
94
163
|
end
|
|
95
164
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "net/http"
|
|
4
|
+
require "openssl"
|
|
4
5
|
require "uri"
|
|
5
6
|
require "json"
|
|
6
7
|
|
|
@@ -42,6 +43,9 @@ module Mbeditor
|
|
|
42
43
|
raise RedmineConfigError, "redmine_url is not configured" if config.redmine_url.blank?
|
|
43
44
|
raise RedmineConfigError, "redmine_api_key is not configured" if config.redmine_api_key.blank?
|
|
44
45
|
|
|
46
|
+
uri = URI.parse(config.redmine_url.to_s.chomp("/"))
|
|
47
|
+
raise RedmineConfigError, "redmine_url must use http or https scheme" unless %w[http https].include?(uri.scheme)
|
|
48
|
+
|
|
45
49
|
fetch_issue(config.redmine_url, config.redmine_api_key)
|
|
46
50
|
end
|
|
47
51
|
|
|
@@ -52,6 +56,9 @@ module Mbeditor
|
|
|
52
56
|
|
|
53
57
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
54
58
|
http.use_ssl = uri.scheme == "https"
|
|
59
|
+
if uri.scheme == "https"
|
|
60
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
|
61
|
+
end
|
|
55
62
|
http.open_timeout = TIMEOUT_SECONDS
|
|
56
63
|
http.read_timeout = TIMEOUT_SECONDS
|
|
57
64
|
|
|
@@ -22,6 +22,7 @@ module Mbeditor
|
|
|
22
22
|
class RubyDefinitionService
|
|
23
23
|
MAX_RESULTS = 20
|
|
24
24
|
MAX_COMMENT_LOOKAHEAD = 15
|
|
25
|
+
MAX_FILES_SCANNED = 10_000
|
|
25
26
|
|
|
26
27
|
# In-process file-index cache.
|
|
27
28
|
# Structure: { absolute_path => { mtime: Float, lines: [String], all_defs: { method_name => [line, ...] } } }
|
|
@@ -101,8 +102,11 @@ module Mbeditor
|
|
|
101
102
|
def call
|
|
102
103
|
self.class.load_disk_cache_once
|
|
103
104
|
|
|
104
|
-
results
|
|
105
|
-
@new_entries
|
|
105
|
+
results = []
|
|
106
|
+
@new_entries = false
|
|
107
|
+
files_scanned = 0
|
|
108
|
+
|
|
109
|
+
evict_deleted_cache_entries
|
|
106
110
|
|
|
107
111
|
Find.find(@workspace_root) do |path|
|
|
108
112
|
# Prune excluded directories
|
|
@@ -120,6 +124,12 @@ module Mbeditor
|
|
|
120
124
|
rel = relative_path(path)
|
|
121
125
|
next if excluded_rel_path?(rel, File.basename(path))
|
|
122
126
|
|
|
127
|
+
files_scanned += 1
|
|
128
|
+
if files_scanned > MAX_FILES_SCANNED
|
|
129
|
+
Rails.logger.warn("[mbeditor] RubyDefinitionService: workspace exceeds #{MAX_FILES_SCANNED} .rb files; stopping scan early")
|
|
130
|
+
break
|
|
131
|
+
end
|
|
132
|
+
|
|
123
133
|
begin
|
|
124
134
|
cached = cache_entry_for(path)
|
|
125
135
|
next unless cached
|
|
@@ -147,6 +157,17 @@ module Mbeditor
|
|
|
147
157
|
|
|
148
158
|
private
|
|
149
159
|
|
|
160
|
+
# Remove cache entries for files that no longer exist on disk.
|
|
161
|
+
def evict_deleted_cache_entries
|
|
162
|
+
stale_keys = self.class.mutex.synchronize do
|
|
163
|
+
self.class.file_cache.keys.select { |p| !File.exist?(p) }
|
|
164
|
+
end
|
|
165
|
+
return if stale_keys.empty?
|
|
166
|
+
|
|
167
|
+
self.class.mutex.synchronize { stale_keys.each { |k| self.class.file_cache.delete(k) } }
|
|
168
|
+
@new_entries = true
|
|
169
|
+
end
|
|
170
|
+
|
|
150
171
|
# Returns the cached index entry for +path+, rebuilding it if the file has
|
|
151
172
|
# been modified since the last parse. Returns nil on any read/parse error.
|
|
152
173
|
def cache_entry_for(path)
|
|
@@ -20,6 +20,10 @@
|
|
|
20
20
|
<%= stylesheet_link_tag "fontawesome.min", media: "all", preload_links_header: false %>
|
|
21
21
|
<%= stylesheet_link_tag "mbeditor/application", media: "all", preload_links_header: false %>
|
|
22
22
|
|
|
23
|
+
<!-- ── ActionCable (deferred — sets window.ActionCable for WebSocket service) ── -->
|
|
24
|
+
<% if defined?(ActionCable::Channel::Base) %>
|
|
25
|
+
<script defer src="<%= asset_path('actioncable.js') %>"></script>
|
|
26
|
+
<% end %>
|
|
23
27
|
<!-- ── Vendor JS (deferred — only needed inside Monaco callback) ── -->
|
|
24
28
|
<script defer src="<%= asset_path('react.min.js') %>"></script>
|
|
25
29
|
<script defer src="<%= asset_path('react-dom.min.js') %>"></script>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mbeditor
|
|
4
|
+
# Wraps the ActionCable logger and suppresses all log lines that mention
|
|
5
|
+
# Mbeditor channels so the development console stays readable.
|
|
6
|
+
# Non-Mbeditor ActionCable messages pass through unchanged.
|
|
7
|
+
class CableLogFilter < SimpleDelegator
|
|
8
|
+
SUPPRESS_PATTERN = /Mbeditor::|mbeditor_editor/
|
|
9
|
+
|
|
10
|
+
%w[debug info warn error fatal unknown].each do |level|
|
|
11
|
+
define_method(level) do |message = nil, &block|
|
|
12
|
+
msg = message.nil? && block ? block.call : message.to_s
|
|
13
|
+
return if msg.match?(SUPPRESS_PATTERN)
|
|
14
|
+
|
|
15
|
+
super(message, &block)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Tagged-logging compat — the block body still passes through the filter.
|
|
20
|
+
def tagged(*tags, &block)
|
|
21
|
+
if __getobj__.respond_to?(:tagged)
|
|
22
|
+
__getobj__.tagged(*tags) { block.call }
|
|
23
|
+
else
|
|
24
|
+
block.call
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Mbeditor
|
|
2
4
|
class Configuration
|
|
3
5
|
attr_accessor :allowed_environments, :workspace_root, :excluded_paths, :rubocop_command,
|
|
4
6
|
:redmine_enabled, :redmine_url, :redmine_api_key, :redmine_ticket_source,
|
|
5
7
|
:test_framework, :test_command, :test_timeout,
|
|
6
|
-
:authenticate_with
|
|
8
|
+
:authenticate_with,
|
|
9
|
+
:lint_timeout, :base_branch_candidates, :git_timeout
|
|
7
10
|
|
|
8
11
|
def initialize
|
|
9
12
|
@allowed_environments = [:development]
|
|
@@ -17,6 +20,9 @@ module Mbeditor
|
|
|
17
20
|
@test_framework = nil # :minitest or :rspec — auto-detected when nil
|
|
18
21
|
@test_command = nil # e.g. "bundle exec ruby -Itest" or "bundle exec rspec"
|
|
19
22
|
@test_timeout = 60 # seconds
|
|
23
|
+
@lint_timeout = 15 # seconds for RuboCop/haml-lint subprocesses
|
|
24
|
+
@base_branch_candidates = %w[origin/develop origin/main origin/master develop main master]
|
|
25
|
+
@git_timeout = nil # seconds; nil disables (no timeout on git subprocesses)
|
|
20
26
|
end
|
|
21
27
|
end
|
|
22
28
|
end
|
data/lib/mbeditor/engine.rb
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require "mbeditor/rack/silence_ping_request"
|
|
2
4
|
require "mbeditor/rack/handle_pending_migrations"
|
|
5
|
+
require "mbeditor/cable_log_filter"
|
|
3
6
|
|
|
4
7
|
module Mbeditor
|
|
5
8
|
class Engine < ::Rails::Engine
|
|
@@ -22,8 +25,42 @@ module Mbeditor
|
|
|
22
25
|
end
|
|
23
26
|
|
|
24
27
|
config.after_initialize do
|
|
28
|
+
# Silence ActionCable framework logs for Mbeditor channels (subscription
|
|
29
|
+
# confirmations, streaming notices, action invocations, disconnect messages).
|
|
30
|
+
# We wrap the existing ActionCable logger in a filter proxy rather than
|
|
31
|
+
# replacing it, so the host app's non-Mbeditor channel logs are unaffected.
|
|
32
|
+
if defined?(ActionCable)
|
|
33
|
+
original_logger = ActionCable.server.config.logger || Rails.logger
|
|
34
|
+
ActionCable.server.config.logger = Mbeditor::CableLogFilter.new(original_logger)
|
|
35
|
+
end
|
|
36
|
+
|
|
25
37
|
Mbeditor::RubyDefinitionService.cache_path =
|
|
26
38
|
Rails.root.join("tmp", "mbeditor_ruby_defs.json").to_s
|
|
39
|
+
|
|
40
|
+
cfg = Mbeditor.configuration
|
|
41
|
+
|
|
42
|
+
if cfg.workspace_root.present? && !File.directory?(cfg.workspace_root.to_s)
|
|
43
|
+
raise ArgumentError, "[mbeditor] config.workspace_root is set to '#{cfg.workspace_root}' but that path is not a directory"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
if cfg.redmine_enabled
|
|
47
|
+
require "uri"
|
|
48
|
+
if cfg.redmine_url.blank?
|
|
49
|
+
Rails.logger.warn("[mbeditor] redmine_enabled is true but redmine_url is not configured")
|
|
50
|
+
else
|
|
51
|
+
begin
|
|
52
|
+
uri = URI.parse(cfg.redmine_url.to_s)
|
|
53
|
+
unless %w[http https].include?(uri.scheme)
|
|
54
|
+
Rails.logger.warn("[mbeditor] redmine_url must use http or https scheme")
|
|
55
|
+
end
|
|
56
|
+
rescue URI::InvalidURIError
|
|
57
|
+
Rails.logger.warn("[mbeditor] redmine_url is not a valid URI")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
if cfg.redmine_api_key.blank?
|
|
61
|
+
Rails.logger.warn("[mbeditor] redmine_enabled is true but redmine_api_key is not configured")
|
|
62
|
+
end
|
|
63
|
+
end
|
|
27
64
|
end
|
|
28
65
|
|
|
29
66
|
initializer "mbeditor.assets.precompile" do |app|
|
|
@@ -17,7 +17,7 @@ module Mbeditor
|
|
|
17
17
|
path = normalized_request_path(env)
|
|
18
18
|
if root_request?(env, path)
|
|
19
19
|
@app.call(env)
|
|
20
|
-
elsif mbeditor_request?(path) || editor_asset_request?(env, path)
|
|
20
|
+
elsif mbeditor_request?(path) || cable_request?(path) || editor_asset_request?(env, path)
|
|
21
21
|
Rails.logger.silence { @app.call(env) }
|
|
22
22
|
else
|
|
23
23
|
@app.call(env)
|
|
@@ -30,6 +30,9 @@ module Mbeditor
|
|
|
30
30
|
path.start_with?("/mbeditor/")
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
def cable_request?(path)
|
|
34
|
+
path == "/cable" || path.start_with?("/cable/")
|
|
35
|
+
end
|
|
33
36
|
# Silence asset pipeline requests that belong to the editor:
|
|
34
37
|
# - /assets/mbeditor/... is always an editor asset (CSS/JS bundle)
|
|
35
38
|
# - other /assets/... requests are silenced only when the browser is
|
data/lib/mbeditor/version.rb
CHANGED
data/lib/mbeditor.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mbeditor
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Oliver Noonan
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-04-
|
|
11
|
+
date: 2026-04-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -78,9 +78,11 @@ files:
|
|
|
78
78
|
- app/assets/javascripts/mbeditor/git_service.js
|
|
79
79
|
- app/assets/javascripts/mbeditor/search_service.js
|
|
80
80
|
- app/assets/javascripts/mbeditor/tab_manager.js
|
|
81
|
+
- app/assets/javascripts/mbeditor/websocket_service.js
|
|
81
82
|
- app/assets/stylesheets/mbeditor/application.css
|
|
82
83
|
- app/assets/stylesheets/mbeditor/editor.css
|
|
83
84
|
- app/assets/stylesheets/mbeditor/themes.css
|
|
85
|
+
- app/channels/mbeditor/editor_channel.rb
|
|
84
86
|
- app/controllers/mbeditor/application_controller.rb
|
|
85
87
|
- app/controllers/mbeditor/editors_controller.rb
|
|
86
88
|
- app/controllers/mbeditor/git_controller.rb
|
|
@@ -98,6 +100,7 @@ files:
|
|
|
98
100
|
- config/initializers/assets.rb
|
|
99
101
|
- config/routes.rb
|
|
100
102
|
- lib/mbeditor.rb
|
|
103
|
+
- lib/mbeditor/cable_log_filter.rb
|
|
101
104
|
- lib/mbeditor/configuration.rb
|
|
102
105
|
- lib/mbeditor/engine.rb
|
|
103
106
|
- lib/mbeditor/rack/handle_pending_migrations.rb
|