metanorma-taste 0.0.4 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eb20ec7e6a17ff430590c88535fdb0e51689bfa6e5e42a5afbf41f64c7afafa7
4
- data.tar.gz: deb669ae16cd287d3f82efc86fd3a55499ed121824ed144d7b8e54f0a367a1a7
3
+ metadata.gz: 7ef00e42b85547e125b2a4fc021ecb9b9fc42c5f4ec5535c536b4b1cf7c6e9fd
4
+ data.tar.gz: 96dca7b1f86bab29bb496302ce4bf75900234ccec17da76bdb5fd911a79cd8cb
5
5
  SHA512:
6
- metadata.gz: 6dfd2cf42b04c22083bf4dd472c6ab708c5d8db7b7192d43d07f2757d6404c47b05ae622a64dfe028689666976558a883f3c91ee28c7e4f57a4b4f6451aa3675
7
- data.tar.gz: 1e13c58cae481e3ebf94341c76948437441e5d41a35aa32876922d9429c925b32287c243fb8b489b3c287e00e365ca53eabc50764b42e3816dc3e21cafad4d9a
6
+ metadata.gz: 9e8cdc3982f9e70b3e376ef7bfe3902253058751a1fded487a805a922454ae78ddd0cd5723b8ff2c69626916e2dc4bece54206fcb40e0cfa666ffc2ab86cdd5c
7
+ data.tar.gz: 0beabd2954ffa0188978915cdcd70bb9a4c22ddc188d6b9c34aaed3e366bb357801960210364a4dc32e8abdb8ab30c55c57bf66807ae5eb729d23ee56cd64ea4
data/Gemfile CHANGED
@@ -1,3 +1,18 @@
1
1
  source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
+
5
+ gem "debug"
6
+ gem "equivalent-xml", "~> 0.6"
7
+ gem "metanorma"
8
+ gem "metanorma-iso"
9
+ gem "mnconvert"
10
+ gem "pry"
11
+ gem "rake", "~> 13.0"
12
+ gem "rspec", "~> 3.0"
13
+ gem "rspec-command", "~> 1.0"
14
+ gem "rubocop", "~> 1"
15
+ gem "rubocop-performance"
16
+ gem "sassc-embedded", "~> 1"
17
+ gem "simplecov", "~> 0.15"
18
+ gem "xml-c14n"
data/README.adoc CHANGED
@@ -67,9 +67,12 @@ The gem is distributed within Metanorma.
67
67
 
68
68
  === Compiling documents
69
69
 
70
- If a taste abbreviation is used instead of a flavor in compiling a Metanorma document, e.g. as the document attribute `:flavor: icc` or
71
- `:mn-document-class: icc`, this gem is used to process that document as an instance of its base flavor, and will substitute the necessary
72
- configuration files and document attributes required to get the document to render as expected.
70
+ If a taste abbreviation is used instead of a flavor in compiling a Metanorma
71
+ document, e.g. as the document attribute `:flavor: icc` or
72
+ `:mn-document-class: icc`, this gem is used to process that document as an
73
+ instance of its base flavor, and will substitute the necessary configuration
74
+ files and document attributes required to get the document to render as
75
+ expected.
73
76
 
74
77
  === Basic usage
75
78
 
@@ -90,16 +93,20 @@ taste.process_input_adoc_overrides(attributes, options)
90
93
  [source,ruby]
91
94
  ----
92
95
  # List all available tastes
93
- Metanorma::TasteRegister.instance.available_tastes
94
- # => [:icc]
96
+ Metanorma::TasteRegister.available_tastes
97
+ # => [:icc, :elf, :enosema]
95
98
 
96
99
  # Get information about a specific taste
97
- Metanorma::TasteRegister.instance.taste_info(:icc)
98
- # => { flavor: :icc, owner: "International Color Consortium", base_flavor: :iso, ... }
100
+ config = Metanorma::TasteRegister.get_config(:icc)
101
+ # => #<Metanorma::Taste::TasteConfig:...>
102
+ puts config.owner
103
+ # => "International Color Consortium"
104
+ puts config.base_flavor
105
+ # => "iso"
99
106
 
100
107
  # Get flavor aliases (mapping to base flavours)
101
- Metanorma::Taste.aliases
102
- # => { icc: :iso }
108
+ Metanorma::TasteRegister.aliases
109
+ # => { icc: :iso, elf: :iso, enosema: :iso }
103
110
 
104
111
  # Demonstrate dynamic class creation
105
112
  taste = Metanorma::TasteRegister.get(:icc)
@@ -350,7 +357,7 @@ The metanorma-taste system follows this architecture:
350
357
  | (Singleton) | | |
351
358
  | +available_tastes|<>---->| +flavor |
352
359
  | +get(flavor) | | +config |
353
- | +taste_info() | | +taste_info |
360
+ | +get_config() | | +directory |
354
361
  +--------+---------+ | +process_input_* |
355
362
  | +-------------------+
356
363
  |
@@ -359,10 +366,10 @@ The metanorma-taste system follows this architecture:
359
366
  | data/ directory| | Dynamic Classes |
360
367
  | | | |
361
368
  | +{taste}/ |------>| Taste::Icc |
362
- | config.yaml | | Taste::Foo |
363
- | copyright.adoc | | (auto-generated) |
364
- | i18n.yaml | +-------------------+
365
- +------------------+
369
+ | config.yaml | | Taste::Elf |
370
+ | copyright.adoc | | Taste::Enosema |
371
+ | i18n.yaml | | (auto-generated) |
372
+ +------------------+ +-------------------+
366
373
  ----
367
374
 
368
375
  === Components
data/data/icc/config.yaml CHANGED
@@ -4,7 +4,7 @@ owner: International Color Consortium
4
4
  base-flavor: iso
5
5
  copyright-notice: copyright.adoc
6
6
  i18n-dictionary: i18n.yaml
7
- publisher-logo: icc.png
7
+ publisher-logo: icc-full.svg
8
8
  base-override:
9
9
  publisher: International Color Consortium
