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



288
289
290
291
292
293
# File 'app/models/scribo/content.rb', line 288

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



53
54
55
56
57
58
59
# File 'app/models/scribo/content.rb', line 53

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)


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

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

.redirect_options(redirect_data) ⇒ Object



367
368
369
370
371
372
373
374
375
# File 'app/models/scribo/content.rb', line 367

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



66
67
68
69
70
# File 'app/models/scribo/content.rb', line 66

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



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

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)


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

def asset?
  kind == 'asset'
end

#cache_keyObject



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

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

#categoriesObject



169
170
171
172
173
174
175
# File 'app/models/scribo/content.rb', line 169

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

#collection_nameObject



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

def collection_name
  return nil unless part_of_collection?

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

#config?Boolean

Returns:

  • (Boolean)


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

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

#content_typeObject



185
186
187
# File 'app/models/scribo/content.rb', line 185

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

#dataObject



153
154
155
156
157
# File 'app/models/scribo/content.rb', line 153

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



89
90
91
92
93
94
95
96
97
# File 'app/models/scribo/content.rb', line 89

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



100
101
102
103
104
105
106
107
108
# File 'app/models/scribo/content.rb', line 100

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

#dateObject



135
136
137
138
139
140
141
142
143
144
145
# File 'app/models/scribo/content.rb', line 135

def date
  # return nil unless post?

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

  prop_date || 
end

#dirObject



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

def dir
  File.dirname(full_path)
end

#excerptObject



159
160
161
162
163
# File 'app/models/scribo/content.rb', line 159

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



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

def extension
  mime_type&.extensions&.first
end

#extnameObject



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

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

#folder?Boolean

Returns:

  • (Boolean)


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

def folder?
  kind == 'folder'
end

#identifierObject



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

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

#layoutObject

Layout as content



78
79
80
81
82
# File 'app/models/scribo/content.rb', line 78

def layout
  return nil unless layout_name.present?

  site.contents.layout(layout_name).first
end

#layout?Boolean

Returns:

  • (Boolean)


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

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

#layout_nameObject

Name of the currently in use layout



73
74
75
# File 'app/models/scribo/content.rb', line 73

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

#media_typeObject



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

def media_type
  mime_type&.media_type
end

#mime_typeObject



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

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

#page?Boolean

Returns:

  • (Boolean)


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

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

#part_of_collection?Boolean

Returns:

  • (Boolean)


225
226
227
228
229
# File 'app/models/scribo/content.rb', line 225

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

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

#pathObject



61
62
63
# File 'app/models/scribo/content.rb', line 61

def path
  self[:path]
end


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

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

#post?Boolean

Returns:

  • (Boolean)


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

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

#post_dateObject



147
148
149
150
151
# File 'app/models/scribo/content.rb', line 147

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

#propertiesObject

Used for merging with defaults



111
112
113
114
# File 'app/models/scribo/content.rb', line 111

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

#properties=(text) ⇒ Object



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

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)


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

def redirect?
  extname == 'link'
end

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



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

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

#store_full_path(force = false) ⇒ Object



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

def store_full_path(force = false)
  if force || saved_changes.include?(:path) || saved_changes.include?(:ancestry)
    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.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



177
178
179
180
181
182
183
# File 'app/models/scribo/content.rb', line 177

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

#translation_scopeObject



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

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

#tree_pathObject



317
318
319
320
321
# File 'app/models/scribo/content.rb', line 317

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

#typeObject



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

def type
  collection_name
end

#urlObject



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

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