glossarist 2.8.14 → 2.8.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CLAUDE.md +25 -0
  3. data/README.adoc +265 -18
  4. data/lib/glossarist/bibliography_data.rb +28 -20
  5. data/lib/glossarist/bibliography_entry.rb +15 -4
  6. data/lib/glossarist/collections/figure_collection.rb +20 -0
  7. data/lib/glossarist/collections/formula_collection.rb +20 -0
  8. data/lib/glossarist/collections/non_verbal_collection.rb +51 -0
  9. data/lib/glossarist/collections/table_collection.rb +20 -0
  10. data/lib/glossarist/collections.rb +8 -0
  11. data/lib/glossarist/figure.rb +39 -0
  12. data/lib/glossarist/figure_image.rb +30 -0
  13. data/lib/glossarist/figure_reference.rb +18 -0
  14. data/lib/glossarist/formula.rb +19 -0
  15. data/lib/glossarist/formula_reference.rb +18 -0
  16. data/lib/glossarist/localized_string.rb +44 -0
  17. data/lib/glossarist/managed_concept_data.rb +49 -0
  18. data/lib/glossarist/non_verb_rep.rb +14 -18
  19. data/lib/glossarist/non_verbal_entity.rb +45 -0
  20. data/lib/glossarist/non_verbal_reference.rb +23 -0
  21. data/lib/glossarist/reference_extractor.rb +28 -2
  22. data/lib/glossarist/shared_non_verbal_entity.rb +29 -0
  23. data/lib/glossarist/table.rb +19 -0
  24. data/lib/glossarist/table_reference.rb +18 -0
  25. data/lib/glossarist/transforms/concept_to_gloss_transform.rb +8 -2
  26. data/lib/glossarist/v3.rb +0 -8
  27. data/lib/glossarist/validation/asset_index.rb +7 -2
  28. data/lib/glossarist/validation/bibliography_index.rb +3 -32
  29. data/lib/glossarist/validation/rules/bibliography_yaml_rule.rb +1 -1
  30. data/lib/glossarist/validation/rules/gcr_context.rb +0 -1
  31. data/lib/glossarist/validation/rules/orphaned_images_rule.rb +1 -23
  32. data/lib/glossarist/version.rb +1 -1
  33. data/lib/glossarist.rb +11 -0
  34. metadata +17 -6
  35. data/lib/glossarist/v3/bibliography_entry.rb +0 -19
  36. data/lib/glossarist/v3/bibliography_file.rb +0 -27
  37. data/lib/glossarist/v3/image_entry.rb +0 -21
  38. data/lib/glossarist/v3/image_file.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 411f9be5f441296d22581729529924c738bdee6538d99c9085c7b1dc0bbaacc7
4
- data.tar.gz: a36be3a51a93fe075f00caec109a80d293edcd18031d85f04eaed4ce9224872f
3
+ metadata.gz: 3dff1f025f20e6cfad5028acb99816984ddef4cd4a231991345a633c42ae5794
4
+ data.tar.gz: 7eed6c0df552c7206225460f212500fac6e4c7f3bc47d04bf75bb11acd53af7d
5
5
  SHA512:
6
- metadata.gz: 37cc79709b04222aa05297f68dfbcde6b1f087027d9e8b7e6fd5c7894b7b6c629a42a4a02f26e8b388fcbedeccf07b23ad3b4bad42290ad8ba4c1d7715f01847
7
- data.tar.gz: 1f71874261f1e5e610314106fe5afb08a34f0612cea7aaae6618476e8b743eab4491f8ee01a3393d3463e794e97dc491e18385c482363270ae6c7791867d8c40
6
+ metadata.gz: 01bda07bdfcff32b5526b33e19bd38074f0eeeab585bdf739593c95f9edacdd85cff549ce7430b53a027b18b1cd011a99a33454f71fdb2163c57be6bb1a1affb
7
+ data.tar.gz: f9e036c52fa7fa63dab55c8623bd47bc46af544d1fa3660368c8f41ef9c9155373ca92ac91116c8f8d7ff18b1ca9e093fde4f6e25ce0ca7b8194c9724b2df75d
data/CLAUDE.md CHANGED
@@ -71,6 +71,31 @@ Designation inheritance hierarchy (MECE):
71
71
  - Supports both camelCase and snake_case keys in YAML (e.g., `localizedConcepts` / `localized_concepts`) using `%i[key1 key2]` mapping syntax.
