simple_inline_text_annotation 2.1.0 → 2.2.0

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: afa33452d357e5a3a6c59e9283111d87cad5b3153e97c759e59b98efed7ec18a
4
- data.tar.gz: 3ad0707815cbad9040153cee41c6e54761f32364bec3c9780f23d7a119c2e2b5
3
+ metadata.gz: 3c4a6b74cd54c5a3ef2263ee7e591cc1f5ef2acab8f36b991fdd3a7f84fc887c
4
+ data.tar.gz: a436a2add0c95d4484f096a4c56ca1dc283f5e54178377ebeb50f53c4cbe9ddb
5
5
  SHA512:
6
- metadata.gz: 22726d0174ed12d50a435d038d6f78adb2bc51062c692d94704705b511cbaffbbfa47c1b4d997bed6519bcf1eb30dc200fbd8380fc3887444fa5bd45668cf524
7
- data.tar.gz: 45d9bc60245dc1f91b72f77110ce04b4b00010c674b1b2be61c46f3499683cf392451279cc126e6d24518a14dedfe4919f23615f6a963c8d0267a77096f73d6d
6
+ metadata.gz: a34913353fd069aab8ad9e19955fcfaf50e8856d8e49c91034eb271c5eb9e156f3cf03371f4b053a9f4fc85d5f3d4e5fc62afaefbc7d5da0b70e93f72acee825
7
+ data.tar.gz: 4eddd143142df13d5b4653805bac281e9b2043fd3ec9ab4ac4d2bf1c104eb43ffa2b2f2491435a31e6a0f8ff0b1145ba29ba246df94d6aee7f93aea28fe20ab2
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4.4
@@ -15,7 +15,11 @@ class SimpleInlineTextAnnotation
15
15
  private
16
16
 
17
17
  def remove_duplicates_from(denotations)
18
- denotations.uniq(&:span)
18
+ # Deduplicate on the FULL identity (span + obj + id), not just span —
19
+ # two denotations sharing a span but pointing at different objs are the
20
+ # multi-label case (e.g. `[eye][UBERON_0000019|UBERON_0000955]`) and
21
+ # Generator pipe-joins them. Only truly identical entries are dropped.
22
+ denotations.uniq { |d| [d.span, d.obj, d.id] }
19
23
  end
20
24
 
21
25
  def remove_non_integer_positions_from(denotations)
@@ -40,12 +44,19 @@ class SimpleInlineTextAnnotation
40
44
  result = []
41
45
 
42
46
  sorted_denotations.each do |denotation|
43
- result << denotation unless result.any? { |outer| denotation.nested_within?(outer) }
47
+ # Preserve denotations that share an EXACT span with an already-accepted
48
+ # one (the multi-label case — Generator will pipe-join their labels).
49
+ # Only drop those STRICTLY nested inside a larger outer span.
50
+ result << denotation unless result.any? { |outer| strictly_nested?(denotation, outer) }
44
51
  end
45
52
 
46
53
  result
47
54
  end
48
55
 
56
+ def strictly_nested?(inner, outer)
57
+ inner.nested_within?(outer) && (inner.begin_pos != outer.begin_pos || inner.end_pos != outer.end_pos)
58
+ end
59
+
49
60
  def remove_boundary_crosses_from(denotations)
50
61
  denotations.reject do |denotation|
51
62
  denotations.any? { |existing| denotation.boundary_crossing?(existing) }
@@ -34,27 +34,46 @@ class SimpleInlineTextAnnotation
34
34
  end
35
35
 
36
36
  def annotate_text(text, denotations, relations)
37
+ # Group denotations by span position so multiple denotations on the
38
+ # SAME span emit ONE annotation with a pipe-joined label
39
+ # (e.g. `[eye][UBERON_0000019|UBERON_0000955]`) — the SIAF spec's
40
+ # extension for multi-labelled spans. Individual URL resolution via
41
+ # `entity types` config still applies to each label independently, so
42
+ # the tail reference block lists every underlying URL.
43
+ grouped = denotations.group_by { |d| [d.begin_pos, d.end_pos] }
44
+
37
45
  # Annotate text from the end to ensure position calculation.
38
- denotations.sort_by(&:begin_pos).reverse_each do |denotation|
39
- text = annotate_text_with_denotation(text, denotation, relations)
46
+ grouped.sort_by { |(b, _e), _| b }.reverse_each do |(_b, _e), ds|
47
+ text = annotate_text_with_denotations(text, ds, relations)
40
48
  end
41
49
 
42
50
  text
43
51
  end
44
52
 
45
- def annotate_text_with_denotation(text, denotation, relations)
46
- begin_pos = denotation.begin_pos
47
- end_pos = denotation.end_pos
48
- annotation = if denotation.id && !denotation.id.empty?
49
- get_annotations(denotation, relations)
50
- else
51
- get_obj(denotation.obj)
52
- end
53
+ def annotate_text_with_denotations(text, denotations, relations)
54
+ begin_pos = denotations.first.begin_pos
55
+ end_pos = denotations.first.end_pos
56
+ composite = compose_label(denotations, relations)
53
57
 
54
- annotated_text = "[#{text[begin_pos...end_pos]}][#{annotation}]"
58
+ annotated_text = "[#{text[begin_pos...end_pos]}][#{composite}]"
55
59
  text[0...begin_pos] + annotated_text + text[end_pos..]
56
60
  end
57
61
 
62
+ # Compose each denotation's label independently (honors get_obj URL →
63
+ # short-label lookup and per-denotation relation composition), then
64
+ # pipe-join with dedupe to preserve insertion order.
65
+ def compose_label(denotations, relations)
66
+ denotations.map { |d| label_for(d, relations) }.uniq.join("|")
67
+ end
68
+
69
+ def label_for(denotation, relations)
70
+ if denotation.id && !denotation.id.empty?
71
+ get_annotations(denotation, relations)
72
+ else
73
+ get_obj(denotation.obj)
74
+ end
75
+ end
76
+
58
77
  def labeled_entity_types
59
78
  return nil unless @config
60
79
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class SimpleInlineTextAnnotation
4
- VERSION = "2.1.0"
4
+ VERSION = "2.2.0"
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_inline_text_annotation
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - xaiBUh29wX
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2025-08-05 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies: []
13
12
  description: This gem provides inline text annotation functionality, extracted from
14
13
  PubAnnotation, with support for denotations, entity types, and nested spans.
@@ -20,6 +19,7 @@ extra_rdoc_files: []
20
19
  files:
21
20
  - ".rspec"
22
21
  - ".rubocop.yml"
22
+ - ".ruby-version"
23
23
  - CHANGELOG.md
24
24
  - CODE_OF_CONDUCT.md
25
25
  - LICENSE.txt
@@ -43,7 +43,6 @@ metadata:
43
43
  homepage_uri: https://github.com/pubannotation/simple_inline_annotation_format
44
44
  changelog_uri: https://github.com/pubannotation/simple_inline_annotation_format/blob/master/ruby/CHANGELOG.md
45
45
  rubygems_uri: https://rubygems.org/gems/simple_inline_text_annotation
46
- post_install_message:
47
46
  rdoc_options: []
48
47
  require_paths:
49
48
  - lib
@@ -58,8 +57,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
58
57
  - !ruby/object:Gem::Version
59
58
  version: '0'
60
59
  requirements: []
61
- rubygems_version: 3.4.20
62
- signing_key:
60
+ rubygems_version: 3.6.7
63
61
  specification_version: 4
64
62
  summary: A Ruby gem for inline text annotation with denotations and entity types.
65
63
  test_files: []