10
10
  publisher_abbr: ICC
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg id="uuid-9bf42bb3-8ca3-4310-8d2a-ee82dc609955" xmlns="http://www.w3.org/2000/svg" width="431.07mm" height="110.25mm" viewBox="0 0 1221.92 312.52"><g id="uuid-d578ad4a-7e99-4d73-a868-e7057360f52d"><polygon points="555.47 187.1 531.69 222.94 194.58 103.74 555.47 187.1" style="fill:#090909;"/><path d="M243.23,115.6c1.04-.29,26.48-26.16,16.58-45.06-10.14-19.37-18.37-28.88-41.23-37.17-2.3-.84-11.56-4.75-12.35-.96-.97,4.68,15.92,6.23,18.43,24.42.42,3.07,5.19,40.48-33.25,39.72-31.14-.61-32.48-28.24-32.17-33.4,1.17-19.86,19.05-24.37,17-28.89-3.43-7.57-49.76,5.93-49.11,43.12.52,29.72,31.74,51.88,45.55,62.27-11.77-3.6-27.1-9.3-40.92-17.32-28.63-16.6-28.79-33.39-29.04-43.08,0,0-24.83,28.9-48.85,40.91-27.03,13.51-38.77,9.08-38.77,9.08,0,0,19.27-7.09,52.72-43.64C89.86,61.52,114.57.53,200.46,4.13c62.03,2.6,72.5,30.07,133.15,45.47-25.32,3.44-61.51-4.64-61.51-4.64,0,0,6.14,1.23,7.87,25.16.91,12.49-5.46,35.11-21.28,49.12l-15.45-3.63Z" style="fill:#090909;"/><polygon points="194.58 103.74 463.68 263.26 388.8 272.3 194.58 103.74" style="fill:#359cd7;"/><polygon points="194.58 103.74 378.55 274.09 299.63 274.09 194.58 103.74" style="fill:#cd1e75;"/><path d="M271.6,228.6l-1-.5s.64-.13,1,.5Z" style="fill:#db3e92;"/><path d="M194.58,103.74c107.3,38.66,329.73,126.43,329.73,126.43l-51.94,28.36s-187.43-104.16-277.79-154.8Z" style="fill:#f0e92a;"/><path d="M230.6,124.6l-1.5-.5c.12.07.73.04,1.5.5Z" style="fill:#f4f5c6;"/></g><path d="M510.17,147.62h-11.71l10.77-88.72h11.84l-10.91,88.72Z" style="fill:#231f20;"/><path d="M539.7,95.08c3.33-4.79,6.78-7.85,12.9-7.85,6.65,0,10.24,3.99,10.24,10.51,0,2.53-.27,5.05-.53,7.58l-5.19,42.3h-10.91l4.92-39.77c.13-1.6.4-3.19.4-4.79,0-3.46-1.6-6.25-5.32-6.25-6.65,0-7.58,7.18-8.25,12.37l-4.79,38.44h-10.77l7.32-59.46h10.77l-.8,6.92Z" style="fill:#231f20;"/><path d="M592.9,96.68h-5.85l-6.25,50.94h-10.77l6.25-50.94h-5.99l1.06-8.51h5.99l2-16.89h10.77l-2,16.89h5.85l-1.06,8.51Z" style="fill:#231f20;"/><path d="M628.42,127.54c-.67,4.39-1.46,8.11-3.72,11.97-3.19,5.72-9.18,9.04-15.7,9.04-11.97,0-15.03-9.44-15.03-19.69,0-7.58,1.06-15.03,2.93-22.35,2.53-9.71,7.85-19.29,19.29-19.29s14.5,11.04,14.5,20.62c0,4.12-.4,8.25-.93,12.24h-24.61c-.27,2.66-.53,5.19-.53,7.85,0,4.12,0,11.17,5.72,11.17s7.45-7.05,7.98-11.57h10.11ZM619.9,105.72c0-3.46-.27-9.18-5.05-9.18-6.38,0-7.85,10.91-8.78,15.56h13.7c.13-1.46.13-2.93.13-4.39v-2Z" style="fill:#231f20;"/><path d="M664.86,98.28c-.67-.13-1.2-.13-1.86-.13-9.04,0-11.44,5.45-12.37,13.43l-4.52,36.05h-10.77l7.32-59.46h10.77l-.93,7.45c3.86-5.32,6.92-8.25,13.83-8.78l-1.46,11.44Z" style="fill:#231f20;"/><path d="M682.55,95.08c3.33-4.79,6.78-7.85,12.9-7.85,6.65,0,10.24,3.99,10.24,10.51,0,2.53-.27,5.05-.53,7.58l-5.19,42.3h-10.91l4.92-39.77c.13-1.6.4-3.19.4-4.79,0-3.46-1.6-6.25-5.32-6.25-6.65,0-7.58,7.18-8.25,12.37l-4.79,38.44h-10.77l7.32-59.46h10.77l-.8,6.92Z" style="fill:#231f20;"/><path d="M744.93,147.62h-10.77l.93-7.58c-2.79,4.92-5.72,8.51-11.84,8.51-9.44,0-11.04-9.84-11.04-17.29,0-11.97,1.73-44.03,18.62-44.03,5.32,0,7.98,3.06,9.84,7.71l.8-6.78h10.77l-7.32,59.46ZM733.89,97.21c-5.59,0-7.32,6.92-8.25,11.31-1.46,6.78-2.39,13.7-2.39,20.62,0,3.72.4,9.58,5.45,9.58s6.65-6.25,7.58-10.11c1.73-7.18,2.66-14.63,2.66-22.08,0-3.46-.4-9.31-5.05-9.31Z" style="fill:#231f20;"/><path d="M780.7,96.68h-5.85l-6.25,50.94h-10.77l6.25-50.94h-5.99l1.06-8.51h5.99l2-16.89h10.77l-2,16.89h5.85l-1.06,8.51Z" style="fill:#231f20;"/><path d="M792.28,147.62h-10.77l7.32-59.46h10.77l-7.32,59.46ZM794.94,77.79c-3.59,0-6.38-2.93-6.38-6.52,0-4.39,3.99-8.38,8.38-8.38,3.86,0,6.38,2.93,6.38,6.65,0,4.39-3.99,8.25-8.38,8.25Z" style="fill:#231f20;"/><path d="M819.81,148.55c-12.24,0-15.16-9.71-15.16-20.08,0-14.9,3.19-41.23,22.88-41.23,11.84,0,15.3,9.44,15.3,19.69,0,14.9-3.06,41.63-23.01,41.63ZM826.32,97.21c-2.39,0-3.86,1.2-5.05,3.06-3.72,5.59-5.19,22.48-5.19,29.4,0,3.59.67,8.65,5.32,8.65,2.39,0,3.86-1.2,5.19-3.19,3.72-5.59,5.19-22.35,5.19-29.26,0-3.72-.67-8.65-5.45-8.65Z" style="fill:#231f20;"/><path d="M865.16,95.08c3.33-4.79,6.78-7.85,12.9-7.85,6.65,0,10.24,3.99,10.24,10.51,0,2.53-.27,5.05-.53,7.58l-5.19,42.3h-10.91l4.92-39.77c.13-1.6.4-3.19.4-4.79,0-3.46-1.6-6.25-5.32-6.25-6.65,0-7.58,7.18-8.25,12.37l-4.79,38.44h-10.77l7.32-59.46h10.77l-.8,6.92Z" style="fill:#231f20;"/><path d="M927.54,147.62h-10.77l.93-7.58c-2.79,4.92-5.72,8.51-11.84,8.51-9.44,0-11.04-9.84-11.04-17.29,0-11.97,1.73-44.03,18.62-44.03,5.32,0,7.98,3.06,9.84,7.71l.8-6.78h10.77l-7.32,59.46ZM916.5,97.21c-5.59,0-7.32,6.92-8.25,11.31-1.46,6.78-2.39,13.7-2.39,20.62,0,3.72.4,9.58,5.45,9.58s6.65-6.25,7.58-10.11c1.73-7.18,2.66-14.63,2.66-22.08,0-3.46-.4-9.31-5.05-9.31Z" style="fill:#231f20;"/><path d="M949.88,147.62h-10.77l11.84-96.96h10.77l-11.84,96.96Z" style="fill:#231f20;"/><path d="M609.37,197.61c-2.26-1.33-4.66-2.26-7.32-2.26-7.71,0-12.77,6.25-15.43,12.9-3.72,9.18-5.72,24.47-5.72,34.45,0,9.18,1.73,20.88,13.43,20.88,2.53,0,4.79-.53,7.05-1.73l-1.33,10.91c-3.33,2-5.85,2.53-9.71,2.53-17.69,0-22.08-15.03-22.08-29.93,0-12.5,2.53-29.13,7.05-40.7,4.39-11.31,12.77-20.35,25.67-20.35,3.86,0,6.25.4,9.58,2.53l-1.2,10.77Z" style="fill:#231f20;"/><path d="M624.53,275.03c-12.24,0-15.16-9.71-15.16-20.08,0-14.9,3.19-41.23,22.88-41.23,11.84,0,15.3,9.44,15.3,19.69,0,14.9-3.06,41.63-23.01,41.63ZM631.05,223.68c-2.39,0-3.86,1.2-5.05,3.06-3.72,5.59-5.19,22.48-5.19,29.4,0,3.59.67,8.65,5.32,8.65,2.39,0,3.86-1.2,5.19-3.19,3.72-5.59,5.19-22.35,5.19-29.26,0-3.72-.67-8.65-5.45-8.65Z" style="fill:#231f20;"/><path d="M663.37,274.09h-10.77l11.84-96.96h10.77l-11.84,96.96Z" style="fill:#231f20;"/><path d="M690.77,275.03c-12.24,0-15.16-9.71-15.16-20.08,0-14.9,3.19-41.23,22.88-41.23,11.84,0,15.3,9.44,15.3,19.69,0,14.9-3.06,41.63-23.01,41.63ZM697.28,223.68c-2.39,0-3.86,1.2-5.05,3.06-3.72,5.59-5.19,22.48-5.19,29.4,0,3.59.67,8.65,5.32,8.65,2.39,0,3.86-1.2,5.19-3.19,3.72-5.59,5.19-22.35,5.19-29.26,0-3.72-.67-8.65-5.45-8.65Z" style="fill:#231f20;"/><path d="M748.36,224.75c-.67-.13-1.2-.13-1.86-.13-9.04,0-11.44,5.45-12.37,13.43l-4.52,36.05h-10.77l7.32-59.46h10.77l-.93,7.45c3.86-5.32,6.92-8.25,13.83-8.78l-1.46,11.44Z" style="fill:#231f20;"/><path d="M815.71,198.81c-2.26-1.33-4.66-2.26-7.32-2.26-7.71,0-12.77,6.25-15.43,12.9-3.72,9.18-5.72,24.47-5.72,34.45,0,9.18,1.73,20.88,13.43,20.88,2.53,0,4.79-.53,7.05-1.73l-1.33,10.91c-3.33,2-5.85,2.53-9.71,2.53-17.69,0-22.08-15.03-22.08-29.93,0-12.5,2.53-29.13,7.05-40.7,4.39-11.31,12.77-20.35,25.67-20.35,3.86,0,6.25.4,9.58,2.53l-1.2,10.77Z" style="fill:#231f20;"/><path d="M830.2,276.22c-12.24,0-15.16-9.71-15.16-20.08,0-14.9,3.19-41.23,22.88-41.23,11.84,0,15.3,9.44,15.3,19.69,0,14.9-3.06,41.63-23.01,41.63ZM836.72,224.88c-2.39,0-3.86,1.2-5.05,3.06-3.72,5.59-5.19,22.48-5.19,29.4,0,3.59.67,8.65,5.32,8.65,2.39,0,3.86-1.2,5.19-3.19,3.72-5.59,5.19-22.35,5.19-29.26,0-3.72-.67-8.65-5.45-8.65Z" style="fill:#231f20;"/><path d="M874.89,222.75c3.33-4.79,6.78-7.85,12.9-7.85,6.65,0,10.24,3.99,10.24,10.51,0,2.53-.27,5.05-.53,7.58l-5.19,42.3h-10.91l4.92-39.77c.13-1.6.4-3.19.4-4.79,0-3.46-1.6-6.25-5.32-6.25-6.65,0-7.58,7.18-8.25,12.37l-4.79,38.44h-10.77l7.32-59.46h10.77l-.8,6.92Z" style="fill:#231f20;"/><path d="M931.68,227.27c-2.26-1.73-4.92-2.93-7.85-2.93-3.99,0-7.85,3.33-7.85,7.45,0,8.51,14.9,10.51,14.9,24.21,0,11.17-7.71,20.22-19.15,20.22-3.86,0-5.99-.67-9.18-2.79l1.33-10.64c2.53,2.13,5.05,3.59,8.51,3.59,5.19,0,8.38-3.59,8.38-8.65,0-8.78-15.16-11.57-15.16-24.34,0-10.51,7.32-18.89,18.09-18.89,3.46,0,6.38.8,9.31,2.53l-1.33,10.24Z" style="fill:#231f20;"/><path d="M951.9,276.22c-12.24,0-15.16-9.71-15.16-20.08,0-14.9,3.19-41.23,22.88-41.23,11.84,0,15.3,9.44,15.3,19.69,0,14.9-3.06,41.63-23.01,41.63ZM958.42,224.88c-2.39,0-3.86,1.2-5.05,3.06-3.72,5.59-5.19,22.48-5.19,29.4,0,3.59.67,8.65,5.32,8.65,2.39,0,3.86-1.2,5.19-3.19,3.72-5.59,5.19-22.35,5.19-29.26,0-3.72-.67-8.65-5.45-8.65Z" style="fill:#231f20;"/><path d="M1008.83,225.94c-.67-.13-1.2-.13-1.86-.13-9.04,0-11.44,5.45-12.37,13.43l-4.52,36.05h-10.77l7.32-59.46h10.77l-.93,7.45c3.86-5.32,6.92-8.25,13.83-8.78l-1.46,11.44Z" style="fill:#231f20;"/><path d="M1035.29,224.34h-5.85l-6.25,50.94h-10.77l6.25-50.94h-5.99l1.06-8.51h5.99l2-16.89h10.77l-2,16.89h5.85l-1.06,8.51Z" style="fill:#231f20;"/><path d="M1046.2,275.29h-10.77l7.32-59.46h10.77l-7.32,59.46ZM1048.86,205.46c-3.59,0-6.38-2.93-6.38-6.52,0-4.39,3.99-8.38,8.38-8.38,3.86,0,6.38,2.93,6.38,6.65,0,4.39-3.99,8.25-8.38,8.25Z" style="fill:#231f20;"/><path d="M1094.88,251.48c-1.73,14.37-3.72,24.87-21.02,24.87-9.71,0-14.76-4.92-14.76-14.63,0-2.26.27-4.39.53-6.65l4.79-39.24h10.77l-4.39,35.65c-.4,2.79-.67,5.45-.67,8.25,0,4.39,1.73,6.12,6.12,6.12,5.72,0,6.52-5.32,7.18-9.84.27-1.46.53-3.06.67-4.52l4.26-35.65h10.91l-4.39,35.65Z" style="fill:#231f20;"/><path d="M1120.01,223.15c3.19-4.66,6.92-8.25,12.9-8.25s8.78,2.66,9.98,8.25c3.33-5.19,6.92-8.25,13.3-8.25s11.17,3.46,11.17,10.24c0,.93,0,1.86-.13,2.79l-5.85,47.35h-10.77l4.79-39.1c.27-1.86.4-3.72.4-5.59,0-3.46-1.2-5.72-4.92-5.72-6.78,0-7.45,5.99-8.11,11.31l-4.79,39.1h-11.17l4.79-39.1c.27-2,.4-3.86.4-5.85,0-3.46-1.86-5.45-5.32-5.45-6.65,0-7.45,6.12-8.11,11.31l-4.92,39.1h-10.77l7.32-59.46h10.77l-.93,7.32Z" style="fill:#231f20;"/><path d="M1194.88,216.46c-9.12,0-16.53-7.41-16.53-16.53s7.41-16.53,16.53-16.53,16.48,7.45,16.48,16.53-7.36,16.53-16.48,16.53ZM1194.88,185.74c-7.79,0-13.95,6.4-13.95,14.14s6.16,14.24,13.95,14.24,13.9-6.5,13.9-14.19-6.07-14.19-13.9-14.19ZM1197.61,209.53l-3.92-8.41v8.41h-3.34v-19.25h4.39c3.97,0,5.54,1.29,5.54,5.3,0,2.39-.91,4.73-3.58,4.92l4.4,9.03h-3.49ZM1194.55,198.26c2.05,0,2.48-1,2.48-2.87,0-2.01-.53-2.77-2.63-2.77h-.72v5.64h.86Z" style="fill:#231f20;"/></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg id="uuid-73864094-f043-4722-bdaa-7af47c32468a" xmlns="http://www.w3.org/2000/svg" width="387.08mm" height="110.25mm" viewBox="0 0 1097.23 312.52"><path d="M542.72,166.51h-6.4l8.61-70.03h6.4l-8.61,70.03Z" style="fill:#231f20;"/><path d="M563.01,123.35c2.52-2.52,5.88-4.51,9.45-4.51,5.35,0,7.87,3.57,7.87,8.61,0,1.47-.1,2.94-.31,4.31l-4.2,34.75h-5.88l4.09-33.7c.21-1.36.42-2.73.42-4.09,0-2.83-1.47-5.04-4.41-5.04-6.4,0-7.87,6.19-8.4,11.23l-3.89,31.6h-5.88l5.77-46.93h5.77l-.42,3.78Z" style="fill:#231f20;"/><path d="M604.05,125.03h-7.77l-5.14,41.47h-5.77l5.15-41.47h-4.94l.63-5.46h5.04l1.57-13.33h5.77l-1.57,13.33h7.66l-.63,5.46Z" style="fill:#231f20;"/><path d="M627.88,150.55c-1.15,7.56-4.62,16.69-13.75,16.69s-10.92-9.34-10.92-16.8c0-4.3.42-8.82,1.36-13.02,1.47-7.35,6.09-18.58,15.12-18.58s10.08,9.45,10.08,16.27c0,3.15-.31,6.09-.84,9.13h-19.42c-.31,2.1-.52,4.1-.52,6.19,0,3.99.21,11.23,5.67,11.23s6.61-7.14,7.35-11.13h5.88ZM623.89,139.21c.1-1.68.21-3.57.21-5.35,0-3.36-.31-9.55-4.93-9.55-6.09,0-8.29,10.4-9.03,14.91h13.75Z" style="fill:#231f20;"/><path d="M651.97,125.66c-7.88,0-8.61,6.09-9.34,12.39l-3.57,28.45h-5.88l5.88-46.93h5.77l-.74,6.09c2-3.36,4.41-6.61,8.71-6.82l-.84,6.82Z" style="fill:#231f20;"/><path d="M662.73,123.35c2.52-2.52,5.88-4.51,9.45-4.51,5.35,0,7.88,3.57,7.88,8.61,0,1.47-.11,2.94-.32,4.31l-4.2,34.75h-5.88l4.09-33.7c.21-1.36.42-2.73.42-4.09,0-2.83-1.47-5.04-4.41-5.04-6.4,0-7.88,6.19-8.4,11.23l-3.88,31.6h-5.88l5.77-46.93h5.78l-.42,3.78Z" style="fill:#231f20;"/><path d="M707.43,166.51h-5.77l.42-3.78c-2.42,2.73-4.83,4.51-8.5,4.51-7.24,0-8.61-6.82-8.61-12.6,0-7.87,1.47-23.52,5.46-30.24,2.1-3.36,5.67-5.56,9.76-5.56,3.15,0,5.04,1.15,6.82,3.88l.42-3.15h5.78l-5.78,46.93ZM700.92,123.56c-2.73,0-4.3,1.68-5.56,3.88-3.04,5.56-4.41,19.53-4.41,26.04,0,3.57.21,8.92,5.04,8.92,5.56,0,6.93-6.61,7.67-10.81,1.26-6.4,2.31-12.81,2.31-19.42,0-3.36-.52-8.61-5.04-8.61Z" style="fill:#231f20;"/><path d="M736.11,125.03h-7.77l-5.14,41.47h-5.77l5.14-41.47h-4.93l.63-5.46h5.04l1.58-13.33h5.78l-1.58,13.33h7.66l-.63,5.46Z" style="fill:#231f20;"/><path d="M741,166.51h-5.88l5.77-46.93h5.78l-5.67,46.93ZM745.09,109.18c-2.21,0-3.88-1.68-3.88-3.78,0-2.73,2.31-5.04,5.04-5.04,2.1,0,3.78,1.68,3.78,3.88,0,2.73-2.31,4.94-4.93,4.94Z" style="fill:#231f20;"/><path d="M777.6,133.85c0,10.5-2.1,33.39-16.48,33.39-9.55,0-11.03-9.45-11.03-17.01,0-10.39,3.15-31.39,16.9-31.39,7.67,0,10.61,6.51,10.61,13.23v1.78ZM766.26,124.3c-8.61,0-10.18,20.68-10.18,26.77,0,3.68.52,10.6,5.56,10.6,8.4,0,9.87-20.47,9.87-26.46,0-3.78-.11-10.92-5.25-10.92Z" style="fill:#231f20;"/><path d="M792.23,123.35c2.52-2.52,5.88-4.51,9.45-4.51,5.35,0,7.88,3.57,7.88,8.61,0,1.47-.11,2.94-.32,4.31l-4.2,34.75h-5.88l4.09-33.7c.21-1.36.42-2.73.42-4.09,0-2.83-1.47-5.04-4.41-5.04-6.4,0-7.88,6.19-8.4,11.23l-3.88,31.6h-5.88l5.77-46.93h5.78l-.42,3.78Z" style="fill:#231f20;"/><path d="M836.93,166.51h-5.77l.42-3.78c-2.42,2.73-4.83,4.51-8.5,4.51-7.24,0-8.61-6.82-8.61-12.6,0-7.87,1.47-23.52,5.46-30.24,2.1-3.36,5.67-5.56,9.76-5.56,3.15,0,5.04,1.15,6.82,3.88l.42-3.15h5.78l-5.78,46.93ZM830.42,123.56c-2.73,0-4.3,1.68-5.56,3.88-3.04,5.56-4.41,19.53-4.41,26.04,0,3.57.21,8.92,5.04,8.92,5.56,0,6.93-6.61,7.67-10.81,1.26-6.4,2.31-12.81,2.31-19.42,0-3.36-.52-8.61-5.04-8.61Z" style="fill:#231f20;"/><path d="M851.31,166.51h-5.88l9.45-76.54h5.78l-9.34,76.54Z" style="fill:#231f20;"/><path d="M650.67,220.69c-2.42-1.79-4.62-3.04-7.67-3.04-4.41,0-7.87,2.73-10.08,6.4-5.25,8.5-7.04,26.14-7.04,36.12,0,6.3.63,16.8,9.24,16.8,3.36,0,6.19-1.36,8.92-3.15l-.74,6.51c-2.83,1.79-5.98,2.94-9.34,2.94-12.07,0-14.91-12.81-14.91-22.47,0-12.28,3.04-32.65,10.71-42.42,3.36-4.2,8.19-7.03,13.65-7.03,2.83,0,5.77.52,8.08,2.21l-.84,7.14Z" style="fill:#231f20;"/><path d="M676.08,249.67c0,10.5-2.1,33.39-16.48,33.39-9.55,0-11.02-9.45-11.02-17.01,0-10.39,3.15-31.39,16.9-31.39,7.66,0,10.6,6.51,10.6,13.23v1.78ZM664.74,240.11c-8.61,0-10.18,20.68-10.18,26.77,0,3.68.53,10.6,5.56,10.6,8.4,0,9.87-20.47,9.87-26.46,0-3.78-.11-10.92-5.25-10.92Z" style="fill:#231f20;"/><path d="M685.47,282.32h-5.88l9.45-76.54h5.77l-9.34,76.54Z" style="fill:#231f20;"/><path d="M722.24,249.67c0,10.5-2.1,33.39-16.48,33.39-9.55,0-11.02-9.45-11.02-17.01,0-10.39,3.15-31.39,16.9-31.39,7.67,0,10.6,6.51,10.6,13.23v1.78ZM710.9,240.11c-8.61,0-10.18,20.68-10.18,26.77,0,3.68.53,10.6,5.56,10.6,8.4,0,9.87-20.47,9.87-26.46,0-3.78-.1-10.92-5.25-10.92Z" style="fill:#231f20;"/><path d="M744.54,241.48c-7.88,0-8.61,6.09-9.34,12.39l-3.57,28.45h-5.88l5.88-46.93h5.77l-.74,6.09c2-3.36,4.41-6.61,8.71-6.82l-.84,6.82Z" style="fill:#231f20;"/><path d="M1067.14,235.85c-6.88,0-12.45-5.58-12.45-12.45s5.58-12.46,12.45-12.46,12.42,5.62,12.42,12.46-5.54,12.45-12.42,12.45ZM1067.14,212.71c-5.87,0-10.51,4.82-10.51,10.65s4.64,10.73,10.51,10.73,10.47-4.9,10.47-10.69-4.57-10.69-10.47-10.69ZM1069.19,230.63l-2.95-6.34v6.34h-2.52v-14.51h3.31c2.99,0,4.17.97,4.17,4,0,1.8-.68,3.56-2.7,3.71l3.31,6.8h-2.63ZM1066.88,222.14c1.55,0,1.87-.76,1.87-2.16,0-1.51-.4-2.09-1.98-2.09h-.54v4.25h.65Z" style="fill:#231f20;"/><path d="M355.46,49.53c-6.88,0-12.45-5.58-12.45-12.45s5.58-12.46,12.45-12.46,12.42,5.62,12.42,12.46-5.54,12.45-12.42,12.45ZM355.46,26.39c-5.87,0-10.51,4.82-10.51,10.65s4.64,10.73,10.51,10.73,10.47-4.9,10.47-10.69-4.57-10.69-10.47-10.69ZM357.51,44.31l-2.95-6.34v6.34h-2.52v-14.51h3.31c2.99,0,4.18.97,4.18,4,0,1.8-.68,3.56-2.7,3.71l3.31,6.8h-2.63ZM355.21,35.82c1.55,0,1.87-.76,1.87-2.16,0-1.51-.4-2.09-1.98-2.09h-.54v4.25h.65Z" style="fill:#231f20;"/><polygon points="437.19 312.52 232.24 123.65 516.06 299.55 437.19 312.52" style="fill:#00aeef;"/><polyline points="568.51 266.35 232.24 123.65 516.02 299.54 568.51 266.35" style="fill:#fff200;"/><polygon points="604.4 223.52 567.74 267.13 232.24 123.65 604.4 223.52" style="fill:#231f20;"/><path d="M268.04,132.99s21.15-26.49,25.42-44.1c4.66-19.21-1.89-33.3-4.15-39.95-.84-2.49-1.56-6.23-1.56-6.23l56.56,8.3S266.57,17.25,234.81,6.36C224.42,2.79,202.45-.37,192.31.03c-50.93,2.01-83.71,29.27-92.07,37.88-7.48,7.71-51.64,59.4-54.8,63.94C32.27,120.77,0,140.08,0,140.08c0,0,28.11.98,44.92-11.24,27.17-19.75,36.73-33.62,39.43-37.36,1.95-2.69,8.42-9.83,10.38-9.86,3.11-.05,10.73,32.24,22.31,43.59,25.94,25.42,49.29,25.42,49.29,25.42,0,0-40.99-18.68-45.66-57.59-4.67-38.91,29.41-56.03,33.09-57.47,12.59-4.89,26.53-5.75,26.53-5.75,0,0-15.77,16.99-16.55,31.04-.52,9.33,11.29,48.22,30.09,48.26,16.77.03,32.78-25.03,30.61-43.07-2.19-18.18-6.75-38.91-6.75-38.91,0,0,23.1,2.93,43.59,21.79,9.04,8.32,21.27,23.87,17.12,45.14-4.15,21.27-17.81,37.08-17.81,37.08l7.44,1.84Z" style="fill:#231f20;"/><polygon points="232.24 123.65 353.3 310.86 437.46 312.5 232.24 123.65" style="fill:#ec008c;"/><path d="M796.99,221.63c-2.42-1.79-4.62-3.04-7.66-3.04-4.41,0-7.88,2.73-10.08,6.4-5.25,8.5-7.03,26.14-7.03,36.12,0,6.3.63,16.8,9.24,16.8,3.36,0,6.19-1.36,8.92-3.15l-.74,6.51c-2.83,1.79-5.98,2.94-9.34,2.94-12.07,0-14.91-12.81-14.91-22.47,0-12.28,3.04-32.65,10.71-42.42,3.36-4.2,8.19-7.03,13.65-7.03,2.83,0,5.77.52,8.08,2.21l-.84,7.14Z" style="fill:#231f20;"/><path d="M822.4,250.61c0,10.5-2.1,33.39-16.48,33.39-9.55,0-11.03-9.45-11.03-17.01,0-10.39,3.15-31.39,16.9-31.39,7.67,0,10.61,6.51,10.61,13.23v1.78ZM811.06,241.06c-8.61,0-10.18,20.68-10.18,26.77,0,3.67.52,10.6,5.56,10.6,8.4,0,9.87-20.47,9.87-26.46,0-3.78-.11-10.92-5.25-10.92Z" style="fill:#231f20;"/><path d="M837.04,240.11c2.52-2.52,5.88-4.51,9.45-4.51,5.35,0,7.88,3.57,7.88,8.61,0,1.47-.11,2.94-.32,4.31l-4.2,34.75h-5.88l4.09-33.7c.21-1.36.42-2.73.42-4.09,0-2.83-1.47-5.04-4.41-5.04-6.4,0-7.88,6.19-8.4,11.23l-3.88,31.6h-5.88l5.77-46.93h5.78l-.42,3.78Z" style="fill:#231f20;"/><path d="M879.84,245.89c-1.79-2.52-3.99-4.83-7.35-4.83-3.88,0-6.61,3.36-6.61,7.14,0,7.98,12.28,10.29,12.28,20.58,0,7.87-5.99,15.22-14.07,15.22-3.25,0-5.88-1.15-8.19-3.25l.73-6.93c2,2.52,4.2,4.62,7.67,4.62,4.41,0,7.66-4.1,7.66-8.29,0-7.98-12.18-11.55-12.18-21.1,0-7.24,5.46-13.44,12.91-13.44,3.15,0,5.56,1.05,7.88,3.04l-.74,7.24Z" style="fill:#231f20;"/><path d="M909.94,250.61c0,10.5-2.1,33.39-16.48,33.39-9.55,0-11.03-9.45-11.03-17.01,0-10.39,3.15-31.39,16.9-31.39,7.67,0,10.61,6.51,10.61,13.23v1.78ZM898.6,241.06c-8.61,0-10.18,20.68-10.18,26.77,0,3.67.52,10.6,5.56,10.6,8.4,0,9.87-20.47,9.87-26.46,0-3.78-.11-10.92-5.25-10.92Z" style="fill:#231f20;"/><path d="M932.24,242.42c-7.88,0-8.61,6.09-9.34,12.39l-3.57,28.45h-5.88l5.88-46.93h5.77l-.74,6.09c2-3.36,4.41-6.61,8.71-6.82l-.84,6.82Z" style="fill:#231f20;"/><path d="M954.07,241.79h-7.77l-5.14,41.47h-5.77l5.14-41.47h-4.93l.63-5.46h5.04l1.58-13.33h5.78l-1.58,13.33h7.66l-.63,5.46Z" style="fill:#231f20;"/><path d="M958.95,283.26h-5.88l5.77-46.93h5.78l-5.67,46.93ZM963.04,225.94c-2.21,0-3.88-1.68-3.88-3.78,0-2.73,2.31-5.04,5.04-5.04,2.1,0,3.78,1.68,3.78,3.88,0,2.73-2.31,4.94-4.93,4.94Z" style="fill:#231f20;"/><path d="M992.79,271.82c-.95,7.45-6.09,12.18-13.65,12.18-6.4,0-10.5-3.67-10.5-10.18,0-.63,0-1.36.1-1.99l4.3-35.49h5.88l-3.78,30.55c-.21,1.79-.42,3.67-.42,5.35,0,3.78,1.26,6.19,5.25,6.19,6.51,0,6.93-6.72,7.56-11.55l3.78-30.55h5.77l-4.3,35.49Z" style="fill:#231f20;"/><path d="M1011.05,240.22c2.52-2.52,5.56-4.62,8.92-4.62,3.99,0,6.61,1.78,7.88,5.46,2.94-3.15,5.77-5.46,10.29-5.46,5.77,0,8.61,3.15,8.61,8.4,0,1.47-.21,2.94-.42,4.31l-4.2,34.96h-5.88l4.3-34.75c.1-.84.21-1.89.21-2.83,0-3.15-1.26-5.25-4.62-5.25-2.94,0-5.77,2.1-6.93,4.83-.94,2.31-1.36,5.46-1.68,7.98l-3.67,30.03h-5.77l4.2-34.65c.11-.95.21-2.1.21-3.15,0-2.83-1.05-5.04-4.09-5.04-2.31,0-4.72,1.16-6.09,3.04-2.1,2.83-2.62,7.24-3.04,10.71l-3.57,29.08h-5.88l5.77-46.93h5.88l-.42,3.88Z" style="fill:#231f20;"/></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg id="uuid-3f899830-4184-486c-a566-1cffe215520e" xmlns="http://www.w3.org/2000/svg" width="204.03mm" height="109.78mm" viewBox="0 0 578.35 311.19"><g id="uuid-25784d54-943b-4b01-b576-3d7f69fdbce8"><polygon points="559.35 193.34 535.58 229.18 198.46 109.98 559.35 193.34" style="fill:#090909;"/><path d="M247.12,121.84c1.04-.29,26.48-26.16,16.58-45.06-10.14-19.37-18.37-28.88-41.23-37.17-2.3-.84-11.56-4.75-12.35-.96-.97,4.68,15.92,6.23,18.43,24.42.42,3.07,5.19,40.48-33.25,39.72-31.14-.61-32.48-28.24-32.17-33.4,1.17-19.86,19.05-24.37,17-28.89-3.43-7.57-49.76,5.93-49.11,43.12.52,29.72,31.74,51.88,45.55,62.27-11.77-3.6-27.1-9.3-40.92-17.32-28.63-16.6-28.79-33.39-29.04-43.08,0,0-24.83,28.9-48.85,40.91-27.03,13.51-38.77,9.08-38.77,9.08,0,0,19.27-7.09,52.72-43.64C93.75,67.76,118.45,6.77,204.34,10.37c62.03,2.6,72.5,30.07,133.15,45.47-25.32,3.44-61.51-4.64-61.51-4.64,0,0,6.14,1.23,7.87,25.16.91,12.49-5.46,35.11-21.28,49.12l-15.45-3.63Z" style="fill:#090909;"/><polygon points="198.46 109.98 467.57 269.5 392.69 278.54 198.46 109.98" style="fill:#359cd7;"/><polygon points="198.46 109.98 382.43 280.33 303.52 280.33 198.46 109.98" style="fill:#cd1e75;"/><path d="M275.49,234.83l-1-.5s.64-.13,1,.5Z" style="fill:#db3e92;"/><path d="M198.46,109.98c107.3,38.66,329.73,126.43,329.73,126.43l-51.94,28.36s-187.43-104.16-277.79-154.8Z" style="fill:#f0e92a;"/><path d="M234.49,130.83l-1.5-.5c.12.07.73.04,1.5.5Z" style="fill:#f4f5c6;"/></g><path d="M532.11,289.65c-9.12,0-16.53-7.41-16.53-16.53s7.41-16.53,16.53-16.53,16.48,7.45,16.48,16.53-7.36,16.53-16.48,16.53ZM532.11,258.93c-7.79,0-13.95,6.4-13.95,14.14s6.16,14.24,13.95,14.24,13.9-6.5,13.9-14.19-6.07-14.19-13.9-14.19ZM534.84,282.72l-3.92-8.41v8.41h-3.34v-19.25h4.4c3.97,0,5.54,1.29,5.54,5.3,0,2.39-.91,4.73-3.58,4.92l4.4,9.03h-3.49ZM531.78,271.45c2.05,0,2.48-1,2.48-2.87,0-2.01-.53-2.77-2.63-2.77h-.72v5.64h.86Z" style="fill:#231f20;"/></svg>
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg id="uuid-75011c32-23f5-4667-82af-3063520eb52e" xmlns="http://www.w3.org/2000/svg" width="213.22mm" height="110.25mm" viewBox="0 0 604.4 312.52"><path d="M355.46,49.53c-6.88,0-12.45-5.58-12.45-12.45s5.58-12.46,12.45-12.46,12.42,5.62,12.42,12.46-5.54,12.45-12.42,12.45ZM355.46,26.39c-5.87,0-10.51,4.82-10.51,10.65s4.64,10.73,10.51,10.73,10.47-4.9,10.47-10.69-4.57-10.69-10.47-10.69ZM357.51,44.31l-2.95-6.34v6.34h-2.52v-14.51h3.31c2.99,0,4.18.97,4.18,4,0,1.8-.68,3.56-2.7,3.71l3.31,6.8h-2.63ZM355.21,35.82c1.55,0,1.87-.76,1.87-2.16,0-1.51-.4-2.09-1.98-2.09h-.54v4.25h.65Z" style="fill:#231f20;"/><polygon points="437.19 312.52 232.24 123.65 516.06 299.55 437.19 312.52" style="fill:#00aeef;"/><polyline points="568.51 266.35 232.24 123.65 516.02 299.54 568.51 266.35" style="fill:#fff200;"/><polygon points="604.4 223.52 567.74 267.13 232.24 123.65 604.4 223.52" style="fill:#231f20;"/><path d="M268.04,132.99s21.15-26.49,25.42-44.1c4.66-19.21-1.89-33.3-4.15-39.95-.84-2.49-1.56-6.23-1.56-6.23l56.56,8.3S266.57,17.25,234.81,6.36C224.42,2.79,202.45-.37,192.31.03c-50.93,2.01-83.71,29.27-92.07,37.88-7.48,7.71-51.64,59.4-54.8,63.94C32.27,120.77,0,140.08,0,140.08c0,0,28.11.98,44.92-11.24,27.17-19.75,36.73-33.62,39.43-37.36,1.95-2.69,8.42-9.83,10.38-9.86,3.11-.05,10.73,32.24,22.31,43.59,25.94,25.42,49.29,25.42,49.29,25.42,0,0-40.99-18.68-45.66-57.59-4.67-38.91,29.41-56.03,33.09-57.47,12.59-4.89,26.53-5.75,26.53-5.75,0,0-15.77,16.99-16.55,31.04-.52,9.33,11.29,48.22,30.09,48.26,16.77.03,32.78-25.03,30.61-43.07-2.19-18.18-6.75-38.91-6.75-38.91,0,0,23.1,2.93,43.59,21.79,9.04,8.32,21.27,23.87,17.12,45.14-4.15,21.27-17.81,37.08-17.81,37.08l7.44,1.84Z" style="fill:#231f20;"/><polygon points="232.24 123.65 353.3 310.86 437.46 312.5 232.24 123.65" style="fill:#ec008c;"/></svg>
@@ -1,126 +1,326 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "yaml"
3
+ require_relative "taste_config"
4
4
 
