revix 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 84fc11db5dc8582011c975954500bc7cdf138644d2eeb23f8a7be8e84e9e19a5
4
+ data.tar.gz: c4a80aaf7fc824afdd86a07637db47a016f5d2dc8090aaf1da147259dc2ed963
5
+ SHA512:
6
+ metadata.gz: 42ae71d3dacde27dbebb7dc4ba5ae7b23e428946286c57d84b4e92f5fa2493b93587c8ca0adc331d2a1c3d84b5d6454ad3489c72b9ba0aef300645bdea0412b7
7
+ data.tar.gz: ca6fb8744817b6d489d25e33ad9df7b509abbf423d79ac73b4c656319b875dc01d7620d9106c9dac855294a2c5be8a70c13445837a9865e8ad9f01e4fce9e647
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in revix.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+ gem "rspec", "~> 3.0"
10
+ gem "rubocop", "~> 1.7"
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2025, Ribose Inc.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.adoc ADDED
@@ -0,0 +1,317 @@
1
+ = Revix: revision history models
2
+
3
+ image:https://img.shields.io/gem/v/revix.svg["Gem Version", link="https://rubygems.org/gems/revix"]
4
+ image:https://github.com/metanorma/revix/workflows/ubuntu/badge.svg["Ubuntu Build Status", link="https://github.com/metanorma/revix/actions?query=workflow%3Aubuntu"]
5
+ image:https://github.com/metanorma/revix/workflows/macos/badge.svg["OSX Build Status", link="https://github.com/metanorma/revix/actions?query=workflow%3Amacos"]
6
+ image:https://github.com/metanorma/revix/workflows/windows/badge.svg["Windows Build Status", link="https://github.com/metanorma/revix/actions?query=workflow%3Awindows"]
7
+ image:https://codeclimate.com/github/metanorma/revix/badges/gpa.svg["Code Climate", link="https://codeclimate.com/github/metanorma/revix"]
8
+ image:https://img.shields.io/github/issues-pr-raw/metanorma/revix.svg["Pull Requests", link="https://github.com/metanorma/revix/pulls"]
9
+ image:https://img.shields.io/github/commits-since/metanorma/revix/latest.svg["Commits since latest",link="https://github.com/metanorma/revix/releases"]
10
+
11
+ == Purpose
12
+
13
+ Revix is a Ruby gem for working with Metanorma document revision history.
14
+
15
+ It provides a set of models and utilities for parsing, manipulating, and
16
+ serializing revision history data in YAML and XML formats.
17
+
18
+ == Installation
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ [source,ruby]
23
+ ----
24
+ gem 'revix'
25
+ ----
26
+
27
+ And then execute:
28
+
29
+ [source,shell]
30
+ ----
31
+ $ bundle install
32
+ ----
33
+
34
+ Or install it yourself as:
35
+
36
+ [source,shell]
37
+ ----
38
+ $ gem install revix
39
+ ----
40
+
41
+ == Usage
42
+
43
+ === Parsing revision history
44
+
45
+ ==== From YAML
46
+
47
+ [source,yaml]
48
+ ----
49
+ - edition: 1.0.0
50
+ date:
51
+ - type: published
52
+ value: 2012-04
53
+ contributor:
54
+ - person:
55
+ name:
56
+ abbreviation: JMS
57
+ completename: J. Michael Straczynski
58
+ amend:
59
+ - description: Approved edition of S-102
60
+ location:
61
+ - type: clause
62
+ value: 4.0
63
+ - type: whole
64
+ ----
65
+
66
+ [source,ruby]
67
+ ----
68
+ require 'revix'
69
+
70
+ # Parse from YAML string
71
+ yaml_content = File.read('revision_history.yaml')
72
+ history = Revix::RevisionHistory.from_yaml(yaml_content)
73
+
74
+ # Access revision data
75
+ history.revisions.each do |revision|
76
+ puts "Edition: #{revision.edition}"
77
+ puts "Date: #{revision.date.first.value} (#{revision.date.first.type})"
78
+
79
+ revision.contributor.each do |contributor|
80
+ if contributor.person
81
+ puts "Contributor: #{contributor.person.name.completename} (#{contributor.person.name.abbreviation})"
82
+ elsif contributor.organization
83
+ puts "Contributor: #{contributor.organization.name}"
84
+ end
85
+ end
86
+
87
+ revision.amend.each do |amendment|
88
+ puts "Amendment: #{amendment.description}"
89
+
90
+ amendment.location&.each do |location|
91
+ if location.value
92
+ puts " Location: #{location.type}=#{location.value}"
93
+ else
94
+ puts " Location: #{location.type}"
95
+ end
96
+ end
97
+
98
+ amendment.classification&.each do |classification|
99
+ puts " Classification: #{classification.tag} = #{classification.value}"
100
+ end
101
+ end
102
+ end
103
+ ----
104
+
105
+ ==== From XML
106
+
107
+ [source,xml]
108
+ ----
109
+ <revision-history>
110
+ <revision>
111
+ <date type="published">2012-04</date>
112
+ <edition>1.0.0</edition>
113
+ <contributor>
114
+ <person>
115
+ <name abbreviation="JMS">
116
+ <completename>J. Michael Straczynski</completename>
117
+ </name>
118
+ </person>
119
+ </contributor>
120
+ <amend>
121
+ <amendment>
122
+ <description>Approved edition of S-102</description>
123
+ <location type="clause">4.0</location>
124
+ <location type="whole"/>
125
+ </amendment>
126
+ </amend>
127
+ </revision>
128
+ </revision-history>
129
+ ----
130
+
131
+ [source,ruby]
132
+ ----
133
+ require 'revix'
134
+
135
+ # Parse from XML string
136
+ xml_content = File.read('revision_history.xml')
137
+ history = Revix::RevisionHistory.from_xml(xml_content)
138
+
139
+ # Access revision data (same as with YAML)
140
+ ----
141
+
142
+ === Serializing revision history
143
+
144
+ ==== To YAML
145
+
146
+ [source,ruby]
147
+ ----
148
+ require 'revix'
149
+
150
+ # Create a revision history object
151
+ history = Revix::RevisionHistory.new(revisions: [
152
+ Revix::Revision.new(
153
+ date: [Revix::DateInfo.new(type: "published", value: "2012-04")],
154
+ edition: "1.0.0",
155
+ contributor: [
156
+ Revix::Contributor.new(
157
+ person: Revix::Person.new(
158
+ name: Revix::Name.new(
159
+ abbreviation: "JMS",
160
+ completename: "J. Michael Straczynski"
161
+ )
162
+ )
163
+ )
164
+ ],
165
+ amend: [
166
+ Revix::Amendment.new(
167
+ description: "Approved edition of S-102",
168
+ location: [
169
+ Revix::Location.new(type: "clause", value: "4.0"),
170
+ Revix::Location.new(type: "whole")
171
+ ]
172
+ )
173
+ ]
174
+ )
175
+ ])
176
+
177
+ # Serialize to YAML
178
+ yaml_content = history.to_yaml
179
+ File.write('revision_history.yaml', yaml_content)
180
+ ----
181
+
182
+ ==== To XML
183
+
184
+ [source,ruby]
185
+ ----
186
+ # Serialize to XML
187
+ xml_content = history.to_xml
188
+ File.write('revision_history.xml', xml_content)
189
+ ----
190
+
191
+ == Data model
192
+
193
+ The Revix gem provides the following models.
194
+
195
+ [source]
196
+ ----
197
+ +-------------------+
198
+ | RevisionHistory |
199
+ | |
200
+ | +revisions |
201
+ +--------+----------+
202
+ |
203
+ | 1..*
204
+ +--------v----------+ +------------+
205
+ | Revision | | DateInfo |
206
+ | | | |
207
+ | -edition |<>--->| -type |
208
+ | -relation_type | | -value |
209
+ | +date | | |
210
+ | +contributor | +------------+
211
+ | +amend |
212
+ +--------+----------+
213
+ |
214
+ +----+----+---------------------+
215
+ | | |
216
+ +---v---+ +---v----------+ +-------v--------+
217
+ |Person | | Organization | | Amendment |
218
+ | | | | | |
219
+ | +name | | -name | | -description |
220
+ | | | -subdivision | | -change |
221
+ | | | -abbreviation| | +location |
222
+ +---+---+ +--------------+ | +classification|
223
+ | +-------+--------+
224
+ | |
225
+ | +------------+------+
226
+ +---v---+ | |
227
+ | Name | +------+-------+ +-------+-------+
228
+ | | + Location | | Classification|
229
+ | -abbr | | | | |
230
+ | -full | | -type | | -tag |
231
+ +-------+ | -value | | -value |
232
+ +--------------+ +---------------+
233
+ ----
234
+
235
+ === RevisionHistory
236
+
237
+ The main container for all revisions.
238
+
239
+ `revisions`:: A collection of `Revision` objects
240
+
241
+ === Revision
242
+
243
+ Represents a single revision entry.
244
+
245
+ `date`:: A collection of `DateInfo` objects
246
+ `edition`:: The version number as a string
247
+ `contributor`:: A collection of `Contributor` objects
248
+ `amend`:: A collection of `Amendment` objects
249
+ `relation_type`:: The relation type (optional)
250
+
251
+ === DateInfo
252
+
253
+ Represents date information.
254
+
255
+ `type`:: The type of date (e.g., "published", "updated")
256
+ `value`:: The date value as a string
257
+
258
+ === Contributor
259
+
260
+ Represents a contributor, which can be either a person or an organization.
261
+
262
+ `person`:: A `Person` object (optional)
263
+ `organization`:: An `Organization` object (optional)
264
+
265
+ === Person
266
+
267
+ Represents a person contributor.
268
+
269
+ `name`:: A `Name` object
270
+
271
+ === Organization
272
+
273
+ Represents an organization contributor.
274
+
275
+ `name`:: The organization name as a string
276
+ `subdivision`:: The organization subdivision as a string (optional)
277
+ `abbreviation`:: The organization abbreviation as a string (optional)
278
+
279
+ === Name
280
+
281
+ Represents a person's name.
282
+
283
+ `abbreviation`:: The person's abbreviation or initials
284
+ `completename`:: The person's full name
285
+
286
+ === Amendment
287
+
288
+ Represents an amendment.
289
+
290
+ `description`:: The amendment description as a string
291
+ `location`:: A collection of `Location` objects (optional)
292
+ `classification`:: A collection of `Classification` objects (optional)
293
+ `change`:: The type of change (default: "modify")
294
+
295
+ === Location
296
+
297
+ Represents a location affected by an amendment.
298
+
299
+ `type`:: The location type. Accepts the defined Metanorma location types, including: `section`, `clause`, `part`, `paragraph`, `chapter`, `page`, `line`, `table`, `annex`, `figure`, `example`, `note`, `formula`, `list`, `time`, `anchor`, `whole`.
300
+ `value`:: The location value (e.g., `4.0`, `B`), can be `nil` for types like `whole`.
301
+
302
+ === Classification
303
+
304
+ Represents a classification tag/value pair.
305
+
306
+ `tag`:: The classification tag (e.g., "severity", "type")
307
+ `value`:: The classification value (e.g., "major", "editorial")
308
+
309
+ == Copyright
310
+
311
+ This gem is developed, maintained and funded by
312
+ https://www.ribose.com[Ribose Inc.]
313
+
314
+ == License
315
+
316
+ The gem is available as open source under the terms of the
317
+ https://opensource.org/licenses/BSD-2-Clause[2-Clause BSD License].
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Revix
6
+ class Amendment < Lutaml::Model::Serializable
7
+ attribute :description, :string
8
+ attribute :location, Location, collection: true
9
+ attribute :classification, Classification, collection: true
10
+ attribute :change, :string, default: -> { "modify" }
11
+
12
+ xml do
13
+ root "amend"
14
+ map_element "description", to: :description
15
+ map_element "location", to: :location
16
+ map_element "classification", to: :classification
17
+ map_element "change", to: :change
18
+ end
19
+
20
+ key_value do
21
+ map "description", to: :description
22
+ map "location", to: :location
23
+ map "classification", to: :classification
24
+ map "change", to: :change
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Revix
6
+ class Classification < Lutaml::Model::Serializable
7
+ attribute :tag, :string
8
+ attribute :value, :string
9
+
10
+ xml do
11
+ root "classification"
12
+ map_element "tag", to: :tag
13
+ map_element "value", to: :value
14
+ end
15
+
16
+ key_value do
17
+ map "tag", to: :tag
18
+ map "value", to: :value
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Revix
6
+ class Contributor < Lutaml::Model::Serializable
7
+ attribute :person, Person
8
+ attribute :organization, Organization
9
+
10
+ xml do
11
+ root "contributor"
12
+ map_element "person", to: :person
13
+ map_element "organization", to: :organization
14
+ end
15
+
16
+ key_value do
17
+ map "person", to: :person
18
+ map "organization", to: :organization
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Revix
6
+ class DateInfo < Lutaml::Model::Serializable
7
+ attribute :type, :string
8
+ attribute :value, :string
9
+
10
+ xml do
11
+ root "date"
12
+ map_element "type", to: :type
13
+ map_element "value", to: :value
14
+ end
15
+
16
+ key_value do
17
+ map "type", to: :type
18
+ map "value", to: :value
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Revix
6
+ class Location < Lutaml::Model::Serializable
7
+ VALID_TYPES = %w[
8
+ section clause part paragraph chapter page line table annex figure
9
+ example note formula list time anchor whole
10
+ ].freeze
11
+
12
+ attribute :value, :string
13
+ attribute :type, :string, values: VALID_TYPES
14
+
15
+ xml do
16
+ root "location"
17
+ map_content to: :value
18
+ map_attribute "type", to: :type
19
+ end
20
+
21
+ key_value do
22
+ map "value", to: :value
23
+ map "type", to: :type
24
+ end
25
+ end
26
+ end
data/lib/revix/name.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Revix
6
+ class Name < Lutaml::Model::Serializable
7
+ attribute :abbreviation, :string
8
+ attribute :completename, :string
9
+
10
+ xml do
11
+ root "name"
12
+ map_element "abbreviation", to: :abbreviation
13
+ map_element "completename", to: :completename
14
+ end
15
+
16
+ key_value do
17
+ map "abbreviation", to: :abbreviation
18
+ map "completename", to: :completename
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Revix
6
+ class Organization < Lutaml::Model::Serializable
7
+ attribute :name, :string
8
+ attribute :subdivision, :string
9
+ attribute :abbreviation, :string
10
+
11
+ xml do
12
+ root "organization"
13
+ map_element "name", to: :name
14
+ map_element "subdivision", to: :subdivision
15
+ map_element "abbreviation", to: :abbreviation
16
+ end
17
+
18
+ key_value do
19
+ map "name", to: :name
20
+ map "subdivision", to: :subdivision
21
+ map "abbreviation", to: :abbreviation
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Revix
6
+ class Person < Lutaml::Model::Serializable
7
+ attribute :name, Name
8
+
9
+ xml do
10
+ root "person"
11
+ map_element "name", to: :name
12
+ end
13
+
14
+ key_value do
15
+ map "name", to: :name
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Revix
6
+ class Revision < Lutaml::Model::Serializable
7
+ attribute :date, DateInfo, collection: true
8
+ attribute :edition, :string
9
+ attribute :contributor, Contributor, collection: true
10
+ attribute :amend, Amendment, collection: true
11
+ attribute :relation_type, Amendment, collection: true
12
+
13
+ xml do
14
+ root "revision"
15
+ map_element "date", to: :date
16
+ map_element "edition", to: :edition
17
+ map_element "contributor", to: :contributor
18
+ map_element "amend", to: :amend
19
+ map_element "relation", to: :relation_type
20
+ end
21
+
22
+ key_value do
23
+ map "date", to: :date
24
+ map "edition", to: :edition
25
+ map "contributor", to: :contributor
26
+ map "amend", to: :amend
27
+ map "relation", to: :relation_type
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Revix
6
+ class RevisionHistory < Lutaml::Model::Serializable
7
+ attribute :revisions, Revix::Revision, collection: true
8
+
9
+ xml do
10
+ root "revision-history"
11
+ map_element "revision", to: :revisions
12
+ end
13
+
14
+ key_value do
15
+ map "revisions", to: :revisions
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Revix
4
+ VERSION = "0.1.0"
5
+ end
data/lib/revix.rb ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "revix/version"
4
+ require "lutaml/model"
5
+
6
+ module Revix
7
+ class Error < StandardError; end
8
+ end
9
+
10
+ require_relative "revix/name"
11
+ require_relative "revix/person"
12
+ require_relative "revix/organization"
13
+ require_relative "revix/contributor"
14
+ require_relative "revix/date_info"
15
+ require_relative "revix/classification"
16
+ require_relative "revix/location"
17
+ require_relative "revix/amendment"
18
+ require_relative "revix/revision"
19
+ require_relative "revix/revision_history"
20
+
21
+ require "lutaml/model/xml_adapter/nokogiri_adapter"
22
+ require "lutaml/model/json_adapter/standard_json_adapter"
23
+ require "lutaml/model/yaml_adapter/standard_yaml_adapter"
24
+
25
+ Lutaml::Model::Config.configure do |config|
26
+ config.xml_adapter = Lutaml::Model::XmlAdapter::NokogiriAdapter
27
+ config.yaml_adapter = Lutaml::Model::YamlAdapter::StandardYamlAdapter
28
+ config.json_adapter = Lutaml::Model::JsonAdapter::StandardJsonAdapter
29
+ end
data/revix.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/revix/version"
4
+
5
+ all_files_in_git = Dir.chdir(File.expand_path(__dir__)) do
6
+ `git ls-files -z`.split("\x0")
7
+ end
8
+
9
+ Gem::Specification.new do |spec|
10
+ spec.name = "revix"
11
+ spec.version = Revix::VERSION
12
+ spec.authors = ["Ribose"]
13
+ spec.email = ["open.source@ribose.com"]
14
+
15
+ spec.summary = "Library to work with Metanorma document revision history."
16
+ spec.homepage = "https://github.com/metanorma/revix"
17
+ spec.license = "BSD-2-Clause"
18
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
19
+
20
+ spec.metadata["homepage_uri"] = spec.homepage
21
+ spec.metadata["source_code_uri"] = spec.homepage
22
+ spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ spec.files = all_files_in_git
26
+ .reject { |f| f.match(%r{\A(?:test|features|bin|\.)/}) }
27
+
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_dependency "lutaml-model", "~> 0.6"
33
+ spec.add_dependency "nokogiri"
34
+ spec.add_dependency "xml-c14n"
35
+ end
@@ -0,0 +1,75 @@
1
+ revisions:
2
+ - date:
3
+ - type: published
4
+ value: 2012-04
5
+ edition: 1.0.0
6
+ contributor:
7
+ - organization:
8
+ name: International Hydrographic Organization
9
+ subdivision: Transfer Standard Maintenance and Application Development
10
+ abbreviation: TSMAD
11
+ amend:
12
+ - description: Approved edition of S-102
13
+ - date:
14
+ - type: published
15
+ value: 2017-03
16
+ edition: 2.0.0
17
+ contributor:
18
+ - organization:
19
+ name: International Hydrographic Organization
20
+ subdivision: S-102 Project Team
21
+ abbreviation: S-102PT
22
+ amend:
23
+ - description: >
24
+ Updated clause 4.0 and 12.0.
25
+
26
+ Populated clause 9.0 and Annex B.
27
+ location:
28
+ - type: clause
29
+ value: 4.0
30
+ - type: clause
31
+ value: 12.0
32
+ - type: clause
33
+ value: 9.0
34
+ - type: annex
35
+ value: B
36
+ - date:
37
+ - type: updated
38
+ value: 2017-05
39
+ edition: 2.0.0
40
+ contributor:
41
+ - organization:
42
+ name: International Hydrographic Organization
43
+ subdivision: S-102 Project Team
44
+ abbreviation: S-102PT
45
+ amend:
46
+ - description: >
47
+ Modified clause 9.0 based on feedback at S-100WG2 meeting.
48
+ location:
49
+ - type: clause
50
+ value: 9.0
51
+ - date:
52
+ - type: updated
53
+ value: 2018-02
54
+ edition: 2.0.0
55
+ contributor:
56
+ - person:
57
+ name:
58
+ completename: Cliff Kottman
59
+ abbreviation: CK
60
+ amend:
61
+ - description: >
62
+ Modified clause 9.0. Deleted contents of Annex B in preparation for updated S-100 Part 10C guidance. Added Annex F: S-102 Dataset Size and Production, Annex G: Gridding Example, Annex H: Statement added for Multi-Resolution Gridding, Annex I: Statement for future S-102 Tiling.
63
+ location:
64
+ - type: clause
65
+ value: 9.0
66
+ - type: annex
67
+ value: B
68
+ - type: annex
69
+ value: F
70
+ - type: annex
71
+ value: G
72
+ - type: annex
73
+ value: H
74
+ - type: annex
75
+ value: I
@@ -0,0 +1,31 @@
1
+ revisions:
2
+ - date:
3
+ - type: published
4
+ value: 2020-06-04
5
+ edition: 0.9.0
6
+ contributor:
7
+ - person:
8
+ name:
9
+ completename: C. Heazel
10
+ abbreviation: CH
11
+ amend:
12
+ - description: Draft for review
13
+ location:
14
+ - type: whole
15
+ - date:
16
+ - type: published
17
+ value: 2020-06-07
18
+ edition: 0.9.1
19
+ contributor:
20
+ - person:
21
+ name:
22
+ completename: T. H. Kolbe
23
+ abbreviation: THK
24
+ amend:
25
+ - description: Bibliography was added
26
+ location:
27
+ - type: clause
28
+ value: 10
29
+ classification:
30
+ - tag: type
31
+ value: editorial
@@ -0,0 +1,54 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <revision-history>
3
+ <revision>
4
+ <date>
5
+ <type>published</type>
6
+ <value>2012-04</value>
7
+ </date>
8
+ <edition>1.0.0</edition>
9
+ <contributor>
10
+ <person>
11
+ <name>
12
+ <abbreviation>JMS</abbreviation>
13
+ <completename>J. Michael Straczynski</completename>
14
+ </name>
15
+ </person>
16
+ </contributor>
17
+ <amend>
18
+ <description>Approved edition of S-102</description>
19
+ </amend>
20
+ </revision>
21
+ <revision>
22
+ <date>
23
+ <type>updated</type>
24
+ <value>2017-03</value>
25
+ </date>
26
+ <edition>2.0.0</edition>
27
+ <contributor>
28
+ <organization>
29
+ <name>S-102PT</name>
30
+ </organization>
31
+ </contributor>
32
+ <amend>
33
+ <description>Updated clause 4.0 and 12.0.
34
+
35
+ Populated clause 9.0.</description>
36
+ <location type="clause">4.0</location>
37
+ <location type="clause">12.0</location>
38
+ <location type="clause">9.0</location>
39
+ <location type="whole"></location>
40
+ <classification>
41
+ <tag>severity</tag>
42
+ <value>major</value>
43
+ </classification>
44
+ <classification>
45
+ <tag>type</tag>
46
+ <value>editorial</value>
47
+ </classification>
48
+ </amend>
49
+ <amend>
50
+ <description>Deleted contents of Annex B in preparation for updated S-100 Part 10C guidance.</description>
51
+ <location type="annex">B</location>
52
+ </amend>
53
+ </revision>
54
+ </revision-history>
@@ -0,0 +1,41 @@
1
+ revisions:
2
+ - date:
3
+ - type: published
4
+ value: 2012-04
5
+ edition: 1.0.0
6
+ contributor:
7
+ - person:
8
+ name:
9
+ abbreviation: JMS
10
+ completename: J. Michael Straczynski
11
+ amend:
12
+ - description: Approved edition of S-102
13
+ - date:
14
+ - type: updated
15
+ value: 2017-03
16
+ edition: 2.0.0
17
+ contributor:
18
+ - organization:
19
+ name: S-102PT
20
+ amend:
21
+ - description: |
22
+ Updated clause 4.0 and 12.0.
23
+
24
+ Populated clause 9.0.
25
+ location:
26
+ - type: clause
27
+ value: 4.0
28
+ - type: clause
29
+ value: 12.0
30
+ - type: clause
31
+ value: 9.0
32
+ - type: whole
33
+ classification:
34
+ - tag: severity
35
+ value: major
36
+ - tag: type
37
+ value: editorial
38
+ - description: Deleted contents of Annex B in preparation for updated S-100 Part 10C guidance.
39
+ location:
40
+ - type: annex
41
+ value: B
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe Revix::Amendment do
6
+ let(:simple_amendment_data) do
7
+ Revix::Amendment.new(description: "Approved edition of S-102")
8
+ end
9
+
10
+ let(:complex_amendment_data) do
11
+ locations = [
12
+ Revix::Location.new(type: "clause", value: "4.0"),
13
+ Revix::Location.new(type: "clause", value: "12.0"),
14
+ Revix::Location.new(type: "clause", value: "9.0"),
15
+ Revix::Location.new(type: "whole", value: nil)
16
+ ]
17
+
18
+ classifications = [
19
+ Revix::Classification.new(tag: "severity", value: "major"),
20
+ Revix::Classification.new(tag: "type", value: "editorial")
21
+ ]
22
+
23
+ Revix::Amendment.new(
24
+ description: "Updated clause 4.0 and 12.0.\n\nPopulated clause 9.0.",
25
+ location: locations,
26
+ classification: classifications,
27
+ change: "modify"
28
+ )
29
+ end
30
+
31
+ describe ".new" do
32
+ it "creates a simple Amendment object" do
33
+ amendment = simple_amendment_data
34
+ expect(amendment).to be_a(Revix::Amendment)
35
+ expect(amendment.description).to eq("Approved edition of S-102")
36
+ expect(amendment.location).to be_empty
37
+ expect(amendment.classification).to be_empty
38
+ expect(amendment.change).to eq("modify") # Default value
39
+ end
40
+
41
+ it "creates a complex Amendment object" do
42
+ amendment = complex_amendment_data
43
+ expect(amendment).to be_a(Revix::Amendment)
44
+ expect(amendment.description).to eq("Updated clause 4.0 and 12.0.\n\nPopulated clause 9.0.")
45
+ expect(amendment.location.size).to eq(4)
46
+ expect(amendment.location.first.type).to eq("clause")
47
+ expect(amendment.location.first.value).to eq("4.0")
48
+ expect(amendment.location.last.type).to eq("whole")
49
+ expect(amendment.location.last.value).to be_nil
50
+ expect(amendment.classification.size).to eq(2)
51
+ expect(amendment.classification.first.tag).to eq("severity")
52
+ expect(amendment.classification.first.value).to eq("major")
53
+ expect(amendment.change).to eq("modify")
54
+ end
55
+ end
56
+
57
+ describe "#to_xml" do
58
+ it "converts a complex Amendment object to XML" do
59
+ amendment = complex_amendment_data
60
+ xml = amendment.to_xml
61
+ expect(xml).to be_a(String)
62
+ expect(xml).to include("<amend>")
63
+ expect(xml).to include("<description>Updated clause 4.0 and 12.0.\n\nPopulated clause 9.0.</description>")
64
+ expect(xml).to include('<location type="clause">4.0</location>')
65
+ expect(xml).to include('<location type="clause">12.0</location>')
66
+ expect(xml).to include('<location type="clause">9.0</location>')
67
+ expect(xml).to include('<location type="whole"></location>')
68
+ expect(xml).to include("<tag>severity</tag>")
69
+ expect(xml).to include("<value>major</value>")
70
+ expect(xml).to include("<tag>type</tag>")
71
+ expect(xml).to include("<value>editorial</value>")
72
+ expect(xml).to include("<change>modify</change>")
73
+ end
74
+
75
+ it "performs round-trip conversion from XML to object and back" do
76
+ original = complex_amendment_data
77
+ xml1 = original.to_xml
78
+
79
+ # Parse back to object and generate XML again
80
+ parsed = Revix::Amendment.from_xml(xml1)
81
+ xml2 = parsed.to_xml
82
+
83
+ # Canonicalize both XMLs and compare using xml-c14n
84
+ c14n1 = Xml::C14n.format(xml1)
85
+ c14n2 = Xml::C14n.format(xml2)
86
+
87
+ expect(c14n2).to eq(c14n1)
88
+ expect(c14n2).to be_analogous_with(c14n1)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe Revix::RevisionHistory do
6
+ fixture_path = File.join(__dir__, "..", "fixtures")
7
+ let(:yaml_content) { File.read(File.join(fixture_path, "sample.yaml")) }
8
+ let(:xml_content) { File.read(File.join(fixture_path, "sample.xml")) }
9
+ let(:iho_yaml_content) { File.read(File.join(fixture_path, "iho_sample.yaml")) }
10
+ let(:ogc_yaml_content) { File.read(File.join(fixture_path, "ogc_sample.yaml")) }
11
+
12
+ describe ".from_yaml" do
13
+ it "parses YAML content into a RevisionHistory object" do
14
+ history = Revix::RevisionHistory.from_yaml(yaml_content)
15
+ expect(history).to be_a(Revix::RevisionHistory)
16
+ expect(history.revisions.size).to eq(2)
17
+ end
18
+
19
+ it "parses IHO YAML content into a RevisionHistory object" do
20
+ history = Revix::RevisionHistory.from_yaml(iho_yaml_content)
21
+ expect(history).to be_a(Revix::RevisionHistory)
22
+ expect(history.revisions.size).to eq(4)
23
+ end
24
+
25
+ it "parses OGC YAML content into a RevisionHistory object" do
26
+ history = Revix::RevisionHistory.from_yaml(ogc_yaml_content)
27
+ expect(history).to be_a(Revix::RevisionHistory)
28
+ expect(history.revisions.size).to eq(2)
29
+ end
30
+ end
31
+
32
+ describe ".from_xml" do
33
+ it "parses XML content into a RevisionHistory object" do
34
+ history = Revix::RevisionHistory.from_xml(xml_content)
35
+ expect(history).to be_a(Revix::RevisionHistory)
36
+ expect(history.revisions.size).to eq(2)
37
+ end
38
+ end
39
+
40
+ describe "#to_yaml" do
41
+ it "converts a RevisionHistory object to YAML" do
42
+ history = Revix::RevisionHistory.from_yaml(yaml_content)
43
+ yaml = history.to_yaml
44
+ expect(yaml).to be_a(String)
45
+ end
46
+ end
47
+
48
+ describe "#to_xml" do
49
+ it "converts a RevisionHistory object to XML" do
50
+ history = Revix::RevisionHistory.from_yaml(yaml_content)
51
+ xml = history.to_xml
52
+ expect(xml).to be_a(String)
53
+ expect(xml).to include("<revision-history>")
54
+ expect(xml).to include("<revision>")
55
+ end
56
+
57
+ it "performs round-trip conversion from XML to object and back" do
58
+ # Start with the static XML sample
59
+ original_xml = xml_content
60
+
61
+ # Parse to object
62
+ history = Revix::RevisionHistory.from_xml(original_xml)
63
+
64
+ # Convert back to XML
65
+ generated_xml = history.to_xml
66
+
67
+ # Canonicalize both XMLs and compare using xml-c14n
68
+ c14n_original = Xml::C14n.format(original_xml)
69
+ c14n_generated = Xml::C14n.format(generated_xml)
70
+
71
+ expect(c14n_generated).to eq(c14n_original)
72
+ expect(c14n_generated).to be_analogous_with(c14n_original)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe Revix::Revision do
6
+ let(:revision_data) do
7
+ date = [
8
+ Revix::DateInfo.new(type: "published", value: "2012-04")
9
+ ]
10
+ name = Revix::Name.new(abbreviation: "JMS", completename: "J. Michael Straczynski")
11
+ person = Revix::Person.new(name: name)
12
+ contributor = Revix::Contributor.new(person: person)
13
+ amendment = Revix::Amendment.new(description: "Approved edition of S-102")
14
+
15
+ Revix::Revision.new(
16
+ date: date,
17
+ edition: "1.0.0",
18
+ contributor: [contributor],
19
+ amend: [amendment]
20
+ )
21
+ end
22
+
23
+ describe ".new" do
24
+ it "creates a new Revision object" do
25
+ revision = revision_data
26
+ expect(revision).to be_a(Revix::Revision)
27
+ expect(revision.edition).to eq("1.0.0")
28
+ expect(revision.date.size).to eq(1)
29
+ expect(revision.date.first.type).to eq("published")
30
+ expect(revision.date.first.value).to eq("2012-04")
31
+ expect(revision.contributor.size).to eq(1)
32
+ expect(revision.contributor.first.person).not_to be_nil
33
+ expect(revision.contributor.first.person.name.abbreviation).to eq("JMS")
34
+ expect(revision.contributor.first.person.name.completename).to eq("J. Michael Straczynski")
35
+ expect(revision.amend.size).to eq(1)
36
+ expect(revision.amend.first.description).to eq("Approved edition of S-102")
37
+ end
38
+ end
39
+
40
+ describe "#to_xml" do
41
+ it "converts a Revision object to XML and back" do
42
+ original = revision_data
43
+ xml1 = original.to_xml
44
+
45
+ # Parse back to object and generate XML again
46
+ parsed = Revix::Revision.from_xml(xml1)
47
+ xml2 = parsed.to_xml
48
+
49
+ # Canonicalize both XMLs and compare using xml-c14n
50
+ c14n1 = Xml::C14n.format(xml1)
51
+ c14n2 = Xml::C14n.format(xml2)
52
+
53
+ expect(c14n2).to eq(c14n1)
54
+ expect(c14n2).to be_analogous_with(c14n1)
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe Revix do
6
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "revix"
5
+ require "xml/c14n"
6
+
7
+ RSpec.configure do |config|
8
+ # Enable flags like --only-failures and --next-failure
9
+ config.example_status_persistence_file_path = ".rspec_status"
10
+
11
+ # Disable RSpec exposing methods globally on `Module` and `main`
12
+ config.disable_monkey_patching!
13
+
14
+ config.expect_with :rspec do |c|
15
+ c.syntax = :expect
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: revix
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ribose
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2025-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: lutaml-model
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: xml-c14n
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email:
57
+ - open.source@ribose.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE
65
+ - README.adoc
66
+ - Rakefile
67
+ - lib/revix.rb
68
+ - lib/revix/amendment.rb
69
+ - lib/revix/classification.rb
70
+ - lib/revix/contributor.rb
71
+ - lib/revix/date_info.rb
72
+ - lib/revix/location.rb
73
+ - lib/revix/name.rb
74
+ - lib/revix/organization.rb
75
+ - lib/revix/person.rb
76
+ - lib/revix/revision.rb
77
+ - lib/revix/revision_history.rb
78
+ - lib/revix/version.rb
79
+ - revix.gemspec
80
+ - spec/fixtures/iho_sample.yaml
81
+ - spec/fixtures/ogc_sample.yaml
82
+ - spec/fixtures/sample.xml
83
+ - spec/fixtures/sample.yaml
84
+ - spec/models/amendment_spec.rb
85
+ - spec/models/revision_history_spec.rb
86
+ - spec/models/revision_spec.rb
87
+ - spec/revix_spec.rb
88
+ - spec/spec_helper.rb
89
+ homepage: https://github.com/metanorma/revix
90
+ licenses:
91
+ - BSD-2-Clause
92
+ metadata:
93
+ homepage_uri: https://github.com/metanorma/revix
94
+ source_code_uri: https://github.com/metanorma/revix
95
+ bug_tracker_uri: https://github.com/metanorma/revix/issues
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: 2.6.0
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubygems_version: 3.5.22
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: Library to work with Metanorma document revision history.
115
+ test_files: []