opulent 0.0.9 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e616139da8f4b17f4fc7f52bb66b3e18d4d42be
4
- data.tar.gz: eb8dfdcaae0b2fb04c83430a742c7ae31ad34364
3
+ metadata.gz: 3d6fdf705335f29c2162e3b2868398f4015ba29c
4
+ data.tar.gz: be920ffc6c6349e76d76ef802425146e5ed734e8
5
5
  SHA512:
6
- metadata.gz: aca80c297f91ccc02b465534f6da7c755749092a10c14ca9b733e64df2f1aa90c551aeaa0383fa49ffd15ea3ecf81e6035df4b48e4bc6163e80aa41a4e0af048
7
- data.tar.gz: 7363ff73b1572727aa7aecaa42b86b04c6e101b82e399b763d25a3538a9c2aee1e1974254b34be5073cc08d1aa8e0dc0269746de8215af2d5a41670fb20751ea
6
+ metadata.gz: 5ff789a689f140eccd4f853322bef8bec37747e52187a62d8c87a59d799944732451d419cd534fd7fc06ab216a55ac48db0a027db98200b86ce912d85c89ad3f
7
+ data.tar.gz: bfcb9e0566c3081bb99f2fe9f30ec697b7f78d35af9924e0fe0fd2835e04176007a62e90a072da4dc0361b23c902213d679d33cc24d486f085155176db67c21a
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -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