oasis-etm 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 (52) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/rake.yml +15 -0
  3. data/.github/workflows/release.yml +23 -0
  4. data/.gitignore +13 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +14 -0
  7. data/.rubocop_todo.yml +24 -0
  8. data/CODE_OF_CONDUCT.md +132 -0
  9. data/Gemfile +15 -0
  10. data/README.adoc +152 -0
  11. data/Rakefile +12 -0
  12. data/bin/console +11 -0
  13. data/bin/setup +8 -0
  14. data/lib/oasis/etm/colspec.rb +28 -0
  15. data/lib/oasis/etm/entry.rb +39 -0
  16. data/lib/oasis/etm/row.rb +22 -0
  17. data/lib/oasis/etm/table.rb +31 -0
  18. data/lib/oasis/etm/tbody.rb +20 -0
  19. data/lib/oasis/etm/tcol.rb +28 -0
  20. data/lib/oasis/etm/tgroup.rb +37 -0
  21. data/lib/oasis/etm/thead.rb +20 -0
  22. data/lib/oasis/etm/version.rb +7 -0
  23. data/lib/oasis/etm.rb +13 -0
  24. data/lib/oasis-etm.rb +1 -0
  25. data/oasis-etm.gemspec +35 -0
  26. data/oasis-etm_wrapped.txt +1910 -0
  27. data/sig/oasis/etm.rbs +6 -0
  28. data/spec/fixtures/isosts/isosts_tables.cals.01.xml +16 -0
  29. data/spec/fixtures/isosts/isosts_tables.cals.02.xml +45 -0
  30. data/spec/fixtures/isosts/isosts_tables.cals.03.xml +35 -0
  31. data/spec/fixtures/isosts/isosts_tables.cals.04.xml +34 -0
  32. data/spec/fixtures/isosts/isosts_tables.cals.05.xml +63 -0
  33. data/spec/fixtures/isosts/isosts_tables.cals.06.xml +52 -0
  34. data/spec/fixtures/isosts/isosts_tables.cals.07.xml +33 -0
  35. data/spec/fixtures/isosts/isosts_tables.cals.08.xml +37 -0
  36. data/spec/fixtures/isosts/isosts_tables.cals.09.xml +37 -0
  37. data/spec/fixtures/isosts/isosts_tables.cals.10.xml +44 -0
  38. data/spec/fixtures/isosts/isosts_tables.cals.11.xml +43 -0
  39. data/spec/fixtures/isosts/isosts_tables.cals.12.xml +22 -0
  40. data/spec/fixtures/native/docbook_example.xml +47 -0
  41. data/spec/fixtures/niso-jats/niso-jats-table-wrap.xml +78 -0
  42. data/spec/oasis/etm/colspec_spec.rb +49 -0
  43. data/spec/oasis/etm/entry_spec.rb +103 -0
  44. data/spec/oasis/etm/row_spec.rb +43 -0
  45. data/spec/oasis/etm/table_spec.rb +94 -0
  46. data/spec/oasis/etm/tbody_spec.rb +48 -0
  47. data/spec/oasis/etm/tgroup_spec.rb +97 -0
  48. data/spec/oasis/etm/thead_spec.rb +48 -0
  49. data/spec/oasis/etm_spec.rb +81 -0
  50. data/spec/spec_helper.rb +31 -0
  51. data/spec/support/shared_examples/validation_examples.rb +20 -0
  52. metadata +110 -0
