glossarist 2.13.5 → 2.13.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f074d0113023ae82f1ae9cc8186cee518bc10ad87faabe3895117dcbbc700524
4
- data.tar.gz: 8d89647b60c955419db263514521fcefcaa2efc07b4f6a16510bae2fa0313a82
3
+ metadata.gz: 51ac508f50dca0e1c04b8a37fbb75460dc27496876321361b9e3691995b203dc
4
+ data.tar.gz: a41b2f29cfaca14931ee3035c751ad296065a0159b9bc202251e1775973f3ea8
5
5
  SHA512:
6
- metadata.gz: 539a902946b70e6dac712f088a73b456e0732b29740ff770194a3165624edffcc88b8169221d37d97cf357d2bb0b486acb0f9b042c716634df04fe9ba0c9d1c9
7
- data.tar.gz: 3ba5d4428d42ab96861986029fe8ca919cbabefa90c42c5106b888e27e8bc74e02c4dc31413b4cb6915858ef4a261c0c4818edbe46e89e0ae01474e4b589ce85
6
+ metadata.gz: 5a9a6b0040e89f986f676a2dbd4b8c86244c110fb4f3c005f9d5995f3bdf7abef50c48564c5d8551d11beca5f7876def2b8970ff719b086e091562f6ce3830ae
7
+ data.tar.gz: 4f81856d110124d519e3cbf10a5863623fe13b57283e89861ce1882c83d7fb1768c792c0f27e41b99c4cd7c462b00ce0a7dcfb894169c92985c4430c4fa8b84a
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "digest"
4
+
5
+ module Glossarist
6
+ module Rdf
7
+ # Deterministic slug helper for RDF subject URIs.
8
+ #
9
+ # When an entity has no natural-language identifier (no source/id
10
+ # pair, no text), derive a deterministic short slug from its
11
+ # content fingerprint. Same content → same slug across runs and
12
+ # across processes; different content → different slug (modulo
13
+ # collision probability).
14
+ #
15
+ # Hash choice:
16
+ # - SHA-256 (not MD5). MD5 is deprecated for new code; SHA-256
17
+ # is the modern baseline and is free performance-wise.
18
+ # - Truncated to 16 hex chars (64 bits). Birthday-paradox
19
+ # collision probability at 4 million items < 1e-9, comfortable
20
+ # margin for any realistic dataset.
21
+ #
22
+ # Previous width was 12 chars (48 bits) using MD5 — collision
23
+ # probability at 100k items was ~0.3%, too high for RDF merge.
24
+ module DeterministicSlug
25
+ HASH_WIDTH = 16
26
+
27
+ def self.from_parts(*parts)
28
+ joined = parts.compact.join("|")
29
+ Digest::SHA256.hexdigest(joined)[0, HASH_WIDTH]
30
+ end
31
+ end
32
+ end
33
+ end
@@ -32,7 +32,7 @@ module Glossarist
32
32
 
33
33
  def self.slug(citation)
34
34
  slug = [citation.source, citation.id].compact.join("/")
35
- slug = Digest::MD5.hexdigest(citation.source || "")[0..11] if slug.empty?
35
+ slug = DeterministicSlug.from_parts(citation.source) if slug.empty?
36
36
  slug
37
37
  end
38
38
  end
@@ -38,7 +38,7 @@ module Glossarist
38
38
  Array(source.sourced_from).each do |sf|
39
39
  parts << sf&.source << sf&.id << sf&.version << sf&.link
40
40
  end
41
- Digest::MD5.hexdigest(parts.compact.join("|"))[0..11]
41
+ DeterministicSlug.from_parts(*parts)
42
42
  end
43
43
  end
44
44
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "digest"
4
3
  require "lutaml/model"
5
4
 
6
5
  module Glossarist
@@ -24,7 +23,7 @@ module Glossarist
24
23
  end
25
24
 
26
25
  def self.deterministic_id(definition)
