glossarist 2.5.2 → 2.6.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 +4 -4
- data/.gitignore +2 -0
- data/.rubocop_todo.yml +52 -12
- data/CLAUDE.md +15 -2
- data/Gemfile +7 -7
- data/README.adoc +86 -0
- data/glossarist.gemspec +2 -1
- data/lib/glossarist/cli/export_command.rb +109 -0
- data/lib/glossarist/cli/package_command.rb +11 -0
- data/lib/glossarist/cli.rb +23 -0
- data/lib/glossarist/concept_set.rb +0 -2
- data/lib/glossarist/gcr_metadata.rb +3 -0
- data/lib/glossarist/gcr_package.rb +95 -11
- data/lib/glossarist/gcr_statistics.rb +5 -1
- data/lib/glossarist/managed_concept.rb +10 -13
- data/lib/glossarist/rdf/localized_literal.rb +25 -0
- data/lib/glossarist/rdf/namespaces/dcterms_namespace.rb +12 -0
- data/lib/glossarist/rdf/namespaces/skos_namespace.rb +12 -0
- data/lib/glossarist/rdf/namespaces.rb +10 -0
- data/lib/glossarist/rdf/skos_concept.rb +44 -0
- data/lib/glossarist/rdf/skos_vocabulary.rb +26 -0
- data/lib/glossarist/rdf.rb +10 -0
- data/lib/glossarist/resolution_adapter/local.rb +1 -3
- data/lib/glossarist/transforms/concept_to_skos_transform.rb +133 -0
- data/lib/glossarist/transforms/concept_to_tbx_transform.rb +86 -0
- data/lib/glossarist/transforms.rb +10 -0
- data/lib/glossarist/version.rb +1 -1
- metadata +34 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b4e48f1d237829b78cd052e39afdd7c952c468be894e25856f79f93471ea2dc6
|
|
4
|
+
data.tar.gz: f6502f7012e30138193c4c28eee2ab551020edf27ff0c6e08cc39939e5d0c0c3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bcfb39fe52138d23d489cfbff45f62b0f00161d3183ef66dbb5718fcbc30694ef5e426bc9f7797329480dddb01a7c96b8f6e1dfc43e392032441bb62487c723a
|
|
7
|
+
data.tar.gz: 289911c5a5851389cb5e37fbc07bd45825b00cdd51fa8cac5679168af3ec9e2b7313f6afbd7093fb93b35384bfc7318dcb97a22d72869f78a321883f4ab299a4
|
data/.gitignore
CHANGED
data/.rubocop_todo.yml
CHANGED
|
@@ -1,17 +1,38 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on 2026-05-
|
|
3
|
+
# on 2026-05-06 18:35:41 UTC using RuboCop version 1.86.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
|
8
8
|
|
|
9
|
+
# Offense count: 5
|
|
10
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
11
|
+
# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation.
|
|
12
|
+
Bundler/OrderedGems:
|
|
13
|
+
Exclude:
|
|
14
|
+
- 'Gemfile'
|
|
15
|
+
|
|
9
16
|
# Offense count: 1
|
|
10
17
|
Gemspec/RequiredRubyVersion:
|
|
11
18
|
Exclude:
|
|
12
19
|
- 'glossarist.gemspec'
|
|
13
20
|
|
|
14
|
-
# Offense count:
|
|
21
|
+
# Offense count: 1
|
|
22
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
23
|
+
Layout/ClosingParenthesisIndentation:
|
|
24
|
+
Exclude:
|
|
25
|
+
- 'spec/unit/concept_set_spec.rb'
|
|
26
|
+
|
|
27
|
+
# Offense count: 1
|
|
28
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
29
|
+
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
|
30
|
+
# SupportedStyles: consistent, consistent_relative_to_receiver, special_for_inner_method_call, special_for_inner_method_call_in_parentheses
|
|
31
|
+
Layout/FirstArgumentIndentation:
|
|
32
|
+
Exclude:
|
|
33
|
+
- 'spec/unit/concept_set_spec.rb'
|
|
34
|
+
|
|
35
|
+
# Offense count: 202
|
|
15
36
|
# This cop supports safe autocorrection (--autocorrect).
|
|
16
37
|
# Configuration parameters: Max, AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings.
|
|
17
38
|
# URISchemes: http, https
|
|
@@ -25,11 +46,6 @@ Lint/ConstantDefinitionInBlock:
|
|
|
25
46
|
Exclude:
|
|
26
47
|
- 'spec/unit/utilities/common_functions_spec.rb'
|
|
27
48
|
|
|
28
|
-
# Offense count: 2
|
|
29
|
-
Lint/DuplicateMethods:
|
|
30
|
-
Exclude:
|
|
31
|
-
- 'lib/glossarist/managed_concept.rb'
|
|
32
|
-
|
|
33
49
|
# Offense count: 1
|
|
34
50
|
# This cop supports safe autocorrection (--autocorrect).
|
|
35
51
|
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions.
|
|
@@ -38,10 +54,11 @@ Lint/UnusedMethodArgument:
|
|
|
38
54
|
Exclude:
|
|
39
55
|
- 'lib/glossarist/dataset_validator.rb'
|
|
40
56
|
|
|
41
|
-
# Offense count:
|
|
57
|
+
# Offense count: 23
|
|
42
58
|
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes, Max.
|
|
43
59
|
Metrics/AbcSize:
|
|
44
60
|
Exclude:
|
|
61
|
+
- 'lib/glossarist/cli/export_command.rb'
|
|
45
62
|
- 'lib/glossarist/cli/package_command.rb'
|
|
46
63
|
- 'lib/glossarist/cli/validate_command.rb'
|
|
47
64
|
- 'lib/glossarist/concept_manager.rb'
|
|
@@ -51,6 +68,8 @@ Metrics/AbcSize:
|
|
|
51
68
|
- 'lib/glossarist/reference_resolver.rb'
|
|
52
69
|
- 'lib/glossarist/resolution_adapter/local.rb'
|
|
53
70
|
- 'lib/glossarist/schema_migration.rb'
|
|
71
|
+
- 'lib/glossarist/transforms/concept_to_skos_transform.rb'
|
|
72
|
+
- 'lib/glossarist/transforms/concept_to_tbx_transform.rb'
|
|
54
73
|
- 'lib/glossarist/utilities/uuid.rb'
|
|
55
74
|
- 'spec/unit/concept_collector_spec.rb'
|
|
56
75
|
|
|
@@ -60,25 +79,34 @@ Metrics/AbcSize:
|
|
|
60
79
|
Metrics/BlockLength:
|
|
61
80
|
Max: 28
|
|
62
81
|
|
|
63
|
-
# Offense count:
|
|
82
|
+
# Offense count: 19
|
|
64
83
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
65
84
|
Metrics/CyclomaticComplexity:
|
|
66
85
|
Exclude:
|
|
86
|
+
- 'lib/glossarist/cli/export_command.rb'
|
|
67
87
|
- 'lib/glossarist/concept_validator.rb'
|
|
68
88
|
- 'lib/glossarist/designation/expression.rb'
|
|
69
89
|
- 'lib/glossarist/gcr_metadata.rb'
|
|
90
|
+
- 'lib/glossarist/gcr_statistics.rb'
|
|
70
91
|
- 'lib/glossarist/managed_concept.rb'
|
|
71
92
|
- 'lib/glossarist/reference_extractor.rb'
|
|
72
93
|
- 'lib/glossarist/reference_resolver.rb'
|
|
73
94
|
- 'lib/glossarist/resolution_adapter/local.rb'
|
|
74
95
|
- 'lib/glossarist/schema_migration.rb'
|
|
96
|
+
- 'lib/glossarist/transforms/concept_to_skos_transform.rb'
|
|
97
|
+
- 'lib/glossarist/transforms/concept_to_tbx_transform.rb'
|
|
75
98
|
|
|
76
|
-
# Offense count:
|
|
99
|
+
# Offense count: 35
|
|
77
100
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
78
101
|
Metrics/MethodLength:
|
|
79
102
|
Max: 42
|
|
80
103
|
|
|
81
|
-
# Offense count:
|
|
104
|
+
# Offense count: 4
|
|
105
|
+
# Configuration parameters: CountKeywordArgs, MaxOptionalParameters.
|
|
106
|
+
Metrics/ParameterLists:
|
|
107
|
+
Max: 6
|
|
108
|
+
|
|
109
|
+
# Offense count: 13
|
|
82
110
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
|
83
111
|
Metrics/PerceivedComplexity:
|
|
84
112
|
Exclude:
|
|
@@ -89,6 +117,8 @@ Metrics/PerceivedComplexity:
|
|
|
89
117
|
- 'lib/glossarist/reference_resolver.rb'
|
|
90
118
|
- 'lib/glossarist/resolution_adapter/local.rb'
|
|
91
119
|
- 'lib/glossarist/schema_migration.rb'
|
|
120
|
+
- 'lib/glossarist/transforms/concept_to_skos_transform.rb'
|
|
121
|
+
- 'lib/glossarist/transforms/concept_to_tbx_transform.rb'
|
|
92
122
|
|
|
93
123
|
# Offense count: 6
|
|
94
124
|
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
|
@@ -97,6 +127,14 @@ Naming/MethodParameterName:
|
|
|
97
127
|
Exclude:
|
|
98
128
|
- 'lib/glossarist/schema_migration.rb'
|
|
99
129
|
|
|
130
|
+
# Offense count: 3
|
|
131
|
+
# Configuration parameters: EnforcedStyle, CheckMethodNames, CheckSymbols, AllowedIdentifiers, AllowedPatterns.
|
|
132
|
+
# SupportedStyles: snake_case, normalcase, non_integer
|
|
133
|
+
# AllowedIdentifiers: TLS1_1, TLS1_2, capture3, iso8601, rfc1123_date, rfc822, rfc2822, rfc3339, x86_64
|
|
134
|
+
Naming/VariableNumber:
|
|
135
|
+
Exclude:
|
|
136
|
+
- 'spec/unit/rdf/skos_vocabulary_spec.rb'
|
|
137
|
+
|
|
100
138
|
# Offense count: 6
|
|
101
139
|
# This cop supports safe autocorrection (--autocorrect).
|
|
102
140
|
# Configuration parameters: MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
|
|
@@ -112,8 +150,10 @@ Style/OneClassPerFile:
|
|
|
112
150
|
- 'test/**/*'
|
|
113
151
|
- 'lib/glossarist.rb'
|
|
114
152
|
|
|
115
|
-
# Offense count:
|
|
153
|
+
# Offense count: 4
|
|
116
154
|
# Configuration parameters: Max.
|
|
117
155
|
Style/SafeNavigationChainLength:
|
|
118
156
|
Exclude:
|
|
119
157
|
- 'lib/glossarist/managed_concept.rb'
|
|
158
|
+
- 'lib/glossarist/transforms/concept_to_skos_transform.rb'
|
|
159
|
+
- 'lib/glossarist/transforms/concept_to_tbx_transform.rb'
|
data/CLAUDE.md
CHANGED
|
@@ -67,11 +67,24 @@ Three classes handle glossary concept registry (GCR) ZIP packages:
|
|
|
67
67
|
|
|
68
68
|
### CLI
|
|
69
69
|
|
|
70
|
-
The `exe/glossarist` executable uses Thor.
|
|
70
|
+
The `exe/glossarist` executable uses Thor. Commands:
|
|
71
|
+
- `generate_latex` — converts concepts to LaTeX glossary entries
|
|
72
|
+
- `package` — creates `.gcr` ZIP archives with optional compiled formats (`--compiled-formats tbx,jsonld,turtle,jsonl`)
|
|
73
|
+
- `export` — exports concepts in json/tbx/jsonld/turtle/jsonl formats
|
|
74
|
+
- `validate` — validates datasets and `.gcr` files
|
|
75
|
+
- `upgrade` — migrates datasets to current schema version
|
|
76
|
+
|
|
77
|
+
### Export Transforms
|
|
78
|
+
|
|
79
|
+
- **`ConceptToTbxTransform`** (`transforms/concept_to_tbx_transform.rb`) — converts ManagedConcept to TBX-XML using the tbx gem (ISO 30042:2019). Produces `Tbx::ConceptEntry` per concept or `Tbx::Document` for full export.
|
|
80
|
+
- **`ConceptToSkosTransform`** (`transforms/concept_to_skos_transform.rb`) — converts ManagedConcept to SKOS RDF using `Glossarist::Rdf::SkosConcept`. Has `transform` (single) and `transform_document` (batch, returns `SkosVocabulary`). Produces JSON-LD and Turtle via the unified `rdf` DSL.
|
|
81
|
+
- **SKOS/RDF models** (`lib/glossarist/rdf/`) — `SkosConcept`, `SkosVocabulary` (ConceptScheme container), `LocalizedLiteral` (language-tagged value), namespace classes.
|
|
82
|
+
- TBX, Turtle, JSON-LD, JSONL export all write a single document file; JSON writes per-concept files.
|
|
71
83
|
|
|
72
84
|
### Dependencies
|
|
73
85
|
|
|
74
|
-
- `lutaml-model` (~> 0.8) — serialization framework (YAML/XML)
|
|
86
|
+
- `lutaml-model` (~> 0.8.5) — serialization framework (YAML/XML/JSON-LD/Turtle)
|
|
87
|
+
- `tbx` — ISO 30042:2019 TBX model classes
|
|
75
88
|
- `relaton` (>= 2.0.0, < 3) — bibliography database integration
|
|
76
89
|
- `thor` — CLI commands
|
|
77
90
|
|
data/Gemfile
CHANGED
|
@@ -12,23 +12,23 @@ gem "rubocop"
|
|
|
12
12
|
gem "rubocop-performance"
|
|
13
13
|
gem "rubocop-rake"
|
|
14
14
|
gem "rubocop-rspec"
|
|
15
|
+
gem "tbx", "~> 0.1"
|
|
15
16
|
|
|
16
17
|
# Override relaton gems with lutaml-model 0.8 compatible versions.
|
|
17
18
|
# Released 2.0.0 gems have untyped lutaml-model attributes that fail with 0.8+.
|
|
18
|
-
#
|
|
19
|
-
# lutaml-integration branches also have typed attributes and work with relaton-bib ~> 2.0.0.
|
|
19
|
+
# lutaml-integration branches have typed attributes and relaton-bib ~> 2.1.0.
|
|
20
20
|
# TODO: Remove once relaton gems release versions with lutaml-model 0.8 support.
|
|
21
21
|
gem "relaton-3gpp", github: "relaton/relaton-3gpp",
|
|
22
|
-
branch: "
|
|
23
|
-
gem "relaton-bib", github: "relaton/relaton-bib", branch: "
|
|
22
|
+
branch: "lutaml-integration"
|
|
23
|
+
gem "relaton-bib", github: "relaton/relaton-bib", branch: "lutaml-integration"
|
|
24
24
|
gem "relaton-bipm", github: "relaton/relaton-bipm",
|
|
25
|
-
branch: "
|
|
26
|
-
gem "relaton-bsi", github: "relaton/relaton-bsi", branch: "
|
|
25
|
+
branch: "lutaml-integration"
|
|
26
|
+
gem "relaton-bsi", github: "relaton/relaton-bsi", branch: "lutaml-integration"
|
|
27
27
|
gem "relaton-calconnect", github: "relaton/relaton-calconnect",
|
|
28
28
|
branch: "lutaml-integration"
|
|
29
29
|
gem "relaton-ccsds", github: "relaton/relaton-ccsds",
|
|
30
30
|
branch: "lutaml-integration"
|
|
31
31
|
gem "relaton-cen", github: "relaton/relaton-cen", branch: "lutaml-integration"
|
|
32
32
|
gem "relaton-iec", github: "relaton/relaton-iec", branch: "lutaml-integration"
|
|
33
|
-
gem "relaton-iso", github: "relaton/relaton-iso", branch: "
|
|
33
|
+
gem "relaton-iso", github: "relaton/relaton-iso", branch: "lutaml-integration"
|
|
34
34
|
gem "relaton-itu", github: "relaton/relaton-itu", branch: "lutaml-integration"
|
data/README.adoc
CHANGED
|
@@ -407,6 +407,12 @@ Options:
|
|
|
407
407
|
|
|
408
408
|
|--tags
|
|
409
409
|
|Tags for the dataset
|
|
410
|
+
|
|
411
|
+
|--compiled-formats
|
|
412
|
+
|Comma-separated compiled formats to bundle (tbx,jsonld,turtle,jsonl)
|
|
413
|
+
|
|
414
|
+
|--concept-uri-template
|
|
415
|
+
|URI template for concept URIs
|
|
410
416
|
|===
|
|
411
417
|
|
|
412
418
|
Ruby API:
|
|
@@ -418,9 +424,89 @@ GcrPackage.create_from_directory(
|
|
|
418
424
|
shortname: "mydataset",
|
|
419
425
|
version: "1.0.0",
|
|
420
426
|
uri_prefix: "urn:iso:std:iso:19111",
|
|
427
|
+
compiled_formats: ["jsonld", "turtle"],
|
|
421
428
|
)
|
|
422
429
|
----
|
|
423
430
|
|
|
431
|
+
=== export
|
|
432
|
+
|
|
433
|
+
Export concepts in machine-readable formats.
|
|
434
|
+
|
|
435
|
+
[,bash]
|
|
436
|
+
----
|
|
437
|
+
glossarist export PATH --format json --output DIR
|
|
438
|
+
glossarist export PATH --format jsonld --output DIR --shortname isotc211
|
|
439
|
+
glossarist export PATH --format turtle --output DIR
|
|
440
|
+
glossarist export PATH --format tbx --output DIR --shortname isotc211
|
|
441
|
+
glossarist export PATH --format jsonl --output DIR
|
|
442
|
+
glossarist export package.gcr --format json --output DIR
|
|
443
|
+
----
|
|
444
|
+
|
|
445
|
+
The path can be either a concept dataset directory or a `.gcr` file. When exporting from a `.gcr`, the `shortname` and `uri_prefix` are automatically resolved from the package metadata.
|
|
446
|
+
|
|
447
|
+
==== Output Formats
|
|
448
|
+
|
|
449
|
+
[cols="1,2,1"]
|
|
450
|
+
|===
|
|
451
|
+
|Format |Output |Files
|
|
452
|
+
|
|
453
|
+
|`json`
|
|
454
|
+
|Per-concept JSON files
|
|
455
|
+
|`{concept_id}.json`
|
|
456
|
+
|
|
457
|
+
|`tbx`
|
|
458
|
+
|Single TBX-XML document (ISO 30042:2019)
|
|
459
|
+
|`{shortname}.tbx.xml`
|
|
460
|
+
|
|
461
|
+
|`jsonld`
|
|
462
|
+
|Single JSON-LD file with `@graph`
|
|
463
|
+
|`{shortname}.jsonld`
|
|
464
|
+
|
|
465
|
+
|`turtle`
|
|
466
|
+
|Single Turtle file with all concept triples
|
|
467
|
+
|`{shortname}.ttl`
|
|
468
|
+
|
|
469
|
+
|`jsonl`
|
|
470
|
+
|JSONL file with one JSON-LD object per line
|
|
471
|
+
|`{shortname}.jsonl`
|
|
472
|
+
|===
|
|
473
|
+
|
|
474
|
+
Options:
|
|
475
|
+
[cols="1,1"]
|
|
476
|
+
|===
|
|
477
|
+
|--format (required)
|
|
478
|
+
|Output format: `json`, `tbx`, `jsonld`, `turtle`, or `jsonl`
|
|
479
|
+
|
|
480
|
+
|o, --output (required)
|
|
481
|
+
|Output directory
|
|
482
|
+
|
|
483
|
+
|--shortname
|
|
484
|
+
|Dataset shortname for concept ID prefixing
|
|
485
|
+
|
|
486
|
+
|--uri-prefix
|
|
487
|
+
|URI/URN prefix for the dataset
|
|
488
|
+
|
|
489
|
+
|--site-url
|
|
490
|
+
|Base URL of the glossarist site
|
|
491
|
+
|
|
492
|
+
|--title
|
|
493
|
+
|Dataset title for document header
|
|
494
|
+
|===
|
|
495
|
+
|
|
496
|
+
Ruby API:
|
|
497
|
+
[,ruby]
|
|
498
|
+
----
|
|
499
|
+
# Export to JSON-LD
|
|
500
|
+
cmd = Glossarist::CLI::ExportCommand.new("path/to/dataset",
|
|
501
|
+
format: "jsonld", output: "/tmp/export", shortname: "isotc211")
|
|
502
|
+
cmd.run
|
|
503
|
+
|
|
504
|
+
# Transform a single concept to SKOS
|
|
505
|
+
skos = Glossarist::Transforms::ConceptToSkosTransform.transform(concept)
|
|
506
|
+
puts skos.to_jsonld
|
|
507
|
+
puts skos.to_turtle
|
|
508
|
+
----
|
|
509
|
+
|
|
424
510
|
=== validate
|
|
425
511
|
|
|
426
512
|
Validate a dataset directory or `.gcr` file for schema compliance.
|
data/glossarist.gemspec
CHANGED
|
@@ -31,8 +31,9 @@ Gem::Specification.new do |spec|
|
|
|
31
31
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
32
32
|
spec.require_paths = ["lib"]
|
|
33
33
|
|
|
34
|
-
spec.add_dependency "lutaml-model", "~> 0.8"
|
|
34
|
+
spec.add_dependency "lutaml-model", "~> 0.8.5"
|
|
35
35
|
spec.add_dependency "relaton", ">= 2.0.0", "< 3"
|
|
36
36
|
spec.add_dependency "rubyzip", ">= 2.3", "< 3"
|
|
37
|
+
spec.add_dependency "tbx", "~> 0.1"
|
|
37
38
|
spec.add_dependency "thor"
|
|
38
39
|
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Glossarist
|
|
4
|
+
class CLI
|
|
5
|
+
class ExportCommand
|
|
6
|
+
EXTENSIONS = {
|
|
7
|
+
"json" => "json",
|
|
8
|
+
**GcrPackage::COMPILED_EXTENSIONS,
|
|
9
|
+
}.freeze
|
|
10
|
+
|
|
11
|
+
def initialize(path, options)
|
|
12
|
+
@path = path
|
|
13
|
+
@options = options
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def run
|
|
17
|
+
format = @options[:format]
|
|
18
|
+
output_dir = File.expand_path(@options[:output])
|
|
19
|
+
FileUtils.mkdir_p(output_dir)
|
|
20
|
+
|
|
21
|
+
concepts = load_concepts
|
|
22
|
+
name = resolve_shortname
|
|
23
|
+
|
|
24
|
+
case format
|
|
25
|
+
when "json" then export_json(concepts, output_dir)
|
|
26
|
+
when "jsonld" then export_jsonld(concepts, name, output_dir)
|
|
27
|
+
when "turtle" then export_turtle(concepts, name, output_dir)
|
|
28
|
+
when "tbx" then export_tbx(concepts, name, output_dir)
|
|
29
|
+
when "jsonl" then export_jsonl(concepts, name, output_dir)
|
|
30
|
+
end
|
|
31
|
+
rescue ArgumentError => e
|
|
32
|
+
warn "Error: #{e.message}"
|
|
33
|
+
exit 1
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def load_concepts
|
|
39
|
+
if @path.end_with?(".gcr")
|
|
40
|
+
package = GcrPackage.load(@path)
|
|
41
|
+
resolve_metadata_from_package(package)
|
|
42
|
+
package.concepts
|
|
43
|
+
else
|
|
44
|
+
collection = ManagedConceptCollection.new
|
|
45
|
+
collection.load_from_files(@path)
|
|
46
|
+
collection.to_a
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def resolve_metadata_from_package(package)
|
|
51
|
+
@options[:shortname] ||= package.metadata["shortname"]
|
|
52
|
+
@options[:uri_prefix] ||= package.metadata["uri_prefix"]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def resolve_shortname
|
|
56
|
+
@options[:shortname] || "glossary"
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def transform_options
|
|
60
|
+
{
|
|
61
|
+
shortname: @options[:shortname],
|
|
62
|
+
uri_prefix: @options[:uri_prefix],
|
|
63
|
+
site_url: @options[:site_url],
|
|
64
|
+
title: @options[:title],
|
|
65
|
+
}.compact
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def export_json(concepts, output_dir)
|
|
69
|
+
concepts.each do |concept|
|
|
70
|
+
id = concept.data&.id || concept.identifier
|
|
71
|
+
File.write(File.join(output_dir, "#{id}.json"), concept.to_json)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def export_jsonld(concepts, name, output_dir)
|
|
76
|
+
require "glossarist/transforms/concept_to_skos_transform"
|
|
77
|
+
vocab = Transforms::ConceptToSkosTransform.transform_document(concepts,
|
|
78
|
+
transform_options)
|
|
79
|
+
File.write(File.join(output_dir, "#{name}.jsonld"), vocab.to_jsonld)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def export_turtle(concepts, name, output_dir)
|
|
83
|
+
require "glossarist/transforms/concept_to_skos_transform"
|
|
84
|
+
vocab = Transforms::ConceptToSkosTransform.transform_document(concepts,
|
|
85
|
+
transform_options)
|
|
86
|
+
File.write(File.join(output_dir, "#{name}.ttl"), vocab.to_turtle)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def export_tbx(concepts, name, output_dir)
|
|
90
|
+
require "glossarist/transforms/concept_to_tbx_transform"
|
|
91
|
+
doc = Transforms::ConceptToTbxTransform.transform_document(concepts,
|
|
92
|
+
transform_options)
|
|
93
|
+
File.write(File.join(output_dir, "#{name}.tbx.xml"), doc.to_xml)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def export_jsonl(concepts, name, output_dir)
|
|
97
|
+
require "glossarist/transforms/concept_to_skos_transform"
|
|
98
|
+
File.open(File.join(output_dir, "#{name}.jsonl"), "w") do |f|
|
|
99
|
+
concepts.each do |concept|
|
|
100
|
+
skos = Transforms::ConceptToSkosTransform.transform(concept,
|
|
101
|
+
transform_options)
|
|
102
|
+
f.write(skos.to_jsonld)
|
|
103
|
+
f.write("\n")
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -20,6 +20,8 @@ module Glossarist
|
|
|
20
20
|
tags: @options[:tags],
|
|
21
21
|
register_yaml: @options[:register_yaml],
|
|
22
22
|
uri_prefix: @options[:uri_prefix],
|
|
23
|
+
concept_uri_template: @options[:concept_uri_template],
|
|
24
|
+
compiled_formats: parse_compiled_formats,
|
|
23
25
|
)
|
|
24
26
|
|
|
25
27
|
puts "Created #{@options[:output]}"
|
|
@@ -27,6 +29,15 @@ module Glossarist
|
|
|
27
29
|
warn "Error: #{e.message}"
|
|
28
30
|
exit 1
|
|
29
31
|
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def parse_compiled_formats
|
|
36
|
+
raw = @options[:compiled_formats]
|
|
37
|
+
return [] unless raw
|
|
38
|
+
|
|
39
|
+
raw.split(",").map(&:strip).reject(&:empty?)
|
|
40
|
+
end
|
|
30
41
|
end
|
|
31
42
|
end
|
|
32
43
|
end
|
data/lib/glossarist/cli.rb
CHANGED
|
@@ -57,6 +57,10 @@ module Glossarist
|
|
|
57
57
|
option :register_yaml, type: :string,
|
|
58
58
|
desc: "Path to register.yaml to include in package"
|
|
59
59
|
option :tags, type: :array, desc: "Tags for the dataset"
|
|
60
|
+
option :compiled_formats, type: :string,
|
|
61
|
+
desc: "Comma-separated compiled formats to bundle (tbx,jsonld,turtle,jsonl)"
|
|
62
|
+
option :concept_uri_template, type: :string,
|
|
63
|
+
desc: "URI template for concept URIs"
|
|
60
64
|
def package(dir)
|
|
61
65
|
require_relative "cli/package_command"
|
|
62
66
|
Glossarist::CLI::PackageCommand.new(dir, options).run
|
|
@@ -76,6 +80,25 @@ module Glossarist
|
|
|
76
80
|
Glossarist::CLI::ValidateCommand.new(path, options).run
|
|
77
81
|
end
|
|
78
82
|
|
|
83
|
+
desc "export PATH", "Export concepts in machine-readable formats"
|
|
84
|
+
option :format, type: :string, required: true,
|
|
85
|
+
enum: %w[json jsonld turtle tbx jsonl],
|
|
86
|
+
desc: "Output format"
|
|
87
|
+
option :output, aliases: :o, type: :string, required: true,
|
|
88
|
+
desc: "Output directory"
|
|
89
|
+
option :shortname, type: :string,
|
|
90
|
+
desc: "Dataset shortname for concept ID prefixing"
|
|
91
|
+
option :uri_prefix, type: :string,
|
|
92
|
+
desc: "URI/URN prefix for the dataset"
|
|
93
|
+
option :site_url, type: :string,
|
|
94
|
+
desc: "Base URL of the glossarist site"
|
|
95
|
+
option :title, type: :string,
|
|
96
|
+
desc: "Dataset title for document header"
|
|
97
|
+
def export(path)
|
|
98
|
+
require_relative "cli/export_command"
|
|
99
|
+
Glossarist::CLI::ExportCommand.new(path, options).run
|
|
100
|
+
end
|
|
101
|
+
|
|
79
102
|
def method_missing(*args)
|
|
80
103
|
warn "No method found named: #{args[0]}"
|
|
81
104
|
warn "Run with `--help` or `-h` to see available options"
|
|
@@ -19,6 +19,7 @@ module Glossarist
|
|
|
19
19
|
attribute :license, :string
|
|
20
20
|
attribute :uri_prefix, :string
|
|
21
21
|
attribute :concept_uri_template, :string
|
|
22
|
+
attribute :compiled_formats, :string, collection: true
|
|
22
23
|
attribute :external_references, :hash, collection: true
|
|
23
24
|
|
|
24
25
|
key_value do
|
|
@@ -39,6 +40,7 @@ module Glossarist
|
|
|
39
40
|
map :license, to: :license
|
|
40
41
|
map :uri_prefix, to: :uri_prefix
|
|
41
42
|
map :concept_uri_template, to: :concept_uri_template
|
|
43
|
+
map :compiled_formats, to: :compiled_formats
|
|
42
44
|
map :external_references, to: :external_references
|
|
43
45
|
end
|
|
44
46
|
|
|
@@ -59,6 +61,7 @@ module Glossarist
|
|
|
59
61
|
statistics: stats,
|
|
60
62
|
uri_prefix: options[:uri_prefix],
|
|
61
63
|
concept_uri_template: options[:concept_uri_template],
|
|
64
|
+
compiled_formats: options[:compiled_formats] || [],
|
|
62
65
|
external_references: derive_external_references(concepts),
|
|
63
66
|
)
|
|
64
67
|
end
|
|
@@ -5,6 +5,15 @@ require "fileutils"
|
|
|
5
5
|
|
|
6
6
|
module Glossarist
|
|
7
7
|
class GcrPackage
|
|
8
|
+
COMPILED_EXTENSIONS = {
|
|
9
|
+
"tbx" => "tbx.xml",
|
|
10
|
+
"jsonld" => "jsonld",
|
|
11
|
+
"turtle" => "ttl",
|
|
12
|
+
"jsonl" => "jsonl",
|
|
13
|
+
}.freeze
|
|
14
|
+
|
|
15
|
+
KNOWN_COMPILED_FORMATS = COMPILED_EXTENSIONS.keys.freeze
|
|
16
|
+
|
|
8
17
|
attr_reader :zip_path, :metadata, :concepts
|
|
9
18
|
|
|
10
19
|
def initialize(zip_path)
|
|
@@ -13,16 +22,18 @@ module Glossarist
|
|
|
13
22
|
@concepts = []
|
|
14
23
|
end
|
|
15
24
|
|
|
16
|
-
def self.create(concepts:, metadata:, output_path:, register_data: nil
|
|
25
|
+
def self.create(concepts:, metadata:, output_path:, register_data: nil,
|
|
26
|
+
compiled_formats: [], **opts)
|
|
17
27
|
FileUtils.mkdir_p(File.dirname(output_path))
|
|
18
28
|
package = new(output_path)
|
|
19
|
-
package.
|
|
29
|
+
package.write(concepts, metadata, register_data,
|
|
30
|
+
compiled_formats: compiled_formats, **opts)
|
|
20
31
|
package
|
|
21
32
|
end
|
|
22
33
|
|
|
23
34
|
def self.load(zip_path)
|
|
24
35
|
package = new(zip_path)
|
|
25
|
-
package.
|
|
36
|
+
package.read
|
|
26
37
|
package
|
|
27
38
|
end
|
|
28
39
|
|
|
@@ -30,8 +41,14 @@ module Glossarist
|
|
|
30
41
|
title: nil, description: nil, owner: nil,
|
|
31
42
|
tags: [], register_yaml: nil,
|
|
32
43
|
uri_prefix: nil, concept_uri_template: nil,
|
|
33
|
-
streaming: false)
|
|
44
|
+
streaming: false, compiled_formats: [])
|
|
34
45
|
dir = File.expand_path(dir)
|
|
46
|
+
formats = Array(compiled_formats).map(&:to_s)
|
|
47
|
+
|
|
48
|
+
if streaming && formats.any?
|
|
49
|
+
raise ArgumentError,
|
|
50
|
+
"Compiled formats require batch mode (streaming: true is incompatible)"
|
|
51
|
+
end
|
|
35
52
|
|
|
36
53
|
if streaming
|
|
37
54
|
create_streaming(dir, output: output, shortname: shortname, version: version,
|
|
@@ -44,7 +61,8 @@ module Glossarist
|
|
|
44
61
|
title: title, description: description, owner: owner,
|
|
45
62
|
tags: tags, register_yaml: register_yaml,
|
|
46
63
|
uri_prefix: uri_prefix,
|
|
47
|
-
concept_uri_template: concept_uri_template
|
|
64
|
+
concept_uri_template: concept_uri_template,
|
|
65
|
+
compiled_formats: formats)
|
|
48
66
|
end
|
|
49
67
|
end
|
|
50
68
|
|
|
@@ -52,9 +70,8 @@ module Glossarist
|
|
|
52
70
|
GcrValidator.new.validate(@zip_path)
|
|
53
71
|
end
|
|
54
72
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def write(concepts, metadata, register_data)
|
|
73
|
+
def write(concepts, metadata, register_data, compiled_formats: [],
|
|
74
|
+
shortname: nil, **opts)
|
|
58
75
|
Zip::File.open(@zip_path, create: true) do |zf|
|
|
59
76
|
zf.get_output_stream("metadata.yaml") do |f|
|
|
60
77
|
f.write(metadata.to_yaml)
|
|
@@ -69,6 +86,11 @@ module Glossarist
|
|
|
69
86
|
concepts.each do |mc|
|
|
70
87
|
write_concept(zf, mc)
|
|
71
88
|
end
|
|
89
|
+
|
|
90
|
+
if compiled_formats.any?
|
|
91
|
+
write_compiled(zf, concepts, compiled_formats, shortname: shortname,
|
|
92
|
+
**opts)
|
|
93
|
+
end
|
|
72
94
|
end
|
|
73
95
|
end
|
|
74
96
|
|
|
@@ -98,10 +120,67 @@ module Glossarist
|
|
|
98
120
|
end
|
|
99
121
|
end
|
|
100
122
|
|
|
123
|
+
def write_compiled(zip_file, concepts, formats, shortname: nil, **opts)
|
|
124
|
+
name = shortname || "glossary"
|
|
125
|
+
transform_opts = { shortname: name }.merge(opts.slice(:site_url,
|
|
126
|
+
:uri_prefix, :title))
|
|
127
|
+
|
|
128
|
+
if formats.include?("tbx")
|
|
129
|
+
write_compiled_tbx(zip_file, concepts, transform_opts, name)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
skos_formats = formats & %w[jsonld turtle jsonl]
|
|
133
|
+
if skos_formats.any?
|
|
134
|
+
write_compiled_skos(zip_file, concepts, skos_formats, transform_opts,
|
|
135
|
+
name)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
(formats - KNOWN_COMPILED_FORMATS).each do |fmt|
|
|
139
|
+
warn "Warning: Unknown compiled format '#{fmt}', skipping"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def write_compiled_tbx(zip_file, concepts, opts, name)
|
|
144
|
+
require "glossarist/transforms/concept_to_tbx_transform"
|
|
145
|
+
doc = Transforms::ConceptToTbxTransform.transform_document(concepts, opts)
|
|
146
|
+
zip_file.get_output_stream("compiled/#{name}.tbx.xml") do |f|
|
|
147
|
+
f.write(doc.to_xml)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def write_compiled_skos(zip_file, concepts, formats, opts, name) # rubocop:disable Metrics/MethodLength
|
|
152
|
+
require "glossarist/transforms/concept_to_skos_transform"
|
|
153
|
+
vocab = Transforms::ConceptToSkosTransform.transform_document(concepts,
|
|
154
|
+
opts)
|
|
155
|
+
|
|
156
|
+
if formats.include?("jsonld")
|
|
157
|
+
zip_file.get_output_stream("compiled/#{name}.jsonld") do |f|
|
|
158
|
+
f.write(vocab.to_jsonld)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
if formats.include?("turtle")
|
|
163
|
+
zip_file.get_output_stream("compiled/#{name}.ttl") do |f|
|
|
164
|
+
f.write(vocab.to_turtle)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
return unless formats.include?("jsonl")
|
|
169
|
+
|
|
170
|
+
zip_file.get_output_stream("compiled/#{name}.jsonl") do |f|
|
|
171
|
+
concepts.each do |concept|
|
|
172
|
+
skos = Transforms::ConceptToSkosTransform.transform(concept, opts)
|
|
173
|
+
f.write(skos.to_jsonld)
|
|
174
|
+
f.write("\n")
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
101
179
|
class << self
|
|
102
180
|
private
|
|
103
181
|
|
|
104
|
-
def create_batch(dir, output:, shortname:, version:,
|
|
182
|
+
def create_batch(dir, output:, shortname:, version:,
|
|
183
|
+
compiled_formats: [], **opts)
|
|
105
184
|
concepts = ConceptCollector.collect(dir)
|
|
106
185
|
if concepts.empty?
|
|
107
186
|
raise ArgumentError,
|
|
@@ -117,13 +196,17 @@ module Glossarist
|
|
|
117
196
|
|
|
118
197
|
register_data = load_register_data(opts[:register_yaml], dir)
|
|
119
198
|
metadata = build_metadata(concepts, shortname: shortname, version: version,
|
|
120
|
-
register_data: register_data,
|
|
199
|
+
register_data: register_data,
|
|
200
|
+
compiled_formats: compiled_formats, **opts)
|
|
121
201
|
|
|
122
202
|
create(
|
|
123
203
|
concepts: concepts,
|
|
124
204
|
metadata: metadata,
|
|
125
205
|
register_data: register_data,
|
|
126
206
|
output_path: File.expand_path(output),
|
|
207
|
+
compiled_formats: compiled_formats,
|
|
208
|
+
shortname: shortname,
|
|
209
|
+
**opts,
|
|
127
210
|
)
|
|
128
211
|
end
|
|
129
212
|
|
|
@@ -195,7 +278,7 @@ module Glossarist
|
|
|
195
278
|
end
|
|
196
279
|
|
|
197
280
|
def build_metadata(concepts, shortname:, version:, register_data: nil,
|
|
198
|
-
**opts)
|
|
281
|
+
compiled_formats: [], **opts)
|
|
199
282
|
GcrMetadata.from_concepts(
|
|
200
283
|
concepts,
|
|
201
284
|
register_data: register_data,
|
|
@@ -208,6 +291,7 @@ module Glossarist
|
|
|
208
291
|
tags: opts[:tags],
|
|
209
292
|
uri_prefix: opts[:uri_prefix],
|
|
210
293
|
concept_uri_template: opts[:concept_uri_template],
|
|
294
|
+
compiled_formats: compiled_formats,
|
|
211
295
|
},
|
|
212
296
|
)
|
|
213
297
|
end
|
|
@@ -29,7 +29,11 @@ module Glossarist
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def self.count_with(l10ns, attr)
|
|
32
|
-
|
|
32
|
+
case attr
|
|
33
|
+
when :definition then l10ns.count { |l| l.data.definition&.any? }
|
|
34
|
+
when :sources then l10ns.count { |l| l.data.sources&.any? }
|
|
35
|
+
else 0
|
|
36
|
+
end
|
|
33
37
|
end
|
|
34
38
|
end
|
|
35
39
|
end
|
|
@@ -10,8 +10,6 @@ module Glossarist
|
|
|
10
10
|
attribute :dates, ConceptDate, collection: true
|
|
11
11
|
attribute :sources, ConceptSource
|
|
12
12
|
attribute :date_accepted, ConceptDate
|
|
13
|
-
# TODO: convert to LocalizedConceptCollection when custom
|
|
14
|
-
# collections are implemented in lutaml-model
|
|
15
13
|
attribute :status, :string,
|
|
16
14
|
values: Glossarist::GlossaryDefinition::CONCEPT_STATUSES
|
|
17
15
|
|
|
@@ -35,14 +33,6 @@ module Glossarist
|
|
|
35
33
|
map :uuid, to: :uuid, with: { from: :uuid_from_yaml, to: :uuid_to_yaml }
|
|
36
34
|
end
|
|
37
35
|
|
|
38
|
-
def localized_concepts
|
|
39
|
-
data.localized_concepts
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def localized_concepts=(val)
|
|
43
|
-
data.localized_concepts = val
|
|
44
|
-
end
|
|
45
|
-
|
|
46
36
|
def localizations
|
|
47
37
|
data.localizations
|
|
48
38
|
end
|
|
@@ -123,9 +113,16 @@ module Glossarist
|
|
|
123
113
|
end
|
|
124
114
|
alias :add_l10n :add_localization
|
|
125
115
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
116
|
+
def to_jsonld
|
|
117
|
+
require "glossarist/transforms/concept_to_skos_transform"
|
|
118
|
+
Transforms::ConceptToSkosTransform.transform(self).to_jsonld
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def to_turtle
|
|
122
|
+
require "glossarist/transforms/concept_to_skos_transform"
|
|
123
|
+
Transforms::ConceptToSkosTransform.transform(self).to_turtle
|
|
124
|
+
end
|
|
125
|
+
|
|
129
126
|
def default_designation
|
|
130
127
|
localized = localization("eng") || localizations.values.first
|
|
131
128
|
terms = localized&.preferred_terms&.first || localized&.terms&.first
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Glossarist
|
|
4
|
+
module Rdf
|
|
5
|
+
class LocalizedLiteral < Lutaml::Model::Serializable
|
|
6
|
+
include Lutaml::Rdf::LanguageTagged
|
|
7
|
+
|
|
8
|
+
attribute :value, :string
|
|
9
|
+
attribute :language_code, :string
|
|
10
|
+
|
|
11
|
+
key_value do
|
|
12
|
+
map :value, to: :value
|
|
13
|
+
map :language_code, to: :language_code
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def language_tag
|
|
17
|
+
language_code
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_s
|
|
21
|
+
value.to_s
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/turtle"
|
|
4
|
+
require "lutaml/jsonld"
|
|
5
|
+
require_relative "../rdf"
|
|
6
|
+
|
|
7
|
+
module Glossarist
|
|
8
|
+
module Rdf
|
|
9
|
+
class SkosConcept < Lutaml::Model::Serializable
|
|
10
|
+
attribute :code, :string
|
|
11
|
+
attribute :labels, LocalizedLiteral, collection: true
|
|
12
|
+
attribute :definitions, LocalizedLiteral, collection: true
|
|
13
|
+
attribute :alt_labels, LocalizedLiteral, collection: true
|
|
14
|
+
attribute :scope_notes, LocalizedLiteral, collection: true
|
|
15
|
+
attribute :sources, :string, collection: true
|
|
16
|
+
attribute :domain, :string
|
|
17
|
+
attribute :date_accepted, :string
|
|
18
|
+
|
|
19
|
+
rdf do
|
|
20
|
+
namespace Namespaces::SkosNamespace, Namespaces::DctermsNamespace
|
|
21
|
+
|
|
22
|
+
subject { |c| "https://glossarist.org/concept/#{c.code}" }
|
|
23
|
+
type "skos:Concept"
|
|
24
|
+
|
|
25
|
+
predicate :notation, namespace: Namespaces::SkosNamespace,
|
|
26
|
+
to: :code
|
|
27
|
+
predicate :prefLabel, namespace: Namespaces::SkosNamespace,
|
|
28
|
+
to: :labels, lang_tagged: true
|
|
29
|
+
predicate :definition, namespace: Namespaces::SkosNamespace,
|
|
30
|
+
to: :definitions, lang_tagged: true
|
|
31
|
+
predicate :altLabel, namespace: Namespaces::SkosNamespace,
|
|
32
|
+
to: :alt_labels, lang_tagged: true
|
|
33
|
+
predicate :scopeNote, namespace: Namespaces::SkosNamespace,
|
|
34
|
+
to: :scope_notes, lang_tagged: true
|
|
35
|
+
predicate :subject, namespace: Namespaces::DctermsNamespace,
|
|
36
|
+
to: :domain
|
|
37
|
+
predicate :source, namespace: Namespaces::DctermsNamespace,
|
|
38
|
+
to: :sources
|
|
39
|
+
predicate :dateAccepted, namespace: Namespaces::DctermsNamespace,
|
|
40
|
+
to: :date_accepted
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/turtle"
|
|
4
|
+
require "lutaml/jsonld"
|
|
5
|
+
require_relative "../rdf"
|
|
6
|
+
|
|
7
|
+
module Glossarist
|
|
8
|
+
module Rdf
|
|
9
|
+
class SkosVocabulary < Lutaml::Model::Serializable
|
|
10
|
+
attribute :id, :string
|
|
11
|
+
attribute :title, :string
|
|
12
|
+
attribute :concepts, SkosConcept, collection: true
|
|
13
|
+
|
|
14
|
+
rdf do
|
|
15
|
+
namespace Namespaces::SkosNamespace, Namespaces::DctermsNamespace
|
|
16
|
+
|
|
17
|
+
subject { |v| "https://glossarist.org/vocab/#{v.id}" }
|
|
18
|
+
type "skos:ConceptScheme"
|
|
19
|
+
|
|
20
|
+
predicate :prefLabel, namespace: Namespaces::SkosNamespace, to: :title
|
|
21
|
+
|
|
22
|
+
members :concepts
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Glossarist
|
|
4
|
+
module Rdf
|
|
5
|
+
autoload :Namespaces, "#{__dir__}/rdf/namespaces"
|
|
6
|
+
autoload :LocalizedLiteral, "#{__dir__}/rdf/localized_literal"
|
|
7
|
+
autoload :SkosConcept, "#{__dir__}/rdf/skos_concept"
|
|
8
|
+
autoload :SkosVocabulary, "#{__dir__}/rdf/skos_vocabulary"
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -41,9 +41,7 @@ module Glossarist
|
|
|
41
41
|
def designations_for(concept)
|
|
42
42
|
if concept.is_a?(ManagedConcept)
|
|
43
43
|
concept.localizations.flat_map do |l10n|
|
|
44
|
-
l10n.data.terms.filter_map
|
|
45
|
-
t.respond_to?(:designation) ? t.designation : nil
|
|
46
|
-
end
|
|
44
|
+
l10n.data.terms.filter_map(&:designation)
|
|
47
45
|
end
|
|
48
46
|
else
|
|
49
47
|
concept.each_value.flat_map do |lang_block|
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "../rdf"
|
|
4
|
+
|
|
5
|
+
module Glossarist
|
|
6
|
+
module Transforms
|
|
7
|
+
class ConceptToSkosTransform
|
|
8
|
+
def self.transform(managed_concept, options = {})
|
|
9
|
+
new(managed_concept, options).build
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.transform_document(concepts, options = {})
|
|
13
|
+
Rdf::SkosVocabulary.new(
|
|
14
|
+
id: options[:shortname] || "glossary",
|
|
15
|
+
title: options[:title],
|
|
16
|
+
concepts: concepts.map { |c| transform(c, options) },
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def initialize(managed_concept, options = {})
|
|
21
|
+
@concept = managed_concept
|
|
22
|
+
@options = options
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def build
|
|
26
|
+
Rdf::SkosConcept.new(
|
|
27
|
+
code: concept_code,
|
|
28
|
+
labels: build_labels,
|
|
29
|
+
definitions: build_definitions,
|
|
30
|
+
alt_labels: build_alt_labels,
|
|
31
|
+
scope_notes: build_scope_notes,
|
|
32
|
+
domain: build_domain,
|
|
33
|
+
sources: build_sources,
|
|
34
|
+
date_accepted: build_date_accepted,
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
attr_reader :concept, :options
|
|
41
|
+
|
|
42
|
+
def concept_code
|
|
43
|
+
concept.data&.id || concept.identifier
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def build_labels
|
|
47
|
+
each_localization.filter_map do |lang, l10n|
|
|
48
|
+
term = l10n.preferred_terms&.first || l10n.terms&.first
|
|
49
|
+
next unless term
|
|
50
|
+
|
|
51
|
+
Rdf::LocalizedLiteral.new(
|
|
52
|
+
value: term.designation.to_s,
|
|
53
|
+
language_code: lang,
|
|
54
|
+
)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def build_alt_labels
|
|
59
|
+
each_localization.flat_map do |lang, l10n|
|
|
60
|
+
preferred_term = l10n.preferred_terms&.first || l10n.terms&.first
|
|
61
|
+
(l10n.terms || []).reject do |t|
|
|
62
|
+
t == preferred_term
|
|
63
|
+
end.filter_map do |term|
|
|
64
|
+
next unless term.designation
|
|
65
|
+
|
|
66
|
+
Rdf::LocalizedLiteral.new(
|
|
67
|
+
value: term.designation.to_s,
|
|
68
|
+
language_code: lang,
|
|
69
|
+
)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def build_definitions
|
|
75
|
+
each_localization.filter_map do |lang, l10n|
|
|
76
|
+
content = l10n.data&.definition&.first&.content
|
|
77
|
+
next unless content
|
|
78
|
+
|
|
79
|
+
Rdf::LocalizedLiteral.new(
|
|
80
|
+
value: content.to_s,
|
|
81
|
+
language_code: lang,
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def build_scope_notes
|
|
87
|
+
each_localization.filter_map do |lang, l10n|
|
|
88
|
+
note = l10n.data&.notes&.first&.content
|
|
89
|
+
next unless note
|
|
90
|
+
|
|
91
|
+
Rdf::LocalizedLiteral.new(
|
|
92
|
+
value: note.to_s,
|
|
93
|
+
language_code: lang,
|
|
94
|
+
)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def build_domain
|
|
99
|
+
l10n = concept.localizations.first
|
|
100
|
+
l10n&.data&.domain
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def build_sources
|
|
104
|
+
each_localization.flat_map do |_lang, l10n|
|
|
105
|
+
Array(l10n.data&.sources).select(&:authoritative?).filter_map do |src|
|
|
106
|
+
origin = src.origin
|
|
107
|
+
next unless origin
|
|
108
|
+
|
|
109
|
+
origin.ref || origin.text
|
|
110
|
+
end
|
|
111
|
+
end.uniq
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def build_date_accepted
|
|
115
|
+
date = concept.date_accepted
|
|
116
|
+
return unless date
|
|
117
|
+
|
|
118
|
+
date.date&.iso8601
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def each_localization
|
|
122
|
+
return enum_for(:each_localization) unless block_given?
|
|
123
|
+
|
|
124
|
+
concept.localizations.each do |l10n|
|
|
125
|
+
lang = l10n.language_code || l10n.data&.language_code
|
|
126
|
+
next unless lang
|
|
127
|
+
|
|
128
|
+
yield lang, l10n
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "tbx"
|
|
4
|
+
|
|
5
|
+
module Glossarist
|
|
6
|
+
module Transforms
|
|
7
|
+
class ConceptToTbxTransform
|
|
8
|
+
def self.transform(managed_concept, options = {})
|
|
9
|
+
new(managed_concept, options).build_entry
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.transform_document(concepts, options = {})
|
|
13
|
+
doc = Tbx::Document.new
|
|
14
|
+
body = Tbx::Body.new
|
|
15
|
+
body.concept_entry = concepts.map { |c| transform(c, options) }
|
|
16
|
+
text = Tbx::TextElement.new
|
|
17
|
+
text.body = body
|
|
18
|
+
doc.text = text
|
|
19
|
+
|
|
20
|
+
if options[:title]
|
|
21
|
+
header = doc.tbx_header || Tbx::TbxHeader.new
|
|
22
|
+
file_desc = Tbx::FileDesc.new
|
|
23
|
+
title_stmt = Tbx::TitleStmt.new
|
|
24
|
+
title = Tbx::Title.new
|
|
25
|
+
title.content = options[:title]
|
|
26
|
+
title_stmt.title = title
|
|
27
|
+
file_desc.title_stmt = title_stmt
|
|
28
|
+
header.file_desc = file_desc
|
|
29
|
+
doc.tbx_header = header
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
doc
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def initialize(managed_concept, options = {})
|
|
36
|
+
@concept = managed_concept
|
|
37
|
+
@options = options
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def build_entry
|
|
41
|
+
entry = Tbx::ConceptEntry.new
|
|
42
|
+
entry.id = concept_id
|
|
43
|
+
entry.lang_sec = build_lang_sections
|
|
44
|
+
entry
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
attr_reader :concept, :options
|
|
50
|
+
|
|
51
|
+
def concept_id
|
|
52
|
+
prefix = options[:shortname]
|
|
53
|
+
id = concept.data&.id || concept.identifier
|
|
54
|
+
prefix ? "#{prefix}_#{id}" : id.to_s
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def build_lang_sections
|
|
58
|
+
concept.localizations.filter_map do |l10n|
|
|
59
|
+
lang = l10n.language_code
|
|
60
|
+
next unless lang
|
|
61
|
+
|
|
62
|
+
ls = Tbx::LangSec.new
|
|
63
|
+
ls.lang = lang
|
|
64
|
+
|
|
65
|
+
term = l10n.preferred_terms&.first || l10n.terms&.first
|
|
66
|
+
if term&.designation
|
|
67
|
+
ts = Tbx::TermSec.new
|
|
68
|
+
t = Tbx::Term.new
|
|
69
|
+
t.content = term.designation.to_s
|
|
70
|
+
ts.term = t
|
|
71
|
+
ls.term_sec = ts
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
definition = l10n.data&.definition&.first&.content
|
|
75
|
+
if definition
|
|
76
|
+
ds = Tbx::Descrip.new
|
|
77
|
+
ds.content = definition.to_s
|
|
78
|
+
ls.descrip = ds
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
ls
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
data/lib/glossarist/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: glossarist
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.6.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ribose
|
|
8
|
+
autorequire:
|
|
8
9
|
bindir: exe
|
|
9
10
|
cert_chain: []
|
|
10
|
-
date:
|
|
11
|
+
date: 2026-05-06 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
12
13
|
- !ruby/object:Gem::Dependency
|
|
13
14
|
name: lutaml-model
|
|
@@ -15,14 +16,14 @@ dependencies:
|
|
|
15
16
|
requirements:
|
|
16
17
|
- - "~>"
|
|
17
18
|
- !ruby/object:Gem::Version
|
|
18
|
-
version:
|
|
19
|
+
version: 0.8.5
|
|
19
20
|
type: :runtime
|
|
20
21
|
prerelease: false
|
|
21
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
23
|
requirements:
|
|
23
24
|
- - "~>"
|
|
24
25
|
- !ruby/object:Gem::Version
|
|
25
|
-
version:
|
|
26
|
+
version: 0.8.5
|
|
26
27
|
- !ruby/object:Gem::Dependency
|
|
27
28
|
name: relaton
|
|
28
29
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -63,6 +64,20 @@ dependencies:
|
|
|
63
64
|
- - "<"
|
|
64
65
|
- !ruby/object:Gem::Version
|
|
65
66
|
version: '3'
|
|
67
|
+
- !ruby/object:Gem::Dependency
|
|
68
|
+
name: tbx
|
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
|
70
|
+
requirements:
|
|
71
|
+
- - "~>"
|
|
72
|
+
- !ruby/object:Gem::Version
|
|
73
|
+
version: '0.1'
|
|
74
|
+
type: :runtime
|
|
75
|
+
prerelease: false
|
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - "~>"
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '0.1'
|
|
66
81
|
- !ruby/object:Gem::Dependency
|
|
67
82
|
name: thor
|
|
68
83
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -77,6 +92,7 @@ dependencies:
|
|
|
77
92
|
- - ">="
|
|
78
93
|
- !ruby/object:Gem::Version
|
|
79
94
|
version: '0'
|
|
95
|
+
description:
|
|
80
96
|
email:
|
|
81
97
|
- open.source@ribose.com
|
|
82
98
|
executables:
|
|
@@ -105,6 +121,7 @@ files:
|
|
|
105
121
|
- lib/glossarist/asset.rb
|
|
106
122
|
- lib/glossarist/citation.rb
|
|
107
123
|
- lib/glossarist/cli.rb
|
|
124
|
+
- lib/glossarist/cli/export_command.rb
|
|
108
125
|
- lib/glossarist/cli/package_command.rb
|
|
109
126
|
- lib/glossarist/cli/upgrade_command.rb
|
|
110
127
|
- lib/glossarist/cli/validate_command.rb
|
|
@@ -158,6 +175,13 @@ files:
|
|
|
158
175
|
- lib/glossarist/managed_concept_collection.rb
|
|
159
176
|
- lib/glossarist/managed_concept_data.rb
|
|
160
177
|
- lib/glossarist/non_verb_rep.rb
|
|
178
|
+
- lib/glossarist/rdf.rb
|
|
179
|
+
- lib/glossarist/rdf/localized_literal.rb
|
|
180
|
+
- lib/glossarist/rdf/namespaces.rb
|
|
181
|
+
- lib/glossarist/rdf/namespaces/dcterms_namespace.rb
|
|
182
|
+
- lib/glossarist/rdf/namespaces/skos_namespace.rb
|
|
183
|
+
- lib/glossarist/rdf/skos_concept.rb
|
|
184
|
+
- lib/glossarist/rdf/skos_vocabulary.rb
|
|
161
185
|
- lib/glossarist/reference_extractor.rb
|
|
162
186
|
- lib/glossarist/reference_resolver.rb
|
|
163
187
|
- lib/glossarist/register_data.rb
|
|
@@ -168,6 +192,9 @@ files:
|
|
|
168
192
|
- lib/glossarist/resolution_adapter/remote.rb
|
|
169
193
|
- lib/glossarist/resolution_adapter/route.rb
|
|
170
194
|
- lib/glossarist/schema_migration.rb
|
|
195
|
+
- lib/glossarist/transforms.rb
|
|
196
|
+
- lib/glossarist/transforms/concept_to_skos_transform.rb
|
|
197
|
+
- lib/glossarist/transforms/concept_to_tbx_transform.rb
|
|
171
198
|
- lib/glossarist/urn_resolver.rb
|
|
172
199
|
- lib/glossarist/utilities.rb
|
|
173
200
|
- lib/glossarist/utilities/common_functions.rb
|
|
@@ -192,6 +219,7 @@ metadata:
|
|
|
192
219
|
source_code_uri: https://github.com/glossarist/glossarist-ruby
|
|
193
220
|
bug_tracker_uri: https://github.com/glossarist/glossarist-ruby/issues
|
|
194
221
|
rubygems_mfa_required: 'true'
|
|
222
|
+
post_install_message:
|
|
195
223
|
rdoc_options: []
|
|
196
224
|
require_paths:
|
|
197
225
|
- lib
|
|
@@ -206,7 +234,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
206
234
|
- !ruby/object:Gem::Version
|
|
207
235
|
version: '0'
|
|
208
236
|
requirements: []
|
|
209
|
-
rubygems_version: 3.
|
|
237
|
+
rubygems_version: 3.5.22
|
|
238
|
+
signing_key:
|
|
210
239
|
specification_version: 4
|
|
211
240
|
summary: Concept models for terminology glossaries conforming ISO 10241-1.
|
|
212
241
|
test_files: []
|