commenter 0.3.0 → 0.3.1
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/.rubocop.yml +4 -0
- data/CLAUDE.md +17 -7
- data/README.adoc +35 -6
- data/lib/commenter/cli.rb +10 -18
- data/lib/commenter/comment.rb +2 -10
- data/lib/commenter/comment_sheet.rb +8 -0
- data/lib/commenter/comment_type.rb +35 -0
- data/lib/commenter/github_integration.rb +11 -60
- data/lib/commenter/github_session.rb +35 -0
- data/lib/commenter/parser/osd_xlsx_parser.rb +1 -10
- data/lib/commenter/parser/track_change_docx_parser.rb +332 -0
- data/lib/commenter/parser.rb +8 -10
- data/lib/commenter/version.rb +1 -1
- data/lib/commenter.rb +5 -0
- data/spec/commenter/comment_sheet_spec.rb +25 -0
- data/spec/commenter/comment_type_spec.rb +45 -0
- data/spec/commenter/github_integration_spec.rb +65 -32
- data/spec/commenter/track_change_docx_parser_spec.rb +277 -0
- data/spec/support/redline_docx_builder.rb +88 -0
- metadata +8 -2
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
require_relative "../support/redline_docx_builder"
|
|
5
|
+
|
|
6
|
+
RSpec.describe Commenter::Parser::TrackChangeDocxParser do
|
|
7
|
+
def author = "CHEN Yvonne"
|
|
8
|
+
|
|
9
|
+
def change(kind, id, text, date: "2025-12-05T20:10:00Z")
|
|
10
|
+
{ change: kind, id: id, author: author, date: date, text: text }
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def with_redline(paragraphs, comments: [], **options)
|
|
14
|
+
file = Tempfile.new(%w[redline .docx])
|
|
15
|
+
RedlineDocxBuilder.write(file.path, paragraphs, comments: comments)
|
|
16
|
+
yield described_class.new.parse(file.path, options)
|
|
17
|
+
ensure
|
|
18
|
+
file.close
|
|
19
|
+
file.unlink
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
let(:base_paragraphs) do
|
|
23
|
+
[
|
|
24
|
+
{ change: :ins, id: "1", author: author, date: "2025-12-05T20:10:00Z", text: "ISO boilerplate" },
|
|
25
|
+
{ heading: true, level: 1, text: "4 Basic principles" },
|
|
26
|
+
{ change: :del, id: "2", author: author, date: "2025-12-05T20:11:00Z", text: "old text" },
|
|
27
|
+
{ heading: true, level: 2, text: "4.2.1Thermodynamic temperature tangent" },
|
|
28
|
+
{ marker: true, id: "9", author: author },
|
|
29
|
+
{ parts: [{ text: "Body " }, change(:ins, "3", "inserted")] },
|
|
30
|
+
{ heading: true, level: 1, text: "Annex A" },
|
|
31
|
+
{ change: :moveTo, id: "4", author: author, date: "2025-12-06T10:00:00Z", text: "moved" }
|
|
32
|
+
]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "extracts track changes in document order with rendered proposed_change" do
|
|
36
|
+
with_redline(base_paragraphs) do |sheet|
|
|
37
|
+
comments = sheet.comments
|
|
38
|
+
|
|
39
|
+
expect(comments.map(&:proposed_change)).to eq([
|
|
40
|
+
'Insert: "ISO boilerplate"',
|
|
41
|
+
'Delete: "old text"',
|
|
42
|
+
'Insert: "inserted"',
|
|
43
|
+
'Move to: "moved"'
|
|
44
|
+
])
|
|
45
|
+
expect(comments.map(&:comments)).to eq([
|
|
46
|
+
"Track change (insertion)",
|
|
47
|
+
"Track change (deletion)",
|
|
48
|
+
"Track change (insertion)",
|
|
49
|
+
"Track change (move (to))"
|
|
50
|
+
])
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "assigns the clause of the nearest preceding heading, including sub-clauses" do
|
|
55
|
+
with_redline(base_paragraphs) do |sheet|
|
|
56
|
+
expect(sheet.comments.map(&:clause)).to eq(["_whole document", "4", "4.2.1", "Annex A"])
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "skips self-closing paragraph-mark markers without corrupting later capture" do
|
|
61
|
+
with_redline(base_paragraphs) do |sheet|
|
|
62
|
+
expect(sheet.comments.length).to eq(4)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it "captures nested track changes" do
|
|
67
|
+
paragraphs = [
|
|
68
|
+
{ change: :ins, id: "1", author: author, date: "2025-12-05T20:10:00Z", text: "",
|
|
69
|
+
nested: [change(:ins, "2", "inner text")] }
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
with_redline(paragraphs) do |sheet|
|
|
73
|
+
# The inner change ends first, so it is emitted before its wrapper.
|
|
74
|
+
expect(sheet.comments.map(&:proposed_change)).to eq(['Insert: "inner text"', 'Insert: ""'])
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "builds CS-prefixed sequential IDs by default" do
|
|
79
|
+
with_redline(base_paragraphs) do |sheet|
|
|
80
|
+
expect(sheet.comments.map(&:id)).to eq(%w[CS-001 CS-002 CS-003 CS-004])
|
|
81
|
+
expect(sheet.comments.map(&:body).uniq).to eq(["CS"])
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "uses a custom body code and technical type" do
|
|
86
|
+
with_redline(base_paragraphs, body: "GB", type: "ge") do |sheet|
|
|
87
|
+
expect(sheet.comments.first.id).to eq("GB-001")
|
|
88
|
+
expect(sheet.comments.first.type).to eq("general")
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "stamps observations on every entry when given" do
|
|
93
|
+
with_redline(base_paragraphs, observations: "Accepted. ISO/CS tracked change accepted.") do |sheet|
|
|
94
|
+
expect(sheet.comments.map(&:observations).uniq)
|
|
95
|
+
.to eq(["Accepted. ISO/CS tracked change accepted."])
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "leaves observations blank by default and honours exclude_observations" do
|
|
100
|
+
with_redline(base_paragraphs) do |sheet|
|
|
101
|
+
expect(sheet.comments.first.observations).to be_nil
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
with_redline(base_paragraphs, observations: "Accepted.", exclude_observations: true) do |sheet|
|
|
105
|
+
expect(sheet.comments.first.observations).to be_nil
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "builds 2012-03 sheet metadata from the changes and options" do
|
|
110
|
+
with_redline(base_paragraphs, document: "ISO 2533:2026", stage: "DIS") do |sheet|
|
|
111
|
+
expect(sheet.version).to eq("2012-03")
|
|
112
|
+
expect(sheet.schema_name).to eq("iso_comment_2012-03.yaml")
|
|
113
|
+
expect(sheet.document).to eq("ISO 2533:2026")
|
|
114
|
+
expect(sheet.stage).to eq("DIS")
|
|
115
|
+
expect(sheet.date).to eq("2025-12-06")
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
it "is reachable through Parser dispatch with format redline" do
|
|
120
|
+
file = Tempfile.new(%w[redline .docx])
|
|
121
|
+
RedlineDocxBuilder.write(file.path, base_paragraphs)
|
|
122
|
+
|
|
123
|
+
sheet = Commenter::Parser.new.parse(file.path, format: "redline")
|
|
124
|
+
expect(sheet.comments.length).to eq(4)
|
|
125
|
+
ensure
|
|
126
|
+
file.close
|
|
127
|
+
file.unlink
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
describe "element locality" do
|
|
131
|
+
def table_paragraphs
|
|
132
|
+
[
|
|
133
|
+
{ heading: true, level: 1, text: "4 Basic principles" },
|
|
134
|
+
{ text: "Table 3 — Atmospheric properties at altitude" },
|
|
135
|
+
{ parts: [{ text: "Body " }, change(:ins, "5", "edited")] },
|
|
136
|
+
{ text: "Formula (9):" },
|
|
137
|
+
{ change: :del, id: "6", author: author, date: "2025-12-05T20:10:00Z", text: "old formula text" },
|
|
138
|
+
{ text: "NOTE 2 — This note provides clarification." },
|
|
139
|
+
{ parts: [{ text: "note body " }, change(:ins, "7", "edited")] }
|
|
140
|
+
]
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "resolves the element from caption paragraphs and carries it to following changes" do
|
|
144
|
+
with_redline(table_paragraphs) do |sheet|
|
|
145
|
+
expect(sheet.comments.map(&:element)).to eq(["Table 3", "Formula (9)", "NOTE 2"])
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "resolves inline element mentions" do
|
|
150
|
+
paragraphs = [
|
|
151
|
+
{ heading: true, level: 1, text: "5 Data tables" },
|
|
152
|
+
{ parts: [{ text: "The values in Table 5 shall be " }, change(:ins, "8", "interpreted thus")] }
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
with_redline(paragraphs) do |sheet|
|
|
156
|
+
expect(sheet.comments.first.element).to eq("Table 5")
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "resolves annex figure captions" do
|
|
161
|
+
paragraphs = [
|
|
162
|
+
{ heading: true, level: 1, text: "Annex A" },
|
|
163
|
+
{ text: "Figure A.2 — Temperature profile" },
|
|
164
|
+
{ change: :ins, id: "9", author: author, date: "2025-12-05T20:10:00Z", text: "new caption text" }
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
with_redline(paragraphs) do |sheet|
|
|
168
|
+
expect(sheet.comments.first.element).to eq("Figure A.2")
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it "resets the element when the clause changes" do
|
|
173
|
+
paragraphs = table_paragraphs + [
|
|
174
|
+
{ heading: true, level: 1, text: "5 Data tables" },
|
|
175
|
+
{ parts: [{ text: "Plain body " }, change(:ins, "10", "edited")] }
|
|
176
|
+
]
|
|
177
|
+
|
|
178
|
+
with_redline(paragraphs) do |sheet|
|
|
179
|
+
expect(sheet.comments.last.element).to be_nil
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
describe "unnumbered sub-headings" do
|
|
185
|
+
it "inherit the parent heading clause" do
|
|
186
|
+
paragraphs = [
|
|
187
|
+
{ heading: true, level: 1, text: "4 Basic principles" },
|
|
188
|
+
{ heading: true, level: 2, text: "4.2 Temperature" },
|
|
189
|
+
{ heading: true, level: 3, text: "Justification" },
|
|
190
|
+
{ parts: [{ text: "Body " }, change(:ins, "11", "edited")] }
|
|
191
|
+
]
|
|
192
|
+
|
|
193
|
+
with_redline(paragraphs) do |sheet|
|
|
194
|
+
expect(sheet.comments.first.clause).to eq("4.2")
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
describe "reviewer comment threads" do
|
|
200
|
+
let(:remark_paragraphs) do
|
|
201
|
+
[
|
|
202
|
+
{ change: :ins, id: "1", author: author, date: "2025-12-05T20:10:00Z", text: "tracked" },
|
|
203
|
+
{ heading: true, level: 1, text: "1 Scope" },
|
|
204
|
+
{ anchor: "74", text: "Values in feet." },
|
|
205
|
+
{ heading: true, level: 1, text: "2 Normative references" },
|
|
206
|
+
{ anchor: "88", text: "Introduction paragraph." }
|
|
207
|
+
]
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
let(:remarks) do
|
|
211
|
+
[
|
|
212
|
+
{ id: "74", author: author, date: "2025-12-05T20:10:00Z",
|
|
213
|
+
text: "Please provide values in km. Equivalent values in ft can be provided in brackets." },
|
|
214
|
+
{ id: "88", author: author, date: "2025-12-05T20:12:00Z",
|
|
215
|
+
text: "Remove this paragraph from the Introduction." }
|
|
216
|
+
]
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it "emits remarks after track changes with -CNNN ids and verbatim text" do
|
|
220
|
+
with_redline(remark_paragraphs, comments: remarks) do |sheet|
|
|
221
|
+
expect(sheet.comments.length).to eq(3)
|
|
222
|
+
|
|
223
|
+
remark = sheet.comments.last
|
|
224
|
+
expect(sheet.comments[1].id).to eq("CS-C001")
|
|
225
|
+
expect(remark.id).to eq("CS-C002")
|
|
226
|
+
expect(remark.comments).to eq("Remove this paragraph from the Introduction.")
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
it "rewords the remark into proposed_change" do
|
|
231
|
+
with_redline(remark_paragraphs, comments: remarks) do |sheet|
|
|
232
|
+
expect(sheet.comments[1].proposed_change)
|
|
233
|
+
.to eq("Provide values in km. Equivalent values in ft can be provided in brackets.")
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it "leaves remark observations empty for the owner to draft" do
|
|
238
|
+
with_redline(remark_paragraphs, comments: remarks) do |sheet|
|
|
239
|
+
expect(sheet.comments[1].observations).to be_nil
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it "anchors remarks to the clause of their commentRangeStart" do
|
|
244
|
+
with_redline(remark_paragraphs, comments: remarks) do |sheet|
|
|
245
|
+
expect(sheet.comments[1].clause).to eq("1")
|
|
246
|
+
expect(sheet.comments.last.clause).to eq("2")
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
it "defaults unanchored remarks to _whole document" do
|
|
251
|
+
unanchored = [{ id: "99", author: author, date: "2025-12-05T20:10:00Z", text: "General remark." }]
|
|
252
|
+
|
|
253
|
+
with_redline([{ text: "Body" }], comments: unanchored) do |sheet|
|
|
254
|
+
expect(sheet.comments.first.clause).to eq("_whole document")
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it "stamps accept_all on track changes but not on remarks" do
|
|
259
|
+
with_redline(remark_paragraphs, accept_all: true, comments: remarks) do |sheet|
|
|
260
|
+
expect(sheet.comments.first.observations).to eq("Accepted. Tracked change accepted.")
|
|
261
|
+
expect(sheet.comments[1].observations).to be_nil
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
it "prefers an explicit observations stamp over accept_all" do
|
|
266
|
+
with_redline(remark_paragraphs, accept_all: true, observations: "Custom.", comments: remarks) do |sheet|
|
|
267
|
+
expect(sheet.comments.first.observations).to eq("Custom.")
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it "handles documents without comments.xml content" do
|
|
272
|
+
with_redline([{ text: "No changes, no remarks." }]) do |sheet|
|
|
273
|
+
expect(sheet.comments).to be_empty
|
|
274
|
+
end
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "zip"
|
|
4
|
+
|
|
5
|
+
# Builds minimal redline DOCX files for specs, without binary fixtures. The
|
|
6
|
+
# document body is assembled from a paragraph DSL:
|
|
7
|
+
#
|
|
8
|
+
# { heading: "1", level: 1, text: "Scope" }
|
|
9
|
+
# { text: "Body text " }
|
|
10
|
+
# { change: :ins, id: "1", author: "CHEN Yvonne", date: "2025-12-05T20:10:00Z",
|
|
11
|
+
# text: "inserted" }
|
|
12
|
+
# { marker: true } # self-closing paragraph-mark insertion inside rPr
|
|
13
|
+
# { anchor: "74", text: "Anchored text" } # w:commentRangeStart/End around text
|
|
14
|
+
#
|
|
15
|
+
# Multiple entries in one paragraph can be given via :parts.
|
|
16
|
+
#
|
|
17
|
+
# comments: [{ id: "74", author: "CHEN Yvonne", date: "...", text: "remark" }]
|
|
18
|
+
# are written to word/comments.xml.
|
|
19
|
+
module RedlineDocxBuilder
|
|
20
|
+
W_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
|
21
|
+
private_constant :W_NS
|
|
22
|
+
|
|
23
|
+
HEADING_LEVEL_STYLE = { 1 => "Heading1", 2 => "Heading2", 3 => "Heading3" }.freeze
|
|
24
|
+
CHANGE_TAG = { ins: "w:ins", del: "w:del", moveFrom: "w:moveFrom", moveTo: "w:moveTo" }.freeze
|
|
25
|
+
private_constant :HEADING_LEVEL_STYLE, :CHANGE_TAG
|
|
26
|
+
|
|
27
|
+
def self.write(path, paragraphs, comments: [])
|
|
28
|
+
zip = Zip::File.new(path, create: true)
|
|
29
|
+
zip.get_output_stream("word/document.xml") { |stream| stream.write(document_xml(paragraphs)) }
|
|
30
|
+
zip.get_output_stream("word/comments.xml") { |stream| stream.write(comments_xml(comments)) }
|
|
31
|
+
zip.close
|
|
32
|
+
path
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def self.document_xml(paragraphs)
|
|
36
|
+
<<~XML
|
|
37
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
38
|
+
<w:document xmlns:w="#{W_NS}"><w:body>#{paragraphs.map { |p| paragraph_xml(p) }.join}</w:body></w:document>
|
|
39
|
+
XML
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.comments_xml(comments)
|
|
43
|
+
entries = comments.map do |c|
|
|
44
|
+
attrs = %(w:id="#{c[:id]}" w:author="#{c[:author]}" w:date="#{c[:date]}" w:initials="X")
|
|
45
|
+
%(<w:comment #{attrs}><w:p><w:r><w:t>#{c[:text]}</w:t></w:r></w:p></w:comment>)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
<<~XML
|
|
49
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
50
|
+
<w:comments xmlns:w="#{W_NS}">#{entries.join}</w:comments>
|
|
51
|
+
XML
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.paragraph_xml(paragraph)
|
|
55
|
+
if paragraph[:marker]
|
|
56
|
+
return %(<w:p><w:pPr><w:rPr><w:ins w:id="#{paragraph[:id]}" w:author="#{paragraph[:author]}"/></w:rPr></w:pPr></w:p>)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
inner = if paragraph[:parts]
|
|
60
|
+
paragraph[:parts].map { |part| part_xml(part) }.join
|
|
61
|
+
elsif paragraph[:heading]
|
|
62
|
+
%(<w:r><w:t>#{paragraph[:text]}</w:t></w:r>)
|
|
63
|
+
elsif paragraph[:change]
|
|
64
|
+
change_xml(paragraph)
|
|
65
|
+
else
|
|
66
|
+
%(<w:r><w:t>#{paragraph[:text]}</w:t></w:r>)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
ppr = paragraph[:heading] ? %(<w:pPr><w:pStyle w:val="#{HEADING_LEVEL_STYLE.fetch(paragraph[:level], 1)}"/></w:pPr>) : ""
|
|
70
|
+
anchor = paragraph[:anchor] ? %(<w:commentRangeStart w:id="#{paragraph[:anchor]}"/>) : ""
|
|
71
|
+
anchor_end = paragraph[:anchor] ? %(<w:commentRangeEnd w:id="#{paragraph[:anchor]}"/>) : ""
|
|
72
|
+
"<w:p>#{ppr}#{anchor}#{inner}#{anchor_end}</w:p>"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.part_xml(part)
|
|
76
|
+
part[:change] ? change_xml(part) : %(<w:r><w:t>#{part[:text]}</w:t></w:r>)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def self.change_xml(change)
|
|
80
|
+
tag = CHANGE_TAG.fetch(change[:change])
|
|
81
|
+
attrs = %(w:id="#{change[:id]}" w:author="#{change[:author]}" w:date="#{change[:date]}")
|
|
82
|
+
|
|
83
|
+
return %(<#{tag} #{attrs}>#{change[:nested].map { |child| change_xml(child) }.join}</#{tag}>) if change[:nested]
|
|
84
|
+
|
|
85
|
+
text_tag = change[:change] == :del ? "w:delText" : "w:t"
|
|
86
|
+
%(<#{tag} #{attrs}><w:r><#{text_tag}>#{change[:text]}</#{text_tag}></w:r></#{tag}>)
|
|
87
|
+
end
|
|
88
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: commenter
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: base64
|
|
@@ -139,10 +139,13 @@ files:
|
|
|
139
139
|
- lib/commenter/cli.rb
|
|
140
140
|
- lib/commenter/comment.rb
|
|
141
141
|
- lib/commenter/comment_sheet.rb
|
|
142
|
+
- lib/commenter/comment_type.rb
|
|
142
143
|
- lib/commenter/filler.rb
|
|
143
144
|
- lib/commenter/github_integration.rb
|
|
145
|
+
- lib/commenter/github_session.rb
|
|
144
146
|
- lib/commenter/parser.rb
|
|
145
147
|
- lib/commenter/parser/osd_xlsx_parser.rb
|
|
148
|
+
- lib/commenter/parser/track_change_docx_parser.rb
|
|
146
149
|
- lib/commenter/version.rb
|
|
147
150
|
- schema/iso_comment_2012-03.yaml
|
|
148
151
|
- schema/iso_comment_osd.yaml
|
|
@@ -150,11 +153,14 @@ files:
|
|
|
150
153
|
- spec/commenter/cli_spec.rb
|
|
151
154
|
- spec/commenter/comment_sheet_spec.rb
|
|
152
155
|
- spec/commenter/comment_spec.rb
|
|
156
|
+
- spec/commenter/comment_type_spec.rb
|
|
153
157
|
- spec/commenter/github_integration_spec.rb
|
|
154
158
|
- spec/commenter/osd_xlsx_parser_spec.rb
|
|
159
|
+
- spec/commenter/track_change_docx_parser_spec.rb
|
|
155
160
|
- spec/commenter_spec.rb
|
|
156
161
|
- spec/spec_helper.rb
|
|
157
162
|
- spec/support/osd_fixtures.rb
|
|
163
|
+
- spec/support/redline_docx_builder.rb
|
|
158
164
|
- spec/support/xlsx_builder.rb
|
|
159
165
|
homepage: https://github.com/metanorma/commenter
|
|
160
166
|
licenses:
|