omml 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +22 -0
  3. data/.github/workflows/release.yml +23 -0
  4. data/.gitignore +2 -0
  5. data/.rubocop.yml +25 -0
  6. data/.rubocop_todo.yml +19 -0
  7. data/CLAUDE.md +64 -0
  8. data/Gemfile +11 -7
  9. data/README.adoc +222 -4
  10. data/Rakefile +3 -3
  11. data/bin/console +3 -3
  12. data/lib/omml/configuration/adapter.rb +21 -0
  13. data/lib/omml/configuration/context_registry.rb +131 -0
  14. data/lib/omml/configuration/model_registry.rb +60 -0
  15. data/lib/omml/configuration/type_resolver.rb +47 -0
  16. data/lib/omml/configuration.rb +25 -0
  17. data/lib/omml/errors/base_error.rb +8 -0
  18. data/lib/omml/errors/invalid_xml_error.rb +8 -0
  19. data/lib/omml/errors/missing_context_error.rb +23 -0
  20. data/lib/omml/errors/root_element_not_found_error.rb +11 -0
  21. data/lib/omml/errors/unsupported_root_element_error.rb +11 -0
  22. data/lib/omml/errors/xml_adapter_not_configured_error.rb +11 -0
  23. data/lib/omml/errors.rb +15 -0
  24. data/lib/omml/models/ct_acc.rb +23 -0
  25. data/lib/omml/models/ct_acc_pr.rb +23 -0
  26. data/lib/omml/models/ct_anchor.rb +60 -0
  27. data/lib/omml/models/ct_attr.rb +23 -0
  28. data/lib/omml/models/ct_bar.rb +23 -0
  29. data/lib/omml/models/ct_bar_pr.rb +23 -0
  30. data/lib/omml/models/ct_bookmark.rb +19 -0
  31. data/lib/omml/models/ct_bookmark_range.rb +21 -0
  32. data/lib/omml/models/ct_border.rb +35 -0
  33. data/lib/omml/models/ct_border_box.rb +24 -0
  34. data/lib/omml/models/ct_border_box_pr.rb +37 -0
  35. data/lib/omml/models/ct_box.rb +23 -0
  36. data/lib/omml/models/ct_box_pr.rb +31 -0
  37. data/lib/omml/models/ct_br.rb +21 -0
  38. data/lib/omml/models/ct_break_bin.rb +19 -0
  39. data/lib/omml/models/ct_break_bin_sub.rb +19 -0
  40. data/lib/omml/models/ct_calendar_type.rb +19 -0
  41. data/lib/omml/models/ct_char.rb +19 -0
  42. data/lib/omml/models/ct_color.rb +25 -0
  43. data/lib/omml/models/ct_control.rb +23 -0
  44. data/lib/omml/models/ct_ctrl_pr.rb +21 -0
  45. data/lib/omml/models/ct_custom_xml_pr.rb +23 -0
  46. data/lib/omml/models/ct_custom_xml_run.rb +27 -0
  47. data/lib/omml/models/ct_d.rb +23 -0
  48. data/lib/omml/models/ct_d_pr.rb +34 -0
  49. data/lib/omml/models/ct_data_binding.rb +23 -0
  50. data/lib/omml/models/ct_decimal_number.rb +19 -0
  51. data/lib/omml/models/ct_drawing.rb +23 -0
  52. data/lib/omml/models/ct_east_asian_layout.rb +27 -0
  53. data/lib/omml/models/ct_effect_extent.rb +25 -0
  54. data/lib/omml/models/ct_em.rb +19 -0
  55. data/lib/omml/models/ct_empty.rb +15 -0
  56. data/lib/omml/models/ct_eq_arr.rb +23 -0
  57. data/lib/omml/models/ct_eq_arr_pr.rb +31 -0
  58. data/lib/omml/models/ct_f.rb +25 -0
  59. data/lib/omml/models/ct_f_pr.rb +23 -0
  60. data/lib/omml/models/ct_f_type.rb +19 -0
  61. data/lib/omml/models/ct_ff_check_box.rb +29 -0
  62. data/lib/omml/models/ct_ff_data.rb +41 -0
  63. data/lib/omml/models/ct_ff_help_text.rb +21 -0
  64. data/lib/omml/models/ct_ff_name.rb +19 -0
  65. data/lib/omml/models/ct_ff_status_text.rb +21 -0
  66. data/lib/omml/models/ct_ff_text_input.rb +27 -0
  67. data/lib/omml/models/ct_ff_text_type.rb +19 -0
  68. data/lib/omml/models/ct_ffdd_list.rb +25 -0
  69. data/lib/omml/models/ct_fit_text.rb +21 -0
  70. data/lib/omml/models/ct_fld_char.rb +32 -0
  71. data/lib/omml/models/ct_fonts.rb +35 -0
  72. data/lib/omml/models/ct_ftn_edn_ref.rb +21 -0
  73. data/lib/omml/models/ct_func.rb +26 -0
  74. data/lib/omml/models/ct_func_pr.rb +21 -0
  75. data/lib/omml/models/ct_graphical_object.rb +21 -0
  76. data/lib/omml/models/ct_graphical_object_data.rb +19 -0
  77. data/lib/omml/models/ct_graphical_object_frame_locking.rb +33 -0
  78. data/lib/omml/models/ct_group_chr.rb +23 -0
  79. data/lib/omml/models/ct_group_chr_pr.rb +27 -0
  80. data/lib/omml/models/ct_highlight.rb +19 -0
  81. data/lib/omml/models/ct_hps_measure.rb +19 -0
  82. data/lib/omml/models/ct_hyperlink.rb +31 -0
  83. data/lib/omml/models/ct_inline.rb +38 -0
  84. data/lib/omml/models/ct_integer2.rb +19 -0
  85. data/lib/omml/models/ct_integer255.rb +19 -0
  86. data/lib/omml/models/ct_lang.rb +19 -0
  87. data/lib/omml/models/ct_language.rb +23 -0
  88. data/lib/omml/models/ct_lim_loc.rb +19 -0
  89. data/lib/omml/models/ct_lim_low.rb +26 -0
  90. data/lib/omml/models/ct_lim_low_pr.rb +21 -0
  91. data/lib/omml/models/ct_lim_upp.rb +25 -0
  92. data/lib/omml/models/ct_lim_upp_pr.rb +21 -0
  93. data/lib/omml/models/ct_lock.rb +19 -0
  94. data/lib/omml/models/ct_m.rb +23 -0
  95. data/lib/omml/models/ct_m_pr.rb +37 -0
  96. data/lib/omml/models/ct_macro_name.rb +19 -0
  97. data/lib/omml/models/ct_manual_break.rb +19 -0
  98. data/lib/omml/models/ct_markup.rb +19 -0
  99. data/lib/omml/models/ct_markup_range.rb +19 -0
  100. data/lib/omml/models/ct_math_pr.rb +53 -0
  101. data/lib/omml/models/ct_mc.rb +21 -0
  102. data/lib/omml/models/ct_mc_pr.rb +23 -0
  103. data/lib/omml/models/ct_mcs.rb +21 -0
  104. data/lib/omml/models/ct_move_bookmark.rb +21 -0
  105. data/lib/omml/models/ct_mr.rb +21 -0
  106. data/lib/omml/models/ct_nary.rb +27 -0
  107. data/lib/omml/models/ct_nary_pr.rb +31 -0
  108. data/lib/omml/models/ct_non_visual_drawing_props.rb +33 -0
  109. data/lib/omml/models/ct_non_visual_graphic_frame_properties.rb +24 -0
  110. data/lib/omml/models/ct_o_math.rb +22 -0
  111. data/lib/omml/models/ct_o_math_arg.rb +28 -0
  112. data/lib/omml/models/ct_o_math_arg_pr.rb +21 -0
  113. data/lib/omml/models/ct_o_math_jc.rb +19 -0
  114. data/lib/omml/models/ct_o_math_para.rb +26 -0
  115. data/lib/omml/models/ct_o_math_para_pr.rb +21 -0
  116. data/lib/omml/models/ct_object.rb +25 -0
  117. data/lib/omml/models/ct_office_art_extension.rb +19 -0
  118. data/lib/omml/models/ct_office_art_extension_list.rb +21 -0
  119. data/lib/omml/models/ct_on_off.rb +19 -0
  120. data/lib/omml/models/ct_p_tab.rb +23 -0
  121. data/lib/omml/models/ct_perm.rb +21 -0
  122. data/lib/omml/models/ct_perm_start.rb +25 -0
  123. data/lib/omml/models/ct_phant.rb +23 -0
  124. data/lib/omml/models/ct_phant_pr.rb +31 -0
  125. data/lib/omml/models/ct_picture.rb +23 -0
  126. data/lib/omml/models/ct_picture_base.rb +15 -0
  127. data/lib/omml/models/ct_placeholder.rb +21 -0
  128. data/lib/omml/models/ct_point2_d.rb +21 -0
  129. data/lib/omml/models/ct_pos_h.rb +27 -0
  130. data/lib/omml/models/ct_pos_v.rb +27 -0
  131. data/lib/omml/models/ct_positive_size2_d.rb +21 -0
  132. data/lib/omml/models/ct_proof_err.rb +19 -0
  133. data/lib/omml/models/ct_r.rb +27 -0
  134. data/lib/omml/models/ct_r_pr.rb +21 -0
  135. data/lib/omml/models/ct_r_pr_change.rb +21 -0
  136. data/lib/omml/models/ct_r_pr_original.rb +21 -0
  137. data/lib/omml/models/ct_rad.rb +25 -0
  138. data/lib/omml/models/ct_rad_pr.rb +23 -0
  139. data/lib/omml/models/ct_rel.rb +19 -0
  140. data/lib/omml/models/ct_rpr.rb +33 -0
  141. data/lib/omml/models/ct_ruby.rb +25 -0
  142. data/lib/omml/models/ct_ruby_align.rb +19 -0
  143. data/lib/omml/models/ct_ruby_content.rb +19 -0
  144. data/lib/omml/models/ct_ruby_pr.rb +31 -0
  145. data/lib/omml/models/ct_run_track_change.rb +23 -0
  146. data/lib/omml/models/ct_s_pre.rb +28 -0
  147. data/lib/omml/models/ct_s_pre_pr.rb +21 -0
  148. data/lib/omml/models/ct_s_sub.rb +25 -0
  149. data/lib/omml/models/ct_s_sub_pr.rb +21 -0
  150. data/lib/omml/models/ct_s_sub_sup.rb +28 -0
  151. data/lib/omml/models/ct_s_sub_sup_pr.rb +23 -0
  152. data/lib/omml/models/ct_s_sup.rb +25 -0
  153. data/lib/omml/models/ct_s_sup_pr.rb +21 -0
  154. data/lib/omml/models/ct_script.rb +19 -0
  155. data/lib/omml/models/ct_sdt_combo_box.rb +23 -0
  156. data/lib/omml/models/ct_sdt_content_run.rb +19 -0
  157. data/lib/omml/models/ct_sdt_date.rb +30 -0
  158. data/lib/omml/models/ct_sdt_date_mapping_type.rb +19 -0
  159. data/lib/omml/models/ct_sdt_doc_part.rb +25 -0
  160. data/lib/omml/models/ct_sdt_drop_down_list.rb +23 -0
  161. data/lib/omml/models/ct_sdt_end_pr.rb +21 -0
  162. data/lib/omml/models/ct_sdt_list_item.rb +21 -0
  163. data/lib/omml/models/ct_sdt_pr.rb +63 -0
  164. data/lib/omml/models/ct_sdt_run.rb +25 -0
  165. data/lib/omml/models/ct_sdt_text.rb +19 -0
  166. data/lib/omml/models/ct_shd.rb +35 -0
  167. data/lib/omml/models/ct_shp.rb +19 -0
  168. data/lib/omml/models/ct_signed_hps_measure.rb +19 -0
  169. data/lib/omml/models/ct_signed_twips_measure.rb +19 -0
  170. data/lib/omml/models/ct_simple_field.rb +29 -0
  171. data/lib/omml/models/ct_smart_tag_pr.rb +21 -0
  172. data/lib/omml/models/ct_smart_tag_run.rb +27 -0
  173. data/lib/omml/models/ct_spacing_rule.rb +19 -0
  174. data/lib/omml/models/ct_string.rb +19 -0
  175. data/lib/omml/models/ct_style.rb +19 -0
  176. data/lib/omml/models/ct_sym.rb +21 -0
  177. data/lib/omml/models/ct_text.rb +19 -0
  178. data/lib/omml/models/ct_text_effect.rb +19 -0
  179. data/lib/omml/models/ct_text_scale.rb +19 -0
  180. data/lib/omml/models/ct_top_bot.rb +19 -0
  181. data/lib/omml/models/ct_track_change.rb +21 -0
  182. data/lib/omml/models/ct_track_change_numbering.rb +19 -0
  183. data/lib/omml/models/ct_twips_measure.rb +19 -0
  184. data/lib/omml/models/ct_un_signed_integer.rb +19 -0
  185. data/lib/omml/models/ct_underline.rb +27 -0
  186. data/lib/omml/models/ct_vertical_align_run.rb +19 -0
  187. data/lib/omml/models/ct_wordprocessing_on_off.rb +19 -0
  188. data/lib/omml/models/ct_wrap_none.rb +15 -0
  189. data/lib/omml/models/ct_wrap_path.rb +25 -0
  190. data/lib/omml/models/ct_wrap_square.rb +31 -0
  191. data/lib/omml/models/ct_wrap_through.rb +27 -0
  192. data/lib/omml/models/ct_wrap_tight.rb +27 -0
  193. data/lib/omml/models/ct_wrap_top_bottom.rb +25 -0
  194. data/lib/omml/models/ct_x_align.rb +19 -0
  195. data/lib/omml/models/ct_y_align.rb +19 -0
  196. data/lib/omml/models/groups/eg_content_run_content.rb +26 -0
  197. data/lib/omml/models/groups/eg_math_content.rb +20 -0
  198. data/lib/omml/models/groups/eg_o_math_elements.rb +20 -0
  199. data/lib/omml/models/groups/eg_o_math_math_elements.rb +56 -0
  200. data/lib/omml/models/groups/eg_office_art_extension_list.rb +16 -0
  201. data/lib/omml/models/groups/eg_p_content.rb +24 -0
  202. data/lib/omml/models/groups/eg_r_pr.rb +17 -0
  203. data/lib/omml/models/groups/eg_r_pr_base.rb +93 -0
  204. data/lib/omml/models/groups/eg_r_pr_content.rb +19 -0
  205. data/lib/omml/models/groups/eg_r_pr_math.rb +23 -0
  206. data/lib/omml/models/groups/eg_range_markup_elements.rb +60 -0
  207. data/lib/omml/models/groups/eg_ruby_content.rb +20 -0
  208. data/lib/omml/models/groups/eg_run_inner_content.rb +83 -0
  209. data/lib/omml/models/groups/eg_run_level_elts.rb +34 -0
  210. data/lib/omml/models/groups/eg_script_style.rb +18 -0
  211. data/lib/omml/models/groups/eg_word_r_pr.rb +17 -0
  212. data/lib/omml/models/groups/eg_wrap_type.rb +27 -0
  213. data/lib/omml/models/groups.rb +19 -0
  214. data/lib/omml/models/o_math.rb +21 -0
  215. data/lib/omml/models/o_math_para.rb +25 -0
  216. data/lib/omml/models/simple_types/enum_string.rb +42 -0
  217. data/lib/omml/models/simple_types/hex_binary.rb +15 -0
  218. data/lib/omml/models/simple_types/st_adj_coordinate.rb +24 -0
  219. data/lib/omml/models/simple_types/st_align_h.rb +17 -0
  220. data/lib/omml/models/simple_types/st_align_v.rb +17 -0
  221. data/lib/omml/models/simple_types/st_border.rb +203 -0
  222. data/lib/omml/models/simple_types/st_br_clear.rb +16 -0
  223. data/lib/omml/models/simple_types/st_br_type.rb +15 -0
  224. data/lib/omml/models/simple_types/st_break_bin.rb +15 -0
  225. data/lib/omml/models/simple_types/st_break_bin_sub.rb +15 -0
  226. data/lib/omml/models/simple_types/st_calendar_type.rb +22 -0
  227. data/lib/omml/models/simple_types/st_combine_brackets.rb +17 -0
  228. data/lib/omml/models/simple_types/st_coordinate.rb +16 -0
  229. data/lib/omml/models/simple_types/st_displaced_by_custom_xml.rb +14 -0
  230. data/lib/omml/models/simple_types/st_ed_grp.rb +19 -0
  231. data/lib/omml/models/simple_types/st_em.rb +17 -0
  232. data/lib/omml/models/simple_types/st_f_type.rb +16 -0
  233. data/lib/omml/models/simple_types/st_ff_text_type.rb +18 -0
  234. data/lib/omml/models/simple_types/st_fld_char_type.rb +15 -0
  235. data/lib/omml/models/simple_types/st_geom_guide_name.rb +10 -0
  236. data/lib/omml/models/simple_types/st_hex_color.rb +24 -0
  237. data/lib/omml/models/simple_types/st_highlight_color.rb +29 -0
  238. data/lib/omml/models/simple_types/st_hint.rb +15 -0
  239. data/lib/omml/models/simple_types/st_info_text_type.rb +14 -0
  240. data/lib/omml/models/simple_types/st_integer2.rb +15 -0
  241. data/lib/omml/models/simple_types/st_integer255.rb +15 -0
  242. data/lib/omml/models/simple_types/st_jc.rb +16 -0
  243. data/lib/omml/models/simple_types/st_lang.rb +24 -0
  244. data/lib/omml/models/simple_types/st_lim_loc.rb +14 -0
  245. data/lib/omml/models/simple_types/st_lock.rb +16 -0
  246. data/lib/omml/models/simple_types/st_on_off.rb +18 -0
  247. data/lib/omml/models/simple_types/st_p_tab_alignment.rb +15 -0
  248. data/lib/omml/models/simple_types/st_p_tab_leader.rb +17 -0
  249. data/lib/omml/models/simple_types/st_p_tab_relative_to.rb +14 -0
  250. data/lib/omml/models/simple_types/st_positive_coordinate.rb +15 -0
  251. data/lib/omml/models/simple_types/st_proof_err.rb +16 -0
  252. data/lib/omml/models/simple_types/st_rel_from_h.rb +20 -0
  253. data/lib/omml/models/simple_types/st_rel_from_v.rb +20 -0
  254. data/lib/omml/models/simple_types/st_ruby_align.rb +18 -0
  255. data/lib/omml/models/simple_types/st_script.rb +18 -0
  256. data/lib/omml/models/simple_types/st_sdt_date_mapping_type.rb +15 -0
  257. data/lib/omml/models/simple_types/st_shd.rb +50 -0
  258. data/lib/omml/models/simple_types/st_shp.rb +14 -0
  259. data/lib/omml/models/simple_types/st_spacing_rule.rb +15 -0
  260. data/lib/omml/models/simple_types/st_style.rb +16 -0
  261. data/lib/omml/models/simple_types/st_text_effect.rb +19 -0
  262. data/lib/omml/models/simple_types/st_text_scale.rb +15 -0
  263. data/lib/omml/models/simple_types/st_theme.rb +20 -0
  264. data/lib/omml/models/simple_types/st_theme_color.rb +29 -0
  265. data/lib/omml/models/simple_types/st_top_bot.rb +14 -0
  266. data/lib/omml/models/simple_types/st_underline.rb +30 -0
  267. data/lib/omml/models/simple_types/st_vertical_align_run.rb +15 -0
  268. data/lib/omml/models/simple_types/st_wrap_text.rb +16 -0
  269. data/lib/omml/models/simple_types/st_x_align.rb +15 -0
  270. data/lib/omml/models/simple_types/st_y_align.rb +15 -0
  271. data/lib/omml/models/simple_types/token.rb +35 -0
  272. data/lib/omml/models/simple_types/unsigned_int.rb +15 -0
  273. data/lib/omml/models/simple_types/unsigned_long.rb +15 -0
  274. data/lib/omml/models/simple_types.rb +60 -0
  275. data/lib/omml/models.rb +183 -0
  276. data/lib/omml/namespace.rb +9 -0
  277. data/lib/omml/parser.rb +39 -0
  278. data/lib/omml/type_substitutions.rb +89 -0
  279. data/lib/omml/version.rb +2 -2
  280. data/lib/omml/wordprocessing_namespace.rb +9 -0
  281. data/lib/omml.rb +31 -3
  282. data/omml.gemspec +18 -14
  283. data/sig/omml.rbs +1 -1
  284. metadata +335 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 396fdf98892abceb0356b66ddc126cd1bf17dd09b56d20d6e300acb70581bbb7
