leanweb 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d4e80c5813858b838b39fea56bb96b2fb28f7749d22f02ab04694662a8595d96
4
- data.tar.gz: c2fdc8ebf92d647516db11352e5a6cb7bc36f1489dfabe69c095e7090f1b7970
3
+ metadata.gz: 9c2c8b263119a2bfb7a4a812f4ffeb66bc9444bfc65a5ea0ab99d627d227e307
4
+ data.tar.gz: bbb016308a12268ee78694e378e931c016475ca8cf9ff4264d017f79664911f3
5
5
  SHA512:
6
- metadata.gz: 1bed8458a93a2f0139609f17fe3402f69065182607b6b6664cc0c6d90ab3815f4dca7cd08c165dab17e5448d9c3f7d3c44ef8e1f28468cd3e4c42a66b096c8b8
7
- data.tar.gz: 320c619aedd70c9bd0ed5e698ef456e293d3cf754bbe3ca939a7669b45ad117a371089db15737edf0c5c271ad638b84784e6ee3a730093a82a16843828a1074c
6
+ metadata.gz: 52c6e7bdd02a5c2797d20cd6979574cec8a4d8333ab659f3332fa6b4e3bce906a69f950124453621e12dee38c0c585ac3abace0a8041c54d444524c0a21bbba3
7
+ data.tar.gz: 64ec617d144264edce4922fa2258173f6cc139a20102a9ba4c4290adb6ec06d13be4b5f265af715fdcd82005ae03c66ac447c7dd79bc30dce0c3235d4a4f8e22
data/bin/leanweb CHANGED
@@ -88,6 +88,12 @@ files = [
88
88
  %body
89
89
  %h1 It works!
90
90
  HAML
91
+ }, {
92
+ filename: '.gitignore'
93
+ content: <<~GITIGNORE
94
+ /.bundle
95
+ /public/**/*.html
96
+ GITIGNORE
91
97
  }
92
98
  ]
93
99
 
@@ -28,15 +28,19 @@ class Hawese
28
28
  end
29
29
  ORIGIN = ENV.fetch('HAWESE_ORIGIN')
30
30
 
31
- def payment_methods
32
- uri = URI("#{ENDPOINT}/gateways/payment-methods/purchase")
33
- JSON.parse(Net::HTTP.get(uri))
31
+ def payment_methods(country = '*', currency = nil)
32
+ endpoint = String.new(
33
+ "#{ENDPOINT}/gateways/payment-methods/purchase?country=#{country}"
34
+ )
35
+ endpoint << "&currency=#{currency}" if currency
36
+ uri = URI(endpoint)
37
+ JSON.parse(Net::HTTP.get(uri), symbolize_names: true)
34
38
  end
35
39
 
36
40
  def gateway_schema(gateway, query_params, schema = 'purchase')
37
41
  uri = URI("#{ENDPOINT}/gateways/#{gateway}/schemas/#{schema}")
38
42
  uri.query = URI.encode_www_form(query_params)
39
- JSON.parse(Net::HTTP.get(uri))
43
+ JSON.parse(Net::HTTP.get(uri), symbolize_names: true)
40
44
  end
41
45
 
42
46
  def purchase(gateway, fields)
@@ -48,15 +52,25 @@ class Hawese
48
52
  fields.to_json,
49
53
  'Content-Type' => 'application/json'
50
54
  )
51
- JSON.parse(response.body)
55
+ JSON.parse(response.body, symbolize_names: true)
52
56
  end
53
57
 
54
58
  def purchase_from_schema(gateway, schema)
55
59
  fields = {}
56
- schema['properties'].each do |property, contents|
57
- fields[property] = contents['default'] if contents.include?('default')
60
+ schema[:properties].each do |property, contents|
61
+ fields[property] = contents[:default] if contents.include?(:default)
58
62
  end
59
63
  purchase(gateway, fields)
60
64
  end
65
+
66
+ def payment(uuid)
67
+ uri = URI("#{ENDPOINT}/payments/#{uuid}")
68
+ Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
69
+ req = Net::HTTP::Get.new(uri)
70
+ req['Authorization'] = "Bearer #{ENV.fetch('HAWESE_AUTH_TOKEN')}"
71
+ response = http.request(req)
72
+ JSON.parse(response.body, symbolize_names: true)
73
+ end
74
+ end
61
75
  end
62
76
  end
@@ -12,7 +12,7 @@ module LeanWeb
12
12
  module ControllerMixins
13
13
  # {render_with_layout} for {Controller} with ERB, HAML, Tilt::EmacsOrg and
14
14
  # Redcarpet Markdown support.
15
- module RenderWithLayout
15
+ module RenderWithLayout # rubocop:disable Metrics/ModuleLength
16
16
  # Render a response with a layout.
17
17
  #
18
18
  # Depending on the `path` file contents and options `@content_for` might
