Class: Scribo::Content

Inherits:
ApplicationRecord show all
Defined in:
app/models/scribo/content.rb

Overview

Represents any content in the system

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ApplicationRecord

#to_liquid

Class Method Details

.alternative_paths_for(search_path) ⇒ Object



292
293
294
295
296
297
# File 'app/models/scribo/content.rb', line 292

def self.alternative_paths_for(search_path)
  search_paths = []
  search_path = Scribo::Utility.switch_extension(search_path, 'html') unless File.extname(search_path).present?
  search_paths.concat(Scribo::Utility.variations_for_path(search_path))
  search_paths << Scribo::Utility.switch_extension(search_path, 'link')
end

.located(path, restricted: true) ⇒ Object



57
58
59
60
61
62
63
# File 'app/models/scribo/content.rb', line 57

def self.located(path, restricted: true)
  restricted = true if restricted.nil? # If blank it's still restricted

  result = published.where(full_path: search_paths_for(path))
  result = result.restricted if restricted
  result.or(published.permalinked(search_paths_for(path)))
end

.paginated?(path) ⇒ Boolean

Returns:

  • (Boolean)


263
264
265
# File 'app/models/scribo/content.rb', line 263

def self.paginated?(path)
  path.match(%r[/(\d+)/$])
end

.redirect_options(redirect_data) ⇒ Object



370
371
372
373
374
375
376
377
378
# File 'app/models/scribo/content.rb', line 370

def redirect_options(redirect_data)
  options = redirect_data.split
  if options.length == 2
    options[0] = options[0].to_i
  else
    options.unshift 302
  end
  options
end

.search(search_string) ⇒ Object



70
71
72
73
74
# File 'app/models/scribo/content.rb', line 70

def self.search(search_string)
  where(
    "to_tsvector(scribo_contents.data || ' ' || COALESCE(scribo_contents.properties::text, '')) @@ to_tsquery(?)", search_string
  )
end

.search_paths_for(path) ⇒ Object



267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'app/models/scribo/content.rb', line 267

def self.search_paths_for(path)
  search_paths = []

  search_path = path
  search_path = "/#{search_path}" unless search_path.start_with?('/')
  search_path.gsub!(%r[/\d+/$], '/') if paginated?(search_path)
  search_path = "#{search_path}index.html" if search_path.ends_with?('/')

  search_paths.concat(alternative_paths_for(search_path))

  secondary_search_path = path.sub(%r[/$], '')
  secondary_search_path = "/#{secondary_search_path}" unless secondary_search_path.start_with?('/')
  search_paths.concat(alternative_paths_for(secondary_search_path)) if secondary_search_path != '' && secondary_search_path != search_path

  permalink_paths = [path]

  normalized_path = path
  normalized_path = "/#{normalized_path}" unless normalized_path.start_with?('/')
  normalized_path = "#{normalized_path}/" unless normalized_path.ends_with?('/')
  permalink_paths << normalized_path
  search_paths.concat(permalink_paths) # deal with permalinks

  search_paths.uniq
end

Instance Method Details

#asset?Boolean

Returns:

  • (Boolean)


255
256
257
# File 'app/models/scribo/content.rb', line 255

def asset?
  kind == 'asset'
end

#cache_keyObject



219
220
221
# File 'app/models/scribo/content.rb', line 219

def cache_key
  "#{super}-#{updated_at}-#{I18n.locale}"
end

#categoriesObject



173
174
175
176
177
178
179
# File 'app/models/scribo/content.rb', line 173

def categories
  if properties&.[]('categories').is_a? Array
    properties&.[]('categories')
  else
    (properties&.[]('categories') || '').split
  end
end

#collection_nameObject



223
224
225
226
227
# File 'app/models/scribo/content.rb', line 223

def collection_name
  return nil unless part_of_collection?

  ancestors.first.path[1..-1]
end

#config?Boolean

Returns:

  • (Boolean)


251
252
253
# File 'app/models/scribo/content.rb', line 251

def config?
  path == '_config.yml' && parent.nil?
end

#content_typeObject



189
190
191
# File 'app/models/scribo/content.rb', line 189

def content_type
  properties&.[]('content_type') || mime_type&.content_type || 'application/octet-stream'
end

#dataObject



157
158
159
160
161
# File 'app/models/scribo/content.rb', line 157

def data
  return attributes['data'] if kind == 'asset'

  attributes['data']&.force_encoding('utf-8')
end

#data_with_frontmatterObject

Data with frontmatter, used for maintenance and import/export



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

def data_with_frontmatter
  return asset.attachment&.download || data if kind != 'text'

  result = ''
  # Use attributes['properties'] here, to always use content-local properties
  result += (YAML.dump(attributes['properties']) + "---\n") if attributes['properties'].present?

  result + data.to_s
end

#data_with_frontmatter=(text) ⇒ Object

Data with frontmatter setter



104
105
106
107
108
109
110
111
112
# File 'app/models/scribo/content.rb', line 104

def data_with_frontmatter=(text)
  if kind == 'text'
     = Scribo::Preamble.parse(text)
    self.properties = .
    self.data = .content
  else
    self.data = text
  end
end

#dateObject



139
140
141
142
143
144
145
146
147
148
149
# File 'app/models/scribo/content.rb', line 139

def date
  # return nil unless post?

  prop_date = begin
    Time.zone.parse(properties['date'])
  rescue StandardError
    nil
  end

  prop_date || 
end

#dirObject



205
206
207
# File 'app/models/scribo/content.rb', line 205

def dir
  File.dirname(full_path)
end

#excerptObject



163
164
165
166
167
# File 'app/models/scribo/content.rb', line 163