72
72
  - Also supports V1 format (`concept-*.yaml` files at root level).
73
73
 
74
+ ### V3 Dataset Syntax (collection files are single-key mappings)
75
+
76
+ A dataset collection file — `bibliography.yaml`, `images.yaml`, and any future
77
+ equivalent — is the *V3 glossarist dataset syntax*: a YAML **mapping with a
78
+ single wrapper key** whose value is an **array of typed items**. No keyed maps
79
+ (indexing items by an out-of-band reference string), and no stray top-level
80
+ arrays — the array is always grouped under one named key. Each item carries its
81
+ own `id` field. (A keyed bibliography was tried and rejected as wrong — a
82
+ bibliography is an ordered collection, not a map, and keying forced the entry to
83
+ degenerate into `citation_key` + an untyped `data` hash. A bare top-level array
84
+ was also rejected — the user does not want stray arrays at the document root.)
85
+
86
+ Canonical models: `BibliographyData` + typed `BibliographyEntry`;
87
+ `V3::ImageFile` + `V3::ImageEntry`. `bibliography.yaml` wraps its entries under a
88
+ single `bibliography:` key. Because the root is a mapping, one `key_value` map
89
+ (`map "bibliography", to: :entries`) drives both the file (`to_yaml`/`from_yaml`)
90
+ and the in-memory store (`to_hash`/`from_hash`) — no overrides, no nested
91
+ Collection, no `YAML.safe_load`. `BibliographyData#shortname` is the
92
+ PackageStore record key only — never serialized. Documentation lives in
93
+ `README.adoc` (`== Bibliography`); this note is internal guidance, not user docs.
94
+
95
+ The remaining `map nil` keyed patterns live only in the **V1 legacy adapters**
96
+ (`v1/register.rb`, `v1/concept.rb`), which are intentional passthroughs for old
97
+ IEV-format datasets — do not "fix" them; that would break reading V1 data.
98
+
74
99
  ### Configuration & Extensibility
75
100
 
76
101
  - **`Config`** (`config.rb`) — singleton that holds registered classes for `:localized_concept` and `:managed_concept`. Allows swapping implementations via `register_class`.
data/README.adoc CHANGED
@@ -423,7 +423,7 @@ related_concept.ref = Glossarist::ConceptRef.new(source: "IEC", id: "102-03-02")
423
423
  [[relationship-types]]
424
424
  ==== Relationship Types
425
425
 
426
- Relationship types are drawn from ISO 10241-1, ISO 25964/SKOS, and ISO 12620/TBX. The table below shows each type with its provenance and cross-standard equivalents.
426
+ Relationship types span five standards (ISO 10241-1, ISO 25964/SKOS, ISO 12620/TBX, ISO 19135). The table below shows each of the 52 types with its category and cross-standard equivalents.
427
427
 
428
428
  [cols="1,1,1,1,1"]
429
429
  |===
@@ -435,6 +435,12 @@ Relationship types are drawn from ISO 10241-1, ISO 25964/SKOS, and ISO 12620/TBX
435
435
  |—
436
436
  |—
437
437
 
438
+ |`deprecated_by`
439
+ |Lifecycle
440
+ |deprecated by
441
+ |—
442
+ |—
443
+
438
444
  |`supersedes`
439
445
  |Lifecycle
440
446
  |supersedes
@@ -447,6 +453,42 @@ Relationship types are drawn from ISO 10241-1, ISO 25964/SKOS, and ISO 12620/TBX
447
453
  |—
448
454
  |—
449
455
 
456
+ |`replaces`
457
+ |Lifecycle (ISO 19135)
458
+ |—
459
+ |—
460
+ |—
461
+
462
+ |`replaced_by`
463
+ |Lifecycle (ISO 19135)
464
+ |—
465
+ |—
466
+ |—
467
+
468
+ |`invalidates`
469
+ |Lifecycle (ISO 19135)
470
+ |—
471
+ |—
472
+ |—
473
+
474
+ |`invalidated_by`
475
+ |Lifecycle (ISO 19135)
476
+ |—
477
+ |—
478
+ |—
479
+
480
+ |`retires`
481
+ |Lifecycle (ISO 19135)
482
+ |—
483
+ |—
484
+ |—
485
+
486
+ |`retired_by`
487
+ |Lifecycle (ISO 19135)
488
+ |—
489
+ |—
490
+ |—
491
+
450
492
  |`broader`
