metanorma-taste 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 40130f7061043b85b1764af26102db83804e934b656f6af7e83ee0b582e65346
4
+ data.tar.gz: 0bb630519b80b9f726847b7ca2ba38ce63ce7379f325a61929bddc49b7324a3b
5
+ SHA512:
6
+ metadata.gz: bf149523ea974279e19331aca8220c2c51c08634981513501811698422da5b3e0ad37b7272d79d0b172f86c8fa86f1716a9e43f57a4e2494cca94de001b5349d
7
+ data.tar.gz: 57570e155e0f800820488a4974aa5f57fa07c2b85784faa62a64a1c5c17c8478dbfb531fb06248d47576a527947a4e13bcd17a66da0d604392886849ce5b1b13
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --format documentation
3
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,14 @@
1
+ # Auto-generated by Cimas: Do not edit it manually!
2
+ # See https://github.com/metanorma/cimas
3
+ inherit_from:
4
+ - .rubocop_todo.yml
5
+ - https://raw.githubusercontent.com/riboseinc/oss-guides/master/ci/rubocop.yml
6
+
7
+ # local repo-specific modifications
8
+ # ...
9
+
10
+ AllCops:
11
+ TargetRubyVersion: 3.1
12
+
13
+ Lint/MissingSuper:
14
+ AllowedParentClasses: [Liquid::Drop]
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,118 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2025-06-03 11:30:10 UTC using RuboCop version 1.75.8.
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: 11
10
+ # This cop supports safe autocorrection (--autocorrect).
11
+ # Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
12
+ # Include: **/*.gemspec
13
+ Gemspec/OrderedDependencies:
14
+ Exclude:
15
+ - 'metanorma-taste.gemspec'
16
+
17
+ # Offense count: 1
18
+ # This cop supports safe autocorrection (--autocorrect).
19
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
20
+ # SupportedStyles: with_first_argument, with_fixed_indentation
21
+ Layout/ArgumentAlignment:
22
+ Exclude:
23
+ - 'lib/metanorma/taste_register.rb'
24
+
25
+ # Offense count: 1
26
+ # This cop supports safe autocorrection (--autocorrect).
27
+ # Configuration parameters: EnforcedStyleAlignWith.
28
+ # SupportedStylesAlignWith: either, start_of_block, start_of_line
29
+ Layout/BlockAlignment:
30
+ Exclude:
31
+ - 'spec/metanorma/taste_register_spec.rb'
32
+
33
+ # Offense count: 1
34
+ # This cop supports safe autocorrection (--autocorrect).
35
+ Layout/BlockEndNewline:
36
+ Exclude:
37
+ - 'spec/metanorma/taste_register_spec.rb'
38
+
39
+ # Offense count: 1
40
+ # This cop supports safe autocorrection (--autocorrect).
41
+ # Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, DefLikeMacros, AllowAdjacentOneLineDefs, NumberOfEmptyLines.
42
+ Layout/EmptyLineBetweenDefs:
43
+ Exclude:
44
+ - 'lib/metanorma/taste/base.rb'
45
+
46
+ # Offense count: 1
47
+ # This cop supports safe autocorrection (--autocorrect).
48
+ Layout/EmptyLines:
49
+ Exclude:
50
+ - 'lib/metanorma/taste/base.rb'
51
+
52
+ # Offense count: 2
53
+ # This cop supports safe autocorrection (--autocorrect).
54
+ # Configuration parameters: Width, AllowedPatterns.
55
+ Layout/IndentationWidth:
56
+ Exclude:
57
+ - 'spec/metanorma/taste_register_spec.rb'
58
+
59
+ # Offense count: 10
60
+ # This cop supports safe autocorrection (--autocorrect).
61
+ # Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings.
62
+ # URISchemes: http, https
63
+ Layout/LineLength:
64
+ Exclude:
65
+ - 'lib/metanorma/taste_register.rb'
66
+ - 'metanorma-taste.gemspec'
67
+ - 'spec/metanorma/taste_register_spec.rb'
68
+
69
+ # Offense count: 3
70
+ # This cop supports safe autocorrection (--autocorrect).
71
+ # Configuration parameters: EnforcedStyle, IndentationWidth.
72
+ # SupportedStyles: aligned, indented, indented_relative_to_receiver
73
+ Layout/MultilineMethodCallIndentation:
74
+ Exclude:
75
+ - 'metanorma-taste.gemspec'
76
+
77
+ # Offense count: 1
78
+ # This cop supports safe autocorrection (--autocorrect).
79
+ # Configuration parameters: AllowInHeredoc.
80
+ Layout/TrailingWhitespace:
81
+ Exclude:
82
+ - 'lib/metanorma/taste_register.rb'
83
+
84
+ # Offense count: 3
85
+ # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
86
+ Metrics/MethodLength:
87
+ Max: 16
88
+
89
+ # Offense count: 1
90
+ # This cop supports safe autocorrection (--autocorrect).
91
+ # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
92
+ # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
93
+ # ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
94
+ # FunctionalMethods: let, let!, subject, watch
95
+ # AllowedMethods: lambda, proc, it
96
+ Style/BlockDelimiters:
97
+ Exclude:
98
+ - 'spec/metanorma/taste_register_spec.rb'
99
+
100
+ # Offense count: 1
101
+ # This cop supports safe autocorrection (--autocorrect).
102
+ Style/MultilineIfModifier:
103
+ Exclude:
104
+ - 'lib/metanorma/taste_register.rb'
105
+
106
+ # Offense count: 1
107
+ # This cop supports safe autocorrection (--autocorrect).
108
+ Style/RedundantFreeze:
109
+ Exclude:
110
+ - 'lib/metanorma/taste/version.rb'
111
+
112
+ # Offense count: 1
113
+ # This cop supports safe autocorrection (--autocorrect).
114
+ # Configuration parameters: EnforcedStyleForMultiline.
115
+ # SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma
116
+ Style/TrailingCommaInHashLiteral:
117
+ Exclude:
118
+ - 'lib/metanorma/taste_register.rb'
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,24 @@
1
+ BSD 2-Clause License
2
+
3
+ Copyright (c) 2025, Metanorma
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.adoc ADDED
@@ -0,0 +1,422 @@
1
+ = Metanorma Taste: lightweight customizable Metanorma flavours
2
+
3
+ image:https://img.shields.io/gem/v/metanorma-taste.svg["Gem Version", link="https://rubygems.org/gems/metanorma-taste"]
4
+ image:https://github.com/metanorma/metanorma-taste/workflows/rake/badge.svg["Build Status", link="https://github.com/metanorma/metanorma-taste/actions?workflow=rake"]
5
+ image:https://img.shields.io/github/issues-pr-raw/metanorma/metanorma-taste.svg["Pull Requests", link="https://github.com/metanorma/metanorma-taste/pulls"]
6
+ image:https://img.shields.io/github/commits-since/metanorma/metanorma-taste/latest.svg["Commits since latest",link="https://github.com/metanorma/metanorma-taste/releases"]
7
+
8
+ == Metanorma Taste
9
+
10
+ === Overview
11
+
12
+ A **Metanorma Taste** is a lightweight, configuration-only customization of an existing Metanorma flavor.
13
+
14
+ Unlike a full Metanorma flavor, a taste does not define its own document
15
+ structure, validation rules, or processing logic. Instead, it provides
16
+ organizational branding and content customization on top of a base flavor.
17
+
18
+ Think of it as "taste" being one aspect of "flavor" in real life -- a taste
19
+ modifies the presentation and branding without changing the fundamental
20
+ characteristics of the underlying flavor.
21
+
22
+ === Features
23
+
24
+ **Configuration-Only**:: Tastes are defined purely through YAML configuration
25
+ files and content assets (copyright notices, i18n dictionaries, stylesheets). No
26
+ code is required.
27
+
28
+ **Base flavor dependency**:: Every taste must specify a `base-flavor` (e.g.,
29
+ `iso`, `ietf`, `ieee`) that provides the document structure and validation
30
+ logic.
31
+
32
+ **Lightweight customization**:: Tastes can override document attributes, provide
33
+ custom copyright notices, modify presentation styling, and add
34
+ internationalization content.
35
+
36
+
37
+ === Limitations
38
+
39
+ Since tastes are configuration-only overlays on existing flavors, they have
40
+ important limitations.
41
+
42
+ **Document structure constraints**:: A taste cannot define document structures
43
+ not allowed by the underlying base flavor. For example, an ISO-based taste
44
+ cannot add document types that ISO doesn't support.
45
+
46
+ **Validation inheritance**:: All document validation rules from the base flavor
47
+ apply unchanged. This includes:
48
+
49
+ * ISO/IEC warnings on terms and definitions requirements
50
+ * Provision requirements and numbering rules
51
+ * Document structure validation
52
+ * Metadata requirements
53
+
54
+ **Processing logic**:: Tastes cannot modify the core document processing,
55
+ rendering, or output generation logic of the base flavor.
56
+
57
+ **Customization scope**:: Tastes can only customize from document attributes or
58
+ presentation attributes supported by the base flavor.
59
+
60
+
61
+ == Installation
62
+
63
+ The gem is distributed within Metanorma.
64
+
65
+
66
+ == Usage
67
+
68
+ === Compiling documents
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.
73
+
74
+ === Basic usage
75
+
76
+ [source,ruby]
77
+ ----
78
+ require "metanorma-taste"
79
+
80
+ # Get a registered taste (returns Metanorma::Taste::Icc instance)
81
+ taste = Metanorma::TasteRegister.get(:icc)
82
+ # => Metanorma::Taste::Icc
83
+
84
+ # Process document attributes and options
85
+ taste.process_input_adoc_overrides(attributes, options)
86
+ ----
87
+
88
+ === Listing tastes
89
+
90
+ [source,ruby]
91
+ ----
92
+ # List all available tastes
93
+ Metanorma::TasteRegister.instance.available_tastes
94
+ # => [:icc]
95
+
96
+ # Get information about a specific taste
97
+ Metanorma::TasteRegister.instance.taste_info(:icc)
98
+ # => { flavor: :icc, owner: "International Color Consortium", base_flavor: :iso, ... }
99
+
100
+ # Get flavor aliases (mapping to base flavours)
101
+ Metanorma::Taste.aliases
102
+ # => { icc: :iso }
103
+
104
+ # Demonstrate dynamic class creation
105
+ taste = Metanorma::TasteRegister.get(:icc)
106
+ puts taste.class.to_s
107
+ # => "Metanorma::Taste::Icc"
108
+ ----
109
+
110
+ == Official tastes
111
+
112
+ === General
113
+
114
+ Official tastes are maintained by the Metanorma team and provide standardized
115
+ customizations for specific organizations or purposes. They are designed to
116
+ be used with the Metanorma framework and provide consistent branding and
117
+ presentation across documents.
118
+
119
+ === Adding official tastes
120
+
121
+ Official tastes are maintained and version tested by the Metanorma team and are
122
+ not user-configurable.
123
+
124
+ Official tastes are only available to organizations that have an existing
125
+ relationship with Metanorma. To request a new official taste, please open an
126
+ issue on the Metanorma GitHub repository.
127
+
128
+ Official tastes are located at the `data/` directory of the metanorma-taste gem.
129
+
130
+ Each official taste has its own directory with the taste package structure.
131
+
132
+ See <<creating-a-taste,Creating a taste>> for instructions on how to create a
133
+ taste.
134
+
135
+ === Available taste codes
136
+
137
+ All taste short codes must be unique among tastes. The following tastes are
138
+ currently available:
139
+
140
+ [cols="a,a,a,a", options="header"]
141
+ |===
142
+ |Code |Organization |Base Flavor |Description
143
+
144
+ |`icc`
145
+ |International Color Consortium
146
+ |`iso`
147
+ |ICC specifications and standards with ICC branding and copyright
148
+
149
+ |===
150
+
151
+
152
+ == Community tastes
153
+
154
+ === General
155
+
156
+ Community tastes are user-defined Metanorma tastes. They are not maintained by
157
+ the Metanorma team, but are available for use by your own community.
158
+
159
+ === Adding community tastes
160
+
161
+ WARNING: This is to be implemented in a future release.
162
+
163
+ Community tastes can be hosted on GitHub repositories or distributed as zip
164
+ files.
165
+
166
+ See <<creating-a-taste,Creating a taste>> for instructions on how to create a
167
+ taste.
168
+
169
+ == Taste package
170
+
171
+ === General
172
+
173
+ A taste package is a directory structure that contains all the necessary files
174
+ to define a Metanorma taste. It includes configuration files, copyright notices, internationalization dictionaries, and stylesheets if any.
175
+
176
+ === Directory structure
177
+
178
+ Tastes are configured using a directory-based structure under `data/`:
179
+
180
+ [source]
181
+ ----
182
+ data/
183
+ └── {taste-code}/
184
+ ├── config.yaml
185
+ ├── copyright.adoc (optional)
186
+ └── i18n.yaml (optional)
187
+ ----
188
+
189
+
190
+ === Configuration schema
191
+
192
+ ==== config.yaml
193
+
194
+ The main configuration file for each taste:
195
+
196
+ [source,yaml]
197
+ ----
198
+ flavor: string # The name of the custom flavor (e.g., "icc")
199
+ owner: string # Organization name (e.g., "International Color Consortium")
200
+ base-flavor: string # Base Metanorma flavor to extend (e.g., "iso")
201
+ copyright-notice: string # Path to boilerplate file (e.g., "copyright.adoc"), which includes
202
+ # copyright, license, legal, and feedback notices
203
+ i18n-dictionary: string # Path to internationalization dictionary (e.g., "i18n.yaml")
204
+ base-override: # Hash of document attributes to override from base flavor
205
+ publisher: string # Publisher name override
206
+ publisher_abbr: string # Publisher abbreviation
207
+ presentation-metadata-*: # Template style attributes for presentation
208
+ ----
209
+
210
+ .Taste configuration example from ICC
211
+ [example]
212
+ ====
213
+ [source,yaml]
214
+ ----
215
+ flavor: icc
216
+ owner: International Color Consortium
217
+ base-flavor: iso
218
+ copyright-notice: copyright.adoc
219
+ i18n-dictionary: i18n.yaml
220
+ base-override:
221
+ publisher: International Color Consortium
222
+ publisher_abbr: ICC
223
+ presentation-metadata-color-secondary: '#376795'
224
+ presentation-metadata-backcover-text: color.org
225
+ ----
226
+ ====
227
+
228
+ ==== i18n.yaml
229
+
230
+ Internationalization dictionary for custom text translations:
231
+
232
+ [source,yaml]
233
+ ----
234
+ doctype_dict: # Document type translations
235
+ international-standard: string # Custom name for document types
236
+ # Add more document type mappings as needed
237
+ ----
238
+
239
+ .i18n.yaml example from ICC
240
+ [example]
241
+ ====
242
+ [source,yaml]
243
+ ----
244
+ doctype_dict:
245
+ international-standard: Specification
246
+ ----
247
+ ====
248
+
249
+
250
+ ==== copyright.adoc
251
+
252
+ Organization-specific copyright, legal, license and feedback text. This file can contain:
253
+
254
+ * Copyright statements with template variables (e.g., `{{ docyear }}`)
255
+ * License information
256
+ * Legal disclaimers
257
+ * Organization contact information
258
+
259
+ The file is in the Metanorma AsciiDoc format, with the following syntax:
260
+
261
+ [source,asciidoc]
262
+ ----
263
+ == copyright-statement
264
+ ...
265
+ ----
266
+
267
+ .Copyright notice from ICC
268
+ [example]
269
+ ====
270
+ [source,asciidoc]
271
+ ----
272
+ == copyright-statement
273
+ === Copyright notice
274
+
275
+ Copyright (c) {{ docyear }} Your Organization Name
276
+
277
+ [Legal text here...]
278
+
279
+ == feedback-statement
280
+ === Contact Information
281
+
282
+ [Organization contact details...]
283
+ ----
284
+ ====
285
+
286
+ The same file format is used internally for Metanorma flavors, and is documented in
287
+ https://www.metanorma.org/develop/topics/metadata-and-boilerplate/[Metadata and predefined text]
288
+ on the metaorma.org site.
289
+
290
+ === Base-Override configuration
291
+
292
+ The `base-override` section allows customization of any document attribute
293
+ supported by the base flavor.
294
+
295
+ This includes:
296
+
297
+ Document attributes:
298
+
299
+ * `publisher`: Organization name
300
+ * `publisher_abbr`: Organization abbreviation
301
+ * `doctype`: Document type mappings
302
+ * Custom organization-specific attributes
303
+
304
+ Template style attributes:
305
+
306
+ * `presentation-metadata-*`: Visual styling attributes
307
+ * Color schemes, logos, layout preferences
308
+ * Typography and formatting options
309
+
310
+ The availability of these attributes depends on the base flavor's supported
311
+ document attributes and template system.
312
+
313
+ For example, the ISO flavor supports specific presentation metadata attributes.
314
+
315
+ Other flavors may have different customization options. Please check the base
316
+ flavor documentation for available attributes.
317
+
318
+
319
+ == Data model
320
+
321
+ The metanorma-taste system follows this architecture:
322
+
323
+ [source]
324
+ ----
325
+ +------------------+ +-------------------+
326
+ | TasteRegister | | Taste::Base |
327
+ | (Singleton) | | |
328
+ | +available_tastes|<>---->| +flavor |
329
+ | +get(flavor) | | +config |
330
+ | +taste_info() | | +taste_info |
331
+ +--------+---------+ | +process_input_* |
332
+ | +-------------------+
333
+ |
334
+ | scans
335
+ +--------v---------+ +-------------------+
336
+ | data/ directory| | Dynamic Classes |
337
+ | | | |
338
+ | +{taste}/ |------>| Taste::Icc |
339
+ | config.yaml | | Taste::Foo |
340
+ | copyright.adoc | | (auto-generated) |
341
+ | i18n.yaml | +-------------------+
342
+ +------------------+
343
+ ----
344
+
345
+ === Components
346
+
347
+ `TasteRegister`:: (Singleton) Manages taste discovery and registration. Scans
348
+ the `data/` directory on initialization and creates a registry of available
349
+ tastes.
350
+
351
+ `Taste::Base`:: Base class containing the core logic for processing document
352
+ attributes and applying taste-specific overrides.
353
+
354
+ `Taste::*` dynamic taste classes:: Automatically generated classes (e.g.,
355
+ `Taste::Icc`) that inherit from `Taste::Base` and are configured with
356
+ taste-specific data.
357
+
358
+ Configuration files:: YAML and AsciiDoc files that define the behavior and
359
+ content for each taste.
360
+
361
+
362
+ === Workflow
363
+
364
+ . Discovery: On gem load, `TasteRegister` scans `data/` directory for taste configurations
365
+ . Registration: Each valid taste directory is registered with its configuration
366
+ . Access: Users call `TasteRegister.get(:flavor)` to obtain a configured taste instance
367
+ . Processing: The taste instance applies overrides and customizations to document attributes
368
+ . Integration: The customized attributes are used by Metanorma for document processing
369
+
370
+
371
+ [[creating-a-taste]]
372
+ == Creating a taste
373
+
374
+ === Overview
375
+
376
+ Creating a new Metanorma taste is straightforward and involves defining a
377
+ configuration directory with the necessary files.
378
+
379
+ === Directory structure
380
+
381
+ To create a new taste:
382
+
383
+ . Create directory: Add a new directory under `data/` with your unique taste code
384
+ . Add configuration: Create `config.yaml` with your taste settings
385
+ . Add content: Optionally add `copyright.adoc` and `i18n.yaml` files
386
+ . Test: The taste will be automatically discovered and available via the TasteRegister
387
+
388
+ Example for a new `acme` taste:
389
+
390
+ [source]
391
+ ----
392
+ data/acme/
393
+ ├── config.yaml
394
+ ├── copyright.adoc
395
+ └── i18n.yaml
396
+ ----
397
+
398
+ The taste will be accessible as:
399
+
400
+ [source,ruby]
401
+ ----
402
+ taste = Metanorma::TasteRegister.get(:acme)
403
+ # Returns an instance of Metanorma::Taste::Acme
404
+ ----
405
+
406
+ === Taste code
407
+
408
+ * Must be unique among all tastes
409
+ * Should be short and descriptive (typically 2-5 characters)
410
+ * Must be valid Ruby constant names when capitalized
411
+ * Should reflect the owner organization's name
412
+
413
+
414
+ == Copyright
415
+
416
+ This gem is developed, maintained and funded by
417
+ https://www.ribose.com[Ribose Inc.]
418
+
419
+ == License
420
+
421
+ The gem is available as open source under the terms of the
422
+ https://opensource.org/licenses/BSD-2-Clause[2-Clause BSD License].
@@ -0,0 +1,11 @@
1
+ ---
2
+ flavor: elf
3
+ owner: EXPRESS Language Foundation
4
+ base-flavor: iso
5
+ copyright-notice: copyright.adoc
6
+ i18n-dictionary: i18n.yaml
7
+ base-override:
8
+ publisher: EXPRESS Language Foundation
9
+ publisher_abbr: ELF
10
+ presentation-metadata-color-secondary: '#3f65a2'
11
+ presentation-metadata-backcover-text: expresslang.org
@@ -0,0 +1,26 @@
1
+ == copyright-statement
2
+ === {blank}
3
+ (c) {{ docyear }} EXPRESS Language Foundation.
4
+
5
+ All rights reserved. Unless otherwise specified, or required in the context of
6
+ its implementation, no part of this publication may be reproduced or utilized
7
+ otherwise in any form or by any means, electronic or mechanical, including
8
+ photocopying, or posting on the internet or an intranet, without prior written
9
+ permission. Permission can be requested from the EXPRESS Language Foundation.
10
+
11
+ EXPRESS Language Foundation +
12
+ 2093 Philadelphia Pike Ste 3311 +
13
+ Claymont, Delaware 19703 +
14
+ USA
15
+
16
+ E-mail: link:mailto:info@expresslang.org[info@expresslang.org]
17
+
18
+ Published in the USA
19
+
20
+
21
+ == feedback-statement
22
+
23
+ === {blank}
24
+
25
+ [align=center]
26
+ Don't panic, [css color:#3f65a2]#**EXPRESS**#.
@@ -0,0 +1,2 @@
1
+ doctype_dict:
2
+ international-standard: Standard
@@ -0,0 +1,11 @@
1
+ ---
2
+ flavor: icc
3
+ owner: International Color Consortium
4
+ base-flavor: iso
5
+ copyright-notice: copyright.adoc
6
+ i18n-dictionary: i18n.yaml
7
+ base-override:
8
+ publisher: International Color Consortium
9
+ publisher_abbr: ICC
10
+ presentation-metadata-color-secondary: '#376795'
11
+ presentation-metadata-backcover-text: color.org
@@ -0,0 +1,70 @@
1
+ == copyright-statement
2
+ === Copyright notice
3
+
4
+ Copyright (c) {{ docyear }} International Color Consortium
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
7
+ this Specification (the "Specification") to exploit the Specification without
8
+ restriction including, without limitation, the rights to use, copy, modify,
9
+ merge, publish, distribute, and/or sublicense, copies of the Specification, and
10
+ to permit persons to whom the Specification is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ Elements of this Specification may be the subject of intellectual property
14
+ rights of third parties throughout the world including, without limitation,
15
+ patents, patent application, utility, models, copyrights, trade secrets or other
16
+ proprietary rights ("Third Party IP Rights"). Although no Third Party IP Rights
17
+ have been brought to the attention of the International Color Consortium (the
18
+ "ICC") by its members, or as a result of the publication of this Specification
19
+ in certain trade journals, the ICC has not conducted any independent
20
+ investigation regarding the existence of Third Party IP Rights. The ICC shall
21
+ not be held responsible for identifying Third Party IP Rights that may be
22
+ implicated by the practice of this Specification or the permissions granted
23
+ above, for conducting inquiries into the applicability, existence, validity, or
24
+ scope of any Third Party IP Rights that are brought to the ICC's attention, or
25
+ for obtaining licensing assurances with respect to any Third Party IP Rights.
26
+
27
+ THE SPECIFICATION IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS,
28
+ IMPLIED, OR OTHERWISE INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF
29
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, QUIET
30
+ ENJOYMENT, SYSTEM INTEGRATION, AND DATA ACCURACY. IN NO EVENT SHALL THE ICC BE
31
+ LIABLE FOR ANY CLAIM, DAMAGES, LOSSES, EXPENSES OR OTHER LIABILITY, WHETHER IN
32
+ AN ACTION OF CONTRACT, TORT OR OTHERWISE, CAUSED BY, ARISING OR RESULTING FROM,
33
+ OR THAT RELATE TO THE SPECIFICATION OR THE PRACTICE OR OTHER EXPLOITATION OF THE
34
+ SPECIFICATION. FURTHER, YOU HEREBY AGREE TO DEFEND, INDEMNIFY AND HOLD HARMLESS
35
+ THE ICC, AND ITS DIRECTORS AND EMPLOYEES, FROM AND AGAINST ANY AND ALL THIRD
36
+ PARTY CLAIMS, ACTIONS SUITS, DAMAGES, LOSSES, COSTS, EXPENSES, OR OTHER
37
+ LIABILITIES (INCLUDING REASONABLE ATTORNEY'S FEES AND EXPENSES) THAT WERE CAUSED
38
+ BY, ARISE OR RESULT FROM, OR RELATE TO, YOUR PRACTICE OR OTHER EXPLOITATION OF
39
+ THE SPECIFICATION (INCLUDING, WITHOUT LIMITATION, CLAIMS OF INFRINGEMENT).
40
+
41
+ The above copyright notice, permission, and conditions and disclaimers shall be
42
+ included in all copies of any material portion of the Specification. Except as
43
+ contained in this statement, the name "International Color Consortium" shall not
44
+ be used in advertising or otherwise to promote the use or other dealings in this
45
+ Specification without prior written authorization from the ICC.
46
+
47
+ === Licenses and trademarks
48
+
49
+ International Color Consortium and the ICC logo are registered trademarks of the
50
+ International Color Consortium.
51
+
52
+ Rather than put a trademark symbol in every occurrence of other trademarked
53
+ names, we state that we are using the names only in an editorial fashion, and to
54
+ the benefit of the trademark owner, with no intention of infringement of the
55
+ trademark.
56
+
57
+ === For additional information on the ICC
58
+
59
+ Visit the ICC Web site: http://www.color.org
60
+
61
+
62
+ == feedback-statement
63
+
64
+ === {blank}
65
+
66
+ // [align=center]
67
+ // **International Color Consortium**:
68
+ // Standardizing [css color:blue]#color# fidelity since 1993.
69
+
70
+ // (c) ICC {{ docyear }} - All rights reserved
@@ -0,0 +1,2 @@
1
+ doctype_dict:
2
+ international-standard: Specification
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module Metanorma
6
+ module Taste
7
+ class Base
8
+ attr_reader :flavor, :config, :taste_info
9
+
10
+ def initialize(flavor, taste_info)
11
+ @flavor = flavor
12
+ @taste_info = taste_info
13
+ @config = taste_info[:config]
14
+ end
15
+
16
+ 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
+ new_attrs = build_attribute_overrides
22
+ attrs.insert(insertion_index, *new_attrs) unless new_attrs.empty?
23
+
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
28
+ end
29
+
30
+ attrs
31
+ end
32
+
33
+ private
34
+
35
+ def build_attribute_overrides
36
+ overrides = []
37
+
38
+ # Add copyright notice if available
39
+ copyright_file = copyright_notice_path
40
+ if copyright_file && File.exist?(copyright_file)
41
+ overrides << ":boilerplate-authority: #{copyright_file}"
42
+ end
43
+
44
+ # Add i18n dictionary if available
45
+ i18n_file = i18n_dictionary_path
46
+ if i18n_file && File.exist?(i18n_file)
47
+ overrides << ":i18nyaml: #{i18n_file}"
48
+ end
49
+
50
+ # Add base-override attributes
51
+ @taste_info[:base_override].each do |key, value|
52
+ overrides << ":#{key}: #{value}"
53
+ end
54
+
55
+ overrides
56
+ end
57
+
58
+ def copyright_notice_path
59
+ return nil unless @taste_info[:copyright_notice]
60
+
61
+ File.join(@taste_info[:directory], @taste_info[:copyright_notice])
62
+ end
63
+
64
+ def i18n_dictionary_path
65
+ return nil unless @taste_info[:i18n_dictionary]
66
+
67
+ File.join(@taste_info[:directory], @taste_info[:i18n_dictionary])
68
+ end
69
+
70
+ def load_i18n_dictionary
71
+ i18n_file = i18n_dictionary_path
72
+ return {} unless i18n_file && File.exist?(i18n_file)
73
+
74
+ YAML.load_file(i18n_file)
75
+ rescue StandardError
76
+ {}
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Metanorma
4
+ module Taste
5
+ VERSION = "0.0.2"
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "taste/base"
4
+ require_relative "taste_register"
5
+
6
+ module Metanorma
7
+ module Taste
8
+ # Convenience method for aliases
9
+ def self.aliases
10
+ TasteRegister.instance.aliases
11
+ end
12
+ end
13
+ end
14
+
15
+ # Initialize the register on load
16
+ Metanorma::TasteRegister.instance
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+ require "singleton"
5
+
6
+ module Metanorma
7
+ class TasteRegister
8
+ include Singleton
9
+
10
+ def initialize
11
+ @tastes = {}
12
+ @taste_classes = {}
13
+ scan_data_directory
14
+ end
15
+
16
+ def self.get(flavor)
17
+ instance.get(flavor)
18
+ end
19
+
20
+ def get(flavor)
21
+ flavor_sym = flavor.to_sym
22
+ return @taste_classes[flavor_sym] if @taste_classes[flavor_sym]
23
+
24
+ config = @tastes[flavor_sym]
25
+ raise "Unknown taste: #{flavor}" unless config
26
+
27
+ # Dynamically create and cache the taste class
28
+ @taste_classes[flavor_sym] = create_taste_class(flavor_sym, config)
29
+ end
30
+
31
+ def available_tastes
32
+ @tastes.keys
33
+ end
34
+
35
+ def taste_info(flavor)
36
+ @tastes[flavor.to_sym]
37
+ end
38
+
39
+ 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]
44
+ end
45
+ aliases
46
+ end
47
+
48
+ private
49
+
50
+ def scan_data_directory
51
+ data_dir = File.join(File.dirname(__FILE__), "..", "..", "data")
52
+ return unless Dir.exist?(data_dir)
53
+
54
+ Dir.entries(data_dir).each do |entry|
55
+ next if entry.start_with?(".")
56
+
57
+ taste_dir = File.join(data_dir, entry)
58
+ next unless Dir.exist?(taste_dir)
59
+
60
+ config_file = File.join(taste_dir, "config.yaml")
61
+ next unless File.exist?(config_file)
62
+
63
+ register_taste(entry, taste_dir, config_file)
64
+ end
65
+ end
66
+
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
+ base_override: config["base-override"] || {},
80
+ }
81
+ end
82
+
83
+ def create_taste_class(flavor, config)
84
+ # Create a dynamic class that inherits from Base
85
+ taste_class = Class.new(Taste::Base) do
86
+ define_method :initialize do
87
+ super(flavor, config)
88
+ end
89
+ end
90
+
91
+ # Define the class constant dynamically
92
+ class_name = flavor.to_s.split(/[-_]/).map(&:capitalize).join
93
+ unless Taste.const_defined?(class_name)
94
+ Taste.const_set(class_name,
95
+ taste_class)
96
+ end
97
+
98
+ taste_class.new
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,2 @@
1
+ require_relative "metanorma/taste"
2
+ require_relative "metanorma/taste/version"
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/metanorma/taste/version"
4
+
5
+ all_files_in_git = Dir.chdir(File.expand_path(__dir__)) do
6
+ `git ls-files -z`.split("\x0")
7
+ end
8
+
9
+ Gem::Specification.new do |spec|
10
+ spec.name = "metanorma-taste"
11
+ spec.version = Metanorma::Taste::VERSION
12
+ spec.authors = ["Ribose Inc."]
13
+ spec.email = ["open.source@ribose.com"]
14
+
15
+ spec.summary = "Metanorma Taste Library"
16
+ spec.description = "Library to process and handle default Metanorma Tastes, providing configuration-driven customization of Metanorma flavours."
17
+ spec.homepage = "https://github.com/metanorma/metanorma-taste"
18
+ spec.license = "BSD-2-Clause"
19
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0")
20
+
21
+ spec.metadata["homepage_uri"] = spec.homepage
22
+ spec.metadata["source_code_uri"] = spec.homepage
23
+ spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
24
+
25
+ # Specify which files should be added to the gem when it is released.
26
+ spec.files = all_files_in_git
27
+ .reject { |f| f.match(%r{\A(?:test|spec|features|bin|\.github)/}) }
28
+ .reject { |f| f.match(%r{Rakefile|bin/rspec}) }
29
+ .reject { |f| f.match(%r{flake|\.(?:direnv|pryrc|irbrc|nix)}) }
30
+
31
+ spec.extra_rdoc_files = %w[README.adoc LICENSE.txt]
32
+ spec.bindir = "bin"
33
+ spec.require_paths = ["lib"]
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"
49
+ end
metadata ADDED
@@ -0,0 +1,263 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: metanorma-taste
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Ribose Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-06-04 00:00:00.000000000 Z
12
+ dependencies:
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
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '1'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !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'
209
+ description: Library to process and handle default Metanorma Tastes, providing configuration-driven
210
+ customization of Metanorma flavours.
211
+ email:
212
+ - open.source@ribose.com
213
+ executables: []
214
+ extensions: []
215
+ extra_rdoc_files:
216
+ - README.adoc
217
+ - LICENSE.txt
218
+ files:
219
+ - ".rspec"
220
+ - ".rubocop.yml"
221
+ - ".rubocop_todo.yml"
222
+ - Gemfile
223
+ - LICENSE.txt
224
+ - README.adoc
225
+ - data/elf/config.yaml
226
+ - data/elf/copyright.adoc
227
+ - data/elf/i18n.yaml
228
+ - data/icc/config.yaml
229
+ - data/icc/copyright.adoc
230
+ - data/icc/i18n.yaml
231
+ - lib/metanorma-taste.rb
232
+ - lib/metanorma/taste.rb
233
+ - lib/metanorma/taste/base.rb
234
+ - lib/metanorma/taste/version.rb
235
+ - lib/metanorma/taste_register.rb
236
+ - metanorma-taste.gemspec
237
+ homepage: https://github.com/metanorma/metanorma-taste
238
+ licenses:
239
+ - BSD-2-Clause
240
+ metadata:
241
+ homepage_uri: https://github.com/metanorma/metanorma-taste
242
+ source_code_uri: https://github.com/metanorma/metanorma-taste
243
+ bug_tracker_uri: https://github.com/metanorma/metanorma-taste/issues
244
+ post_install_message:
245
+ rdoc_options: []
246
+ require_paths:
247
+ - lib
248
+ required_ruby_version: !ruby/object:Gem::Requirement
249
+ requirements:
250
+ - - ">="
251
+ - !ruby/object:Gem::Version
252
+ version: 3.1.0
253
+ required_rubygems_version: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ">="
256
+ - !ruby/object:Gem::Version
257
+ version: '0'
258
+ requirements: []
259
+ rubygems_version: 3.5.22
260
+ signing_key:
261
+ specification_version: 4
262
+ summary: Metanorma Taste Library
263
+ test_files: []