canon 0.3.2 → 0.3.3

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: b000e9e89684d66d4f037a950a2121a88717dd6c72d975648742f32b5a83fb9f
4
- data.tar.gz: c5e8b5ecfdcb8435559be3e6c940e8e8bec99202054b90fa857f9e3afd3097e2
3
+ metadata.gz: 52174949c77e8f33286b2875ac5e4052e6f5671b64e53e48a3b0b3128bb598a1
4
+ data.tar.gz: 0b2efb1c4fa7e060f6d54f1c149bd775d45fab66e09ac7bbf306f0a6142360fa
5
5
  SHA512:
6
- metadata.gz: '0804e7a2a07ff2687e363ee2bd0a1e2d00a5fe826e45ae5bd69fe26749bf2e2b1517a6fb2fcd3518e41d7d9bf6bf0b76fd8e704c288293724d27cbc3613978f4'
7
- data.tar.gz: 6d9dca5aa3c29bbde5d067ca02e2a22c4d7bee098635e0fd8b48df16fbf08102fa713608f1965d198f3ace1c064743916b57d34d7a2cc2a6b845902e1553a045
6
+ metadata.gz: 4e78d8618af59c255979bf3987a1be3e7419e009354b73ca64df75600ce8c2f1cc90aa515eb14be97149fe5426243efacda4ff42eab63b5fc8f291407baa046e
7
+ data.tar.gz: 2596286ac94921e6021590fe6f1ece71d827145743cc993f703cfca079fb91472845c67f25a3e9ad03aecd471c6cc482cd78854a5e9ce85d16bd8f0ea5643636
data/lib/canon/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Canon
4
- VERSION = "0.3.2"
4
+ VERSION = "0.3.3"
5
5
  end
@@ -228,7 +228,9 @@ inherited_namespaces: nil)
228
228
  def self.build_text_node(nokogiri_text, preserve_whitespace: false)
229
229
  content = nokogiri_text.content
230
230
 
231
- if !preserve_whitespace && content.strip.empty? && nokogiri_text.parent.is_a?(Nokogiri::XML::Element)
231
+ unless WhitespacePolicy.keep_dom_text?(content,
232
+ preserve_whitespace: preserve_whitespace,
233
+ element_parent: nokogiri_text.parent.is_a?(Nokogiri::XML::Element))
232
234
  return nil
233
235
  end
234
236
 
@@ -394,7 +396,7 @@ preserve_whitespace: false)
394
396
  # whitespace-only skip rule matches the wrapper path exactly.
395
397
  def self.build_moxml_text_from_record(record, preserve_whitespace)
396
398
  content = record[:text].to_s
397
- return nil if !preserve_whitespace && content.strip.empty?
399
+ return nil unless WhitespacePolicy.keep_dom_text?(content, preserve_whitespace: preserve_whitespace)
398
400
 
399
401
  Nodes::TextNode.new(value: content, original: content)
400
402
  end
@@ -502,7 +504,9 @@ inherited_namespaces: nil)
502
504
  def self.build_moxml_text_node(moxml_text, preserve_whitespace: false)
503
505
  content = moxml_text.content
504
506
 
505
- if !preserve_whitespace && content.strip.empty? && moxml_text.parent.is_a?(Moxml::Element)
507
+ unless WhitespacePolicy.keep_dom_text?(content,
508
+ preserve_whitespace: preserve_whitespace,
509
+ element_parent: moxml_text.parent.is_a?(Moxml::Element))
506
510
  return nil
507
511
  end
508
512
 
data/lib/canon/xml/sax.rb CHANGED
@@ -10,13 +10,16 @@ module Canon
10
10
  # API to that protocol. OCP: a new engine is a new driver plus one line
11
11
  # here; the builder never changes.
12
12
  #
13
- # Engine choice: leptris SAX outperforms Nokogiri SAX (1.10x min-of-N
14
- # on canon's builder, 53KB doc) through moxml 0.5.12's
15
- # interest-proportional callbacksBUT the batch-attribute transport
16
- # reads uninitialized memory at certain buffer offsets, corrupting the
17
- # first N attributes of an element (leptris-ruby#95). Until that is
18
- # fixed, CRuby keeps the Nokogiri driver; flipping is the one-line
19
- # change below.
13
+ # Engine choice: the leptris SAX flip is armed but blocked twice over.
14
+ # The batch-attribute corruption (leptris-ruby#95) is answered by a
15
+ # correctness-first path in leptris 1.9.36 attributes are correct,
16
+ # but that path DROPS namespace declarations from SAX events
17
+ # entirely (raw `["<root xmlns:a=.../>", []]` xmlns pairs vanish),
18
+ # blinding namespace comparison. Until xmlns reporting is restored
19
+ # (and then the fast path returns with the C fix), CRuby keeps the
20
+ # Nokogiri driver; the flip is the one-line change below. With
21
+ # leptris absent (moxml resolving nokogiri) the driver calls Nokogiri
22
+ # directly — the wrapper layer only adds overhead there.
20
23
  module Sax
