Class: Alula::Content::Item

Inherits:
Object
  • Object
show all
Defined in:
lib/alula/contents/item.rb

Direct Known Subclasses

Attachment, Page, Post

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}, hooks = {}) ⇒ Item

Returns a new instance of Item.



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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/alula/contents/item.rb', line 53

def initialize(opts = {}, hooks = {})
  @site = opts.delete(:site)
  @item = opts.delete(:item)
  @name = opts.delete(:name) || @item.name
  
  # Set up method overrides
  @hooks = {}
  # @hooks = hooks
  hooks.each do |name, blk|
    hook_id = blk.hash.to_s(36)
    hook_name = "#{name}_#{hook_id}"
    prev_hook_name = "#{name}_without_#{hook_id}"
    (class << self; self; end).send(:define_method, hook_name) do |*args|
      previous_hook = self.method(prev_hook_name)
      instance_exec(previous_hook, *args, &blk)
    end
    (class << self; self; end).send(:alias_method, prev_hook_name, name)
    (class << self; self; end).send(:alias_method, name, hook_name)
  end
  # hooks.each do |name, impl|
  #   self.class.send(:define_method, name, &impl)
  # end
  
  @url = {}
  @path = {}
  @ids = {}
  @navigation = {}
  @substitutes = {}
  @sidebar = {}
  
  # Initialize content variables
  flush
  
  # Initialize metadata
  @metadata = Metadata.new({
    # Defaults
    date: Time.new(0),
    pin: 500,       # Default sorting pin
    sidebar: true,  # Display item in sidebar (if page etc)
    layout: 'default',
    view: (self.class.to_s == "Alula::Content::Page" ? "page" : "post"),
    
    # Utilities
    base_locale: @site.config.locale,
    environment: @site.config.environment,
    
    last_modified: _last_modified,
    generator: nil,
  }.merge(opts))
  
  if /^((?<date>(?:\d+-\d+-\d+))-)?(?<slug>(?:.*))(?<extension>(?:\.[^.]+))$/ =~ @name
    @metadata.date = Time.parse(date) unless date.nil? rescue @metadata.date
    @metadata.slug = slug unless slug.nil?
    @metadata.extension = extension unless extension.nil?
  end
  
  # If payload requested, read it
  read_payload if has_payload?
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args, &blk) ⇒ Object

Proxy to metadata



350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/alula/contents/item.rb', line 350

def method_missing(meth, *args, &blk)
  # Proxy to metadata
  if !meth[/=$/] and .respond_to?(meth)
    # Invalidate some attributes depending on this
    if %w{template name slug}.include?(meth[0..-2])
      var = instance_variable_get("@#{meth[0..-2]}")
      instance_variable_set("@#{meth[0..2]}", var.class.new)
    end
    args.unshift(self.current_locale || @site.config.locale) if args.empty?
    .send(meth, *args)
  else
    super
  end
end

Instance Attribute Details

#metadataObject (readonly)

Metadata, contains all informative data for item



20
21
22
# File 'lib/alula/contents/item.rb', line 20

def 
  @metadata
end

#nameObject (readonly)

Returns the value of attribute name.



22
23
24
# File 'lib/alula/contents/item.rb', line 22

def name
  @name
end

Returns the value of attribute navigation.



25
26
27
# File 'lib/alula/contents/item.rb', line 25

def navigation
  @navigation
end

#siteObject (readonly)

Returns the value of attribute site.



23
24
25
# File 'lib/alula/contents/item.rb', line 23

def site
  @site
end

Class Method Details

.has_payloadObject



27
28
29
# File 'lib/alula/contents/item.rb', line 27

def self.has_payload
  class_variable_set(:@@payload, true)
end

.has_payload?Boolean

Returns:

  • (Boolean)


31
32
33
# File 'lib/alula/contents/item.rb', line 31

def self.has_payload?
  class_variable_defined?(:@@payload) && class_variable_get(:@@payload)
end

.load(opts = {}) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/alula/contents/item.rb', line 39

def self.load(opts = {})
  # Just return nil right away if we have no item
  return nil if opts[:item].nil?
  
  # Return nothing if file is not regular file
  return nil unless opts[:item].exists?

  # If payload is required by class and file doesn't contain it, just skip it
  return nil if has_payload? && !opts[:item].has_payload?

  # All ok
  return self.new(opts)
end

Instance Method Details

#<=>(other) ⇒ Object

Sorting



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/alula/contents/item.rb', line 131