5
5
  module Metanorma
6
6
  module Taste
7
+ # Base processor for taste-specific document attribute handling
8
+ #
9
+ # This class handles the processing of AsciiDoc attributes for taste-specific
10
+ # document generation, including file-based overrides, base configuration overrides,
11
+ # and doctype-specific transformations.
12
+ #
13
+ # @example Basic usage
14
+ # config = TasteConfig.from_yaml(yaml_content)
15
+ # base = Base.new("icc", config, directory: "data/icc")
16
+ #
17
+ # attrs = [":doctype: specification", ":title: My Document"]
18
+ # options = {}
19
+ # processed_attrs = base.process_input_adoc_overrides(attrs, options)
20
+ #
21
+ # @example Processing workflow
22
+ # # 1. File-based attributes are added (copyright, logo, i18n)
23
+ # # 2. Base override attributes are applied
24
+ # # 3. Doctype-specific transformations are performed
25
+ # # 4. Boilerplate authority is set in options if copyright exists
7
26
  class Base
8
- attr_reader :flavor, :config, :taste_info
27
+ # @return [String, Symbol] The flavor identifier (e.g., :icc, :elf)
28
+ attr_reader :flavor
9
29
 
10
- def initialize(flavor, taste_info)
30
+ # @return [TasteConfig] The taste configuration object
31
+ attr_reader :config
32
+
33
+ # Mapping of base override configuration keys to AsciiDoc attribute names
34
+ #
35
+ # This constant defines how base_override configuration properties
36
+ # are translated into AsciiDoc document attributes.
37
+ #
38
+ # @example Configuration to attribute mapping
39
+ # config.base_override.publisher => :publisher:
40
+ # config.base_override.presentation_metadata_color_secondary => :presentation-metadata-color-secondary:
41
+ BASE_OVERRIDE_MAPPINGS = {
42
+ publisher: "publisher",
43
+ publisher_abbr: "publisher_abbr",
44
+ presentation_metadata_color_secondary: "presentation-metadata-color-secondary",
45
+ presentation_metadata_backcover_text: "presentation-metadata-backcover-text",
46
+ }.freeze
47
+
48
+ # Initialize a new Base processor
49
+ #
50
+ # @param flavor [String, Symbol] The taste flavor identifier
51
+ # @param config [TasteConfig] The taste configuration object
52
+ # @param directory [String] The base directory for taste files (default: current directory)
53
+ #
54
+ # @example
55
+ # config = TasteConfig.from_yaml(File.read("config.yaml"))
56
+ # base = Base.new("icc", config, directory: "data/icc")
57
+ def initialize(flavor, config, directory: Dir.pwd)
11
58
  @flavor = flavor
