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.
- checksums.yaml +4 -4
- data/.gitignore +9 -0
- data/.libold/opulent.rb +96 -0
- data/.libold/opulent/context.rb +80 -0
- data/.libold/opulent/engine.rb +88 -0
- data/.libold/opulent/filter.rb +101 -0
- data/.libold/opulent/logger.rb +67 -0
- data/.libold/opulent/nodes.rb +13 -0
- data/.libold/opulent/nodes/block.rb +29 -0
- data/.libold/opulent/nodes/comment.rb +35 -0
- data/.libold/opulent/nodes/control.rb +230 -0
- data/.libold/opulent/nodes/define.rb +42 -0
- data/.libold/opulent/nodes/eval.rb +41 -0
- data/.libold/opulent/nodes/expression.rb +28 -0
- data/.libold/opulent/nodes/filter.rb +70 -0
- data/.libold/opulent/nodes/helper.rb +69 -0
- data/.libold/opulent/nodes/node.rb +101 -0
- data/.libold/opulent/nodes/root.rb +62 -0
- data/.libold/opulent/nodes/text.rb +54 -0
- data/.libold/opulent/nodes/theme.rb +36 -0
- data/.libold/opulent/parser.rb +252 -0
- data/.libold/opulent/parser/block.rb +70 -0
- data/.libold/opulent/parser/comment.rb +32 -0
- data/.libold/opulent/parser/control.rb +83 -0
- data/.libold/opulent/parser/define.rb +39 -0
- data/.libold/opulent/parser/eval.rb +33 -0
- data/.libold/opulent/parser/expression.rb +350 -0
- data/.libold/opulent/parser/filter.rb +41 -0
- data/.libold/opulent/parser/node.rb +232 -0
- data/.libold/opulent/parser/root.rb +96 -0
- data/.libold/opulent/parser/text.rb +114 -0
- data/.libold/opulent/parser/theme.rb +36 -0
- data/.libold/opulent/preprocessor.rb +102 -0
- data/.libold/opulent/runtime.rb +144 -0
- data/.libold/opulent/template.rb +43 -0
- data/.libold/opulent/tokens.rb +276 -0
- data/.libold/opulent/version.rb +5 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +2 -0
- data/LICENSE +21 -0
- data/README.md +102 -0
- data/Rakefile +6 -0
- data/benchmark/benchmark.rb +46 -0
- data/benchmark/cases/node/node.haml +17 -0
- data/benchmark/cases/node/node.op +14 -0
- data/benchmark/cases/node/node.slim +19 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/docs/syntax.md +3 -0
- data/docs/usage.md +3 -0
- data/lib/opulent.rb +11 -64
- data/lib/opulent/compiler.rb +132 -0
- data/lib/opulent/compiler/block.rb +31 -0
- data/lib/opulent/compiler/comment.rb +22 -0
- data/lib/opulent/compiler/control.rb +152 -0
- data/lib/opulent/compiler/define.rb +88 -0
- data/lib/opulent/compiler/eval.rb +15 -0
- data/lib/opulent/compiler/filter.rb +54 -0
- data/lib/opulent/compiler/node.rb +232 -0
- data/lib/opulent/compiler/root.rb +19 -0
- data/lib/opulent/compiler/text.rb +60 -0
- data/lib/opulent/context.rb +88 -0
- data/lib/opulent/engine.rb +60 -0
- data/lib/opulent/filters.rb +222 -0
- data/lib/opulent/logger.rb +47 -0
- data/lib/opulent/parser.rb +196 -0
- data/lib/opulent/parser/block.rb +56 -0
- data/lib/opulent/parser/comment.rb +27 -0
- data/lib/opulent/parser/control.rb +112 -0
- data/lib/opulent/parser/define.rb +30 -0
- data/lib/opulent/parser/eval.rb +21 -0
- data/lib/opulent/parser/expression.rb +344 -0
- data/lib/opulent/parser/filter.rb +25 -0
- data/lib/opulent/parser/node.rb +246 -0
- data/lib/opulent/parser/root.rb +48 -0
- data/lib/opulent/parser/text.rb +127 -0
- data/lib/opulent/settings.rb +79 -0
- data/lib/opulent/template.rb +67 -0
- data/lib/opulent/tokens.rb +166 -0
- data/lib/opulent/version.rb +4 -0
- data/opulent.gemspec +36 -0
- metadata +160 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d6fdf705335f29c2162e3b2868398f4015ba29c
|
4
|
+
data.tar.gz: be920ffc6c6349e76d76ef802425146e5ed734e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ff789a689f140eccd4f853322bef8bec37747e52187a62d8c87a59d799944732451d419cd534fd7fc06ab216a55ac48db0a027db98200b86ce912d85c89ad3f
|
7
|
+
data.tar.gz: bfcb9e0566c3081bb99f2fe9f30ec697b7f78d35af9924e0fe0fd2835e04176007a62e90a072da4dc0361b23c902213d679d33cc24d486f085155176db67c21a
|
data/.gitignore
ADDED
data/.libold/opulent.rb
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'htmlentities'
|
2
|
+
require 'tilt'
|
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/context'
|
10
|
+
require_relative 'opulent/runtime'
|
11
|
+
require_relative 'opulent/template'
|
12
|
+
require_relative 'opulent/filter'
|
13
|
+
require 'pp'
|
14
|
+
|
15
|
+
# @Opulent
|
16
|
+
module Opulent
|
17
|
+
# Wrapper method for creating a new Opulent instance
|
18
|
+
#
|
19
|
+
def Opulent.new
|
20
|
+
return Opulent.new
|
21
|
+
end
|
22
|
+
|
23
|
+
# @Opulent
|
24
|
+
class Opulent
|
25
|
+
# Analyze the input code and check for matching tokens. In case no match was
|
26
|
+
# found, throw an exception. In special cases, modify the token hash.
|
27
|
+
#
|
28
|
+
# @param file [String] The file that needs to be analyzed
|
29
|
+
# @param locals [Hash] Render call local variables
|
30
|
+
# @param block [Proc] Processing environment data
|
31
|
+
#
|
32
|
+
def render_file(file, locals = {}, &block)
|
33
|
+
# Temporarily set file render mode for using it in the Preprocessor
|
34
|
+
@mode = :file
|
35
|
+
|
36
|
+
# Render the file
|
37
|
+
render file, locals, &block
|
38
|
+
end
|
39
|
+
|
40
|
+
# Analyze the input code and check for matching tokens. In case no match was
|
41
|
+
# found, throw an exception. In special cases, modify the token hash.
|
42
|
+
#
|
43
|
+
# @param file [String] The file that needs to be analyzed
|
44
|
+
# @param locals [Hash] Render call local variables
|
45
|
+
# @param block [Proc] Processing environment data
|
46
|
+
#
|
47
|
+
def render(code, locals = {}, &block)
|
48
|
+
# Get the code from the input file
|
49
|
+
@code = PreProcessor.process code, @mode, &block
|
50
|
+
|
51
|
+
# Reset rendering mode to code. The mode variable is used to specify
|
52
|
+
# whether we're using render file or render code. When using render code,
|
53
|
+
# the preprocessor can be used only when a block is also passed
|
54
|
+
@mode = :code
|
55
|
+
|
56
|
+
# Instantiate required language components
|
57
|
+
@syntax = Parser.parse @code
|
58
|
+
|
59
|
+
# Create a new context based on our rendering environment
|
60
|
+
#bind = block.binding if block
|
61
|
+
#@context = Context.new locals, bind
|
62
|
+
|
63
|
+
# Instantiate required language components
|
64
|
+
#@model = Runtime.remodel @syntax, @context
|
65
|
+
|
66
|
+
#puts "\n\nModel\n---"
|
67
|
+
#Logger.pretty_print @model
|
68
|
+
end
|
69
|
+
|
70
|
+
# Update the engine options with the required option changes
|
71
|
+
#
|
72
|
+
def update_options(opts)
|
73
|
+
Engine.update_options(opts)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
# Give an explicit error report where an unexpected sequence of tokens
|
79
|
+
# appears and give indications on how to solve it
|
80
|
+
#
|
81
|
+
# @param context [Symbol] Context name in which the error happens
|
82
|
+
# @param data [Array] Additional error information
|
83
|
+
#
|
84
|
+
def error(context, *data)
|
85
|
+
message = case context
|
86
|
+
when :options_key
|
87
|
+
"The input \"#{data[0]}\" is not a valid option name."
|
88
|
+
end
|
89
|
+
|
90
|
+
# Reconstruct lines to display where errors occur
|
91
|
+
fail "\n\nOpulent " + Logger.red("[Engine Error]") + "\n---\n" +
|
92
|
+
"An error has been encountered when updating the engine options.\n" +
|
93
|
+
"#{message}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# @Opulent
|
2
|
+
module Opulent
|
3
|
+
# @Context
|
4
|
+
#
|
5
|
+
# The context class is used to differentiate local, instance and class variables
|
6
|
+
# and to define the current working environment. Each class, method and instance
|
7
|
+
# has its own context
|
8
|
+
#
|
9
|
+
class Context
|
10
|
+
attr_accessor :locals, :binding, :parent, :name
|
11
|
+
|
12
|
+
# Create a context from the environment binding, extended with the locals
|
13
|
+
# given as arguments
|
14
|
+
#
|
15
|
+
# @param locals [Hash] Binding extension
|
16
|
+
# @param bind [Binding] Call environment binding
|
17
|
+
#
|
18
|
+
def initialize(locals = {}, bind = nil)
|
19
|
+
@binding = if bind
|
20
|
+
bind.clone
|
21
|
+
else
|
22
|
+
Binding.new
|
23
|
+
end
|
24
|
+
|
25
|
+
extend_locals locals
|
26
|
+
end
|
27
|
+
|
28
|
+
# Evaluate ruby code in current context
|
29
|
+
#
|
30
|
+
# @param code [String] Code to be evaluated
|
31
|
+
#
|
32
|
+
def evaluate(code)
|
33
|
+
begin
|
34
|
+
eval code, @binding
|
35
|
+
rescue NameError => variable
|
36
|
+
Runtime.error :binding, variable, code
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Extend the call context with a Hash, String or other Object
|
41
|
+
#
|
42
|
+
# @param context [Object] Extension object
|
43
|
+
#
|
44
|
+
def extend_locals(locals)
|
45
|
+
# Create new local variables from the input hash
|
46
|
+
locals.each do |key, value|
|
47
|
+
begin
|
48
|
+
@binding.local_variable_set(key.to_sym, value)
|
49
|
+
rescue NameError => variable
|
50
|
+
Runtime.error :variable_name, variable, key
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Extend instance, class and global variables for use in definitions
|
56
|
+
#
|
57
|
+
# @param bind [Binding] Binding to extend current context binding
|
58
|
+
#
|
59
|
+
def extend_nonlocals(bind)
|
60
|
+
bind.eval('instance_variables').each do |var|
|
61
|
+
@binding.eval('self').instance_variable_set var, bind.eval(var.to_s)
|
62
|
+
end
|
63
|
+
|
64
|
+
bind.eval('self.class.class_variables').each do |var|
|
65
|
+
@binding.eval('self').class_variable_set var, bind.eval(var.to_s)
|
66
|
+
end
|
67
|
+
|
68
|
+
bind.eval('self.class.constants').each do |var|
|
69
|
+
@binding.eval('self').const_set var, bind.eval(var.to_s)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# @Binding
|
75
|
+
class Binding
|
76
|
+
def self.new
|
77
|
+
binding
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# @SugarCube
|
2
|
+
module Opulent
|
3
|
+
# @Engine
|
4
|
+
module Engine
|
5
|
+
# Default (root) theme name which can be accesed using the root definitions
|
6
|
+
DEFAULT_THEME = :default
|
7
|
+
|
8
|
+
# Default yield target which is used for child block replacements
|
9
|
+
DEFAULT_YIELD = :children
|
10
|
+
|
11
|
+
# List of self enclosing node elements
|
12
|
+
SELF_ENCLOSING = %w(img link input meta br hr area base col command embed keygen param source track wbr)
|
13
|
+
|
14
|
+
# @Singleton
|
15
|
+
class << self
|
16
|
+
attr_accessor :filters, :options
|
17
|
+
|
18
|
+
# Opulent runtime options
|
19
|
+
@@defaults = {
|
20
|
+
pretty: true,
|
21
|
+
indent: 2,
|
22
|
+
dependency_manager: true,
|
23
|
+
shorthand: {
|
24
|
+
class: /\./,
|
25
|
+
id: /\#/,
|
26
|
+
name: /\&/
|
27
|
+
},
|
28
|
+
each: {
|
29
|
+
:default_key => :key,
|
30
|
+
:default_value => :value
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
# Set defaults as initial options
|
35
|
+
@@options = @@defaults.clone
|
36
|
+
|
37
|
+
# Get an option at runtime
|
38
|
+
#
|
39
|
+
# @param name [Symbol] Identifier for the option
|
40
|
+
#
|
41
|
+
def [](name)
|
42
|
+
@@options[name]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Set a new option at runtime
|
46
|
+
#
|
47
|
+
# @param name [Symbol] Identifier for the option
|
48
|
+
# @param value Option value to be set
|
49
|
+
#
|
50
|
+
def []=(name, value)
|
51
|
+
@@options[name] = value
|
52
|
+
end
|
53
|
+
|
54
|
+
# Add a new Opulent filter to the filters knowledgebase
|
55
|
+
#
|
56
|
+
# @param class [Class] Class to be used for filter instance
|
57
|
+
# @param name [Symbol] Identifier in the filters hash
|
58
|
+
# @param options [Hash] Filter engine instance options
|
59
|
+
#
|
60
|
+
def register(klass, name, options)
|
61
|
+
@filters ||= {}
|
62
|
+
@filters[name] = klass.new name, options
|
63
|
+
end
|
64
|
+
|
65
|
+
# Check if the chosen filter name is registed within our knowledgebase
|
66
|
+
#
|
67
|
+
def filter?(name)
|
68
|
+
@filters.has_key? name
|
69
|
+
end
|
70
|
+
|
71
|
+
# Update the engine options with the required option changes
|
72
|
+
#
|
73
|
+
# @param opts [Hash] Option extension
|
74
|
+
#
|
75
|
+
def update_options(opts)
|
76
|
+
@@options = @@defaults.clone
|
77
|
+
|
78
|
+
opts.each do |key, value|
|
79
|
+
if @@options[key]
|
80
|
+
@@options[key] = value
|
81
|
+
else
|
82
|
+
error :options_key, key
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# @Opulent
|
2
|
+
module Opulent
|
3
|
+
# @Filter
|
4
|
+
module Filter
|
5
|
+
# @Filter
|
6
|
+
class Filter
|
7
|
+
attr_accessor :name, :options, :loaded
|
8
|
+
|
9
|
+
# Set tag and attribute options for filter
|
10
|
+
#
|
11
|
+
def initialize(name, options)
|
12
|
+
@name = name
|
13
|
+
@options = options
|
14
|
+
@loaded = false
|
15
|
+
end
|
16
|
+
|
17
|
+
# Error output in case the filter does not exist
|
18
|
+
#
|
19
|
+
def load_filter
|
20
|
+
unless @loaded
|
21
|
+
# Try to load the library associated to the chosen filter
|
22
|
+
begin
|
23
|
+
require gem_name
|
24
|
+
@loaded = true
|
25
|
+
rescue LoadError => error
|
26
|
+
# Error output with filter name and installation instructions
|
27
|
+
Runtime.error :filter_load, @name, install_error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Error message to be shown in order to provide installation instructions
|
33
|
+
# for the developer
|
34
|
+
#
|
35
|
+
def install_error
|
36
|
+
"gem install #{gem_name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
# Process input code using this filter and return the output to the
|
40
|
+
# evaluation method from the Filter Node
|
41
|
+
#
|
42
|
+
def render(code, options = {})
|
43
|
+
raise NoMethodError
|
44
|
+
end
|
45
|
+
|
46
|
+
# RubyGems name for explicit library require
|
47
|
+
#
|
48
|
+
def gem_name
|
49
|
+
raise NoMethodError
|
50
|
+
# "gem_name"
|
51
|
+
end
|
52
|
+
|
53
|
+
# After defining how to render the code,
|
54
|
+
#
|
55
|
+
# Engine.register self, :filter, tag: :tag, attributes: { type: 'text/css' }
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# Add the default registered rendering filters for Opulent
|
60
|
+
|
61
|
+
# @CoffeeScript
|
62
|
+
class CoffeeScript < Filter
|
63
|
+
def render(code, options = {})
|
64
|
+
::CoffeeScript.compile code, options
|
65
|
+
end
|
66
|
+
|
67
|
+
def gem_name
|
68
|
+
"coffee-script"
|
69
|
+
end
|
70
|
+
|
71
|
+
Engine.register self, :coffeescript, tag: :script, attributes: { type: 'javascript' }
|
72
|
+
end
|
73
|
+
|
74
|
+
# @Scss
|
75
|
+
class Scss < Filter
|
76
|
+
def render(code, options = {})
|
77
|
+
::Sass.compile code, options
|
78
|
+
end
|
79
|
+
|
80
|
+
def gem_name
|
81
|
+
"sass"
|
82
|
+
end
|
83
|
+
|
84
|
+
Engine.register self, :scss, tag: :style, attributes: { type: 'text/css' }
|
85
|
+
end
|
86
|
+
|
87
|
+
# @Sass
|
88
|
+
class Sass < Filter
|
89
|
+
def render(code, options = {})
|
90
|
+
options[:syntax] = :sass
|
91
|
+
::Sass.compile code, options
|
92
|
+
end
|
93
|
+
|
94
|
+
def gem_name
|
95
|
+
"sass"
|
96
|
+
end
|
97
|
+
|
98
|
+
Engine.register self, :sass, tag: :style, attributes: { type: 'text/css' }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# @Opulent
|
2
|
+
module Opulent
|
3
|
+
# @Logger
|
4
|
+
module Logger
|
5
|
+
# @Singleton
|
6
|
+
class << self
|
7
|
+
# Color the input text with the chosen color
|
8
|
+
#
|
9
|
+
# @param text [String] the string that will be colored
|
10
|
+
# @param color_code [String] preset code for certain colors
|
11
|
+
#
|
12
|
+
def colorize(text, color_code)
|
13
|
+
require_windows_libs
|
14
|
+
"#{color_code}#{text}\e[0m"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Colors available in the terminal
|
18
|
+
#
|
19
|
+
def black(text); colorize(text, "\e[30m"); end
|
20
|
+
def red(text); colorize(text, "\e[31m"); end
|
21
|
+
def green(text); colorize(text, "\e[32m"); end
|
22
|
+
def yellow(text); colorize(text, "\e[33m"); end
|
23
|
+
def blue(text); colorize(text, "\e[34m"); end
|
24
|
+
def magenta(text); colorize(text, "\e[35m"); end
|
25
|
+
def cyan(text); colorize(text, "\e[36m"); end
|
26
|
+
def white(text); colorize(text, "\e[37m"); end
|
27
|
+
def default(text); colorize(text, "\e[38m"); end
|
28
|
+
|
29
|
+
# Require windows libraries for ANSI Console output
|
30
|
+
#
|
31
|
+
def require_windows_libs
|
32
|
+
begin
|
33
|
+
require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /win32/
|
34
|
+
rescue LoadError
|
35
|
+
raise 'You must run "gem install win32console" to use Opulent\'s
|
36
|
+
error reporting on Windows.'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Pretty print Nodes with their important details
|
41
|
+
#
|
42
|
+
def pretty_print(model, indent = 0)
|
43
|
+
model.each do |node|
|
44
|
+
case node
|
45
|
+
when Nodes::Node
|
46
|
+
puts " " * indent +
|
47
|
+
node.name.to_s +
|
48
|
+
"::" + node.class.to_s.split('::').last +
|
49
|
+
" #{node.attributes unless node.attributes.empty?}"
|
50
|
+
pretty_print node.children, indent + 2
|
51
|
+
when Nodes::Text, Nodes::Print
|
52
|
+
puts " " * indent +
|
53
|
+
"text" +
|
54
|
+
"::" + node.class.to_s.split('::').last +
|
55
|
+
" {:value => \"#{node.value}\"}"
|
56
|
+
when NilClass
|
57
|
+
else
|
58
|
+
puts " " * indent +
|
59
|
+
node.name.to_s +
|
60
|
+
"::" + node.class.to_s.split('::').last +
|
61
|
+
" {:value => \"#{node.value}\"}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|