Class: Jekyll::Document
- Inherits:
-
Object
- Object
- Jekyll::Document
- Includes:
- Comparable
- Defined in:
- lib/jekyll/document.rb
Constant Summary collapse
- YAML_FRONT_MATTER_REGEXP =
/\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m- DATELESS_FILENAME_MATCHER =
/^(.*)(\.[^.]+)$/- DATE_FILENAME_MATCHER =
/^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
Instance Attribute Summary collapse
-
#collection ⇒ Object
readonly
Returns the value of attribute collection.
-
#content ⇒ Object
Returns the value of attribute content.
-
#extname ⇒ Object
readonly
Returns the value of attribute extname.
-
#output ⇒ Object
Returns the value of attribute output.
-
#output_ext ⇒ Object
readonly
Returns the value of attribute output_ext.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#site ⇒ Object
readonly
Returns the value of attribute site.
Instance Method Summary collapse
-
#<=>(anotherDocument) ⇒ Object
Compare this document against another document.
- #[](key) ⇒ Object
-
#asset_file? ⇒ Boolean
Determine whether the document is an asset file.
-
#basename ⇒ Object
The base filename of the document.
-
#basename_without_ext ⇒ Object
The base filename of the document, without the file extname.
-
#cleaned_relative_path ⇒ Object
Produces a "cleaned" relative path.
-
#coffeescript_file? ⇒ Boolean
Determine whether the document is a CoffeeScript file.
-
#data ⇒ Object
Fetch the Document's data.
- #date ⇒ Object
-
#destination(base_directory) ⇒ Object
The full path to the output file.
-
#excerpt_separator ⇒ Object
The Document excerpt_separator, from the YAML Front-Matter or site default excerpt_separator value.
-
#generate_excerpt? ⇒ Boolean
Whether to generate an excerpt.
- #id ⇒ Object
-
#initialize(path, relations) ⇒ Document
constructor
Create a new Document.
-
#inspect ⇒ Object
The inspect string for this document.
-
#merge_data!(other) ⇒ Object
Merge some data in with this document's data.
-
#merged_file_read_opts(opts) ⇒ Object
Returns merged option hash for File.read of self.site (if exists) and a given param.
-
#method_missing(method, *args, &blck) ⇒ Object
Override of method_missing to check in @data for the key.
- #next_doc ⇒ Object
-
#permalink ⇒ Object
The permalink for this Document.
-
#place_in_layout? ⇒ Boolean
Determine whether the file should be placed into layouts.
- #populate_categories ⇒ Object
- #populate_tags ⇒ Object
- #post_read ⇒ Object
- #previous_doc ⇒ Object
-
#published? ⇒ Boolean
Whether the file is published or not, as indicated in YAML front-matter.
-
#read(opts = {}) ⇒ Object
Read in the file and assign the content and data based on the file contents.
-
#related_posts ⇒ Object
Calculate related posts.
-
#relative_path ⇒ Object
The path to the document, relative to the site source.
-
#render_with_liquid? ⇒ Boolean
Determine whether the file should be rendered with Liquid.
-
#respond_to?(method, include_private = false) ⇒ Boolean
Override of normal respond_to? to match method_missing's logic for looking in @data.
-
#sass_file? ⇒ Boolean
Determine whether the document is a Sass file.
-
#to_liquid ⇒ Object
Create a Liquid-understandable version of this Document.
-
#to_s ⇒ Object
The string representation for this document.
- #trigger_hooks(hook_name, *args) ⇒ Object
-
#url ⇒ Object
The computed URL for the document.
-
#url_placeholders ⇒ Object
Construct a Hash of key-value pairs which contain a mapping between a key in the URL template and the corresponding value for this document.
-
#url_template ⇒ Object
The URL template where the document would be accessible.
-
#write(dest) ⇒ Object
Write the generated Document file to the destination directory.
-
#write? ⇒ Boolean
Determine whether this document should be written.
-
#yaml_file? ⇒ Boolean
Determine whether the document is a YAML file.
Constructor Details
#initialize(path, relations) ⇒ Document
Create a new Document.
site - the Jekyll::Site instance to which this Document belongs path - the path to the file
Returns nothing.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/jekyll/document.rb', line 19 def initialize(path, relations) @site = relations[:site] @path = path @extname = File.extname(path) @output_ext = Jekyll::Renderer.new(site, self).output_ext @collection = relations[:collection] @has_yaml_header = nil subdirs = relative_path.split(File::SEPARATOR).reject do |c| c.empty? || c.eql?(collection.relative_directory) || c.eql?("_drafts") || c.eql?(basename) end merge_data!({'categories' => subdirs }) data.default_proc = proc do |hash, key| site.frontmatter_defaults.find(relative_path, collection.label, key) end trigger_hooks(:post_init) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &blck) ⇒ Object
Override of method_missing to check in @data for the key.
442 443 444 445 446 447 448 449 450 |
# File 'lib/jekyll/document.rb', line 442 def method_missing(method, *args, &blck) if data.key?(method.to_s) Jekyll.logger.warn "Deprecation:", "Document##{method} is now a key in the #data hash." Jekyll.logger.warn "", "Called by #{caller.first}." data[method.to_s] else super end end |
Instance Attribute Details
#collection ⇒ Object (readonly)
Returns the value of attribute collection.
7 8 9 |
# File 'lib/jekyll/document.rb', line 7 def collection @collection end |
#content ⇒ Object
Returns the value of attribute content.
7 8 9 |
# File 'lib/jekyll/document.rb', line 7 def content @content end |
#extname ⇒ Object (readonly)
Returns the value of attribute extname.
7 8 9 |
# File 'lib/jekyll/document.rb', line 7 def extname @extname end |
#output ⇒ Object
Returns the value of attribute output.
7 8 9 |
# File 'lib/jekyll/document.rb', line 7 def output @output end |
#output_ext ⇒ Object (readonly)
Returns the value of attribute output_ext.
7 8 9 |
# File 'lib/jekyll/document.rb', line 7 def output_ext @output_ext end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
7 8 9 |
# File 'lib/jekyll/document.rb', line 7 def path @path end |
#site ⇒ Object (readonly)
Returns the value of attribute site.
7 8 9 |
# File 'lib/jekyll/document.rb', line 7 def site @site end |
Instance Method Details
#<=>(anotherDocument) ⇒ Object
Compare this document against another document. Comparison is a comparison between the 2 paths of the documents.
Returns -1, 0, +1 or nil depending on whether this doc's path is less than, equal or greater than the other doc's path. See String#<=> for more details.
369 370 371 372 373 374 375 |
# File 'lib/jekyll/document.rb', line 369 def <=>(anotherDocument) cmp = data['date'] <=> anotherDocument.data['date'] if 0 == cmp cmp = path <=> anotherDocument.path end cmp end |
#[](key) ⇒ Object
214 215 216 |
# File 'lib/jekyll/document.rb', line 214 def [](key) data[key] end |
#asset_file? ⇒ Boolean
Determine whether the document is an asset file. Asset files include CoffeeScript files and Sass/SCSS files.
Returns true if the extname belongs to the set of extensions that asset files use.
128 129 130 |
# File 'lib/jekyll/document.rb', line 128 def asset_file? sass_file? || coffeescript_file? end |
#basename ⇒ Object
The base filename of the document.
Returns the base filename of the document.
96 97 98 |
# File 'lib/jekyll/document.rb', line 96 def basename @basename ||= File.basename(path) end |
#basename_without_ext ⇒ Object
The base filename of the document, without the file extname.
Returns the basename without the file extname.
89 90 91 |
# File 'lib/jekyll/document.rb', line 89 def basename_without_ext @basename_without_ext ||= File.basename(path, '.*') end |
#cleaned_relative_path ⇒ Object
Produces a "cleaned" relative path. The "cleaned" relative path is the relative path without the extname and with the collection's directory removed as well. This method is useful when building the URL of the document.
Examples:
When relative_path is "_methods/site/generate.md":
cleaned_relative_path
# => "/site/generate"
Returns the cleaned relative path of the document.
111 112 113 114 |
# File 'lib/jekyll/document.rb', line 111 def cleaned_relative_path @cleaned_relative_path ||= relative_path[0 .. -extname.length - 1].sub(collection.relative_directory, "") end |
#coffeescript_file? ⇒ Boolean
Determine whether the document is a CoffeeScript file.
Returns true if extname == .coffee, false otherwise.
142 143 144 |
# File 'lib/jekyll/document.rb', line 142 def coffeescript_file? '.coffee'.eql?(extname) end |
#data ⇒ Object
Fetch the Document's data.
Returns a Hash containing the data. An empty hash is returned if no data was read.
53 54 55 |
# File 'lib/jekyll/document.rb', line 53 def data @data ||= Hash.new end |
#date ⇒ Object
74 75 76 |
# File 'lib/jekyll/document.rb', line 74 def date data['date'] ||= site.time end |
#destination(base_directory) ⇒ Object
The full path to the output file.
base_directory - the base path of the output directory
Returns the full path to the output file of this document.
223 224 225 226 227 228 229 |
# File 'lib/jekyll/document.rb', line 223 def destination(base_directory) dest = site.in_dest_dir(base_directory) path = site.in_dest_dir(dest, URL.unescape_path(url)) path = File.join(path, "index.html") if url.end_with?("/") path << output_ext unless path.end_with?(output_ext) path end |
#excerpt_separator ⇒ Object
The Document excerpt_separator, from the YAML Front-Matter or site default excerpt_separator value
Returns the document excerpt_separator
390 391 392 |
# File 'lib/jekyll/document.rb', line 390 def excerpt_separator (data['excerpt_separator'] || site.config['excerpt_separator']).to_s end |
#generate_excerpt? ⇒ Boolean
Whether to generate an excerpt
Returns true if the excerpt separator is configured.
397 398 399 |
# File 'lib/jekyll/document.rb', line 397 def generate_excerpt? !excerpt_separator.empty? end |
#id ⇒ Object
424 425 426 |
# File 'lib/jekyll/document.rb', line 424 def id @id ||= File.join(File.dirname(url), (data['slug'] || basename_without_ext).to_s) end |
#inspect ⇒ Object
The inspect string for this document. Includes the relative path and the collection label.
Returns the inspect string for this document.
353 354 355 |
# File 'lib/jekyll/document.rb', line 353 def inspect "#<Jekyll::Document #{relative_path} collection=#{collection.label}>" end |
#merge_data!(other) ⇒ Object
Merge some data in with this document's data.
Returns the merged data.
60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/jekyll/document.rb', line 60 def merge_data!(other) if other.key?('categories') && !other['categories'].nil? if other['categories'].is_a?(String) other['categories'] = other['categories'].split(" ").map(&:strip) end other['categories'] = (data['categories'] || []) | other['categories'] end Utils.deep_merge_hashes!(data, other) if data.key?('date') && !data['date'].is_a?(Time) data['date'] = Utils.parse_date(data['date'].to_s, "Document '#{relative_path}' does not have a valid date in the YAML front matter.") end data end |
#merged_file_read_opts(opts) ⇒ Object
Returns merged option hash for File.read of self.site (if exists) and a given param
opts - override options
Return the file read options hash.
252 253 254 |
# File 'lib/jekyll/document.rb', line 252 def merged_file_read_opts(opts) site ? site.file_read_opts.merge(opts) : opts end |
#next_doc ⇒ Object
401 402 403 404 405 406 407 408 |
# File 'lib/jekyll/document.rb', line 401 def next_doc pos = collection.docs.index {|post| post.equal?(self) } if pos && pos < collection.docs.length - 1 collection.docs[pos + 1] else nil end end |
#permalink ⇒ Object
The permalink for this Document. Permalink is set via the data Hash.
Returns the permalink or nil if no permalink was set in the data.
199 200 201 |
# File 'lib/jekyll/document.rb', line 199 def permalink data && data.is_a?(Hash) && data['permalink'] end |
#place_in_layout? ⇒ Boolean
Determine whether the file should be placed into layouts.
Returns false if the document is either an asset file or a yaml file, true otherwise.
158 159 160 |
# File 'lib/jekyll/document.rb', line 158 def place_in_layout? !(asset_file? || yaml_file?) end |
#populate_categories ⇒ Object
314 315 316 317 318 319 320 |
# File 'lib/jekyll/document.rb', line 314 def populate_categories merge_data!({ "categories" => ( Array(data['categories']) + Utils.pluralized_array_from_hash(data, 'category', 'categories') ).map { |c| c.to_s }.flatten.uniq }) end |
#populate_tags ⇒ Object
322 323 324 325 326 |
# File 'lib/jekyll/document.rb', line 322 def merge_data!({ "tags" => Utils.pluralized_array_from_hash(data, "tag", "tags").flatten }) end |
#post_read ⇒ Object
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 |
# File 'lib/jekyll/document.rb', line 296 def post_read if DATE_FILENAME_MATCHER =~ relative_path m, cats, date, slug, ext = *relative_path.match(DATE_FILENAME_MATCHER) merge_data!({ "slug" => slug, "ext" => ext }) merge_data!({"date" => date}) if data['date'].nil? || data['date'].to_i == site.time.to_i data['title'] ||= slug.split('-').select {|w| w.capitalize! || w }.join(' ') end populate_categories if generate_excerpt? data['excerpt'] ||= Jekyll::Excerpt.new(self) end end |
#previous_doc ⇒ Object
410 411 412 413 414 415 416 417 |
# File 'lib/jekyll/document.rb', line 410 def previous_doc pos = collection.docs.index {|post| post.equal?(self) } if pos && pos > 0 collection.docs[pos - 1] else nil end end |
#published? ⇒ Boolean
Whether the file is published or not, as indicated in YAML front-matter
Returns true if the 'published' key is specified in the YAML front-matter and not false.
259 260 261 |
# File 'lib/jekyll/document.rb', line 259 def published? !(data.key?('published') && data['published'] == false) end |
#read(opts = {}) ⇒ Object
Read in the file and assign the content and data based on the file contents. Merge the frontmatter of the file with the frontmatter default values
Returns nothing.
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/jekyll/document.rb', line 268 def read(opts = {}) @to_liquid = nil Jekyll.logger.debug "Reading:", relative_path if yaml_file? @data = SafeYAML.load_file(path) else begin defaults = @site.frontmatter_defaults.all(url, collection.label.to_sym) merge_data!(defaults) unless defaults.empty? self.content = File.read(path, merged_file_read_opts(opts)) if content =~ YAML_FRONT_MATTER_REGEXP self.content = $POSTMATCH data_file = SafeYAML.load($1) merge_data!(data_file) if data_file end post_read rescue SyntaxError => e puts "YAML Exception reading #{path}: #{e.}" rescue Exception => e puts "Error reading file #{path}: #{e.}" end end end |
#related_posts ⇒ Object
Calculate related posts.
Returns an Array of related Posts.
431 432 433 |
# File 'lib/jekyll/document.rb', line 431 def Jekyll::RelatedPosts.new(self).build end |
#relative_path ⇒ Object
The path to the document, relative to the site source.
Returns a String path which represents the relative path from the site source to this document
82 83 84 |
# File 'lib/jekyll/document.rb', line 82 def relative_path @relative_path ||= Pathname.new(path).relative_path_from(Pathname.new(site.source)).to_s end |
#render_with_liquid? ⇒ Boolean
Determine whether the file should be rendered with Liquid.
Returns false if the document is either an asset file or a yaml file, true otherwise.
150 151 152 |
# File 'lib/jekyll/document.rb', line 150 def render_with_liquid? !(coffeescript_file? || yaml_file?) end |
#respond_to?(method, include_private = false) ⇒ Boolean
Override of normal respond_to? to match method_missing's logic for looking in @data.
437 438 439 |
# File 'lib/jekyll/document.rb', line 437 def respond_to?(method, include_private = false) data.key?(method.to_s) || super end |
#sass_file? ⇒ Boolean
Determine whether the document is a Sass file.
Returns true if extname == .sass or .scss, false otherwise.
135 136 137 |
# File 'lib/jekyll/document.rb', line 135 def sass_file? %w[.sass .scss].include?(extname) end |
#to_liquid ⇒ Object
Create a Liquid-understandable version of this Document.
Returns a Hash representing this Document's data.
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
# File 'lib/jekyll/document.rb', line 331 def to_liquid @to_liquid ||= if data.is_a?(Hash) Utils.deep_merge_hashes Utils.deep_merge_hashes({ "output" => output, "content" => content, "relative_path" => relative_path, "path" => relative_path, "url" => url, "collection" => collection.label, "next" => next_doc, "previous" => previous_doc, "id" => id, }, data), { 'excerpt' => data['excerpt'].to_s } else data end end |
#to_s ⇒ Object
The string representation for this document.
Returns the content of the document
360 361 362 |
# File 'lib/jekyll/document.rb', line 360 def to_s output || content || 'NO CONTENT' end |
#trigger_hooks(hook_name, *args) ⇒ Object
419 420 421 422 |
# File 'lib/jekyll/document.rb', line 419 def trigger_hooks(hook_name, *args) Jekyll::Hooks.trigger collection.label.to_sym, hook_name, self, *args if collection Jekyll::Hooks.trigger :documents, hook_name, self, *args end |
#url ⇒ Object
The computed URL for the document. See Jekyll::URL#to_s for more details.
Returns the computed URL for the document.
206 207 208 209 210 211 212 |
# File 'lib/jekyll/document.rb', line 206 def url @url = URL.new({ template: url_template, placeholders: url_placeholders, permalink: permalink }).to_s end |
#url_placeholders ⇒ Object
Construct a Hash of key-value pairs which contain a mapping between a key in the URL template and the corresponding value for this document.
Returns the Hash of key-value pairs for replacement in the URL.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/jekyll/document.rb', line 173 def url_placeholders { collection: collection.label, path: cleaned_relative_path, output_ext: output_ext, name: Utils.slugify(basename_without_ext), title: Utils.slugify(data['slug']) || Utils.slugify(basename_without_ext), year: date.strftime("%Y"), month: date.strftime("%m"), day: date.strftime("%d"), hour: date.strftime("%H"), minute: date.strftime("%M"), second: date.strftime("%S"), i_day: date.strftime("%-d"), i_month: date.strftime("%-m"), categories: (data['categories'] || []).map { |c| c.to_s.downcase }.uniq.join('/'), short_month: date.strftime("%b"), short_year: date.strftime("%y"), y_day: date.strftime("%j"), } end |
#url_template ⇒ Object
The URL template where the document would be accessible.
Returns the URL template for the document.
165 166 167 |
# File 'lib/jekyll/document.rb', line 165 def url_template collection.url_template end |
#write(dest) ⇒ Object
Write the generated Document file to the destination directory.
dest - The String path to the destination dir.
Returns nothing.
236 237 238 239 240 241 242 243 244 |
# File 'lib/jekyll/document.rb', line 236 def write(dest) path = destination(dest) FileUtils.mkdir_p(File.dirname(path)) File.open(path, 'wb') do |f| f.write(output) end trigger_hooks(:post_write) end |
#write? ⇒ Boolean
Determine whether this document should be written. Based on the Collection to which it belongs.
True if the document has a collection and if that collection's #write? method returns true, otherwise false.
382 383 384 |
# File 'lib/jekyll/document.rb', line 382 def write? collection && collection.write? end |
#yaml_file? ⇒ Boolean
Determine whether the document is a YAML file.
Returns true if the extname is either .yml or .yaml, false otherwise.
119 120 121 |
# File 'lib/jekyll/document.rb', line 119 def yaml_file? %w[.yaml .yml].include?(extname) end |