1
0
Fork 0
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:
Thomas Reynolds 2020-11-25 18:20:52 -08:00
parent 48f1a0f15e
commit 22f867d0a7
16 changed files with 153 additions and 38 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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"

View file

@ -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"

View file

@ -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 "---"

View file

@ -0,0 +1,7 @@
[titles]
[titles.first]
title = "One"
[titles.second]
title = "Two"

View file

@ -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 %>

View file

@ -0,0 +1,6 @@
+++
layout = false
title = "This is the title"
+++
<h1><%= current_page.data.title %></h1>

View file

@ -3,4 +3,4 @@ layout: false
title: This is the title
---
<h1><%= current_page.data.title %></h1>
<h1><%= current_page.data.title %></h1>

View file

@ -0,0 +1 @@
<h1><%= current_page.data.title %></h1>

View file

@ -0,0 +1,4 @@
+++
layout = false
title = "This is the title"
+++

View file

@ -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)

View file

@ -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

View file

@ -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[--- ---],

View file

@ -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]

View file

@ -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'])