451
493
  |Hierarchical
452
494
  |broader concept
@@ -483,6 +525,18 @@ Relationship types are drawn from ISO 10241-1, ISO 25964/SKOS, and ISO 12620/TBX
483
525
  |NTP (narrowerPartitive)
484
526
  |narrowerTermPartitive
485
527
 
528
+ |`has_part`
529
+ |Hierarchical (partitive)
530
+ |has part
531
+ |—
532
+ |—
533
+
534
+ |`is_part_of`
535
+ |Hierarchical (partitive)
536
+ |is part of
537
+ |—
538
+ |—
539
+
486
540
  |`broader_instantial`
487
541
  |Hierarchical (instantial)
488
542
  |—
@@ -495,6 +549,18 @@ Relationship types are drawn from ISO 10241-1, ISO 25964/SKOS, and ISO 12620/TBX
495
549
  |NTI (narrowerInstantial)
496
550
  |narrowerTermInstantial
497
551
 
552
+ |`instance_of`
553
+ |Hierarchical (instantial)
554
+ |instance of
555
+ |—
556
+ |—
557
+
558
+ |`has_instance`
559
+ |Hierarchical (instantial)
560
+ |has instance
561
+ |—
562
+ |—
563
+
498
564
  |`equivalent`
499
565
  |Equivalence
500
566
  |equivalent
@@ -543,6 +609,12 @@ Relationship types are drawn from ISO 10241-1, ISO 25964/SKOS, and ISO 12620/TBX
543
609
  |RT (relatedTerm)
544
610
  |crossReference
545
611
 
612
+ |`references`
613
+ |Associative
614
+ |references
615
+ |—
616
+ |—
617
+
546
618
  |`related_concept`
547
619
  |Associative
548
620
  |—
@@ -561,23 +633,23 @@ Relationship types are drawn from ISO 10241-1, ISO 25964/SKOS, and ISO 12620/TBX
561
633
  |—
562
634
  |relatedConceptNarrower
563
635
 
564
- |`sequentially_related_concept`
636
+ |`sequentially_related`
565
637
  |Associative (sequential)
566
638
  |—
567
639
  |—
568
- |sequentiallyRelatedConcept
640
+ |sequentiallyRelated
569
641
 
570
- |`spatially_related_concept`
642
+ |`spatially_related`
571
643
  |Associative (spatial)
572
644
  |—
573
645
  |—
574
- |spatiallyRelatedConcept
646
+ |spatiallyRelated
575
647
 
576
- |`temporally_related_concept`
648
+ |`temporally_related`
577
649
  |Associative (temporal)
578
650
  |—
579
651
  |—
580
- |temporallyRelatedConcept
652
+ |temporallyRelated
581
653
 
582
654
  |`homograph`
583
655
  |Lexical
@@ -590,6 +662,66 @@ Relationship types are drawn from ISO 10241-1, ISO 25964/SKOS, and ISO 12620/TBX
590
662
  |—
591
663
  |—
592
664
  |falseFriend
665
+
666
+ |`has_concept`
667
+ |Register (ISO 19135)
668
+ |—
669
+ |—
670
+ |—
671
+
672
+ |`is_concept_of`
673
+ |Register (ISO 19135)
674
+ |—
675
+ |—
676
+ |—
677
+
678
+ |`has_definition`
679
+ |Register (ISO 19135)
680
+ |—
681
+ |—
682
+ |—
683
+
684
+ |`definition_of`
685
+ |Register (ISO 19135)
686
+ |—
687
+ |—
688
+ |—
689
+
690
+ |`inherits`
691
+ |Register (ISO 19135)
692
+ |—
693
+ |—
694
+ |—
695
+
696
+ |`inherited_by`
697
+ |Register (ISO 19135)
698
+ |—
699
+ |—
700
+ |—
701
+
702
+ |`has_version`
703
+ |Versioning (ISO 19135)
704
+ |—
705
+ |—
706
+ |—
707
+
708
+ |`version_of`
709
+ |Versioning (ISO 19135)
710
+ |—
711
+ |—
712
+ |—
713
+
714
+ |`current_version`
715
+ |Versioning (ISO 19135)
716
+ |—
717
+ |—
718
+ |—
719
+
720
+ |`current_version_of`
721
+ |Versioning (ISO 19135)
722
+ |—
723
+ |—
724
+ |—
593
725
  |===
