prosereflect 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.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/rake.yml +15 -0
  3. data/.github/workflows/release.yml +25 -0
  4. data/.gitignore +12 -0
  5. data/.rubocop.yml +1 -0
  6. data/.rubocop_todo.yml +228 -0
  7. data/CODE_OF_CONDUCT.md +132 -0
  8. data/Gemfile +10 -0
  9. data/README.adoc +268 -0
  10. data/Rakefile +12 -0
  11. data/debug_loading.rb +34 -0
  12. data/lib/prosereflect/document.rb +63 -0
  13. data/lib/prosereflect/hard_break.rb +22 -0
  14. data/lib/prosereflect/node.rb +77 -0
  15. data/lib/prosereflect/paragraph.rb +50 -0
  16. data/lib/prosereflect/parser.rb +56 -0
  17. data/lib/prosereflect/table.rb +64 -0
  18. data/lib/prosereflect/table_cell.rb +37 -0
  19. data/lib/prosereflect/table_row.rb +32 -0
  20. data/lib/prosereflect/text.rb +37 -0
  21. data/lib/prosereflect/version.rb +5 -0
  22. data/lib/prosereflect.rb +17 -0
  23. data/prosereflect.gemspec +33 -0
  24. data/sig/prosemirror.rbs +4 -0
  25. data/spec/fixtures/ituob-1000/ituob-1000-DP.json +366 -0
  26. data/spec/fixtures/ituob-1000/ituob-1000-DP.yaml +182 -0
  27. data/spec/fixtures/ituob-1000/ituob-1000-E118_IIN.json +381 -0
  28. data/spec/fixtures/ituob-1000/ituob-1000-E118_IIN.yaml +182 -0
  29. data/spec/fixtures/ituob-1000/ituob-1000-E164_ACN.json +203 -0
  30. data/spec/fixtures/ituob-1000/ituob-1000-E164_ACN.yaml +98 -0
  31. data/spec/fixtures/ituob-1000/ituob-1000-E212_MNC.json +202 -0
  32. data/spec/fixtures/ituob-1000/ituob-1000-E212_MNC.yaml +101 -0
  33. data/spec/fixtures/ituob-1000/ituob-1000-F32_TDI.json +6948 -0
  34. data/spec/fixtures/ituob-1000/ituob-1000-F32_TDI.yaml +3519 -0
  35. data/spec/fixtures/ituob-1000/ituob-1000-M1400_ICC.json +529 -0
  36. data/spec/fixtures/ituob-1000/ituob-1000-M1400_ICC.yaml +263 -0
  37. data/spec/fixtures/ituob-1000/ituob-1000-NNP.json +288 -0
  38. data/spec/fixtures/ituob-1000/ituob-1000-NNP.yaml +152 -0
  39. data/spec/fixtures/ituob-1000/ituob-1000-Q708_ISPC.json +1534 -0
  40. data/spec/fixtures/ituob-1000/ituob-1000-Q708_ISPC.yaml +789 -0
  41. data/spec/fixtures/ituob-1000/ituob-1000-Q708_SANC.json +252 -0
  42. data/spec/fixtures/ituob-1000/ituob-1000-Q708_SANC.yaml +123 -0
  43. data/spec/fixtures/ituob-1000/ituob-1000-R_SP_LM.V.json +428 -0
  44. data/spec/fixtures/ituob-1000/ituob-1000-R_SP_LM.V.yaml +208 -0
  45. data/spec/fixtures/ituob-1000/ituob-1000-T35_NA.json +621 -0
  46. data/spec/fixtures/ituob-1000/ituob-1000-T35_NA.yaml +317 -0
  47. data/spec/fixtures/ituob-1001/ituob-1001-DP.json +532 -0
  48. data/spec/fixtures/ituob-1001/ituob-1001-DP.yaml +266 -0
  49. data/spec/fixtures/ituob-1001/ituob-1001-E118_IIN.json +1093 -0
  50. data/spec/fixtures/ituob-1001/ituob-1001-E118_IIN.yaml +519 -0
  51. data/spec/fixtures/ituob-1001/ituob-1001-E164_ACN.json +449 -0
  52. data/spec/fixtures/ituob-1001/ituob-1001-E164_ACN.yaml +214 -0
  53. data/spec/fixtures/ituob-1001/ituob-1001-E164_CC.json +271 -0
  54. data/spec/fixtures/ituob-1001/ituob-1001-E164_CC.yaml +136 -0
  55. data/spec/fixtures/ituob-1001/ituob-1001-E212_MNC.json +199 -0
  56. data/spec/fixtures/ituob-1001/ituob-1001-E212_MNC.yaml +99 -0
  57. data/spec/fixtures/ituob-1001/ituob-1001-NNP.json +288 -0
  58. data/spec/fixtures/ituob-1001/ituob-1001-NNP.yaml +152 -0
  59. data/spec/fixtures/ituob-1001/ituob-1001-Q708_ISPC.json +960 -0
  60. data/spec/fixtures/ituob-1001/ituob-1001-Q708_ISPC.yaml +487 -0
  61. data/spec/prosereflect/document_spec.rb +149 -0
  62. data/spec/prosereflect/hard_break_spec.rb +51 -0
  63. data/spec/prosereflect/node_spec.rb +256 -0
  64. data/spec/prosereflect/paragraph_spec.rb +152 -0
  65. data/spec/prosereflect/parser_spec.rb +129 -0
  66. data/spec/prosereflect/table_cell_spec.rb +114 -0
  67. data/spec/prosereflect/table_row_spec.rb +77 -0
  68. data/spec/prosereflect/table_spec.rb +144 -0
  69. data/spec/prosereflect/text_spec.rb +116 -0
  70. data/spec/prosereflect/version_spec.rb +11 -0
  71. data/spec/prosereflect_spec.rb +57 -0
  72. data/spec/spec_helper.rb +21 -0
  73. data/spec/support/matchers.rb +131 -0
  74. data/spec/support/shared_examples.rb +220 -0
  75. metadata +133 -0