12
- @taste_info = taste_info
13
- @config = taste_info[:config]
59
+ @config = config
60
+ @directory = directory
14
61
  end
15
62
 
63
+ # Process input AsciiDoc attributes with taste-specific overrides
64
+ #
65
+ # This is the main entry point for attribute processing. It applies
66
+ # file-based overrides, base configuration overrides, and doctype
67
+ # transformations to the input attributes.
68
+ #
69
+ # @param attrs [Array<String>] Array of AsciiDoc attribute strings
70
+ # @param options [Hash] Options hash that may be modified with additional settings
71
+ # @return [Array<String>] Modified array of AsciiDoc attributes
72
+ #
73
+ # @example
74
+ # attrs = [":doctype: specification", ":title: My Document"]
75
+ # options = {}
76
+ # result = base.process_input_adoc_overrides(attrs, options)
77
+ # # => [":doctype: specification", ":title: My Document", ":publisher: ICC", ...]
16
78
  def process_input_adoc_overrides(attrs, options)
17
- # Insert after the second element (index 1)
18
- # If attrs has fewer than 2 elements, this will handle it appropriately
19
- insertion_index = [attrs.length, 2].min
20
-
21
- attrs, new_attrs = build_attribute_overrides(attrs)
22
- attrs.insert(insertion_index, *new_attrs) unless new_attrs.empty?
79
+ # Insert new attributes after the second element (or at the end if fewer elements)
80
+ insertion_index = calculate_insertion_index(attrs)
23
81
 
