relaton-render 1.2.0 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bfa59dd1186cb178a96316ffff00066b9c048a326f47dda9381424f4d805e79c
4
- data.tar.gz: b6f23cf5a7190c5cbac9b57350cf3a3812da2fbf94cf45218d02c7f4a8bc026c
3
+ metadata.gz: ece7911d68f25665c109d3a9420e30aab669c880655c5bb15b4146c8acee4f43
4
+ data.tar.gz: 1ba627049f678c0b817da7a93af4420b74e34579965a65eeaeb0f80126abed02
5
5
  SHA512:
6
- metadata.gz: 8a857436fbd6e62d3d0471efe0a8c0b4b2a77684a9346558d1912d51fdd84d353a8c40aa7a141f5bfd03da162dd97e0a6c5817e86dffaa3c139e2df0b7d638c8
7
- data.tar.gz: 8701d33d12f8cad24ccb245c0804c4e3e886aa833a6a8da8d86866acd2b7db540c12221a47ec9ae234617744c8cc26bec40c1c2192900ec89ce1af002135d697
6
+ metadata.gz: 92ad5ab36726f3b857ff9d792cce3ae2ba3ba0b8adba21308b0596da88822f16e4131b92c7047b31105036c534c552815d12e10b3e0773cbf04634769713c8f5
7
+ data.tar.gz: 790abb7747575c3b990fdb6a4ed579c3fc2269d35b1e05f0d3ab6c0869686784b4b91dfd8c0f9d7a006516c681e1821604f6351e91918fd210df78c9f106e760
@@ -82,6 +82,13 @@ module Relaton
82
82
  end
83
83
  end
84
84
 
85
+ ALLOWED_INLINE_TAGS = %w[
86
+ em eref strong stem sub sup tt underline keyword ruby
87
+ strike smallcap xref br link hr pagebreak bookmark
88
+ image index index-xref concept add del span erefstack
89
+ date fn
90
+ ].freeze
91
+
85
92
  private
86
93
 
87
94
  def blank?(text)
@@ -93,6 +100,46 @@ module Relaton
93
100
  "<esc>#{text}</esc>"
94
101
  end
95
102
 
103
+ # Strip any tag not in ALLOWED_INLINE_TAGS, in both literal (<tag>) and
104
+ # entity-encoded (&lt;tag&gt;) forms. Used to defend Liquid template
105
+ # output against embedded structural markup (most commonly <title>) in
106
+ # bibliographic text fields, where relaton-bib may surface either form
107
+ # depending on lutaml-model serialisation behaviour.
108
+ #
109
+ # Authors embed inline markup either literally (<em>foo</em>) or
110
+ # entity-encoded (&lt;em&gt;foo&lt;/em&gt;); both are intended as
111
+ # markup, and downstream template rendering decodes entities anyway
112
+ # (see HTMLEntities.decode in template.rb), so we normalise the
113
+ # encoded form to literal up front and let a single Nokogiri-fragment
114
+ # walk handle both. Elements whose name is in the allow-list are
115
+ # preserved verbatim with their entire subtree, so wrappers that
116
+ # legitimately carry block content (notably <fn><p>…</p></fn>)
117
+ # round-trip intact rather than being shredded one tag at a time.
118
+ # Disallowed elements are unwrapped (tag dropped, children kept),
119
+ # recursing first so allowed wrappers nested inside disallowed
120
+ # wrappers still survive. Nokogiri re-escapes any genuine `<` left in
121
+ # text positions on serialisation, so plain prose like "5 < 10" is
122
+ # preserved correctly.
123
+ def sanitise_inline_markup(str)
124
+ blank?(str) and return str
125
+ normalised = str.gsub("&lt;", "<").gsub("&gt;", ">")
126
+ frag = Nokogiri::XML.fragment(normalised)
127
+ unwrap_disallowed(frag)
128
+ save_opts = Nokogiri::XML::Node::SaveOptions::AS_XML |
129
+ Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
130
+ frag.to_xml(encoding: "UTF-8", save_with: save_opts)
131
+ end
132
+
133
+ def unwrap_disallowed(node)
134
+ node.children.to_a.each do |child|
135
+ next unless child.element?
136
+ next if ALLOWED_INLINE_TAGS.include?(child.name)
137
+
138
+ unwrap_disallowed(child)
139
+ child.replace(child.children)
140
+ end
141
+ end
142
+
96
143
  def wrap_in_esc(obj)
97
144
  case obj
98
145
  when String then esc(obj)
@@ -4,15 +4,12 @@ module Relaton
4
4
  def content(node)
5
5
  node.nil? and return node
6
6
  node.is_a?(String) and
7
- return node.strip.gsub("</title>", "").gsub("<title>", "")
7
+ return sanitise_inline_markup(node.strip)
8
8
  .gsub(/>\n\s*</, "><").gsub(/\n\s*/, " ")
9
9
  node.content.is_a?(Array) and return node.content.map { |x| content(x) }
10
- ret = node.content.strip
11
- .gsub("</title>", "").gsub("<title>", "")
10
+ ret = sanitise_inline_markup(node.content.strip)
12
11
  # safeguard against indented XML
13
12
  ret.gsub(/>\n\s*</, "><").gsub(/\n\s*/, " ")
14
- # node.children.map { |n| n.text? ? n.content : n.to_xml }.join
15
- # node.text? ? node.content.strip : node.to_xml.strip
16
13
  end
17
14
 
18
15
  def extract_orgname(org)
@@ -1,5 +1,5 @@
1
1
  module Relaton
2
2
  module Render
3
- VERSION = "1.2.0".freeze
3
+ VERSION = "1.2.2".freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-render
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-05-11 00:00:00.000000000 Z
11
+ date: 2026-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler