Module: Ro::Methods

Included in:
Ro
Defined in:
lib/ro/methods.rb

Constant Summary collapse

EXPAND_ASSET_URL_STRATEGIES =

asset expansion methods | v

i[
  accurate_expand_asset_urls
  sloppy_expand_asset_urls
]
DEFAULT_IMAGE_EXTENSIONS =
i[
  webp jpg jpeg png gif tif tiff svg
]
DEFAULT_IMAGE_PATTERNS =
[
  /[.](#{ DEFAULT_IMAGE_EXTENSIONS.join('|') })$/i
]

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#loggerObject

log methods | v



110
111
112
# File 'lib/ro/methods.rb', line 110

def logger
  @logger
end

Instance Method Details

#accurate_expand_asset_urls(html, node) ⇒ Object



200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/ro/methods.rb', line 200

def accurate_expand_asset_urls(html, node)
  doc = Nokogiri::HTML.fragment(html.to_str)

  doc.traverse do |element|
    if element.respond_to?(:attributes)
      attributes = element.attributes
      expand_asset_values!(attributes) unless attributes.empty?
    end
  end

  expanded = doc.to_s.strip

  HTML.new(expanded)
end

#cast(which, arg, *args) ⇒ Object

cast methods | v



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/ro/methods.rb', line 6

def cast(which, arg, *args)
  which = which.to_s
  values = [arg, *args].join(',').scan(/[^,\s]+/)

  list_of = which.match(/^list_of_(.+)$/)
  which = list_of[1] if list_of

  cast = casts.fetch(which.to_s.to_sym)

  if list_of
    values.map { |value| cast[value] }
  else
    raise ArgumentError, "too many values in #{values.inspect}" if values.size > 1

    value = values.first
    cast[value]
  end
end

#castsObject



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/ro/methods.rb', line 25

def casts
  {
    :string        => proc { |value| String(value) },
    :int           => proc { |value| Integer(value.to_s) },
    :string_or_nil => proc { |value| String(value).empty? ? nil : String(value) },
    :url           => proc { |value| Ro.normalize_url(value) },
    :array         => proc { |value| String(value).scan(/[^,:]+/) },
    :bool          => proc { |value| String(value) !~ /^\s*(f|false|off|no|0){0,1}\s*$/ },
    :path          => proc { |value| Path.for(value) },
    :path_or_nil   => proc { |value| String(value).empty? ? nil : Path.for(value) },
    :root          => proc { |value| Root.for(value) },
    :time          => proc { |value| Time.parse(value.to_s) },
    :date          => proc { |value| Date.parse(value.to_s) },
  }
end

#debug!Object



131
132
133
134
135
136
# File 'lib/ro/methods.rb', line 131

def debug!
  Ro.logger =
    ::Logger.new(STDERR).tap do |logger|
      logger.level = ::Logger::DEBUG
    end
end

#emsg(e) ⇒ Object



150
151
152
153
154
155
156
# File 'lib/ro/methods.rb', line 150

def emsg(e)
  if e.is_a?(Exception)
    "#{ e.message } (#{ e.class.name })\n#{ Array(e.backtrace).join(10.chr) }"
  else
    e.to_s
  end
end

#error!(message, **context) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/ro/methods.rb', line 138

def error!(message, **context)
  error = Error.new(message, **context)

  begin
    raise error
  rescue Error
    backtrace = error.backtrace || []
    error.set_backtrace(backtrace[1..-1])
    raise
  end
end

#expand_asset_url_strategiesObject



181
182
183
# File 'lib/ro/methods.rb', line 181

def expand_asset_url_strategies
  @expand_asset_url_strategies ||= EXPAND_ASSET_URL_STRATEGIES.dup
end

#expand_asset_urls(html, node) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/ro/methods.rb', line 185

def expand_asset_urls(html, node)
  strategies = expand_asset_url_strategies
  error = nil

  strategies.each do |strategy|
    return send(strategy, html, node)
  rescue Object => e
    error = e
    Ro.log(:error, emsg(error))
    Ro.log(:error, "failed to expand assets via #{ strategy }")
  end

  raise error
end

#expand_asset_values(hash, node) ⇒ Object



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# File 'lib/ro/methods.rb', line 233

def expand_asset_values(hash, node)
  src = Map.for(hash)
  dst = Map.new(hash)

  return dst if src.empty?

  re = %r{\A(?:[.]/)?(assets/[^\s]+)\s*\z}

  src.depth_first_each do |key, value|
    next unless value.is_a?(String)

    if (match = re.match(value.strip))
      path = match[1].strip
      url = node.url_for(path)
      value = url
    end

    dst.set(key, value)
  end

  dst.to_hash
end

#expand_asset_values!(hash, node) ⇒ Object



256
257
258
259
260
# File 'lib/ro/methods.rb', line 256

def expand_asset_values!(hash, node)
  expand_asset_values(hash, node).each do |key, value|
    hash[key] = value
  end
end

#image_info(path) ⇒ Object



283
284
285
286
287
# File 'lib/ro/methods.rb', line 283

def image_info(path)
  is = ImageSize.path(path)
  format, width, height = is.format.to_s, is.width, is.height
  {format:, width:, height:}
end

#image_patternObject



275
276
277
# File 'lib/ro/methods.rb', line 275

def image_pattern
  Regexp.union(Ro.image_patterns)
end

#image_patternsObject



271
272
273
# File 'lib/ro/methods.rb', line 271

def image_patterns
  @image_patterns ||= DEFAULT_IMAGE_PATTERNS.dup
end

#is_image?(path) ⇒ Boolean

Returns:

  • (Boolean)


279
280
281
# File 'lib/ro/methods.rb', line 279

def is_image?(path)
  !!(URI.parse(path.to_s).path =~ Ro.image_pattern)
end

#log(*args, &block) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
# File 'lib/ro/methods.rb', line 112

def log(*args, &block)
  level = nil

  level = if args.size == 0 || args.size == 1
            :info
          else
            args.shift.to_s.to_sym
          end

  @logger && @logger.send(level, *args, &block)
end

#log!Object



124
125
126
127
128
129
# File 'lib/ro/methods.rb', line 124

def log!
  Ro.logger =
    ::Logger.new(STDERR).tap do |logger|
      logger.level = ::Logger::INFO
    end
end

#mapify(pod) ⇒ Object



41
42
43
# File 'lib/ro/methods.rb', line 41

def mapify(pod)
  Map.for(:pod => pod)[:pod]
end

#normalize_url(url) ⇒ Object



101
102
103
104
105
# File 'lib/ro/methods.rb', line 101

def normalize_url(url)
  uri = URI.parse(url.to_s).normalize
  uri.path = Path.for(uri.path).absolute
  uri.to_s
end

#pod(object) ⇒ Object



45
46
47
# File 'lib/ro/methods.rb', line 45

def pod(object)
  JSON.parse(object.to_json)
end

#query_string_for(hash, options = {}) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ro/methods.rb', line 80

def query_string_for(hash, options = {})
  options = Map.for(options)
  escape = options.has_key?(:escape) ? options[:escape] : true
  pairs = []
  esc = escape ? proc { |v| CGI.escape(v.to_s) } : proc { |v| v.to_s }
  hash.each do |key, values|
    key = key.to_s
    values = [values].flatten
    values.each do |value|
      value = value.to_s
      pairs << if value.empty?
                 [esc[key]]
               else
                 [esc[key], esc[value]].join('=')
               end
    end
  end
  pairs.replace(pairs.sort_by { |pair| pair.size })
  pairs.join('&')
end

#render(path, context = nil) ⇒ Object



165
166
167
# File 'lib/ro/methods.rb', line 165

def render(path, context = nil)
  Template.render(path, context:)
end

#render_src(path, context = nil) ⇒ Object



169
170
171
# File 'lib/ro/methods.rb', line 169

def render_src(path, context = nil)
  Template.render_src(path, context:)
end

#sloppy_expand_asset_urls(html, node) ⇒ Object



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/ro/methods.rb', line 215

def sloppy_expand_asset_urls(html, node)
  re = %r`\s*=\s*['"](?:[.]/)?(assets/[^'"\s]+)['"]`

  expanded =
    html.to_str.gsub(re) do |match|
      path = match[%r`assets/[^'"\s]+`]

      if node.path_for(path).exist?
        url = node.url_for(path)
        "='#{url}'"
      else
        match
      end
    end

  HTML.new(expanded)
end

#template(method = :tap, *args, &block) ⇒ Object

template methods | v



161
162
163
# File 'lib/ro/methods.rb', line 161

def template(method = :tap, *args, &block)
  Template.send(method, *args, &(block || proc {}))
end

#url_for(path, *args) ⇒ Object

url methods | v



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
# File 'lib/ro/methods.rb', line 52

def url_for(path, *args)
  options = Map.extract_options!(args)

  base = (options.delete(:base) || options.delete(:url))

  path = Path.for(path, *args)

  base ||= (
    if Ro.is_image?(path)
      Ro.config.img_url
    else
      Ro.config.url
    end
  )

  fragment = options.delete(:fragment)
  query = options.delete(:query) || options

  uri = URI.parse(base.to_s)
  uri.path = Path.for(uri.path, path).absolute
  uri.path = '' if uri.path == '/'

  uri.query = query_string_for(query) unless query.empty?
  uri.fragment = fragment unless fragment.nil?

  uri.to_s
end

#uuidObject



289
290
291
# File 'lib/ro/methods.rb', line 289

def uuid
  SecureRandom.uuid_v7.to_s
end