opulent 0.0.9 → 1.0.2

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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +9 -0
  3. data/.libold/opulent.rb +96 -0
  4. data/.libold/opulent/context.rb +80 -0
  5. data/.libold/opulent/engine.rb +88 -0
  6. data/.libold/opulent/filter.rb +101 -0
  7. data/.libold/opulent/logger.rb +67 -0
  8. data/.libold/opulent/nodes.rb +13 -0
  9. data/.libold/opulent/nodes/block.rb +29 -0
  10. data/.libold/opulent/nodes/comment.rb +35 -0
  11. data/.libold/opulent/nodes/control.rb +230 -0
  12. data/.libold/opulent/nodes/define.rb +42 -0
  13. data/.libold/opulent/nodes/eval.rb +41 -0
  14. data/.libold/opulent/nodes/expression.rb +28 -0
  15. data/.libold/opulent/nodes/filter.rb +70 -0
  16. data/.libold/opulent/nodes/helper.rb +69 -0
  17. data/.libold/opulent/nodes/node.rb +101 -0
  18. data/.libold/opulent/nodes/root.rb +62 -0
  19. data/.libold/opulent/nodes/text.rb +54 -0
  20. data/.libold/opulent/nodes/theme.rb +36 -0
  21. data/.libold/opulent/parser.rb +252 -0
  22. data/.libold/opulent/parser/block.rb +70 -0
  23. data/.libold/opulent/parser/comment.rb +32 -0
  24. data/.libold/opulent/parser/control.rb +83 -0
  25. data/.libold/opulent/parser/define.rb +39 -0
  26. data/.libold/opulent/parser/eval.rb +33 -0
  27. data/.libold/opulent/parser/expression.rb +350 -0
  28. data/.libold/opulent/parser/filter.rb +41 -0
  29. data/.libold/opulent/parser/node.rb +232 -0
  30. data/.libold/opulent/parser/root.rb +96 -0
  31. data/.libold/opulent/parser/text.rb +114 -0
  32. data/.libold/opulent/parser/theme.rb +36 -0
  33. data/.libold/opulent/preprocessor.rb +102 -0
  34. data/.libold/opulent/runtime.rb +144 -0
  35. data/.libold/opulent/template.rb +43 -0
  36. data/.libold/opulent/tokens.rb +276 -0
  37. data/.libold/opulent/version.rb +5 -0
  38. data/.rspec +2 -0
  39. data/.travis.yml +4 -0
  40. data/Gemfile +2 -0
  41. data/LICENSE +21 -0
  42. data/README.md +102 -0
  43. data/Rakefile +6 -0
  44. data/benchmark/benchmark.rb +46 -0
  45. data/benchmark/cases/node/node.haml +17 -0
  46. data/benchmark/cases/node/node.op +14 -0
  47. data/benchmark/cases/node/node.slim +19 -0
  48. data/bin/console +14 -0
  49. data/bin/setup +7 -0
  50. data/docs/syntax.md +3 -0
  51. data/docs/usage.md +3 -0
  52. data/lib/opulent.rb +11 -64
  53. data/lib/opulent/compiler.rb +132 -0
  54. data/lib/opulent/compiler/block.rb +31 -0
  55. data/lib/opulent/compiler/comment.rb +22 -0
  56. data/lib/opulent/compiler/control.rb +152 -0
  57. data/lib/opulent/compiler/define.rb +88 -0
  58. data/lib/opulent/compiler/eval.rb +15 -0
  59. data/lib/opulent/compiler/filter.rb +54 -0
  60. data/lib/opulent/compiler/node.rb +232 -0
  61. data/lib/opulent/compiler/root.rb +19 -0
  62. data/lib/opulent/compiler/text.rb +60 -0
  63. data/lib/opulent/context.rb +88 -0
  64. data/lib/opulent/engine.rb +60 -0
  65. data/lib/opulent/filters.rb +222 -0
  66. data/lib/opulent/logger.rb +47 -0
  67. data/lib/opulent/parser.rb +196 -0
  68. data/lib/opulent/parser/block.rb +56 -0
  69. data/lib/opulent/parser/comment.rb +27 -0
  70. data/lib/opulent/parser/control.rb +112 -0
  71. data/lib/opulent/parser/define.rb +30 -0
  72. data/lib/opulent/parser/eval.rb +21 -0
  73. data/lib/opulent/parser/expression.rb +344 -0
  74. data/lib/opulent/parser/filter.rb +25 -0
  75. data/lib/opulent/parser/node.rb +246 -0
  76. data/lib/opulent/parser/root.rb +48 -0
  77. data/lib/opulent/parser/text.rb +127 -0
  78. data/lib/opulent/settings.rb +79 -0
  79. data/lib/opulent/template.rb +67 -0
  80. data/lib/opulent/tokens.rb +166 -0
  81. data/lib/opulent/version.rb +4 -0
  82. data/opulent.gemspec +36 -0
  83. metadata +160 -7
