bridgetown-routes 1.0.0.alpha2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7d99af4d6cf66c15ad4ca1da7044ca24142f45dbf6035696573dbb8e5033f8c7
4
+ data.tar.gz: 8418e77c8b4bd9263468149ba6d231d5a51b6922ffe299291374b8abb8e2ba80
5
+ SHA512:
6
+ metadata.gz: 5f0528d922fbf73a90edf3f62fd584f8fba34853337228b2fa16dcb3e2f31a927d0c6e30ebe549a4762aa56f9649812c03d4c9be5b5f9e1597fac4e00d8c25ff
7
+ data.tar.gz: b17f234af39b21ec58721c842eb6f4bbd6294c579f0c4a9cf0884ad0a891aaf873e33b7a01d34efef9abd7d496281dd9ab42a5454ce6648320046ef555e2555d
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ inherit_from: ../.rubocop.yml
3
+
4
+ AllCops:
5
+ Exclude:
6
+ - "*.gemspec"
data/Rakefile ADDED
@@ -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,19 @@
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-routes"
7
+ spec.version = Bridgetown::VERSION
8
+ spec.author = "Bridgetown Team"
9
+ spec.email = "maintainers@bridgetownrb.com"
10
+ spec.summary = "A Bridgetown plugin to add support for file-based Roda backend routes within the source folder."
11
+ spec.homepage = "https://github.com/bridgetownrb/bridgetown/tree/main/bridgetown-routes"
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
+ spec.add_dependency("roda-route_list", ">= 2.1")
19
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Routes
5
+ module CodeBlocks
6
+ class << self
7
+ attr_accessor :blocks
8
+
9
+ def add_route(name, file_code = nil, &block)
10
+ block.instance_variable_set(:@_route_file_code, file_code) if file_code
11
+
12
+ @blocks ||= {}
13
+ @blocks[name] = block
14
+ end
15
+
16
+ # @param name [String]
17
+ def route_defined?(name)
18
+ blocks&.key?(name)
19
+ end
20
+
21
+ def route_block(name)
22
+ blocks[name] if route_defined?(name)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Routes
5
+ module ViewHelpers
6
+ def request
7
+ view.resource&.roda_data&.request
8
+ end
9
+ alias_method :r, :request
10
+
11
+ def response
12
+ view.resource&.roda_data&.response
13
+ end
14
+
15
+ def flash
16
+ view.resource&.roda_data&.flash
17
+ end
18
+
19
+ # def csrf_tag(...)
20
+ # request.scope.csrf_tag(...)
21
+ # end
22
+
23
+ # def csrf_token(...)
24
+ # request.scope.csrf_token(...)
25
+ # end
26
+ end
27
+ end
28
+ end
29
+
30
+ Bridgetown::RubyTemplateView::Helpers.include Bridgetown::Routes::ViewHelpers
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Routes
5
+ module Manifest
6
+ class << self
7
+ def routable_extensions
8
+ %w(rb md serb erb liquid)
9
+ end
10
+
11
+ def generate_manifest # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
12
+ return @route_manifest if @route_manifest && Bridgetown.env.production?
13
+
14
+ routes_dir = File.expand_path("src/_routes", Dir.pwd)
15
+ # @type [Array]
16
+ routes = Dir.glob(routes_dir + "/**/*.{#{routable_extensions.join(",")}}").map do |file|
17
+ if File.basename(file).start_with?("_", ".") ||
18
+ File.basename(file, ".*").end_with?(".test")
19
+ next
20
+ end
21
+
22
+ # @type [String]
23
+ file_slug = file.delete_prefix("#{routes_dir}/").then do |f|
24
+ [File.dirname(f), File.basename(f, ".*")].join("/").delete_prefix("./")
25
+ end.delete_suffix("/index")
26
+ segment_keys = []
27
+ file_slug.gsub!(%r{\[([^/]+)\]}) do |_segment|
28
+ segment_keys << Regexp.last_match(1)
29
+ ":#{Regexp.last_match(1)}"
30
+ end
31
+
32
+ [file, file_slug, segment_keys]
33
+ end.compact
34
+
35
+ routes.sort! do |route_a, route_b|
36
+ # @type [String]
37
+ _, slug_a = route_a
38
+ _, slug_b = route_b
39
+
40
+ weight1 = slug_a.count("/") <=> slug_b.count("/")
41
+ if weight1.zero?
42
+ slug_b.count("/:") <=> slug_a.count("/:")
43
+ else
44
+ weight1
45
+ end
46
+ end.reverse!
47
+
48
+ @route_manifest = routes
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bridgetown
4
+ module Routes
5
+ module RodaRouter
6
+ def self.start!(app) # rubocop:disable Metrics/MethodLength
7
+ r = app.request
8
+ response = app.response
9
+
10
+ Bridgetown::Routes::Manifest.generate_manifest.each do |route|
11
+ file, file_slug, segment_keys = route
12
+
13
+ r.on file_slug do |*segment_values|
14
+ response["X-Bridgetown-SSR"] = "1"
15
+ unless Bridgetown.env.production? &&
16
+ Bridgetown::Routes::CodeBlocks.route_defined?(file_slug)
17
+ eval_route_file file, file_slug, app
18
+ end
19
+
20
+ segment_values.each_with_index do |value, index|
21
+ r.params[segment_keys[index]] ||= value
22
+ end
23
+
24
+ route_block = Bridgetown::Routes::CodeBlocks.route_block(file_slug)
25
+ app.instance_variable_set(
26
+ :@_route_file_code, route_block.instance_variable_get(:@_route_file_code)
27
+ ) # could be nil
28
+ app.instance_exec(&route_block)
29
+ end
30
+ end
31
+
32
+ nil
33
+ end
34
+
35
+ def self.eval_route_file(file, file_slug, app) # rubocop:disable Lint/UnusedMethodArgument
36
+ code = File.read(file)
37
+ code_postmatch = nil
38
+ ruby_content = code.match(Bridgetown::FrontMatterImporter::RUBY_BLOCK)
39
+ if ruby_content
40
+ code = ruby_content[1]
41
+ code_postmatch = ruby_content.post_match
42
+ end
43
+
44
+ code = <<~RUBY
45
+ r = app.request
46
+ Bridgetown::Routes::CodeBlocks.add_route(#{file_slug.inspect}, #{code_postmatch.inspect}) do
47
+ #{code}
48
+ end
49
+ RUBY
50
+ instance_eval(code, file, -1)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bridgetown-core"
4
+ require "bridgetown-core/version"
5
+
6
+ require_relative "roda/plugins/bridgetown_routes"
7
+
8
+ require_relative "bridgetown-routes/helpers"
9
+
10
+ module Bridgetown
11
+ module Routes
12
+ autoload :CodeBlocks, "bridgetown-routes/code_blocks"
13
+ autoload :Manifest, "bridgetown-routes/manifest"
14
+ autoload :RodaRouter, "bridgetown-routes/roda_router"
15
+
16
+ # rubocop:disable Bridgetown/NoPutsAllowed
17
+ def self.print_roda_routes
18
+ routes = begin
19
+ JSON.parse(File.read("#{Dir.pwd}/.routes.json"))
20
+ rescue StandardError
21
+ []
22
+ end
23
+ puts
24
+ puts "Routes:"
25
+ puts "======="
26
+ if routes.blank?
27
+ puts "No routes found. Have you commented all of your routes?"
28
+ puts "Documentation: https://github.com/jeremyevans/roda-route_list#basic-usage-"
29
+ end
30
+
31
+ routes.each do |route|
32
+ puts [route["methods"]&.join("|") || "GET", route["path"]].compact.join(" ")
33
+ end
34
+ end
35
+ # rubocop:enable Bridgetown/NoPutsAllowed
36
+ end
37
+ end
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "roda/plugins/flash"
4
+
5
+ class Roda
6
+ module RodaPlugins
7
+ module BridgetownRoutes
8
+ def self.load_dependencies(app)
9
+ app.plugin :slash_path_empty # now /hello and /hello/ are both matched
10
+ app.plugin :placeholder_string_matchers
11
+ app.plugin :flash
12
+ app.plugin :route_csrf, check_header: true
13
+ end
14
+
15
+ def self.configure(app, _opts = {})
16
+ return unless app.opts[:bridgetown_site].nil?
17
+
18
+ raise "Roda app failure: the bridgetown_ssr plugin must be registered before" \
19
+ " bridgetown_routes"
20
+ end
21
+
22
+ module InstanceMethods
23
+ def render_with(data: {}) # rubocop:todo Metrics/AbcSize
24
+ path = Kernel.caller_locations(1, 1).first.absolute_path
25
+ source_path = Pathname.new(path).relative_path_from(Bridgetown::Current.site.source)
26
+ code = @_route_file_code
27
+
28
+ unless code.present?
29
+ raise Bridgetown::Errors::FatalException,
30
+ "`render_with' method must be called from a template-based file in `src/_routes'"
31
+ end
32
+
33
+ data = Bridgetown::Model::BuilderOrigin.new("builder://#{source_path}").read do
34
+ data[:_collection_] = Bridgetown::Current.site.collections.pages
35
+ data[:_content_] = code
36
+ data
37
+ end
38
+
39
+ Bridgetown::Model::Base.new(data).to_resource.tap do |resource|
40
+ resource.roda_data[:request] = request
41
+ resource.roda_data[:response] = response
42
+ resource.roda_data[:flash] = nil
43
+ # resource.roda_data[:flash] = flash
44
+ end.read!.transform!.output
45
+ end
46
+
47
+ ruby2_keywords def render(*args, &block)
48
+ view.render(*args, &block)
49
+ end
50
+
51
+ def view(view_class: Bridgetown::ERBView)
52
+ response._fake_resource_view(
53
+ view_class: view_class, request: request, bridgetown_site: bridgetown_site
54
+ )
55
+ end
56
+ end
57
+
58
+ module ResponseMethods
59
+ def _fake_resource_view(view_class:, request:, bridgetown_site:)
60
+ @_fake_resource_views ||= {}
61
+ @_fake_resource_views[view_class] ||= view_class.new(
62
+ # TODO: use a Stuct for better performance...?
63
+ HashWithDotAccess::Hash.new({
64
+ data: {},
65
+ roda_data: {
66
+ request: request,
67
+ response: self,
68
+ flash: nil, # flash,
69
+ },
70
+ site: bridgetown_site,
71
+ })
72
+ )
73
+ end
74
+ end
75
+ end
76
+
77
+ register_plugin :bridgetown_routes, BridgetownRoutes
78
+ end
79
+ end
80
+
81
+ module RodaResourceExtension
82
+ module RubyResource
83
+ def roda_data
84
+ @roda_data ||= HashWithDotAccess::Hash.new
85
+ end
86
+ end
87
+ end
88
+ Bridgetown::Resource.register_extension RodaResourceExtension
89
+
90
+ Roda::RodaPlugins::Flash::FlashHash.class_eval do
91
+ def info
92
+ self["info"]
93
+ end
94
+
95
+ def info=(val)
96
+ self["info"] = val
97
+ end
98
+
99
+ def alert
100
+ self["alert"]
101
+ end
102
+
103
+ def alert=(val)
104
+ self["alert"] = val
105
+ end
106
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bridgetown-routes
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.alpha2
5
+ platform: ruby
6
+ authors:
7
+ - Bridgetown Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-10-16 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: 1.0.0.alpha2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0.alpha2
27
+ - !ruby/object:Gem::Dependency
28
+ name: roda-route_list
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '2.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '2.1'
41
+ description:
42
+ email: maintainers@bridgetownrb.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - ".rubocop.yml"
48
+ - Rakefile
49
+ - bridgetown-routes.gemspec
50
+ - lib/bridgetown-routes.rb
51
+ - lib/bridgetown-routes/code_blocks.rb
52
+ - lib/bridgetown-routes/helpers.rb
53
+ - lib/bridgetown-routes/manifest.rb
54
+ - lib/bridgetown-routes/roda_router.rb
55
+ - lib/roda/plugins/bridgetown_routes.rb
56
+ homepage: https://github.com/bridgetownrb/bridgetown/tree/main/bridgetown-routes
57
+ licenses:
58
+ - MIT
59
+ metadata: {}
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">"
72
+ - !ruby/object:Gem::Version
73
+ version: 1.3.1
74
+ requirements: []
75
+ rubygems_version: 3.1.4
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: A Bridgetown plugin to add support for file-based Roda backend routes within
79
+ the source folder.
80
+ test_files: []