collab 0.3.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/collab.rb +3 -0
- data/lib/collab/channel.rb +25 -11
- data/lib/collab/config.rb +3 -4
- data/lib/collab/engine.rb +2 -2
- data/lib/collab/has_tracked_document_positions.rb +34 -0
- data/lib/collab/js.rb +15 -10
- data/lib/collab/models/commit.rb +13 -39
- data/lib/collab/models/document.rb +66 -8
- data/lib/collab/models/tracked_position.rb +45 -0
- data/lib/collab/selection.rb +21 -0
- data/lib/collab/version.rb +1 -1
- data/lib/generators/collab/install/templates/channel.rb +15 -8
- data/lib/generators/collab/install/templates/create_collab_tables.rb.erb +13 -0
- data/lib/generators/collab/install/templates/initializer.rb +0 -5
- metadata +33 -3
- data/app/jobs/collab/commit_job.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57b6b2acc480ad0a0d40fb20c82a1091b30dbea74b674a5d02339dd1bf8b7f83
|
4
|
+
data.tar.gz: 2a36b774b1ad0693feef4194888a07b58e8899173de10bad52a174d012a6c2f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab13771371259f4294fd94d207889643631f541dfdc26f43dbc6b2e7a454e79de4816dc4be560d1203b70dfe82a2e8b26fb3d1bcc56172743d2ce872060ee40f
|
7
|
+
data.tar.gz: 0a18c044a507454196599921a00ba0ace34fb7b3230dcb2c0a06124774f5893fa77d12a373f34d91cfe556af31a8c0d41a89571da8f3c0a37d8841dd141795e1
|
data/lib/collab.rb
CHANGED
@@ -6,10 +6,13 @@ require "collab/engine"
|
|
6
6
|
module Collab
|
7
7
|
autoload "Channel", "collab/channel"
|
8
8
|
autoload "HasCollaborativeDocument", "collab/has_collaborative_document"
|
9
|
+
# autoload "DocumentSelection", "collab/selection"
|
10
|
+
autoload "HasTrackedDocumentPositions", "collab/has_tracked_document_positions"
|
9
11
|
|
10
12
|
module Models
|
11
13
|
autoload "Base", "collab/models/base"
|
12
14
|
autoload "Document", "collab/models/document"
|
13
15
|
autoload "Commit", "collab/models/commit"
|
16
|
+
autoload "TrackedPosition", "collab/models/tracked_position"
|
14
17
|
end
|
15
18
|
end
|
data/lib/collab/channel.rb
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
module Collab
|
2
2
|
module Channel
|
3
|
-
def document; @document end
|
4
|
-
|
5
3
|
def subscribed
|
6
|
-
@document = find_document
|
7
|
-
|
4
|
+
reject_unauthorized_connection unless @document = find_document
|
5
|
+
|
8
6
|
starting_version = params[:startingVersion]&.to_i
|
9
7
|
raise "missing startingVersion" if starting_version.nil?
|
8
|
+
raise "invalid version" unless @document.possibly_saved_version? starting_version
|
10
9
|
|
11
|
-
stream_for document
|
10
|
+
stream_for @document
|
12
11
|
|
13
|
-
commits = document.commits
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
commits = @document.commits
|
13
|
+
.where("document_version > ?", starting_version)
|
14
|
+
.order(document_version: :asc)
|
15
|
+
.load
|
17
16
|
|
18
17
|
unless commits.empty?
|
19
18
|
raise "invalid version" unless commits.first.document_version == (starting_version + 1)
|
@@ -22,10 +21,25 @@ module Collab
|
|
22
21
|
end
|
23
22
|
|
24
23
|
def commit(data)
|
25
|
-
|
26
|
-
document.commit_later(data)
|
24
|
+
@document.apply_commit(data)
|
27
25
|
end
|
28
26
|
|
27
|
+
# def select(data)
|
28
|
+
# return unless defined?(_select)
|
29
|
+
|
30
|
+
# version = data["v"]&.to_i
|
31
|
+
# anchor_pos = data["anchor"]&.to_i
|
32
|
+
# head_pos = data["head"]&.to_i
|
33
|
+
|
34
|
+
# return unless version && @document.possibly_saved_version?(version) && anchor_pos && head_pos
|
35
|
+
|
36
|
+
# @document.resolve_selection(anchor_pos, head_pos, version: version) do |selection|
|
37
|
+
# _select selection
|
38
|
+
# end
|
39
|
+
|
40
|
+
# transmit({ack: "select"})
|
41
|
+
# end
|
42
|
+
|
29
43
|
def unsubscribed
|
30
44
|
stop_all_streams # this may not be needed
|
31
45
|
end
|
data/lib/collab/config.rb
CHANGED
@@ -16,19 +16,18 @@ module Collab
|
|
16
16
|
|
17
17
|
class Config
|
18
18
|
attr_accessor :base_record,
|
19
|
-
:base_job,
|
20
19
|
:channel,
|
21
|
-
:commit_job,
|
22
20
|
:commit_model,
|
23
21
|
:document_model,
|
24
22
|
:max_commit_history_length,
|
25
23
|
:num_js_processes,
|
26
|
-
:schema_package
|
24
|
+
:schema_package,
|
25
|
+
:tracked_position_model
|
27
26
|
|
28
27
|
def initialize
|
29
|
-
self.commit_job = "Collab::CommitJob"
|
30
28
|
self.document_model = "Collab::Models::Document"
|
31
29
|
self.commit_model = "Collab::Models::Commit"
|
30
|
+
self.tracked_position_model = "Collab::Models::TrackedPosition"
|
32
31
|
end
|
33
32
|
end
|
34
33
|
end
|
data/lib/collab/engine.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Collab
|
2
|
+
module HasTrackedDocumentPositions
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
class_methods do
|
6
|
+
def has_tracked_document_position(pos_name, optional: true)
|
7
|
+
has_one pos_name.to_sym, -> { where(name: pos_name) }, class_name: ::Collab.config.tracked_position_model, as: :owner, dependent: :destroy, autosave: true
|
8
|
+
validates pos_name.to_sym, presence: !optional
|
9
|
+
|
10
|
+
define_method :"#{pos_name}=" do |pos|
|
11
|
+
pos.name = pos_name
|
12
|
+
super(pos)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def has_tracked_document_selection(selection_name)
|
17
|
+
has_tracked_document_position :"#{selection_name}_anchor"
|
18
|
+
has_tracked_document_position :"#{selection_name}_head"
|
19
|
+
|
20
|
+
define_method selection_name do
|
21
|
+
anchor = self.send(:"#{selection_name}_anchor")
|
22
|
+
head = self.send(:"#{selection_name}_head")
|
23
|
+
|
24
|
+
::Collab::DocumentSelection.new anchor, head
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method :"#{selection_name}=" do |sel|
|
28
|
+
self.send(:"#{selection_name}_anchor=", sel&.anchor)
|
29
|
+
self.send(:"#{selection_name}_head=", sel&.head)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/collab/js.rb
CHANGED
@@ -21,20 +21,26 @@ module Collab
|
|
21
21
|
queue << js
|
22
22
|
end
|
23
23
|
|
24
|
-
def call(name, data = nil, schema_name
|
25
|
-
|
24
|
+
def call(name, data = nil, schema_name = nil)
|
25
|
+
req = {name: name, data: data, schemaPackage: ::Collab.config.schema_package}
|
26
|
+
req[:schemaName] = schema_name if schema_name
|
27
|
+
with_js { |js| js.call(JSON.generate(req)) }
|
26
28
|
end
|
27
29
|
|
28
|
-
def apply_commit(document, commit, schema_name:)
|
29
|
-
call("applyCommit", {doc: document, commit: commit
|
30
|
+
def apply_commit(document, commit, pos: nil, map_steps_through:, schema_name:)
|
31
|
+
call("applyCommit", {doc: document, commit: commit, mapStepsThrough: map_steps_through, pos: pos},schema_name)
|
30
32
|
end
|
31
33
|
|
32
34
|
def html_to_document(html, schema_name:)
|
33
|
-
call("htmlToDoc", html, schema_name
|
35
|
+
call("htmlToDoc", html, schema_name)
|
34
36
|
end
|
35
37
|
|
36
38
|
def document_to_html(document, schema_name:)
|
37
|
-
call("docToHtml", document, schema_name
|
39
|
+
call("docToHtml", document, schema_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
def map_through(steps:, pos:)
|
43
|
+
call("mapThru", {steps: steps, pos: pos})
|
38
44
|
end
|
39
45
|
|
40
46
|
private
|
@@ -58,9 +64,8 @@ module Collab
|
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
61
|
-
def call(
|
62
|
-
req
|
63
|
-
@node.puts(JSON.generate(req))
|
67
|
+
def call(req)
|
68
|
+
@node.puts(req)
|
64
69
|
res = JSON.parse(@node.gets)
|
65
70
|
raise ::Collab::JS::JSRuntimeError.new(res["error"]) if res["error"]
|
66
71
|
res["result"]
|
@@ -68,7 +73,7 @@ module Collab
|
|
68
73
|
|
69
74
|
private
|
70
75
|
def open_node
|
71
|
-
IO.popen(["node", "-e", "require('
|
76
|
+
IO.popen(["node", "-e", "require('@pmcp/authority/dist/rpc')"], "r+")
|
72
77
|
end
|
73
78
|
end
|
74
79
|
|
data/lib/collab/models/commit.rb
CHANGED
@@ -2,52 +2,26 @@ module Collab
|
|
2
2
|
class Models::Commit < ::Collab::Models::Base
|
3
3
|
belongs_to :document, class_name: ::Collab.config.document_model
|
4
4
|
|
5
|
-
validates :steps,
|
6
|
-
validates :document_version, presence: true
|
7
|
-
validates :ref, length: { maximum: 36 }
|
5
|
+
validates :steps, length: { in: 0..10, allow_nil: false }
|
6
|
+
validates :document_version, presence: true, numericality: {only_integer: true, greater_than_or_equal_to: 0}
|
7
|
+
validates :ref, length: { maximum: 36 }, if: :ref
|
8
8
|
|
9
9
|
after_create_commit :broadcast
|
10
10
|
|
11
|
-
def
|
12
|
-
|
11
|
+
def steps
|
12
|
+
super || []
|
13
13
|
end
|
14
14
|
|
15
|
-
def
|
16
|
-
{
|
17
|
-
v
|
18
|
-
steps
|
19
|
-
ref
|
20
|
-
}
|
21
|
-
end
|
22
|
-
|
23
|
-
def apply_later
|
24
|
-
raise "cannot apply persisted commit" if self.persisted?
|
25
|
-
raise "commit not valid" unless self.valid?
|
26
|
-
return false if self.document.document_version != self.document_version
|
27
|
-
|
28
|
-
::Collab.config.commit_job.constantize.perform_later(self.document, as_json)
|
29
|
-
end
|
30
|
-
|
31
|
-
def apply!
|
32
|
-
raise "cannot apply persisted commit" if self.persisted?
|
33
|
-
raise "commit not valid" unless self.valid?
|
34
|
-
return false if self.document.document_version != self.document_version # optimization, prevents need to apply lock if outdated
|
35
|
-
|
36
|
-
self.document.with_lock do
|
37
|
-
return false if self.document.document_version != self.document_version
|
38
|
-
|
39
|
-
return false unless result = ::Collab::JS.apply_commit(self.document, self.to_json, schema_name: self.document.schema_name)
|
40
|
-
|
41
|
-
self.document.document = result["doc"]
|
42
|
-
self.document.document_version = self.document_version
|
43
|
-
|
44
|
-
self.document.save!
|
45
|
-
self.save!
|
46
|
-
end
|
15
|
+
def broadcast
|
16
|
+
::Collab.config.channel.constantize.broadcast_to(document, {
|
17
|
+
"v" => document_version,
|
18
|
+
"steps" => steps,
|
19
|
+
"ref" => ref
|
20
|
+
})
|
47
21
|
end
|
48
22
|
|
49
|
-
def
|
50
|
-
|
23
|
+
def self.steps
|
24
|
+
pluck(:steps).flatten(1)
|
51
25
|
end
|
52
26
|
end
|
53
27
|
end
|
@@ -1,7 +1,11 @@
|
|
1
1
|
module Collab
|
2
2
|
class Models::Document < ::Collab::Models::Base
|
3
3
|
belongs_to :attached, polymorphic: true
|
4
|
-
|
4
|
+
|
5
|
+
with_options foreign_key: :document_id do
|
6
|
+
has_many :commits, class_name: ::Collab.config.commit_model
|
7
|
+
has_many :tracked_positions, class_name: ::Collab.config.tracked_position_model
|
8
|
+
end
|
5
9
|
|
6
10
|
validates :content, presence: true
|
7
11
|
validates :document_version, presence: true, numericality: {only_integer: true, greater_than_or_equal_to: 0}
|
@@ -24,12 +28,49 @@ module Collab
|
|
24
28
|
end
|
25
29
|
end
|
26
30
|
|
27
|
-
def
|
28
|
-
|
31
|
+
def apply_commit(data)
|
32
|
+
base_version = data["v"]&.to_i
|
33
|
+
steps = data["steps"]
|
34
|
+
|
35
|
+
return false unless base_version
|
36
|
+
return false unless steps.is_a?(Array) && !steps.empty?
|
37
|
+
|
38
|
+
self.with_lock do
|
39
|
+
return false unless self.possibly_saved_version? base_version
|
40
|
+
|
41
|
+
self.document_version += 1
|
42
|
+
|
43
|
+
original_positions = self.tracked_positions.current.distinct.pluck(:pos, :assoc).map { |(pos, assoc)| {pos: pos, assoc: assoc} }
|
44
|
+
|
45
|
+
result = ::Collab::JS.apply_commit content,
|
46
|
+
{steps: steps},
|
47
|
+
map_steps_through: self.commits.where("document_version > ?", base_version).steps,
|
48
|
+
pos: original_positions,
|
49
|
+
schema_name: schema_name
|
50
|
+
|
51
|
+
self.content = result["doc"]
|
52
|
+
|
53
|
+
commits.create!({
|
54
|
+
steps: result["steps"],
|
55
|
+
ref: data["ref"],
|
56
|
+
document_version: self.document_version
|
57
|
+
})
|
58
|
+
|
59
|
+
self.save!
|
60
|
+
|
61
|
+
original_positions.lazy.zip(result["pos"]) do |original, res|
|
62
|
+
if res["deleted"]
|
63
|
+
tracked_positions.current.where(original).update_all deleted_at_version: self.document_version
|
64
|
+
elsif original[:pos] != res["pos"]
|
65
|
+
tracked_positions.current.where(original).update_all pos: res["pos"]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
29
70
|
end
|
30
71
|
|
31
|
-
def
|
32
|
-
|
72
|
+
def from_html(html)
|
73
|
+
self.content = ::Collab::JS.html_to_document(html, schema_name: schema_name)
|
33
74
|
end
|
34
75
|
|
35
76
|
def as_json
|
@@ -41,12 +82,29 @@ module Collab
|
|
41
82
|
self.serialized_html = nil
|
42
83
|
end
|
43
84
|
|
85
|
+
def possibly_saved_version?(version)
|
86
|
+
self.document_version >= version && self.oldest_saved_commit_version <= version
|
87
|
+
end
|
88
|
+
|
89
|
+
def oldest_saved_commit_version
|
90
|
+
v = document_version - ::Collab.config.max_commit_history_length
|
91
|
+
v > 0 ? v : 0
|
92
|
+
end
|
93
|
+
|
94
|
+
def resolve_positions(*positions, **kwargs, &block)
|
95
|
+
::Collab.config.tracked_position_model.constantize.resolve(self, *positions, **kwargs, &block)
|
96
|
+
end
|
97
|
+
alias :resolve_position :resolve_positions
|
98
|
+
|
99
|
+
def resolve_selection(anchor_pos, head_pos, version:, &block)
|
100
|
+
::Collab::DocumentSelection.resolve(self, anchor_pos, head_pos, version: version, &block)
|
101
|
+
end
|
102
|
+
|
44
103
|
private
|
45
104
|
|
46
105
|
def delete_old_commits
|
47
|
-
|
48
|
-
|
49
|
-
commits.where("document_version < ?", cutoff).delete_all
|
106
|
+
return if oldest_saved_commit_version == 0
|
107
|
+
commits.where("document_version < ?", oldest_saved_commit_version).delete_all
|
50
108
|
end
|
51
109
|
end
|
52
110
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Collab
|
2
|
+
# Represents a position in the document which is tracked between commits
|
3
|
+
#
|
4
|
+
# If the position is deleted through mapping, deleted_at_version will be set, the position will
|
5
|
+
# no longer be tracked,
|
6
|
+
#
|
7
|
+
class Models::TrackedPosition < ::Collab::Models::Base
|
8
|
+
belongs_to :document, class_name: ::Collab.config.document_model
|
9
|
+
belongs_to :owner, polymorphic: true
|
10
|
+
|
11
|
+
validates :pos, presence: true, numericality: {only_integer: true, greater_than_or_equal_to: 0}
|
12
|
+
validates :assoc, presence: true, inclusion: {in: [-1, 1]}, numericality: {only_integer: true}
|
13
|
+
|
14
|
+
validates :deleted_at_version, numericality: {only_integer: true, greater_than_or_equal_to: 0}, if: :deleted_at_version
|
15
|
+
|
16
|
+
scope :current, -> { where(deleted_at_version: nil) }
|
17
|
+
|
18
|
+
# Resolves a set of positions and yields them to the block given, returning the result of the block
|
19
|
+
# The document will be locked IN SHARE MODE during resolution and the block execution
|
20
|
+
# Positions should consist of {"pos" => number, "assoc": number}
|
21
|
+
# Returns false if invalid version or any position has been deleted
|
22
|
+
def self.resolve(document, *positions, version:)
|
23
|
+
raise false unless document.possibly_saved_version? version
|
24
|
+
|
25
|
+
document.with_lock("FOR SHARE") do
|
26
|
+
unless document.document_version == version
|
27
|
+
steps = document.commits.where("document_version > ?", @mapped_to).order(document_version: :asc).pluck(:steps).flatten(1)
|
28
|
+
|
29
|
+
map_results = ::Collab::JS.map_through(steps: steps, pos: positions)["pos"]
|
30
|
+
|
31
|
+
map_results.each_with_index do |r, i|
|
32
|
+
return false if r["deleted"]
|
33
|
+
positions[i]["pos"] = r["pos"]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
positions.map! do |p|
|
38
|
+
document.tracked_positions.current.find_or_initialize_by(pos: p["pos"], assoc: p["assoc"])
|
39
|
+
end
|
40
|
+
|
41
|
+
yield(*positions)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# module Collab
|
2
|
+
# class DocumentSelection
|
3
|
+
# attr_reader :anchor, :head
|
4
|
+
# def initialize(anchor, head)
|
5
|
+
# @anchor = anchor
|
6
|
+
# @head = head
|
7
|
+
# end
|
8
|
+
|
9
|
+
# def self.resolve(document, anchor_pos, head_pos, version:)
|
10
|
+
# anchor_assoc = anchor_pos > head_pos ? -1 : 1
|
11
|
+
|
12
|
+
# document.resolve_positions(
|
13
|
+
# {"pos" => anchor_pos, "assoc" => anchor_assoc},
|
14
|
+
# {"pos" => head_pos, "assoc" => anchor_assoc * -1},
|
15
|
+
# version: version
|
16
|
+
# ) do |anchor, head|
|
17
|
+
# yield new anchor, head
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
# end
|
data/lib/collab/version.rb
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
class CollabDocumentChannel < ApplicationCable::Channel
|
2
2
|
include Collab::Channel
|
3
3
|
|
4
|
+
def commit(data)
|
5
|
+
if false # replace with your own authorization logic
|
6
|
+
raise "authorization not implemented"
|
7
|
+
end
|
8
|
+
|
9
|
+
super # make sure to call super in order to process the commit
|
10
|
+
end
|
11
|
+
|
4
12
|
private
|
5
13
|
|
6
14
|
# Find the document to subscribe to based on the params passed to the channel
|
@@ -8,15 +16,14 @@ class CollabDocumentChannel < ApplicationCable::Channel
|
|
8
16
|
def find_document
|
9
17
|
Collab::Models::Document.find(params[:document_id]).tap do |document|
|
10
18
|
# TODO: Replace with your own authorization logic
|
11
|
-
|
19
|
+
reject_unauthorized_connection
|
12
20
|
end
|
13
21
|
end
|
14
22
|
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
end
|
23
|
+
# Uncomment this line to receive the user's selection
|
24
|
+
# You must allow enable syncSelection on the client
|
25
|
+
#
|
26
|
+
# def _select(selection)
|
27
|
+
# ...
|
28
|
+
# end
|
22
29
|
end
|
@@ -24,5 +24,18 @@ class CreateCollabTables < ActiveRecord::Migration[6.0]
|
|
24
24
|
|
25
25
|
t.datetime :created_at, null: false
|
26
26
|
end
|
27
|
+
|
28
|
+
create_table :collab_tracked_positions<%= ", id: #{@primary_key_type.inspect}" if @primary_key_type %> do |t|
|
29
|
+
t.references :document, null: false, foreign_key: {to_table: :collab_documents}, index: false<%= ", type: #{@primary_key_type.inspect}" if @primary_key_type %>
|
30
|
+
t.references :owner, null: false, polymorphic: true, index: false<%= ", type: #{@primary_key_type.inspect}" if @primary_key_type %>
|
31
|
+
t.string :name, null: false
|
32
|
+
|
33
|
+
t.integer :pos, null: false
|
34
|
+
t.integer :assoc, null: false, default: 1
|
35
|
+
t.integer :deleted_at_version
|
36
|
+
|
37
|
+
t.index [:document_id, :deleted_at_version, :pos], name: "index_collab_tracked_positions_on_document_pos"
|
38
|
+
t.index [:owner_type, :name, :owner_id], name: "index_collab_tracked_positions_on_owner"
|
39
|
+
end
|
27
40
|
end
|
28
41
|
end
|
@@ -12,11 +12,6 @@ Collab.config do |c|
|
|
12
12
|
# If you change this, you must pass the value as {channel: "[ChannelName]"} in the params from the ActionCable client
|
13
13
|
c.channel = "CollabDocumentChannel"
|
14
14
|
|
15
|
-
# The class which jobs in the gem should inherit from
|
16
|
-
c.base_job = "ApplicationJob"
|
17
|
-
# The jobs to use, if you want to implement your own jobs
|
18
|
-
# c.commit_job = "..."
|
19
|
-
|
20
15
|
# The class which models in the gem should inherit from
|
21
16
|
c.base_record = "ApplicationRecord"
|
22
17
|
# The models to use, if you want to implement your own models
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: collab
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Aubin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-08-
|
11
|
+
date: 2020-08-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -44,6 +44,34 @@ dependencies:
|
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
46
|
version: '0'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: webpacker
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: puma
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
47
75
|
description:
|
48
76
|
email:
|
49
77
|
- ben@benaubin.com
|
@@ -52,16 +80,18 @@ extensions: []
|
|
52
80
|
extra_rdoc_files: []
|
53
81
|
files:
|
54
82
|
- Rakefile
|
55
|
-
- app/jobs/collab/commit_job.rb
|
56
83
|
- lib/collab.rb
|
57
84
|
- lib/collab/channel.rb
|
58
85
|
- lib/collab/config.rb
|
59
86
|
- lib/collab/engine.rb
|
60
87
|
- lib/collab/has_collaborative_document.rb
|
88
|
+
- lib/collab/has_tracked_document_positions.rb
|
61
89
|
- lib/collab/js.rb
|
62
90
|
- lib/collab/models/base.rb
|
63
91
|
- lib/collab/models/commit.rb
|
64
92
|
- lib/collab/models/document.rb
|
93
|
+
- lib/collab/models/tracked_position.rb
|
94
|
+
- lib/collab/selection.rb
|
65
95
|
- lib/collab/version.rb
|
66
96
|
- lib/generators/collab/install/install_generator.rb
|
67
97
|
- lib/generators/collab/install/templates/channel.rb
|