27
- Digest::MD5.hexdigest(definition.content.to_s)[0..11]
26
+ DeterministicSlug.from_parts(definition.content)
28
27
  end
29
28
  end
30
29
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "digest"
4
3
  require "lutaml/model"
5
4
 
6
5
  module Glossarist
@@ -48,9 +47,10 @@ module Glossarist
48
47
  readable = [member.ref_source, member.ref_id].compact.reject(&:empty?)
49
48
  return readable.join(":") unless readable.empty?
50
49
 
51
- parts = [member.ref_source, member.ref_id, member.ref_text,
52
- member.presence, member.count, member.is_delimiting]
53
- Digest::MD5.hexdigest(parts.compact.join("|"))[0..11]
50
+ DeterministicSlug.from_parts(
51
+ member.ref_source, member.ref_id, member.ref_text,
52
+ member.presence, member.count, member.is_delimiting
53
+ )
54
54
  end
55
55
  end
56
56
  end
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "digest"
4
3
  require "lutaml/model"
5
4
 
6
5
  module Glossarist
@@ -38,12 +37,12 @@ module Glossarist
38
37
  end
39
38
 
40
39
  def self.deterministic_id(rel)
41
- parts = [rel.identifier, rel.comprehensive_uri, rel.completeness]
42
- parts << criterion_fingerprint(rel.criterion)
40
+ parts = [rel.identifier, rel.comprehensive_uri, rel.completeness,
41
+ criterion_fingerprint(rel.criterion)]
43
42
  Array(rel.partitive_members).each do |m|
44
43
  parts << GlossPartitiveMember.deterministic_id(m)
45
44
  end
46
- Digest::MD5.hexdigest(parts.compact.join("|"))[0..11]
45
+ DeterministicSlug.from_parts(*parts)
47
46
  end
48
47
 
49
48
  def self.criterion_fingerprint(criterion)
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "lutaml/model"
4
- require "digest"
5
4
 
6
5
  module Glossarist
7
6
  module Rdf
@@ -47,7 +46,7 @@ module Glossarist
47
46
 
48
47
  def self.slug(ref)
49
48
  slug = [ref.source, ref.id].compact.join("/")
50
- slug = Digest::MD5.hexdigest(ref.text || "")[0..11] if slug.empty?
49
+ slug = DeterministicSlug.from_parts(ref.text) if slug.empty?
51
50
  slug
52
51
  end
53
52
  end
@@ -17,6 +17,7 @@ module Glossarist
17
17
  autoload :LutamlTurtleTransformExt, "#{__dir__}/rdf/lutaml_ext"
18
18
 
19
19
  autoload :Namespaces, "#{__dir__}/rdf/namespaces"
20
+ autoload :DeterministicSlug, "#{__dir__}/rdf/deterministic_slug"
20
21
  autoload :LocalizedLiteral, "#{__dir__}/rdf/localized_literal"
21
22
  autoload :RelationshipPredicates, "#{__dir__}/rdf/relationship_predicates"
22
23
  autoload :GlossLocality, "#{__dir__}/rdf/gloss_locality"
@@ -4,5 +4,5 @@
4
4
  #
5
5
 
6
6
  module Glossarist
7
- VERSION = "2.13.5"
7
+ VERSION = "2.13.6"
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glossarist
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.13.5
4
+ version: 2.13.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-07-28 00:00:00.000000000 Z
11
+ date: 2026-07-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lutaml-model
@@ -296,6 +296,7 @@ files:
296
296
  - lib/glossarist/non_verbal_reference.rb
297
297
  - lib/glossarist/pronunciation.rb
298
298
  - lib/glossarist/rdf.rb
299
+ - lib/glossarist/rdf/deterministic_slug.rb
299
300
  - lib/glossarist/rdf/gloss_citation.rb
300
301
  - lib/glossarist/rdf/gloss_concept.rb
301
302
  - lib/glossarist/rdf/gloss_concept_date.rb