dang 1.0.0.rc1
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 +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
|
+
[](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,"") }
|