def <=>(other)
  # Sort by date
  cmp = self.date <=> other.date

  # Sort by pinning, smaller marks higher in the list
  cmp == 0 and cmp = self..pin <=> other..pin
    
  # Sort by slug name alphabetically
  cmp == 0 and cmp = self.slug <=> other.slug

  cmp
end

#body(locale = nil) ⇒ Object



237
238
239
240
241
# File 'lib/alula/contents/item.rb', line 237

def body(locale = nil)
  @body[(locale || self.current_locale || self.site.config.locale)] ||= begin
    parse_markdown(locale)
  end
end

#content(locale = nil) ⇒ Object



231
232
233
234
235
# File 'lib/alula/contents/item.rb', line 231

def content(locale = nil)
  @content[(locale || self.current_locale || self.site.config.locale)] ||= begin
    render(locale)
  end
end

#current_localeObject



223
224
225
# File 'lib/alula/contents/item.rb', line 223

def current_locale
  @@current_locale ||= nil
end

#current_locale=(newLocale) ⇒ Object



227
228
229
# File 'lib/alula/contents/item.rb', line 227

def current_locale=(newLocale)
  @@current_locale = newLocale
end

#description(locale = nil) ⇒ Object

Accessors



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/alula/contents/item.rb', line 206

def description(locale = nil)
  @description[(locale || self.current_locale || self.site.config.locale)] ||= begin
    @metadata.description(locale) || begin
      doc = Nokogiri::HTML(self.body(locale))
      words = doc.text.split(' ')
      summary = words.inject("") do |summary, word|
        if (summary + " #{word}").length < 152
          summary += "#{word} "
        else
          summary += "..." unless summary[/\.\.\.$/]
        end
        summary
      end
    end
  end
end

#exists?Boolean

Functionality, existence

Returns:

  • (Boolean)


118
119
120
# File 'lib/alula/contents/item.rb', line 118

def exists?
  @item.exists?
end

#extensionObject



122
123
124
# File 'lib/alula/contents/item.rb', line 122

def extension
  @item.extension
end

#filepathObject



126
127
128
# File 'lib/alula/contents/item.rb', line 126

def filepath
  @item.filepath
end

#flushObject

Resets all cached variables and languages etc.



336
337
338
339
340
341
# File 'lib/alula/contents/item.rb', line 336

def flush
  flush_render
  @markdown = {}
  @body = {}
  @description = {}
end

#flush_renderObject



343
344
345
346
347
# File 'lib/alula/contents/item.rb', line 343

def flush_render
  # Initialize current locale
  self.current_locale ||= nil
  @content = {}
end

#has_payload?Boolean

Returns:

  • (Boolean)


35
36
37
# File 'lib/alula/contents/item.rb', line 35

def has_payload?
  self.class.has_payload?
end

#id(locale = nil) ⇒ Object



293
294
295
296
297
298
# File 'lib/alula/contents/item.rb', line 293

def id(locale = nil)
  @ids[(locale || self.current_locale || self.site.config.locale)] ||= self.url(locale)
    .gsub(/\.\S+$/, '')
    .gsub(/[\/]/, ' ')
    .to_url
end

#inspectObject



113
114
115
# File 'lib/alula/contents/item.rb', line 113

def inspect
  "#<#{self.class.to_s} name=#{self.name}>"
end

#layoutObject

Layout engine



197
198
199
# File 'lib/alula/contents/item.rb', line 197

def layout
  @layout ||= @site.theme.layout(self..layout)
end

#markdown(locale = nil) ⇒ Object



243
244
245
246
247
# File 'lib/alula/contents/item.rb', line 243

def markdown(locale = nil)
  @markdown[(locale || self.current_locale || self.site.config.locale)] ||= begin
    parse_liquid(locale)
  end
end

#next(locale = nil) ⇒ Object



320
321
322
323
324
325
326
327
328
329
# File 'lib/alula/contents/item.rb', line 320

def next(locale = nil)
  if self.navigation
    pos = self.navigation(locale).index(self)
    if pos and pos > 0
      self.navigation(locale)[pos - 1]
    else
      nil
    end
  end
end

#path(locale = nil) ⇒ Object



300
301
302
303
304
305
306
307
# File 'lib/alula/contents/item.rb', line 300

def path(locale = nil)
  locale ||= self.current_locale || self.site.config.locale
  @path[locale] ||= begin
    path = ::File.join(CGI.unescape(self.url(locale)))
    path = ::File.join(path, "index.html") unless path[/\/$/].nil?
    path
  end
end

#previous(locale = nil) ⇒ Object



309
310
311
312
313
314
315
316
317
318
# File 'lib/alula/contents/item.rb', line 309