24
- # Set boilerplate authority if copyright notice exists
25
- copyright_file = copyright_notice_path
26
- if copyright_file && File.exist?(copyright_file)
27
- options[":boilerplate-authority:"] = copyright_file
82
+ # Build and insert override attributes
83
+ attrs, override_attrs = build_all_attribute_overrides(attrs)
84
+ unless override_attrs.empty?
85
+ attrs.insert(insertion_index,
86
+ *override_attrs)
28
87
  end
29
88
 
89
+ # Set boilerplate authority in options if copyright notice exists
90
+ set_boilerplate_authority_option(options)
91
+
30
92
  attrs
31
93
  end
32
94
 
33
95
  private
34
96
 
35
- def build_attribute_overrides(attrs)
36
- overrides = []
37
- #build_attribute_copyright_overrides(overrides)
38
- #build_attribute_i18n_overrides(overrides)
39
- #build_attribute_publisher_logo_overrides(overrides)
40
- file_attr_override(:copyright_notice, "boilerplate-authority", overrides)
41
- file_attr_override(:publisher_logo, "publisher_logo", overrides)
42
- file_attr_override(:i18n_dictionary, "i18nyaml", overrides)
43
- # Add base-override attributes
44
- @taste_info[:base_override].each do |key, value|
45
- overrides << ":#{key}: #{value}"
46
- end
47
- build_attribute_doctype_overrides(attrs, overrides)
48
- [attrs, overrides]
97
+ # Calculate the appropriate insertion index for new attributes
98
+ #
99
+ # Attributes are inserted after the second element to maintain
100
+ # proper AsciiDoc document structure.
101
+ #
102
+ # @param attrs [Array] The attributes array
103
+ # @return [Integer] The insertion index
104
+ def calculate_insertion_index(attrs)
105
+ [attrs.length, 2].min
49
106
  end
