dang 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.autotest +12 -0
- data/History.md +5 -0
- data/Manifest.txt +10 -0
- data/README.md +95 -0
- data/Rakefile +30 -0
- data/bin/dang +26 -0
- data/lib/dang.rb +4 -0
- data/lib/dang/dang.rb +40 -0
- data/lib/dang/parser.kpeg +240 -0
- data/lib/dang/parser.rb +2664 -0
- metadata +95 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA512:
|
3
|
+
metadata.gz: ffabe3af990c95e65060e84baa3aafbc4e5f2819b2d42a2a95eb05d49c4db064bbf853f8983d4f2ba6bbf8f0ec19c39c5a8744ab2f7ddeb15b8e6a2c9179eed2
|
4
|
+
data.tar.gz: a41454e0e02dddc883a99c484972336edd08ac4d7b36277454c0b0dbfae041e03cb3d14c46fb0755fdcf6bfa7f7ed6ab89e43fc2832b51987641ff5d3bad9daa
|
5
|
+
SHA1:
|
6
|
+
metadata.gz: 2678da64cfb92588a3140913f902176929bba2fb
|
7
|
+
data.tar.gz: 31398bcdeb3a87e0de26ad2063becd441c377e2a
|
data/.autotest
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# require 'autotest/restart'
|
2
|
+
#
|
3
|
+
# Autotest.add_hook :initialize do |at|
|
4
|
+
# at.clear_mappings
|
5
|
+
#
|
6
|
+
# at.add_mapping %r%/^lib/(.*)\.rb$% do |_, m|
|
7
|
+
# possible = File.basename(m[1])
|
8
|
+
# files_matching %r%^test/.*test_#{possible}\.rb$%
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# at.add_mapping(%r%^test/.*\.rb$%) {|filename, _| filename }
|
12
|
+
# end
|
data/History.md
ADDED
data/Manifest.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# Dang
|
2
|
+
|
3
|
+
https://github.com/veganstraightedge/dang
|
4
|
+
|
5
|
+
## Description
|
6
|
+
|
7
|
+
Another dang templating language.
|
8
|
+
|
9
|
+
## Build Status
|
10
|
+
|
11
|
+
[![Build Status](https://travis-ci.org/veganstraightedge/dang.png?branch=master)](https://travis-ci.org/veganstraightedge/dang)
|
12
|
+
|
13
|
+
## Features
|
14
|
+
|
15
|
+
* CSS selectors for HTML tags
|
16
|
+
* Not as noisy syntax than ERB
|
17
|
+
* Not quite as elegant as [HAML](http://haml-lang.com)
|
18
|
+
* No %s in the codez
|
19
|
+
* More closers than HAML
|
20
|
+
* A lot is based on / inspired by [HAML](http://haml.info)
|
21
|
+
|
22
|
+
## Synopsis
|
23
|
+
|
24
|
+
<b BOLD b> => <b>BOLD</b>
|
25
|
+
|
26
|
+
## Current Version
|
27
|
+
|
28
|
+
0.1.0
|
29
|
+
|
30
|
+
## Requirements
|
31
|
+
|
32
|
+
* [rake](https://github.com/jimweirich/rake)
|
33
|
+
* [kpeg](https://github.com/evanphx/kpeg)
|
34
|
+
* [hoe](https://github.com/seattlerb/hoe)
|
35
|
+
* [minitest](https://github.com/seattlerb/minitest)
|
36
|
+
|
37
|
+
## Installation
|
38
|
+
|
39
|
+
### Gemfile
|
40
|
+
|
41
|
+
Add this line to your application's Gemfile:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
gem 'dang'
|
45
|
+
```
|
46
|
+
|
47
|
+
### Manual
|
48
|
+
|
49
|
+
Or install it yourself as:
|
50
|
+
|
51
|
+
```bash
|
52
|
+
gem install dang
|
53
|
+
```
|
54
|
+
|
55
|
+
You may need to use `sudo` to install it manually.
|
56
|
+
|
57
|
+
## Developers
|
58
|
+
|
59
|
+
After checking out the source, run:
|
60
|
+
|
61
|
+
```bash
|
62
|
+
bundle
|
63
|
+
```
|
64
|
+
|
65
|
+
This task will install any missing dependencies, run the tests/specs, and generate the RDoc.
|
66
|
+
|
67
|
+
## Authors
|
68
|
+
|
69
|
+
* Shane Becker / [@veganstraightedge](https://github.com/veganstraightedge)
|
70
|
+
* Evan Phoenix / [@evanphx](https://github.com/evanphx)
|
71
|
+
|
72
|
+
## Contributing
|
73
|
+
|
74
|
+
1. Fork it
|
75
|
+
2. Get it running
|
76
|
+
3. Create your feature branch (`git checkout -b my-new-feature`)
|
77
|
+
4. Write your code and **specs**
|
78
|
+
5. Commit your changes (`git commit -am 'Add some feature'`)
|
79
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
80
|
+
7. Create new Pull Request
|
81
|
+
|
82
|
+
If you find bugs, have feature requests or questions, please
|
83
|
+
[file an issue](https://github.com/veganstraightedge/dang).
|
84
|
+
|
85
|
+
## License
|
86
|
+
|
87
|
+
**PUBLIC DOMAIN**
|
88
|
+
|
89
|
+
Your heart is as free as the air you breathe. <br>
|
90
|
+
The ground you stand on is liberated territory.
|
91
|
+
|
92
|
+
In legal text, Dang is dedicated to the public domain
|
93
|
+
using Creative Commons -- CC0 1.0 Universal.
|
94
|
+
|
95
|
+
[http://creativecommons.org/publicdomain/zero/1.0](http://creativecommons.org/publicdomain/zero/1.0 "Creative Commons — CC0 1.0 Universal")
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "hoe"
|
3
|
+
|
4
|
+
Hoe.plugins.delete :rubyforge
|
5
|
+
Hoe.plugin :doofus, :git, :minitest
|
6
|
+
|
7
|
+
Hoe.spec "dang" do
|
8
|
+
developer "Shane Becker", "veganstraightedge@gmail.com"
|
9
|
+
|
10
|
+
self.extra_rdoc_files = Dir["*.rdoc"]
|
11
|
+
self.history_file = "History.md"
|
12
|
+
self.readme_file = "README.md"
|
13
|
+
end
|
14
|
+
|
15
|
+
task :parser do
|
16
|
+
sh "ruby -I../kpeg/lib ../kpeg/bin/kpeg -o lib/dang/parser.rb -f -n Dang::Parser -s lib/dang/parser.kpeg"
|
17
|
+
end
|
18
|
+
|
19
|
+
$:.unshift "."
|
20
|
+
$:.unshift "./lib"
|
21
|
+
|
22
|
+
task :default => :spec
|
23
|
+
|
24
|
+
task :spec do
|
25
|
+
Dir[File.dirname(__FILE__) + "/spectory/**/*_spec.rb"].each do |path|
|
26
|
+
require path
|
27
|
+
end
|
28
|
+
|
29
|
+
Minitest.autorun
|
30
|
+
end
|
data/bin/dang
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'dang'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
to_eval = nil
|
7
|
+
path = nil
|
8
|
+
|
9
|
+
opt = OptionParser.new do |o|
|
10
|
+
o.on "-e STR", "Evaluate the string as Dang" do |s|
|
11
|
+
to_eval = s
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
opt.parse! ARGV
|
16
|
+
|
17
|
+
if to_eval
|
18
|
+
puts Dang.it(to_eval)
|
19
|
+
|
20
|
+
else
|
21
|
+
path = ARGV.shift
|
22
|
+
if !path
|
23
|
+
raise "Specify -e or a path to a file"
|
24
|
+
end
|
25
|
+
puts Dang.it(File.read(path))
|
26
|
+
end
|
data/lib/dang.rb
ADDED
data/lib/dang/dang.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'kpeg'
|
5
|
+
|
6
|
+
require 'dang/parser'
|
7
|
+
|
8
|
+
class Dang
|
9
|
+
VERSION = '1.0.0.rc1'
|
10
|
+
|
11
|
+
@filters = {}
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def it(str, env=nil)
|
15
|
+
parser = Dang::Parser.new(str, true)
|
16
|
+
unless parser.parse
|
17
|
+
io = StringIO.new
|
18
|
+
parser.show_error(io)
|
19
|
+
raise io.string
|
20
|
+
end
|
21
|
+
|
22
|
+
parser.output(env)
|
23
|
+
end
|
24
|
+
|
25
|
+
def register_filter(name, filter)
|
26
|
+
@filters[name] = filter
|
27
|
+
end
|
28
|
+
|
29
|
+
def run_filter(name, text)
|
30
|
+
if filter = @filters[name]
|
31
|
+
return filter[text]
|
32
|
+
else
|
33
|
+
raise "Unknown filter: \"#{name}\""
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# A default filter.
|
39
|
+
register_filter "raw", proc { |str| str }
|
40
|
+
end
|
@@ -0,0 +1,240 @@
|
|
1
|
+
%% name = Dang::Parser
|
2
|
+
|
3
|
+
%% {
|
4
|
+
def initialize(str, debug=false)
|
5
|
+
setup_parser(str, debug)
|
6
|
+
@doctype = nil
|
7
|
+
@output = ""
|
8
|
+
end
|
9
|
+
|
10
|
+
DOC_TYPES = {
|
11
|
+
"html" => "<!doctype html>",
|
12
|
+
"html5" => "<!doctype html>",
|
13
|
+
"html4" => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
|
14
|
+
"html4 transitional" => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
|
15
|
+
"html4 strict" => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
|
16
|
+
"html4 frameset" => '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
|
17
|
+
|
18
|
+
"xhtml 1" => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
|
19
|
+
"xhtml 1 transitional" => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
|
20
|
+
"xhtml 1 strict" => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
|
21
|
+
"xhtml 1 frameset" => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
|
22
|
+
"xhtml 1.1" => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
|
23
|
+
"xhtml 1.1 basic" => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
|
24
|
+
"xhtml 1.2 mobile" => '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">',
|
25
|
+
"xhtml rdfa" => '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">',
|
26
|
+
"xhtml 5" => '<!DOCTYPE html>',
|
27
|
+
|
28
|
+
"xml iso-8859-1" => "<?xml version='1.0' encoding='iso-8859-1' ?>"
|
29
|
+
}
|
30
|
+
|
31
|
+
def html_doctype
|
32
|
+
return "" unless @doctype
|
33
|
+
|
34
|
+
unless DOC_TYPES.key? @doctype
|
35
|
+
warn "doctype '#{@doctype}' not understood, using 'html'"
|
36
|
+
@doctype = "html"
|
37
|
+
end
|
38
|
+
|
39
|
+
DOC_TYPES[@doctype].dup
|
40
|
+
end
|
41
|
+
|
42
|
+
def output(env=nil)
|
43
|
+
doctype = html_doctype
|
44
|
+
|
45
|
+
strings = @output.flatten.map do |i|
|
46
|
+
case i
|
47
|
+
when Literal
|
48
|
+
"_out << #{i.str.dump}"
|
49
|
+
when Code
|
50
|
+
if i.print
|
51
|
+
"_out << (#{i.str}).to_s"
|
52
|
+
else
|
53
|
+
i.str
|
54
|
+
end
|
55
|
+
when Filter
|
56
|
+
"_out << Dang.run_filter('#{i.name}', #{i.str.dump}).to_s"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
code = "_out = '';\n" + strings.join(";") + ";_out"
|
61
|
+
|
62
|
+
out = eval(code, env || binding).strip
|
63
|
+
|
64
|
+
if doctype.empty?
|
65
|
+
str = out
|
66
|
+
else
|
67
|
+
if out.empty?
|
68
|
+
str = doctype
|
69
|
+
else
|
70
|
+
str = doctype << "\n" << out
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
str
|
75
|
+
end
|
76
|
+
|
77
|
+
def attrs(at,sel=[])
|
78
|
+
out = []
|
79
|
+
classes = []
|
80
|
+
|
81
|
+
(at+sel).each do |key,val|
|
82
|
+
if key == "class"
|
83
|
+
classes.unshift val
|
84
|
+
elsif val == true
|
85
|
+
out << "#{key}"
|
86
|
+
else
|
87
|
+
out << "#{key}='#{val}'"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
unless classes.empty?
|
92
|
+
out.unshift "class='#{classes.join(' ')}'"
|
93
|
+
end
|
94
|
+
|
95
|
+
out.join(' ')
|
96
|
+
end
|
97
|
+
|
98
|
+
class Literal
|
99
|
+
def initialize(str)
|
100
|
+
@str = str
|
101
|
+
end
|
102
|
+
|
103
|
+
attr_reader :str
|
104
|
+
end
|
105
|
+
|
106
|
+
class Code
|
107
|
+
def initialize(str, print)
|
108
|
+
@str = str
|
109
|
+
@print = print
|
110
|
+
end
|
111
|
+
|
112
|
+
attr_reader :str, :print
|
113
|
+
end
|
114
|
+
|
115
|
+
class Filter
|
116
|
+
def initialize(name, str)
|
117
|
+
@name = name
|
118
|
+
@str = str
|
119
|
+
end
|
120
|
+
|
121
|
+
attr_reader :name, :str
|
122
|
+
end
|
123
|
+
|
124
|
+
def joinm(*elems)
|
125
|
+
elems.map do |i|
|
126
|
+
if i.kind_of? String
|
127
|
+
Literal.new(i)
|
128
|
+
else
|
129
|
+
i
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def join(f,b)
|
135
|
+
f = Literal.new(f) if f.kind_of? String
|
136
|
+
b = Literal.new(b) if b.kind_of? String
|
137
|
+
|
138
|
+
if b.kind_of? Array
|
139
|
+
[f] + b
|
140
|
+
else
|
141
|
+
[f,b]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def code(str, print=true)
|
146
|
+
Code.new(str, print)
|
147
|
+
end
|
148
|
+
}
|
149
|
+
|
150
|
+
space = " " | "\t"
|
151
|
+
bs = " " | "\t" | "\n"
|
152
|
+
- = bs+
|
153
|
+
eol = "\n"
|
154
|
+
eof = !.
|
155
|
+
rest = < (!eol .)* > (eol | eof) { text }
|
156
|
+
|
157
|
+
doctype = "!!!" space* rest:r { @doctype = r.empty? ? "html" : r }
|
158
|
+
|
159
|
+
name = < /[a-zA-Z0-9_\-:]+/ > { text }
|
160
|
+
start = "<" name:n { n }
|
161
|
+
pts = space+ { "" }
|
162
|
+
| < eol bs* > { text }
|
163
|
+
|
164
|
+
end = name:n ">" { n }
|
165
|
+
slash = - "/>"
|
166
|
+
|
167
|
+
marker = start | "<!" | (- end)
|
168
|
+
chunk = < (!marker .)* > { text }
|
169
|
+
|
170
|
+
rclose = "->"
|
171
|
+
ruby = "<-" < (!rclose .)* > rclose { code(text, false) }
|
172
|
+
|
173
|
+
pclose = "=>"
|
174
|
+
puby = "<=" < (!pclose .)* > pclose { code(text) }
|
175
|
+
|
176
|
+
part = ruby | puby| filter | comment | tag | chunk
|
177
|
+
body = part:p body:b { join(p,b) }
|
178
|
+
| part
|
179
|
+
|
180
|
+
key = name
|
181
|
+
| "'" < /[^'\n]*/ > "'" { text }
|
182
|
+
|
183
|
+
val = "'" < /[^'\n]*/ > "'" { text }
|
184
|
+
| < (!"]" .)* > { text }
|
185
|
+
|
186
|
+
dattr = "[" key:k "=" val:v "]" { "data-#{k}='#{v}'" }
|
187
|
+
dattrs = dattr:a dattrs:l { "#{a} #{l}" }
|
188
|
+
| dattr
|
189
|
+
|
190
|
+
attr = "[data" dattrs:t "]" { [t,true] }
|
191
|
+
| "[" key:k "=" val:v "]" { [k, v] }
|
192
|
+
| "[" key:k "]" { [k,true] }
|
193
|
+
attrs = attr:a attrs:l { [a] + l }
|
194
|
+
| attr:a { [a] }
|
195
|
+
|
196
|
+
cc_if = /[iI][fF]/
|
197
|
+
cc_end = /[eE][nN][dD][iI][fF]/
|
198
|
+
comment = "<!" space+ < "[" space* cc_if (!"]" .)* "]" > space+ "!>"
|
199
|
+
{ "<!--#{text}>" }
|
200
|
+
| "<!" space+ < "[" space* cc_end (!"]" .)* "]" > space+ "!>"
|
201
|
+
{ "<!#{text}-->" }
|
202
|
+
| "<!" < (!"!>" .)* > "!>"
|
203
|
+
{ "<!--#{text}-->" }
|
204
|
+
|
205
|
+
simple = /[a-zA-Z0-9_\-]+/
|
206
|
+
select = "#" < simple > { ["id", text] }
|
207
|
+
| "." < simple > { ["class", text] }
|
208
|
+
|
209
|
+
selects = select:s selects:t { [s] + t }
|
210
|
+
| select:s { [s] }
|
211
|
+
|
212
|
+
end_filter(n) = bs* < /[a-zA-Z]+/ > &{ n == text } ":>"
|
213
|
+
|
214
|
+
filter = "<:" name:n bs* < (!end_filter(n) .)* > end_filter(n)
|
215
|
+
{ Filter.new(n, text) }
|
216
|
+
|
217
|
+
tag = start:l slash { "<#{l} />" }
|
218
|
+
| start:l space+ end:r { "<#{l}></#{r}>" }
|
219
|
+
| start:l attrs:a slash
|
220
|
+
{ "<#{l} #{attrs(a)} />" }
|
221
|
+
| start:l selects:t slash
|
222
|
+
{ "<#{l} #{attrs(t)} />" }
|
223
|
+
| start:l selects:t attrs:a slash
|
224
|
+
{ "<#{l} #{attrs(t,a)} />" }
|
225
|
+
| start:l attrs:a space+ end:r
|
226
|
+
{ "<#{l} #{attrs(a)}></#{r}>" }
|
227
|
+
| start:l selects:t space+ end:r
|
228
|
+
{ "<#{l} #{attrs(t)}></#{r}>" }
|
229
|
+
| start:l selects:t attrs:a space+ end:r
|
230
|
+
{ "<#{l} #{attrs(t,a)}></#{r}>" }
|
231
|
+
| start:l selects:t attrs:a pts body:b pts:es end:r
|
232
|
+
{ joinm "<#{l} #{attrs(a,t)}>",b,es,"</#{r}>" }
|
233
|
+
| start:l attrs:a pts body:b pts:es end:r
|
234
|
+
{ joinm "<#{l} #{attrs(a)}>", b, es, "</#{r}>" }
|
235
|
+
| start:l selects:t pts:s body:b pts:es end:r
|
236
|
+
{ joinm "<#{l} #{attrs(t)}>",s, b, es, "</#{r}>" }
|
237
|
+
| start:l pts:s body:b pts:es end:r
|
238
|
+
{ joinm "<#{l}>", s, b, es, "</#{r}>" }
|
239
|
+
|
240
|
+
root = doctype? body:b eof { @output = join(b,"") }
|