Class: SaxPrinter

Inherits:
Nokogiri::XML::SAX::Document
  • Object
show all
Defined in:
lib/sax/sax_printer.rb

Constant Summary collapse

CCS =
{
  amp: {named: '&', hex: '&'},
  lt: {named: '<', hex: '<'},
  gt: {named: '>', hex: '>'},
}
XMLDEC_ATTRS =
%w(version encoding standalone)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ SaxPrinter

Returns a new instance of SaxPrinter.



11
12
13
# File 'lib/sax/sax_printer.rb', line 11

def initialize(options)
  set_options_as_ivars(options)
end

Instance Attribute Details

#instructionsObject

Returns the value of attribute instructions.



2
3
4
# File 'lib/sax/sax_printer.rb', line 2

def instructions
  @instructions
end

#prettyObject

Returns the value of attribute pretty.



2
3
4
# File 'lib/sax/sax_printer.rb', line 2

def pretty
  @pretty
end

Instance Method Details

#add_opening_tag(name, attrs) ⇒ Object



126
127
128
129
# File 'lib/sax/sax_printer.rb', line 126

def add_opening_tag(name, attrs)
  tag = attrs.empty? ? "<#{name}>" : tag_with_attrs(name, attrs)
  pretty << tag
end

#below_block?Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/sax/sax_printer.rb', line 161

def below_block?
  in_inline? or in_compact?
end

#block?(name) ⇒ Boolean

Returns:

  • (Boolean)


61
62
63
# File 'lib/sax/sax_printer.rb', line 61

def block?(name)
  @block.include?(name)
end

#characters(string) ⇒ Object



139
140
141
142
143
144
145
146
147
# File 'lib/sax/sax_printer.rb', line 139

def characters(string)
  return false if ws_only_in_block?(string)
  handle_whitespace(string)
  unless string.empty?
    @open_tag = nil
    sanitize(string)
    pretty << string
  end
end

#comment(string) ⇒ Object



170
171
172
173
# File 'lib/sax/sax_printer.rb', line 170

def comment(string)
  pretty << "<!--#{string}-->"
  @open_tag = nil
end

#compact?(name) ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
# File 'lib/sax/sax_printer.rb', line 65

def compact?(name)
  @compact.include?(name)
end

#end_documentObject



136
137
# File 'lib/sax/sax_printer.rb', line 136

def end_document
end

#end_element(name) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
# File 'lib/sax/sax_printer.rb', line 106

def end_element(name)
  if self_closing?(name)
    pretty[-1] = '/>'
  else
    space_before_close(name)
    pretty << "</#{name}>"
  end
  @depth -= 1
  @open_tag = nil
  @opens.pop
end

#error(string) ⇒ Object



181
182
183
# File 'lib/sax/sax_printer.rb', line 181

def error(string)
  fail Nokogiri::XML::SyntaxError.new(string)
end

#handle_whitespace(string) ⇒ Object



165
166
167
168
# File 'lib/sax/sax_printer.rb', line 165

def handle_whitespace(string)
  string.gsub!(/[\r\n]/, '') unless keep_linebreaks?
  string.gsub!(/^\s+|\s+$/, '') unless whitespace?
end

#in_block?Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/sax/sax_printer.rb', line 81

def in_block?
  block?(@opens[-1])
end

#in_compact?Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/sax/sax_printer.rb', line 77

def in_compact?
  compact?(@opens[-1])
end

#in_inline?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/sax/sax_printer.rb', line 73

def in_inline?
  inline?(@opens[-1])
end

#increment_spaceObject



102
103
104
# File 'lib/sax/sax_printer.rb', line 102

def increment_space
  pretty << ws_adder
end

#inline?(name) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
# File 'lib/sax/sax_printer.rb', line 69

def inline?(name)
  @inline.include?(name)
end

#keep_linebreaks?Boolean

Returns:

  • (Boolean)


157
158
159
# File 'lib/sax/sax_printer.rb', line 157

def keep_linebreaks?
  @preserve_linebreaks.include?(@open_tag)
end

#processing_instruction(name, content) ⇒ Object



32
33
34
# File 'lib/sax/sax_printer.rb', line 32

def processing_instruction(name, content)
  instructions << "<?#{name} #{content}?>"
end

#sanitize(string) ⇒ Object



175
176
177
178
179
# File 'lib/sax/sax_printer.rb', line 175

