Class: StringMaster

Inherits:
Object
  • Object
show all
Includes:
ActionView::Helpers, ERB::Util
Defined in:
lib/string_master/string_master.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(string) {|_self| ... } ⇒ StringMaster

Returns a new instance of StringMaster.

Yields:

  • (_self)

Yield Parameters:

  • _self (StringMaster)

    the object that the method was called on



12
13
14
15
16
# File 'lib/string_master/string_master.rb', line 12

def initialize(string)
  @initial_string  = String.new(string.html_safe)
  @modified_string = String.new(string.html_safe)
  yield(self) if block_given?
end

Instance Attribute Details

#modified_stringObject (readonly) Also known as: string

Returns the value of attribute modified_string.



9
10
11
# File 'lib/string_master/string_master.rb', line 9

def modified_string
  @modified_string
end

Instance Method Details

#break_long_words(length = 75, break_char = " ", &block) ⇒ Object

Breaks words that are longer than ‘length’



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/string_master/string_master.rb', line 84

def break_long_words(length=75, break_char=" ", &block)
  @modified_string.gsub!(/https?:\/\/\S+|<a [^>]+>|<img [^>]+>|([^\s^\n^\^^\A^\t^\r<]{#{length},}?)|<\/a>/) do |s|
    if $1
      ns = block_given? ? yield($1) : $1
      last_pos, result_string = 0, ''
        while string = ns[last_pos..(last_pos + length)]
        result_string += string + break_char
        last_pos += (length + 1)
      end
      result_string
    else
      s
    end
  end
  self
end

#close_tagsObject

Closes all unclosed tags that need to be closed (i.e. skips <img>,
etc.)



19
20
21
22
23
24
25
26
27
28
29
# File 'lib/string_master/string_master.rb', line 19

def close_tags
  text = @modified_string

  open_tags = []
  text.scan(/<([a-zA-Z0-9]+?)(\s[^>]*)?>/).each { |t| open_tags.unshift(t[0]) }
  text.scan(/<\/\s*?([a-zA-Z0-9]+)\s*?>/).each  { |t| open_tags.slice!(open_tags.index(t[0])) unless open_tags.index(t[0]).nil? }
  open_tags.each { |t| text += "</#{t}>" unless %w(img br hr).include?(t.to_s) }

  @modified_string = text
  return self
end

#cut(length, cut_at, options = {}) ⇒ Object

Cuts a string starting at ‘cut_at’ if the string is longer than ‘length’. Appends characters (if specified in :append) to the end of the cut string.



103
104
105
106
107
# File 'lib/string_master/string_master.rb', line 103

def cut(length, cut_at, options = {})
  append = options[:append] || ''
  @modified_string.size > (length) ? @modified_string = @modified_string.mb_chars[0...cut_at] + append : @modified_message
  self
end

#html_escape(options = {}) ⇒ Object

escapes all tags except the ones, that are listed in :except option



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/string_master/string_master.rb', line 33

def html_escape(options={})
  except = options[:except] || %w()
  close_tags
  @modified_string.gsub!(/<\/?(.*?)(\s.*?)?\/?>/) do |tag|
    if except.include?($1)
      # sanitize attributes
      tag.gsub(/\s(.+?)=('|").*?\2(?=.*?>)/) do |a|
        ["href", "src", "lang"].include?($1) ? a : ""
      end
    else
      h(tag)
    end
  end
  # Convert all unclosed left tag brackets (<) into &lt;
  @modified_string.gsub!(/<+([^>]*)\Z/, '&lt;\1')
  # Convert all unopened right tag brackets (>) into &gt;
  @modified_string.gsub!(/\A([^<]*)>+/, '\1&gt;')
  self
end

#newlines_to_brObject



109
110
111
112
# File 'lib/string_master/string_master.rb', line 109

def newlines_to_br
  @modified_string.gsub!("\n", "<br/>")
  self
end

#preserve_whitespace_within(tag) ⇒ Object

Preserves whitespace within a given tag. Each occurence of 2 or more spaces is transformed into a &nbsp; entities.



164
165
166
167
168
169
# File 'lib/string_master/string_master.rb', line 164

def preserve_whitespace_within(tag)
  @modified_string.gsub!(/<#{tag}>(.|\n)+?<\/#{tag}>/) do |match|
    match.gsub(/( )( )+/) { |m| "&nbsp;"*m.length }
  end
  self
end

#to_sObject



182
183
184
# File 'lib/string_master/string_master.rb', line 182

def to_s
  modified_string.html_safe
end

#urls_to_images(options = {}) ⇒ Object

Creates <img> tags for all urls that look like images.



54
55
56
57
58
59
60
61
62
# File 'lib/string_master/string_master.rb', line 54

def urls_to_images(options = {})
  wrap_with    = options[:wrap_with]    || ['','']
  html_options = options[:html_options] || ''
  @modified_string.gsub!(
    /(\s|^|\A|\n|\t|\r)((http|https):\/\/.*?\.(jpg|jpeg|png|gif|JPG|JPEG|PNG|GIF))([,.])?(\s|$|\n|\Z|\t|\r)/,
    "#{wrap_with[0]}<img src=\"\\2\" alt=\"\" #{html_options}/>\\6#{wrap_with[1]}"
  )
  self
end

Creates <a> tags for all urls. IMPORTANT: make sure you’ve used #urls_to_images method first if you wanted all images urls to become <img> tags.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/string_master/string_master.rb', line 67

def urls_to_links(options = {})
  wrap_with = options[:wrap_with] || ['','']
  html_options = options[:html_options] || ''

  # ascii_only option - show URLs with warning about contain non-latin characters
  if options[:ascii_only]
    validate_url_contains_ascii(@modified_string, html_options, wrap_with)
  else
    @modified_string.gsub!(
        /(\s|^|\A|\n|\t|\r)((http|https):\/\/.*?)([,.])?(\s|$|\n|\Z|\t|\r|<)/,
        '\1<a href="\2" ' + html_options + '>\2</a>\4\5'
    )
  end
  self
end

#wrap_backticks_code(opening_tag = "<code>", closing_tag = "</code>") ⇒ Object

Same as wrap_inline_code, but spans across multiplelines



177
178
179
180
# File 'lib/string_master/string_master.rb', line 177

def wrap_backticks_code(opening_tag="<code>", closing_tag="</code>")
  @modified_string.gsub!(/`(.+?)`/m, opening_tag + '\1' + closing_tag)
  self
end

#wrap_codeObject

Finds all lines that start with 4 spaces and wraps them into <code> tags. It also transforms each occurence of 2 or more spaces into an &nbsp; entity, which is available as a standalone method #preserve_whitespace



157
158
159
160
# File 'lib/string_master/string_master.rb', line 157

def wrap_code
  wrap_lines("code", /\A\s{4}/, remove_newlines: true)
  preserve_whitespace_within("code") # already returns `self`
end

#wrap_inline_code(opening_tag = "<span class=\"inlineCode\">", closing_tag = "</span>") ⇒ Object



171
172
173
174
# File 'lib/string_master/string_master.rb', line 171

def wrap_inline_code(opening_tag="<span class=\"inlineCode\">", closing_tag="</span>")
  @modified_string.gsub!(/`(.+?)`/m, opening_tag + '\1' + closing_tag)
  self
end

#wrap_lines(tag, regexp, options = {remove_newlines: false}) ⇒ Object

Finds lines of text that satisfy a ‘regexp’ and wraps them into an opening and closing ‘tag’. Best example of usage is #wrap_code.

Also receives an option :remove_newlines (default is false) which removes n around the tag that wraps the lines of text. Useful if you’re using this method with #newlines_to_br to avoid extra space that may or may not be in the user’s input.



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
# File 'lib/string_master/string_master.rb', line 121

def wrap_lines(tag, regexp, options={remove_newlines: false})
  code_tag = nil; result = ""
  @modified_string.each_line do |line|
    if line =~ regexp
      unless code_tag == :opened
        result.chomp! if options[:remove_newlines]
        result += "<#{tag}>"
        code_tag = :opened
      end
      result += line.sub(regexp, '')
    else
      if code_tag == :opened
        code_tag = :closed
        result.chomp!
        result += "</#{tag}>"
      elsif code_tag == :closed
        code_tag = nil
        result.chomp! if options[:remove_newlines]
      end
      result += line
    end
  end

  # Make sure there's always a closing tag
  if code_tag == :opened
    result.chomp!
    result += "</#{tag}>\n"
  end

  @modified_string = result
  self
end