bridgetown-builder 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d55403ba9988ba7ef4f805e8f46f9bb1f3b6f5bf5571ba442372938fe11c3b7e
4
+ data.tar.gz: faf5ad6c2a5767522c00bf4618a8e3ff330f3b393cff018059e6fbf8bada5022
5
+ SHA512:
6
+ metadata.gz: 286318aa0554d4e905bbea42ba651f0293378dfc3c0c0ae978b54428d62dcae1aa1fc3e07e58221e5b2a91609c0c0b4b58845d0428ecabdc1e60733f3f504278
7
+ data.tar.gz: cdb633657736552e5a7a1691019dca4788895fa8b148c4ab52ba45b7d93d621e72b8a82950a8cad75ee86d7eb70f42876788576dfd473ee91232fd36745c59bc
@@ -0,0 +1,17 @@
1
+ ---
2
+ inherit_from: ../.rubocop.yml
3
+
4
+ AllCops:
5
+ Include:
6
+ - lib/**/*.rb
7
+ - spec/**/*.rb
8
+
9
+ Metrics/AbcSize:
10
+ Exclude:
11
+ - lib/bridgetown-builder/dsl/*
12
+ Metrics/MethodLength:
13
+ Exclude:
14
+ - lib/bridgetown-builder/dsl/*
15
+ Metrics/ParameterLists:
16
+ Exclude:
17
+ - lib/bridgetown-builder/dsl/hooks.rb
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+
5
+ task spec: :test
6
+ require "rake/testtask"
7
+ Rake::TestTask.new(:test) do |test|
8
+ test.libs << "lib" << "test"
9
+ test.pattern = "test/**/test_*.rb"
10
+ test.verbose = true
11
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../bridgetown-core/lib/bridgetown-core/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "bridgetown-builder"
7
+ spec.version = Bridgetown::VERSION
8
+ spec.author = "Bridgetown Team"
9
+ spec.email = "maintainers@bridgetownrb.com"
10
+ spec.summary = "A Bridgetown plugin to provide a sophisticated DSL for writing plugins at a higher level of abstraction."
11
+ spec.homepage = "https://github.com/bridgetownrb/bridgetown/tree/master/bridgetown-builder"
12
+ spec.license = "MIT"
13
+
14
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r!^(test|script|spec|features)/!) }
15
+ spec.require_paths = ["lib"]
16
+
17
+ spec.add_dependency("bridgetown-core", Bridgetown::VERSION)
18
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bridgetown-core"
4
+ require "bridgetown-core/version"
5
+
6
+ module Bridgetown
7
+ module Builders
8
+ autoload :PluginBuilder, "bridgetown-builder/plugin"
9
+ autoload :DocumentBuilder, "bridgetown-builder/document"
10
+ autoload :DocumentsGenerator, "bridgetown-builder/documents_generator"
11
+ end
12
+
13
+ autoload :Builder, "bridgetown-builder/builder"
14
+ end
15
+
16
+ Bridgetown::Hooks.register_one :site, :pre_read, priority: :low, reloadable: false do |site|
17
+ # SiteBuilder is the superclass sites can subclass to create any number of
18
+ # builders, but if the site hasn't defined it explicitly, this is a no-op
19
+ if defined?(SiteBuilder)
20
+ SiteBuilder.descendants.map do |c|
21
+ c.new(c.name, site)
22
+ end
23
+ end
24
+
25
+ # If the documents generator is in use, we need to add it at the top of the
26
+ # list so the site runs the generator before any others
27
+ if Bridgetown::Builders.autoload?(:DocumentsGenerator).nil? &&
28
+ !site.generators.first.is_a?(Bridgetown::Builders::DocumentsGenerator)
29
+ site.generators.unshift Bridgetown::Builders::DocumentsGenerator.new(site.config)
30
+ end
31
+ end
32
+
33
+ Bridgetown::Hooks.register_one :site, :pre_reload, reloadable: false do |site|
34
+ # Remove all anonymous generator classes so they can later get reloaded
35
+ site.converters.delete_if { |generator| generator.class.name.nil? }
36
+ site.generators.delete_if { |generator| generator.class.name.nil? }
37
+
38
+ unless Bridgetown::Builders.autoload? :DocumentsGenerator
39
+ Bridgetown::Builders::DocumentsGenerator.clear_documents_to_generate
40
+ end
41
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ # Superclass for a website's SiteBuilder abstract class
5
+ class Builder < Bridgetown::Builders::PluginBuilder
6
+ class << self
7
+ def register
8
+ Bridgetown::Hooks.register_one :site, :pre_read, reloadable: false do |site|
9
+ new(name, site)
10
+ end
11
+ end
12
+ end
13
+
14
+ # Subclass is expected to implement #build
15
+ def initialize(name, current_site = nil)
16
+ super(name, current_site)
17
+ build
18
+ end
19
+
20
+ def inspect
21
+ name
22
+ end
23
+
24
+ def self.inherited(const)
25
+ (@children ||= Set.new).add const
26
+ catch_inheritance(const) do |const_|
27
+ catch_inheritance(const_)
28
+ end
29
+ end
30
+
31
+ def self.catch_inheritance(const)
32
+ const.define_singleton_method :inherited do |const_|
33
+ (@children ||= Set.new).add const_
34
+ yield const_ if block_given?
35
+ end
36
+ end
37
+
38
+ def self.descendants
39
+ @children ||= Set.new
40
+ out = @children.map(&:descendants)
41
+ out << self unless ["SiteBuilder", "Bridgetown::Builder"].include?(name)
42
+ Set.new(out).flatten
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Builders
5
+ class DocumentBuilder
6
+ attr_reader :site
7
+
8
+ def initialize(site, path)
9
+ @site = site
10
+ @path = path
11
+ @data = ActiveSupport::HashWithIndifferentAccess.new
12
+ end
13
+
14
+ def front_matter(data)
15
+ @data.merge!(data)
16
+ end
17
+
18
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
19
+ def _add_document_to_site
20
+ @collection = (@data[:collection] || :posts).to_s
21
+ collection = @site.collections[@collection]
22
+ unless collection
23
+ collection = Collection.new(@site, @collection)
24
+ collection.metadata["output"] = true
25
+ @site.collections[@collection] = collection
26
+ end
27
+
28
+ doc = Document.new(
29
+ File.join(collection.directory, @path),
30
+ site: @site,
31
+ collection: collection
32
+ )
33
+ doc.send(:merge_defaults)
34
+ doc.content = @data[:content]
35
+ @data.delete(:content)
36
+
37
+ if @path.start_with?("/")
38
+ pathname = Pathname.new(@path)
39
+ @data[:permalink] = File.join(
40
+ pathname.dirname,
41
+ pathname.basename.sub(pathname.extname, "")
42
+ ) + "/"
43
+ end
44
+
45
+ doc.merge_data!(@data)
46
+ doc.send(:read_post_data)
47
+
48
+ collection.docs << doc
49
+ end
50
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
51
+
52
+ # rubocop:disable Style/MissingRespondToMissing
53
+ def method_missing(key, value = nil)
54
+ if respond_to?(key)
55
+ super
56
+ else
57
+ @data[key] = value
58
+ end
59
+ end
60
+ # rubocop:enable Style/MissingRespondToMissing
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Builders
5
+ class DocumentsGenerator < Bridgetown::Generator
6
+ priority :high
7
+
8
+ def self.add(path, block)
9
+ @documents_to_generate ||= []
10
+ @documents_to_generate << [path, block]
11
+ end
12
+
13
+ class << self
14
+ attr_reader :documents_to_generate
15
+ end
16
+
17
+ def self.clear_documents_to_generate
18
+ @documents_to_generate = []
19
+ end
20
+
21
+ def generate(site)
22
+ self.class.documents_to_generate&.each do |doc_block|
23
+ path, block = doc_block
24
+ doc_builder = DocumentBuilder.new(site, path)
25
+ doc_builder.instance_exec(&block)
26
+ doc_builder._add_document_to_site
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Builders
5
+ module DSL
6
+ module Generators
7
+ def generator(method_name = nil, &block)
8
+ block = method(method_name) if method_name.is_a?(Symbol)
9
+ local_name = name # pull the name method into a local variable
10
+
11
+ new_gen = Class.new(Bridgetown::Generator) do
12
+ define_method(:_builder_block) { block }
13
+ define_singleton_method(:custom_name) { local_name }
14
+
15
+ attr_reader :site
16
+
17
+ def inspect
18
+ "#{self.class.custom_name} (Generator)"
19
+ end
20
+
21
+ def generate(_site)
22
+ _builder_block.call
23
+ end
24
+ end
25
+
26
+ first_low_priority_index = site.generators.find_index { |gen| gen.class.priority == :low }
27
+ site.generators.insert(first_low_priority_index || 0, new_gen.new(site.config))
28
+
29
+ functions << { name: name, generator: new_gen }
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Builders
5
+ module DSL
6
+ module Hooks
7
+ def hook(
8
+ owner,
9
+ event,
10
+ method_name = nil,
11
+ priority: Bridgetown::Hooks::DEFAULT_PRIORITY,
12
+ &block
13
+ )
14
+ block = method(method_name) if method_name.is_a?(Symbol)
15
+
16
+ hook_block = Bridgetown::Hooks.register_one(owner, event, priority: priority, &block)
17
+ functions << { name: name, hook: [owner, event, priority, hook_block] }
18
+ end
19
+
20
+ def add_data(data_key)
21
+ hook(:site, :post_read) do
22
+ site.data[data_key] = yield
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "faraday_middleware/redirect_limit_reached"
4
+ require "faraday_middleware/response/follow_redirects"
5
+ require "faraday_middleware/response/parse_json"
6
+
7
+ module Bridgetown
8
+ module Builders
9
+ module DSL
10
+ module HTTP
11
+ def get(url, headers: {}, parse_json: true)
12
+ body = begin
13
+ connection(parse_json: parse_json).get(url, headers: headers).body
14
+ rescue Faraday::ParsingError
15
+ Bridgetown.logger.error(
16
+ "Faraday::ParsingError",
17
+ "The response from #{url} did not contain valid JSON"
18
+ )
19
+ nil
20
+ end
21
+ yield body
22
+ end
23
+
24
+ def connection(headers: {}, parse_json: true)
25
+ headers["Content-Type"] = "application/json" if parse_json
26
+
27
+ Faraday.new(headers: headers) do |faraday|
28
+ faraday.use FaradayMiddleware::FollowRedirects
29
+ faraday.use FaradayMiddleware::ParseJson if parse_json
30
+ yield faraday if block_given?
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Builders
5
+ module DSL
6
+ module Liquid
7
+ def liquid_filter(filter_name, method_name = nil, &block)
8
+ block = method(method_name) if method_name.is_a?(Symbol)
9
+
10
+ m = Module.new
11
+ m.send(:define_method, filter_name, &block)
12
+ ::Liquid::Template.register_filter(m)
13
+
14
+ functions << { name: name, filter: m }
15
+ end
16
+
17
+ def liquid_tag(tag_name, method_name = nil, as_block: false, &block)
18
+ block = method(method_name) if method_name.is_a?(Symbol)
19
+ local_name = name # pull the name method into a local variable
20
+
21
+ tag_class = as_block ? ::Liquid::Block : ::Liquid::Tag
22
+ tag = Class.new(tag_class) do
23
+ define_method(:_builder_block) { block }
24
+ define_singleton_method(:custom_name) { local_name }
25
+
26
+ def inspect
27
+ "#{self.class.custom_name} (Liquid Tag)"
28
+ end
29
+
30
+ attr_reader :content, :context
31
+
32
+ def render(context)
33
+ @context = context
34
+ @content = super if is_a?(::Liquid::Block)
35
+ _builder_block.call(@markup.strip, self)
36
+ end
37
+ end
38
+
39
+ ::Liquid::Template.register_tag tag_name, tag
40
+ functions << { name: name, tag: [tag_name, tag] }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bridgetown-builder/dsl/generators"
4
+ require "bridgetown-builder/dsl/hooks"
5
+ require "bridgetown-builder/dsl/http"
6
+ require "bridgetown-builder/dsl/liquid"
7
+ module Bridgetown
8
+ module Builders
9
+ class PluginBuilder
10
+ include DSL::Generators
11
+ include DSL::Hooks
12
+ include DSL::HTTP
13
+ include DSL::Liquid
14
+
15
+ attr_accessor :functions, :name, :site, :config
16
+
17
+ def initialize(name, current_site = nil)
18
+ self.functions = Set.new
19
+ self.name = name
20
+ self.site = current_site || Bridgetown.sites.first
21
+
22
+ self.config = if defined?(self.class::CONFIG_DEFAULTS)
23
+ Bridgetown::Utils.deep_merge_hashes(
24
+ self.class::CONFIG_DEFAULTS.with_indifferent_access, site.config
25
+ )
26
+ else
27
+ site.config
28
+ end
29
+ end
30
+
31
+ def inspect
32
+ "#{name} (Hook)"
33
+ end
34
+
35
+ def doc(path, &block)
36
+ DocumentsGenerator.add(path, block)
37
+ end
38
+ end
39
+ end
40
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bridgetown-builder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.14.0
5
+ platform: ruby
6
+ authors:
7
+ - Bridgetown Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bridgetown-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.14.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.14.0
27
+ description:
28
+ email: maintainers@bridgetownrb.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - ".rubocop.yml"
34
+ - Rakefile
35
+ - bridgetown-builder.gemspec
36
+ - lib/bridgetown-builder.rb
37
+ - lib/bridgetown-builder/builder.rb
38
+ - lib/bridgetown-builder/document.rb
39
+ - lib/bridgetown-builder/documents_generator.rb
40
+ - lib/bridgetown-builder/dsl/generators.rb
41
+ - lib/bridgetown-builder/dsl/hooks.rb
42
+ - lib/bridgetown-builder/dsl/http.rb
43
+ - lib/bridgetown-builder/dsl/liquid.rb
44
+ - lib/bridgetown-builder/plugin.rb
45
+ homepage: https://github.com/bridgetownrb/bridgetown/tree/master/bridgetown-builder
46
+ licenses:
47
+ - MIT
48
+ metadata: {}
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubygems_version: 3.0.6
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: A Bridgetown plugin to provide a sophisticated DSL for writing plugins at
68
+ a higher level of abstraction.
69
+ test_files: []