Skip to content

Commit

Permalink
add_resource DSL now available for builders (#419)
Browse files Browse the repository at this point in the history
* `add_resource` DSL now available for builders

* get ready to merge
  • Loading branch information
jaredcwhite authored Oct 16, 2021
1 parent c1f56db commit 65b8f4b
Show file tree
Hide file tree
Showing 7 changed files with 182 additions and 14 deletions.
42 changes: 42 additions & 0 deletions bridgetown-builder/lib/bridgetown-builder/dsl/resources.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

module Bridgetown
module Builders
module DSL
module Resources
def add_resource(collection_name, path, &block)
data = Bridgetown::Utils::RubyFrontMatter.new(scope: self).tap do |fm|
fm.define_singleton_method(:___) do |hsh|
hsh.each do |k, v|
fm.set k, v
end
end
fm.instance_exec(&block)
end.to_h
if data[:content]
data[:_content_] = data[:content]
data.delete :content
end

collection_name = collection_name.to_s
unless @site.collections[collection_name]
Bridgetown.logger.info(
"#{self.class.name}:",
"Creating `#{collection_name}' collection on the fly..."
)
collection = Collection.new(@site, collection_name)
collection.metadata["output"] = true
@site.collections[collection_name] = collection
end

Bridgetown::Model::Base.build(
self,
collection_name,
path,
data
).as_resource_in_collection
end
end
end
end
end
7 changes: 5 additions & 2 deletions bridgetown-builder/lib/bridgetown-builder/plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require "bridgetown-builder/dsl/hooks"
require "bridgetown-builder/dsl/http"
require "bridgetown-builder/dsl/liquid"
require "bridgetown-builder/dsl/resources"
module Bridgetown
module Builders
class PluginBuilder
Expand All @@ -13,6 +14,7 @@ class PluginBuilder
include DSL::Hooks
include DSL::HTTP
include DSL::Liquid
include DSL::Resources

attr_accessor :functions, :name, :site, :config

Expand All @@ -34,8 +36,9 @@ def inspect
"#{name} (Hook)"
end

def doc(path, &block)
DocumentsGenerator.add(path, block)
def doc(*)
raise Bridgetown::Errors::FatalException,
"The `doc' method has been removed. Please use the `new_resource' builder DSL instead"
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion bridgetown-builder/test/test_helpers_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class TestHelpers < BridgetownUnitTest
Bridgetown.sites.clear
@site = Site.new(site_configuration)
@builder = HelpersBuilder.new("HelpersBuilder", @site)
@resource = Bridgetown::Model::Base.build(:posts, "im-a-post.md", {
@resource = Bridgetown::Model::Base.build(self, :posts, "im-a-post.md", {
title: "I'm a post!",
date: "2019-05-01",
}).as_resource_in_collection
Expand Down
107 changes: 107 additions & 0 deletions bridgetown-builder/test/test_resources_dsl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# frozen_string_literal: true

require "helper"

class TestResources < BridgetownUnitTest
include Bridgetown::Builders::DSL::Resources

class Inner
include Bridgetown::Builders::DSL::Resources

def initialize
@site = Bridgetown::Current.site
end

def self.resource_data_for_id(id)
{ title: "After a while, crocodile!" } if id == "builder://TestResources.Inner/later.html"
end
end

def method_value
"Resolved!"
end

context "creating a new resource" do
setup do
Bridgetown.sites.clear
@site = Site.new(site_configuration)
end

should "support content" do
add_resource :posts, "im-a-markdown-post.md" do
title "I'm a Markdown post!"
resolve_me from: -> { method_value }
delayed -> { 123 }
nested do
val 456
end
content <<~MARKDOWN
# Hello World!
MARKDOWN
end

resource = @site.collections.posts.resources.first
assert_equal 1, @site.collections.posts.resources.length
assert_equal "builder://TestResources/im-a-markdown-post.md", resource.id
assert_equal "I'm a Markdown post!", resource.data.title
assert_equal "Resolved!", resource.model.resolve_me
refute_equal 123, resource.model.delayed
assert_equal 123, resource.data.delayed
assert_equal 456, resource.data.nested.val
assert_equal "# Hello World!", resource.content.strip
resource.transform!
assert_equal %(<h1 id="hello-world">Hello World!</h1>), resource.output.strip
end

should "support recreating data later" do
resource = Inner.new.add_resource :page, "later.html" do
title "Later, alligator!"
end

assert_equal "builder://TestResources.Inner/later.html", resource.id
new_model = Bridgetown::Model::Base.find(resource.id)

assert_equal "After a while, crocodile!", new_model.title
end

should "support front matter hashes" do
add_resource :pages, "/generated/doc.md" do
___({ "external" => { "data" => [1, 2, 3] } })
end

assert_equal 1, @site.collections.pages.resources.length
assert_equal [1, 2, 3], @site.collections.pages.resources.first.data[:external][:data]
assert_includes @site.collections.pages.resources.first.destination.output_path, "/dest/generated/doc/index.html"
end

should "place it in a new collection" do
build_output = capture_output do
add_resource :tutorials, "learn-stuff.md", &(proc {})
end

assert_includes build_output, "TestResources: Creating `tutorials' collection on the fly..."
assert_equal 1, @site.collections[:tutorials].resources.length
assert @site.collections[:tutorials].resources.first.write?
assert_includes @site.collections[:tutorials].resources.first.destination.output_path, "/dest/tutorials/learn-stuff/index.html"
end

should "support standard filenames" do
@site.config[:collections][:posts][:permalink] = "/:categories/:year/:slug/"
add_resource :posts, "im-a-post.md" do
title "I'm a post!"
date "2019-05-01"
end

assert_includes @site.collections.posts.resources.first.destination.output_path, "/dest/2019/im-a-post/index.html"
end

should "support date-based filenames" do
@site.config[:collections][:posts][:permalink] = "/:categories/:year/:slug/"
add_resource :posts, "2018-05-01-im-an-old-post.md" do
title "I'm a post!"
end

assert_includes @site.collections.posts.resources.first.destination.output_path, "/dest/2018/im-an-old-post/index.html"
end
end
end
6 changes: 4 additions & 2 deletions bridgetown-core/lib/bridgetown-core/model/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ def self.origin_for_id(id)
end

class << self
def build(collection_name, path, data)
data = Bridgetown::Model::BuilderOrigin.new("builder://#{path}").read do
def build(builder, collection_name, path, data)
data = Bridgetown::Model::BuilderOrigin.new(
Bridgetown::Model::BuilderOrigin.id_for_builder_path(builder, path)
).read do
data[:_collection_] = Bridgetown::Current.site.collections[collection_name]
data
end
Expand Down
30 changes: 22 additions & 8 deletions bridgetown-core/lib/bridgetown-core/model/builder_origin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,21 @@ def self.handle_scheme?(scheme)
scheme == "builder"
end

def self.id_for_builder_path(builder, path)
"builder://#{builder.class.name.gsub("::", ".")}/#{path}"
end

def initialize(id)
self.id = id
@relative_path = Pathname.new(id.delete_prefix("builder://"))
@relative_path = Pathname.new(url.path.delete_prefix("/"))
end

def url
@url ||= URI.parse(id)
end

def read
@data = if block_given?
yield
elsif defined?(SiteBuilder) && SiteBuilder.respond_to?(:data_for_id)
SiteBuilder.data_for_id(id)
else
raise "No builder exists which can read #{id}"
end
@data = block_given? ? yield : read_data_from_builder
@data[:_id_] = id
@data[:_origin_] = self
@relative_path = Pathname.new(@data[:_relative_path_]) if @data[:_relative_path_]
Expand All @@ -33,6 +35,18 @@ def read
def exists?
false
end

def read_data_from_builder
builder = Kernel.const_get(url.host.gsub(".", "::"))
raise NameError unless builder.respond_to?(:resource_data_for_id)

builder.resource_data_for_id(id)
rescue NameError
raise(
Bridgetown::Errors::FatalException,
"Builder not found which can read #{id}"
)
end
end
end
end
2 changes: 1 addition & 1 deletion bridgetown-core/lib/bridgetown-core/model/repo_origin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def read
end

def url
@url = URI.parse(id)
@url ||= URI.parse(id)
end

def relative_path
Expand Down

0 comments on commit 65b8f4b

Please sign in to comment.