594
726
 
595
727
  [[id,concept-reference]]
@@ -598,12 +730,12 @@ Relationship types are drawn from ISO 10241-1, ISO 25964/SKOS, and ISO 12620/TBX
598
730
  A typed reference to another concept, either local (within the same glossary) or external (in another concept registry).
599
731
 
600
732
  term:: String — the display text for the referenced concept.
601
- concept_id:: String — the identifier of the target concept.
733
+ concept_id:: String — the identifier of the target concept. Also accepts the `id` key in YAML (alias for backward compatibility with the concept-model format).
602
734
  source:: String — the registry URI prefix for external references (e.g. `urn:iec:std:iec:60050`).
603
- ref_type:: String — the reference type: `local`, `designation`, or `urn`.
735
+ ref_type:: String — the reference type: `local`, `designation`, `cite`, `section`, `domain`, or `urn`.
604
736
  urn:: String — a direct URN for the target concept (e.g. `urn:iec:std:iec:60050-102-01-01`).
605
737
 
606
- Local references use `concept_id` without `source`. External references use `source` + `concept_id` or a direct `urn`.
738
+ Local references use `concept_id` without `source`. External references use `source` + `concept_id` or a direct `urn`. `cite` references resolve against a `ConceptSource#id` in the same concept. `section` references point to a section defined in `register.yaml`.
607
739
 
608
740
  [,ruby]
609
741
  ----
@@ -779,23 +911,35 @@ result.diffs # Array of ConceptDiff with similarity scores
779
911
 
780
912
  === NonVerbRep
781
913
 
782
- Non-verbal representations are associated resources (images, tables, formulas) used to help define a concept (ISO 10241-1 §6.5). They live outside the concept model and are referenced by URI. Resources can be shared across concepts and belong either to the dataset package (relative path) or are externally referenced (URL/URN).
914
+ Non-verbal representations are associated resources (images, tables, formulas) used to help define a concept (ISO 10241-1 §6.5). NonVerbRep is the concept-local form attached directly to a concept's data; the dataset-shared form is xref:figure[Figure] / Table / Formula. Both share the same accessibility payload via `NonVerbalEntity`.
783
915
 
784
- type:: String — the type of representation: `image`, `table`, or `formula`.
785
- ref:: String URI reference to the resource (relative path within the GCR package, URN, or URL).
786
- text:: Stringoptional text description or alt text.
916
+ type:: String — the kind of representation: `image`, `table`, or `formula`.
917
+ images:: Collection of `FigureImage` variants (responsive, format fallbacks, dark/light). Used when `type: image`.
918
+ caption:: Localized hash short title keyed by ISO 639 code (e.g. `{ eng: "..." }`).
919
+ description:: Localized hash — long description for accessibility.
920
+ alt:: Localized hash — short alternative text for screen readers.
787
921
  sources:: Collection of <<concept-source,ConceptSource>> entries — bibliographic sources for the representation.
788
922
 
789
923
  Example:
790
924
  +
791
925
  [,yaml]
792
926
  ----
793
- non_verbal_rep:
927
+ non_verb_rep:
794
928
  - type: image
795
- ref: assets/images/figure-1.svg
796
- text: Diagram showing the concept hierarchy
929
+ images:
930
+ - src: assets/images/figure-1.svg
931
+ format: svg
932
+ role: vector
933
+ - src: assets/images/figure-1.png
934
+ format: png
935
+ role: raster
936
+ caption:
937
+ eng: Concept hierarchy
938
+ alt:
939
+ eng: Diagram showing the concept hierarchy
797
940
  - type: formula
798
- ref: urn:gcr:assets:formula-eq1
941
+ images:
942
+ - src: urn:gcr:assets:formula-eq1
799
943
  sources:
800
944
  - type: authoritative
801
945
  status: identical
@@ -812,6 +956,100 @@ origin:: The bibliographic <<citation,citation>> for the managed term.
812
956
  modification:: A description of the modification to the cited definition of the term, if any, as it is to be applied in the present context.