@@ -43,15 +43,21 @@ module LeanWeb
43
43
  head: nil,
44
44
  layout: 'layout.haml',
45
45
  sub_layout: nil,
46
- options: {},
46
+ options: nil,
47
47
  &block
48
48
  )
49
49
  @content_for[:title] = title unless title.nil?
50
50
  content = render_by_extension(path, sub_layout, options, &block)
51
- prepare_head(head) unless head.nil?
51
+ prepare_head(**head) unless head.nil?
52
52
  render_response(layout, 'text/html'){ content }
53
53
  end
54
54
 
55
+ # Render response for missing static action methods. Called from
56
+ # {Route#respond}.
57
+ def default_static_action(view_path)
58
+ render_with_layout(view_path)
59
+ end
60
+
55
61
  protected
56
62
 
57
63
  # @param path [String]
@@ -60,8 +66,8 @@ module LeanWeb
60
66
  # @option options [String] :setupfile can be absolute or relative to
61
67
  # {VIEW_PATH}.
62
68
  def render_org(path, layout: nil, options: {})
63
- options[:setupfile] = "#{VIEW_PATH}/#{options[:setupfile]}" \
64
- if options.include?(:setupfile) && options[:setupfile][0] != '/'
69
+ options[:setupfile] = absolute_view_path(options[:setupfile]) \
70
+ if options.include?(:setupfile)
65
71
 
66
72
  org_template = create_template(path, options)
67
73
 
@@ -83,6 +89,10 @@ module LeanWeb
83
89
  def render_markdown(path, layout: nil, options: {})
84
90
  maybe_render_markdown_toc!(path, options)
85
91
  markdown_template = create_template(path, options)
92
+
93
+ @content_for[:title] = find_title('md', path) \
94
+ unless @content_for.include?(:title)
95
+
86
96
  if layout
87
97
  create_template(layout).render(self){ markdown_template.render(self) }
88
98
  else
@@ -104,6 +114,23 @@ module LeanWeb
104
114
  options[:with_toc_data] = true
105
115
  end
106
116
 
117
+ def find_title(ext, path)
118
+ regex = find_title_ext_regex(ext)
119
+ title = nil
120
+ File.foreach(absolute_view_path(path)) do |line|
121
+ matches = line.match(regex)
122
+ (title = matches[1]) && break if matches
123
+ end
124
+ title
125
+ end
126
+
127
+ def find_title_ext_regex(ext)
128
+ case ext
129
+ when 'md' then /#(?!#)\s?(.+)/
130
+ when 'haml' then /%h1[^\s]*\s(.+)/
131
+ end
132
+ end
133
+
107
134
  # @param path [String]
108
135
  # @param layout [String]
109
136
  # @param options [Hash] Check `Haml` options.
@@ -119,16 +146,24 @@ module LeanWeb
119
146
  end
120
147
  end
121
148
 
149
+ # rubocop:disable Metrics/MethodLength
122
150
  def render_by_extension(path, layout, options, &block)
123
- case File.extname(path)
124
- when '.org'
125
- render_org(path, layout: layout, options: options)
126
- when '.md'
127
- render_markdown(path, layout: layout, options: options)
128
- else
129
- render_other(path, layout: layout, options: options, &block)
151
+ ext = File.extname(path)[1..]
152
+ options = options || template_defaults[ext] || {}
153
+
154
+ case ext
155
+ when 'org'
156
+ return render_org(path, layout: layout, options: options)
157
+ when 'md'
158
+ return render_markdown(path, layout: layout, options: options)
159
+ when 'haml'
160
+ @content_for[:title] = find_title('haml', path) \
161
+ unless @content_for.include?(:title)
130
162
  end
163
+
164
+ render_other(path, layout: layout, options: options, &block)
131
165
  end
166
+ # rubocop:enable Metrics/MethodLength
132
167
 
133
168
  def prepare_head(js: nil, jsm: nil, css: nil, raw: nil)
134
169
  head = String.new
@@ -59,6 +59,12 @@ module LeanWeb
59
59
  Tilt[ext].new(path, 1, options || template_defaults[ext] || {})
60
60
  end
61
61
 
62
+ # Render response for missing static action methods. Called from
63
+ # {Route#respond}.
64
+ def default_static_action(view_path)
65
+ render_response(view_path)
66
+ end
67
+
62
68
  # Relative route to path from public directory considering current route.
63
69
  #
64
70
  # @param path [String] path from public directory, never begins with `/`.
@@ -70,9 +76,28 @@ module LeanWeb
70
76
  @base_url + path
71
77
  end
72
78
 