4
- data.tar.gz: 375640f63f5c1fc558e63d8124a38f450a7ff899e433c2f5ad629e70594d96b0
3
+ metadata.gz: 2cc9754f1577e9e79ba68c5d841c61067b6c8eb88223a695d0a335a84724c177
4
+ data.tar.gz: 3c4677636e4951c68c99fe9af4ce85f7348a12cbec14f9b68431eccda957523b
5
5
  SHA512:
6
- metadata.gz: 429a2e4d69e94fbd3af19e5675cac37596400749953653523bfcf82971a05811519745f3c2691aadb3b5d941bf88eed2309c3402d894a0c0f255b519b7b05d5c
7
- data.tar.gz: 4fac51cee7307f401d99a49f2a198b58d1a7792d0ff2835c7a3b2eaa597b1fa1ed149654c25a48b5137fc35fc6c7ba97e2d3941f4cc97fabdc387e25615b8943
6
+ metadata.gz: 98fe061fee5b9906b97db4cf6826c86638d2c7ec8b9a2b16538b9027f404abac6a3f2062db6d02c25a35d70f55c738f219a2387c7c421049bee7c5a899de7b85
7
+ data.tar.gz: fb05a68e0d0855cfb314a3531857b920ee4b56113a7986f943a2800c25bf99957efefb0a110cda39fc82ffbdbb517c140754a65491fb464d057fb1d29784d3ad
@@ -0,0 +1,22 @@
1
+ name: rake
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ tags: [ v* ]
7
+ pull_request:
8
+
9
+ jobs:
10
+ rake:
11
+ uses: metanorma/ci/.github/workflows/generic-rake.yml@main
12
+ with:
13
+ # This is to fix Ruby 3.4 on Windows, as per lutaml/lutaml-model#447
14
+ before-setup-ruby: |
15
+ mkdir -p .bundle
16
+ touch .bundle/config
17
+ cat .bundle/config
18
+ echo "---" >> .bundle/config
19
+ echo 'BUNDLE_BUILD__RUBY___LL: "--with-cflags=-std=gnu17"' >> .bundle/config
20
+ cat .bundle/config
21
+ secrets:
22
+ pat_token: ${{ secrets.PLURIMATH_CI_PAT_TOKEN }}
@@ -0,0 +1,23 @@
1
+ name: release
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ next_version:
7
+ description: |
8
+ Next release version. Possible values: x.y.z, major, minor, patch or pre|rc|etc
9
+ required: true
10
+ default: 'skip'
11
+ push:
12
+ tags: [ v* ]
13
+
14
+ jobs:
15
+ release:
16
+ permissions:
17
+ contents: write
18
+ id-token: write
19
+ uses: metanorma/ci/.github/workflows/rubygems-release.yml@main
20
+ with:
21
+ next_version: ${{ github.event.inputs.next_version }}
22
+ secrets:
23
+ rubygems-api-key: ${{ secrets.PLURIMATH_CI_RUBYGEMS_API_KEY }}
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .rspec_status
2
+ Gemfile.lock
data/.rubocop.yml ADDED
@@ -0,0 +1,25 @@
1
+ inherit_from:
2
+ - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
3
+ - .rubocop_todo.yml
4
+
5
+ plugins:
6
+ - rubocop-performance
7
+ - rubocop-rake
8
+ - rubocop-rspec
9
+
10
+ AllCops:
11
+ TargetRubyVersion: 3.0
12
+ NewCops: enable
13
+ Exclude:
14
+ - 'vendor/**/*'
15
+
16
+ Metrics/BlockLength:
17
+ AllowedMethods:
18
+ - choice
19
+ - xml
20
+
21
+ RSpec/ExampleLength:
22
+ Max: 20
23
+
24
+ RSpec/MultipleExpectations:
25
+ Max: 10
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,19 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2026-05-01 11:14:00 UTC using RuboCop version 1.86.1.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 1
10
+ # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
11
+ Metrics/AbcSize:
12
+ Exclude:
13
+ - 'spec/omml_fixture_round_trip_spec.rb'
14
+
15
+ # Offense count: 1
16
+ # Configuration parameters: .
17
+ # SupportedStyles: have_received, receive
18
+ RSpec/MessageSpies:
19
+ EnforcedStyle: receive
data/CLAUDE.md ADDED
@@ -0,0 +1,64 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ `omml` is a Ruby gem that parses and serializes OMML (Office Math Markup Language), the XML format used by Microsoft Word for mathematical equations. It is part of the [Plurimath](https://github.com/plurimath) ecosystem. Models are defined using `lutaml-model` (declarative XML serialization) with `ox` as the XML backend.
8
+
9
+ ## Commands
10
+
11
+ ```bash
12
+ bundle install # Install dependencies
13
+ bundle exec rake # Run specs + rubocop (default task)
14
+ bundle exec rspec # Run all specs
15
+ bundle exec rspec spec/omml_spec.rb # Run a single spec file
16
+ bundle exec rspec spec/omml_spec.rb:77 # Run a single test by line number
17
+ bundle exec rubocop # Lint
18
+ ```
19
+
20
+ ## Architecture
21
+
22
+ ### Entry point and parsing flow
23
+
24
+ `Omml.parse(xml_string)` → `Parser.parse` → parses XML via the adapter → resolves the root class (`OMath` or `OMathPara` based on root element name) → calls `.of_xml` to deserialize into a Lutaml model tree.
25
+
26
+ The top-level API is in `lib/omml.rb`. `Parser` in `lib/omml/parser.rb` handles the parsing pipeline.
27
+
28
+ ### Type context system (`Omml::Configuration`)
29
+
30
+ `Configuration` manages a Lutaml `GlobalContext` (context ID `:omml`) that holds a registry of all model classes. Models are registered via `Omml::Configuration.register_model(Class)` at load time, and the context is populated lazily on first parse. Custom contexts can be created for downstream libraries (e.g., Plurimath) that fall back to the OMML context.
31
+
32
+ Model IDs are derived from class names: prefix `CT`/`EG`/`ST` is stripped and snake-cased with the prefix (e.g., `CTOMath` → `:ct_o_math`).
33
+
34
+ ### Model layer (`lib/omml/models/`)
35
+
36
+ Three categories of models, all extending `Lutaml::Model::Serializable`:
37
+
38
+ - **Complex types** (`ct_*.rb`) — represent OMML schema complex types. Each defines attributes and XML element mappings, and self-registers via `Omml::Configuration.register_model`.
39
+ - **Simple types** (`simple_types/*.rb`) — enum/value types like `STJc`, `STOnOff`. These wrap string values with validation.
40
+ - **Group models** (`groups/*.rb`) — shared compositional groups (e.g., `EGOMathElements`). These use `import_model_attributes` / `import_model_mappings` to compose attributes from other groups, implementing the OMML schema's choice/sequence patterns.
41
+
42
+ Root element wrappers (`o_math.rb`, `o_math_para.rb`) extend `CommonCode::RootModel` and use `omml_root_element` to declare themselves as XML root elements with the OMML namespace.
43
+
44
+ ### Namespaces
45
+
46
+ - `Omml::Namespace` — the OMML namespace (`http://schemas.openxmlformats.org/officeDocument/2006/math`, prefix `m`)
47
+ - `Omml::WordprocessingNamespace` — the Word ML namespace (prefix `w`), used for elements like `w:rPr` that appear inside OMML
48
+
49
+ ### Type substitutions (`TypeSubstitutions`)
50
+
51
+ Many OMML simple types are aliases for built-in Lutaml types (e.g., `STString` → `Lutaml::Model::Type::String`). These are registered as aliases in the context rather than as separate model classes.
52
+
53
+ ## Testing
54
+
55
+ - `spec/omml_spec.rb` — unit tests for parsing, context management, and error handling
56
+ - `spec/fixture_round_trip_spec.rb` — parses 279 OMML fixture files from `spec/fixtures/omml/`, round-trips them through parse → serialize, and compares the XML trees structurally (not string-equality). This is the primary correctness check.
57
+ - The round-trip spec expects exact XML structural fidelity: same elements, attributes, namespaces, text content, and child ordering.
58
+
59
+ ## Key conventions
60
+
61
+ - All models are in the `Omml::Models` module namespace
62
+ - The XML adapter is resolved by lutaml-model's AdapterResolver (lazy auto-detection)
63
+ - Models use `ordered` and `sequence` blocks for XML mapping to preserve element order
64
+ - `render_empty: true` is used on elements that must be emitted even when empty
data/Gemfile CHANGED
@@ -1,13 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- source 'https://rubygems.org'
3
+ source "https://rubygems.org"
4
4
 
5
5
  gemspec
6
6
  git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
7
7
 
8
- gem 'pry'
9
- gem 'rake', '~> 12.0'
10
- gem 'rspec', '~> 3.0'
11
- gem 'rubocop'
12
- gem 'rubocop-performance'
13
- gem 'rubocop-rails'
8
+ # TODO: remove this override once lutaml-model 0.8.0 is released.
9
+ gem "lutaml-model", github: "lutaml/lutaml-model", branch: "main"
10
+
11
+ gem "pry"
12
+ gem "rake", "~> 12.0"
13
+ gem "rspec", "~> 3.0"
14
+ gem "rubocop"
15
+ gem "rubocop-performance"
16
+ gem "rubocop-rake"
17
+ gem "rubocop-rspec"
data/README.adoc CHANGED
@@ -1,9 +1,227 @@
1
- = Plurimath OMML library
1
+ = Omml: OMML parser and builder for Ruby
2
+
3
+ :toc:
4
+ :toclevels: 2
2
5
 
3
6
  == Purpose
4
7
 
5
- `omml` is the OMML (Office Math Markup Language) library used by Plurimath.
8
+ Omml provides OMML (Office Math Markup Language) XML parsing and serialization
9
+ for Ruby. It maps the full OMML element set into Ruby model classes using the
10
+ https://github.com/lutaml/lutaml-model[lutaml-model] framework and is used by
11
+ https://github.com/plurimath/plurimath[Plurimath] for mathematical formula
12
+ representation.
13
+
14
+ Key features:
15
+
16
+ * **Round-trip fidelity**: Parse XML to an object graph, modify, and serialize back
17
+ * **Full schema coverage**: 172 complex types, 53 simple types, and 17 group models
18
+ generated from the OOXML Shared Math schema (`shared-math.xsd`)
19
+ * **Namespace handling**: OMML namespace with `m:` prefix, plus Word ML namespace
20
+ for embedded `w:rPr` run properties
21
+ * **Opal support**: Runs in the browser via Ruby-to-JavaScript compilation
22
+
23
+ == Installation
24
+
25
+ [source,ruby]
26
+ ----
27
+ gem 'omml'
28
+ ----
29
+
30
+ [source,bash]
31
+ ----
32
+ $ bundle install
33
+ # or
34
+ $ gem install omml
35
+ ----
36
+
37
+ == Quick start
38
+
39
+ [source,ruby]
40
+ ----
41
+ require "omml"
42
+
43
+ # Parse OMML XML
44
+ math = Omml.parse('<m:oMath xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"><m:r><m:t>x</m:t></m:r></m:oMath>')
45
+ # => #<Omml::Models::OMath:...>
46
+
47
+ # Serialize back to XML
48
+ math.to_xml(prefix: 'm')
49
+ # => "<m:oMath xmlns:m=\"...\">...</m:oMath>"
50
+ ----
51
+
52
+ == Parsing and serialization
53
+
54
+ === Parsing
55
+
56
+ `Omml.parse` accepts an XML string and returns a model tree. The root element
57
+ determines the wrapper class:
58
+
59
+ * `<m:oMath>` → `Omml::Models::OMath`
60
+ * `<m:oMathPara>` → `Omml::Models::OMathPara`
61
+
62
+ [source,ruby]
63
+ ----
64
+ # oMath root
65
+ math = Omml.parse('<m:oMath xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"><m:r><m:t>x</m:t></m:r></m:oMath>')
66
+ math.class # => Omml::Models::OMath
67
+
68
+ # oMathPara root
69
+ para = Omml.parse('<m:oMathPara xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math"><m:oMath><m:r><m:t>y</m:t></m:r></m:oMath></m:oMathPara>')
70
+ para.class # => Omml::Models::OMathPara
71
+ ----
72
+
73
+ === Serialization
74
+
75
+ [source,ruby]
76
+ ----
77
+ math.to_xml # Default serialization
78
+ math.to_xml(prefix: 'm') # With m: prefix on all elements
79
+ ----
80
+
81
+ === Round-trip (parse, modify, serialize)
82
+
83
+ [source,ruby]
84
+ ----
85
+ math = Omml.parse(xml_string)
86
+ # Access and modify the model tree
87
+ math.r.first.t.content = "new value"
88
+ math.to_xml(prefix: 'm')
89
+ ----
90
+
91
+ == Internal architecture
92
+
93
+ === Parsing flow
94
+
95
+ `Omml.parse(xml_string)` delegates to `Parser.parse`, which:
96
+
97
+ 1. Configures the XML adapter (`:ox` on MRI, `:oga` on Opal)
98
+ 2. Parses the XML string into a document
99
+ 3. Resolves the root class from the root element name (`OMath` or `OMathPara`)
100
+ 4. Calls `.of_xml` to deserialize into a Lutaml model tree
101
+
102
+ === Type context system
103
+
104
+ `Omml::Configuration` manages a `Lutaml::Model::GlobalContext` (context ID `:omml`)
105
+ that holds a registry of all model classes. Models register themselves at load
106
+ time via `Omml::Configuration.register_model`. The context is populated lazily on
107
+ first parse.
108
+
109
+ Custom contexts can be created for downstream libraries (e.g., Plurimath) that
110
+ fall back to the OMML context:
111
+
112
+ [source,ruby]
113
+ ----
114
+ # Create a custom context with OMML fallback
115
+ Omml::Configuration.create_context(id: :custom_omml)
116
+
117
+ # Parse using the custom context
118
+ Omml.parse(xml, context: :custom_omml)
119
+ ----
120
+
121
+ Model IDs are derived from class names by stripping the `CT`/`EG`/`ST` prefix
122
+ and snake-casing with the prefix (e.g., `CTOMath` → `:ct_o_math`,
123
+ `EGOMathElements` → `:eg_o_math_elements`).
124
+
125
+ === Model layer (`lib/omml/models/`)
126
+
127
+ Three categories of models, all extending `Lutaml::Model::Serializable`:
128
+
129
+ *Complex types* (`ct_*.rb`): Represent OMML schema complex types. Each defines
130
+ attributes and XML element mappings, and self-registers via
131
+ `Omml::Configuration.register_model`.
132
+
133
+ *Simple types* (`simple_types/st_*.rb`): Enum/value types like `STJc`, `STOnOff`.
134
+ These wrap string values with validation.
135
+
136
+ *Group models* (`groups/eg_*.rb`): Shared compositional groups (e.g.,
137
+ `EGOMathElements`). These use `import_model_attributes` /
138
+ `import_model_mappings` to compose attributes from other groups, implementing
139
+ the OMML schema's choice/sequence patterns.
140
+
141
+ Root element wrappers (`o_math.rb`, `o_math_para.rb`) extend
142
+ `CommonCode::RootModel` and use `omml_root_element` to declare themselves as XML
143
+ root elements with the OMML namespace.
144
+
145
+ === Namespaces
146
+
147
+ * `Omml::Namespace` — OMML namespace
148
+ (`http://schemas.openxmlformats.org/officeDocument/2006/math`, prefix `m`)
149
+ * `Omml::WordprocessingNamespace` — Word ML namespace (prefix `w`), used for
150
+ elements like `w:rPr` that appear inside OMML `ctrlPr` elements
151
+
152
+ === Type substitutions
153
+
154
+ Many OMML simple types are aliases for built-in Lutaml types (e.g., `STString`
155
+ → `Lutaml::Model::Type::String`). These are registered as aliases in the
156
+ context rather than as separate model classes, via `Omml::TypeSubstitutions`.
157
+
158
+ == Configuration
159
+
160
+ [source,ruby]
161
+ ----
162
+ # XML adapter (default: :ox, :oga on Opal)
163
+ Omml.configure_adapter!
164
+ Omml::Configuration.adapter = :oga
165
+
166
+ # Access the built-in context
167
+ Omml::Configuration.context_id # => :omml
168
+ Omml::Configuration.context
169
+
170
+ # Rebuild after a reset
171
+ Omml::Configuration.populate_context!
172
+
173
+ # Resolve a model class by its context ID
174
+ Omml::Configuration.resolve_type(:ct_o_math)
175
+ # => Omml::Models::CTOMath
176
+ ----
177
+
178
+ == Test Suite and Fixtures
179
+
180
+ The gem uses 279 OMML fixture files from `spec/fixtures/omml/` for round-trip
181
+ validation. Each fixture is parsed, serialized, and the output is compared
182
+ structurally against the original.
183
+
184
+ === Running Tests
185
+
186
+ [source,bash]
187
+ ----
188
+ bundle exec rake # Run all specs + rubocop
189
+ bundle exec rspec # Run all tests
190
+ bundle exec rspec spec/omml_spec.rb # Run specific test file
191
+ bundle exec rspec spec/omml_spec.rb:77 # Run single test by line
192
+ bundle exec rspec --only-failures # Re-run failures
193
+ ----
194
+
195
+ === XSD Validation
196
+
197
+ The fixture round-trips are validated against the OOXML `shared-math.xsd`
198
+ schema. Some fixtures contain Word-specific deviations from the strict XSD:
199
+
200
+ * Element ordering differences (Word may output children in a different order
201
+ than the schema sequence)
202
+ * Numeric `val` values (`1`/`0`) on `CT_OnOff` elements where the XSD specifies
203
+ `on`/`off` enumeration
204
+ * `r` elements directly under `oMathPara` (Word output, not in the XSD sequence)
205
+
206
+ These are well-known Word compatibilities and do not represent parser bugs.
207
+
208
+ == Development
209
+
210
+ [source,bash]
211
+ ----
212
+ bundle install # Install dependencies
213
+ bundle exec rake # Run specs + rubocop
214
+ bundle exec rspec # Run tests
215
+ bundle exec rubocop # Lint
216
+ ----
217
+
218
+ == Contributing
219
+
220
+ Bug reports and pull requests are welcome on GitHub at
221
+ https://github.com/plurimath/omml.
222
+
223
+ == Copyright and license
6
224
 
7
- == Copyright and License
225
+ Copyright Ribose Inc.
8
226
 
9
- Copyright (c) 2024 Ribose Inc.
227
+ https://opensource.org/licenses/BSD-2-Clause[BSD-2-Clause License].
data/Rakefile CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'bundler/gem_tasks'
4
- require 'rspec/core/rake_task'
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
5
 
6
6
  RSpec::Core::RakeTask.new(:spec)
7
7
 
8
- require 'rubocop/rake_task'
8
+ require "rubocop/rake_task"
9
9
 
10
10
  RuboCop::RakeTask.new
11
11
 
data/bin/console CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'bundler/setup'
5
- require 'omml'
4
+ require "bundler/setup"
5
+ require "omml"
6
6
 
7
7
  # You can add fixtures and/or initialization code here to make experimenting
8
8
  # with your gem easier. You can also use a different console, if you like.
9
9
 
10
- require 'irb'
10
+ require "irb"
11
11
  IRB.start(__FILE__)
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omml
4
+ module Configuration
5
+ # Extended only by Omml::Configuration together with the sibling modules.
6
+ module Adapter
7
+ def adapter
8
+ Lutaml::Model::Config.xml_adapter_type
9
+ end
10
+
11
+ def adapter=(_adapter)
12
+ # No-op: omml is not user-facing and must not change the global
13
+ # adapter. Adapter resolution is handled by AdapterResolver.
14
+ end
15
+
16
+ def xml_adapter
17
+ Lutaml::Model::Config.adapter_for(:xml)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,131 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omml
4
+ module Configuration
5
+ # Extended only by Omml::Configuration together with the sibling modules.
6
+ module ContextRegistry
7
+ def context(id = context_id)
8
+ Lutaml::Model::GlobalContext.context(id.to_sym)
9
+ end
10
+
11
+ def create_context(id:, registry: nil, fallback_to: [context_id],
12
+ substitutions: [])
13
+ normalized_id = normalize_context_id(id)
14
+ if default_context_id?(normalized_id)
15
+ return create_default_context(registry, fallback_to,
16
+ substitutions)
17
+ end
18
+
19
+ create_custom_context(
20
+ id: normalized_id, registry: registry,
21
+ fallback_to: fallback_to, substitutions: substitutions
22
+ )
23
+ end
24
+
25
+ def populate_context!
26
+ # Trigger the model manifest autoload before replaying registrations.
27
+ Omml.const_get(:Models)
28
+ reset_context!
29
+ register_models_in(populate_base_context)
30
+ end
31
+
32
+ def require_context!(id = context_id)
33
+ normalized_id = id.to_sym
34
+ type_context = context(normalized_id)
35
+ return type_context if type_context
36
+
37
+ raise Omml::Errors::MissingContextError, normalized_id
38
+ end
39
+
40
+ def reset_context!(id: context_id)
41
+ normalized_id = normalize_context_id(id)
42
+ existing_context = Lutaml::Model::GlobalContext.context(normalized_id)
43
+ return unless existing_context
44
+
45
+ Lutaml::Model::GlobalContext.unregister_context(normalized_id)
46
+ end
47
+
48
+ private
49
+
50
+ def default_context_id?(id)
51
+ id == context_id
52
+ end
53
+
54
+ def create_default_context(registry, fallback_to, substitutions)
55
+ unless default_context_options?(registry, fallback_to, substitutions)
56
+ raise ArgumentError,
57
+ "create_context cannot customize the default " \
58
+ ":#{context_id} context; use populate_context! to rebuild it."
59
+ end
60
+
61
+ populate_context!
62
+ end
63
+
64
+ def default_context_options?(registry, fallback_to, substitutions)
65
+ registry.nil? &&
66
+ normalize_fallbacks(fallback_to) == [context_id] &&
67
+ Array(substitutions).empty?
68
+ end
69
+
70
+ def create_custom_context(id:, registry:, fallback_to:, substitutions:)
71
+ reset_context!(id: id)
72
+ create_type_context(
73
+ id: id,
74
+ registry: registry || Lutaml::Model::TypeRegistry.new,
75
+ fallback_to: prepare_fallback_contexts(fallback_to),
76
+ substitutions: substitutions,
77
+ )
78
+ end
79
+
80
+ def populate_base_context
81
+ base_type_context.tap { bind_namespace!(context_id) }
82
+ end
83
+
84
+ def create_type_context(id:, registry:, fallback_to:, substitutions: [])
85
+ Lutaml::Model::GlobalContext.create_context(
86
+ id: id,
87
+ registry: registry,
88
+ fallback_to: Array(fallback_to),
89
+ substitutions: substitutions,
90
+ ).tap do
91
+ Lutaml::Model::GlobalContext.clear_caches
92
+ end
93
+ end
94
+
95
+ def base_type_context
96
+ create_type_context(
97
+ id: context_id,
98
+ registry: Lutaml::Model::TypeRegistry.new,
99
+ fallback_to: [:default],
100
+ )
101
+ end
102
+
103
+ def prepare_fallback_contexts(fallback_to)
104
+ normalize_fallbacks(fallback_to).tap do |fallbacks|
105
+ populate_context! if populate_fallback_context?(fallbacks)
106
+ end
107
+ end
108
+
109
+ def populate_fallback_context?(fallbacks)
110
+ fallbacks.include?(context_id) && !context(context_id)
111
+ end
112
+
113
+ def normalize_fallbacks(fallback_to)
114
+ Array(fallback_to).map do |fallback|
115
+ normalize_context_id(fallback)
116
+ end
117
+ end
118
+
119
+ def normalize_context_id(id)
120
+ id.to_sym
121
+ end
122
+
123
+ def bind_namespace!(id)
124
+ Lutaml::Model::GlobalContext.bind_register_to_namespace(
125
+ id,
126
+ Omml::Namespace.uri,
127
+ )
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Omml
4
+ module Configuration
5
+ # Extended only by Omml::Configuration together with the sibling modules.
6
+ module ModelRegistry
7
+ def register_model(klass, id: nil)
8
+ model_id = (id || model_id_for(klass)).to_sym
9
+ registered_models[model_id] = klass
10
+
11
+ if (type_context = context(context_id))
12
+ type_context.registry.register(model_id, klass)
13
+ clear_cache(klass, type_context.id)
14
+ end
15
+
16
+ klass
17
+ end
18
+
19
+ def model_id_for(klass)
20
+ class_name = klass.name.split("::").last
21
+ prefix = SCHEMA_MODEL_PREFIXES.find do |candidate|
22
+ class_name.start_with?(candidate) && class_name != candidate
23
+ end
24
+
25
+ if prefix
26
+ model_name = class_name.delete_prefix(prefix)
27
+ return :"#{prefix.downcase}_#{Lutaml::Model::Utils.snake_case(model_name)}"
28
+ end
29
+
30
+ Lutaml::Model::Utils.snake_case(class_name).to_sym
31
+ end
32
+
33
+ def registered_models
34
+ @registered_models ||= {}
35
+ end
36
+
37
+ private
38
+
39
+ def register_models_in(type_context)
40
+ register_id = type_context.id
41
+ registered_models.each do |model_id, klass|
42
+ type_context.registry.register(model_id, klass)
43
+ clear_cache(klass, register_id)
44
+ end
45
+
46
+ Omml::TypeSubstitutions.each_alias do |type_name, klass|
47
+ type_context.registry.register(type_name, klass)
48
+ end
49
+
50
+ Lutaml::Model::GlobalContext.clear_caches
51
+ type_context
52
+ end
53
+
54
+ def clear_cache(klass, register_id)
55
+ klass.instance_variable_set(:@register, register_id)
56
+ klass.clear_cache(register_id) if klass.respond_to?(:clear_cache)
57
+ end
58
+ end
59
+ end
60
+ end