@@ -0,0 +1,220 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.shared_examples 'a parsable format' do |format|
4
+ it "parses #{format} content correctly" do
5
+ document = case format
6
+ when :yaml
7
+ Prosereflect::Parser.parse_document(YAML.safe_load(file_content))
8
+ when :json
9
+ Prosereflect::Parser.parse_document(JSON.parse(file_content))
10
+ end
11
+
12
+ expect(document).to be_a(Prosereflect::Document)
13
+ expect(document.content).not_to be_empty
14
+ end
15
+
16
+ it "maintains structure after #{format} round-trip" do
17
+ # Parse the original content
18
+ original_data = case format
19
+ when :yaml
20
+ YAML.safe_load(file_content)
21
+ when :json
22
+ JSON.parse(file_content)
23
+ end
24
+
25
+ # Create a document from the data
26
+ document = Prosereflect::Parser.parse_document(original_data)
27
+
28
+ # Convert back to the original format
29
+ round_trip_data = case format
30
+ when :yaml
31
+ YAML.safe_load(document.to_yaml)
32
+ when :json
33
+ JSON.parse(document.to_json)
34
+ end
35
+
36
+ # Compare the structures
37
+ case format
38
+ when :yaml
39
+ expect(round_trip_data).to be_equivalent_yaml(original_data)
40
+ when :json
41
+ expect(round_trip_data).to be_equivalent_json(original_data)
42
+ end
43
+ end
44
+ end
45
+
46
+ RSpec.shared_examples 'a document with tables' do
47
+ it 'contains at least one table' do
48
+ document = case file_content
49
+ when String
50
+ if file_content.strip.start_with?('{')
51
+ Prosereflect::Parser.parse_document(JSON.parse(file_content))
52
+ else
53
+ Prosereflect::Parser.parse_document(YAML.safe_load(file_content))
54
+ end
55
+ else
56
+ Prosereflect::Parser.parse_document(file_content)
57
+ end
58
+
59
+ expect(document.tables.size).to be > 0
60
+ end
61
+
62
+ it 'has tables with rows and cells' do
63
+ document = case file_content
64
+ when String
65
+ if file_content.strip.start_with?('{')
66
+ Prosereflect::Parser.parse_document(JSON.parse(file_content))
67
+ else
68
+ Prosereflect::Parser.parse_document(YAML.safe_load(file_content))
69
+ end
70
+ else
71
+ Prosereflect::Parser.parse_document(file_content)
72
+ end
73
+
74
+ table = document.tables.first
75
+ expect(table.rows.size).to be > 0
76
+ expect(table.rows.first.cells.size).to be > 0
77
+ end
78
+ end
79
+
80
+ RSpec.shared_examples 'document traversal' do
81
+ it 'can find nodes by type' do
82
+ document = case file_content
83
+ when String
84
+ if file_content.strip.start_with?('{')
85
+ Prosereflect::Parser.parse_document(JSON.parse(file_content))
86
+ else
87
+ Prosereflect::Parser.parse_document(YAML.safe_load(file_content))
88
+ end
89
+ else
90
+ Prosereflect::Parser.parse_document(file_content)
91
+ end
92
+
93
+ expect(document.find_all('table').size).to be > 0
94
+ expect(document.find_all('paragraph').size).to be >= 0
95
+ expect(document.find_all('text').size).to be > 0
96
+ end
97
+ end
98
+
99
+ RSpec.shared_examples 'text content extraction' do
100
+ it 'extracts text content from nodes' do
101
+ document = case file_content
102
+ when String
103
+ if file_content.strip.start_with?('{')
104
+ Prosereflect::Parser.parse_document(JSON.parse(file_content))
105
+ else
106
+ Prosereflect::Parser.parse_document(YAML.safe_load(file_content))
107
+ end
108
+ else
109
+ Prosereflect::Parser.parse_document(file_content)
110
+ end
111
+
112
+ # Get text from the first paragraph or table cell that contains text
113
+ text_container = document.find_first('paragraph') || document.find_first('table_cell')
114
+
115
+ if text_container
116
+ expect(text_container.text_content).to be_a(String)
117
+ expect(text_container.text_content).not_to be_empty if text_container.find_first('text')
118
+ end
119
+ end
120
+ end
121
+
122
+ RSpec.shared_examples 'document creation' do
123
+ it 'creates an empty document' do
124
+ document = Prosereflect::Document.create
125
+ expect(document).to be_a(Prosereflect::Document)
126
+ expect(document.type).to eq('doc')
127
+ expect(document.content).to eq([])
128
+ end
129
+
130
+ it 'creates a document with attributes' do
131
+ attrs = { 'version' => '1.0' }
132
+ document = Prosereflect::Document.create(attrs)
133
+ expect(document.attrs).to eq(attrs)
134
+ end
135
+
136
+ it 'adds paragraphs to a document' do
137
+ document = Prosereflect::Document.create
138
+ paragraph = document.add_paragraph('Test paragraph')
139
+
140
+ expect(document.content.size).to eq(1)
141
+ expect(paragraph).to be_a(Prosereflect::Paragraph)
142
+ expect(paragraph.text_content).to eq('Test paragraph')
143
+ end
144
+
145
+ it 'adds tables to a document' do
146
+ document = Prosereflect::Document.create
147
+ table = document.add_table
148
+
149
+ expect(document.content.size).to eq(1)
150
+ expect(table).to be_a(Prosereflect::Table)
151
+ end
152
+ end
153
+
154
+ # Helper for parsing any format of content
155
+ RSpec.shared_examples 'format parsing' do
156
+ let(:document) do
157
+ case file_content
158
+ when String
159
+ if file_content.strip.start_with?('{')
160
+ Prosereflect::Parser.parse_document(JSON.parse(file_content))
161
+ else
162
+ Prosereflect::Parser.parse_document(YAML.safe_load(file_content))
163
+ end
164
+ else
165
+ Prosereflect::Parser.parse_document(file_content)
166
+ end
167
+ end
168
+ end
169
+
170
+ RSpec.shared_examples 'format round-trip' do |format|
171
+ it "maintains document structure after #{format} round-trip" do
172
+ # Create a rich document
173
+ document = Prosereflect::Document.create
174
+
175
+ # Add paragraph with formatted text
176
+ para = document.add_paragraph('Plain text')
177
+ para.add_text(' bold text', [{ 'type' => 'bold' }])
178
+ para.add_hard_break
179
+ para.add_text('After line break', [{ 'type' => 'italic' }])
180
+
181
+ # Add a table
182
+ table = document.add_table
183
+ table.add_header(['Header 1', 'Header 2', 'Header 3'])
184
+ table.add_row(%w[R1C1 R1C2 R1C3])
185
+ table.add_row(%w[R2C1 R2C2 R2C3])
186
+
187
+ # Add another paragraph
188
+ document.add_paragraph('Concluding paragraph')
189
+
190
+ # Convert to specified format and back
191
+ parsed_doc = round_trip_conversion(document, format)
192
+
193
+ # Verify structure is maintained
194
+ expect(parsed_doc.paragraphs.size).to eq(document.paragraphs.size)
195
+ expect(parsed_doc.tables.size).to eq(document.tables.size)
196
+ expect(parsed_doc.find_all('hard_break').size).to eq(document.find_all('hard_break').size)
197
+
198
+ # Verify table structure
199
+ table_in_parsed = parsed_doc.first_table
200
+ expect(table_in_parsed.rows.size).to eq(document.first_table.rows.size)
201
+ expect(table_in_parsed.header_row.cells.size).to eq(document.first_table.header_row.cells.size)
202
+ end
203
+
204
+ def round_trip_conversion(doc, format)
205
+ case format
206
+ when :yaml
207
+ yaml = doc.to_yaml
208
+ parsed = Prosereflect::Parser.parse_document(YAML.safe_load(yaml))
209
+ # Compare structures
210
+ expect(YAML.safe_load(parsed.to_yaml)).to be_equivalent_yaml(YAML.safe_load(doc.to_yaml))
211
+ parsed
212
+ when :json
213
+ json = doc.to_json
214
+ parsed = Prosereflect::Parser.parse_document(JSON.parse(json))
215
+ # Compare structures
216
+ expect(JSON.parse(parsed.to_json)).to be_equivalent_json(JSON.parse(doc.to_json))
217
+ parsed
218
+ end
219
+ end
220
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prosereflect
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-05-12 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.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.7'
27
+ description:
28
+ email:
29
+ - open.source@ribose.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".github/workflows/rake.yml"
35
+ - ".github/workflows/release.yml"
36
+ - ".gitignore"
37
+ - ".rubocop.yml"
38
+ - ".rubocop_todo.yml"
39
+ - CODE_OF_CONDUCT.md
40
+ - Gemfile
41
+ - README.adoc
42
+ - Rakefile
43
+ - debug_loading.rb
44
+ - lib/prosereflect.rb
45
+ - lib/prosereflect/document.rb
46
+ - lib/prosereflect/hard_break.rb
47
+ - lib/prosereflect/node.rb
48
+ - lib/prosereflect/paragraph.rb
49
+ - lib/prosereflect/parser.rb
50
+ - lib/prosereflect/table.rb
51
+ - lib/prosereflect/table_cell.rb
52
+ - lib/prosereflect/table_row.rb
53
+ - lib/prosereflect/text.rb
54
+ - lib/prosereflect/version.rb
55
+ - prosereflect.gemspec
56
+ - sig/prosemirror.rbs
57
+ - spec/fixtures/ituob-1000/ituob-1000-DP.json
58
+ - spec/fixtures/ituob-1000/ituob-1000-DP.yaml
59
+ - spec/fixtures/ituob-1000/ituob-1000-E118_IIN.json
60
+ - spec/fixtures/ituob-1000/ituob-1000-E118_IIN.yaml
61
+ - spec/fixtures/ituob-1000/ituob-1000-E164_ACN.json
62
+ - spec/fixtures/ituob-1000/ituob-1000-E164_ACN.yaml
63
+ - spec/fixtures/ituob-1000/ituob-1000-E212_MNC.json
64
+ - spec/fixtures/ituob-1000/ituob-1000-E212_MNC.yaml
65
+ - spec/fixtures/ituob-1000/ituob-1000-F32_TDI.json
66
+ - spec/fixtures/ituob-1000/ituob-1000-F32_TDI.yaml
67
+ - spec/fixtures/ituob-1000/ituob-1000-M1400_ICC.json
68
+ - spec/fixtures/ituob-1000/ituob-1000-M1400_ICC.yaml
69
+ - spec/fixtures/ituob-1000/ituob-1000-NNP.json
70
+ - spec/fixtures/ituob-1000/ituob-1000-NNP.yaml
71
+ - spec/fixtures/ituob-1000/ituob-1000-Q708_ISPC.json
72
+ - spec/fixtures/ituob-1000/ituob-1000-Q708_ISPC.yaml
73
+ - spec/fixtures/ituob-1000/ituob-1000-Q708_SANC.json
74
+ - spec/fixtures/ituob-1000/ituob-1000-Q708_SANC.yaml
75
+ - spec/fixtures/ituob-1000/ituob-1000-R_SP_LM.V.json
76
+ - spec/fixtures/ituob-1000/ituob-1000-R_SP_LM.V.yaml
77
+ - spec/fixtures/ituob-1000/ituob-1000-T35_NA.json
78
+ - spec/fixtures/ituob-1000/ituob-1000-T35_NA.yaml
79
+ - spec/fixtures/ituob-1001/ituob-1001-DP.json
80
+ - spec/fixtures/ituob-1001/ituob-1001-DP.yaml
81
+ - spec/fixtures/ituob-1001/ituob-1001-E118_IIN.json
82
+ - spec/fixtures/ituob-1001/ituob-1001-E118_IIN.yaml
83
+ - spec/fixtures/ituob-1001/ituob-1001-E164_ACN.json
84
+ - spec/fixtures/ituob-1001/ituob-1001-E164_ACN.yaml
85
+ - spec/fixtures/ituob-1001/ituob-1001-E164_CC.json
86
+ - spec/fixtures/ituob-1001/ituob-1001-E164_CC.yaml
87
+ - spec/fixtures/ituob-1001/ituob-1001-E212_MNC.json
88
+ - spec/fixtures/ituob-1001/ituob-1001-E212_MNC.yaml
89
+ - spec/fixtures/ituob-1001/ituob-1001-NNP.json
90
+ - spec/fixtures/ituob-1001/ituob-1001-NNP.yaml
91
+ - spec/fixtures/ituob-1001/ituob-1001-Q708_ISPC.json
92
+ - spec/fixtures/ituob-1001/ituob-1001-Q708_ISPC.yaml
93
+ - spec/prosereflect/document_spec.rb
94
+ - spec/prosereflect/hard_break_spec.rb
95
+ - spec/prosereflect/node_spec.rb
96
+ - spec/prosereflect/paragraph_spec.rb
97
+ - spec/prosereflect/parser_spec.rb
98
+ - spec/prosereflect/table_cell_spec.rb
99
+ - spec/prosereflect/table_row_spec.rb
100
+ - spec/prosereflect/table_spec.rb
101
+ - spec/prosereflect/text_spec.rb
102
+ - spec/prosereflect/version_spec.rb
103
+ - spec/prosereflect_spec.rb
104
+ - spec/spec_helper.rb
105
+ - spec/support/matchers.rb
106
+ - spec/support/shared_examples.rb
107
+ homepage: https://github.com/metanorma/prosereflect
108
+ licenses:
109
+ - BSD-2-Clause
110
+ metadata:
111
+ homepage_uri: https://github.com/metanorma/prosereflect
112
+ source_code_uri: https://github.com/metanorma/prosereflect
113
+ bug_tracker_uri: https://github.com/metanorma/prosereflect/issues
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: 2.6.0
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubygems_version: 3.5.22
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Ruby model accessor for prosereflect document trees.
133
+ test_files: []