ruty 0.0.1

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.
@@ -0,0 +1,28 @@
1
+ # = Ruty Capture Tag
2
+ #
3
+ # Author:: Armin Ronacher
4
+ #
5
+ # Copyright (c) 2006 by Armin Ronacher
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of the BSD license.
8
+
9
+ class Ruty::Tags::Capture < Ruty::Tag
10
+
11
+ def initialize parser, argstring
12
+ if not argstring =~ /^as\s+([a-zA-Z_][a-zA-Z0-9_]*)$/
13
+ parser.fail('syntax for capture tag: {% capture as <variable> %}')
14
+ end
15
+
16
+ @name = $1.to_sym
17
+ @nodelist = parser.parse_until { |n, a| n == :endcapture }
18
+ end
19
+
20
+ def render_node context, stream
21
+ substream = ''
22
+ @nodelist.render(context, substream)
23
+ context[@name] = substream
24
+ end
25
+
26
+ Ruty::Tags.register(self, :include)
27
+
28
+ end
@@ -0,0 +1,59 @@
1
+ # = Ruty Conditional Tags
2
+ #
3
+ # Author:: Armin Ronacher
4
+ #
5
+ # Copyright (c) 2006 by Armin Ronacher
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of the BSD license.
8
+
9
+ class Ruty::Tags::If < Ruty::Tag
10
+
11
+ def initialize parser, argstring
12
+ # parse everything until the next else or endif tag
13
+ # and save in a variable if it was a else tag for
14
+ # postprocessing.
15
+ was_else = false
16
+ @body = parser.parse_until do |name, a|
17
+ if [:endif, :else].include? name
18
+ was_else = name == :else
19
+ true
20
+ end
21
+ end
22
+
23
+ args = parser.parse_arguments(argstring)
24
+ @else_body = parser.parse_until { |name, a| name == :endif } if was_else
25
+
26
+ if not [1, 2].include?(args.length) or \
27
+ (args.length == 2 and args[0] != :not)
28
+ parser.fail('invalid syntax for if tag')
29
+ end
30
+
31
+ @negated = args.length == 2
32
+ @item = @negated ? args[1] : args[0]
33
+ end
34
+
35
+ def render_node context, stream
36
+ item = context.resolve(@item)
37
+ if item == false
38
+ val = false
39
+ elsif item.respond_to?(:nonzero?)
40
+ val = item.nonzero?
41
+ elsif item.respond_to?(:empty?)
42
+ val = !item.empty?
43
+ elsif item.respond_to?(:size)
44
+ val = item.size > 0
45
+ elsif item.respond_to?(:length)
46
+ val = item.length > 0
47
+ else
48
+ val = !item.nil?
49
+ end
50
+ if @negated ? !val : val
51
+ @body.render_node(context, stream)
52
+ elsif @else_body
53
+ @else_body.render_node(context, stream)
54
+ end
55
+ end
56
+
57
+ Ruty::Tags.register(self, :if)
58
+
59
+ end
@@ -0,0 +1,28 @@
1
+ # = Ruty Debug Tag
2
+ #
3
+ # Author:: Armin Ronacher
4
+ #
5
+ # Copyright (c) 2006 by Armin Ronacher
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of the BSD license.
8
+
9
+ require 'stringio'
10
+ require 'pp'
11
+
12
+ class Ruty::Tags::Debug < Ruty::Tag
13
+
14
+ def initialize parser, argstring
15
+ parser.fail('debug tag takes no arguments') if not argstring.empty?
16
+ end
17
+
18
+ def render_node context, stream
19
+ buffer = StringIO.new
20
+ PP.pp(context, buffer)
21
+ buffer.rewind
22
+ stream << buffer.read.strip
23
+ buffer.close
24
+ end
25
+
26
+ Ruty::Tags.register(self, :debug)
27
+
28
+ end
@@ -0,0 +1,27 @@
1
+ # = Ruty Filter Tag
2
+ #
3
+ # Author:: Armin Ronacher
4
+ #
5
+ # Copyright (c) 2006 by Armin Ronacher
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of the BSD license.
8
+
9
+ class Ruty::Tags::Filter < Ruty::Tag
10
+
11
+ def initialize parser, argstring
12
+ @filters = parser.parse_arguments('|' + argstring)
13
+ parser.fail('filter tag requires at least on filter') if @filters.empty?
14
+ @nodelist = parser.parse_until { |n, a| n == :endfilter }
15
+ end
16
+
17
+ def render_node context, stream
18
+ substream = Ruty::Datastructure::OutputStream.new
19
+ @nodelist.render_node(context, substream)
20
+ value = context.apply_filters(substream.to_s, @filters).to_s
21
+ stream << value if not value.empty?
22
+ nil
23
+ end
24
+
25
+ Ruty::Tags.register(self, :filter)
26
+
27
+ end
@@ -0,0 +1,83 @@
1
+ # = Ruty For Loop Tag
2
+ #
3
+ # Author:: Armin Ronacher
4
+ #
5
+ # Copyright (c) 2006 by Armin Ronacher
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of the BSD license.
8
+
9
+ class Ruty::Tags::ForLoop < Ruty::Tag
10
+
11
+ def initialize parser, argstring
12
+ # parse everything until the next else or endfor tag
13
+ # and save in a variable if it was a else tag or an
14
+ # endfor tag so that we can parse the second part if
15
+ # required later.
16
+ was_else = false
17
+ @body = parser.parse_until do |name, a|
18
+ if [:endfor, :else].include? name
19
+ was_else = name == :else
20
+ true
21
+ end
22
+ end
23
+
24
+ args = parser.parse_arguments(argstring)
25
+ @else_body = parser.parse_until { |name, a| name == :endfor } if was_else
26
+ if args.length != 3 or args[1] != :in
27
+ parser.fail('invalid syntax for for-loop tag')
28
+ end
29
+ @item = args[0]
30
+ @iterable = args[2]
31
+ end
32
+
33
+ def render_node context, stream
34
+ iterable = context.resolve(@iterable)
35
+ length = 0
36
+ if iterable.respond_to?(:each)
37
+ if iterable.respond_to?(:size)
38
+ length = iterable.size
39
+ elsif iterable.respond_to?(:length)
40
+ length = iterable.length
41
+ end
42
+ end
43
+
44
+ if length > 0
45
+ index = 0
46
+ parent = context[:loop]
47
+ context.push
48
+
49
+ iterable.each do |item|
50
+ break if index == length
51
+ context[@item] = item
52
+ context[:loop] = {
53
+ :parent => parent,
54
+ :index => index + 1,
55
+ :index0 => index,
56
+ :revindex => length - index,
57
+ :revindex0 => length - index - 1,
58
+ :first => index == 0,
59
+ :last => length - index == 1,
60
+ :length => length,
61
+ :even => index % 2 != 0,
62
+ :odd => index % 2 == 0
63
+ }
64
+ @body.render_node(context, stream)
65
+ index += 1
66
+ end
67
+ if index != 0
68
+ context.pop
69
+ return nil
70
+ end
71
+ end
72
+
73
+ # if we reach this point there was no iteration. either because
74
+ # we tried to iterate something without a size or it was an object
75
+ # that isn't iterable, render the else_body if given
76
+ @else_body.render_node(context, stream) if @else_body
77
+ context.pop
78
+ nil
79
+ end
80
+
81
+ Ruty::Tags.register(self, :for)
82
+
83
+ end
@@ -0,0 +1,31 @@
1
+ # = Ruty Include Tags
2
+ #
3
+ # Author:: Armin Ronacher
4
+ #
5
+ # Copyright (c) 2006 by Armin Ronacher
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of the BSD license.
8
+
9
+ # simple include tag. just includes another template at
10
+ # the current position. (for header/footer inclusion for
11
+ # example, although it's better to use extends in combination
12
+ # with some blocks)
13
+ class Ruty::Tags::Include < Ruty::Tag
14
+
15
+ def initialize parser, argstring
16
+ if not argstring =~ /^("')(.*?)\1$/
17
+ parser.fail('include takes exactly one argument which must be ' +
18
+ 'an hardcoded string')
19
+ end
20
+
21
+ # load given template using the load_local function of the parser
22
+ @nodelist = parser.load_local(argstring[1...-1])
23
+ end
24
+
25
+ def render_node context, stream
26
+ @nodelist.render_node(context, stream)
27
+ end
28
+
29
+ Ruty::Tags.register(self, :include)
30
+
31
+ end
@@ -0,0 +1,80 @@
1
+ # = Ruty Template Inheritance
2
+ #
3
+ # Author:: Armin Ronacher
4
+ #
5
+ # Copyright (c) 2006 by Armin Ronacher
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of the BSD license.
8
+
9
+ # special tag that marks a part of a template for inheritance.
10
+ # If a template extends from a template with a block tag with
11
+ # the same name it will replace the block in the inherited
12
+ # template with the block with the same name in the current
13
+ # template.
14
+ class Ruty::Tags::Block < Ruty::Tag
15
+
16
+ def initialize parser, argstring
17
+ if not argstring =~ /^[a-zA-Z_][a-zA-Z0-9_]*$/
18
+ parser.fail('Invalid syntax for block tag')
19
+ end
20
+ @name = argstring.to_sym
21
+ @stack = [parser.parse_until { |name, a| name == :endblock }]
22
+
23
+ blocks = (parser.storage[:blocks] ||= {})
24
+ parser.fail("block '#{@name}' defined twice") if blocks.include?(@name)
25
+ blocks[@name] = self
26
+ end
27
+
28
+ def add_layer nodelist
29
+ @stack << nodelist
30
+ end
31
+
32
+ def render_node context, stream, index=-1
33
+ context.push
34
+ context[:block] = Ruty::Datastructure::Deferred.new(
35
+ :super => Proc.new {
36
+ render_node(context, stream, index - 1) if index.abs <= @stack.size
37
+ },
38
+ :depth => Proc.new { index.abs },
39
+ :name => Proc.new { @name }
40
+ )
41
+ @stack[index].render_node(context, stream)
42
+ context.pop
43
+ nil
44
+ end
45
+
46
+ Ruty::Tags.register(self, :block)
47
+
48
+ end
49
+
50
+ # tag used to load a template from another file. must be the first
51
+ # tag of a document!
52
+ class Ruty::Tags::Extends < Ruty::Tag
53
+
54
+ def initialize parser, argstring
55
+ if not parser.first
56
+ parser.fail('extends tag must be at the beginning of a template')
57
+ elsif not argstring =~ /^(["'])(.*?)\1$/
58
+ parser.fail('extends takes exactly one argument which must be ' +
59
+ 'an hardcoded string')
60
+ end
61
+
62
+ # parse the template to the end and load parent nodelist
63
+ parser.parse_all
64
+ @nodelist = parser.load_local(argstring[1...-1])
65
+ blocks = @nodelist.parser.storage[:blocks] || {}
66
+
67
+ # iterate over all blocks found while parsing and add them
68
+ # to the parent nodelist which will be the new nodelist
69
+ (parser.storage[:blocks] || []).each do |name, tag|
70
+ blocks[name].add_layer(tag) if blocks.include?(name)
71
+ end
72
+ end
73
+
74
+ def render_node context, stream
75
+ @nodelist.render_node(context, stream)
76
+ end
77
+
78
+ Ruty::Tags.register(self, :extends)
79
+
80
+ end
@@ -0,0 +1,85 @@
1
+ # = Ruty Loop Tool Tags
2
+ #
3
+ # Author:: Armin Ronacher
4
+ #
5
+ # Copyright (c) 2006 by Armin Ronacher
6
+ #
7
+ # You can redistribute it and/or modify it under the terms of the BSD license.
8
+
9
+ # A tag that cycles through a list of values each iteration
10
+ # Useful for example if you want alternating rows:
11
+ #
12
+ # {% for row in rows %}
13
+ # <tr class="{% cycle 'row1', 'row2' %}">
14
+ # <td>..</td>
15
+ # </tr>
16
+ # {% endfor %}
17
+ class Ruty::Tags::Cycle < Ruty::Tag
18
+
19
+ def initialize parser, argstring
20
+ args = parser.parse_arguments(argstring)
21
+ parser.fail('At least one item is required for cycle') if args.empty?
22
+ @items = args
23
+ end
24
+
25
+ def render_node context, stream
26
+ item = @items[context[self] = ((context[self] || -1) + 1) % @items.length]
27
+ item = context.resolve(item) if item.is_a?(Symbol)
28
+ stream << item.to_s
29
+ nil
30
+ end
31
+
32
+ Ruty::Tags.register(self, :cycle)
33
+
34
+ end
35
+
36
+
37
+ # just render everything between the tag and the closing
38
+ # endifchanged tag if the given variable hasn't changed
39
+ # from the last iteration. If no variable is given the
40
+ # block will check it's own rendering against the
41
+ # rendering of the last iteration.
42
+ #
43
+ # {% for day in days %}
44
+ # <div class="day">
45
+ # <h2>{{ day.name|escape }}</h2>
46
+ # {% for entry in day.entries %}
47
+ # {% ifchanged entry.pub_date.hour %}
48
+ # <h3>{{ entry.pub_date }}</h3>
49
+ # {% endifchanged %}
50
+ # ...
51
+ # {% endfor %}
52
+ # </div>
53
+ # {% endfor %}
54
+ class Ruty::Tags::IfChanged < Ruty::Tag
55
+
56
+ def initialize parser, argstring
57
+ args = parser.parse_arguments(argstring)
58
+ if not [0, 1].include?(args.length)
59
+ parser.fail('ifchanged-tag takes at most one argument')
60
+ end
61
+ @arg = args[0]
62
+ @body = parser.parse_until { |name, a| name == :endifchanged }
63
+ end
64
+
65
+ def render_node context, stream
66
+ if not @arg
67
+ substream = Datastructure::OutputStream.new
68
+ @body.render_node(context, substream)
69
+ this_iteration = substream.to_s
70
+ if this_iteration != context[self]
71
+ block << this_iteration
72
+ context[self] = this_iteration
73
+ end
74
+ else
75
+ item = (@arg.is_a?(Symbol)) ? context.resolve(@arg) : @arg
76
+ if item != context[self]
77
+ @body.render_node(context, stream)
78
+ context[self] = item
79
+ end
80
+ end
81
+ nil
82
+ end
83
+
84
+ Ruty::Tags.register(self, :ifchanged)
85
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.0
3
+ specification_version: 1
4
+ name: ruty
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.0.1
7
+ date: 2007-01-21 00:00:00 +01:00
8
+ summary: A Template-Engine inspired by the jinja engine
9
+ require_paths:
10
+ - lib
11
+ email:
12
+ homepage:
13
+ rubyforge_project:
14
+ description:
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: "true"
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Armin Ronacher
31
+ files:
32
+ - lib/ruty
33
+ - lib/ruty.rb
34
+ - lib/ruty/constants.rb
35
+ - lib/ruty/context.rb
36
+ - lib/ruty/datastructure.rb
37
+ - lib/ruty/filters.rb
38
+ - lib/ruty/loaders
39
+ - lib/ruty/loaders.rb
40
+ - lib/ruty/parser.rb
41
+ - lib/ruty/tags
42
+ - lib/ruty/tags.rb
43
+ - lib/ruty/loaders/filesystem.rb
44
+ - lib/ruty/tags/capture.rb
45
+ - lib/ruty/tags/conditional.rb
46
+ - lib/ruty/tags/debug.rb
47
+ - lib/ruty/tags/filter.rb
48
+ - lib/ruty/tags/forloop.rb
49
+ - lib/ruty/tags/inclusion.rb
50
+ - lib/ruty/tags/inheritance.rb
51
+ - lib/ruty/tags/looptools.rb
52
+ test_files: []
53
+
54
+ rdoc_options: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ executables: []
59
+
60
+ extensions: []
61
+
62
+ requirements: []
63
+
64
+ dependencies: []
65
+