def excerpt
  # FIXME: This is a terrible implementation
  excerpt_part = data.gsub("\r\n", "\n\n").split("\n\n").reject(&:empty?).reject { |p| p.start_with?('#') }.first
  Scribo::ContentRenderService.new(self, {}, data: excerpt_part, layout: false).call
end

#extensionObject



197
198
199
# File 'app/models/scribo/content.rb', line 197

def extension
  mime_type&.extensions&.first
end

#extnameObject



209
210
211
# File 'app/models/scribo/content.rb', line 209

def extname
  File.extname(full_path).tr('.', '')
end

#folder?Boolean

Returns:

  • (Boolean)


259
260
261
# File 'app/models/scribo/content.rb', line 259

def folder?
  kind == 'folder'
end

#identifierObject



88
89
90
# File 'app/models/scribo/content.rb', line 88

def identifier
  File.basename(path, File.extname(path))
end

#layoutObject

Layout as content



82
83
84
85
86
# File 'app/models/scribo/content.rb', line 82

def layout
  return nil unless layout_name.present?

  site.contents.layout(layout_name).first
end

#layout?Boolean

Returns:

  • (Boolean)


239
240
241
# File 'app/models/scribo/content.rb', line 239

def layout?
  full_path.start_with?('/_layouts/')
end

#layout_nameObject

Name of the currently in use layout



77
78
79
# File 'app/models/scribo/content.rb', line 77

def layout_name
  properties&.key?('layout') ? properties&.[]('layout') : ''
end

#media_typeObject



193
194
195
# File 'app/models/scribo/content.rb', line 193

def media_type
  mime_type&.media_type
end

#mime_typeObject



201
202
203
# File 'app/models/scribo/content.rb', line 201

def mime_type
  MIME::Types.type_for(path).first
end

#page?Boolean

Returns:

  • (Boolean)


247
248
249
# File 'app/models/scribo/content.rb', line 247

def page?
  Scribo::Utility.output_content_type(self) == 'text/html'
end

#part_of_collection?Boolean

Returns:

  • (Boolean)


229
230
231
232
233
# File 'app/models/scribo/content.rb', line 229

def part_of_collection?
  return false unless ancestors.first&.path&.start_with?('_')

  site.collections.include?(ancestors.first.path[1..-1])
end

#pathObject



65
66
67
# File 'app/models/scribo/content.rb', line 65

def path
  self[:path]
end


129
130
131
# File 'app/models/scribo/content.rb', line 129

def permalink
  properties&.[]('permalink')
end

#post?Boolean

Returns:

  • (Boolean)


243
244
245
# File 'app/models/scribo/content.rb', line 243

def post?
  ancestors.map(&:path).join('/').start_with?('_posts')
end

#post_dateObject



151
152
153
154
155
# File 'app/models/scribo/content.rb', line 151

def 
  Time.zone.strptime(path[0, 10], '%Y-%m-%d')
rescue StandardError
  nil
end

#propertiesObject

Used for merging with defaults



115
116
117
118
# File 'app/models/scribo/content.rb', line 115

def properties
  attributes['properties']
  # defaults.merge(attributes['properties'] || {})
end

#properties=(text) ⇒ Object



120
121
122
123
# File 'app/models/scribo/content.rb', line 120

def properties=(text)
  props = text.is_a?(String) ? Scribo::Utility.yaml_safe_parse(text.gsub("\t", '  ')) : text
  write_attribute :properties, props
end

#redirect?Boolean

Returns:

  • (Boolean)


235
236
237
# File 'app/models/scribo/content.rb', line 235

def redirect?
  extname == 'link'
end

#render(context = {}, options = {}) ⇒ Object



169
170
171
# File 'app/models/scribo/content.rb', line 169

def render(context = {}, options = {})
  Scribo::ContentRenderService.new(self, context, options).call
end

#store_full_path(force = false) ⇒ Object



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'app/models/scribo/content.rb', line 299

def store_full_path(force = false)
  if force || saved_changes.include?(:path) || saved_changes.include?(:parent_id)
    if post?
      result = categories.join('/') + '/'
      result += date.strftime('%Y/%m/%d/') if date
      result += path[11..-1]
    elsif part_of_collection? && site.output_collection?(collection_name)
      result = "#{collection_name}/#{path}"
    else
      result = (ancestors.reverse.map(&:path) << path).join('/')
    end
    result = '/' + result unless result.start_with?('/')

    update_column(:full_path, result)

    children.reload.each do |child|
      child.store_full_path(true)
    end
  end
end

#tagsObject



181
182
183
184
185
186
187
# File 'app/models/scribo/content.rb', line 181

def tags
  if properties&.[]('tags').is_a? Array
    properties&.[]('tags')
  else
    (properties&.[]('tags') || '').split
  end
end

#translation_scopeObject



213
214
215
216
217
# File 'app/models/scribo/content.rb', line 213

def translation_scope
  scope = File.dirname(full_path).split('/')
  scope << File.basename(full_path, File.extname(full_path))
  scope.join('.')
end

#tree_pathObject



320
321
322
323
324
# File 'app/models/scribo/content.rb', line 320

def tree_path
  result = (ancestors.reverse.map(&:path) << path).join('/')
  result = '/' + result unless result.start_with?('/')
  result
end

#typeObject



125
126
127
# File 'app/models/scribo/content.rb', line 125

def type
  collection_name
end

#urlObject



133
134
135
136
137
# File 'app/models/scribo/content.rb', line 133

def url
  result = permalink || Scribo::Utility.switch_extension(full_path)
  result += '/' unless result.end_with?('/')
  result
end