21
24
  autoload :NokogiriDriver, "canon/xml/sax/nokogiri_driver"
22
25
  autoload :MoxmlDriver, "canon/xml/sax/moxml_driver"
@@ -198,22 +198,12 @@ strip_doctype: false)
198
198
  return
199
199
  end
200
200
 
201
- # Skip whitespace-only text nodes unless:
202
- # 1. preserve_whitespace is true, OR
203
- # 2. The content contains CR (from &#xD; entities) which must be preserved for C14N, OR
204
- # 3. The content contains non-ASCII whitespace (NBSP U+00A0, ideographic
205
- # space U+3000, etc.) — those are semantically meaningful content,
206
- # not pretty-print indentation, and must survive parsing so the
207
- # comparator can detect Unicode whitespace-type differences.
208
- #
209
- # Strip only when the node is pure ASCII whitespace (space, tab, CR, LF).
210
- # This lets pretty-printed fixtures work (indent nodes stripped) while
211
- # preserving NBSP-only text nodes.
212
- if !@preserve_whitespace && decoded_string.gsub(/[ \t\r\n]/,
213
- "").empty? && parent.node_type == :element && !decoded_string.include?("\r")
214
- # Only skip if parent is an element (not root)
215
- return
216
- end
201
+ # Skip whitespace-only text nodes unless preserving, per the SAX
202
+ # policy (CR-bearing content always survives for C14N;
203
+ # non-ASCII whitespace is meaningful content).
204
+ return unless WhitespacePolicy.keep_sax_text?(decoded_string,
205
+ preserve_whitespace: @preserve_whitespace,
206
+ element_parent: parent.node_type == :element)
217
207
 
218
208
  text = Nodes::TextNode.new(value: decoded_string, original: raw_string)
219
209
  parent.add_child(text)
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Canon
4
+ module Xml
5
+ # Parse-time whitespace policy: whether a character-data node
6
+ # survives conversion. One home for the keep/strip rules so the
7
+ # DOM/SAX differences are visible here instead of implied by
8
+ # copy-paste across conversion sites.
9
+ module WhitespacePolicy
10
+ module_function
11
+
12
+ # DOM conversion rule: whitespace-only text is dropped unless
13
+ # preserving. Non-ASCII whitespace (NBSP, U+3000) survives —
14
+ # String#strip only removes ASCII whitespace.
15
+ #
16
+ # NOTE: CR-only nodes are dropped on this path; the SAX rule keeps
17
+ # them (character references must survive for C14N).
18
+ def keep_dom_text?(content, preserve_whitespace:, element_parent: true)
19
+ return true if preserve_whitespace
20
+ return true unless element_parent
21
+
22
+ !content.strip.empty?
23
+ end
24
+
25
+ # SAX rule: same shape, plus CR-bearing content is always kept
26
+ # (&#xD; must survive parsing for C14N) — only runs of pure ASCII
27
+ # whitespace (space, tab, CR, LF) are dropped when not preserving.
28
+ def keep_sax_text?(content, preserve_whitespace:, element_parent: true)
29
+ return true if preserve_whitespace
30
+ return true unless element_parent
31
+ return true if content.include?("\r")
32
+
33
+ !content.gsub(/[ \t\r\n]/, "").empty?
34
+ end
35
+ end
36
+ end
37
+ end
data/lib/canon/xml.rb CHANGED
@@ -28,6 +28,7 @@ module Canon
28
28
  autoload :Sax, "canon/xml/sax"
29
29
  autoload :SaxBuilder, "canon/xml/sax_builder"
30
30
  autoload :WhitespaceNormalizer, "canon/xml/whitespace_normalizer"
31
+ autoload :WhitespacePolicy, "canon/xml/whitespace_policy"
31
32
  autoload :XmlBaseHandler, "canon/xml/xml_base_handler"
32
33
  autoload :XPathEngine, "canon/xml/xpath_engine"
33
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: canon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.3.3
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-08-28 00:00:00.000000000 Z
11
+ date: 2026-08-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: diff-lcs
@@ -401,6 +401,7 @@ files:
401
401
  - lib/canon/xml/sax/nokogiri_driver.rb
402
402
  - lib/canon/xml/sax_builder.rb
403
403
  - lib/canon/xml/whitespace_normalizer.rb
404
+ - lib/canon/xml/whitespace_policy.rb
404
405
  - lib/canon/xml/xml_base_handler.rb
405
406
  - lib/canon/xml/xpath_engine.rb
406
407
  - lib/canon/xml_backend.rb