middleman/middleman-core/lib/middleman-core/util/data.rb

87 lines
2.2 KiB
Ruby
Raw Normal View History

2015-06-17 00:30:37 +02:00
require 'yaml'
2015-09-17 18:41:17 +02:00
require 'json'
2015-09-20 14:23:47 +02:00
require 'pathname'
require 'middleman-core/util'
require 'middleman-core/contracts'
2015-06-17 00:30:37 +02:00
2015-09-20 14:23:47 +02:00
module Middleman::Util::Data
include Contracts
2015-06-17 00:30:37 +02:00
2015-09-20 14:23:47 +02:00
module_function
2015-06-17 00:30:37 +02:00
2015-09-20 14:23:47 +02:00
# Get the frontmatter and plain content from a file
# @param [String] path
# @return [Array<Hash, String>]
Contract Pathname, Maybe[Symbol] => [Hash, Maybe[String]]
def parse(full_path, known_type=nil)
return [{}, nil] if Middleman::Util.binary?(full_path)
2015-06-17 00:30:37 +02:00
2015-09-20 14:23:47 +02:00
# Avoid weird race condition when a file is renamed
begin
content = File.read(full_path)
rescue EOFError, IOError, Errno::ENOENT
return [{}, nil]
end
2015-06-17 00:30:37 +02:00
2015-09-20 14:23:47 +02:00
/
2015-09-30 06:45:34 +02:00
\A(?:[^\r\n]*coding:[^\r\n]*\r?\n)?
(?<start>---|;;;)[ ]*\r?\n
(?<frontmatter>.*?)[ ]*\r?\n?
2015-09-30 06:45:34 +02:00
^(?<stop>---|\.\.\.|;;;)[ ]*\r?\n?
\r?\n?
2015-09-20 14:23:47 +02:00
(?<additional_content>.*)
/mx =~ content
unless frontmatter
case known_type
when :yaml
return [parse_yaml(content, full_path), nil]
when :json
return [parse_json(content, full_path), nil]
end
end
2015-09-20 14:23:47 +02:00
case [start, stop]
2015-09-24 01:20:16 +02:00
when %w(--- ---), %w(--- ...)
2015-09-20 14:23:47 +02:00
[parse_yaml(frontmatter, full_path), additional_content]
2015-09-24 01:20:16 +02:00
when %w(;;; ;;;)
2015-09-24 21:27:36 +02:00
[parse_json("{#{frontmatter}}", full_path), additional_content]
2015-09-20 14:23:47 +02:00
else
[{}, content]
end
end
2015-06-17 00:30:37 +02:00
2015-09-20 14:23:47 +02:00
# Parse YAML frontmatter out of a string
# @param [String] content
# @return [Hash]
2015-09-20 14:23:47 +02:00
Contract String, Pathname, Bool => Hash
def parse_yaml(content, full_path)
symbolize_recursive(YAML.load(content) || {})
2015-09-20 14:23:47 +02:00
rescue StandardError, Psych::SyntaxError => error
warn "YAML Exception parsing #{full_path}: #{error.message}"
{}
end
2015-06-17 00:30:37 +02:00
2015-09-20 14:23:47 +02:00
# Parse JSON frontmatter out of a string
# @param [String] content
# @return [Hash]
2015-09-20 14:23:47 +02:00
Contract String, Pathname => Hash
def parse_json(content, full_path)
symbolize_recursive(JSON.parse(content) || {})
2015-09-20 14:23:47 +02:00
rescue StandardError => error
warn "JSON Exception parsing #{full_path}: #{error.message}"
{}
end
2015-06-17 00:30:37 +02:00
2015-09-20 14:23:47 +02:00
def symbolize_recursive(value)
case value
when Hash
value.map { |k, v| [k.to_sym, symbolize_recursive(v)] }.to_h
when Array
value.map { |v| symbolize_recursive(v) }
else
value
2015-06-17 00:30:37 +02:00
end
end
end