mirror of
https://github.com/middleman/middleman.git
synced 2022-11-09 12:20:27 -05:00
Support TOML as a frontmatter or data format
This commit is contained in:
parent
48f1a0f15e
commit
22f867d0a7
16 changed files with 153 additions and 38 deletions
|
@ -1,5 +1,6 @@
|
|||
# master
|
||||
|
||||
- Support TOML as frontmatter and data.
|
||||
- Handle the removal of a file in dependencies. Fixes #2292
|
||||
- Update rubocop + use enable-frozen-string-literal (#2354)
|
||||
- Add ability to external pipeline ignore process exit code (#2353)
|
||||
|
|
|
@ -29,6 +29,7 @@ PATH
|
|||
sassc (~> 2.0)
|
||||
servolux
|
||||
tilt (~> 2.0.9)
|
||||
toml
|
||||
uglifier (~> 4.1)
|
||||
|
||||
GEM
|
||||
|
@ -132,7 +133,7 @@ GEM
|
|||
lazy_priority_queue (0.1.1)
|
||||
libv8 (8.4.255.0)
|
||||
liquid (4.0.3)
|
||||
listen (3.2.1)
|
||||
listen (3.3.2)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
memoist (0.16.2)
|
||||
|
@ -149,7 +150,7 @@ GEM
|
|||
nio4r (2.5.2)
|
||||
nokogiri (1.10.10)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
oj (3.10.8)
|
||||
oj (3.10.16)
|
||||
padrino-helpers (0.14.4)
|
||||
i18n (~> 0.6, >= 0.6.7)
|
||||
padrino-support (= 0.14.4)
|
||||
|
@ -158,6 +159,7 @@ GEM
|
|||
parallel (1.20.1)
|
||||
parser (2.7.2.0)
|
||||
ast (~> 2.4.1)
|
||||
parslet (1.8.2)
|
||||
protobuf-cucumber (3.10.8)
|
||||
activesupport (>= 3.2)
|
||||
middleware
|
||||
|
@ -243,6 +245,8 @@ GEM
|
|||
thread_safe (0.3.6)
|
||||
tilt (2.0.10)
|
||||
timers (4.3.0)
|
||||
toml (0.2.0)
|
||||
parslet (~> 1.8.0)
|
||||
tzinfo (1.2.7)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (4.2.0)
|
||||
|
|
|
@ -92,3 +92,23 @@ Feature: Local Data API
|
|||
Then I should see "<h1>With Content</h1>"
|
||||
Then I should see '<h2 id="header-2">Header 2</h2>'
|
||||
Then I should see "<p>Paragraph 1</p>"
|
||||
|
||||
Scenario: Rendering toml
|
||||
Given the Server is running at "basic-data-app"
|
||||
When I go to "/data4.html"
|
||||
Then I should see "One:Two"
|
||||
When the file "data/test3.toml" has the contents
|
||||
"""
|
||||
[titles]
|
||||
|
||||
[titles.first]
|
||||
title = "Three"
|
||||
|
||||
[titles.second]
|
||||
title = "Four"
|
||||
"""
|
||||
When I go to "/data4.html"
|
||||
Then I should see "Three:Four"
|
||||
When the file "data/test3.toml" is removed
|
||||
When I go to "/data4.html"
|
||||
Then I should see "No Test Data"
|
|
@ -23,6 +23,12 @@ Feature: Neighboring YAML Front Matter
|
|||
When I go to "/raw-front-matter.php.frontmatter"
|
||||
Then I should see "File Not Found"
|
||||
|
||||
Scenario: Rendering raw (template-less) (toml)
|
||||
Given the Server is running at "frontmatter-neighbor-app"
|
||||
When I go to "/raw-front-matter-toml.html"
|
||||
Then I should see "<h1><%= current_page.data.title %></h1>"
|
||||
Then I should not see "---"
|
||||
|
||||
Scenario: YAML not on first line, with encoding
|
||||
Given the Server is running at "frontmatter-neighbor-app"
|
||||
When I go to "/front-matter-encoding.html"
|
||||
|
@ -65,10 +71,10 @@ Feature: Neighboring YAML Front Matter
|
|||
Scenario: A template should handle an empty YAML feed
|
||||
Given the Server is running at "frontmatter-neighbor-app"
|
||||
And the file "source/front-matter-change.html.erb.frontmatter" has the contents
|
||||
"""
|
||||
---
|
||||
---
|
||||
"""
|
||||
"""
|
||||
---
|
||||
---
|
||||
"""
|
||||
When I go to "/front-matter-change.html"
|
||||
Then I should not see "Hello World"
|
||||
Then I should not see "Hola Mundo"
|
||||
|
@ -78,14 +84,14 @@ Feature: Neighboring YAML Front Matter
|
|||
Scenario: Setting layout, ignoring, and disabling directory indexes through frontmatter (build)
|
||||
Given a successfully built app at "frontmatter-settings-neighbor-app"
|
||||
Then the following files should exist:
|
||||
| build/proxied.html |
|
||||
| build/proxied.html |
|
||||
And the file "build/alternate_layout.html" should contain "Alternate layout"
|
||||
And the following files should not exist:
|
||||
| build/ignored.html |
|
||||
| build/alternate_layout.html.erb.frontmatter |
|
||||
| build/ignored.html.erb.frontmatter |
|
||||
| build/ignored.html |
|
||||
| build/alternate_layout.html.erb.frontmatter |
|
||||
| build/ignored.html.erb.frontmatter |
|
||||
| build/override_layout.html.erb.frontmatter |
|
||||
| build/page_mentioned.html.erb.frontmatter |
|
||||
| build/page_mentioned.html.erb.frontmatter |
|
||||
|
||||
Scenario: Setting layout, ignoring, and disabling directory indexes through frontmatter (preview)
|
||||
Given the Server is running at "frontmatter-settings-neighbor-app"
|
||||
|
@ -130,22 +136,22 @@ Feature: Neighboring YAML Front Matter
|
|||
When I go to "/page_mentioned.html.erb.frontmatter"
|
||||
Then I should see "File Not Found"
|
||||
|
||||
# Scenario: Neighbor frontmatter for destination of proxy resources
|
||||
# Given the Server is running at "frontmatter-settings-neighbor-app"
|
||||
# And the file "source/proxied_with_frontmatter.html.frontmatter" has the contents
|
||||
# """
|
||||
# ---
|
||||
# title: Proxied title
|
||||
# ---
|
||||
# """
|
||||
# And the file "source/ignored.html.erb" has the contents
|
||||
# """
|
||||
# ---
|
||||
# ignored: true
|
||||
# ---
|
||||
# Scenario: Neighbor frontmatter for destination of proxy resources
|
||||
# Given the Server is running at "frontmatter-settings-neighbor-app"
|
||||
# And the file "source/proxied_with_frontmatter.html.frontmatter" has the contents
|
||||
# """
|
||||
# ---
|
||||
# title: Proxied title
|
||||
# ---
|
||||
# """
|
||||
# And the file "source/ignored.html.erb" has the contents
|
||||
# """
|
||||
# ---
|
||||
# ignored: true
|
||||
# ---
|
||||
|
||||
# <%= current_resource.data.inspect %>
|
||||
# <%= current_resource.data.title %>
|
||||
# """
|
||||
# When I go to "/proxied_with_frontmatter.html"
|
||||
# Then I should see "Proxied title"
|
||||
# <%= current_resource.data.inspect %>
|
||||
# <%= current_resource.data.title %>
|
||||
# """
|
||||
# When I go to "/proxied_with_frontmatter.html"
|
||||
# Then I should see "Proxied title"
|
||||
|
|
|
@ -90,10 +90,16 @@ Feature: YAML Front Matter
|
|||
Scenario: A template should handle an empty YAML feed
|
||||
Given the Server is running at "frontmatter-app"
|
||||
And the file "source/front-matter-change.html.erb" has the contents
|
||||
"""
|
||||
---
|
||||
---
|
||||
Hello World
|
||||
"""
|
||||
"""
|
||||
---
|
||||
---
|
||||
Hello World
|
||||
"""
|
||||
When I go to "/front-matter-change.html"
|
||||
Then I should see "Hello World"
|
||||
|
||||
Scenario: Rendering raw (template-less) (toml)
|
||||
Given the Server is running at "frontmatter-app"
|
||||
When I go to "/raw-front-matter-toml.html"
|
||||
Then I should see "<h1><%= current_page.data.title %></h1>"
|
||||
Then I should not see "---"
|
7
middleman-core/fixtures/basic-data-app/data/test3.toml
Normal file
7
middleman-core/fixtures/basic-data-app/data/test3.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[titles]
|
||||
|
||||
[titles.first]
|
||||
title = "One"
|
||||
|
||||
[titles.second]
|
||||
title = "Two"
|
|
@ -0,0 +1,5 @@
|
|||
<% if data.respond_to?(:test3) && data.test3.respond_to?(:titles) %>
|
||||
<%= data.test3.titles.map { |r| r[1].title }.join(":") %>
|
||||
<% else %>
|
||||
No Test Data
|
||||
<% end %>
|
|
@ -0,0 +1,6 @@
|
|||
+++
|
||||
layout = false
|
||||
title = "This is the title"
|
||||
+++
|
||||
|
||||
<h1><%= current_page.data.title %></h1>
|
|
@ -3,4 +3,4 @@ layout: false
|
|||
title: This is the title
|
||||
---
|
||||
|
||||
<h1><%= current_page.data.title %></h1>
|
||||
<h1><%= current_page.data.title %></h1>
|
|
@ -0,0 +1 @@
|
|||
<h1><%= current_page.data.title %></h1>
|
|
@ -0,0 +1,4 @@
|
|||
+++
|
||||
layout = false
|
||||
title = "This is the title"
|
||||
+++
|
|
@ -21,7 +21,7 @@ module Middleman
|
|||
expose_to_template internal_data_store: :data_store
|
||||
|
||||
# The regex which tells Middleman which files are for data
|
||||
DATA_FILE_MATCHER = /^(.*?)[\w-]+\.(yml|yaml|json)$/.freeze
|
||||
DATA_FILE_MATCHER = /^(.*?)[\w-]+\.(yml|yaml|json|toml)$/.freeze
|
||||
|
||||
Contract IsA['::Middleman::Application'], Hash => Any
|
||||
def initialize(app, options_hash = ::Middleman::EMPTY_HASH, &block)
|
||||
|
|
|
@ -18,7 +18,8 @@ module Middleman
|
|||
|
||||
YAML_EXTS = Set.new %w[.yaml .yml]
|
||||
JSON_EXTS = Set.new %w[.json]
|
||||
ALL_EXTS = YAML_EXTS | JSON_EXTS
|
||||
TOML_EXTS = Set.new %w[.toml]
|
||||
ALL_EXTS = YAML_EXTS | JSON_EXTS | TOML_EXTS
|
||||
|
||||
def_delegators :@local_data, :keys, :key?, :[]
|
||||
|
||||
|
@ -55,6 +56,8 @@ module Middleman
|
|||
data[:postscript] = postscript if !postscript.nil? && data.is_a?(Hash)
|
||||
elsif JSON_EXTS.include?(extension)
|
||||
data, _postscript = ::Middleman::Util::Data.parse(file, @app.config[:frontmatter_delims], :json)
|
||||
elsif TOML_EXTS.include?(extension)
|
||||
data, _postscript = ::Middleman::Util::Data.parse(file, @app.config[:frontmatter_delims], :toml)
|
||||
end
|
||||
|
||||
data_branch = @local_data
|
||||
|
|
|
@ -16,7 +16,30 @@ module Middleman::CoreExtensions
|
|||
|
||||
# Set textual delimiters that denote the start and end of frontmatter
|
||||
define_setting :frontmatter_delims, {
|
||||
json: [%w[;;; ;;;]],
|
||||
json: [
|
||||
%w[;;; ;;;],
|
||||
|
||||
# Haml with commented frontmatter
|
||||
["-#\n ;;;", ' ;;;'],
|
||||
|
||||
# Slim with commented frontmatter
|
||||
["\/\n ;;;", ' ;;;'],
|
||||
|
||||
# ERb with commented frontmatter
|
||||
["<%#\n ;;;", " ;;;\n%>"]
|
||||
],
|
||||
toml: [
|
||||
%w[+++ +++],
|
||||
|
||||
# Haml with commented frontmatter
|
||||
["-#\n +++", ' +++'],
|
||||
|
||||
# Slim with commented frontmatter
|
||||
["\/\n +++", ' +++'],
|
||||
|
||||
# ERb with commented frontmatter
|
||||
["<%#\n +++", " +++\n%>"]
|
||||
],
|
||||
yaml: [
|
||||
# Normal
|
||||
%w[--- ---],
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
require 'yaml'
|
||||
require 'json'
|
||||
require 'toml'
|
||||
require 'pathname'
|
||||
require 'hashie'
|
||||
require 'memoist'
|
||||
|
@ -72,6 +73,8 @@ module Middleman
|
|||
return [parse_yaml(content, full_path), nil]
|
||||
when :json
|
||||
return [parse_json(content, full_path), nil]
|
||||
when :toml
|
||||
return [parse_toml(content, full_path), nil]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -86,6 +89,11 @@ module Middleman
|
|||
parse_json("{#{match[:frontmatter]}}", full_path),
|
||||
match[:additional_content]
|
||||
]
|
||||
when *frontmatter_delims[:toml]
|
||||
[
|
||||
parse_toml(match[:frontmatter], full_path),
|
||||
match[:additional_content]
|
||||
]
|
||||
else
|
||||
[
|
||||
{},
|
||||
|
@ -129,6 +137,26 @@ module Middleman
|
|||
end
|
||||
memoize :parse_yaml
|
||||
|
||||
# Parse TOML frontmatter out of a string
|
||||
# @param [String] content
|
||||
# @return [Hash]
|
||||
Contract String, Pathname => Hash
|
||||
def parse_toml(content, full_path)
|
||||
c = begin
|
||||
::Middleman::Util.instrument 'parse.toml' do
|
||||
::TOML.load(content)
|
||||
end
|
||||
rescue StandardError
|
||||
# TOML parser swallows useful error, so we can't warn about it.
|
||||
# https://github.com/jm/toml/issues/47
|
||||
warn "TOML Exception parsing #{full_path}"
|
||||
{}
|
||||
end
|
||||
|
||||
c ? symbolize_recursive(c) : {}
|
||||
end
|
||||
memoize :parse_yaml
|
||||
|
||||
# Parse JSON frontmatter out of a string
|
||||
# @param [String] content
|
||||
# @return [Hash]
|
||||
|
|
|
@ -26,6 +26,7 @@ Gem::Specification.new do |s|
|
|||
s.add_dependency('servolux')
|
||||
s.add_dependency('dotenv')
|
||||
s.add_dependency('rgl', ['~> 0.5.3'])
|
||||
s.add_dependency('toml')
|
||||
|
||||
# Helpers
|
||||
s.add_dependency('activesupport', ['>= 5.0.0'])
|
||||
|
|
Loading…
Reference in a new issue