50
107
 
51
- # Add copyright notice if available
52
- def build_attribute_copyright_overrides(overrides)
53
- copyright_file = copyright_notice_path
54
- if copyright_file && File.exist?(copyright_file)
55
- overrides << ":boilerplate-authority: #{copyright_file}"
56
- end
108
+ # Build all attribute overrides from various sources
109
+ #
110
+ # This method coordinates the building of attributes from:
111
+ # - File-based sources (copyright, logo, i18n)
112
+ # - Base override configuration
113
+ # - Doctype-specific overrides
114
+ #
115
+ # @param attrs [Array<String>] Original attributes array
116
+ # @return [Array<Array<String>, Array<String>>] Tuple of [original_attrs, override_attrs]
117
+ def build_all_attribute_overrides(attrs)
118
+ override_attrs = []
119
+
120
+ # Add attributes from different sources
121
+ add_file_based_overrides(override_attrs)
122
+ add_base_configuration_overrides(override_attrs)
123
+ apply_doctype_overrides(attrs, override_attrs)
124
+
125
+ [attrs, override_attrs]
57
126
  end
58
127
 
59
- # Add copyright notice if available
60
- def build_attribute_publisher_logo_overrides(overrides)
61
- copyright_file = publisher_logo_path
62
- if copyright_file && File.exist?(copyright_file)
63
- overrides << ":publisher_logo: #{copyright_file}"
128
+ # Add file-based attribute overrides
129
+ #
130
+ # Processes file-based configuration properties and adds corresponding
131
+ # attributes if the files exist.
132
+ #
133
+ # @param override_attrs [Array<String>] Array to append override attributes to
134
+ def add_file_based_overrides(override_attrs)
135
+ file_override_mappings.each do |config_attr, attr_name|
136
+ add_file_override(override_attrs, config_attr, attr_name)
64
137
  end
65
138
  end
66
139
 
67
- # Add i18n dictionary if available
68
- def build_attribute_i18n_overrides(overrides)
69
- i18n_file = i18n_dictionary_path
70
- if i18n_file && File.exist?(i18n_file)
71
- overrides << ":i18nyaml: #{i18n_file}"
72
- end
140
+ # Get the mapping of file-based configuration attributes to AsciiDoc attributes
141
+ #
142
+ # @return [Hash<Symbol, String>] Mapping of config attributes to AsciiDoc attribute names
143
+ def file_override_mappings
144
+ {
145
+ copyright_notice: "boilerplate-authority",
146
+ publisher_logo: "publisher_logo",
147
+ i18n_dictionary: "i18nyaml",
148
+ }
149
+ end
150
+
151
+ # Add a single file-based override attribute
152
+ #
153
+ # @param override_attrs [Array<String>] Array to append to
154
+ # @param config_attr [Symbol] Configuration attribute name
155
+ # @param attr_name [String] AsciiDoc attribute name
156
+ def add_file_override(override_attrs, config_attr, attr_name)
157
+ filepath = file_path_for(config_attr)
158
+ return unless filepath && File.exist?(filepath)
159
+
160
+ override_attrs << ":#{attr_name}: #{filepath}"
161
+ end
162
+
163
+ # Get the full file path for a configuration attribute
164
+ #
165
+ # @param config_attr [Symbol] The configuration attribute name
166
+ # @return [String, nil] The full file path, or nil if not configured
167
+ #
168
+ # @example
169
+ # file_path_for(:copyright_notice) # => "data/icc/copyright.adoc"
170
+ # file_path_for(:publisher_logo) # => "data/icc/logo.svg"
171
+ def file_path_for(config_attr)
172
+ filename = @config.send(config_attr)
173
+ return nil unless filename
174
+
175
+ File.join(@directory, filename)
73
176
  end
74
177
 
75
- def file_attr_override(source_attr_name, target_attr_name, overrides)
76
- s = @taste_info[source_attr_name] or return nil
77
- f = File.join(@taste_info[:directory], s)
78
- if f && File.exist?(f)
79
- overrides << ":#{target_attr_name}: #{f}"
178
+ # Add base configuration override attributes
179
+ #
180
+ # Processes base_override configuration and adds corresponding
181
+ # AsciiDoc attributes for each configured property.
182
+ #
183
+ # @param override_attrs [Array<String>] Array to append override attributes to
184
+ def add_base_configuration_overrides(override_attrs)
185
+ return unless @config.base_override
186
+
187
+ BASE_OVERRIDE_MAPPINGS.each do |config_key, attr_key|
188
+ value = @config.base_override.send(config_key)
189
+ next unless value
190
+
191
+ override_attrs << ":#{attr_key}: #{value}"
80
192
  end
81
193
  end
82
194
 
83
- def build_attribute_doctype_overrides(attrs, overrides)
84
- doctype_idx, dt = build_attribute_doctype_overrides_prep(attrs)
85
- dt.nil? and return
86
- overrides << ":presentation-metadata-doctype-alias: #{dt['taste']}"
87
- attrs[doctype_idx] = ":doctype: #{dt['base']}"
88
- dt["override_attributes"]&.each do |key, value|
89
- overrides << ":#{key}: #{value}"
195
+ # Apply doctype-specific overrides and transformations
196
+ #
197
+ # This method handles the transformation of doctype attributes based on
198
+ # taste-specific doctype configurations. It:
199
+ # 1. Finds the doctype attribute in the input
200
+ # 2. Looks up the corresponding doctype configuration
201
+ # 3. Transforms the doctype value (taste -> base)
202
+ # 4. Adds doctype-specific override attributes
203
+ #
204
+ # @param attrs [Array<String>] The attributes array (modified in place)
205
+ # @param override_attrs [Array<String>] Array to append override attributes to
206
+ def apply_doctype_overrides(attrs, override_attrs)
207
+ doctype_index = find_doctype_attribute_index(attrs)
208
+ return unless doctype_index
209
+
210
+ current_doctype = extract_doctype_value(attrs[doctype_index])
211
+ doctype_config = find_doctype_configuration(current_doctype)
212
+ return unless doctype_config
213
+
214
+ # Transform the doctype attribute
215
+ transform_doctype_attribute(attrs, doctype_index, doctype_config)
216
+
217
+ # Add doctype-specific overrides
218
+ add_doctype_specific_overrides(override_attrs, doctype_config)
219
+ end
220
+
221
+ # Find the index of the doctype attribute in the attributes array
222
+ #
223
+ # @param attrs [Array<String>] The attributes array
224
+ # @return [Integer, nil] The index of the doctype attribute, or nil if not found
225
+ def find_doctype_attribute_index(attrs)
226
+ attrs.index { |attr| attr.match?(/^:doctype:/) }
227
+ end
228
+
229
+ # Extract the doctype value from a doctype attribute string
230
+ #
231
+ # @param doctype_attr [String] The doctype attribute string (e.g., ":doctype: specification")
232
+ # @return [String] The doctype value (e.g., "specification")
233
+ def extract_doctype_value(doctype_attr)
234
+ doctype_attr.sub(/^:doctype:/, "").strip
235
+ end
236
+
237
+ # Find the doctype configuration for a given taste doctype
238
+ #
239
+ # @param taste_doctype [String] The taste-specific doctype name
240
+ # @return [DoctypeConfig, nil] The doctype configuration, or nil if not found
241
+ def find_doctype_configuration(taste_doctype)
242
+ @config.doctypes&.detect { |dt| dt.taste == taste_doctype }
243
+ end
244
+
245
+ # Transform the doctype attribute from taste-specific to base doctype
246
+ #
247
+ # @param attrs [Array<String>] The attributes array (modified in place)
248
+ # @param doctype_index [Integer] The index of the doctype attribute
249
+ # @param doctype_config [DoctypeConfig] The doctype configuration
250
+ def transform_doctype_attribute(attrs, doctype_index, doctype_config)
251
+ attrs[doctype_index] = ":doctype: #{doctype_config.base}"
252
+ end
253
+
254
+ # Add doctype-specific override attributes
255
+ #
256
+ # @param override_attrs [Array<String>] Array to append override attributes to
257
+ # @param doctype_config [DoctypeConfig] The doctype configuration
258
+ def add_doctype_specific_overrides(override_attrs, doctype_config)
259
+ # Add the doctype alias for presentation metadata
260
+ override_attrs << ":presentation-metadata-doctype-alias: #{doctype_config.taste}"
261
+
262
+ # Add any additional override attributes defined in the doctype configuration
263
+ add_doctype_override_attributes(override_attrs, doctype_config)
264
+ end
265
+
266
+ # Add override attributes defined in the doctype configuration
267
+ #
268
+ # The override_attributes property contains an array of hash objects,
269
+ # where each hash contains key-value pairs for attribute overrides.
270
+ #
271
+ # @param override_attrs [Array<String>] Array to append override attributes to
272
+ # @param doctype_config [DoctypeConfig] The doctype configuration
273
+ def add_doctype_override_attributes(override_attrs, doctype_config)
274
+ return unless doctype_config.override_attributes
275
+
276
+ doctype_config.override_attributes.each do |attr_hash|
277
+ attr_hash.each do |key, value|
278
+ override_attrs << ":#{key}: #{value}"
279
+ end
90
280
  end
91
281
  end
92
282
 
93
- def build_attribute_doctype_overrides_prep(attrs)
94
- doctype_idx = attrs.index { |e| /^:doctype:/.match?(e) } or
95
- return [nil, nil, nil]
96
- old_doctype = attrs[doctype_idx].sub(/^:doctype:/, "").strip
97
- dt = @taste_info[:doctypes].detect do |e|
98
- e["taste"] == old_doctype
99
- end or return [nil, nil, nil]
100
- [doctype_idx, dt]
283
+ # Set the boilerplate authority option if copyright notice exists
284
+ #
285
+ # This method checks for the existence of a copyright notice file
286
+ # and sets the appropriate option for boilerplate processing.
287
+ #
288
+ # @param options [Hash] Options hash to modify
289
+ def set_boilerplate_authority_option(options)
290
+ copyright_file = copyright_notice_path
291
+ return unless copyright_file && File.exist?(copyright_file)
292
+
293
+ options[":boilerplate-authority:"] = copyright_file
101
294
  end