813
957
 
814
958
 
959
+ [[dataset-register,Dataset Register]]
960
+ == Dataset Register
961
+
962
+ A dataset directory may contain a `register.yaml` — the self-describing metadata file. It carries identity (URN, ref, year), structure (ordering, hierarchical sections), provenance (owner, sourceRepo), and relationships (supersedes other datasets).
963
+
964
+ [,yaml]
965
+ ----
966
+ schema_type: glossarist
967
+ schema_version: "3"
968
+ id: iso-19111
969
+ ref: "ISO 19111:2019"
970
+ year: 2019
971
+ urn: "urn:iso:std:iso:19111"
972
+ status: current
973
+ owner: ISO
974
+ languages: [eng, fra]
975
+ ordering: systematic
976
+ sections:
977
+ - id: "3"
978
+ names: { eng: "Geometric concepts" }
979
+ children:
980
+ - id: "3.1"
981
+ names: { eng: "Points and lines" }
982
+ ----
983
+
984
+ [[hierarchical-sections,Hierarchical Sections]]
985
+ === Hierarchical sections
986
+
987
+ Sections provide structural organization for concepts within a dataset. A section may contain child sections, forming a tree. Concepts reference sections via `domains[]` with `ref_type: section`:
988
+
989
+ [,yaml]
990
+ ----
991
+ data:
992
+ domains:
993
+ - source: urn:iso:std:iso:19111
994
+ id: "3.1"
995
+ ref_type: section
996
+ ----
997
+
998
+ ==== Cascading membership
999
+
1000
+ Section membership is transitive: a concept in section `3.1.1` is also a member of `3.1` and `3` for filtering and display. Use `DatasetRegister#concept_section_ids(concept)` to resolve all sections a concept belongs to, including transitive ancestors.
1001
+
1002
+ [,ruby]
1003
+ ----
1004
+ register = Glossarist::DatasetRegister.from_file("path/to/register.yaml")
1005
+ register.concept_section_ids(concept) # => ["3.1", "3"]
1006
+ ----
1007
+
1008
+ When a concept has no explicit `domains[]` entry with `ref_type: section`, section membership is derived from the concept's identifier using the longest registered section prefix (e.g. `103-01-01` → section `103`).
1009
+
1010
+
1011
+ [[bibliography,Bibliography]]
1012
+ == Bibliography
1013
+
1014
+ A dataset directory may contain a `bibliography.yaml` — the dataset's bibliography, an ordered collection of the bibliographic references cited by its concepts. It is a YAML *mapping with a single key*, `bibliography`, whose value is an array of typed entries. This is the **V3 glossarist dataset syntax** for a collection file: a typed list grouped under one wrapper key, never a keyed map and never a stray top-level array. Each entry carries its own `id` — the identifier is a field on the item, not an out-of-band hash key.
1015
+
1016
+ [,yaml]
1017
+ ----
1018
+ bibliography:
1019
+ - id: ref_1
1020
+ reference: ISO 704
1021
+ title: Terminology work — Principles and methods
1022
+ - id: ref_23
1023
+ reference: UNECE TRANS/WP29/1045
1024
+ title: Common definitions of vehicle categories, masses and dimensions
1025
+ link: https://www.unece.org/fileadmin/DAM/trans/doc/2005/wp29/TRANS-WP29-1045e.pdf
1026
+ - id: iso_std_iso_15704_en
1027
+ reference: ISO 15704
1028
+ ----
1029
+
1030
+ `BibliographyEntry` fields:
1031
+
1032
+ [cols="1,4"]
1033
+ |===
1034
+ |Field |Description
1035
+
1036
+ |`id` |Entry identifier, dataset-unique. Cited from concept sources and inline `{{cite:...}}` mentions.
1037
+ |`reference` |Publication reference string (e.g. `ISO 704`, `IEC 60050`).
1038
+ |`title` |Title of the referenced document.
1039
+ |`link` |Optional URL to the referenced document.
1040
+ |`type` |Optional document type (e.g. `standard`).
1041
+ |===
1042
+
1043
+ [,ruby]
1044
+ ----
1045
+ bib = Glossarist::BibliographyData.from_file("path/to/bibliography.yaml")
1046
+ bib.entries # => [#<BibliographyEntry id: "ref_1", ...>, ...]
1047
+ bib.find("ref_1") # => #<BibliographyEntry ...>
1048
+ bib.keys # => ["ref_1", "ref_23", ...]
1049
+ ----
1050
+
1051
+ The same single-key convention applies to every dataset collection file (`images.yaml`, and any future equivalent): the collection is an array of typed items grouped under one wrapper key.
1052
+
815
1053
  == Commands
