silicon 0.2.0
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/.gitignore +16 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +372 -0
- data/Rakefile +6 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/exe/silicon +5 -0
- data/lib/silicon.rb +6 -0
- data/lib/silicon/app.rb +90 -0
- data/lib/silicon/base/handle_errors.rb +16 -0
- data/lib/silicon/chain.rb +69 -0
- data/lib/silicon/chain_factory.rb +39 -0
- data/lib/silicon/config.rb +15 -0
- data/lib/silicon/errors/silicon_error.rb +4 -0
- data/lib/silicon/errors/syntax_error.rb +6 -0
- data/lib/silicon/errors/view_engine_error.rb +6 -0
- data/lib/silicon/extensions/hash.rb +18 -0
- data/lib/silicon/generators/cli.rb +23 -0
- data/lib/silicon/generators/templates/actions/common/handle_errors.rb +2 -0
- data/lib/silicon/generators/templates/actions/welcome.tt +9 -0
- data/lib/silicon/generators/templates/app.rb +4 -0
- data/lib/silicon/generators/templates/app.routes +4 -0
- data/lib/silicon/generators/templates/config.ru +8 -0
- data/lib/silicon/generators/templates/silicon.yml +7 -0
- data/lib/silicon/generators/templates/views/show_welcome.json.jbuilder +1 -0
- data/lib/silicon/loaders/dependency_loader.rb +14 -0
- data/lib/silicon/loaders/template_loader.rb +20 -0
- data/lib/silicon/loaders/type_loader.rb +25 -0
- data/lib/silicon/request.rb +65 -0
- data/lib/silicon/routing/builder.rb +96 -0
- data/lib/silicon/routing/file_reader.rb +27 -0
- data/lib/silicon/routing/match.rb +12 -0
- data/lib/silicon/routing/matcher.rb +40 -0
- data/lib/silicon/routing/parser.rb +25 -0
- data/lib/silicon/routing/route.rb +19 -0
- data/lib/silicon/routing/routing.rb +11 -0
- data/lib/silicon/routing/syntax.rb +28 -0
- data/lib/silicon/routing/syntax/action.rb +30 -0
- data/lib/silicon/routing/syntax/actions.rb +15 -0
- data/lib/silicon/routing/syntax/after_section.rb +19 -0
- data/lib/silicon/routing/syntax/before_section.rb +18 -0
- data/lib/silicon/routing/syntax/catch_section.rb +15 -0
- data/lib/silicon/routing/syntax/command.rb +27 -0
- data/lib/silicon/routing/syntax/commands.rb +7 -0
- data/lib/silicon/routing/syntax/node.rb +47 -0
- data/lib/silicon/routing/syntax/nodes.rb +13 -0
- data/lib/silicon/routing/syntax/primitives/arrow.rb +4 -0
- data/lib/silicon/routing/syntax/primitives/back_arrow.rb +4 -0
- data/lib/silicon/routing/syntax/primitives/eol.rb +4 -0
- data/lib/silicon/routing/syntax/primitives/http_status.rb +13 -0
- data/lib/silicon/routing/syntax/primitives/http_verb.rb +4 -0
- data/lib/silicon/routing/syntax/primitives/indent.rb +4 -0
- data/lib/silicon/routing/syntax/primitives/parameter.rb +4 -0
- data/lib/silicon/routing/syntax/primitives/path.rb +5 -0
- data/lib/silicon/routing/syntax/respond.rb +25 -0
- data/lib/silicon/routing/syntax/route.rb +25 -0
- data/lib/silicon/routing/syntax/sections.rb +19 -0
- data/lib/silicon/routing/syntax/tree_section.rb +11 -0
- data/lib/silicon/routing/syntax/view.rb +7 -0
- data/lib/silicon/routing/syntax_error_interpreter.rb +28 -0
- data/lib/silicon/routing/syntax_grammar.tt +95 -0
- data/lib/silicon/template_registry.rb +17 -0
- data/lib/silicon/version.rb +3 -0
- data/lib/silicon/view_builder.rb +18 -0
- data/lib/silicon/view_builder_registry.rb +21 -0
- data/lib/silicon/view_builders/json.rb +16 -0
- data/lib/silicon/view_factory.rb +21 -0
- data/silicon.gemspec +45 -0
- metadata +272 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
module Syntax
|
2
|
+
class Node < Treetop::Runtime::SyntaxNode
|
3
|
+
attr_accessor :route, :actions, :my_nodes, :parent_node, :level, :before_commands, :after_commands
|
4
|
+
|
5
|
+
def parse(parent_node = nil)
|
6
|
+
@parent_node = parent_node
|
7
|
+
|
8
|
+
elements.each do |element|
|
9
|
+
if element.is_a? Indent
|
10
|
+
@level = element.elements.length
|
11
|
+
end
|
12
|
+
|
13
|
+
if element.is_a? Route
|
14
|
+
@route = element.parse(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
if element.is_a? Actions
|
18
|
+
@actions = element.parse(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
if element.is_a? Nodes
|
22
|
+
@my_nodes = element.parse(self)
|
23
|
+
end
|
24
|
+
|
25
|
+
if element.is_a? BeforeSection
|
26
|
+
@before_commands = element.parse.commands
|
27
|
+
end
|
28
|
+
|
29
|
+
if element.is_a? AfterSection
|
30
|
+
@after_commands = element.parse.commands
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_hash
|
38
|
+
{
|
39
|
+
route: @route.to_hash,
|
40
|
+
actions: @actions,
|
41
|
+
level: @level,
|
42
|
+
before: @before_commands,
|
43
|
+
after: @after_commands
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Syntax
|
2
|
+
class Respond < Treetop::Runtime::SyntaxNode
|
3
|
+
attr_reader :view, :http_status
|
4
|
+
|
5
|
+
def parse
|
6
|
+
if elements.length > 0
|
7
|
+
elements[0].elements[1].elements.each do |element|
|
8
|
+
if element.is_a? View
|
9
|
+
@view = element.parse
|
10
|
+
end
|
11
|
+
|
12
|
+
if element.is_a? HttpStatus
|
13
|
+
@http_status = element.parse
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_hash
|
22
|
+
{view: @view, http_status: @http_status}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Syntax
|
2
|
+
class Route < Treetop::Runtime::SyntaxNode
|
3
|
+
attr_reader :node, :path, :parameter
|
4
|
+
|
5
|
+
def parse(node)
|
6
|
+
@node = node
|
7
|
+
|
8
|
+
elements.each do |element|
|
9
|
+
if element.is_a? Parameter
|
10
|
+
@parameter = element.text_value
|
11
|
+
end
|
12
|
+
|
13
|
+
if element.is_a? Path
|
14
|
+
@path = element.text_value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_hash
|
22
|
+
{path: @path, parameter: @parameter}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Syntax
|
2
|
+
class Sections < Treetop::Runtime::SyntaxNode
|
3
|
+
attr_reader :node, :catch
|
4
|
+
|
5
|
+
def parse
|
6
|
+
elements.each do |element|
|
7
|
+
if element.is_a? Node
|
8
|
+
@node = element.parse
|
9
|
+
end
|
10
|
+
|
11
|
+
if element.is_a? CatchSection
|
12
|
+
@catch = element.parse
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'silicon/errors/syntax_error'
|
2
|
+
|
3
|
+
module Silicon
|
4
|
+
module Routing
|
5
|
+
class SyntaxErrorInterpreter
|
6
|
+
def initialize(syntax_parser)
|
7
|
+
@syntax_parser = syntax_parser
|
8
|
+
end
|
9
|
+
|
10
|
+
def interpret
|
11
|
+
line_num = 1
|
12
|
+
(0..@syntax_parser.max_terminal_failure_index - 1).each {|i|
|
13
|
+
line_num += 1 if @syntax_parser.input[i] == ';'
|
14
|
+
}
|
15
|
+
|
16
|
+
message = "Syntax error in routes definition, line #{line_num}. Expected: "
|
17
|
+
expected = []
|
18
|
+
@syntax_parser.terminal_failures.each do |f|
|
19
|
+
item = f.expected_string
|
20
|
+
.gsub('^', '<space>/<tab>')
|
21
|
+
.gsub(';', '<new line>')
|
22
|
+
expected << item
|
23
|
+
end
|
24
|
+
message + expected.join(', ') + '.'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
grammar Syntax
|
2
|
+
rule sections
|
3
|
+
':receive' eol node catch <Sections>
|
4
|
+
end
|
5
|
+
|
6
|
+
rule before
|
7
|
+
(indent ':before' commands eol+) 0..1 <BeforeSection>
|
8
|
+
end
|
9
|
+
|
10
|
+
rule after
|
11
|
+
(indent ':after' commands eol+) 0..1 <AfterSection>
|
12
|
+
end
|
13
|
+
|
14
|
+
rule catch
|
15
|
+
(':catch' command eol*) 0..1 <CatchSection>
|
16
|
+
end
|
17
|
+
|
18
|
+
rule node
|
19
|
+
indent route before after actions nodes <Node>
|
20
|
+
end
|
21
|
+
|
22
|
+
rule action
|
23
|
+
indent http_verb commands respond eol <Action>
|
24
|
+
end
|
25
|
+
|
26
|
+
rule route
|
27
|
+
(path / parameter) arrow eol <Route>
|
28
|
+
end
|
29
|
+
|
30
|
+
rule path
|
31
|
+
('.' / ('/' [a-z0-9_\-]+)) 1..1 <Path>
|
32
|
+
end
|
33
|
+
|
34
|
+
rule http_verb
|
35
|
+
('GET' / 'POST' / 'PUT' / 'PATCH' / 'DELETE') 1..1 <HttpVerb>
|
36
|
+
end
|
37
|
+
|
38
|
+
rule parameter
|
39
|
+
('$' [a-z0-9_]+) 1..1 <Parameter>
|
40
|
+
end
|
41
|
+
|
42
|
+
rule command
|
43
|
+
(arrow [a-z0-9_]+) 1..1 <Command>
|
44
|
+
end
|
45
|
+
|
46
|
+
rule commands
|
47
|
+
command+ <Commands>
|
48
|
+
end
|
49
|
+
|
50
|
+
rule actions
|
51
|
+
action* <Actions>
|
52
|
+
end
|
53
|
+
|
54
|
+
rule nodes
|
55
|
+
node* <Nodes>
|
56
|
+
end
|
57
|
+
|
58
|
+
rule view
|
59
|
+
(back_arrow [a-z] [a-z0-9_]* ('/' [a-z0-9_]*)*) 0..1 <View>
|
60
|
+
end
|
61
|
+
|
62
|
+
rule respond
|
63
|
+
(arrow (':respond' view http_status)) 0..1 <Respond>
|
64
|
+
end
|
65
|
+
|
66
|
+
rule http_status
|
67
|
+
('=' (
|
68
|
+
'100' / '101' / '102' /
|
69
|
+
'200' / '201' / '202' / '203' / '204' / '205' / '206' / '207' / '208' / '226' /
|
70
|
+
'300' / '301' / '302' / '303' / '304' / '305' / '306' / '307' / '308' /
|
71
|
+
'400' / '401' / '402' / '403' / '404' / '405' / '406' / '407' / '408' /
|
72
|
+
'409' / '410' / '411' / '412' / '413' / '414' / '415' / '416' / '417' / '418' /
|
73
|
+
'421' / '422' / '423' / '424' / '426' / '428' / '429' / '431' / '444' / '449' / '451' /
|
74
|
+
'500' / '501' / '502' / '503' / '504' / '505' / '506' / '507' / '508' /
|
75
|
+
'509' / '510' / '511' / '520' / '521' / '522' / '523' / '524' / '525' / '526'
|
76
|
+
) 1..1) 0..1
|
77
|
+
<HttpStatus>
|
78
|
+
end
|
79
|
+
|
80
|
+
rule arrow
|
81
|
+
('*>' / '=>' / '=*') 1..1 <Arrow>
|
82
|
+
end
|
83
|
+
|
84
|
+
rule back_arrow
|
85
|
+
'<*' <BackArrow>
|
86
|
+
end
|
87
|
+
|
88
|
+
rule eol
|
89
|
+
';'+ <Eol>
|
90
|
+
end
|
91
|
+
|
92
|
+
rule indent
|
93
|
+
'^'+ <Indent>
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Silicon
|
2
|
+
class TemplateRegistry
|
3
|
+
def initialize(template_loader, silicon_config)
|
4
|
+
@templates = template_loader.load_templates
|
5
|
+
@config = silicon_config
|
6
|
+
end
|
7
|
+
|
8
|
+
def get(name, type)
|
9
|
+
directory = @config[:path][:views]
|
10
|
+
template_path = File.join(directory, name + ".#{type}")
|
11
|
+
match = @templates.keys.find{|k| k.include? template_path}
|
12
|
+
raise Silicon::SiliconError, "View #{name} of type #{type} not found" if match.nil?
|
13
|
+
|
14
|
+
@templates[match]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Silicon
|
2
|
+
class ViewBuilder
|
3
|
+
def initialize(template, container)
|
4
|
+
@template = template
|
5
|
+
@container = container
|
6
|
+
@variables = template.scan(/@[a-z_][a-zA-Z_0-9]*/).uniq
|
7
|
+
end
|
8
|
+
|
9
|
+
def process
|
10
|
+
@variables.each do |variable|
|
11
|
+
value = @container.resolve(variable.sub('@', '').to_sym)
|
12
|
+
instance_variable_set variable, value
|
13
|
+
end
|
14
|
+
|
15
|
+
build
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'silicon/view_builder'
|
2
|
+
|
3
|
+
module Silicon
|
4
|
+
class ViewBuilderRegistry
|
5
|
+
def initialize
|
6
|
+
@view_builders = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def add(view_builder, format)
|
10
|
+
unless view_builder < Silicon::ViewBuilder
|
11
|
+
raise Silicon::SiliconError, 'view_builder parameter should be a Silicon::ViewBuilder'
|
12
|
+
end
|
13
|
+
|
14
|
+
@view_builders[format] = view_builder
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(format)
|
18
|
+
@view_builders[format]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'silicon/template_registry'
|
2
|
+
require 'silicon/view_builders/json'
|
3
|
+
require 'silicon/view_builder_registry'
|
4
|
+
|
5
|
+
module Silicon
|
6
|
+
class ViewFactory
|
7
|
+
def initialize(container, template_registry, view_builder_registry)
|
8
|
+
@container = container
|
9
|
+
@template_registry = template_registry
|
10
|
+
@view_builder_registry = view_builder_registry
|
11
|
+
end
|
12
|
+
|
13
|
+
def create(name, content_type)
|
14
|
+
type = content_type.split('/')[1]
|
15
|
+
template = @template_registry.get(name, type)
|
16
|
+
builder = @view_builder_registry.get(type)
|
17
|
+
view = builder.new(template, @container)
|
18
|
+
view.process
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|