sho 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +150 -0
- data/lib/sho/argument_validator.rb +33 -0
- data/lib/sho/configurator.rb +127 -0
- data/lib/sho/version.rb +9 -0
- data/lib/sho.rb +31 -0
- metadata +246 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 125faf4a77feba4430c913006c9a0c594032492c
|
4
|
+
data.tar.gz: 48b7aef74a0acd727c7cfa848fa95f932e22504a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8bf09de4470247c23f2cd1ab956d01996337c8e654337cd53fe20f8331bdab50027dd7c0d46ee0a40edf1baad9dc88bbec8550088f6c3a0293a4754119da5e29
|
7
|
+
data.tar.gz: a4f0689ca99551d70ef474b90d856321fc1894918ac280e9931b48cf57da8e1e46d551fec964b5fbfc689d38f16e6d467e8e93cf4f86c1f40db85ba53d03d626
|
data/README.md
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
# Sho: post-framework view library
|
2
|
+
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/sho.svg)](http://badge.fury.io/rb/sho)
|
4
|
+
[![Build Status](https://travis-ci.org/zverok/sho.svg?branch=master)](https://travis-ci.org/zverok/sho)
|
5
|
+
|
6
|
+
**Sho** is an experimental **post-framework** Ruby view library. It is based on Tilt and meant to provide entire view layer for a web application (based on any framework or completely frameworkless).
|
7
|
+
|
8
|
+
<sup>"Sho?" ("Шо?") is a Kharkiv dialecticism, meaning "What?", typically in a slightly aggressive manner. It is chosen as a library name because it is close to "show" in a written and spoken form (and also because "What?" is expected typical reaction to the library).</sup>
|
9
|
+
|
10
|
+
**Post-framework** means Sho behaves as a decent _library_, neither implying nor forcing _any_ kind of conventions for your code layout and structure.
|
11
|
+
|
12
|
+
Currently, if you want your app architecture not to follow strict framework's _frame_, you can take ROM or Sequel for _data layer_; Sinatra, Roda, or Grape for _routing layer_; but for _view layer_, the situation seems to be different. Typical "views" part of the application (say, with Rails, Hanami, Padrino) is bound to a lot of conventions (like "it will look for the corresponding template in that folders") and global configuration, and tightly coupled with routes/controllers ("if you want data from controller to be passed to view, you mark it so an so").
|
13
|
+
|
14
|
+
**Sho** is an experiment to provide view layer that is "just Ruby" (= follows the regular intuitions of _Ruby_ programmer, not introducing some hidden conventions that are not deductible from the code) and reuses regular Ruby concepts for code sharing, parameters passing and flow structuring instead of introducing its own concepts like "helpers", "exposures", "locals" (completely unlike local variables!) and so on.
|
15
|
+
|
16
|
+
## Basic synopsis
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
# in any class you want
|
20
|
+
include Sho
|
21
|
+
|
22
|
+
sho.template :name, 'path/to/template.erb', :param1, param2: default_value
|
23
|
+
```
|
24
|
+
|
25
|
+
This creates instance method with a signature¹ `YourClass#name(param1:, param2: default_value)`, which, when called, renders the template from `path/to/template.erb`.
|
26
|
+
|
27
|
+
<sup>¹Due to metaprogramming limitations, real signature of method would be `name(**params)` and check of mandatory params and assignment of defaults is performed by Sho.</sup>
|
28
|
+
|
29
|
+
You can think about the template as a _method body_, which immediately answers a lot of questions:
|
30
|
+
|
31
|
+
* **What context the template is evaluated in?** Like any method: in context of the instance of the class, where the method is defined.
|
32
|
+
* **What names are available in the template?** The same as in any methods: parameters, and other methods/variables of the instance.
|
33
|
+
* **How do I do share "helper" code with several templates?** Just in a regular Ruby: extract it to a module, include the module in several classes with views. Or make the base class and inherit from it. Or use any other code sharing technique you are fond of.
|
34
|
+
* **How do I do "partials" (render one template from another)?** The same as when you want to call one method from another one: just call it.
|
35
|
+
```ruby
|
36
|
+
# In `user.rb`
|
37
|
+
sho.template :render, 'user.slim'
|
38
|
+
# That would be "partial":
|
39
|
+
sho.template :status_with_popup, 'user/_status_with_popup.slim'
|
40
|
+
```
|
41
|
+
```slim
|
42
|
+
/ In `user.slim` (think of it as a body for `User#render` method):
|
43
|
+
p
|
44
|
+
span.name = name
|
45
|
+
/ Call of a "partial":
|
46
|
+
span.status = status_with_popup
|
47
|
+
```
|
48
|
+
* **How do I test it? How do I set all the context for testing?** Just as with regular method: just create an instance, and call the method, and test the result.
|
49
|
+
* **But where do I put this method?** Wherever you wish! Sho does NOT insist on any particular architecture or code layout, which means you can experiment and evaluate several options, like:
|
50
|
+
* embed rendering in controller/Sinatra app (or even model, if you want to be really naughty today!) for the very first 30-lines-long prototype, then move it elsewhere (like "Extract Method" refactoring pattern, you know?)
|
51
|
+
* embed rendering in your service (operation) objects, so
|
52
|
+
* make Users::List class with `#html`, `#atom` and `#json` methods and use it like `Users::List.new(scope).send(request.format)` or `User::List.send(request.format, scope)`
|
53
|
+
* make `Trailblazer::Cells`-like one-class-per-template objects to call them like `Users::HtmlList.new(scope).()`
|
54
|
+
* ...switch between several of the approaches, or even combine them in the same app!
|
55
|
+
|
56
|
+
## Implementation details
|
57
|
+
|
58
|
+
**Where should I store the templates?**
|
59
|
+
|
60
|
+
Sho doesn't have any global configuration for "templates folder", neither convention for "templates are in `app/views/<current_class_name>`" or something like that. `template` method just looks for templates relative to current working folder (`Dir.pwd`). As it could be tiresome to write `app/views/blah/blah/blah/blah.slim` for each and every method, there is `sho.base_folder = ` class-level setting:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
# Before
|
64
|
+
sho.template :profile, 'app/views/users/profile.slim'
|
65
|
+
sho.template :icon, 'app/views/users/icon.slim'
|
66
|
+
|
67
|
+
# After
|
68
|
+
sho.base_folder = 'app/views/users'
|
69
|
+
sho.template :profile, 'profile.slim'
|
70
|
+
sho.template :icon, 'icon.slim'
|
71
|
+
|
72
|
+
# If all of your classes and templates are in the same `app/view`, further shortcutting is
|
73
|
+
# your own responsibility, like:
|
74
|
+
|
75
|
+
sho.base_folder = VIEWS_BASE + '/users'
|
76
|
+
```
|
77
|
+
|
78
|
+
Another interesting approach that is made easy by Sho:
|
79
|
+
```ruby
|
80
|
+
# In app/view_models/users.rb
|
81
|
+
|
82
|
+
# It is like require_relative, template should be stored at
|
83
|
+
# app/view_models/users/profile.slim
|
84
|
+
sho.template_relative :profile, 'users/profile.slim'
|
85
|
+
```
|
86
|
+
|
87
|
+
The idea is: as `ViewModels::Users` have `profile.slim` as a `#profile` method body, it is this class' implementation details, so, there is no point to store it in a completely different folder.
|
88
|
+
|
89
|
+
**What about layouts?**
|
90
|
+
|
91
|
+
**Sho** supports concept of layout with `:_layout` param. It accepts method name, and supposes this method will call `yield` at some point:
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
# in app/view_models/users.rb
|
95
|
+
sho.template_relative :list, 'users/list.slim', _layout: :main_layout
|
96
|
+
sho.template :main_layout, 'app/views/main_layout.slim'
|
97
|
+
```
|
98
|
+
|
99
|
+
Sharing of the layout between several classes could be done in the same way as sharing of any other methods: extract it to a common module, and include wherever you like.
|
100
|
+
|
101
|
+
**Small-scale usage of the library**
|
102
|
+
|
103
|
+
As Sho is a _library_, not a framework, it doesn't require you to switch to Sho-only code immediately and completely. You can try it in some parts of your system, or just in one class. One useful idea is to use it in decorators (like [draper](https://github.com/drapergem/draper)), and Sho provides `inline_template` for this kind of usage:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
class RatingDecorator < Draper::Decorator
|
107
|
+
# ...
|
108
|
+
|
109
|
+
# before:
|
110
|
+
def row
|
111
|
+
h.content_tag(:tr,
|
112
|
+
h.safe_join([
|
113
|
+
h.content_tag(:th, "Rated by #{user.name}"),
|
114
|
+
h.content_tag(:td, stars),
|
115
|
+
h.content_tag(:td, rated_at)
|
116
|
+
]),
|
117
|
+
class: 'rating'
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
# after:
|
122
|
+
include Sho
|
123
|
+
|
124
|
+
sho.inline_template :row,
|
125
|
+
slim: <<~SLIM
|
126
|
+
tr.rating
|
127
|
+
th
|
128
|
+
| Rated by
|
129
|
+
= user.name
|
130
|
+
td = stars
|
131
|
+
td = rated_at
|
132
|
+
SLIM
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
**Template caching**
|
137
|
+
|
138
|
+
Sho creates Tilt templates at a moment of the method definition. This seems to lead to most natural behavior: the templates are found and cached at a moment of code loading/reloading (whatever reloader you use).
|
139
|
+
|
140
|
+
## Library status
|
141
|
+
|
142
|
+
It is fresh and experimental. Tested, documented and stuff, but still not extensively used in production. Nothing guaranteed, but I'll be happy to have at least a meaningful discussion started.
|
143
|
+
|
144
|
+
## Author
|
145
|
+
|
146
|
+
[Victor Shepelev aka @zverok](https://zverok.github.io)
|
147
|
+
|
148
|
+
## License
|
149
|
+
|
150
|
+
MIT
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sho
|
4
|
+
# @private
|
5
|
+
class ArgumentValidator
|
6
|
+
def initialize(*mandatory, **optional)
|
7
|
+
mandatory.all? { |m| m.is_a?(Symbol) } or
|
8
|
+
fail ArgumentError, 'Mandatory arguments should be send as array of symbols'
|
9
|
+
@mandatory = mandatory
|
10
|
+
@optional = optional
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(**params)
|
14
|
+
guard_missing!(params)
|
15
|
+
guard_unknown!(params)
|
16
|
+
params.merge(@optional.reject { |key,| params.key?(key) })
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def guard_missing!(**params)
|
22
|
+
(@mandatory - params.keys).tap do |missing|
|
23
|
+
missing.empty? or fail ArgumentError, "missing keywords: #{missing.join(', ')}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def guard_unknown!(**params)
|
28
|
+
(params.keys - @mandatory - @optional.keys).tap do |unknown|
|
29
|
+
unknown.empty? or fail ArgumentError, "unknown keywords: #{unknown.join(', ')}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Sho
|
4
|
+
# rubocop:disable Lint/UnderscorePrefixedVariableName
|
5
|
+
|
6
|
+
# Main Sho object providing rendering method creation API.
|
7
|
+
#
|
8
|
+
# There are three ways to create rendering methods:
|
9
|
+
#
|
10
|
+
# * {#template}: template is looked up relative to main folder, or {#base_folder};
|
11
|
+
# * {#template_relative}: template is looked up relative to current class' folder;
|
12
|
+
# * {#inline_template}: template is provided inline as a Ruby string/heredoc.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# class AnyClass
|
16
|
+
# include Sho
|
17
|
+
#
|
18
|
+
# # `sho` returns an instance of Configurator
|
19
|
+
# sho.template :rendering_method_name, 'path/to/template.slim', :param1, param2: default_value
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
class Configurator
|
23
|
+
# @private
|
24
|
+
attr_reader :host
|
25
|
+
|
26
|
+
# @return [String, nil] folder to look templates at for {#template} method. `nil` by default,
|
27
|
+
# meaning application's current folder (`Dir.pwd`).
|
28
|
+
attr_accessor :base_folder
|
29
|
+
|
30
|
+
# @private
|
31
|
+
def initialize(host)
|
32
|
+
@host = host
|
33
|
+
end
|
34
|
+
|
35
|
+
# Generates instance method named `name` in a host module, which renders template from
|
36
|
+
# `template`.
|
37
|
+
# Instance of the host class is passed as a template scope on rendering.
|
38
|
+
#
|
39
|
+
# Template is looked up relative to application's main folder, or {#base_folder}.
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# # generates method with signature #profile()
|
43
|
+
# sho.template :profile, 'app/views/users/profile.slim'
|
44
|
+
#
|
45
|
+
# # generates method with signature #profile(context:, detailed: false)
|
46
|
+
# # `context` and `detailed` vairables are accessible inside template.
|
47
|
+
# sho.template :profile, 'app/views/users/profile.slim', :context, detailed: false
|
48
|
+
#
|
49
|
+
# @param name [Symbol] name of method to generate;
|
50
|
+
# @param template [String] path to template to render;
|
51
|
+
# @param _layout [Symbol, nil] name of method which provides layout (wraps results of current
|
52
|
+
# method);
|
53
|
+
# @param mandatory [Array<Symbol>] list of mandatory params;
|
54
|
+
# @param optional [Hash{Symbol => Object}] list of optional params and their default values
|
55
|
+
def template(name, template, *mandatory, _layout: nil, **optional)
|
56
|
+
tpl = Tilt.new(File.expand_path(template, base_folder || Dir.pwd))
|
57
|
+
define_template_method(name, tpl, mandatory, optional, _layout)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Like {#template}, but looks up template relative to host module path. Allows to structure
|
61
|
+
# views like:
|
62
|
+
#
|
63
|
+
# ```
|
64
|
+
# app/
|
65
|
+
# +- view_models/
|
66
|
+
# +- users.rb # calls sho.template_relative :profile, 'users/profile.slim'
|
67
|
+
# +- users/
|
68
|
+
# +- profile.slim
|
69
|
+
# ```
|
70
|
+
#
|
71
|
+
# @param name [Symbol] name of method to generate;
|
72
|
+
# @param template [String] path to template to render;
|
73
|
+
# @param _layout [Symbol, nil] name of method which provides layout (wraps results of current
|
74
|
+
# method);
|
75
|
+
# @param mandatory [Array<Symbol>] list of mandatory params;
|
76
|
+
# @param optional [Hash{Symbol => Object}] list of optional params and their default values
|
77
|
+
def template_relative(name, template, *mandatory, _layout: nil, **optional)
|
78
|
+
base = File.dirname(caller(1..1).first.split(':').first)
|
79
|
+
tpl = Tilt.new(File.expand_path(template, base))
|
80
|
+
|
81
|
+
define_template_method(name, tpl, mandatory, optional, _layout)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Inline rendering method definition, useful in decorators and other contexts with small
|
85
|
+
# templates.
|
86
|
+
#
|
87
|
+
# @example
|
88
|
+
# sho.inline_template :badge,
|
89
|
+
# slim: <<~SLIM
|
90
|
+
# span.badge
|
91
|
+
# span.name = user.name
|
92
|
+
# i.role(class: user.role)
|
93
|
+
# SLIM
|
94
|
+
#
|
95
|
+
# @param name [Symbol] name of method to generate;
|
96
|
+
# @param _layout [Symbol, nil] name of method which provides layout (wraps results of current
|
97
|
+
# method);
|
98
|
+
# @param mandatory [Array<Symbol>] list of mandatory params;
|
99
|
+
# @param options [Hash{Symbol => Object}] list of optional params and their default values +
|
100
|
+
# template to render (passed in a key named `slim:` or `erb:` or `haml:`, and so on).
|
101
|
+
def template_inline(name, *mandatory, _layout: nil, **options)
|
102
|
+
kind, template = options.detect { |key,| Tilt.registered?(key.to_s) }
|
103
|
+
template or fail ArgumentError, "No known templates found in #{options.keys}"
|
104
|
+
optional = options.reject { |key,| key == kind }
|
105
|
+
tpl = Tilt.default_mapping[kind].new { template }
|
106
|
+
|
107
|
+
define_template_method(name, tpl, mandatory, optional, _layout)
|
108
|
+
end
|
109
|
+
|
110
|
+
alias inline_template template_inline
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def define_template_method(name, tilt, mandatory, optional, layout)
|
115
|
+
arguments = ArgumentValidator.new(*mandatory, **optional)
|
116
|
+
@host.__send__(:define_method, name) do |**locals|
|
117
|
+
locals = arguments.call(**locals)
|
118
|
+
if layout
|
119
|
+
__send__(layout) { tilt.render(self, **locals) }
|
120
|
+
else
|
121
|
+
tilt.render(self, **locals)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
# rubocop:enable Lint/UnderscorePrefixedVariableName
|
127
|
+
end
|
data/lib/sho/version.rb
ADDED
data/lib/sho.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tilt'
|
4
|
+
|
5
|
+
# Sho is a small, non-framework view library based on Tilt.
|
6
|
+
#
|
7
|
+
# `sho` object in an example below is an instance of {Sho::Configurator}, look at its docs to
|
8
|
+
# understand how to define rendering methods.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# class AnyClass
|
12
|
+
# include Sho
|
13
|
+
#
|
14
|
+
# sho.template :rendering_method_name, 'path/to/template.slim', :param1, param2: default_value
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # with instance of AnyClass:
|
18
|
+
# object.rendering_method_name(param1: 'foo', param2: 'bar') # => template.slim rendered
|
19
|
+
#
|
20
|
+
module Sho
|
21
|
+
# Adds `#sho` method (access to instance of {Sho::Configurator}) to class/module `Sho` is
|
22
|
+
# included into.
|
23
|
+
def self.included(mod)
|
24
|
+
mod.define_singleton_method(:sho) {
|
25
|
+
@__sho_configurator__ ||= Configurator.new(mod)
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
require_relative 'sho/argument_validator'
|
31
|
+
require_relative 'sho/configurator'
|
metadata
ADDED
@@ -0,0 +1,246 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sho
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Victor Shepelev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-06-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: tilt
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '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'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: yard
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: redcarpet
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: github-markup
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: yard-junk
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 3.7.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 3.7.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec-its
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: saharspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: fakefs
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: slim
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rubocop
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: rubocop-rspec
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: rake
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: rubygems-tasks
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
description: |2
|
210
|
+
Post-framework Ruby view library. It is based on Tilt and meant to provide entire
|
211
|
+
view layer for a web application (based on any framework or completely frameworkless).
|
212
|
+
email: zverok.offline@gmail.com
|
213
|
+
executables: []
|
214
|
+
extensions: []
|
215
|
+
extra_rdoc_files: []
|
216
|
+
files:
|
217
|
+
- README.md
|
218
|
+
- lib/sho.rb
|
219
|
+
- lib/sho/argument_validator.rb
|
220
|
+
- lib/sho/configurator.rb
|
221
|
+
- lib/sho/version.rb
|
222
|
+
homepage: https://github.com/zverok/sho
|
223
|
+
licenses:
|
224
|
+
- MIT
|
225
|
+
metadata: {}
|
226
|
+
post_install_message:
|
227
|
+
rdoc_options: []
|
228
|
+
require_paths:
|
229
|
+
- lib
|
230
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
231
|
+
requirements:
|
232
|
+
- - ">="
|
233
|
+
- !ruby/object:Gem::Version
|
234
|
+
version: 2.1.0
|
235
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
236
|
+
requirements:
|
237
|
+
- - ">="
|
238
|
+
- !ruby/object:Gem::Version
|
239
|
+
version: '0'
|
240
|
+
requirements: []
|
241
|
+
rubyforge_project:
|
242
|
+
rubygems_version: 2.6.14
|
243
|
+
signing_key:
|
244
|
+
specification_version: 4
|
245
|
+
summary: Experimental post-framework view library
|
246
|
+
test_files: []
|