def previous(locale = nil)
  if self.navigation
    pos = self.navigation(locale).index(self)
    if pos and pos < (self.navigation(locale).count - 1)
      self.navigation(locale)[pos + 1]
    else
      nil
    end
  end
end

#render(locale) ⇒ Object

Renders actual content of itm using current layout This handles all locales automatically



146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/alula/contents/item.rb', line 146

def render(locale)
  @content[locale] ||= begin
    _old_locale = self.current_locale
    self.current_locale = locale
    
    # Make sure our content is parsed
    parse_liquid(locale)
    parse_markdown(locale)
    
    self.view.render(item: self, content: self.body(locale), locale: locale)
  ensure
    self.current_locale = _old_locale
  end
end


249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/alula/contents/item.rb', line 249

def sidebar(locale = nil)
  locale ||= self.current_locale || self.site.config.locale
  @sidebar[locale] ||= begin
    items = self.site.config.content.sidebar.collect do |item|
      case item
      when :pages
        self.site.content.pages
          .select{|p| p.languages.include?(locale) }
          .reject{|p| p..sidebar == false}
      when :languages
        # Get index page titles
        index_page = site.content.by_slug("index")
        if index_page
          index_page.languages
            .reject{|lang| lang == locale}
            .collect{|lang| Hashie::Mash.new({url: index_page.url(lang), title: I18n.t('language_name', locale: lang)}) }
        end
      when Hash
        item
      else
        self.site.content.by_slug(item)
      end
    end
    items.flatten.select {|i| !i.nil?}
  end
end

#substitude(template, locale = nil) ⇒ Object

Substitudes for URL



366
367
368
369
370
371
# File 'lib/alula/contents/item.rb', line 366

def substitude(template, locale = nil)
  s = self.substitutes(locale).inject(template) { |result, token|
    result.gsub(/:#{Regexp.escape token.first}/, token.last)
  }
  s.gsub(/\/{2,}/, '/')
end

#substitutes(locale = nil) ⇒ Object



373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
# File 'lib/alula/contents/item.rb', line 373

def substitutes(locale = nil)
  locale ||=  self.current_locale || self.site.config.locale
  @substitutes[locale] ||= begin
    subs = {
      "year"        => @metadata.date.strftime('%Y'),
      "month"       => @metadata.date.strftime('%m'),
      "monthname"   => @metadata.date.strftime('%B'),
      "monthabbr"   => @metadata.date.strftime('%b'),
      "day"         => @metadata.date.strftime('%d'),
      "weekday"     => @metadata.date.strftime('%A'),
      "weekdayabbr" => @metadata.date.strftime('%a'),
      "locale"      => (@site.config.locale == locale && @site.config.hides_base_locale ? "" : locale),
      "name"        => CGI.escape(name).gsub('%2F', '/'),
      "slug"        => CGI.escape(@metadata.slug(locale)).gsub('%2F', '/'),
      "title"       => @metadata.title(locale).to_url,
    }
    if self..generator
      subs.merge!(self..generator.substitutes(locale, self))
    end
    subs
  end
end

#url(locale = nil) ⇒ Object



276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'lib/alula/contents/item.rb', line 276

def url(locale = nil)
  locale ||= self.current_locale || self.site.config.locale
  @url[locale] ||= begin
    url = if @metadata.permalink(locale)
      @metadata.permalink(locale)
    else
      template = @metadata.template || (self.class.to_s == "Alula::Content::Page" ? @site.config.pagelinks : @site.config.permalinks)
      substitude(template, locale)
    end
    # Add .html only if we don't have extension already
    if ::File.extname(url).empty?
      url += ".html" unless url[/\/$/] and ::File.extname(url).empty?
    end
    url
  end
end

#viewObject



201
202
203
# File 'lib/alula/contents/item.rb', line 201

def view
  @view ||= @site.theme.view(self..view)
end

#writeObject



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/alula/contents/item.rb', line 161

def write
  # Write all languages
  languages = self..languages || [self.site.config.locale]
  
  languages.each do |locale|
    begin
      _old_locale = self.current_locale
      self.current_locale = locale

      # Render our content
      self.render(locale)
      
      output = self.layout.render(item: self, locale: locale) do
        self.content(locale)
      end
      
      # Filter output
      self.site.filters.each do |name, filter|
        output = filter.output(output, locale) if filter.respond_to?(:output)
      end
      
      # Write content to file
      @site.storage.output_public(self.path(locale)) do
        if self.site.compressors.html.compresses?(self)
          self.site.compressors.html.compress(self, output)
        else
          output
        end
      end
    ensure
      self.current_locale = _old_locale
    end
  end
end