@@ -0,0 +1,1910 @@
1
+ --- START FILE: .github/workflows/rake.yml ---
2
+ # Auto-generated by Cimas: Do not edit it manually!
3
+ # See https://github.com/metanorma/cimas
4
+ name: rake
5
+
6
+ on:
7
+ push:
8
+ branches: [ master, main ]
9
+ tags: [ v* ]
10
+ pull_request:
11
+
12
+ jobs:
13
+ rake:
14
+ uses: metanorma/ci/.github/workflows/generic-rake.yml@main
15
+ secrets:
16
+ pat_token: ${{ secrets.LUTAML_CI_PAT_TOKEN }}
17
+ --- END FILE: .github/workflows/rake.yml ---
18
+ --- START FILE: .github/workflows/release.yml ---
19
+ # Auto-generated by Cimas: Do not edit it manually!
20
+ # See https://github.com/metanorma/cimas
21
+ name: release
22
+
23
+ on:
24
+ workflow_dispatch:
25
+ inputs:
26
+ next_version:
27
+ description: |
28
+ Next release version. Possible values: x.y.z, major, minor, patch or pre|rc|etc
29
+ required: true
30
+ default: 'skip'
31
+ repository_dispatch:
32
+ types: [ do-release ]
33
+
34
+ jobs:
35
+ release:
36
+ uses: metanorma/ci/.github/workflows/rubygems-release.yml@main
37
+ with:
38
+ next_version: ${{ github.event.inputs.next_version }}
39
+ secrets:
40
+ rubygems-api-key: ${{ secrets.LUTAML_CI_RUBYGEMS_API_KEY }}
41
+ pat_token: ${{ secrets.LUTAML_CI_PAT_TOKEN }}
42
+ --- END FILE: .github/workflows/release.yml ---
43
+ --- START FILE: CODE_OF_CONDUCT.md ---
44
+ # Contributor Covenant Code of Conduct
45
+
46
+ ## Our Pledge
47
+
48
+ We as members, contributors, and leaders pledge to make participation in our
49
+ community a harassment-free experience for everyone, regardless of age, body
50
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
51
+ identity and expression, level of experience, education, socio-economic status,
52
+ nationality, personal appearance, race, caste, color, religion, or sexual
53
+ identity and orientation.
54
+
55
+ We pledge to act and interact in ways that contribute to an open, welcoming,
56
+ diverse, inclusive, and healthy community.
57
+
58
+ ## Our Standards
59
+
60
+ Examples of behavior that contributes to a positive environment for our
61
+ community include:
62
+
63
+ * Demonstrating empathy and kindness toward other people
64
+ * Being respectful of differing opinions, viewpoints, and experiences
65
+ * Giving and gracefully accepting constructive feedback
66
+ * Accepting responsibility and apologizing to those affected by our mistakes,
67
+ and learning from the experience
68
+ * Focusing on what is best not just for us as individuals, but for the overall
69
+ community
70
+
71
+ Examples of unacceptable behavior include:
72
+
73
+ * The use of sexualized language or imagery, and sexual attention or advances of
74
+ any kind
75
+ * Trolling, insulting or derogatory comments, and personal or political attacks
76
+ * Public or private harassment
77
+ * Publishing others' private information, such as a physical or email address,
78
+ without their explicit permission
79
+ * Other conduct which could reasonably be considered inappropriate in a
80
+ professional setting
81
+
82
+ ## Enforcement Responsibilities
83
+
84
+ Community leaders are responsible for clarifying and enforcing our standards of
85
+ acceptable behavior and will take appropriate and fair corrective action in
86
+ response to any behavior that they deem inappropriate, threatening, offensive,
87
+ or harmful.
88
+
89
+ Community leaders have the right and responsibility to remove, edit, or reject
90
+ comments, commits, code, wiki edits, issues, and other contributions that are
91
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
92
+ decisions when appropriate.
93
+
94
+ ## Scope
95
+
96
+ This Code of Conduct applies within all community spaces, and also applies when
97
+ an individual is officially representing the community in public spaces.
98
+ Examples of representing our community include using an official email address,
99
+ posting via an official social media account, or acting as an appointed
100
+ representative at an online or offline event.
101
+
102
+ ## Enforcement
103
+
104
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
105
+ reported to the community leaders responsible for enforcement at
106
+ [INSERT CONTACT METHOD].
107
+ All complaints will be reviewed and investigated promptly and fairly.
108
+
109
+ All community leaders are obligated to respect the privacy and security of the
110
+ reporter of any incident.
111
+
112
+ ## Enforcement Guidelines
113
+
114
+ Community leaders will follow these Community Impact Guidelines in determining
115
+ the consequences for any action they deem in violation of this Code of Conduct:
116
+
117
+ ### 1. Correction
118
+
119
+ **Community Impact**: Use of inappropriate language or other behavior deemed
120
+ unprofessional or unwelcome in the community.
121
+
122
+ **Consequence**: A private, written warning from community leaders, providing
123
+ clarity around the nature of the violation and an explanation of why the
124
+ behavior was inappropriate. A public apology may be requested.
125
+
126
+ ### 2. Warning
127
+
128
+ **Community Impact**: A violation through a single incident or series of
129
+ actions.
130
+
131
+ **Consequence**: A warning with consequences for continued behavior. No
132
+ interaction with the people involved, including unsolicited interaction with
133
+ those enforcing the Code of Conduct, for a specified period of time. This
134
+ includes avoiding interactions in community spaces as well as external channels
135
+ like social media. Violating these terms may lead to a temporary or permanent
136
+ ban.
137
+
138
+ ### 3. Temporary Ban
139
+
140
+ **Community Impact**: A serious violation of community standards, including
141
+ sustained inappropriate behavior.
142
+
143
+ **Consequence**: A temporary ban from any sort of interaction or public
144
+ communication with the community for a specified period of time. No public or
145
+ private interaction with the people involved, including unsolicited interaction
146
+ with those enforcing the Code of Conduct, is allowed during this period.
147
+ Violating these terms may lead to a permanent ban.
148
+
149
+ ### 4. Permanent Ban
150
+
151
+ **Community Impact**: Demonstrating a pattern of violation of community
152
+ standards, including sustained inappropriate behavior, harassment of an
153
+ individual, or aggression toward or disparagement of classes of individuals.
154
+
155
+ **Consequence**: A permanent ban from any sort of public interaction within the
156
+ community.
157
+
158
+ ## Attribution
159
+
160
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
161
+ version 2.1, available at
162
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
163
+
164
+ Community Impact Guidelines were inspired by
165
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
166
+
167
+ For answers to common questions about this code of conduct, see the FAQ at
168
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
169
+ [https://www.contributor-covenant.org/translations][translations].
170
+
171
+ [homepage]: https://www.contributor-covenant.org
172
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
173
+ [Mozilla CoC]: https://github.com/mozilla/diversity
174
+ [FAQ]: https://www.contributor-covenant.org/faq
175
+ [translations]: https://www.contributor-covenant.org/translations
176
+ --- END FILE: CODE_OF_CONDUCT.md ---
177
+ --- START FILE: Gemfile ---
178
+ # frozen_string_literal: true
179
+
180
+ source "https://rubygems.org"
181
+
182
+ # Specify your gem's dependencies in oasis-etm.gemspec
183
+ gemspec
184
+
185
+ gem "rake", "~> 13.0"
186
+ gem "rspec", "~> 3.0"
187
+ gem "rubocop", "~> 1.21"
188
+ gem "nokogiri"
189
+ gem "xml-c14n"
190
+ --- END FILE: Gemfile ---
191
+ --- START FILE: README.adoc ---
192
+ = OASIS Exchange Table Model library
193
+
194
+ https://github.com/lutaml/oasis-etm[image:https://img.shields.io/github/stars/lutaml/oasis-etm.svg?style=social[GitHub Stars]]
195
+ https://github.com/lutaml/oasis-etm[image:https://img.shields.io/github/forks/lutaml/oasis-etm.svg?style=social[GitHub Forks]]
196
+ image:https://img.shields.io/github/license/lutaml/oasis-etm.svg[License]
197
+ image:https://img.shields.io/github/actions/workflow/status/lutaml/oasis-etm/test.yml?branch=main[Build Status]
198
+ image:https://img.shields.io/gem/v/oasis-etm.svg[RubyGems Version]
199
+
200
+ == Purpose
201
+
202
+
203
+ == Features
204
+
205
+
206
+ == Installation
207
+
208
+ Add this line to your application's Gemfile:
209
+
210
+ [source,ruby]
211
+ ----
212
+ gem 'oasis-etm'
213
+ ----
214
+
215
+ And then execute:
216
+
217
+ [source,shell]
218
+ ----
219
+ bundle install
220
+ ----
221
+
222
+ Or install it yourself as:
223
+
224
+ [source,shell]
225
+ ----
226
+ gem install oasis-etm
227
+ ----
228
+
229
+ = OASIS Exchange Table Model (ETM) Parser
230
+ :source-highlighter: rouge
231
+ :toc: macro
232
+ :toclevels: 3
233
+
234
+ image:https://img.shields.io/gem/v/oasis-etm.svg[Gem Version, link=https://rubygems.org/gems/oasis-etm]
235
+ image:https://github.com/yourusername/oasis-etm/actions/workflows/test.yml/badge.svg[Build Status, link=https://github.com/yourusername/oasis-etm/actions/workflows/test.yml]
236
+ image:https://img.shields.io/github/license/yourusername/oasis-etm.svg[License, link=https://github.com/yourusername/oasis-etm/blob/main/LICENSE]
237
+
238
+ toc::[]
239
+
240
+ == Purpose
241
+
242
+ Ruby library to parse and create OASIS Exchange Table Model (ETM) formatted tables.
243
+ This library provides a Ruby implementation of the OASIS Technical Resolution TR 9503:1995.
244
+
245
+ == Installation
246
+
247
+ Add this line to your application's Gemfile:
248
+
249
+ [source,ruby]
250
+ ----
251
+ gem 'oasis-etm'
252
+ ----
253
+
254
+ And then execute:
255
+
256
+ [source,sh]
257
+ ----
258
+ $ bundle install
259
+ ----
260
+
261
+ Or install it yourself as:
262
+
263
+ [source,sh]
264
+ ----
265
+ $ gem install oasis-etm
266
+ ----
267
+
268
+
269
+ == Usage
270
+
271
+ === Basic Example
272
+
273
+ [source,ruby]
274
+ ----
275
+ require 'oasis-etm'
276
+
277
+ # Parse an ETM XML file
278
+ table = Oasis::Etm::Table.from_xml(File.read('table.xml'))
279
+
280
+ # Access table attributes
281
+ puts table.frame
282
+ puts table.colsep
283
+ puts table.rowsep
284
+
285
+ # Access table content
286
+ table.tgroups.each do |tgroup|
287
+ tgroup.colspecs.each do |colspec|
288
+ puts "Column #{colspec.colnum}: #{colspec.colwidth}"
289
+ end
290
+ end
291
+
292
+ # Create a new table
293
+ table = Oasis::Etm::Table.new(
294
+ frame: 'all',
295
+ colsep: 1,
296
+ rowsep: 1,
297
+ tgroups: [
298
+ Oasis::Etm::Tgroup.new(
299
+ cols: 3,
300
+ colspecs: [
301
+ Oasis::Etm::Colspec.new(colnum: 1, colwidth: '1*'),
302
+ Oasis::Etm::Colspec.new(colnum: 2, colwidth: '2*'),
303
+ Oasis::Etm::Colspec.new(colnum: 3, colwidth: '1*')
304
+ ]
305
+ )
306
+ ]
307
+ )
308
+
309
+ # Convert to XML
310
+ xml = table.to_xml
311
+ ----
312
+
313
+ === XML Schema
314
+
315
+ The OASIS ETM format follows this basic structure:
316
+
317
+ [source,xml]
318
+ ----
319
+ <table frame="all" colsep="1" rowsep="1">
320
+ <title>Sample Table</title>
321
+ <tgroup cols="3">
322
+ <colspec colnum="1" colwidth="1*"/>
323
+ <colspec colnum="2" colwidth="2*"/>
324
+ <colspec colnum="3" colwidth="1*"/>
325
+ <thead>
326
+ <row>
327
+ <entry>Header 1</entry>
328
+ <entry>Header 2</entry>
329
+ <entry>Header 3</entry>
330
+ </row>
331
+ </thead>
332
+ <tbody>
333
+ <row>
334
+ <entry>Cell 1</entry>
335
+ <entry>Cell 2</entry>
336
+ <entry>Cell 3</entry>
337
+ </row>
338
+ </tbody>
339
+ </tgroup>
340
+ </table>
341
+ ----
342
+
343
+ == Contributing
344
+
345
+ Bug reports and pull requests are welcome. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
346
+
347
+ . Fork it
348
+ . Create your feature branch (`git checkout -b my-new-feature`)
349
+ . Commit your changes (`git commit -am 'Add some feature'`)
350
+ . Push to the branch (`git push origin my-new-feature`)
351
+ . Create new Pull Request
352
+
353
+
354
+ == License and Copyright
355
+
356
+ This project is licensed under the BSD 2-clause License.
357
+ See the link:LICENSE.md[] file for details.
358
+
359
+ Copyright Ribose.
360
+ --- END FILE: README.adoc ---
361
+ --- START FILE: Rakefile ---
362
+ # frozen_string_literal: true
363
+
364
+ require "bundler/gem_tasks"
365
+ require "rspec/core/rake_task"
366
+
367
+ RSpec::Core::RakeTask.new(:spec)
368
+
369
+ require "rubocop/rake_task"
370
+
371
+ RuboCop::RakeTask.new
372
+
373
+ task default: %i[spec rubocop]
374
+ --- END FILE: Rakefile ---
375
+ --- START FILE: lib/oasis-etm.rb ---
376
+ require "oasis/etm"
377
+ --- END FILE: lib/oasis-etm.rb ---
378
+ --- START FILE: lib/oasis/etm.rb ---
379
+ # frozen_string_literal: true
380
+
381
+ require "lutaml/model"
382
+ require_relative "etm/version"
383
+ require_relative "etm/table"
384
+
385
+ module Oasis
386
+ module Etm
387
+ class Error < StandardError; end
388
+
389
+ # Your code goes here...
390
+ end
391
+ end
392
+ --- END FILE: lib/oasis/etm.rb ---
393
+ --- START FILE: lib/oasis/etm/colspec.rb ---
394
+ module Oasis
395
+ module Etm
396
+ class Colspec < Lutaml::Model::Serializable
397
+ # Optional attributes
398
+ attribute :colnum, :integer
399
+ attribute :colname, :string
400
+ attribute :colwidth, :string
401
+ attribute :colsep, :integer, values: [0, 1]
402
+ attribute :rowsep, :integer, values: [0, 1]
403
+ attribute :align, :string, values: %w[left right center justify char]
404
+ attribute :char, :string
405
+ attribute :charoff, :string
406
+
407
+ xml do
408
+ root "colspec"
409
+
410
+ map_attribute "colnum", to: :colnum
411
+ map_attribute "colname", to: :colname
412
+ map_attribute "colwidth", to: :colwidth
413
+ map_attribute "colsep", to: :colsep
414
+ map_attribute "rowsep", to: :rowsep
415
+ map_attribute "align", to: :align
416
+ map_attribute "char", to: :char
417
+ map_attribute "charoff", to: :charoff
418
+ end
419
+ end
420
+ end
421
+ end
422
+ --- END FILE: lib/oasis/etm/colspec.rb ---
423
+ --- START FILE: lib/oasis/etm/entry.rb ---
424
+ module Oasis
425
+ module Etm
426
+ class Entry < Lutaml::Model::Serializable
427
+ # Optional attributes
428
+ attribute :colname, :string
429
+ attribute :namest, :string
430
+ attribute :nameend, :string
431
+ attribute :morerows, :integer
432
+ attribute :colsep, :integer, values: [0, 1]
433
+ attribute :rowsep, :integer, values: [0, 1]
434
+ attribute :align, :string, values: %w[left right center justify char]
435
+ attribute :char, :string
436
+ attribute :charoff, :string
437
+ attribute :valign, :string, values: %w[top middle bottom]
438
+
439
+ # Content
440
+ attribute :content, :string
441
+
442
+ xml do
443
+ root "entry"
444
+
445
+ # Attribute mappings
446
+ map_attribute "colname", to: :colname
447
+ map_attribute "namest", to: :namest
448
+ map_attribute "nameend", to: :nameend
449
+ map_attribute "morerows", to: :morerows
450
+ map_attribute "colsep", to: :colsep
451
+ map_attribute "rowsep", to: :rowsep
452
+ map_attribute "align", to: :align
453
+ map_attribute "char", to: :char
454
+ map_attribute "charoff", to: :charoff
455
+ map_attribute "valign", to: :valign
456
+
457
+ # Content mapping
458
+ map_content to: :content
459
+ end
460
+ end
461
+ end
462
+ end
463
+ --- END FILE: lib/oasis/etm/entry.rb ---
464
+ --- START FILE: lib/oasis/etm/row.rb ---
465
+ require_relative "entry"
466
+
467
+ module Oasis
468
+ module Etm
469
+ class Row < Lutaml::Model::Serializable
470
+ # Optional attributes
471
+ attribute :rowsep, :integer, values: [0, 1]
472
+ attribute :valign, :string, values: %w[top middle bottom]
473
+
474
+ # Content
475
+ attribute :entries, Entry, collection: true
476
+
477
+ xml do
478
+ root "row"
479
+
480
+ map_attribute "rowsep", to: :rowsep
481
+ map_attribute "valign", to: :valign
482
+ map_element "entry", to: :entries
483
+ end
484
+ end
485
+ end
486
+ end
487
+ --- END FILE: lib/oasis/etm/row.rb ---
488
+ --- START FILE: lib/oasis/etm/table.rb ---
489
+ require_relative "tgroup"
490
+
491
+ module Oasis
492
+ module Etm
493
+ class Table < Lutaml::Model::Serializable
494
+ # Table attributes
495
+ attribute :frame, :string, values: %w[top bottom topbot all sides none]
496
+ attribute :colsep, :integer, values: [0, 1]
497
+ attribute :rowsep, :integer, values: [0, 1]
498
+ attribute :pgwide, :integer, values: [0, 1]
499
+
500
+ # Table content
501
+ attribute :title, :string
502
+ attribute :tgroups, Tgroup, collection: true
503
+
504
+ xml do
505
+ root "table"
506
+
507
+ # Frame mappings
508
+ map_attribute "frame", to: :frame
509
+ map_attribute "colsep", to: :colsep
510
+ map_attribute "rowsep", to: :rowsep
511
+ map_attribute "pgwide", to: :pgwide
512
+
513
+ # Content mappings
514
+ map_element "title", to: :title
515
+ map_element "tgroup", to: :tgroups
516
+ end
517
+ end
518
+ end
519
+ end
520
+ --- END FILE: lib/oasis/etm/table.rb ---
521
+ --- START FILE: lib/oasis/etm/tbody.rb ---
522
+ require_relative "row"
523
+
524
+ module Oasis
525
+ module Etm
526
+ class Tbody < Lutaml::Model::Serializable
527
+ # Optional attributes
528
+ attribute :valign, :string, values: %w[top middle bottom]
529
+
530
+ # Content
531
+ attribute :rows, Row, collection: true
532
+
533
+ xml do
534
+ root "tbody"
535
+
536
+ map_attribute "valign", to: :valign
537
+ map_element "row", to: :rows
538
+ end
539
+ end
540
+ end
541
+ end
542
+ --- END FILE: lib/oasis/etm/tbody.rb ---
543
+ --- START FILE: lib/oasis/etm/tcol.rb ---
544
+ module Oasis
545
+ module Etm
546
+ class Colspec < Lutaml::Model::Serializable
547
+ # Optional attributes
548
+ attribute :colnum, :integer
549
+ attribute :colname, :string
550
+ attribute :colwidth, :string
551
+ attribute :colsep, :integer, values: [0, 1]
552
+ attribute :rowsep, :integer, values: [0, 1]
553
+ attribute :align, :string, values: %w[left right center justify char]
554
+ attribute :char, :string
555
+ attribute :charoff, :string
556
+
557
+ xml do
558
+ root "colspec"
559
+
560
+ map_attribute "colnum", to: :colnum
561
+ map_attribute "colname", to: :colname
562
+ map_attribute "colwidth", to: :colwidth
563
+ map_attribute "colsep", to: :colsep
564
+ map_attribute "rowsep", to: :rowsep
565
+ map_attribute "align", to: :align
566
+ map_attribute "char", to: :char
567
+ map_attribute "charoff", to: :charoff
568
+ end
569
+ end
570
+ end
571
+ end
572
+ --- END FILE: lib/oasis/etm/tcol.rb ---
573
+ --- START FILE: lib/oasis/etm/tgroup.rb ---
574
+ require_relative "colspec"
575
+ require_relative "thead"
576
+ require_relative "tbody"
577
+
578
+ module Oasis
579
+ module Etm
580
+ class Tgroup < Lutaml::Model::Serializable
581
+ # Required attributes
582
+ attribute :cols, :integer
583
+
584
+ # Optional attributes
585
+ attribute :colsep, :integer, values: [0, 1]
586
+ attribute :rowsep, :integer, values: [0, 1]
587
+ attribute :align, :string, values: %w[left right center justify char]
588
+
589
+ # Content
590
+ attribute :colspecs, Colspec, collection: true
591
+ attribute :thead, Thead
592
+ attribute :tbody, Tbody
593
+
594
+ xml do
595
+ root "tgroup"
596
+
597
+ # Attribute mappings
598
+ map_attribute "cols", to: :cols
599
+ map_attribute "colsep", to: :colsep
600
+ map_attribute "rowsep", to: :rowsep
601
+ map_attribute "align", to: :align
602
+
603
+ # Content mappings
604
+ map_element "colspec", to: :colspecs
605
+ map_element "thead", to: :thead
606
+ map_element "tbody", to: :tbody
607
+ end
608
+ end
609
+ end
610
+ end
611
+ --- END FILE: lib/oasis/etm/tgroup.rb ---
612
+ --- START FILE: lib/oasis/etm/thead.rb ---
613
+ require_relative "row"
614
+
615
+ module Oasis
616
+ module Etm
617
+ class Thead < Lutaml::Model::Serializable
618
+ # Optional attributes
619
+ attribute :valign, :string, values: %w[top middle bottom]
620
+
621
+ # Content
622
+ attribute :rows, Row, collection: true
623
+
624
+ xml do
625
+ root "thead"
626
+
627
+ map_attribute "valign", to: :valign
628
+ map_element "row", to: :rows
629
+ end
630
+ end
631
+ end
632
+ end
633
+ --- END FILE: lib/oasis/etm/thead.rb ---
634
+ --- START FILE: lib/oasis/etm/version.rb ---
635
+ # frozen_string_literal: true
636
+
637
+ module Oasis
638
+ module Etm
639
+ VERSION = "0.1.0"
640
+ end
641
+ end
642
+ --- END FILE: lib/oasis/etm/version.rb ---
643
+ --- START FILE: oasis-etm.gemspec ---
644
+ # frozen_string_literal: true
645
+
646
+ require_relative "lib/oasis/etm/version"
647
+
648
+ Gem::Specification.new do |spec|
649
+ spec.name = "oasis-etm"
650
+ spec.version = Oasis::Etm::VERSION
651
+ spec.authors = ["Ribose Inc."]
652
+ spec.email = ["open.source@ribose.com"]
653
+
654
+ spec.summary = "Library for OASIS Exchange Table Model"
655
+ spec.description = <<~DESCRIPTION
656
+ Library for manipulation of OASIS Exchange Table Model XML.
657
+ DESCRIPTION
658
+
659
+ spec.homepage = "https://github.com/lutaml/oasis-etm"
660
+ spec.license = "BSD-2-Clause"
661
+
662
+ spec.bindir = "exe"
663
+ spec.require_paths = ["lib"]
664
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
665
+
666
+ # Specify which files should be added to the gem when it is released.
667
+ # The `git ls-files -z` loads the files in the
668
+ # RubyGem that have been added into git.
669
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
670
+ `git ls-files -z`.split("\x0").reject do |f|
671
+ f.match(%r{^(test|features)/})
672
+ end
673
+ end
674
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
675
+
676
+ spec.add_dependency "lutaml-model"
677
+ spec.metadata["rubygems_mfa_required"] = "true"
678
+ end
679
+ --- END FILE: oasis-etm.gemspec ---
680
+ --- START FILE: oasis-etm_wrapped.txt ---
681
+ --- START FILE: .github/workflows/rake.yml ---
682
+ # Auto-generated by Cimas: Do not edit it manually!
683
+ # See https://github.com/metanorma/cimas
684
+ name: rake
685
+
686
+ on:
687
+ push:
688
+ branches: [ master, main ]
689
+ tags: [ v* ]
690
+ pull_request:
691
+
692
+ jobs:
693
+ rake:
694
+ uses: metanorma/ci/.github/workflows/generic-rake.yml@main
695
+ secrets:
696
+ pat_token: ${{ secrets.LUTAML_CI_PAT_TOKEN }}
697
+ --- END FILE: .github/workflows/rake.yml ---
698
+ --- START FILE: .github/workflows/release.yml ---
699
+ # Auto-generated by Cimas: Do not edit it manually!
700
+ # See https://github.com/metanorma/cimas
701
+ name: release
702
+
703
+ on:
704
+ workflow_dispatch:
705
+ inputs:
706
+ next_version:
707
+ description: |
708
+ Next release version. Possible values: x.y.z, major, minor, patch or pre|rc|etc
709
+ required: true
710
+ default: 'skip'
711
+ repository_dispatch:
712
+ types: [ do-release ]
713
+
714
+ jobs:
715
+ release:
716
+ uses: metanorma/ci/.github/workflows/rubygems-release.yml@main
717
+ with:
718
+ next_version: ${{ github.event.inputs.next_version }}
719
+ secrets:
720
+ rubygems-api-key: ${{ secrets.LUTAML_CI_RUBYGEMS_API_KEY }}
721
+ pat_token: ${{ secrets.LUTAML_CI_PAT_TOKEN }}
722
+ --- END FILE: .github/workflows/release.yml ---
723
+ --- START FILE: CODE_OF_CONDUCT.md ---
724
+ # Contributor Covenant Code of Conduct
725
+
726
+ ## Our Pledge
727
+
728
+ We as members, contributors, and leaders pledge to make participation in our
729
+ community a harassment-free experience for everyone, regardless of age, body
730
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
731
+ identity and expression, level of experience, education, socio-economic status,
732
+ nationality, personal appearance, race, caste, color, religion, or sexual
733
+ identity and orientation.
734
+
735
+ We pledge to act and interact in ways that contribute to an open, welcoming,
736
+ diverse, inclusive, and healthy community.
737
+
738
+ ## Our Standards
739
+
740
+ Examples of behavior that contributes to a positive environment for our
741
+ community include:
742
+
743
+ * Demonstrating empathy and kindness toward other people
744
+ * Being respectful of differing opinions, viewpoints, and experiences
745
+ * Giving and gracefully accepting constructive feedback
746
+ * Accepting responsibility and apologizing to those affected by our mistakes,
747
+ and learning from the experience
748
+ * Focusing on what is best not just for us as individuals, but for the overall
749
+ community
750
+
751
+ Examples of unacceptable behavior include:
752
+
753
+ * The use of sexualized language or imagery, and sexual attention or advances of
754
+ any kind
755
+ * Trolling, insulting or derogatory comments, and personal or political attacks
756
+ * Public or private harassment
757
+ * Publishing others' private information, such as a physical or email address,
758
+ without their explicit permission
759
+ * Other conduct which could reasonably be considered inappropriate in a
760
+ professional setting
761
+
762
+ ## Enforcement Responsibilities
763
+
764
+ Community leaders are responsible for clarifying and enforcing our standards of
765
+ acceptable behavior and will take appropriate and fair corrective action in
766
+ response to any behavior that they deem inappropriate, threatening, offensive,
767
+ or harmful.
768
+
769
+ Community leaders have the right and responsibility to remove, edit, or reject
770
+ comments, commits, code, wiki edits, issues, and other contributions that are
771
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
772
+ decisions when appropriate.
773
+
774
+ ## Scope
775
+
776
+ This Code of Conduct applies within all community spaces, and also applies when
777
+ an individual is officially representing the community in public spaces.
778
+ Examples of representing our community include using an official email address,
779
+ posting via an official social media account, or acting as an appointed
780
+ representative at an online or offline event.
781
+
782
+ ## Enforcement
783
+
784
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
785
+ reported to the community leaders responsible for enforcement at
786
+ [INSERT CONTACT METHOD].
787
+ All complaints will be reviewed and investigated promptly and fairly.
788
+
789
+ All community leaders are obligated to respect the privacy and security of the
790
+ reporter of any incident.
791
+
792
+ ## Enforcement Guidelines
793
+
794
+ Community leaders will follow these Community Impact Guidelines in determining
795
+ the consequences for any action they deem in violation of this Code of Conduct:
796
+
797
+ ### 1. Correction
798
+
799
+ **Community Impact**: Use of inappropriate language or other behavior deemed
800
+ unprofessional or unwelcome in the community.
801
+
802
+ **Consequence**: A private, written warning from community leaders, providing
803
+ clarity around the nature of the violation and an explanation of why the
804
+ behavior was inappropriate. A public apology may be requested.
805
+
806
+ ### 2. Warning
807
+
808
+ **Community Impact**: A violation through a single incident or series of
809
+ actions.
810
+
811
+ **Consequence**: A warning with consequences for continued behavior. No
812
+ interaction with the people involved, including unsolicited interaction with
813
+ those enforcing the Code of Conduct, for a specified period of time. This
814
+ includes avoiding interactions in community spaces as well as external channels
815
+ like social media. Violating these terms may lead to a temporary or permanent
816
+ ban.
817
+
818
+ ### 3. Temporary Ban
819
+
820
+ **Community Impact**: A serious violation of community standards, including
821
+ sustained inappropriate behavior.
822
+
823
+ **Consequence**: A temporary ban from any sort of interaction or public
824
+ communication with the community for a specified period of time. No public or
825
+ private interaction with the people involved, including unsolicited interaction
826
+ with those enforcing the Code of Conduct, is allowed during this period.
827
+ Violating these terms may lead to a permanent ban.
828
+
829
+ ### 4. Permanent Ban
830
+
831
+ **Community Impact**: Demonstrating a pattern of violation of community
832
+ standards, including sustained inappropriate behavior, harassment of an
833
+ individual, or aggression toward or disparagement of classes of individuals.
834
+
835
+ **Consequence**: A permanent ban from any sort of public interaction within the
836
+ community.
837
+
838
+ ## Attribution
839
+
840
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
841
+ version 2.1, available at
842
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
843
+
844
+ Community Impact Guidelines were inspired by
845
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
846
+
847
+ For answers to common questions about this code of conduct, see the FAQ at
848
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
849
+ [https://www.contributor-covenant.org/translations][translations].
850
+
851
+ [homepage]: https://www.contributor-covenant.org
852
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
853
+ [Mozilla CoC]: https://github.com/mozilla/diversity
854
+ [FAQ]: https://www.contributor-covenant.org/faq
855
+ [translations]: https://www.contributor-covenant.org/translations
856
+ --- END FILE: CODE_OF_CONDUCT.md ---
857
+ --- START FILE: Gemfile ---
858
+ # frozen_string_literal: true
859
+
860
+ source "https://rubygems.org"
861
+
862
+ # Specify your gem's dependencies in oasis-etm.gemspec
863
+ gemspec
864
+
865
+ gem "rake", "~> 13.0"
866
+ gem "rspec", "~> 3.0"
867
+ gem "rubocop", "~> 1.21"
868
+ gem "nokogiri"
869
+ gem "xml-c14n"
870
+ --- END FILE: Gemfile ---
871
+ --- START FILE: README.adoc ---
872
+ = OASIS Exchange Table Model library
873
+
874
+ https://github.com/lutaml/oasis-etm[image:https://img.shields.io/github/stars/lutaml/oasis-etm.svg?style=social[GitHub Stars]]
875
+ https://github.com/lutaml/oasis-etm[image:https://img.shields.io/github/forks/lutaml/oasis-etm.svg?style=social[GitHub Forks]]
876
+ image:https://img.shields.io/github/license/lutaml/oasis-etm.svg[License]
877
+ image:https://img.shields.io/github/actions/workflow/status/lutaml/oasis-etm/test.yml?branch=main[Build Status]
878
+ image:https://img.shields.io/gem/v/oasis-etm.svg[RubyGems Version]
879
+
880
+ == Purpose
881
+
882
+
883
+ == Features
884
+
885
+
886
+ == Installation
887
+
888
+ Add this line to your application's Gemfile:
889
+
890
+ [source,ruby]
891
+ ----
892
+ gem 'oasis-etm'
893
+ ----
894
+
895
+ And then execute:
896
+
897
+ [source,shell]
898
+ ----
899
+ bundle install
900
+ ----
901
+
902
+ Or install it yourself as:
903
+
904
+ [source,shell]
905
+ ----
906
+ gem install oasis-etm
907
+ ----
908
+
909
+ = OASIS Exchange Table Model (ETM) Parser
910
+ :source-highlighter: rouge
911
+ :toc: macro
912
+ :toclevels: 3
913
+
914
+ image:https://img.shields.io/gem/v/oasis-etm.svg[Gem Version, link=https://rubygems.org/gems/oasis-etm]
915
+ image:https://github.com/yourusername/oasis-etm/actions/workflows/test.yml/badge.svg[Build Status, link=https://github.com/yourusername/oasis-etm/actions/workflows/test.yml]
916
+ image:https://img.shields.io/github/license/yourusername/oasis-etm.svg[License, link=https://github.com/yourusername/oasis-etm/blob/main/LICENSE]
917
+
918
+ toc::[]
919
+
920
+ == Purpose
921
+
922
+ Ruby library to parse and create OASIS Exchange Table Model (ETM) formatted tables.
923
+ This library provides a Ruby implementation of the OASIS Technical Resolution TR 9503:1995.
924
+
925
+ == Installation
926
+
927
+ Add this line to your application's Gemfile:
928
+
929
+ [source,ruby]
930
+ ----
931
+ gem 'oasis-etm'
932
+ ----
933
+
934
+ And then execute:
935
+
936
+ [source,sh]
937
+ ----
938
+ $ bundle install
939
+ ----
940
+
941
+ Or install it yourself as:
942
+
943
+ [source,sh]
944
+ ----
945
+ $ gem install oasis-etm
946
+ ----
947
+
948
+
949
+ == Usage
950
+
951
+ === Basic Example
952
+
953
+ [source,ruby]
954
+ ----
955
+ require 'oasis-etm'
956
+
957
+ # Parse an ETM XML file
958
+ table = Oasis::Etm::Table.from_xml(File.read('table.xml'))
959
+
960
+ # Access table attributes
961
+ puts table.frame
962
+ puts table.colsep
963
+ puts table.rowsep
964
+
965
+ # Access table content
966
+ table.tgroups.each do |tgroup|
967
+ tgroup.colspecs.each do |colspec|
968
+ puts "Column #{colspec.colnum}: #{colspec.colwidth}"
969
+ end
970
+ end
971
+
972
+ # Create a new table
973
+ table = Oasis::Etm::Table.new(
974
+ frame: 'all',
975
+ colsep: 1,
976
+ rowsep: 1,
977
+ tgroups: [
978
+ Oasis::Etm::Tgroup.new(
979
+ cols: 3,
980
+ colspecs: [
981
+ Oasis::Etm::Colspec.new(colnum: 1, colwidth: '1*'),
982
+ Oasis::Etm::Colspec.new(colnum: 2, colwidth: '2*'),
983
+ Oasis::Etm::Colspec.new(colnum: 3, colwidth: '1*')
984
+ ]
985
+ )
986
+ ]
987
+ )
988
+
989
+ # Convert to XML
990
+ xml = table.to_xml
991
+ ----
992
+
993
+ === XML Schema
994
+
995
+ The OASIS ETM format follows this basic structure:
996
+
997
+ [source,xml]
998
+ ----
999
+ <table frame="all" colsep="1" rowsep="1">
1000
+ <title>Sample Table</title>
1001
+ <tgroup cols="3">
1002
+ <colspec colnum="1" colwidth="1*"/>
1003
+ <colspec colnum="2" colwidth="2*"/>
1004
+ <colspec colnum="3" colwidth="1*"/>
1005
+ <thead>
1006
+ <row>
1007
+ <entry>Header 1</entry>
1008
+ <entry>Header 2</entry>
1009
+ <entry>Header 3</entry>
1010
+ </row>
1011
+ </thead>
1012
+ <tbody>
1013
+ <row>
1014
+ <entry>Cell 1</entry>
1015
+ <entry>Cell 2</entry>
1016
+ <entry>Cell 3</entry>
1017
+ </row>
1018
+ </tbody>
1019
+ </tgroup>
1020
+ </table>
1021
+ ----
1022
+
1023
+ == Contributing
1024
+
1025
+ Bug reports and pull requests are welcome. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
1026
+
1027
+ . Fork it
1028
+ . Create your feature branch (`git checkout -b my-new-feature`)
1029
+ . Commit your changes (`git commit -am 'Add some feature'`)
1030
+ . Push to the branch (`git push origin my-new-feature`)
1031
+ . Create new Pull Request
1032
+
1033
+
1034
+ == License and Copyright
1035
+
1036
+ This project is licensed under the BSD 2-clause License.
1037
+ See the link:LICENSE.md[] file for details.
1038
+
1039
+ Copyright Ribose.
1040
+ --- END FILE: README.adoc ---
1041
+ --- START FILE: Rakefile ---
1042
+ # frozen_string_literal: true
1043
+
1044
+ require "bundler/gem_tasks"
1045
+ require "rspec/core/rake_task"
1046
+
1047
+ RSpec::Core::RakeTask.new(:spec)
1048
+
1049
+ require "rubocop/rake_task"
1050
+
1051
+ RuboCop::RakeTask.new
1052
+
1053
+ task default: %i[spec rubocop]
1054
+ --- END FILE: Rakefile ---
1055
+ --- START FILE: lib/oasis-etm.rb ---
1056
+ require "oasis/etm"
1057
+ --- END FILE: lib/oasis-etm.rb ---
1058
+ --- START FILE: lib/oasis/etm.rb ---
1059
+ # frozen_string_literal: true
1060
+
1061
+ require "lutaml/model"
1062
+ require_relative "etm/version"
1063
+ require_relative "etm/table"
1064
+
1065
+ module Oasis
1066
+ module Etm
1067
+ class Error < StandardError; end
1068
+
1069
+ # Your code goes here...
1070
+ end
1071
+ end
1072
+ --- END FILE: lib/oasis/etm.rb ---
1073
+ --- START FILE: lib/oasis/etm/colspec.rb ---
1074
+ module Oasis
1075
+ module Etm
1076
+ class Colspec < Lutaml::Model::Serializable
1077
+ # Optional attributes
1078
+ attribute :colnum, :integer
1079
+ attribute :colname, :string
1080
+ attribute :colwidth, :string
1081
+ attribute :colsep, :integer, values: [0, 1]
1082
+ attribute :rowsep, :integer, values: [0, 1]
1083
+ attribute :align, :string, values: %w[left right center justify char]
1084
+ attribute :char, :string
1085
+ attribute :charoff, :string
1086
+
1087
+ xml do
1088
+ root "colspec"
1089
+
1090
+ map_attribute "colnum", to: :colnum
1091
+ map_attribute "colname", to: :colname
1092
+ map_attribute "colwidth", to: :colwidth
1093
+ map_attribute "colsep", to: :colsep
1094
+ map_attribute "rowsep", to: :rowsep
1095
+ map_attribute "align", to: :align
1096
+ map_attribute "char", to: :char
1097
+ map_attribute "charoff", to: :charoff
1098
+ end
1099
+ end
1100
+ end
1101
+ end
1102
+ --- END FILE: lib/oasis/etm/colspec.rb ---
1103
+ --- START FILE: lib/oasis/etm/entry.rb ---
1104
+ module Oasis
1105
+ module Etm
1106
+ class Entry < Lutaml::Model::Serializable
1107
+ # Optional attributes
1108
+ attribute :colname, :string
1109
+ attribute :namest, :string
1110
+ attribute :nameend, :string
1111
+ attribute :morerows, :integer
1112
+ attribute :colsep, :integer, values: [0, 1]
1113
+ attribute :rowsep, :integer, values: [0, 1]
1114
+ attribute :align, :string, values: %w[left right center justify char]
1115
+ attribute :char, :string
1116
+ attribute :charoff, :string
1117
+ attribute :valign, :string, values: %w[top middle bottom]
1118
+
1119
+ # Content
1120
+ attribute :content, :string
1121
+
1122
+ xml do
1123
+ root "entry"
1124
+
1125
+ # Attribute mappings
1126
+ map_attribute "colname", to: :colname
1127
+ map_attribute "namest", to: :namest
1128
+ map_attribute "nameend", to: :nameend
1129
+ map_attribute "morerows", to: :morerows
1130
+ map_attribute "colsep", to: :colsep
1131
+ map_attribute "rowsep", to: :rowsep
1132
+ map_attribute "align", to: :align
1133
+ map_attribute "char", to: :char
1134
+ map_attribute "charoff", to: :charoff
1135
+ map_attribute "valign", to: :valign
1136
+
1137
+ # Content mapping
1138
+ map_content to: :content
1139
+ end
1140
+ end
1141
+ end
1142
+ end
1143
+ --- END FILE: lib/oasis/etm/entry.rb ---
1144
+ --- START FILE: lib/oasis/etm/row.rb ---
1145
+ require_relative "entry"
1146
+
1147
+ module Oasis
1148
+ module Etm
1149
+ class Row < Lutaml::Model::Serializable
1150
+ # Optional attributes
1151
+ attribute :rowsep, :integer, values: [0, 1]
1152
+ attribute :valign, :string, values: %w[top middle bottom]
1153
+
1154
+ # Content
1155
+ attribute :entries, Entry, collection: true
1156
+
1157
+ xml do
1158
+ root "row"
1159
+
1160
+ map_attribute "rowsep", to: :rowsep
1161
+ map_attribute "valign", to: :valign
1162
+ map_element "entry", to: :entries
1163
+ end
1164
+ end
1165
+ end
1166
+ end
1167
+ --- END FILE: lib/oasis/etm/row.rb ---
1168
+ --- START FILE: lib/oasis/etm/table.rb ---
1169
+ require_relative "tgroup"
1170
+
1171
+ module Oasis
1172
+ module Etm
1173
+ class Table < Lutaml::Model::Serializable
1174
+ # Table attributes
1175
+ attribute :frame, :string, values: %w[top bottom topbot all sides none]
1176
+ attribute :colsep, :integer, values: [0, 1]
1177
+ attribute :rowsep, :integer, values: [0, 1]
1178
+ attribute :pgwide, :integer, values: [0, 1]
1179
+
1180
+ # Table content
1181
+ attribute :title, :string
1182
+ attribute :tgroups, Tgroup, collection: true
1183
+
1184
+ xml do
1185
+ root "table"
1186
+
1187
+ # Frame mappings
1188
+ map_attribute "frame", to: :frame
1189
+ map_attribute "colsep", to: :colsep
1190
+ map_attribute "rowsep", to: :rowsep
1191
+ map_attribute "pgwide", to: :pgwide
1192
+
1193
+ # Content mappings
1194
+ map_element "title", to: :title
1195
+ map_element "tgroup", to: :tgroups
1196
+ end
1197
+ end
1198
+ end
1199
+ end
1200
+ --- END FILE: lib/oasis/etm/table.rb ---
1201
+ --- START FILE: lib/oasis/etm/tbody.rb ---
1202
+ require_relative "row"
1203
+
1204
+ module Oasis
1205
+ module Etm
1206
+ class Tbody < Lutaml::Model::Serializable
1207
+ # Optional attributes
1208
+ attribute :valign, :string, values: %w[top middle bottom]
1209
+
1210
+ # Content
1211
+ attribute :rows, Row, collection: true
1212
+
1213
+ xml do
1214
+ root "tbody"
1215
+
1216
+ map_attribute "valign", to: :valign
1217
+ map_element "row", to: :rows
1218
+ end
1219
+ end
1220
+ end
1221
+ end
1222
+ --- END FILE: lib/oasis/etm/tbody.rb ---
1223
+ --- START FILE: lib/oasis/etm/tcol.rb ---
1224
+ module Oasis
1225
+ module Etm
1226
+ class Colspec < Lutaml::Model::Serializable
1227
+ # Optional attributes
1228
+ attribute :colnum, :integer
1229
+ attribute :colname, :string
1230
+ attribute :colwidth, :string
1231
+ attribute :colsep, :integer, values: [0, 1]
1232
+ attribute :rowsep, :integer, values: [0, 1]
1233
+ attribute :align, :string, values: %w[left right center justify char]
1234
+ attribute :char, :string
1235
+ attribute :charoff, :string
1236
+
1237
+ xml do
1238
+ root "colspec"
1239
+
1240
+ map_attribute "colnum", to: :colnum
1241
+ map_attribute "colname", to: :colname
1242
+ map_attribute "colwidth", to: :colwidth
1243
+ map_attribute "colsep", to: :colsep
1244
+ map_attribute "rowsep", to: :rowsep
1245
+ map_attribute "align", to: :align
1246
+ map_attribute "char", to: :char
1247
+ map_attribute "charoff", to: :charoff
1248
+ end
1249
+ end
1250
+ end
1251
+ end
1252
+ --- END FILE: lib/oasis/etm/tcol.rb ---
1253
+ --- START FILE: lib/oasis/etm/tgroup.rb ---
1254
+ require_relative "colspec"
1255
+ require_relative "thead"
1256
+ require_relative "tbody"
1257
+
1258
+ module Oasis
1259
+ module Etm
1260
+ class Tgroup < Lutaml::Model::Serializable
1261
+ # Required attributes
1262
+ attribute :cols, :integer
1263
+
1264
+ # Optional attributes
1265
+ attribute :colsep, :integer, values: [0, 1]
1266
+ attribute :rowsep, :integer, values: [0, 1]
1267
+ attribute :align, :string, values: %w[left right center justify char]
1268
+
1269
+ # Content
1270
+ attribute :colspecs, Colspec, collection: true
1271
+ attribute :thead, Thead
1272
+ attribute :tbody, Tbody
1273
+
1274
+ xml do
1275
+ root "tgroup"
1276
+
1277
+ # Attribute mappings
1278
+ map_attribute "cols", to: :cols
1279
+ map_attribute "colsep", to: :colsep
1280
+ map_attribute "rowsep", to: :rowsep
1281
+ map_attribute "align", to: :align
1282
+
1283
+ # Content mappings
1284
+ map_element "colspec", to: :colspecs
1285
+ map_element "thead", to: :thead
1286
+ map_element "tbody", to: :tbody
1287
+ end
1288
+ end
1289
+ end
1290
+ end
1291
+ --- END FILE: lib/oasis/etm/tgroup.rb ---
1292
+ --- START FILE: lib/oasis/etm/thead.rb ---
1293
+ require_relative "row"
1294
+
1295
+ module Oasis
1296
+ module Etm
1297
+ class Thead < Lutaml::Model::Serializable
1298
+ # Optional attributes
1299
+ attribute :valign, :string, values: %w[top middle bottom]
1300
+
1301
+ # Content
1302
+ attribute :rows, Row, collection: true
1303
+
1304
+ xml do
1305
+ root "thead"
1306
+
1307
+ map_attribute "valign", to: :valign
1308
+ map_element "row", to: :rows
1309
+ end
1310
+ end
1311
+ end
1312
+ end
1313
+ --- END FILE: lib/oasis/etm/thead.rb ---
1314
+ --- START FILE: lib/oasis/etm/version.rb ---
1315
+ # frozen_string_literal: true
1316
+
1317
+ module Oasis
1318
+ module Etm
1319
+ VERSION = "0.1.0"
1320
+ end
1321
+ end
1322
+ --- END FILE: lib/oasis/etm/version.rb ---
1323
+ --- START FILE: oasis-etm.gemspec ---
1324
+ # frozen_string_literal: true
1325
+
1326
+ require_relative "lib/oasis/etm/version"
1327
+
1328
+ Gem::Specification.new do |spec|
1329
+ spec.name = "oasis-etm"
1330
+ spec.version = Oasis::Etm::VERSION
1331
+ spec.authors = ["Ribose Inc."]
1332
+ spec.email = ["open.source@ribose.com"]
1333
+
1334
+ spec.summary = "Library for OASIS Exchange Table Model"
1335
+ spec.description = <<~DESCRIPTION
1336
+ Library for manipulation of OASIS Exchange Table Model XML.
1337
+ DESCRIPTION
1338
+
1339
+ spec.homepage = "https://github.com/lutaml/oasis-etm"
1340
+ spec.license = "BSD-2-Clause"
1341
+
1342
+ spec.bindir = "exe"
1343
+ spec.require_paths = ["lib"]
1344
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.0.0")
1345
+
1346
+ # Specify which files should be added to the gem when it is released.
1347
+ # The `git ls-files -z` loads the files in the
1348
+ # RubyGem that have been added into git.
1349
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
1350
+ `git ls-files -z`.split("\x0").reject do |f|
1351
+ f.match(%r{^(test|features)/})
1352
+ end
1353
+ end
1354
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
1355
+
1356
+ spec.add_dependency "lutaml-model"
1357
+ spec.metadata["rubygems_mfa_required"] = "true"
1358
+ end
1359
+ --- END FILE: oasis-etm_wrapped.txt ---
1360
+ --- START FILE: sig/oasis/etm.rbs ---
1361
+ module Oasis
1362
+ module Etm
1363
+ VERSION: String
1364
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
1365
+ end
1366
+ end
1367
+ --- END FILE: sig/oasis/etm.rbs ---
1368
+ --- START FILE: spec/oasis/etm/colspec_spec.rb ---
1369
+ RSpec.describe Oasis::Etm::Colspec do
1370
+ let(:xml) do
1371
+ <<~XML
1372
+ <colspec
1373
+ colnum="1"
1374
+ colname="col1"
1375
+ colwidth="1*"
1376
+ colsep="1"
1377
+ rowsep="1"
1378
+ align="center"
1379
+ char="."
1380
+ charoff="50"/>
1381
+ XML
1382
+ end
1383
+
1384
+ describe ".from_xml" do
1385
+ subject(:colspec) { described_class.from_xml(xml) }
1386
+
1387
+ it "parses all attributes" do
1388
+ expect(colspec.colnum).to eq(1)
1389
+ expect(colspec.colname).to eq("col1")
1390
+ expect(colspec.colwidth).to eq("1*")
1391
+ expect(colspec.colsep).to eq(1)
1392
+ expect(colspec.rowsep).to eq(1)
1393
+ expect(colspec.align).to eq("center")
1394
+ expect(colspec.char).to eq(".")
1395
+ expect(colspec.charoff).to eq("50")
1396
+ end
1397
+ end
1398
+
1399
+ describe "#to_xml" do
1400
+ subject(:colspec) do
1401
+ described_class.new(
1402
+ colnum: 1,
1403
+ colname: "col1",
1404
+ colwidth: "1*",
1405
+ colsep: 1,
1406
+ rowsep: 1,
1407
+ align: "center",
1408
+ char: ".",
1409
+ charoff: "50",
1410
+ )
1411
+ end
1412
+
1413
+ it "generates valid XML" do
1414
+ expect(colspec.to_xml).to be_analogous_with(xml)
1415
+ end
1416
+ end
1417
+ end
1418
+ --- END FILE: spec/oasis/etm/colspec_spec.rb ---
1419
+ --- START FILE: spec/oasis/etm/entry_spec.rb ---
1420
+ RSpec.describe Oasis::Etm::Entry do
1421
+ let(:xml) do
1422
+ <<~XML
1423
+ <entry
1424
+ colname="col1"
1425
+ namest="col1"
1426
+ nameend="col2"
1427
+ morerows="1"
1428
+ colsep="1"
1429
+ rowsep="1"
1430
+ align="center"
1431
+ char="."
1432
+ charoff="50"
1433
+ valign="middle">Cell content</entry>
1434
+ XML
1435
+ end
1436
+
1437
+ describe ".from_xml" do
1438
+ subject(:entry) { described_class.from_xml(xml) }
1439
+
1440
+ it "parses attributes" do
1441
+ expect(entry.colname).to eq("col1")
1442
+ expect(entry.namest).to eq("col1")
1443
+ expect(entry.nameend).to eq("col2")
1444
+ expect(entry.morerows).to eq(1)
1445
+ expect(entry.colsep).to eq(1)
1446
+ expect(entry.rowsep).to eq(1)
1447
+ expect(entry.align).to eq("center")
1448
+ expect(entry.char).to eq(".")
1449
+ expect(entry.charoff).to eq("50")
1450
+ expect(entry.valign).to eq("middle")
1451
+ end
1452
+
1453
+ it "parses content" do
1454
+ expect(entry.content).to eq("Cell content")
1455
+ end
1456
+ end
1457
+
1458
+ describe "#to_xml" do
1459
+ subject(:entry) do
1460
+ described_class.new(
1461
+ colname: "col1",
1462
+ namest: "col1",
1463
+ nameend: "col2",
1464
+ morerows: 1,
1465
+ colsep: 1,
1466
+ rowsep: 1,
1467
+ align: "center",
1468
+ char: ".",
1469
+ charoff: "50",
1470
+ valign: "middle",
1471
+ content: "Cell content",
1472
+ )
1473
+ end
1474
+
1475
+ it "generates valid XML" do
1476
+ expect(entry.to_xml).to be_analogous_with(xml)
1477
+ end
1478
+ end
1479
+
1480
+ context "with validation" do
1481
+ it "validates align values" do
1482
+ expect {
1483
+ described_class.new(align: "invalid")
1484
+ }.to raise_error(Lutaml::Model::ValidationError)
1485
+ end
1486
+
1487
+ it "validates valign values" do
1488
+ expect {
1489
+ described_class.new(valign: "invalid")
1490
+ }.to raise_error(Lutaml::Model::ValidationError)
1491
+ end
1492
+
1493
+ it "validates colsep values" do
1494
+ expect {
1495
+ described_class.new(colsep: 2)
1496
+ }.to raise_error(Lutaml::Model::ValidationError)
1497
+ end
1498
+
1499
+ it "validates rowsep values" do
1500
+ expect {
1501
+ described_class.new(rowsep: 2)
1502
+ }.to raise_error(Lutaml::Model::ValidationError)
1503
+ end
1504
+ end
1505
+ end
1506
+ --- END FILE: spec/oasis/etm/entry_spec.rb ---
1507
+ --- START FILE: spec/oasis/etm/row_spec.rb ---
1508
+ RSpec.describe Oasis::Etm::Row do
1509
+ let(:xml) do
1510
+ <<~XML
1511
+ <row rowsep="1" valign="middle">
1512
+ <entry>Cell 1</entry>
1513
+ <entry>Cell 2</entry>
1514
+ <entry>Cell 3</entry>
1515
+ </row>
1516
+ XML
1517
+ end
1518
+
1519
+ describe ".from_xml" do
1520
+ subject(:row) { described_class.from_xml(xml) }
1521
+
1522
+ it "parses attributes" do
1523
+ expect(row.rowsep).to eq(1)
1524
+ expect(row.valign).to eq("middle")
1525
+ end
1526
+
1527
+ it "parses entries" do
1528
+ expect(row.entries.size).to eq(3)
1529
+ expect(row.entries.map(&:content)).to eq(["Cell 1", "Cell 2", "Cell 3"])
1530
+ end
1531
+ end
1532
+
1533
+ describe "#to_xml" do
1534
+ subject(:row) do
1535
+ described_class.new(
1536
+ rowsep: 1,
1537
+ valign: "middle",
1538
+ entries: [
1539
+ Oasis::Etm::Entry.new(content: "Cell 1"),
1540
+ Oasis::Etm::Entry.new(content: "Cell 2"),
1541
+ Oasis::Etm::Entry.new(content: "Cell 3"),
1542
+ ],
1543
+ )
1544
+ end
1545
+
1546
+ it "generates valid XML" do
1547
+ expect(row.to_xml).to be_analogous_with(xml)
1548
+ end
1549
+ end
1550
+ end
1551
+ --- END FILE: spec/oasis/etm/row_spec.rb ---
1552
+ --- START FILE: spec/oasis/etm/table_spec.rb ---
1553
+ RSpec.describe Oasis::Etm::Table do
1554
+ let(:xml) do
1555
+ <<~XML
1556
+ <table frame="all" colsep="1" rowsep="1">
1557
+ <title>Sample Table</title>
1558
+ <tgroup cols="3">
1559
+ <colspec colnum="1" colwidth="1*"/>
1560
+ <colspec colnum="2" colwidth="2*"/>
1561
+ <colspec colnum="3" colwidth="1*"/>
1562
+ <thead>
1563
+ <row>
1564
+ <entry>Header 1</entry>
1565
+ <entry>Header 2</entry>
1566
+ <entry>Header 3</entry>
1567
+ </row>
1568
+ </thead>
1569
+ <tbody>
1570
+ <row>
1571
+ <entry>Cell 1</entry>
1572
+ <entry>Cell 2</entry>
1573
+ <entry>Cell 3</entry>
1574
+ </row>
1575
+ </tbody>
1576
+ </tgroup>
1577
+ </table>
1578
+ XML
1579
+ end
1580
+
1581
+ describe ".from_xml" do
1582
+ subject(:table) { described_class.from_xml(xml) }
1583
+
1584
+ it "parses table attributes" do
1585
+ expect(table.frame).to eq("all")
1586
+ expect(table.colsep).to eq(1)
1587
+ expect(table.rowsep).to eq(1)
1588
+ end
1589
+
1590
+ it "parses title" do
1591
+ expect(table.title).to eq("Sample Table")
1592
+ end
1593
+
1594
+ it "parses tgroup" do
1595
+ expect(table.tgroups.size).to eq(1)
1596
+ expect(table.tgroups.first.cols).to eq(3)
1597
+ end
1598
+ end
1599
+
1600
+ describe "#to_xml" do
1601
+ subject(:table) do
1602
+ described_class.new(
1603
+ frame: "all",
1604
+ colsep: 1,
1605
+ rowsep: 1,
1606
+ title: "Sample Table",
1607
+ tgroups: [
1608
+ Oasis::Etm::Tgroup.new(
1609
+ cols: 3,
1610
+ colspecs: [
1611
+ Oasis::Etm::Colspec.new(colnum: 1, colwidth: "1*"),
1612
+ Oasis::Etm::Colspec.new(colnum: 2, colwidth: "2*"),
1613
+ Oasis::Etm::Colspec.new(colnum: 3, colwidth: "1*"),
1614
+ ],
1615
+ thead: Oasis::Etm::Thead.new(
1616
+ rows: [
1617
+ Oasis::Etm::Row.new(
1618
+ entries: [
1619
+ Oasis::Etm::Entry.new(content: "Header 1"),
1620
+ Oasis::Etm::Entry.new(content: "Header 2"),
1621
+ Oasis::Etm::Entry.new(content: "Header 3"),
1622
+ ],
1623
+ ),
1624
+ ],
1625
+ ),
1626
+ tbody: Oasis::Etm::Tbody.new(
1627
+ rows: [
1628
+ Oasis::Etm::Row.new(
1629
+ entries: [
1630
+ Oasis::Etm::Entry.new(content: "Cell 1"),
1631
+ Oasis::Etm::Entry.new(content: "Cell 2"),
1632
+ Oasis::Etm::Entry.new(content: "Cell 3"),
1633
+ ],
1634
+ ),
1635
+ ],
1636
+ ),
1637
+ ),
1638
+ ],
1639
+ )
1640
+ end
1641
+
1642
+ it "generates valid XML" do
1643
+ expect(table.to_xml).to be_analogous_with(xml)
1644
+ end
1645
+ end
1646
+ end
1647
+ --- END FILE: spec/oasis/etm/table_spec.rb ---
1648
+ --- START FILE: spec/oasis/etm/tbody_spec.rb ---
1649
+ RSpec.describe Oasis::Etm::Tbody do
1650
+ let(:xml) do
1651
+ <<~XML
1652
+ <tbody valign="top">
1653
+ <row>
1654
+ <entry>Cell 1</entry>
1655
+ <entry>Cell 2</entry>
1656
+ <entry>Cell 3</entry>
1657
+ </row>
1658
+ </tbody>
1659
+ XML
1660
+ end
1661
+
1662
+ describe ".from_xml" do
1663
+ subject(:tbody) { described_class.from_xml(xml) }
1664
+
1665
+ it "parses valign attribute" do
1666
+ expect(tbody.valign).to eq("top")
1667
+ end
1668
+
1669
+ it "parses rows" do
1670
+ expect(tbody.rows.size).to eq(1)
1671
+ expect(tbody.rows.first.entries.size).to eq(3)
1672
+ expect(tbody.rows.first.entries.first.content).to eq("Cell 1")
1673
+ end
1674
+ end
1675
+
1676
+ describe "#to_xml" do
1677
+ subject(:tbody) do
1678
+ described_class.new(
1679
+ valign: "top",
1680
+ rows: [
1681
+ Oasis::Etm::Row.new(
1682
+ entries: [
1683
+ Oasis::Etm::Entry.new(content: "Cell 1"),
1684
+ Oasis::Etm::Entry.new(content: "Cell 2"),
1685
+ Oasis::Etm::Entry.new(content: "Cell 3"),
1686
+ ],
1687
+ ),
1688
+ ],
1689
+ )
1690
+ end
1691
+
1692
+ it "generates valid XML" do
1693
+ expect(tbody.to_xml).to be_analogous_with(xml)
1694
+ end
1695
+ end
1696
+ end
1697
+ --- END FILE: spec/oasis/etm/tbody_spec.rb ---
1698
+ --- START FILE: spec/oasis/etm/tgroup_spec.rb ---
1699
+ RSpec.describe Oasis::Etm::Tgroup do
1700
+ let(:xml) do
1701
+ <<~XML
1702
+ <tgroup cols="3" colsep="1" rowsep="1" align="center">
1703
+ <colspec colnum="1" colwidth="1*"/>
1704
+ <colspec colnum="2" colwidth="2*"/>
1705
+ <colspec colnum="3" colwidth="1*"/>
1706
+ <thead>
1707
+ <row>
1708
+ <entry>Header 1</entry>
1709
+ <entry>Header 2</entry>
1710
+ <entry>Header 3</entry>
1711
+ </row>
1712
+ </thead>
1713
+ <tbody>
1714
+ <row>
1715
+ <entry>Cell 1</entry>
1716
+ <entry>Cell 2</entry>
1717
+ <entry>Cell 3</entry>
1718
+ </row>
1719
+ </tbody>
1720
+ </tgroup>
1721
+ XML
1722
+ end
1723
+
1724
+ describe ".from_xml" do
1725
+ subject(:tgroup) { described_class.from_xml(xml) }
1726
+
1727
+ it "parses required attributes" do
1728
+ expect(tgroup.cols).to eq(3)
1729
+ end
1730
+
1731
+ it "parses optional attributes" do
1732
+ expect(tgroup.colsep).to eq(1)
1733
+ expect(tgroup.rowsep).to eq(1)
1734
+ expect(tgroup.align).to eq("center")
1735
+ end
1736
+
1737
+ it "parses colspecs" do
1738
+ expect(tgroup.colspecs.size).to eq(3)
1739
+ expect(tgroup.colspecs.first.colnum).to eq(1)
1740
+ expect(tgroup.colspecs.first.colwidth).to eq("1*")
1741
+ end
1742
+
1743
+ it "parses thead" do
1744
+ expect(tgroup.thead).to be_a(Oasis::Etm::Thead)
1745
+ expect(tgroup.thead.rows.size).to eq(1)
1746
+ end
1747
+
1748
+ it "parses tbody" do
1749
+ expect(tgroup.tbody).to be_a(Oasis::Etm::Tbody)
1750
+ expect(tgroup.tbody.rows.size).to eq(1)
1751
+ end
1752
+ end
1753
+
1754
+ describe "#to_xml" do
1755
+ subject(:tgroup) do
1756
+ described_class.new(
1757
+ cols: 3,
1758
+ colsep: 1,
1759
+ rowsep: 1,
1760
+ align: "center",
1761
+ colspecs: [
1762
+ Oasis::Etm::Colspec.new(colnum: 1, colwidth: "1*"),
1763
+ Oasis::Etm::Colspec.new(colnum: 2, colwidth: "2*"),
1764
+ Oasis::Etm::Colspec.new(colnum: 3, colwidth: "1*"),
1765
+ ],
1766
+ thead: Oasis::Etm::Thead.new(
1767
+ rows: [
1768
+ Oasis::Etm::Row.new(
1769
+ entries: [
1770
+ Oasis::Etm::Entry.new(content: "Header 1"),
1771
+ Oasis::Etm::Entry.new(content: "Header 2"),
1772
+ Oasis::Etm::Entry.new(content: "Header 3"),
1773
+ ],
1774
+ ),
1775
+ ],
1776
+ ),
1777
+ tbody: Oasis::Etm::Tbody.new(
1778
+ rows: [
1779
+ Oasis::Etm::Row.new(
1780
+ entries: [
1781
+ Oasis::Etm::Entry.new(content: "Cell 1"),
1782
+ Oasis::Etm::Entry.new(content: "Cell 2"),
1783
+ Oasis::Etm::Entry.new(content: "Cell 3"),
1784
+ ],
1785
+ ),
1786
+ ],
1787
+ ),
1788
+ )
1789
+ end
1790
+
1791
+ it "generates valid XML" do
1792
+ expect(tgroup.to_xml).to be_analogous_with(xml)
1793
+ end
1794
+ end
1795
+ end
1796
+ --- END FILE: spec/oasis/etm/tgroup_spec.rb ---
1797
+ --- START FILE: spec/oasis/etm/thead_spec.rb ---
1798
+ RSpec.describe Oasis::Etm::Thead do
1799
+ let(:xml) do
1800
+ <<~XML
1801
+ <thead valign="middle">
1802
+ <row>
1803
+ <entry>Header 1</entry>
1804
+ <entry>Header 2</entry>
1805
+ <entry>Header 3</entry>
1806
+ </row>
1807
+ </thead>
1808
+ XML
1809
+ end
1810
+
1811
+ describe ".from_xml" do
1812
+ subject(:thead) { described_class.from_xml(xml) }
1813
+
1814
+ it "parses valign attribute" do
1815
+ expect(thead.valign).to eq("middle")
1816
+ end
1817
+
1818
+ it "parses rows" do
1819
+ expect(thead.rows.size).to eq(1)
1820
+ expect(thead.rows.first.entries.size).to eq(3)
1821
+ expect(thead.rows.first.entries.first.content).to eq("Header 1")
1822
+ end
1823
+ end
1824
+
1825
+ describe "#to_xml" do
1826
+ subject(:thead) do
1827
+ described_class.new(
1828
+ valign: "middle",
1829
+ rows: [
1830
+ Oasis::Etm::Row.new(
1831
+ entries: [
1832
+ Oasis::Etm::Entry.new(content: "Header 1"),
1833
+ Oasis::Etm::Entry.new(content: "Header 2"),
1834
+ Oasis::Etm::Entry.new(content: "Header 3"),
1835
+ ],
1836
+ ),
1837
+ ],
1838
+ )
1839
+ end
1840
+
1841
+ it "generates valid XML" do
1842
+ expect(thead.to_xml).to be_analogous_with(xml)
1843
+ end
1844
+ end
1845
+ end
1846
+ --- END FILE: spec/oasis/etm/thead_spec.rb ---
1847
+ --- START FILE: spec/oasis/etm_spec.rb ---
1848
+ # frozen_string_literal: true
1849
+
1850
+ RSpec.describe Oasis::Etm do
1851
+ it "has a version number" do
1852
+ expect(Oasis::Etm::VERSION).not_to be nil
1853
+ end
1854
+ end
1855
+ --- END FILE: spec/oasis/etm_spec.rb ---
1856
+ --- START FILE: spec/spec_helper.rb ---
1857
+ # frozen_string_literal: true
1858
+
1859
+ require "oasis-etm"
1860
+ require "nokogiri"
1861
+ require "xml-c14n"
1862
+
1863
+ # Require all support files
1864
+ Dir[File.join(__dir__, "support", "**", "*.rb")].sort.each { |f| require f }
1865
+
1866
+ RSpec.configure do |config|
1867
+ # Enable flags like --only-failures and --next-failure
1868
+ config.example_status_persistence_file_path = ".rspec_status"
1869
+
1870
+ # Disable RSpec exposing methods globally on `Module` and `main`
1871
+ config.disable_monkey_patching!
1872
+
1873
+ config.expect_with :rspec do |c|
1874
+ c.syntax = :expect
1875
+ end
1876
+ end
1877
+
1878
+ require "lutaml/model"
1879
+ require "lutaml/model/xml_adapter/nokogiri_adapter"
1880
+ require "lutaml/model/json_adapter/standard_json_adapter"
1881
+ require "lutaml/model/yaml_adapter/standard_yaml_adapter"
1882
+
1883
+ Lutaml::Model::Config.configure do |config|
1884
+ config.xml_adapter = Lutaml::Model::XmlAdapter::NokogiriAdapter
1885
+ config.json_adapter = Lutaml::Model::JsonAdapter::StandardJsonAdapter
1886
+ config.yaml_adapter = Lutaml::Model::YamlAdapter::StandardYamlAdapter
1887
+ end
1888
+ --- END FILE: spec/spec_helper.rb ---
1889
+ --- START FILE: spec/support/shared_examples/validation_examples.rb ---
1890
+ # spec/support/shared_examples/validation_examples.rb
1891
+ RSpec.shared_examples "validates attributes" do |attributes|
1892
+ attributes.each do |attribute, valid_values|
1893
+ context "with #{attribute}" do
1894
+ it "accepts valid values" do
1895
+ valid_values.each do |value|
1896
+ expect {
1897
+ described_class.new(attribute => value)
1898
+ }.not_to raise_error
1899
+ end
1900
+ end
1901
+
1902
+ it "rejects invalid values" do
1903
+ expect {
1904
+ described_class.new(attribute => "invalid")
1905
+ }.to raise_error(Lutaml::Model::ValidationError)
1906
+ end
1907
+ end
1908
+ end
1909
+ end
1910
+ --- END FILE: spec/support/shared_examples/validation_examples.rb ---