79
+ # Get absolute path for a file within {VIEW_PATH}.
80
+ # @param path [String] Can be:
81
+ # - A full path, starts with `/`.
82
+ # - A path relative to {VIEW_PATH}.
83
+ # - A path relative to current @route.path directory, starts with `./`.
84
+ # @return [String] Absolute path.
85
+ def absolute_view_path(path)
86
+ return path if path.start_with?('/')
87
+
88
+ view_path = String.new(LeanWeb::VIEW_PATH)
89
+
90
+ if path.start_with?('./')
91
+ view_path << @route.path.sub(%r{/[^/]*$}, '')
92
+ path = path[2..]
93
+ end
94
+
95
+ path == '' ? view_path : "#{view_path}/#{path}"
96
+ end
97
+
73
98
  # Request params.
74
99
  def params
75
- @request.params
100
+ @request&.params
76
101
  end
77
102
 
78
103
  protected
@@ -81,11 +106,5 @@ module LeanWeb
81
106
  def template_defaults
82
107
  {}
83
108
  end
84
-
85
- # @param path [String]
86
- # @return [String] Full path.
87
- def absolute_view_path(path)
88
- path[0] == '/' ? path : "#{LeanWeb::VIEW_PATH}/#{path}"
89
- end
90
109
  end
91
110
  end
data/lib/leanweb/route.rb CHANGED
@@ -63,12 +63,20 @@ module LeanWeb
63
63
  str_path[-1] == '/' ? 'index' : File.basename(str_path)
64
64
  end
65
65
 
66
+ # Respond with a proc, controller method, or in case of true static routes
67
+ # a rendering of {VIEW_PATH}/{path} with any file extension.
68
+ #
66
69
  # @param request [Rack::Request]
67
70
  # @return [Array] a valid rack response.
68
71
  def respond(request)
69
72
  return respond_proc(request) if @action.instance_of?(Proc)
70
73
 
71
74
  respond_method(request)
75
+ rescue NoMethodError
76
+ raise unless @static == true && (view_path = guess_view_path)
77
+
78
+ controller = default_controller_class.new(self)
79
+ controller.default_static_action(view_path)
72
80
  end
73
81
 
74
82
  # String path, independent if {#path} is Regexp or String.
@@ -141,7 +149,14 @@ module LeanWeb
141
149
  end
142
150
 
143
151
  def default_action_action
144
- "#{path_basename.gsub('-', '_')}_#{@method.downcase}".to_sym
152
+ "#{path_basename.gsub(/[.-]/, '_')}_#{@method.downcase}".to_sym
153
+ end
154
+
155
+ def default_controller_class
156
+ require_relative("#{CONTROLLER_PATH}/#{DEFAULT_CONTROLLER.to_s.snakeize}")
157
+ Object.const_get(DEFAULT_CONTROLLER)
158
+ rescue LoadError
159
+ Controller
145
160
  end
146
161
 
147
162
  # @param request [Rack::Request]
@@ -160,8 +175,7 @@ module LeanWeb
160
175
  # @return [Array] a valid Rack response.
161
176
  def respond_proc(request)
162
177
  params = action_params(request.path)
163
- require_relative("#{CONTROLLER_PATH}/#{DEFAULT_CONTROLLER.to_s.snakeize}")
164
- controller = Object.const_get(DEFAULT_CONTROLLER).new(self, request)
178
+ controller = default_controller_class.new(self, request)
165
179
  return controller.instance_exec(**params, &@action) \
166
180
  if params.instance_of?(Hash)
167
181
 
@@ -188,7 +202,7 @@ module LeanWeb
188
202
  def output_path(path, content_type)
189
203
  out_path =
190
204
  if path[-1] == '/'
191
- String.new("#{PUBLIC_PATH}#{path}/index")
205
+ String.new("#{PUBLIC_PATH}#{path}index")
192
206
  else
193
207
  String.new("#{PUBLIC_PATH}#{path}")
194
208
  end
@@ -199,5 +213,15 @@ module LeanWeb
199
213
 
200
214
  out_path
201
215
  end
216
+
217
+ def guess_view_path
218
+ return if @path.instance_of?(Regexp)
219
+
220
+ view_path = String.new("#{LeanWeb::VIEW_PATH}#{@path}")
221
+ view_path << 'index' if @path[-1] == '/' # add index if is index
222
+ view_path.sub!(%r{\.[^/]+$}, '') # drop static file extension if set
223
+
224
+ Dir["#{view_path}.*"].first # return first file match or nil
225
+ end
202
226
  end
203
227
  end
@@ -9,5 +9,5 @@
9
9
 
10
10
 
11
11
  module LeanWeb
12
- VERSION = '0.3.0'
12
+ VERSION = '0.4.0'
13
13
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: leanweb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Freeman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-14 00:00:00.000000000 Z
11
+ date: 2022-11-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -222,7 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
222
222
  - !ruby/object:Gem::Version
223
223
  version: '0'
224
224
  requirements: []
225
- rubygems_version: 3.3.21
225
+ rubygems_version: 3.3.23
226
226
  signing_key:
227
227
  specification_version: 4
228
228
  summary: LeanWeb is a minimal hybrid static / dynamic web framework