Class: Card::Content

Inherits:
SimpleDelegator
  • Object
show all
Defined in:
lib/card/content.rb,
lib/card/content/chunk.rb,
lib/card/content/parser.rb

Defined Under Namespace

Modules: Chunk Classes: Parser

Constant Summary collapse

ALLOWED_TAGS =
{}
ATTR_VALUE_RE =
[/(?<=^')[^']+(?=')/, /(?<=^")[^"]+(?=")/, /\S+/].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(content, format_or_card, opts = {}) ⇒ Content

Returns a new instance of Content.



10
11
12
13
14
15
16
17
18
19
20
21
# File 'lib/card/content.rb', line 10

def initialize content, format_or_card, opts={}
  @format =
    if format_or_card.is_a?(Card)
      Format.new format_or_card, format: nil
    else
      format_or_card
    end
  @opts = opts || {}

  @chunks = Parser.new(chunk_list).parse(content, self)
  super(@chunks.any? ? @chunks : content)
end

Instance Attribute Details

#chunksObject (readonly)

Returns the value of attribute chunks.



8
9
10
# File 'lib/card/content.rb', line 8

def chunks
  @chunks
end

#formatObject (readonly)

Returns the value of attribute format.



8
9
10
# File 'lib/card/content.rb', line 8

def format
  @format
end

#optsObject (readonly)

Returns the value of attribute opts.



8
9
10
# File 'lib/card/content.rb', line 8

def opts
  @opts
end

#revisionObject (readonly)

Returns the value of attribute revision.



8
9
10
# File 'lib/card/content.rb', line 8

def revision
  @revision
end

Class Method Details

.clean!(string, tags = ALLOWED_TAGS) ⇒ Object

this has been hacked for card to allow classes if the class begins with “w-”



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/card/content.rb', line 98

def clean! string, tags=ALLOWED_TAGS
  string.gsub(%r{<(/*)(\w+)([^>]*)>}) do
    raw = $LAST_MATCH_INFO
    tag = raw[2].downcase
    if (attrs = tags[tag])
      html_attribs =
        attrs.each_with_object([tag]) do |attr, pcs|
          q, rest_value = process_attribute attr, raw[3]
          pcs << "#{attr}=#{q}#{rest_value}#{q}" unless rest_value.blank?
        end * ' '
      "<#{raw[1]}#{html_attribs}>"
    else
      ' '
    end
  end.gsub(/<\!--.*?-->/, '')
end

.find_tags(wordstring) ⇒ Object



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/card/content.rb', line 165

def find_tags wordstring
  tags = []

  # match tags with or without self closing (ie. <foo />)
  wordstring.scan(%r{\<([^\>\s/]+)[^\>]*?\>}).each do |t|
    tags.unshift(t[0])
  end
  # match tags with self closing and mark them as closed
  wordstring.scan(%r{\<([^\>\s/]+)[^\>]*?/\>}).each do |t|
    next unless (x = tags.index(t[0]))
    tags.slice!(x)
  end
  # match close tags
  wordstring.scan(%r{\</([^\>\s/]+)[^\>]*?\>}).each do |t|
    next unless (x = tags.rindex(t[0]))
    tags.slice!(x)
  end
  tags
end

.process_attribute(attr, all_attributes) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/card/content.rb', line 115

def process_attribute attr, all_attributes
  return ['"', nil] unless all_attributes =~ /\b#{attr}\s*=\s*(?=(.))/i
  q = '"'
  rest_value = $'
  (idx = %w(' ").index(Regexp.last_match(1))) &&
    (q = Regexp.last_match(1))
  re = ATTR_VALUE_RE[idx || 2]
  if (match = rest_value.match(re))
    rest_value = match[0]
    if attr == 'class'
      rest_value =
        rest_value.split(/\s+/).select { |s| s =~ /^w-/i }.join(' ')
    end
  end
  [q, rest_value]
end

.truncatewords_with_closing_tags(input, words = 25, _truncate_string = '...') ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/card/content.rb', line 140

def truncatewords_with_closing_tags input, words=25,
                                    _truncate_string='...'
  return if input.nil?
  wordlist = input.to_s.split
  l = words.to_i - 1
  l = 0 if l < 0
  wordstring = wordlist.length > l ? wordlist[0..l].join(' ') : input.to_s
  # nuke partial tags at end of snippet
  wordstring.gsub!(/(<[^\>]+)$/, '')

  tags = find_tags wordstring
  tags.each { |t| wordstring += "</#{t}>" }

  if wordlist.length > l
    wordstring += '<span class="closed-content-ellipses">...</span>'
  end

  # wordstring += '...' if wordlist.length > l
  wordstring.gsub! %r{<[/]?br[\s/]*>}, ' '
  # Also a hack -- get rid of <br>'s -- they make line view ugly.
  wordstring.gsub! %r{<[/]?p[^>]*>}, ' '
  ## Also a hack -- get rid of <br>'s -- they make line view ugly.
  wordstring
end

Instance Method Details

#cardObject



23
24
25
# File 'lib/card/content.rb', line 23

def card
  format.card
end

#chunk_listObject



27
28
29
# File 'lib/card/content.rb', line 27

def chunk_list
  @opts[:chunk_list] || @format.chunk_list
end

#clean_with_space_last!(string, tags = ALLOWED_TAGS) ⇒ Object



133
134
135
136
# File 'lib/card/content.rb', line 133

def clean_with_space_last! string, tags=ALLOWED_TAGS
  cwo = clean_without_space_last!(string, tags)
  cwo.gsub(/(?:^|\b) ((?:&nbsp;)+)/, '\1 ')
end

#each_chunkObject



44
45
46
47
48
49
50
51
52
53
54
# File 'lib/card/content.rb', line 44

def each_chunk
  return enum_for(:each_chunk) unless block_given?
  case __getobj__
  when Hash  then each_value { |v| yield v if v.is_a?(Chunk::Abstract) }
  when Array then each       { |e| yield e if e.is_a?(Chunk::Abstract) }
  when String # noop. strings are parsed in self, so no chunks in a String
  else
    Rails.logger.warn 'error self is unrecognized type' \
                      " #{self.class} #{__getobj__.class}"
  end
end

#find_chunks(chunk_type) ⇒ Object



56
57
58
# File 'lib/card/content.rb', line 56

def find_chunks chunk_type
  each_chunk.select { |chunk| chunk.is_a?(chunk_type) }
end

#inspectObject



40
41
42
# File 'lib/card/content.rb', line 40

def inspect
  "<#{__getobj__.class}:#{card}:#{self}>"
end

#process_each_chunk(&block) ⇒ Object



60
61
62
63
# File 'lib/card/content.rb', line 60

def process_each_chunk &block
  each_chunk { |chunk| chunk.process_chunk(&block) }
  self
end

#to_sObject



31
32
33
34
35
36
37
38
# File 'lib/card/content.rb', line 31

def to_s
  case __getobj__
  when Array    then map(&:to_s) * ''
  when String   then __getobj__
  when NilClass then '' # raise "Nil Card::Content"
  else               __getobj__.to_s
  end
end