sal 0.1.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.
- data/README.md +7 -0
- data/lib/sal/compiler.rb +35 -0
- data/lib/sal/engine.rb +16 -0
- data/lib/sal/filter.rb +13 -0
- data/lib/sal/parser.rb +103 -0
- data/lib/sal/template.rb +13 -0
- data/lib/sal/version.rb +3 -0
- data/lib/sal.rb +26 -0
- metadata +96 -0
data/README.md
ADDED
data/lib/sal/compiler.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
module Sal
|
2
|
+
# Compiles HTML into Temple::HTML expressions
|
3
|
+
# @api private
|
4
|
+
class Compiler < Filter
|
5
|
+
|
6
|
+
def on_sal_tag(ele, attrs, closed, content)
|
7
|
+
[:html, :tag, ele, attrs, closed, compile(content)]
|
8
|
+
end
|
9
|
+
|
10
|
+
def on_sal_code(code, tag, attrs, content)
|
11
|
+
tmp1, tmp2 = tmp_var(:sal), tmp_var(:sal)
|
12
|
+
|
13
|
+
[:multi,
|
14
|
+
[:block, "#{tmp1} = #{code}"],
|
15
|
+
[:block, "if #{tmp1}.kind_of?(String)"],
|
16
|
+
[:html, :tag, tag, attrs, false, [:dynamic, tmp1]],
|
17
|
+
[:block, "elsif #{tmp1}.kind_of?(Array)"],
|
18
|
+
[:block, "#{tmp1}.each do |#{tmp2}|"],
|
19
|
+
[:html, :tag, tag, ada(attrs, tmp2), false,
|
20
|
+
[:dynamic, "Sal.parse_for_html(#{tmp2})"]],
|
21
|
+
[:block, 'end'],
|
22
|
+
[:block, "else"],
|
23
|
+
[:html, :tag, tag, ada(attrs, tmp1), false,
|
24
|
+
[:dynamic, "Sal.parse_for_html(#{tmp1})"]],
|
25
|
+
[:block, 'end'],
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def ada(attrs, tmpvar)
|
32
|
+
attrs.dup << [:dynamic, "Sal.parse_for_attributes(#{tmpvar})"]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/sal/engine.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Sal
|
2
|
+
class Engine < Temple::Engine
|
3
|
+
set_default_options :format => :html,
|
4
|
+
:generator => Temple::Generators::ArrayBuffer
|
5
|
+
|
6
|
+
use Sal::Parser, :file, :tabsize, :encoding
|
7
|
+
use Sal::Compiler
|
8
|
+
use Temple::HTML::Fast
|
9
|
+
|
10
|
+
filter :MultiFlattener # Collapse nested multis into single multi
|
11
|
+
filter :StaticMerger # Merge several statics into a single static
|
12
|
+
filter :DynamicInliner # Merge several static/dynamic into single dynamic
|
13
|
+
|
14
|
+
use(:Generator) { |exp| options[:generator].new(options).call(exp) }
|
15
|
+
end
|
16
|
+
end
|
data/lib/sal/filter.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Sal
|
2
|
+
class Filter < Temple::Filter
|
3
|
+
temple_dispatch :sal
|
4
|
+
|
5
|
+
def on_sal_code(code, tag, attrs, content)
|
6
|
+
[:sal, :code, code, tag, attrs, content]
|
7
|
+
end
|
8
|
+
|
9
|
+
def on_sal_tag(tag, attrs, content)
|
10
|
+
[:sal, :tag, tag, attrs, content]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/sal/parser.rb
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Sal
|
4
|
+
class Parser
|
5
|
+
include Temple::Mixins::Options
|
6
|
+
|
7
|
+
set_default_options :tabsize => 4,
|
8
|
+
:encoding => 'utf-8'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
#TODO: Remove node_types after fleshing out tests
|
12
|
+
def node_types
|
13
|
+
@node_types ||= define_node_types
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
def define_node_types
|
18
|
+
nt = {}
|
19
|
+
Nokogiri::XML::Node.constants.each do |name|
|
20
|
+
nt[eval("Nokogiri::XML::Node::#{name}")] = name if name =~ /_NODE$/
|
21
|
+
end
|
22
|
+
nt
|
23
|
+
end
|
24
|
+
end # class block
|
25
|
+
|
26
|
+
def initialize(options = {})
|
27
|
+
super
|
28
|
+
@tab = ' ' * @options[:tabsize]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Compile the string to a Temple expression
|
32
|
+
#
|
33
|
+
# @param [String] str Html code
|
34
|
+
# @return [Array] Temple expression representing the code
|
35
|
+
def call(str)
|
36
|
+
if options[:encoding] && str.respond_to?(:encoding)
|
37
|
+
old = str.encoding
|
38
|
+
str = str.dup if str.frozen?
|
39
|
+
str.force_encoding(options[:encoding])
|
40
|
+
# Fall back to old encoding if new encoding is invalid
|
41
|
+
str.force_encoding(old_enc) unless str.valid_encoding?
|
42
|
+
end
|
43
|
+
|
44
|
+
result = [:multi]
|
45
|
+
|
46
|
+
doc = Nokogiri::XML(str)
|
47
|
+
|
48
|
+
parse_nodeset([result], doc)
|
49
|
+
|
50
|
+
result
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def parse_nodeset(stacks, nodes)
|
56
|
+
nodes.children.each do |node|
|
57
|
+
tag = node.name
|
58
|
+
|
59
|
+
case node.type
|
60
|
+
when Nokogiri::XML::Node::ELEMENT_NODE
|
61
|
+
content = [:multi]
|
62
|
+
attrs, code = parse_attrs(node)
|
63
|
+
if code
|
64
|
+
stacks.last << [:sal, :code, code, tag, attrs, content]
|
65
|
+
else
|
66
|
+
stacks.last << [:sal, :tag, tag, attrs, false, content]
|
67
|
+
end
|
68
|
+
stacks << content
|
69
|
+
parse_nodeset(stacks, node)
|
70
|
+
stacks.pop
|
71
|
+
when Nokogiri::XML::Node::TEXT_NODE
|
72
|
+
str = node.text
|
73
|
+
if str.strip.empty?
|
74
|
+
stacks.last << [:newline]
|
75
|
+
else
|
76
|
+
stacks.last << [:static, str]
|
77
|
+
end
|
78
|
+
when Nokogiri::XML::Node::DTD_NODE
|
79
|
+
stacks.last << [:static, node.to_s]
|
80
|
+
when Nokogiri::XML::Node::COMMENT_NODE
|
81
|
+
stacks.last << [:html, :comment, [:static, node.text]]
|
82
|
+
else
|
83
|
+
raise "Unexpected node type: #{self.class.node_types[node.node_type]}"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def parse_attrs(node)
|
89
|
+
code = nil
|
90
|
+
attrs = []
|
91
|
+
|
92
|
+
node.attribute_nodes.each do |an|
|
93
|
+
if an.name == 'data-sal'
|
94
|
+
code = an.value
|
95
|
+
else
|
96
|
+
attrs << [an.name, [:static, an.value]]
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
return [:multi, [:html, :staticattrs] + attrs], code
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
data/lib/sal/template.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Sal
|
2
|
+
# Tilt template implementation for sal
|
3
|
+
# @api public
|
4
|
+
Template = Temple::Templates::Tilt(Sal::Engine, :register_as => :sal)
|
5
|
+
|
6
|
+
if Object.const_defined?(:Rails)
|
7
|
+
RailsTemplate = Temple::Templates::Rails(Sal::Engine, :register_as => :sal)
|
8
|
+
|
9
|
+
RailsTemplate.set_default_options :generator => Temple::Generators::RailsOutputBuffer,
|
10
|
+
:disable_capture => true
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
data/lib/sal/version.rb
ADDED
data/lib/sal.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'temple'
|
4
|
+
require 'sal/parser'
|
5
|
+
require 'sal/filter'
|
6
|
+
require 'sal/compiler'
|
7
|
+
require 'sal/engine'
|
8
|
+
require 'sal/template'
|
9
|
+
require 'sal/version'
|
10
|
+
|
11
|
+
module Sal
|
12
|
+
class << self
|
13
|
+
def parse_for_attributes(result = nil)
|
14
|
+
return unless result.kind_of?(Hash)
|
15
|
+
" #{result.collect{ |k,v| "#{k}='#{v}'" unless k.to_s == 'html' }.compact.join(' ')}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse_for_html(result = nil)
|
19
|
+
if result.kind_of?(String)
|
20
|
+
result
|
21
|
+
elsif result.kind_of?(Hash)
|
22
|
+
result.delete(:html)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sal
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Andrew Stone
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-04-19 00:00:00 -04:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: nokogiri
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "1.4"
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: temple
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ~>
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0.2"
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: tilt
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ~>
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "1.2"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id003
|
49
|
+
description: sal.rb is an attribute language.
|
50
|
+
email:
|
51
|
+
- andy@stonean.com
|
52
|
+
executables: []
|
53
|
+
|
54
|
+
extensions: []
|
55
|
+
|
56
|
+
extra_rdoc_files:
|
57
|
+
- README.md
|
58
|
+
files:
|
59
|
+
- README.md
|
60
|
+
- lib/sal.rb
|
61
|
+
- lib/sal/compiler.rb
|
62
|
+
- lib/sal/engine.rb
|
63
|
+
- lib/sal/filter.rb
|
64
|
+
- lib/sal/parser.rb
|
65
|
+
- lib/sal/template.rb
|
66
|
+
- lib/sal/version.rb
|
67
|
+
has_rdoc: true
|
68
|
+
homepage: http://github.com/stonean/sal.rb
|
69
|
+
licenses: []
|
70
|
+
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options:
|
73
|
+
- --charset=UTF-8
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: "0"
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: "0"
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project: sal
|
91
|
+
rubygems_version: 1.6.1
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: sal is a template language.
|
95
|
+
test_files: []
|
96
|
+
|