Module: MarkupTransform

Included in:
Variable
Defined in:
app/models/markup_transform.rb

Instance Method Summary collapse

Instance Method Details

#block_element?(node) ⇒ Boolean

Returns:

  • (Boolean)


157
158
159
# File 'app/models/markup_transform.rb', line 157

def block_element?(node)
  node && ['more', 'b1', 'b2', 'b3', 'li', 'i1', 'i2', 'i3', 'code', 'topcode', 'bottomcode'].include?(node.name)
end

#default_text_handler ⇒ Object



27
28
29
# File 'app/models/markup_transform.rb', line 27

def default_text_handler
  Proc.new { |item| parse_text(item)}
end

#ensure_p_closed ⇒ Object



212
213
214
215
216
217
218
# File 'app/models/markup_transform.rb', line 212

def ensure_p_closed
  if @markup_p_open
    @markup_p_open = false
    return '</p>'
  end
  ''
end

#format_in_paragraph(e) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'app/models/markup_transform.rb', line 112

def format_in_paragraph(e)
  text = e.to_s
  # puts "parsing text in paragraph '#{e.to_s}'"

  ## Remove leading double lines if the preceding tag was a block element
  previous_node = e.previous
  if block_element?(previous_node)
    text.gsub!(/\A\n+/m, '')
  end

  next_node = e.next

  # Remove leading newline if we are in a <more> tag
  text.gsub!(/\A\n/, '') if e.parent.name == 'more'

  # Remove trailing double line
  if block_element?(next_node)
    text.gsub!(/\n+\z/m, '')
  end

  start_tag = '<p class="paragraph">' # starting tag
  text = text.to_s.dup
  if text.gsub!(/\n\n+/, "</p>\n\n#{start_tag}")  # 2+ newline  -> paragraph
    @markup_p_open = true
  end

  text.gsub!(/((\A|[^\n])\n)((?=[^\n]|\z))/, '\1<br />')  # 1 newline   -> br

  #prev_node was a block node (ul, div, then start this <p>)
  if block_element?(previous_node) && !text.empty?
    text.insert 0, start_tag
    # valid because we could not have closed in text before this line.  If the logic changes above,
    #  then this may need to chagne as well
    @markup_p_open = true
  end

  #next_node is a block node (ul, div, then close this <p>)
  if block_element?(next_node) && !text.empty?
    text << "</p>\n"
    @markup_p_open = false
  end

  text
end

#format_not_in_paragraph(e) ⇒ Object



165
166
167
168
169
170
171
172
173
# File 'app/models/markup_transform.rb', line 165

def format_not_in_paragraph(e)
  # puts "parsing text NOT in paragraph '#{e.to_s}'"
  # puts "parent is #{e.parent.name}"
  text = e.to_s
  text.gsub!(/\n\n+/, "<br /><br />\n\n") unless inside_ul?(e) #2+ newline -> br br
  text.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline   -> br
  #text = "\n<br />" if text == "\n" # nothing but a single newline -> br
  text
end

#inside_ul?(node) ⇒ Boolean

Returns:

  • (Boolean)


161
162
163
# File 'app/models/markup_transform.rb', line 161

def inside_ul?(node)
  node && node.parent && node.parent.name == 'ul'
end


175
176
177
178
179
180
181
182
# File 'app/models/markup_transform.rb', line 175

def link_target (anchors, vars)
  unless anchors.nil?
    vars_to_anchor = anchors.downcase == "all" ? vars.split(/\s/) : anchors.split(/\s/)
    return vars_to_anchor.map{|v| "<a name=\"#{v}\"></a>"}.join('')
  else
    return ""
  end
end

#load_file(id) ⇒ Object



184
185
186
187
188
189
190
# File 'app/models/markup_transform.rb', line 184

def load_file(id)
  raise "Unused! Use load_html_fragment instead."
  return '' if Link.hash.empty?
  dir = IPUMS::project.config[:included_html_dir]
  path = dir + Link.hash[id]
  File.open(path).read
end

#load_html_fragment(link_id) ⇒ Object

Should replace load_file()



198
199
200
201
202
203
204
205
206
# File 'app/models/markup_transform.rb', line 198

def load_html_fragment(link_id)
  name = Link.hash[link_id]
  fragment = InsertHtmlFragment.find_by_name(name)
  if fragment.nil?
    raise "Could not find HTML fragment link ID #{link_id} with name #{name}."
  end

  fragment.content
end

#load_image(id) ⇒ Object



192
193
194
195
# File 'app/models/markup_transform.rb', line 192

def load_image(id)
  href = Link.hash ? Link.hash[id] : ''
  "<img src=\"#{href}\"/>"
end


208
209
210
# File 'app/models/markup_transform.rb', line 208

def load_link(id, text)
  "<a href=\"#{Link.hash.empty? ? '' : Link.hash[id]}\">#{text}</a>"
end

#more(e, text_handler) ⇒ Object



225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'app/models/markup_transform.rb', line 225

def more(e, text_handler)
  @show_hider_count += 1
  p_was_open = @markup_p_open
  result = "<a id=\"toggler-#{@show_hider_count}\" title=\"Toggle visibility\" class=\"show-hide-toggler\">&nbsp;</a>"
  result += ensure_p_closed
  result += "<div id=\"toggler-#{@show_hider_count}-target\">"
  result += open_p
  result += parse_node(e, text_handler)
  result += ensure_p_closed
  result += "</div><p></p>"
  if p_was_open
    result += open_p
  end
  result