816
1054
 
817
1055
  === generate_latex
@@ -1351,6 +1589,15 @@ Upgrade a dataset to the current schema version.
1351
1589
  glossarist upgrade SOURCE_DIR -o OUTPUT_DIR
1352
1590
  ----
1353
1591
 
1592
+ === version
1593
+
1594
+ Show the installed Glossarist version.
1595
+
1596
+ [,bash]
1597
+ ----
1598
+ glossarist version
1599
+ ----
1600
+
1354
1601
  == Glossarist Concept Repository (GCR)
1355
1602
 
1356
1603
  A **GCR** (Glossarist Concept Repository) is a distributable, versioned ZIP archive containing glossary concepts and metadata. GCR packages are created from v2 datasets.
@@ -1,41 +1,49 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Glossarist
4
+ # The bibliography of a dataset, persisted as bibliography.yaml.
5
+ #
6
+ # The file is the *V3 glossarist dataset syntax* for a collection: a YAML
7
+ # mapping with a single key, +bibliography+, whose value is an array of typed
8
+ # BibliographyEntry items. A bibliography is an ordered collection of
9
+ # references, not a keyed map, so each item carries its own +id+ field rather
10
+ # than being indexed by an out-of-band reference string. The single wrapper
11
+ # key keeps the document root a mapping (no stray top-level array).
12
+ #
13
+ # Because the root is a mapping, a single +key_value+ mapping drives both the
14
+ # file (#to_yaml / .from_yaml) and the in-memory store (#to_hash /
15
+ # .from_hash) — no special-case serialization.
16
+ #
17
+ # +shortname+ is internal bookkeeping only: lutaml-store's PackageStore needs
18
+ # a key field to store the bibliography as a single record. It is never
19
+ # serialized — only the +bibliography+ key appears in the file.
4
20
  class BibliographyData < Lutaml::Model::Serializable
5
21
  attribute :shortname, :string, default: -> { "bibliography" }
6
22
  attribute :entries, BibliographyEntry, collection: true,
7
23
  initialize_empty: true
8
24
 
9
25
  key_value do
10
- map nil, to: :entries,
11
- with: { from: :entries_from_hash, to: :entries_to_hash }
26
+ map "bibliography", to: :entries
12
27
  end
13
28
 
14
- def find(citation_key)
15
- entries.find { |e| e.citation_key == citation_key }
16
- end
29
+ class << self
30
+ def from_file(path)
31
+ return nil unless File.exist?(path)
17
32
 
18
- def keys
19
- entries.map(&:citation_key)
33
+ from_yaml(File.read(path, encoding: "utf-8"))
34
+ end
20
35
  end
21
36
 
22
- def [](citation_key)
23
- entry = find(citation_key)
24
- entry&.data
37
+ def find(id)
38
+ entries.find { |e| e.id == id.to_s }
25
39
  end
26
40
 
27
- def entries_from_hash(model, value)
28
- return unless value.is_a?(Hash)
29
-
30
- model.entries = value.map do |key, data|
31
- BibliographyEntry.new(citation_key: key, data: data || {})
32
- end
41
+ def keys
42
+ entries.map(&:id)
33
43
  end
34
44
 
35
- def entries_to_hash(model, doc)
36
- model.entries.each do |entry|
37
- doc[entry.citation_key] = entry.data
38
- end
45
+ def [](id)
46
+ find(id)
39
47
  end
40
48
  end
41
49
  end
@@ -1,13 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Glossarist
4
+ # A single bibliographic item in a dataset's bibliography.
5
+ #
6
+ # A bibliography is an ordered collection of references, so bibliography.yaml
7
+ # is a YAML sequence (array) of these typed entries. The entry's identifier is
8
+ # the +id+ field on each item — never an out-of-band hash key.
4
9
  class BibliographyEntry < Lutaml::Model::Serializable
