commenter 0.2.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 +7 -0
- data/.github/workflows/rake.yml +15 -0
- data/.github/workflows/release.yml +25 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +8 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/Gemfile +12 -0
- data/README.adoc +284 -0
- data/Rakefile +12 -0
- data/commenter.gemspec +35 -0
- data/comments.yaml +687 -0
- data/data/iso_comment_template_2012-03.docx +0 -0
- data/exe/commenter +7 -0
- data/lib/commenter/cli.rb +82 -0
- data/lib/commenter/comment.rb +89 -0
- data/lib/commenter/comment_sheet.rb +71 -0
- data/lib/commenter/filler.rb +107 -0
- data/lib/commenter/parser.rb +101 -0
- data/lib/commenter/version.rb +5 -0
- data/lib/commenter.rb +11 -0
- data/schema/iso_comment_2012-03.yaml +69 -0
- data/sig/commenter.rbs +4 -0
- data/spec/commenter_spec.rb +8 -0
- data/spec/spec_helper.rb +15 -0
- metadata +100 -0
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
require "yaml"
|
5
|
+
require "fileutils"
|
6
|
+
require "commenter/parser"
|
7
|
+
require "commenter/filler"
|
8
|
+
|
9
|
+
module Commenter
|
10
|
+
class CLI < Thor
|
11
|
+
desc "import INPUT.docx", "Convert DOCX comment sheet to YAML"
|
12
|
+
option :output, type: :string, aliases: :o, default: "comments.yaml", desc: "Output YAML file"
|
13
|
+
option :exclude_observations, type: :boolean, aliases: :e, desc: "Exclude observations column"
|
14
|
+
option :schema_dir, type: :string, default: "schema", desc: "Directory for schema file"
|
15
|
+
def import(input_docx)
|
16
|
+
output_yaml = options[:output]
|
17
|
+
schema_dir = options[:schema_dir]
|
18
|
+
|
19
|
+
# Ensure schema directory exists
|
20
|
+
FileUtils.mkdir_p(schema_dir) unless Dir.exist?(schema_dir)
|
21
|
+
|
22
|
+
# Parse the DOCX file
|
23
|
+
parser = Parser.new
|
24
|
+
comment_sheet = parser.parse(input_docx, options)
|
25
|
+
|
26
|
+
# Write the YAML data file with schema reference
|
27
|
+
yaml_content = generate_yaml_with_header(comment_sheet.to_yaml_h, schema_dir)
|
28
|
+
File.write(output_yaml, yaml_content)
|
29
|
+
|
30
|
+
# Copy schema file to output directory
|
31
|
+
schema_source = File.join(__dir__, "../../schema/iso_comment_2012-03.yaml")
|
32
|
+
schema_target = File.join(schema_dir, "iso_comment_2012-03.yaml")
|
33
|
+
|
34
|
+
# Only copy if source and target are different
|
35
|
+
unless File.expand_path(schema_source) == File.expand_path(schema_target)
|
36
|
+
FileUtils.cp(schema_source, schema_target)
|
37
|
+
end
|
38
|
+
|
39
|
+
puts "Converted #{input_docx} to #{output_yaml}"
|
40
|
+
puts "Schema file created at #{schema_target}"
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "fill INPUT.yaml", "Fill DOCX template from YAML comments"
|
44
|
+
option :output, type: :string, aliases: :o, default: "filled_comments.docx", desc: "Output DOCX file"
|
45
|
+
option :template, type: :string, aliases: :t, desc: "Custom template file"
|
46
|
+
option :shading, type: :boolean, aliases: :s, desc: "Apply status-based shading"
|
47
|
+
def fill(input_yaml)
|
48
|
+
output_docx = options[:output]
|
49
|
+
|
50
|
+
# Load YAML data
|
51
|
+
data = YAML.load_file(input_yaml)
|
52
|
+
|
53
|
+
# Extract comments from the structure
|
54
|
+
comments = if data.is_a?(Hash)
|
55
|
+
data["comments"] || data[:comments] || []
|
56
|
+
else
|
57
|
+
data || []
|
58
|
+
end
|
59
|
+
|
60
|
+
raise "No comments found in YAML file" if comments.empty?
|
61
|
+
|
62
|
+
# Use default template if none specified
|
63
|
+
template_path = options[:template] || File.join(__dir__, "../../data/iso_comment_template_2012-03.docx")
|
64
|
+
|
65
|
+
# Fill the template
|
66
|
+
Filler.new.fill(template_path, output_docx, comments, options)
|
67
|
+
puts "Filled template to #{output_docx}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.exit_on_failure?
|
71
|
+
true
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def generate_yaml_with_header(data, schema_dir)
|
77
|
+
schema_path = File.join(schema_dir, "iso_comment_2012-03.yaml")
|
78
|
+
header = "# yaml-language-server: $schema=#{schema_path}\n\n"
|
79
|
+
header + data.to_yaml
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Commenter
|
4
|
+
class Comment
|
5
|
+
attr_accessor :id, :body, :locality, :type, :comments, :proposed_change, :observations
|
6
|
+
|
7
|
+
def initialize(attributes = {})
|
8
|
+
# Normalize input to symbols
|
9
|
+
attrs = symbolize_keys(attributes)
|
10
|
+
|
11
|
+
@id = attrs[:id]
|
12
|
+
@body = attrs[:body]
|
13
|
+
@locality = symbolize_keys(attrs[:locality] || {})
|
14
|
+
@type = attrs[:type]
|
15
|
+
@comments = attrs[:comments]
|
16
|
+
@proposed_change = attrs[:proposed_change]
|
17
|
+
@observations = attrs[:observations]
|
18
|
+
end
|
19
|
+
|
20
|
+
def line_number
|
21
|
+
@locality[:line_number]
|
22
|
+
end
|
23
|
+
|
24
|
+
def line_number=(value)
|
25
|
+
@locality[:line_number] = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def clause
|
29
|
+
@locality[:clause]
|
30
|
+
end
|
31
|
+
|
32
|
+
def clause=(value)
|
33
|
+
@locality[:clause] = value
|
34
|
+
end
|
35
|
+
|
36
|
+
def element
|
37
|
+
@locality[:element]
|
38
|
+
end
|
39
|
+
|
40
|
+
def element=(value)
|
41
|
+
@locality[:element] = value
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_h
|
45
|
+
{
|
46
|
+
id: @id,
|
47
|
+
body: @body,
|
48
|
+
locality: @locality,
|
49
|
+
type: @type,
|
50
|
+
comments: @comments,
|
51
|
+
proposed_change: @proposed_change,
|
52
|
+
observations: @observations
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_yaml_h
|
57
|
+
hash = to_h
|
58
|
+
# Remove observations if it's nil or empty
|
59
|
+
hash.delete(:observations) if hash[:observations].nil? || hash[:observations] == ""
|
60
|
+
stringify_keys(hash)
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.from_hash(hash)
|
64
|
+
new(hash)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def symbolize_keys(hash)
|
70
|
+
return hash unless hash.is_a?(Hash)
|
71
|
+
|
72
|
+
hash.each_with_object({}) do |(key, value), result|
|
73
|
+
new_key = key.to_sym
|
74
|
+
new_value = value.is_a?(Hash) ? symbolize_keys(value) : value
|
75
|
+
result[new_key] = new_value
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def stringify_keys(hash)
|
80
|
+
return hash unless hash.is_a?(Hash)
|
81
|
+
|
82
|
+
hash.each_with_object({}) do |(key, value), result|
|
83
|
+
new_key = key.to_s
|
84
|
+
new_value = value.is_a?(Hash) ? stringify_keys(value) : value
|
85
|
+
result[new_key] = new_value
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "comment"
|
4
|
+
|
5
|
+
module Commenter
|
6
|
+
class CommentSheet
|
7
|
+
attr_accessor :version, :date, :document, :project, :comments
|
8
|
+
|
9
|
+
def initialize(attributes = {})
|
10
|
+
# Normalize input to symbols
|
11
|
+
attrs = symbolize_keys(attributes)
|
12
|
+
|
13
|
+
@version = attrs[:version] || "2012-03"
|
14
|
+
@date = attrs[:date]
|
15
|
+
@document = attrs[:document]
|
16
|
+
@project = attrs[:project]
|
17
|
+
@comments = (attrs[:comments] || []).map { |c| c.is_a?(Comment) ? c : Comment.from_hash(c) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_comment(comment)
|
21
|
+
@comments << (comment.is_a?(Comment) ? comment : Comment.from_hash(comment))
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_h
|
25
|
+
{
|
26
|
+
version: @version,
|
27
|
+
date: @date,
|
28
|
+
document: @document,
|
29
|
+
project: @project,
|
30
|
+
comments: @comments.map(&:to_h)
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_yaml_h
|
35
|
+
stringify_keys(to_h.merge(comments: @comments.map(&:to_yaml_h)))
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.from_hash(hash)
|
39
|
+
new(hash)
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def symbolize_keys(hash)
|
45
|
+
return hash unless hash.is_a?(Hash)
|
46
|
+
|
47
|
+
hash.each_with_object({}) do |(key, value), result|
|
48
|
+
new_key = key.to_sym
|
49
|
+
new_value = value.is_a?(Hash) ? symbolize_keys(value) : value
|
50
|
+
result[new_key] = new_value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def stringify_keys(hash)
|
55
|
+
return hash unless hash.is_a?(Hash)
|
56
|
+
|
57
|
+
hash.each_with_object({}) do |(key, value), result|
|
58
|
+
new_key = key.to_s
|
59
|
+
new_value = case value
|
60
|
+
when Hash
|
61
|
+
stringify_keys(value)
|
62
|
+
when Array
|
63
|
+
value.map { |item| item.is_a?(Hash) ? stringify_keys(item) : item }
|
64
|
+
else
|
65
|
+
value
|
66
|
+
end
|
67
|
+
result[new_key] = new_value
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "docx"
|
4
|
+
|
5
|
+
module Commenter
|
6
|
+
class Filler
|
7
|
+
def fill(template_path, output_path, comments, options = {})
|
8
|
+
doc = Docx::Document.open(template_path)
|
9
|
+
table = doc.tables.first
|
10
|
+
|
11
|
+
raise "No table found in template" unless table
|
12
|
+
raise "Template table must have at least one row" if table.row_count < 1
|
13
|
+
|
14
|
+
# Get the template row (first row in the table)
|
15
|
+
template_row = table.rows.first
|
16
|
+
|
17
|
+
# Add new rows for each comment by copying the template row
|
18
|
+
comments.each_with_index do |comment, index|
|
19
|
+
# Convert comment to symbol keys for consistent access
|
20
|
+
comment_data = symbolize_keys(comment)
|
21
|
+
|
22
|
+
# Copy the template row and insert it
|
23
|
+
begin
|
24
|
+
new_row = template_row.copy
|
25
|
+
new_row.insert_before(template_row)
|
26
|
+
row = new_row
|
27
|
+
rescue => e
|
28
|
+
puts "Warning: Could not add row for comment #{comment_data[:id]}: #{e.message}"
|
29
|
+
next
|
30
|
+
end
|
31
|
+
|
32
|
+
# Map comment to table cells using text substitution
|
33
|
+
set_cell_text(row.cells[0], comment_data[:id] || "")
|
34
|
+
set_cell_text(row.cells[1], comment_data.dig(:locality, :line_number) || "")
|
35
|
+
set_cell_text(row.cells[2], comment_data.dig(:locality, :clause) || "")
|
36
|
+
set_cell_text(row.cells[3], comment_data.dig(:locality, :element) || "")
|
37
|
+
set_cell_text(row.cells[4], comment_data[:type] || "")
|
38
|
+
set_cell_text(row.cells[5], comment_data[:comments] || "")
|
39
|
+
set_cell_text(row.cells[6], comment_data[:proposed_change] || "")
|
40
|
+
|
41
|
+
# Handle observations with optional shading
|
42
|
+
observations = comment_data[:observations]
|
43
|
+
if observations && !observations.empty?
|
44
|
+
set_cell_text(row.cells[7], observations)
|
45
|
+
apply_shading(row.cells[7], observations) if options[:shading]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Remove the original template row after all comments are added
|
50
|
+
template_row.remove if template_row.respond_to?(:remove)
|
51
|
+
|
52
|
+
doc.save(output_path)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def set_cell_text(cell, text)
|
58
|
+
return if text.nil? || text.empty?
|
59
|
+
|
60
|
+
# Handle both empty cells and cells with existing text
|
61
|
+
text_set = false
|
62
|
+
|
63
|
+
cell.paragraphs.each do |paragraph|
|
64
|
+
paragraph.each_text_run do |text_run|
|
65
|
+
# Get current text and substitute it with new text
|
66
|
+
current_text = text_run.text
|
67
|
+
if current_text && !current_text.empty?
|
68
|
+
text_run.substitute(current_text, text)
|
69
|
+
text_set = true
|
70
|
+
return # Only substitute in the first text run found
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# If no text runs with content were found, add text to the first paragraph
|
76
|
+
unless text_set
|
77
|
+
if cell.paragraphs.any?
|
78
|
+
paragraph = cell.paragraphs.first
|
79
|
+
# Try to add a text run to the paragraph
|
80
|
+
if paragraph.respond_to?(:add_text)
|
81
|
+
paragraph.add_text(text)
|
82
|
+
elsif paragraph.respond_to?(:text=)
|
83
|
+
paragraph.text = text
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
rescue => e
|
88
|
+
puts "Warning: Could not set text '#{text}' in cell: #{e.message}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def symbolize_keys(hash)
|
92
|
+
return hash unless hash.is_a?(Hash)
|
93
|
+
|
94
|
+
hash.each_with_object({}) do |(key, value), result|
|
95
|
+
new_key = key.to_sym
|
96
|
+
new_value = value.is_a?(Hash) ? symbolize_keys(value) : value
|
97
|
+
result[new_key] = new_value
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def apply_shading(cell, observation)
|
102
|
+
# Shading functionality is not fully supported by the docx gem
|
103
|
+
# This is a placeholder for future implementation
|
104
|
+
puts "Shading requested for: #{observation}" if observation
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "docx"
|
4
|
+
require_relative "comment_sheet"
|
5
|
+
require_relative "comment"
|
6
|
+
|
7
|
+
module Commenter
|
8
|
+
class Parser
|
9
|
+
def parse(docx_path, options = {})
|
10
|
+
doc = Docx::Document.open(docx_path)
|
11
|
+
|
12
|
+
# Extract metadata from the first table
|
13
|
+
metadata = extract_metadata(doc)
|
14
|
+
|
15
|
+
# The comments are in the second table (or first table if there's only one)
|
16
|
+
comments_table = doc.tables.length > 1 ? doc.tables[1] : doc.tables.first
|
17
|
+
raise "No comments table found in document" unless comments_table
|
18
|
+
raise "Comments table appears to be empty" if comments_table.row_count < 2
|
19
|
+
|
20
|
+
comments = []
|
21
|
+
|
22
|
+
# Process all rows - don't skip any rows, respect all content
|
23
|
+
(0..comments_table.row_count - 1).each do |i|
|
24
|
+
row = comments_table.rows[i]
|
25
|
+
cells = row.cells.map { |c| c.text.strip }
|
26
|
+
|
27
|
+
# Skip only completely empty rows
|
28
|
+
next if cells.all?(&:empty?)
|
29
|
+
|
30
|
+
# Extract body from ID (e.g., "DE-001" -> "DE")
|
31
|
+
id = cells[0] || ""
|
32
|
+
body = id.include?("-") ? id.split("-").first : id
|
33
|
+
|
34
|
+
# Create comment with symbol keys, respecting all input data
|
35
|
+
comment_attrs = {
|
36
|
+
id: id,
|
37
|
+
body: body,
|
38
|
+
locality: {
|
39
|
+
line_number: cells[1]&.empty? ? nil : cells[1],
|
40
|
+
clause: cells[2]&.empty? ? nil : cells[2],
|
41
|
+
element: cells[3]&.empty? ? nil : cells[3]
|
42
|
+
},
|
43
|
+
type: cells[4] || "",
|
44
|
+
comments: cells[5] || "",
|
45
|
+
proposed_change: cells[6] || ""
|
46
|
+
}
|
47
|
+
|
48
|
+
# Handle observations column
|
49
|
+
unless options[:exclude_observations]
|
50
|
+
comment_attrs[:observations] = cells[7]&.empty? ? nil : cells[7]
|
51
|
+
end
|
52
|
+
|
53
|
+
comments << Comment.new(comment_attrs)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Create comment sheet
|
57
|
+
CommentSheet.new(
|
58
|
+
version: "2012-03",
|
59
|
+
date: metadata[:date],
|
60
|
+
document: metadata[:document],
|
61
|
+
project: metadata[:project],
|
62
|
+
comments: comments
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def extract_metadata(doc)
|
69
|
+
metadata = { date: nil, document: nil, project: nil }
|
70
|
+
|
71
|
+
# Try to extract metadata from document properties first
|
72
|
+
begin
|
73
|
+
if doc.respond_to?(:created) && doc.created
|
74
|
+
metadata[:date] = doc.created.strftime("%Y-%m-%d") rescue nil
|
75
|
+
end
|
76
|
+
rescue => e
|
77
|
+
# Ignore errors accessing document properties
|
78
|
+
end
|
79
|
+
|
80
|
+
# Search for metadata in the document text
|
81
|
+
all_text = doc.to_s
|
82
|
+
|
83
|
+
# Look for date patterns
|
84
|
+
date_match = all_text.match(/Date:\s*([0-9]{4}-[0-9]{2}-[0-9]{2})/)
|
85
|
+
metadata[:date] = date_match[1] if date_match
|
86
|
+
|
87
|
+
# Look for document patterns
|
88
|
+
doc_match = all_text.match(/Document:\s*(ISO\s+[0-9\-:]+)/)
|
89
|
+
metadata[:document] = doc_match[1] if doc_match
|
90
|
+
|
91
|
+
# Look for project patterns
|
92
|
+
project_match = all_text.match(/Project:\s*([^\n\r]+)/)
|
93
|
+
metadata[:project] = project_match[1]&.strip if project_match
|
94
|
+
|
95
|
+
# If no metadata found, try to extract from filename or other sources
|
96
|
+
# This is a fallback - in practice, users might need to provide metadata manually
|
97
|
+
|
98
|
+
metadata
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/commenter.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "commenter/version"
|
4
|
+
require_relative "commenter/comment"
|
5
|
+
require_relative "commenter/comment_sheet"
|
6
|
+
require_relative "commenter/parser"
|
7
|
+
require_relative "commenter/filler"
|
8
|
+
|
9
|
+
module Commenter
|
10
|
+
class Error < StandardError; end
|
11
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# ISO Comment Template 2012-03 Schema
|
2
|
+
# Template: "ISO/IEC/CEN/CENELEC electronic balloting commenting template/version 2012-03"
|
3
|
+
$schema: http://json-schema.org/draft-07/schema#
|
4
|
+
title: ISO Comment 2012-03
|
5
|
+
description: Schema for ISO comment sheets following the 2012-03 template format
|
6
|
+
type: object
|
7
|
+
properties:
|
8
|
+
version:
|
9
|
+
type: string
|
10
|
+
const: "2012-03"
|
11
|
+
description: Version of the ISO commenting template
|
12
|
+
comments:
|
13
|
+
type: array
|
14
|
+
description: Array of comment entries from the ISO comment sheet
|
15
|
+
items:
|
16
|
+
type: object
|
17
|
+
properties:
|
18
|
+
id:
|
19
|
+
type: string
|
20
|
+
pattern: "^[A-Z*]{2,3}-\\d{2,3}(-\\d{3})?$"
|
21
|
+
description: "Comment ID in format: {MB/NC}-{number} or {MB/NC}-{org_id}-{seq_id}"
|
22
|
+
examples:
|
23
|
+
- "US-001"
|
24
|
+
- "DE-01-002"
|
25
|
+
- "**-001"
|
26
|
+
body:
|
27
|
+
type: string
|
28
|
+
description: "Member body or National committee abbreviation (extracted from ID)"
|
29
|
+
examples:
|
30
|
+
- "US"
|
31
|
+
- "DE"
|
32
|
+
- "**"
|
33
|
+
locality:
|
34
|
+
type: object
|
35
|
+
description: "Location information for the comment"
|
36
|
+
properties:
|
37
|
+
line_number:
|
38
|
+
type: ["string", "null"]
|
39
|
+
description: "Line number reference"
|
40
|
+
clause:
|
41
|
+
type: string
|
42
|
+
description: "Clause/subclause reference"
|
43
|
+
examples:
|
44
|
+
- "_whole document"
|
45
|
+
- "5"
|
46
|
+
- "4.2.1"
|
47
|
+
element:
|
48
|
+
type: ["string", "null"]
|
49
|
+
description: "Paragraph/Figure/Table reference"
|
50
|
+
examples:
|
51
|
+
- "2-5.7, 4th column"
|
52
|
+
- "Table 1"
|
53
|
+
- "Figure 3"
|
54
|
+
required: ["clause"]
|
55
|
+
type:
|
56
|
+
type: string
|
57
|
+
enum: ["ge", "te", "ed"]
|
58
|
+
description: "Type of comment: ge=general, te=technical, ed=editorial"
|
59
|
+
comments:
|
60
|
+
type: string
|
61
|
+
description: "The actual comment text"
|
62
|
+
proposed_change:
|
63
|
+
type: string
|
64
|
+
description: "Proposed change or solution"
|
65
|
+
observations:
|
66
|
+
type: ["string", "null"]
|
67
|
+
description: "Observations of the Secretariat (optional)"
|
68
|
+
required: ["id", "body", "locality", "type", "comments", "proposed_change"]
|
69
|
+
required: ["version", "comments"]
|
data/sig/commenter.rbs
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "commenter"
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
# Enable flags like --only-failures and --next-failure
|
7
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
8
|
+
|
9
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
10
|
+
config.disable_monkey_patching!
|
11
|
+
|
12
|
+
config.expect_with :rspec do |c|
|
13
|
+
c.syntax = :expect
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: commenter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ribose
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-06-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: docx
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
description: Convert between ISO comment sheet DOCX and structured YAML with schema
|
42
|
+
validation.
|
43
|
+
email:
|
44
|
+
- open.source@ribose.com
|
45
|
+
executables:
|
46
|
+
- commenter
|
47
|
+
extensions: []
|
48
|
+
extra_rdoc_files: []
|
49
|
+
files:
|
50
|
+
- ".github/workflows/rake.yml"
|
51
|
+
- ".github/workflows/release.yml"
|
52
|
+
- ".gitignore"
|
53
|
+
- ".rspec"
|
54
|
+
- ".rubocop.yml"
|
55
|
+
- CODE_OF_CONDUCT.md
|
56
|
+
- Gemfile
|
57
|
+
- README.adoc
|
58
|
+
- Rakefile
|
59
|
+
- commenter.gemspec
|
60
|
+
- comments.yaml
|
61
|
+
- data/iso_comment_template_2012-03.docx
|
62
|
+
- exe/commenter
|
63
|
+
- lib/commenter.rb
|
64
|
+
- lib/commenter/cli.rb
|
65
|
+
- lib/commenter/comment.rb
|
66
|
+
- lib/commenter/comment_sheet.rb
|
67
|
+
- lib/commenter/filler.rb
|
68
|
+
- lib/commenter/parser.rb
|
69
|
+
- lib/commenter/version.rb
|
70
|
+
- schema/iso_comment_2012-03.yaml
|
71
|
+
- sig/commenter.rbs
|
72
|
+
- spec/commenter_spec.rb
|
73
|
+
- spec/spec_helper.rb
|
74
|
+
homepage: https://github.com/metanorma/commenter
|
75
|
+
licenses:
|
76
|
+
- BSD-2-Clause
|
77
|
+
metadata:
|
78
|
+
homepage_uri: https://github.com/metanorma/commenter
|
79
|
+
source_code_uri: https://github.com/metanorma/commenter
|
80
|
+
bug_tracker_uri: https://github.com/metanorma/commenter/issues
|
81
|
+
post_install_message:
|
82
|
+
rdoc_options: []
|
83
|
+
require_paths:
|
84
|
+
- lib
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 2.6.0
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
requirements: []
|
96
|
+
rubygems_version: 3.5.22
|
97
|
+
signing_key:
|
98
|
+
specification_version: 4
|
99
|
+
summary: Library to work with ISO comment sheets in DOCX format.
|
100
|
+
test_files: []
|