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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1609bb9eed80e408daebc9c67cda2c657e8484186acce89b823e6b411a5f9ea5
|
|
4
|
+
data.tar.gz: 46316674e2c639b9256390385d2cb3c59ed8946b604b44fbb0be28728475cd38
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 887aa19ab8ca3559fd20caf3e19a9941b631c677faeda86553597671883fc8dbae8c1e1f6d83bd0014e036774743addc16bc538b7404f6939be6636e1d623704
|
|
7
|
+
data.tar.gz: 3b850d0872f2f572b599d0bf7a70a977e1e5e7e797f5fb3447905c09cc7578cff18d99de6b32ae3b539758b7319b07590fdfd9d5249f74024ffdcd842d48d09d
|
data/.rubocop.yml
CHANGED
data/CLAUDE.md
CHANGED
|
@@ -18,13 +18,23 @@ bin/console # interactive prompt
|
|
|
18
18
|
|
|
19
19
|
CI (metanorma/ci `generic-rake.yml`) runs `bundle exec rake` on Ruby 3.2/3.4/4.0 across macOS/Ubuntu/Windows. RuboCop offenses fail CI — run `bundle exec rake`, not just rspec, before pushing. `Gemfile.lock` is gitignored; dependencies resolve fresh in CI.
|
|
20
20
|
|
|
21
|
-
Specs generate XLSX fixtures at runtime via `spec/support/xlsx_builder.rb` (plain rubyzip, no spreadsheet-writing dependency) plus row data in `spec/support/osd_fixtures.rb` — there are no binary fixture files in the repo.
|
|
21
|
+
Specs generate XLSX fixtures at runtime via `spec/support/xlsx_builder.rb` (plain rubyzip, no spreadsheet-writing dependency) plus row data in `spec/support/osd_fixtures.rb` — there are no binary fixture files in the repo. Redline DOCX fixtures are built at runtime via `spec/support/redline_docx_builder.rb` (same approach).
|
|
22
|
+
|
|
23
|
+
## Release
|
|
24
|
+
|
|
25
|
+
NEVER bump `lib/commenter/version.rb` by hand and never push tags. Releases go through the GHA workflow, which does the version bump, `v*` tag, and gem push itself:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
gh workflow run release.yml --ref main -f next_version=X.Y.Z
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The version number is the maintainer's decision — ask, never infer it from semver reasoning. PRs are rebase-merged.
|
|
22
32
|
|
|
23
33
|
## What this gem does
|
|
24
34
|
|
|
25
35
|
Converts ISO comment sheets to structured YAML and back, and syncs comments to GitHub issues:
|
|
26
36
|
|
|
27
|
-
- **Import**: DOCX (ISO 2012-03 balloting template) or XLSX (ISO Online Standards Development exports) → YAML + schema file. Format auto-detected from extension.
|
|
37
|
+
- **Import**: DOCX (ISO 2012-03 balloting template) or XLSX (ISO Online Standards Development exports) → YAML + schema file. Format auto-detected from extension. Redline DOCX with tracked changes is dispatched to `Parser::TrackChangeDocxParser` via `--format redline`.
|
|
28
38
|
- **Fill**: YAML → filled DOCX comment sheet (`data/iso_comment_template_2012-03.docx`), optional status-based cell shading.
|
|
29
39
|
- **GitHub round-trip**: `github-create` makes issues from YAML via Liquid templates; `github-retrieve` pulls `> **OBSERVATION:**` blockquotes from closed issues back into the YAML's observations field.
|
|
30
40
|
|
|
@@ -34,11 +44,12 @@ Plain text only — formulas/images/complex formatting are unsupported (docx gem
|
|
|
34
44
|
|
|
35
45
|
Core flow: `Parser` → `CommentSheet` (metadata + `Comment` objects) → YAML / DOCX / GitHub issues.
|
|
36
46
|
|
|
37
|
-
- `Commenter::Comment` / `Commenter::CommentSheet` — data model. `Comment` carries the common fields plus optional OSD-specific fields (`user_name`, `resolution_status`, `motivation`, etc.) and a `github` sub-hash tracking issue state. The sheet's `version` field (`"2012-03"` vs `"osd"`) selects the output schema.
|
|
38
|
-
- `Commenter::Parser` — dispatches by format: `.docx` parsed inline with the `docx` gem; `.xlsx` delegated to `Parser::OsdXlsxParser` (uses `roo`)
|
|
47
|
+
- `Commenter::Comment` / `Commenter::CommentSheet` — data model. `Comment` carries the common fields plus optional OSD-specific fields (`user_name`, `resolution_status`, `motivation`, etc.) and a `github` sub-hash tracking issue state. Comment types: short codes (`ge`/`te`/`ed`) are expanded to full names (`general`/`technical`/`editorial`) when a `Comment` is loaded; YAML output stores the expanded form. The sheet's `version` field (`"2012-03"` vs `"osd"`) selects the output schema.
|
|
48
|
+
- `Commenter::Parser` — dispatches by format: `.docx` parsed inline with the `docx` gem; `.xlsx` delegated to `Parser::OsdXlsxParser` (uses `roo`); `redline` delegated to `Parser::TrackChangeDocxParser`.
|
|
39
49
|
- `Parser::OsdXlsxParser` — auto-detects two OSD export variants by header row ("resolved" 17-col starting `Comment ID`; "unresolved" 15-col starting `User name`), extracts metadata (date/reference/stage/titles) from header rows 1–2, maps columns by header name into `Comment` attributes, and synthesizes `observations` from `resolution_status` + `motivation`.
|
|
40
|
-
- `
|
|
41
|
-
- `Commenter::
|
|
50
|
+
- `Parser::TrackChangeDocxParser` — redline DOCX import: streams `word/document.xml` with Nokogiri XML::Reader (redlines can exceed 100 MB), captures `w:ins`/`w:del`/`w:moveFrom`/`w:moveTo` as comment entries (`proposed_change` renders the change itself, e.g. `Insert: "text"`; clause resolved from the nearest preceding heading including sub-clauses; element resolved from Table/Figure/Formula/NOTE references in the same clause; self-closing paragraph-mark markers skipped), plus reviewer `w:comment` threads as `-CNNN` remark entries (remark verbatim in `comments`, instruction reworded in `proposed_change`, empty `observations` for the owner). Stamps `observations` from the `observations`/`accept_all` options.
|
|
51
|
+
- `Commenter::Filler` — writes comments into the DOCX template table; maps observation status text (`accept(ed)?`, `noted`, `reject(ed)?`, …) to shading colors.
|
|
52
|
+
- GitHub integration (`lib/commenter/github_integration.rb`) — two classes with parallel structure: `GitHubIssueCreator` (`github-create`) and `GitHubIssueRetriever` (`github-retrieve`). Each loads its own config YAML and Octokit client, and rewrites the comments YAML in place after the run. Duplicate detection searches issue titles for a unique ID rendered from a configurable Liquid `unique_id` template (stage-aware by default: `[DIS] GB-001`), so the same comment ID at different ballot stages creates separate issues.
|
|
42
53
|
- `Commenter::Cli` (`lib/commenter/cli.rb`) — Thor CLI with subcommands `import`, `fill`, `github-create`, `github-retrieve`.
|
|
43
54
|
|
|
44
55
|
### Schemas
|
|
@@ -55,4 +66,3 @@ Core flow: `Parser` → `CommentSheet` (metadata + `Comment` objects) → YAML /
|
|
|
55
66
|
- `data/` files (DOCX template, Liquid templates, sample config) are shipped with the gem and loaded relative to `__dir__` — do not treat them as disposable.
|
|
56
67
|
- Testing GitHub integration: use `--dry-run` with `GITHUB_TOKEN=dummy_token` — exercises template rendering without API calls.
|
|
57
68
|
- `sig/commenter.rbs` is a minimal stub; RBS coverage is not currently maintained.
|
|
58
|
-
- Release: pushing a `v*` tag triggers `.github/workflows/release.yml`. Version lives in `lib/commenter/version.rb`.
|
data/README.adoc
CHANGED
|
@@ -19,6 +19,8 @@ The supported input formats are:
|
|
|
19
19
|
(DOCX)
|
|
20
20
|
* ISO Online Standards Development (OSD) XLSX exports (resolved and unresolved
|
|
21
21
|
comment sheets)
|
|
22
|
+
* Redlined Word documents containing tracked changes (e.g. ISO/CS editor
|
|
23
|
+
redlines), imported with `--format redline`
|
|
22
24
|
|
|
23
25
|
This gem only supports plain text comment extraction and filling. Only use this
|
|
24
26
|
to handle plain text comments and resolutions.
|
|
@@ -56,7 +58,9 @@ $ gem install commenter
|
|
|
56
58
|
=== Importing comments
|
|
57
59
|
|
|
58
60
|
Convert an ISO comment sheet (DOCX or XLSX) to structured YAML.
|
|
59
|
-
The format is auto-detected from the file extension
|
|
61
|
+
The format is auto-detected from the file extension; redline DOCX must be
|
|
62
|
+
selected explicitly with `--format redline` because the extension cannot
|
|
63
|
+
distinguish a redline from a comment sheet.
|
|
60
64
|
|
|
61
65
|
[source,shell]
|
|
62
66
|
----
|
|
@@ -68,8 +72,28 @@ $ commenter import "91855-Comments-resolved.xlsx" -o comments.yaml
|
|
|
68
72
|
|
|
69
73
|
# From XLSX (ISO OSD comments-only export)
|
|
70
74
|
$ commenter import "ISO 5843-6-Comments.xlsx" -o comments.yaml
|
|
75
|
+
|
|
76
|
+
# From a redlined DOCX with tracked changes (ISO/CS editor redline)
|
|
77
|
+
$ commenter import "ISO_DIS 2533 Enquiry Trackchange Word.docx" --format redline \
|
|
78
|
+
--body CS --document "ISO 2533:2026" --stage DIS \
|
|
79
|
+
--observations "Accepted. ISO/CS tracked change accepted." \
|
|
80
|
+
-o comments-cs.yaml
|
|
71
81
|
----
|
|
72
82
|
|
|
83
|
+
Each tracked change (`w:ins`, `w:del`, `w:moveFrom`, `w:moveTo`) becomes a
|
|
84
|
+
comment entry whose `proposed_change` renders the change itself
|
|
85
|
+
(`Insert: "..."` / `Delete: "..."` / `Move ...: "..."`) and whose
|
|
86
|
+
`locality.clause` is resolved from the nearest preceding heading (including
|
|
87
|
+
sub-clauses such as `4.2.1` and `Annex A`), with `locality.element` resolved
|
|
88
|
+
from the nearest `Table`/`Figure`/`Formula`/`NOTE` reference in the same
|
|
89
|
+
clause. Self-closing paragraph-mark markers are skipped because they carry
|
|
90
|
+
no content.
|
|
91
|
+
|
|
92
|
+
Reviewer comment threads (`w:comment`) are emitted after the track changes
|
|
93
|
+
with `-CNNN` ids: the remark verbatim in `comments`, its instruction
|
|
94
|
+
reworded as the `proposed_change` (a leading "Please " is dropped), and
|
|
95
|
+
empty `observations` for the document owner to draft.
|
|
96
|
+
|
|
73
97
|
This will create two files:
|
|
74
98
|
|
|
75
99
|
`comments.yaml`:: The structured comment data
|
|
@@ -87,10 +111,15 @@ Options:
|
|
|
87
111
|
`-o, --output FILE`:: Output YAML file (default: comments.yaml)
|
|
88
112
|
`-e, --exclude-observations`:: Skip the observations column
|
|
89
113
|
`--schema-dir DIR`:: Directory for schema file (default: schema)
|
|
90
|
-
`--format FORMAT`:: Force input format (`docx` or `
|
|
91
|
-
`--sheet NAME`:: XLSX sheet name to parse (default: first sheet)
|
|
114
|
+
`--format FORMAT`:: Force input format (`docx`, `xlsx` or `redline`; auto-detected by default)
|
|
115
|
+
`--sheet NAME`:: XLSX: sheet name to parse (default: first sheet)
|
|
92
116
|
`--resolved-only`:: XLSX: use resolved comments sheet only
|
|
93
117
|
`--unresolved-only`:: XLSX: use unresolved comments sheet only
|
|
118
|
+
`--body CODE`:: Redline: member body code for comment IDs (default: `CS`)
|
|
119
|
+
`--observations TEXT`:: Redline: observations stamped on all track changes
|
|
120
|
+
`--accept-all`:: Redline: stamp `Accepted. Tracked change accepted.` on all track changes (an explicit `--observations` wins)
|
|
121
|
+
`--document ID`:: Redline: document identifier (e.g. `ISO 2533:2026`)
|
|
122
|
+
`--stage STAGE`:: Redline: approval stage (e.g. `DIS`)
|
|
94
123
|
|
|
95
124
|
==== Metadata (extraction limitation)
|
|
96
125
|
|
|
@@ -134,7 +163,7 @@ comments:
|
|
|
134
163
|
line_number:
|
|
135
164
|
clause: "_whole document"
|
|
136
165
|
element:
|
|
137
|
-
type:
|
|
166
|
+
type: general
|
|
138
167
|
comments: |
|
|
139
168
|
The document should include more examples
|
|
140
169
|
to clarify the implementation requirements.
|
|
@@ -150,7 +179,7 @@ comments:
|
|
|
150
179
|
line_number: "45"
|
|
151
180
|
clause: "5.2.1"
|
|
152
181
|
element: "Table 3"
|
|
153
|
-
type:
|
|
182
|
+
type: technical
|
|
154
183
|
comments: |
|
|
155
184
|
The values in Table 3 appear to be
|
|
156
185
|
inconsistent with the formula in 5.1.
|
|
@@ -471,7 +500,7 @@ comments:
|
|
|
471
500
|
locality:
|
|
472
501
|
clause: "5.2.1"
|
|
473
502
|
element: "Table 3"
|
|
474
|
-
type:
|
|
503
|
+
type: technical
|
|
475
504
|
comments: "The values in Table 3 appear inconsistent..."
|
|
476
505
|
proposed_change: "Correct the values in column 2..."
|
|
477
506
|
observations: ""
|
data/lib/commenter/cli.rb
CHANGED
|
@@ -3,20 +3,23 @@
|
|
|
3
3
|
require "thor"
|
|
4
4
|
require "yaml"
|
|
5
5
|
require "fileutils"
|
|
6
|
-
require "commenter
|
|
7
|
-
require "commenter/filler"
|
|
8
|
-
require "commenter/github_integration"
|
|
6
|
+
require "commenter"
|
|
9
7
|
|
|
10
8
|
module Commenter
|
|
11
9
|
class Cli < Thor
|
|
12
|
-
desc "import INPUT", "Convert comment sheet (DOCX or XLSX) to YAML"
|
|
10
|
+
desc "import INPUT", "Convert comment sheet (DOCX or XLSX) or redline DOCX to YAML"
|
|
13
11
|
option :output, type: :string, aliases: :o, default: "comments.yaml", desc: "Output YAML file"
|
|
14
12
|
option :exclude_observations, type: :boolean, aliases: :e, desc: "Exclude observations column"
|
|
15
13
|
option :schema_dir, type: :string, default: "schema", desc: "Directory for schema file"
|
|
16
|
-
option :format, type: :string, desc: "Force input format (docx or
|
|
14
|
+
option :format, type: :string, desc: "Force input format (docx, xlsx or redline)"
|
|
17
15
|
option :sheet, type: :string, desc: "XLSX sheet name to parse (default: first sheet)"
|
|
18
16
|
option :resolved_only, type: :boolean, desc: "XLSX: use resolved comments sheet only"
|
|
19
17
|
option :unresolved_only, type: :boolean, desc: "XLSX: use unresolved comments sheet only"
|
|
18
|
+
option :body, type: :string, desc: "Redline: member body code for comment IDs (default: CS)"
|
|
19
|
+
option :observations, type: :string, desc: "Redline: observations stamped on all track changes"
|
|
20
|
+
option :accept_all, type: :boolean, desc: "Redline: stamp 'Accepted. Tracked change accepted.' on all track changes"
|
|
21
|
+
option :document, type: :string, desc: "Redline: document identifier (e.g. ISO 2533:2026)"
|
|
22
|
+
option :stage, type: :string, desc: "Redline: approval stage (e.g. DIS)"
|
|
20
23
|
def import(input_file)
|
|
21
24
|
output_yaml = options[:output]
|
|
22
25
|
schema_dir = options[:schema_dir]
|
|
@@ -28,14 +31,11 @@ module Commenter
|
|
|
28
31
|
parser = Parser.new
|
|
29
32
|
comment_sheet = parser.parse(input_file, options)
|
|
30
33
|
|
|
31
|
-
# Determine which schema to use based on version
|
|
32
|
-
schema_name = comment_sheet.version == "osd" ? "iso_comment_osd.yaml" : "iso_comment_2012-03.yaml"
|
|
33
|
-
|
|
34
34
|
# Write the YAML data file with schema reference
|
|
35
|
-
|
|
36
|
-
File.write(output_yaml, yaml_content)
|
|
35
|
+
File.write(output_yaml, comment_sheet.to_yaml_document(schema_dir))
|
|
37
36
|
|
|
38
37
|
# Copy schema file to output directory
|
|
38
|
+
schema_name = comment_sheet.schema_name
|
|
39
39
|
schema_source = File.join(__dir__, "../../schema/#{schema_name}")
|
|
40
40
|
schema_target = File.join(schema_dir, schema_name)
|
|
41
41
|
|
|
@@ -212,13 +212,5 @@ module Commenter
|
|
|
212
212
|
def self.exit_on_failure?
|
|
213
213
|
true
|
|
214
214
|
end
|
|
215
|
-
|
|
216
|
-
private
|
|
217
|
-
|
|
218
|
-
def generate_yaml_with_header(data, schema_dir, schema_name = "iso_comment_2012-03.yaml")
|
|
219
|
-
schema_path = File.join(schema_dir, schema_name)
|
|
220
|
-
header = "# yaml-language-server: $schema=#{schema_path}\n\n"
|
|
221
|
-
header + data.to_yaml
|
|
222
|
-
end
|
|
223
215
|
end
|
|
224
216
|
end
|
data/lib/commenter/comment.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Commenter
|
|
|
13
13
|
@id = attrs[:id]
|
|
14
14
|
@body = attrs[:body]
|
|
15
15
|
@locality = symbolize_keys(attrs[:locality] || {})
|
|
16
|
-
@type =
|
|
16
|
+
@type = CommentType.full_name(attrs[:type])
|
|
17
17
|
@comments = attrs[:comments]
|
|
18
18
|
@proposed_change = attrs[:proposed_change]
|
|
19
19
|
@observations = attrs[:observations]
|
|
@@ -30,16 +30,8 @@ module Commenter
|
|
|
30
30
|
@stage_code = attrs[:stage_code]
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
# Expands short type codes to full names. One-way by design: already
|
|
34
|
-
# expanded values pass through unchanged so that reloading YAML output
|
|
35
|
-
# stays stable.
|
|
36
33
|
def expand_comment_type(type)
|
|
37
|
-
|
|
38
|
-
when "ge" then "general"
|
|
39
|
-
when "te" then "technical"
|
|
40
|
-
when "ed" then "editorial"
|
|
41
|
-
else type
|
|
42
|
-
end
|
|
34
|
+
CommentType.full_name(type)
|
|
43
35
|
end
|
|
44
36
|
|
|
45
37
|
def line_number
|
|
@@ -45,6 +45,14 @@ module Commenter
|
|
|
45
45
|
stringify_keys(hash)
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
+
def schema_name
|
|
49
|
+
version == "osd" ? "iso_comment_osd.yaml" : "iso_comment_2012-03.yaml"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def to_yaml_document(schema_dir = "schema")
|
|
53
|
+
"# yaml-language-server: $schema=#{File.join(schema_dir.to_s, schema_name)}\n\n#{to_yaml_h.to_yaml}"
|
|
54
|
+
end
|
|
55
|
+
|
|
48
56
|
def self.from_hash(hash)
|
|
49
57
|
new(hash)
|
|
50
58
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Commenter
|
|
4
|
+
# Single home for the comment type vocabulary: short codes (ge/te/ed) and
|
|
5
|
+
# their expanded names (general/technical/editorial). Unrecognized values
|
|
6
|
+
# pass through unchanged; display_name capitalizes recognized types.
|
|
7
|
+
module CommentType
|
|
8
|
+
FULL_NAMES = {
|
|
9
|
+
"ge" => "general",
|
|
10
|
+
"te" => "technical",
|
|
11
|
+
"ed" => "editorial"
|
|
12
|
+
}.freeze
|
|
13
|
+
|
|
14
|
+
CODES = FULL_NAMES.invert.freeze
|
|
15
|
+
|
|
16
|
+
DISPLAY_NAMES = FULL_NAMES.each_with_object({}) do |(code, full), display|
|
|
17
|
+
display[code] = full.capitalize
|
|
18
|
+
display[full] = full.capitalize
|
|
19
|
+
end.freeze
|
|
20
|
+
|
|
21
|
+
module_function
|
|
22
|
+
|
|
23
|
+
def code(type)
|
|
24
|
+
CODES.fetch(type.to_s.strip.downcase) { type&.to_s&.strip }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def full_name(type)
|
|
28
|
+
FULL_NAMES.fetch(type.to_s.strip.downcase) { type&.to_s&.strip }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def display_name(type)
|
|
32
|
+
DISPLAY_NAMES.fetch(type.to_s.strip.downcase) { type || "Unknown" }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -8,11 +8,10 @@ require "dotenv/load"
|
|
|
8
8
|
module Commenter
|
|
9
9
|
class GitHubIssueCreator
|
|
10
10
|
def initialize(config_path, title_template_path = nil, body_template_path = nil)
|
|
11
|
-
@
|
|
12
|
-
@
|
|
13
|
-
@
|
|
14
|
-
|
|
15
|
-
raise "GitHub repository not specified in config" unless @repo
|
|
11
|
+
@session = GitHubSession.new(config_path)
|
|
12
|
+
@config = @session.config
|
|
13
|
+
@github_client = @session.client
|
|
14
|
+
@repo = @session.repo
|
|
16
15
|
|
|
17
16
|
@title_template = load_liquid_template(title_template_path || default_title_template_path)
|
|
18
17
|
@body_template = load_liquid_template(body_template_path || default_body_template_path)
|
|
@@ -43,19 +42,6 @@ module Commenter
|
|
|
43
42
|
|
|
44
43
|
private
|
|
45
44
|
|
|
46
|
-
def load_config(config_path)
|
|
47
|
-
YAML.load_file(config_path)
|
|
48
|
-
rescue Errno::ENOENT
|
|
49
|
-
raise "Configuration file not found: #{config_path}"
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def create_github_client
|
|
53
|
-
token = @config.dig("github", "token") || ENV["GITHUB_TOKEN"]
|
|
54
|
-
raise "GitHub token not found. Set GITHUB_TOKEN environment variable or specify in config file." unless token
|
|
55
|
-
|
|
56
|
-
Octokit::Client.new(access_token: token)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
45
|
def default_title_template_path
|
|
60
46
|
File.join(__dir__, "../../data/github_issue_title_template.liquid")
|
|
61
47
|
end
|
|
@@ -103,7 +89,7 @@ module Commenter
|
|
|
103
89
|
"comment_id" => comment.id || "",
|
|
104
90
|
"body" => comment.body || "",
|
|
105
91
|
"type" => comment.type || "",
|
|
106
|
-
"type_full_name" =>
|
|
92
|
+
"type_full_name" => CommentType.display_name(comment.type),
|
|
107
93
|
"comments" => comment.comments || "",
|
|
108
94
|
"proposed_change" => comment.proposed_change || "",
|
|
109
95
|
"observations" => comment.observations || "",
|
|
@@ -134,15 +120,6 @@ module Commenter
|
|
|
134
120
|
@unique_id_template.render(base_variables).strip
|
|
135
121
|
end
|
|
136
122
|
|
|
137
|
-
def expand_comment_type(type)
|
|
138
|
-
case type&.downcase
|
|
139
|
-
when "ge", "general" then "General"
|
|
140
|
-
when "te", "technical" then "Technical"
|
|
141
|
-
when "ed", "editorial" then "Editorial"
|
|
142
|
-
else type || "Unknown"
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
|
|
146
123
|
def format_locality(comment)
|
|
147
124
|
parts = []
|
|
148
125
|
parts << "Clause #{comment.clause}" if comment.clause && !comment.clause.strip.empty?
|
|
@@ -314,23 +291,16 @@ module Commenter
|
|
|
314
291
|
|
|
315
292
|
# Write updated YAML
|
|
316
293
|
output_file = options[:output] || yaml_file
|
|
317
|
-
|
|
318
|
-
File.write(output_file, yaml_content)
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
def generate_yaml_with_header(data)
|
|
322
|
-
header = "# yaml-language-server: $schema=schema/iso_comment_2012-03.yaml\n\n"
|
|
323
|
-
header + data.to_yaml
|
|
294
|
+
File.write(output_file, comment_sheet.to_yaml_document)
|
|
324
295
|
end
|
|
325
296
|
end
|
|
326
297
|
|
|
327
298
|
class GitHubIssueRetriever
|
|
328
299
|
def initialize(config_path)
|
|
329
|
-
@
|
|
330
|
-
@
|
|
331
|
-
@
|
|
332
|
-
|
|
333
|
-
raise "GitHub repository not specified in config" unless @repo
|
|
300
|
+
@session = GitHubSession.new(config_path)
|
|
301
|
+
@config = @session.config
|
|
302
|
+
@github_client = @session.client
|
|
303
|
+
@repo = @session.repo
|
|
334
304
|
end
|
|
335
305
|
|
|
336
306
|
def retrieve_observations_from_yaml(yaml_file, options = {})
|
|
@@ -357,19 +327,6 @@ module Commenter
|
|
|
357
327
|
|
|
358
328
|
private
|
|
359
329
|
|
|
360
|
-
def load_config(config_path)
|
|
361
|
-
YAML.load_file(config_path)
|
|
362
|
-
rescue Errno::ENOENT
|
|
363
|
-
raise "Configuration file not found: #{config_path}"
|
|
364
|
-
end
|
|
365
|
-
|
|
366
|
-
def create_github_client
|
|
367
|
-
token = @config.dig("github", "token") || ENV["GITHUB_TOKEN"]
|
|
368
|
-
raise "GitHub token not found. Set GITHUB_TOKEN environment variable or specify in config file." unless token
|
|
369
|
-
|
|
370
|
-
Octokit::Client.new(access_token: token)
|
|
371
|
-
end
|
|
372
|
-
|
|
373
330
|
def retrieve_observation(comment, options)
|
|
374
331
|
issue_number = comment.github_issue_number
|
|
375
332
|
|
|
@@ -486,13 +443,7 @@ module Commenter
|
|
|
486
443
|
|
|
487
444
|
def update_yaml_with_observations(yaml_file, comment_sheet, options)
|
|
488
445
|
output_file = options[:output] || yaml_file
|
|
489
|
-
|
|
490
|
-
File.write(output_file, yaml_content)
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
def generate_yaml_with_header(data)
|
|
494
|
-
header = "# yaml-language-server: $schema=schema/iso_comment_2012-03.yaml\n\n"
|
|
495
|
-
header + data.to_yaml
|
|
446
|
+
File.write(output_file, comment_sheet.to_yaml_document)
|
|
496
447
|
end
|
|
497
448
|
end
|
|
498
449
|
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "octokit"
|
|
4
|
+
require "yaml"
|
|
5
|
+
|
|
6
|
+
module Commenter
|
|
7
|
+
# Shared connection setup for the GitHub integration commands: loads the
|
|
8
|
+
# configuration file, builds the Octokit client, and resolves the target
|
|
9
|
+
# repository. One constructor, one test surface.
|
|
10
|
+
class GitHubSession
|
|
11
|
+
attr_reader :config, :client, :repo
|
|
12
|
+
|
|
13
|
+
def initialize(config_path)
|
|
14
|
+
@config = load_config(config_path)
|
|
15
|
+
@client = Octokit::Client.new(access_token: required_token)
|
|
16
|
+
@repo = @config.dig("github", "repository")
|
|
17
|
+
raise "GitHub repository not specified in config" unless @repo
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def load_config(config_path)
|
|
23
|
+
YAML.load_file(config_path)
|
|
24
|
+
rescue Errno::ENOENT
|
|
25
|
+
raise "Configuration file not found: #{config_path}"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def required_token
|
|
29
|
+
token = @config.dig("github", "token") || ENV["GITHUB_TOKEN"]
|
|
30
|
+
raise "GitHub token not found. Set GITHUB_TOKEN environment variable or specify in config file." unless token
|
|
31
|
+
|
|
32
|
+
token
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -201,7 +201,7 @@ module Commenter
|
|
|
201
201
|
clause: clause.empty? ? nil : clause,
|
|
202
202
|
element: clause_title.empty? ? nil : clause_title
|
|
203
203
|
}.compact,
|
|
204
|
-
type:
|
|
204
|
+
type: CommentType.code(cell_value_str(row, col_map[:comment_type]).to_s),
|
|
205
205
|
comments: comment_text.to_s.strip,
|
|
206
206
|
proposed_change: cell_value_str(row, col_map[:proposed_change]) ||
|
|
207
207
|
cell_value_str(row, col_map[:proposal_on_text])
|
|
@@ -227,15 +227,6 @@ module Commenter
|
|
|
227
227
|
parts.empty? ? nil : parts.join(". ")
|
|
228
228
|
end
|
|
229
229
|
|
|
230
|
-
def normalize_comment_type(type_str)
|
|
231
|
-
case type_str.strip.downcase
|
|
232
|
-
when "editorial", "ed" then "ed"
|
|
233
|
-
when "technical", "te" then "te"
|
|
234
|
-
when "general", "ge" then "ge"
|
|
235
|
-
else type_str.strip
|
|
236
|
-
end
|
|
237
|
-
end
|
|
238
|
-
|
|
239
230
|
def cell_value(row, index)
|
|
240
231
|
return nil if index.nil? || row.length <= index
|
|
241
232
|
|