102
295
 
296
+ # Get the full path to the copyright notice file
297
+ #
298
+ # @return [String, nil] The copyright notice file path, or nil if not configured
299
+ #
300
+ # @example
301
+ # copyright_notice_path # => "data/icc/copyright.adoc"
103
302
  def copyright_notice_path
104
- @taste_info[:copyright_notice] or return nil
105
- File.join(@taste_info[:directory], @taste_info[:copyright_notice])
303
+ file_path_for(:copyright_notice)
106
304
  end
107
305
 
306
+ # Get the full path to the publisher logo file
307
+ #
308
+ # @return [String, nil] The publisher logo file path, or nil if not configured
309
+ #
310
+ # @example
311
+ # publisher_logo_path # => "data/icc/logo.svg"
108
312
  def publisher_logo_path
109
- @taste_info[:publisher_logo] or return nil
110
- File.join(@taste_info[:directory], @taste_info[:publisher_logo])
313
+ file_path_for(:publisher_logo)
111
314
  end
112
315
 
316
+ # Get the full path to the i18n dictionary file
317
+ #
318
+ # @return [String, nil] The i18n dictionary file path, or nil if not configured
319
+ #
320
+ # @example
321
+ # i18n_dictionary_path # => "data/icc/i18n.yaml"
113
322
  def i18n_dictionary_path
114
- @taste_info[:i18n_dictionary] or return nil
115
- File.join(@taste_info[:directory], @taste_info[:i18n_dictionary])
116
- end
117
-
118
- def load_i18n_dictionary
119
- i18n_file = i18n_dictionary_path
120
- i18n_file && File.exist?(i18n_file) or return {}
121
- YAML.load_file(i18n_file)
122
- rescue StandardError
123
- {}
323
+ file_path_for(:i18n_dictionary)
124
324
  end
125
325
  end
126
326
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Metanorma
6
+ module Taste
7
+ # Model for base-override configuration
8
+ class BaseOverride < Lutaml::Model::Serializable
9
+ attribute :publisher, :string
10
+ attribute :publisher_abbr, :string
11
+ attribute :presentation_metadata_color_secondary, :string
12
+ attribute :presentation_metadata_backcover_text, :string
13
+
14
+ key_value do
15
+ map "publisher", to: :publisher
16
+ map "publisher_abbr", to: :publisher_abbr
17
+ map "presentation-metadata-color-secondary",
18
+ to: :presentation_metadata_color_secondary
19
+ map "presentation-metadata-backcover-text",
20
+ to: :presentation_metadata_backcover_text
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+
5
+ module Metanorma
6
+ module Taste
7
+ # Model for individual doctype configuration
8
+ class DoctypeConfig < Lutaml::Model::Serializable
9
+ attribute :taste, :string
10
+ attribute :base, :string
11
+ attribute :override_attributes, :hash, collection: true
12
+
13
+ key_value do
14
+ map "taste", to: :taste
15
+ map "base", to: :base
16
+ map "override-attributes", to: :override_attributes
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "lutaml/model"
4
+ require_relative "base_override"
5
+ require_relative "doctype_config"
6
+
7
+ module Metanorma
8
+ module Taste
9
+ # Main configuration model
10
+ class TasteConfig < Lutaml::Model::Serializable
11
+ attribute :flavor, :string
12
+ attribute :owner, :string
13
+ attribute :base_flavor, :string
14
+ attribute :copyright_notice, :string
15
+ attribute :i18n_dictionary, :string
16
+ attribute :publisher_logo, :string
17
+ attribute :base_override, BaseOverride
18
+ attribute :doctypes, DoctypeConfig, collection: true
19
+ attribute :directory, :string
20
+
21
+ key_value do
22
+ map "flavor", to: :flavor
23
+ map "owner", to: :owner
24
+ map "base-flavor", to: :base_flavor
25
+ map "copyright-notice", to: :copyright_notice
26
+ map "i18n-dictionary", to: :i18n_dictionary
27
+ map "publisher-logo", to: :publisher_logo
28
+ map "base-override", to: :base_override
29
+ map "doctypes", to: :doctypes
30
+ end
31
+ end
32
+ end
33
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Metanorma
4
4
  module Taste
5
- VERSION = "0.0.4"
5
+ VERSION = "0.1.1"
6
6
  end
7
7
  end
@@ -1,103 +1,241 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "yaml"
4
3
  require "singleton"
4
+ require_relative "taste/taste_config"
5
+ require_relative "taste/base"
5
6
 
6
7
  module Metanorma
8
+ # Registry for managing and providing access to taste configurations
9
+ #
10
+ # This singleton class automatically discovers taste configurations from the data directory,
11
+ # loads them using lutaml-model, and provides a centralized registry for accessing
12
+ # taste instances and their metadata.
13
+ #
14
+ # @example Basic usage
15
+ # # Get a taste instance
16
+ # icc_taste = TasteRegister.get("icc")
17
+ #
18
+ # # List available tastes
19
+ # TasteRegister.available_tastes
20
+ # # => [:icc, :elf, :enosema]
21
+ #
22
+ # # Get taste configuration
23
+ # config = TasteRegister.get_config("icc")
24
+ # # => #<Metanorma::Taste::TasteConfig:...>
25
+ # puts config.owner # => "International Color Consortium"
7
26
  class TasteRegister
8
27
  include Singleton
9
28
 
29
+ # Error raised when an unknown taste is requested
30
+ class UnknownTasteError < StandardError; end
31
+
32
+ # Error raised when taste configuration is invalid
33
+ class InvalidTasteConfigError < StandardError; end
34
+
10
35
  def initialize
11
- @tastes = {}
12
- @taste_classes = {}
13
- scan_data_directory
36
+ @taste_configs = {}
37
+ @taste_instances = {}
38
+ discover_and_load_tastes
14
39
  end
15
40
 
41
+ # Get a taste instance by flavor name
42
+ #
43
+ # @param flavor [String, Symbol] The flavor name (e.g., "icc", "elf")
44
+ # @return [Taste::Base] The taste instance
45
+ # @raise [UnknownTasteError] If the flavor is not registered
46
+ #
47
+ # @example
48
+ # taste = TasteRegister.get("icc")
49
+ # taste.process_input_adoc_overrides(attrs, options)
16
50
  def self.get(flavor)
17
51
  instance.get(flavor)
18
52
  end
19
53
 
54
+ # Get a taste instance by flavor name
55
+ #
56
+ # @param flavor [String, Symbol] The flavor name
57
+ # @return [Taste::Base] The taste instance
58
+ # @raise [UnknownTasteError] If the flavor is not registered
20
59
  def get(flavor)
21
- flavor_sym = flavor.to_sym
22
- return @taste_classes[flavor_sym] if @taste_classes[flavor_sym]
60
+ flavor_sym = normalize_flavor_name(flavor)
61
+
62
+ return @taste_instances[flavor_sym] if @taste_instances[flavor_sym]
23
63
 
24
- config = @tastes[flavor_sym]
25
- raise "Unknown taste: #{flavor}" unless config
64
+ config = @taste_configs[flavor_sym]
65
+ raise UnknownTasteError, "Unknown taste: #{flavor}" unless config
26
66
 
27
- # Dynamically create and cache the taste class
28
- @taste_classes[flavor_sym] = create_taste_class(flavor_sym, config)
67
+ @taste_instances[flavor_sym] = create_taste_instance(flavor_sym, config)
29
68
  end
30
69
 
70
+ # Get list of available taste flavors
71
+ #
72
+ # @return [Array<Symbol>] Array of available flavor names
73
+ #
74
+ # @example
75
+ # TasteRegister.available_tastes
76
+ # # => [:icc, :elf, :enosema]
31
77
  def available_tastes
32
- @tastes.keys
78
+ @taste_configs.keys
33
79
  end
34
80
 
35
- def taste_info(flavor)
36
- @tastes[flavor.to_sym]
81
+ # Get detailed information about a specific taste
82
+ #
83
+ # @param flavor [String, Symbol] The flavor name
84
+ # @return [TasteConfig, nil] The taste configuration object, or nil if not found
85
+ #
86
+ # @example
87
+ # config = TasteRegister.get_config("icc")
88
+ # puts config.owner # => "International Color Consortium"
89
+ def self.get_config(flavor)
90
+ instance.get_config(flavor)
91
+ end
92
+
93
+ def get_config(flavor)
94
+ flavor_sym = normalize_flavor_name(flavor)
95
+ config = @taste_configs[flavor_sym]
96
+ return nil unless config
97
+
98
+ # Set the directory on the config object
99
+ config.directory = config_directory_for(flavor_sym)
100
+ config
101
+ end
102
+
103
+ # Get flavor aliases mapping
104
+ #
105
+ # @return [Hash<Symbol, Symbol>] Mapping of flavor to base_flavor
106
+ #
107
+ # @example
108
+ # aliases = TasteRegister.instance.aliases
109
+ # # => { icc: :iso, elf: :iso, enosema: :iso }
110
+ def self.aliases
111
+ instance.aliases
37
112
  end
38
113
 
39
114
  def aliases
40
- # Build aliases dynamically from registered tastes
41
- aliases = {}
42
- @tastes.each do |flavor, info|
43
- aliases[flavor] = info[:base_flavor] if info[:base_flavor]
115
+ @taste_configs.each_with_object({}) do |(flavor, config), aliases|
116
+ aliases[flavor] = config.base_flavor&.to_sym if config.base_flavor
44
117
  end
45
- aliases
46
118
  end
47
119
 
48
120
  private
49
121
 
50
- def scan_data_directory
51
- data_dir = File.join(File.dirname(__FILE__), "..", "..", "data")
52
- return unless Dir.exist?(data_dir)
122
+ # Discover and load all taste configurations from the data directory
123
+ #
124
+ # Scans the data directory for subdirectories containing config.yaml files,
125
+ # loads each configuration using lutaml-model, and registers them.
126
+ def discover_and_load_tastes
127
+ data_directory_path = data_directory
128
+ return unless data_directory_path && Dir.exist?(data_directory_path)
53
129
 