5
- attribute :citation_key, :string
6
- attribute :data, :hash, default: -> { {} }
10
+ attribute :id, :string
11
+ attribute :reference, :string
12
+ attribute :title, :string
13
+ attribute :link, :string
14
+ attribute :type, :string
7
15
 
8
16
  key_value do
9
- map "citation_key", to: :citation_key
10
- map "data", to: :data
17
+ map :id, to: :id
18
+ map :reference, to: :reference
19
+ map :title, to: :title
20
+ map :link, to: :link
21
+ map :type, to: :type
11
22
  end
12
23
  end
13
24
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Glossarist
4
+ module Collections
5
+ class FigureCollection < NonVerbalCollection
6
+ instances :entries, Figure
7
+
8
+ key_value { map_instances to: :entries }
9
+
10
+ def self.from_directory(dir)
11
+ collection = new
12
+ Dir.glob(File.join(dir, "*.yaml")).each do |path|
13
+ fig = Figure.from_file(path)
14
+ collection.store(fig) if fig
15
+ end
16
+ collection
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Glossarist
4
+ module Collections
5
+ class FormulaCollection < NonVerbalCollection
6
+ instances :entries, Formula
7
+
8
+ key_value { map_instances to: :entries }
9
+
10
+ def self.from_directory(dir)
11
+ collection = new
12
+ Dir.glob(File.join(dir, "*.yaml")).each do |path|
13
+ fml = Formula.from_file(path)
14
+ collection.store(fml) if fml
15
+ end
16
+ collection
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Glossarist
4
+ module Collections
5
+ # Generic collection for dataset-level non-verbal entities
6
+ # (Figure, Table, Formula). Provides by_id lookup across top-level
7
+ # entities and recursive subfigures (for Figure).
8
+ #
9
+ # Subclasses declare the entity type via `instances`.
10
+ class NonVerbalCollection < Lutaml::Model::Collection
11
+ # Find an entity by ID, searching recursively (Figure subfigures).
12
+ #
13
+ # @param id [String] the entity or sub-entity ID
14
+ # @return [NonVerbalEntity, nil]
15
+ def by_id(target_id)
16
+ entries.each do |entity|
17
+ found = entity.find_by_id(target_id)
18
+ return found if found
19
+ end
20
+ nil
21
+ end
22
+
23
+ # All entity IDs including sub-entity IDs (for Figure subfigures).
24
+ #
25
+ # @return [Set<String>]
26
+ def ids
27
+ Set.new(entries.flat_map(&:all_ids).compact)
28
+ end
29
+
30
+ # Check if an entity with the given ID exists.
31
+ #
32
+ # @param id [String]
33
+ # @return [Boolean]
34
+ def exists?(id)
35
+ !by_id(id).nil?
36
+ end
37
+
38
+ # Store an entity.
39
+ #
40
+ # @param entity [NonVerbalEntity]
41
+ def store(entity)
42
+ entries << entity
43
+ end
44
+ alias :<< :store
45
+
46
+ def entries
47
+ @entries ||= []
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Glossarist
4
+ module Collections
5
+ class TableCollection < NonVerbalCollection
6
+ instances :entries, Table
7
+
8
+ key_value { map_instances to: :entries }
9
+
10
+ def self.from_directory(dir)
11
+ collection = new
12
+ Dir.glob(File.join(dir, "*.yaml")).each do |path|
13
+ tbl = Table.from_file(path)
14
+ collection.store(tbl) if tbl
15
+ end
16
+ collection
17
+ end
18
+ end
19
+ end
20
+ end
@@ -15,6 +15,14 @@ module Glossarist
15
15
  "glossarist/collections/detailed_definition_collection"
16
16
  autoload :LocalizationCollection,
17
17
  "glossarist/collections/localization_collection"
18
+ autoload :NonVerbalCollection,
19
+ "glossarist/collections/non_verbal_collection"
20
+ autoload :FigureCollection,
21
+ "glossarist/collections/figure_collection"
22
+ autoload :TableCollection,
23
+ "glossarist/collections/table_collection"
24
+ autoload :FormulaCollection,
25
+ "glossarist/collections/formula_collection"
18
26
  autoload :TypedCollection,
19
27
  "glossarist/collections/typed_collection"
20
28
  end