def sanitize(string)
  string.gsub!(/&/, CCS[:amp][@ccs])
  string.gsub!(/</, CCS[:lt][@ccs])
  string.gsub!(/>/, CCS[:gt][@ccs])
end

#self_closing?(name) ⇒ Boolean

Returns:

  • (Boolean)


118
119
120
# File 'lib/sax/sax_printer.rb', line 118

def self_closing?(name)
  @open_tag == name and !@close_tags.include?(name)
end

#set_control_vars(options) ⇒ Object



47
48
49
50
51
52
53
54
# File 'lib/sax/sax_printer.rb', line 47

def set_control_vars(options)
  @whitespace = options.include?(:preserve_whitespace) ?  options[:preserve_whitespace] : true
  @close_tags = options[:close_tags] ? Set.new(options[:close_tags]) : []
  @preserve_linebreaks = options[:preserve_linebreaks] ? Set.new(options[:preserve_linebreaks]) : []
  @ccs = options[:control_chars] || :named
  @use_ns = options[:use_namespaces]
  @tab = options[:tab] || '  '
end

#set_element_types(options) ⇒ Object



41
42
43
44
45
# File 'lib/sax/sax_printer.rb', line 41

def set_element_types(options)
  @block = Set.new(options[:block])
  @compact = Set.new(options[:compact])
  @inline = Set.new(options[:inline])
end

#set_options_as_ivars(options) ⇒ Object



56
57
58
59
# File 'lib/sax/sax_printer.rb', line 56

def set_options_as_ivars(options)
  set_element_types(options)
  set_control_vars(options)
end

#space_before_close(name) ⇒ Object



122
123
124
# File 'lib/sax/sax_printer.rb', line 122

def space_before_close(name)
  increment_space if block?(name) and @depth != 0
end

#space_before_open(name) ⇒ Object



98
99
100
# File 'lib/sax/sax_printer.rb', line 98

def space_before_open(name)
  increment_space if block?(name) or compact?(name)
end

#start_documentObject



36
37
38
39
# File 'lib/sax/sax_printer.rb', line 36

def start_document
  @depth = 0
  @opens = []
end

#start_element(name, attributes) ⇒ Object



90
91
92
93
94
95
96
# File 'lib/sax/sax_printer.rb', line 90

def start_element(name, attributes)
  @depth += 1
  space_before_open(name)
  add_opening_tag(name, attributes)
  @opens << name
  @open_tag = name
end

#start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = []) ⇒ Object



15
16
17
18
19
20
21
# File 'lib/sax/sax_printer.rb', line 15

def start_element_namespace(name, attrs = [], prefix = nil, uri = nil, ns = [])
  if @use_ns
    super
  else
    start_element(name, attrs.map { |a| [a.localname, a.value] })
  end
end

#tag_with_attrs(name, attrs) ⇒ Object



131
132
133
134
# File 'lib/sax/sax_printer.rb', line 131

def tag_with_attrs(name, attrs)
  attr_str = attrs.map { |n, v| "#{n}=\"#{v}\""}.join(' ')
  "<#{name} #{attr_str}>"
end

#whitespace?Boolean

Returns:

  • (Boolean)


153
154
155
# File 'lib/sax/sax_printer.rb', line 153

def whitespace?
  @whitespace and below_block?
end

#ws_adderObject



85
86
87
88
# File 'lib/sax/sax_printer.rb', line 85

def ws_adder
  ws = @tab * (@depth - 1)
  pretty.empty? ? ws : "\n#{ws}"
end

#ws_only_in_block?(string) ⇒ Boolean

Returns:

  • (Boolean)


149
150
151
# File 'lib/sax/sax_printer.rb', line 149

def ws_only_in_block?(string)
  string[/\A\s*\Z/] and in_block?
end

#xmldec_attrs(args) ⇒ Object



23
24
25
# File 'lib/sax/sax_printer.rb', line 23

def xmldec_attrs(args)
  XMLDEC_ATTRS.each_with_index.to_a.map { |t, i| " #{t}=\"#{args[i]}\"" if args[i] }.compact.join
end

#xmldecl(*args) ⇒ Object



27
28
29
30
# File 'lib/sax/sax_printer.rb', line 27

def xmldecl(*args)
  opts = xmldec_attrs(args)
  instructions << "<?xml#{opts}?>"
end