54
- Dir.entries(data_dir).each do |entry|
55
- next if entry.start_with?(".")
130
+ taste_directories = find_taste_directories(data_directory_path)
131
+ taste_directories.each { |dir| load_taste_from_directory(dir) }
132
+ end
56
133
 
57
- taste_dir = File.join(data_dir, entry)
58
- next unless Dir.exist?(taste_dir)
134
+ # Get the path to the data directory
135
+ #
136
+ # @return [String] Path to the data directory
137
+ def data_directory
138
+ File.join(File.dirname(__FILE__), "..", "..", "data")
139
+ end
59
140
 
60
- config_file = File.join(taste_dir, "config.yaml")
61
- next unless File.exist?(config_file)
141
+ # Find all valid taste directories in the data directory
142
+ #
143
+ # @param data_dir [String] Path to the data directory
144
+ # @return [Array<String>] Array of taste directory paths
145
+ def find_taste_directories(data_dir)
146
+ Dir.entries(data_dir)
147
+ .reject { |entry| entry.start_with?(".") }
148
+ .map { |entry| File.join(data_dir, entry) }
149
+ .select { |path| Dir.exist?(path) && has_config_file?(path) }
150
+ end
62
151
 
63
- register_taste(entry, taste_dir, config_file)
152
+ # Check if a directory contains a config.yaml file
153
+ #
154
+ # @param directory [String] Directory path to check
155
+ # @return [Boolean] True if config.yaml exists
156
+ def has_config_file?(directory)
157
+ File.exist?(File.join(directory, "config.yaml"))
158
+ end
159
+
160
+ # Load and register a taste configuration from a directory
161
+ #
162
+ # @param taste_directory [String] Path to the taste directory
163
+ # @raise [InvalidTasteConfigError] If the configuration is invalid
164
+ def load_taste_from_directory(taste_directory)
165
+ config_file = File.join(taste_directory, "config.yaml")
166
+ directory_name = File.basename(taste_directory)
167
+
168
+ begin
169
+ config_content = File.read(config_file)
170
+ config = Taste::TasteConfig.from_yaml(config_content)
171
+
172
+ validate_taste_config!(config, directory_name)
173
+ register_taste_config(config, taste_directory)
174
+ rescue StandardError => e
175
+ raise InvalidTasteConfigError,
176
+ "Failed to load taste from #{taste_directory}: #{e.message}"
64
177
  end
65
178
  end
66
179
 
67
- def register_taste(directory_name, taste_dir, config_file)
68
- config = YAML.load_file(config_file)
69
- flavor = config["flavor"]&.to_sym || directory_name.to_sym
70
-
71
- @tastes[flavor] = {
72
- flavor: flavor,
73
- owner: config["owner"],
74
- base_flavor: config["base-flavor"]&.to_sym,
75
- directory: taste_dir,
76
- config: config,
77
- copyright_notice: config["copyright-notice"],
78
- i18n_dictionary: config["i18n-dictionary"],
79
- publisher_logo: config["publisher-logo"],
80
- base_override: config["base-override"] || {},
81
- doctypes: config["doctypes"] || {}
82
- }
83
- end
84
-
85
- def create_taste_class(flavor, config)
86
- # Create a dynamic class that inherits from Base
87
- taste_class = Class.new(Taste::Base) do
88
- define_method :initialize do
89
- super(flavor, config)
90
- end
180
+ # Validate that a taste configuration is complete and valid
181
+ #
182
+ # @param config [Taste::TasteConfig] The configuration to validate
183
+ # @param directory_name [String] The directory name for fallback
184
+ # @raise [InvalidTasteConfigError] If validation fails
185
+ def validate_taste_config!(config, directory_name)
186
+ unless config.flavor || directory_name
187
+ raise InvalidTasteConfigError, "Taste must have a flavor name"
91
188
  end
189
+ end
190
+
191
+ # Register a taste configuration in the registry
192
+ #
193
+ # @param config [Taste::TasteConfig] The configuration to register
194
+ # @param directory [String] The taste directory path
195
+ def register_taste_config(config, directory)
196
+ # Use config flavor or fall back to directory name
197
+ flavor = config.flavor&.to_sym || File.basename(directory).to_sym
198
+
199
+ # Store the config and remember its directory
200
+ @taste_configs[flavor] = config
201
+ @config_directories ||= {}
202
+ @config_directories[flavor] = directory
203
+ end
92
204
 
93
- # Define the class constant dynamically
94
- class_name = flavor.to_s.split(/[-_]/).map(&:capitalize).join
205
+ # Create a taste instance for the given flavor and configuration
206
+ #
207
+ # @param flavor [Symbol] The flavor name
208
+ # @param config [Taste::TasteConfig] The taste configuration
209
+ # @return [Taste::Base] The created taste instance
210
+ def create_taste_instance(flavor, config)
211
+ directory = config_directory_for(flavor)
212
+
213
+ # Create dynamic class if it doesn't exist
214
+ class_name = flavor.to_s.capitalize
95
215
  unless Taste.const_defined?(class_name)
96
- Taste.const_set(class_name,
97
- taste_class)
216
+ Taste.const_set(class_name, Class.new(Taste::Base))
98
217
  end
99
218
 
100
- taste_class.new
219
+ # Create instance of the dynamic class
220
+ dynamic_class = Taste.const_get(class_name)
221
+ dynamic_class.new(flavor, config, directory: directory)
222
+ end
223
+
224
+ # Get the directory path for a registered flavor
225
+ #
226
+ # @param flavor [Symbol] The flavor name
227
+ # @return [String] The directory path
228
+ def config_directory_for(flavor)
229
+ @config_directories ||= {}
230
+ @config_directories[flavor] || File.join(data_directory, flavor.to_s)
231
+ end
232
+
233
+ # Normalize flavor name to symbol
234
+ #
235
+ # @param flavor [String, Symbol] The flavor name
236
+ # @return [Symbol] Normalized flavor name
237
+ def normalize_flavor_name(flavor)
238
+ flavor.to_sym
101
239
  end
102
240
  end
103
241
  end
@@ -32,18 +32,5 @@ Gem::Specification.new do |spec|
32
32
  spec.bindir = "bin"
33
33
  spec.require_paths = ["lib"]
34
34
 
35
- spec.add_development_dependency "debug"
36
- spec.add_development_dependency "equivalent-xml", "~> 0.6"
37
- spec.add_development_dependency "metanorma"
38
- spec.add_development_dependency "metanorma-iso"
39
- spec.add_development_dependency "mnconvert"
40
- spec.add_development_dependency "pry"
41
- spec.add_development_dependency "rake", "~> 13.0"
42
- spec.add_development_dependency "rspec", "~> 3.0"
43
- spec.add_development_dependency "rspec-command", "~> 1.0"
44
- spec.add_development_dependency "rubocop", "~> 1"
45
- spec.add_development_dependency "rubocop-performance"
46
- spec.add_development_dependency "sassc-embedded", "~> 1"
47
- spec.add_development_dependency "simplecov", "~> 0.15"
48
- spec.add_development_dependency "xml-c14n"
35
+ spec.add_dependency "lutaml-model", "~>0.7"
49
36
  end
metadata CHANGED
@@ -1,211 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metanorma-taste
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-07-01 00:00:00.000000000 Z
11
+ date: 2025-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: debug
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: equivalent-xml
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '0.6'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '0.6'
41
- - !ruby/object:Gem::Dependency
42
- name: metanorma
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: metanorma-iso
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: mnconvert
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: pry
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: rake
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '13.0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '13.0'
111
- - !ruby/object:Gem::Dependency
112
- name: rspec
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '3.0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '3.0'
125
- - !ruby/object:Gem::Dependency
126
- name: rspec-command
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '1.0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '1.0'
139
- - !ruby/object:Gem::Dependency
140
- name: rubocop
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - "~>"
144
- - !ruby/object:Gem::Version
145
- version: '1'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '1'
153
- - !ruby/object:Gem::Dependency
154
- name: rubocop-performance
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - ">="
165
- - !ruby/object:Gem::Version
166
- version: '0'
167
- - !ruby/object:Gem::Dependency
168
- name: sassc-embedded
14
+ name: lutaml-model
169
15
  requirement: !ruby/object:Gem::Requirement
170
16
  requirements:
171
17
  - - "~>"
172
18
  - !ruby/object:Gem::Version
173
- version: '1'
174
- type: :development
19
+ version: '0.7'
20
+ type: :runtime
175
21
  prerelease: false
176
22
  version_requirements: !ruby/object:Gem::Requirement
177
23
  requirements:
178
24
  - - "~>"
179
25
  - !ruby/object:Gem::Version
180
- version: '1'
181
- - !ruby/object:Gem::Dependency
182
- name: simplecov
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - "~>"
186
- - !ruby/object:Gem::Version
187
- version: '0.15'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - "~>"
193
- - !ruby/object:Gem::Version
194
- version: '0.15'
195
- - !ruby/object:Gem::Dependency
196
- name: xml-c14n
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - ">="
200
- - !ruby/object:Gem::Version
201
- version: '0'
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - ">="
207
- - !ruby/object:Gem::Version
208
- version: '0'
26
+ version: '0.7'
209
27
  description: Library to process and handle default Metanorma Tastes, providing configuration-driven
210
28
  customization of Metanorma flavours.
211
29
  email:
@@ -233,10 +51,16 @@ files:
233
51
  - data/icc/config.yaml
234
52
  - data/icc/copyright.adoc
235
53
  - data/icc/i18n.yaml
236
- - data/icc/icc.png
54
+ - data/icc/icc-full-new.svg
55
+ - data/icc/icc-full.svg
56
+ - data/icc/icc-small-new.svg
57
+ - data/icc/icc-small.svg
237
58
  - lib/metanorma-taste.rb
238
59
  - lib/metanorma/taste.rb
239
60
  - lib/metanorma/taste/base.rb
61
+ - lib/metanorma/taste/base_override.rb
62
+ - lib/metanorma/taste/doctype_config.rb
63
+ - lib/metanorma/taste/taste_config.rb
240
64
  - lib/metanorma/taste/version.rb
241
65
  - lib/metanorma/taste_register.rb
242
66
  - metanorma-taste.gemspec
data/data/icc/icc.png DELETED
Binary file