@@ -0,0 +1,5 @@
1
+ module Opulent
2
+ # Opulent version string
3
+ # @api public
4
+ VERSION = '0.0.1'
5
+ end
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
4
+ before_install: gem install bundler -v 1.10.5
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Pixevil
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,102 @@
1
+ # Opulent
2
+
3
+ Opulent is an __Intelligent Web Templating Engine__ created for extremly fast, efficient and DRY Web Development. Based on the idea of creating lightweight __Web Component__ definitions, Opulent greatly speeds up the development process of any project.
4
+
5
+ ## Syntax
6
+
7
+ Opulent is as beautiful as it gets: no tags, indentation based, optional brackets, inline text, inline children and in page definitions.
8
+
9
+ __Page Markup__
10
+ ```
11
+ html
12
+ head
13
+ title Opulent is Awesome
14
+ body
15
+ #content
16
+ ul.list-inline
17
+ li > a href="http://opulent.io" Opulent
18
+ li > a href="http://github.com" GitHub
19
+
20
+ footer |
21
+ With Opulent, you can do anything.
22
+ ```
23
+
24
+ __Web Component__
25
+ ```
26
+ def hello(place)
27
+ p Hello #{place}
28
+
29
+ hello place="World"
30
+ ```
31
+
32
+ __Control Structures__
33
+ ```
34
+ ul.navbar
35
+ if @user.logged_in?
36
+ li Hello #{@user.name}
37
+ else
38
+ li > a href=link_to_register Sign Up
39
+ ```
40
+
41
+ __Starting to feel it?__ There's so much more you can do with Opulent.
42
+
43
+ [Read the Documentation](docs/syntax.md)
44
+
45
+
46
+
47
+ ## Installation
48
+
49
+ Install it yourself using the ruby gem:
50
+
51
+ $ gem install opulent
52
+
53
+ ---
54
+
55
+ Or add this line to your application's Gemfile:
56
+
57
+ ```ruby
58
+ gem 'opulent'
59
+ ```
60
+
61
+ And then execute:
62
+
63
+ $ bundle
64
+
65
+
66
+ ## Usage
67
+
68
+ Using Opulent to render a file is as easy as including it in your application and using the render method.
69
+
70
+ [Read the Documentation](docs/usage.md)
71
+
72
+ ```ruby
73
+ require 'opulent'
74
+
75
+ Opulent.new.render_file 'file.op'
76
+ ```
77
+
78
+ <!--
79
+ ## Development
80
+
81
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
82
+
83
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
84
+ -->
85
+
86
+ ## Contributing
87
+
88
+ Bug reports and pull requests are welcome on GitHub at https://github.com/opulent/opulent. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
89
+
90
+ #### Under Development
91
+ Opulent is currently in the Beta Phase. It has serious potential to becoming the next generation of Templating Engines for Ruby, therefore any contribution is more than welcome.
92
+
93
+ It still has development going on the following subjects:
94
+
95
+ * Template amble (preamble, cache, postamble) generation
96
+ * More block yielding tests
97
+ * Multiple page layouts
98
+ * More to come
99
+
100
+ ## License
101
+
102
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,46 @@
1
+ require 'benchmark'
2
+ require_relative '../lib/opulent'
3
+ require 'slim'
4
+ require 'haml'
5
+
6
+ # Choose the benchmark you want to run
7
+ BENCHMARK = :node
8
+
9
+ # How many times each command should be run
10
+ N = 1000
11
+
12
+ # Templating engine initialization
13
+ puts "BENCHMARK"
14
+ case BENCHMARK
15
+ when :node
16
+ case_folder = 'cases/node/'
17
+ opulent = Tilt.new("#{case_folder}node.op")
18
+ slim = Tilt.new("#{case_folder}node.slim")
19
+ haml = Tilt.new("#{case_folder}node.haml")
20
+
21
+ locals = {
22
+ a: 3,
23
+ b: 4,
24
+ c: 5
25
+ }
26
+
27
+ scope = Object.new
28
+
29
+ Benchmark.bm do |x|
30
+ x.report("haml") do
31
+ N.times do
32
+ haml.render(scope, locals) do end
33
+ end
34
+ end
35
+ x.report("opulent") do
36
+ N.times do
37
+ opulent.render(scope, locals) do end
38
+ end
39
+ end
40
+ x.report("slim") do
41
+ N.times do
42
+ slim.render(scope, locals) do end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ %html
2
+ %head
3
+ %title Hello world
4
+ %meta(name="description" content="Node benchmark")
5
+ %body
6
+ %nav.navbar
7
+ %ul.nav.left
8
+ %li Home
9
+ %li About
10
+ %li Contact
11
+ #content
12
+ .container
13
+ .row
14
+ .col-md-12
15
+ | Hello world, this is a dummy text used for the speed benchmark in Opulent
16
+ %footer
17
+ | Copyright &copy; Hello world!
@@ -0,0 +1,14 @@
1
+ html
2
+ head
3
+ title
4
+ meta
5
+ body
6
+ nav
7
+ ul
8
+ li
9
+ li
10
+ li
11
+ content
12
+ container
13
+ row
14
+ col-md-12
@@ -0,0 +1,19 @@
1
+ html
2
+ head
3
+ - a = 3
4
+ title =a
5
+ meta name="description" content="Node benchmark"
6
+ body
7
+ nav.navbar
8
+ ul.nav.left
9
+ li Home
10
+ li About
11
+ li Contact
12
+ #content
13
+ .container
14
+ .row
15
+ .col-md-12
16
+ | Hello world, this is a dummy text used for
17
+ the speed benchmark in Opulent
18
+ footer
19
+ | Copyright &copy; Hello world!
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "opulent"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,3 @@
1
+ #Opulent Syntax
2
+
3
+ @TODO
@@ -0,0 +1,3 @@
1
+ # Opulent Usage
2
+
3
+ @TODO
@@ -1,64 +1,11 @@
1
- require 'pp'
2
- require 'json'
3
- require_relative 'opulent/engine'
4
- require_relative 'opulent/logger'
5
- require_relative 'opulent/preprocessor'
6
- require_relative 'opulent/tokens'
7
- require_relative 'opulent/nodes'
8
- require_relative 'opulent/parser'
9
- require_relative 'opulent/runtime'
10
-
11
- module Opulent
12
- class << self
13
- # Analyze the input code and check for matching tokens. In case no match was
14
- # found, throw an exception. In special cases, modify the token hash.
15
- #
16
- # @param file [String] The file that needs to be analyzed
17
- # @param context [Hash | String] Processing environment data
18
- #
19
- def render(file, context = nil)
20
- # Get the code from the input file
21
- @code = PreProcessor.process(file)
22
-
23
- # Accept both ruby hashes and JSON files as database environments
24
- @context = Runtime.apply context
25
-
26
- # Instantiate required language components
27
- @syntax = Parser.parse code
28
-
29
- pretty = Proc.new do |elements, indent|
30
- if elements.is_a? Nodes::Text
31
- puts " " * indent + "text: " + elements.value
32
- else
33
- elements.each do |element|
34
- text = " " * indent + element.name.to_s
35
- if element.respond_to? :attributes
36
- text += " " + element.attributes.to_s
37
- elsif element.respond_to? :value
38
- text += " -> " + element.value.to_s
39
- end
40
- puts text
41
-
42
- if element.is_a?(Nodes::Text) || element.is_a?(Nodes::Print) || element.is_a?(Nodes::Comment) || element.children.empty?
43
- elsif [Nodes::CnditionalControl, Nodes::CaseControl].any? do |node| element.is_a? node end
44
- element.children.each do |c| pretty[c, indent+2] end
45
- else
46
- pretty[element.children, indent + 2]
47
- end
48
- end
49
- end
50
- end
51
-
52
- puts "Definitions\n---"
53
- @syntax.themes.each do |theme, theme_value|
54
- puts theme.to_s
55
- theme_value.each do |key, value|
56
- puts " " + key.to_s + " " + value.attributes.to_s
57
- pretty[value.children, 4]
58
- end
59
- end
60
- puts "\n\nNodes\n---"
61
- pretty[@syntax.children, 0]
62
- end
63
- end
64
- end
1
+ require 'tilt'
2
+ require 'htmlentities'
3
+ require_relative 'opulent/compiler.rb'
4
+ require_relative 'opulent/context.rb'
5
+ require_relative 'opulent/engine.rb'
6
+ require_relative 'opulent/filters.rb'
7
+ require_relative 'opulent/logger.rb'
8
+ require_relative 'opulent/parser.rb'
9
+ require_relative 'opulent/settings.rb'
10
+ require_relative 'opulent/template.rb'
11
+ require_relative 'opulent/tokens.rb'
@@ -0,0 +1,132 @@
1
+ require_relative 'compiler/block.rb'
2
+ require_relative 'compiler/comment.rb'
3
+ require_relative 'compiler/control.rb'
4
+ require_relative 'compiler/define.rb'
5
+ require_relative 'compiler/eval.rb'
6
+ require_relative 'compiler/filter.rb'
7
+ require_relative 'compiler/node.rb'
8
+ require_relative 'compiler/root.rb'
9
+ require_relative 'compiler/text.rb'
10
+
11
+ # @Opulent
12
+ module Opulent
13
+ # @Compiler
14
+ class Compiler
15
+ Buffer = :_buffer
16
+
17
+ # All node Objects (Array) must follow the next convention in order
18
+ # to make parsing faster
19
+ #
20
+ # [:node_type, :value, :attributes, :children, :indent]
21
+ #
22
+ def initialize
23
+ # Setup convention accessors
24
+ @type = 0
25
+ @value = 1
26
+ @options = 2
27
+ @children = 3
28
+ @indent = 4
29
+
30
+ # Create the HTML Entities encoder/decoder
31
+ @entities = HTMLEntities.new
32
+
33
+ # Get special node types from the settings
34
+ @multi_node = Settings::MultiNode
35
+ @inline_node = Settings::InlineNode
36
+
37
+ # Quick accessor for default yield constant
38
+ @default_yield = Settings::DefaultYield
39
+
40
+ # The node stack is needed to keep track of all the visited nodes
41
+ # from the current branch level
42
+ @node_stack = []
43
+
44
+ # The sibling stack keeps track of the sibling count from the current
45
+ # branch level being generated
46
+ @sibling_stack = []
47
+
48
+ # Whenever we enter a definition compilation, add the provided blocks to
49
+ # the current block stack. When exiting a definition, remove blocks.
50
+ @block_stack = []
51
+ end
52
+
53
+ # Compile input nodes, replace them with their definitions and
54
+ #
55
+ # @param root [Array] Root node containing all document nodes
56
+ # @param context [Context] Context holding environment variables
57
+ #
58
+ def compile(root_node, context)
59
+ # Compiler generated code
60
+ @code = ""
61
+ @generator = ""
62
+
63
+ # Set initial parent, from which we start generating code
64
+ @sibling_stack << root_node[@children].size
65
+
66
+ # Start building up the code from the root node
67
+ root_node[@children].each do |child|
68
+ root child, 0, context
69
+ end
70
+
71
+ return @code
72
+ end
73
+
74
+ # Escape a given input value using htmlentities
75
+ #
76
+ # @param value [String] String to be escaped
77
+ #
78
+ def escape(value)
79
+ @entities.encode value
80
+ end
81
+
82
+ # Remove the last newline from the current code buffer
83
+ #
84
+ def remove_trailing_newline
85
+ @code.chop! if @code[-1] == "\n"
86
+ end
87
+
88
+ # Indent all lines of the input text using give indentation
89
+ #
90
+ # @param text [String] Input text to be indented
91
+ # @param indent [String] Indentation string to be appended
92
+ #
93
+ def indent_lines text, indent
94
+ text ||= ""
95
+ text.lines.inject("") do |result, line|
96
+ result += indent + line
97
+ end
98
+ end
99
+
100
+ # Give an explicit error report where an unexpected sequence of tokens
101
+ # appears and give indications on how to solve it
102
+ #
103
+ # @param context [Symbol] Context name in which the error happens
104
+ # @param data [Array] Additional error information
105
+ #
106
+ def error(context, *data)
107
+ message = case context
108
+ when :enumerable
109
+ "The provided each structure iteration input \"#{data[0]}\" is not Enumerable."
110
+ when :binding
111
+ data[0] = data[0].to_s.match(/\`(.*)\'/)
112
+ data[0] = data[0][1] if data[0]
113
+ "Found an undefined local variable or method \"#{data[0]}\" at \"#{data[1]}\"."
114
+ when :variable_name
115
+ data[0] = data[0].to_s.match(/\`(.*)\'/)[1]
116
+ "Found an undefined local variable or method \"#{data[0]}\" in locals."
117
+ when :extension
118
+ "The extension sequence \"#{data[0]}\" is not a valid attributes extension. " +
119
+ "Please use a Hash to extend attributes."
120
+ when :filter_registered
121
+ "The \"#{data[0]}\" filter could not be recognized by Opulent."
122
+ when :filter_load
123
+ "The gem required for the \"#{data[0]}\" filter is not installed. You can install it by running:\n\n#{data[1]}"
124
+ end
125
+
126
+ # Reconstruct lines to display where errors occur
127
+ fail "\n\nOpulent " + Logger.red("[Runtime Error]") + "\n---\n" +
128
+ "A runtime error has been encountered when building the compiled node tree.\n" +
129
+ "#{message}\n\n\n"
130
+ end
131
+ end
132
+ end