end

#open_p ⇒ Object



220
221
222
223
# File 'app/models/markup_transform.rb', line 220

def open_p
  @markup_p_open = true
  '<p>'
end

#parse_list(node) ⇒ Object



84
85
86
87
88
89
90
91
92
# File 'app/models/markup_transform.rb', line 84

def parse_list (node)
  out = node.children.map do |e|
#    puts "Children are: #{e.inspect}"
    # Split lines into li's
     (e.text? ? parse_list_text(e) : parse_non_text_node(e, Proc.new {|item| parse_list_text(item) }))
  end.join
  out.gsub!(/\A\s*/, '')
  "<li>" + out +"</li>"
end

#parse_list_text(node) ⇒ Object



94
95
96
97
98
99
100
101
# File 'app/models/markup_transform.rb', line 94

def parse_list_text (node)
  str = node.to_s
  str.gsub!(/\A\s*\z/, '') ## remove lines that are entirely whitespace
  str.gsub!(/\A(\s)?\s*/,'\1') ## Remove duplicate whitespace at the beginning
  str.gsub!(/\n\n+\s*/, "</li>\n\n<li>") ## break 2+ new lines into separate bullets, remove any extra whitespace
  #puts "Ret is #{str.inspect}"
  str
end

#parse_node(node, text_handler) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'app/models/markup_transform.rb', line 31

def parse_node (node, text_handler)
  if node.children.nil?
    Rails.logger.warn "Node #{node.name} has no children"
    return ''
  end

  # svar isn't a formatting tag but includes an opening '\n'; get rid of it
  node.inner_html = node.inner_html.sub(/\n/, '') if node.name == 'svar'

  node.children.map do |e|
    e.text? ? text_handler.call(e) : parse_non_text_node(e, text_handler)
  end.join
end

#parse_non_text_node(e, text_handler) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'app/models/markup_transform.rb', line 45

def parse_non_text_node(e, text_handler)
  case e.name
    when 'insert_html'
      load_html_fragment(e[:id])
    when 'sample'
      ''
    when 'survey_section'
      ''
    when 'i1', 'i2', 'i3', 'title' # block styles
      "<div class=\"#{e.name}\">" + parse_node(e, text_handler) + "</div>"
    when 'b1', 'b2', 'b3' # list styles
      "<ul class=\"#{e.name}\">\n" + parse_list(e) + "\n</ul>"
    when 'em', 'pg', 'ital', 'lang', 'h1', 'h2', 'h3'  # inline styles
      "<span class=\"#{e.name}\">" + parse_node(e, text_handler) + "</span>"
    when 'insert_image'
      load_image(e[:id])
    when 'link'
      load_link(e[:id], e.inner_html)
    when 'svar', 'invar'
      link_target(e[:a],e[:v]) + parse_node(e, text_handler)
    when 'crvar'
      #"<a href=\"#{variable_path(e.inner_html.strip)}\">#{e.inner_html.strip}</a>"
      variable_path(e.inner_html.strip)
    when 'crcode'
      "<a href=\"#{codes_variable_path(e.inner_html.strip)}\">#{e.inner_html.strip}</a>"
    when 'code'
      "<div class=\"code\">Codes</div>"
    when 'topcode'
      "<div class=\"topcode\">Top codes:</div>"
    when 'bottomcode'
      "<div class=\"bottomcode\">Bottom codes:</div>"
    when 'more'
      more(e, text_handler)
    else
      attrs = e.attributes.map { |name, attr| name + (attr.value.empty? ? "" : "=\"#{attr.value}\"")}.join(" ")
      "<#{e.name} #{attrs}>" + parse_node(e, text_handler)  + "</#{e.name}>"
  end
end

#parse_text(e) ⇒ Object



103
104
105
106
107
108
109
110
# File 'app/models/markup_transform.rb', line 103

def parse_text (e)
  ### Svar is an enclosing tag, but we're moving it's contents outside the <a> tag for display.
  if e.parent.nil? || e.parent.xml? || e.parent.fragment? || e.parent.name == 'svar' || e.parent.name == 'more'
    format_in_paragraph e
  else
    format_not_in_paragraph e  ### This is already inside some kind of html (e.g. <div> or <ul>.)  We don't want paragraphs.
  end
end

#transform_markup(node) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'app/models/markup_transform.rb', line 5

def transform_markup(node)

  # special functions
  # PAGE_NUMBER_TAG = "pg";
  # FOOTNOTE_TAG = "fn";
  # FOOTNOTE_REF_TAG = "fnarg";
  # COMMENT = "comment";

  #insert_image is usa only.
  #insert_html example: ipumsi educkg
  #crvar is common in ihis

  # Whether a paragraph tag has been opened
  @markup_p_open = false
  @show_hider_count = 0

  return "" if node.nil? || node.empty?
  node.gsub!(/\r\n?/,"\n")
  doc = IpumsXmlParsing.build_xml_doc_from_fragment(node)
  "<p>#{parse_node(doc, default_text_handler)}</p>".html_safe
end