bridgetown-routes 1.0.0.alpha2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +6 -0
- data/Rakefile +11 -0
- data/bridgetown-routes.gemspec +19 -0
- data/lib/bridgetown-routes/code_blocks.rb +27 -0
- data/lib/bridgetown-routes/helpers.rb +30 -0
- data/lib/bridgetown-routes/manifest.rb +53 -0
- data/lib/bridgetown-routes/roda_router.rb +54 -0
- data/lib/bridgetown-routes.rb +37 -0
- data/lib/roda/plugins/bridgetown_routes.rb +106 -0
- metadata +80 -0
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
data/Rakefile
ADDED
@@ -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: []
|