ruex 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.
- checksums.yaml +7 -0
- data/LICENSE +24 -0
- data/README.md +205 -0
- data/VERSION +1 -0
- data/bin/ruex +82 -0
- data/lib/ruex/cli.rb +23 -0
- data/lib/ruex/core.rb +88 -0
- data/lib/ruex/helper/cli.rb +76 -0
- data/lib/ruex/tags.yml +194 -0
- data/lib/ruex/version.rb +4 -0
- data/lib/ruex.rb +7 -0
- metadata +53 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 13224922b7e3d224c8519f480b1cd5ba0b0c5838330af7f240520a703c8f149f
|
|
4
|
+
data.tar.gz: aee7340b08113ad97b628bcb056c5069428e51e982d74af4645f0849858ab7cd
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 224c71be4526088840e75d8440a8ce07ca8b5e6a1a76f922f2a1700af635114b3f3f0b0603956dbd2688665796cb1c16c74fdc06e1da0aca49bae6d318f2fb92
|
|
7
|
+
data.tar.gz: c615a249f8a61ea13e6d5b50851a725c97c0c16a6b2f870e6f1befd7f3d445c8bb3e93f64dc0699aa29a8cc04a7ca8b2ad3693d75d35933a271c180b592e26f3
|
data/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
BSD 2-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, takanobu maekawa
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
16
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
17
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
19
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
20
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
21
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
22
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
23
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
24
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# ruex
|
|
2
|
+
|
|
3
|
+
A library and CLI tool that generates HTML using plain Ruby expressions.
|
|
4
|
+
It is intended for static site or page generation, and is not suitable as a dynamic web page renderer.
|
|
5
|
+
|
|
6
|
+
Technically, you only need to know HTML, CSS, and Ruby — nothing more.
|
|
7
|
+
Easy to extend when needed.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
gem install ruex
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or add to your Gemfile:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem "ruex"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Quick Example
|
|
26
|
+
|
|
27
|
+
```shell
|
|
28
|
+
$ ruex -e 'div { p "hello" }'
|
|
29
|
+
<div><p>hello</p></div>
|
|
30
|
+
|
|
31
|
+
# same thing by the command pipeline
|
|
32
|
+
$ echo 'div { p "hello" }' | ruex
|
|
33
|
+
<div><p>hello</p></div>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## How it works
|
|
37
|
+
|
|
38
|
+
Every standard HTML tag is available as a Ruby method.
|
|
39
|
+
|
|
40
|
+
```shell
|
|
41
|
+
$ ruex -e 'p "hello"'
|
|
42
|
+
<p>hello</p>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Attributes
|
|
46
|
+
|
|
47
|
+
```shell
|
|
48
|
+
$ ruex -e 'p "Hi", class: "msg"'
|
|
49
|
+
<p class="msg">Hi</p>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Blocks
|
|
53
|
+
|
|
54
|
+
You can write child elements inside blocks:
|
|
55
|
+
|
|
56
|
+
```shell
|
|
57
|
+
$ ruex -e 'div { p "Hello" }'
|
|
58
|
+
<div><p>Hello</p></div>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Mixing Ruby code
|
|
62
|
+
|
|
63
|
+
You can freely mix Ruby code.
|
|
64
|
+
|
|
65
|
+
```shell
|
|
66
|
+
$ cat list.html.rx
|
|
67
|
+
ul{
|
|
68
|
+
%w[Foo Bar].each do |name|
|
|
69
|
+
li(name)
|
|
70
|
+
end
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
$ cat list.html.rx | ruex
|
|
74
|
+
<ul><li>Foo</li><li>Bar</li></ul>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Variable binding
|
|
78
|
+
|
|
79
|
+
```shell
|
|
80
|
+
$ cat table.html.rx
|
|
81
|
+
table {
|
|
82
|
+
people.each do |person|
|
|
83
|
+
tr{ td(person[:name]) }
|
|
84
|
+
end
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
$ cat table.html.rx | ruex -b '{people: [{name: "hoge"}, {name: "bar"}]}'
|
|
88
|
+
<table><tr><td>hoge</td></tr><tr><td>bar</td></tr></table>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Embedding text
|
|
92
|
+
|
|
93
|
+
`text` and `_` functions embed texts in HTML:
|
|
94
|
+
|
|
95
|
+
```shell
|
|
96
|
+
$ ruex -e 'text "Today is a good day"'
|
|
97
|
+
Today is a good day
|
|
98
|
+
|
|
99
|
+
$ ruex -e '_"Today is a good day"'
|
|
100
|
+
Today is a good day
|
|
101
|
+
|
|
102
|
+
$ ruex -e 'div{ _"Today is a good day" }'
|
|
103
|
+
<div>Today is a good day</div>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### HTML comments
|
|
107
|
+
|
|
108
|
+
ruex does not provide a comment function.
|
|
109
|
+
If you want to include an HTML comment, write it directly as a string:
|
|
110
|
+
|
|
111
|
+
```shell
|
|
112
|
+
$ ruex -e 'div { _"<!-- note -->" }'
|
|
113
|
+
<div><!-- note --></div>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Custom Tags
|
|
117
|
+
|
|
118
|
+
Just compose HTML using ruex expressions.
|
|
119
|
+
|
|
120
|
+
```ruby
|
|
121
|
+
# my_tags.rb
|
|
122
|
+
|
|
123
|
+
require 'ruex'
|
|
124
|
+
|
|
125
|
+
module MyTag
|
|
126
|
+
include Ruex
|
|
127
|
+
|
|
128
|
+
def card(title, &block)
|
|
129
|
+
div(class: "card"){
|
|
130
|
+
h2 title
|
|
131
|
+
block.call if block_given?
|
|
132
|
+
}
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
There are a few things you should know:
|
|
138
|
+
|
|
139
|
+
- you must provide your custom tag library as a module.
|
|
140
|
+
- Your module name must correspond to its file name (PascalCase → snake_case).
|
|
141
|
+
ex) MyTag -> my_tag.rb
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
You can use your library throuth `ruex` command, of course.
|
|
145
|
+
|
|
146
|
+
```shell
|
|
147
|
+
$ ruex -I /your/ruby/load/path -r my_tags.rb -e 'card("Hello") { p "world" }'
|
|
148
|
+
<div class="card"><h2>Hello</h2><p>world</p></div>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
If you make your custom tag library as Ruby gems, you don't need to specify `-I`.
|
|
152
|
+
|
|
153
|
+
### CLI options
|
|
154
|
+
|
|
155
|
+
```shell
|
|
156
|
+
$ ruex -h
|
|
157
|
+
Render ruex expressions as HTML.
|
|
158
|
+
|
|
159
|
+
Usage:
|
|
160
|
+
echo 'p "hello"' | ruex
|
|
161
|
+
ruex -e 'p "hello"'
|
|
162
|
+
ruex -f template.ruex
|
|
163
|
+
|
|
164
|
+
Options:
|
|
165
|
+
-I, --include-path PATH Add PATH to $LOAD_PATH
|
|
166
|
+
-r, --require LIB Require LIB and include its module into Ruex::Core
|
|
167
|
+
-e, --expr EXPR Evaluate EXPR instead of reading from stdin
|
|
168
|
+
-f, --file FILE Read Ruex DSL from FILE
|
|
169
|
+
-b, --bind KEY=VALUE Bind a variable available inside Ruex DSL
|
|
170
|
+
-c, --context-file FILE Load variables from YAML or JSON file
|
|
171
|
+
-v, --version Show Ruex version
|
|
172
|
+
-h, --help Show this help message
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Using in program code
|
|
176
|
+
|
|
177
|
+
1. To use ruex in Ruby code, include `Ruex`
|
|
178
|
+
2. use `render` method
|
|
179
|
+
|
|
180
|
+
```ruby
|
|
181
|
+
require 'ruex'
|
|
182
|
+
|
|
183
|
+
include Ruex
|
|
184
|
+
|
|
185
|
+
render 'div { _"Hello, World!!" }'
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
All tag name methods such as `div`, `p` and so on are **not intended to use outside the string literals.**
|
|
189
|
+
|
|
190
|
+
## Intended Use / Safety Notes
|
|
191
|
+
ruex evaluates Ruby expressions directly.
|
|
192
|
+
Use it with trusted, developer-authored templates such as static site content.
|
|
193
|
+
It is not intended for rendering untrusted input in web applications.
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
ruex is distributed under the BSD 2-Clause License (SPDX: BSD-2-Clause).
|
|
198
|
+
See the LICENSE file for details.
|
|
199
|
+
|
|
200
|
+
## Author
|
|
201
|
+
|
|
202
|
+
Takanobu Maekawa
|
|
203
|
+
|
|
204
|
+
https://github.com/tmkw
|
|
205
|
+
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
data/bin/ruex
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "optparse"
|
|
4
|
+
require "stringio"
|
|
5
|
+
require "ruex/cli"
|
|
6
|
+
require "ruex/version"
|
|
7
|
+
require "ruex/helper/cli"
|
|
8
|
+
|
|
9
|
+
include Ruex::Helper::CLI
|
|
10
|
+
|
|
11
|
+
load_paths = []
|
|
12
|
+
require_files = []
|
|
13
|
+
expr = nil
|
|
14
|
+
file_path = nil
|
|
15
|
+
bindings = {}
|
|
16
|
+
context_file = nil
|
|
17
|
+
|
|
18
|
+
opts = OptionParser.new do |opt|
|
|
19
|
+
opt.on("-I", "--include-path PATH") { |path| load_paths << path }
|
|
20
|
+
opt.on("-r", "--require LIB") { |lib| require_files << lib }
|
|
21
|
+
opt.on("-e", "--expr EXPR") { |e| expr = e }
|
|
22
|
+
opt.on("-f", "--file FILE") { |path| file_path = path }
|
|
23
|
+
|
|
24
|
+
opt.on("-b", "--bind RUBY_HASH") do |str|
|
|
25
|
+
begin
|
|
26
|
+
hash = ContextFile.read(StringIO.new(str))
|
|
27
|
+
bindings.merge!(hash)
|
|
28
|
+
rescue => e
|
|
29
|
+
warn e.message
|
|
30
|
+
exit(1)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
opt.on("-c", "--context-file FILE") do |file|
|
|
35
|
+
context_file = file
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
opt.on("-h", "--help") do
|
|
39
|
+
puts load_help
|
|
40
|
+
exit(0)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
opt.on("-v", "--version") do
|
|
44
|
+
puts Ruex::VERSION
|
|
45
|
+
exit(0)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
begin
|
|
50
|
+
opts.parse!(ARGV)
|
|
51
|
+
rescue OptionParser::InvalidOption => e
|
|
52
|
+
warn "Unknown option: #{e.args.join(" ")}"
|
|
53
|
+
exit(1)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Load context file
|
|
57
|
+
if context_file
|
|
58
|
+
begin
|
|
59
|
+
bindings.merge!(ContextFile.read(context_file))
|
|
60
|
+
rescue => e
|
|
61
|
+
warn e.message
|
|
62
|
+
exit(1)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Load paths
|
|
67
|
+
load_paths.each { |p| $LOAD_PATH.unshift(p) }
|
|
68
|
+
|
|
69
|
+
# load custom tag libraries
|
|
70
|
+
require_files.each do |lib|
|
|
71
|
+
require lib
|
|
72
|
+
mod_name = path_to_module_name(lib)
|
|
73
|
+
Ruex::Core.include(Object.const_get(mod_name))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Execute
|
|
77
|
+
Ruex::CLI.new.run(
|
|
78
|
+
expr: expr,
|
|
79
|
+
file: file_path,
|
|
80
|
+
ctx: bindings
|
|
81
|
+
)
|
|
82
|
+
|
data/lib/ruex/cli.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
require 'ruex'
|
|
2
|
+
|
|
3
|
+
module Ruex
|
|
4
|
+
class CLI
|
|
5
|
+
include Ruex
|
|
6
|
+
|
|
7
|
+
def run(expr: nil, file: nil, ctx: {})
|
|
8
|
+
input = if expr
|
|
9
|
+
expr
|
|
10
|
+
elsif file
|
|
11
|
+
File.read(file)
|
|
12
|
+
else
|
|
13
|
+
$stdin.read
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
input = input.to_s.strip
|
|
17
|
+
return if input.empty?
|
|
18
|
+
|
|
19
|
+
puts render(input, ctx: ctx)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
data/lib/ruex/core.rb
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
module Ruex
|
|
2
|
+
class Core
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
5
|
+
TAGS = YAML.load_file([__dir__, "tags.yml"].join('/'))
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@output = ''.dup
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def render_attrs(attrs, boolean_attrs)
|
|
12
|
+
return '' if attrs.empty?
|
|
13
|
+
|
|
14
|
+
parts = []
|
|
15
|
+
|
|
16
|
+
# data attributes
|
|
17
|
+
if attrs.key?(:data)
|
|
18
|
+
data_hash = attrs.delete(:data)
|
|
19
|
+
data_hash.each do |k, v|
|
|
20
|
+
html_key = "data-#{k.to_s.gsub('_', '-')}"
|
|
21
|
+
parts << %(#{html_key}="#{v}")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
attrs.each do |k, v|
|
|
26
|
+
if boolean_attrs&.include?(k)
|
|
27
|
+
# boolean attributes
|
|
28
|
+
parts << k.to_s if v # use only when the option is enabled
|
|
29
|
+
else
|
|
30
|
+
# normal attributes
|
|
31
|
+
parts << %(#{k}="#{v}")
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
parts.join(" ")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def render_tag(tag_def, args, attrs, block)
|
|
39
|
+
name = tag_def['name']
|
|
40
|
+
void = tag_def['void']
|
|
41
|
+
boolean_attrs = (tag_def['boolean'] || []).map(&:to_sym)
|
|
42
|
+
|
|
43
|
+
rendered_attrs = render_attrs(attrs, boolean_attrs)
|
|
44
|
+
attr_str = rendered_attrs.empty? ? '' : %( #{rendered_attrs})
|
|
45
|
+
|
|
46
|
+
if void
|
|
47
|
+
@output << "<#{name}#{attr_str}>".dup
|
|
48
|
+
return
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
@output << "<#{name}#{attr_str}>".dup
|
|
52
|
+
|
|
53
|
+
if block
|
|
54
|
+
block.call
|
|
55
|
+
elsif args.first
|
|
56
|
+
@output << args.first.to_s
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
@output << "</#{name}>".dup
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
TAGS.each do |tag|
|
|
63
|
+
define_method(tag['name']) do |*args, **attrs, &block|
|
|
64
|
+
render_tag(tag, args, attrs, block)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# for text node
|
|
69
|
+
def text(str)
|
|
70
|
+
@output << str.to_s
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
alias _ text
|
|
74
|
+
|
|
75
|
+
def render(code, ctx: {})
|
|
76
|
+
@output = "".dup
|
|
77
|
+
|
|
78
|
+
___binding___ = binding
|
|
79
|
+
ctx.each do |k, v|
|
|
80
|
+
___binding___.local_variable_set(k, v)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
eval(code, ___binding___, __FILE__, __LINE__)
|
|
84
|
+
#instance_eval(code, __FILE__, __LINE__)
|
|
85
|
+
@output
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module Ruex
|
|
2
|
+
module Helper
|
|
3
|
+
module CLI
|
|
4
|
+
require "json"
|
|
5
|
+
require "yaml"
|
|
6
|
+
|
|
7
|
+
def load_help
|
|
8
|
+
help_path = File.expand_path("../../../doc/help", __dir__)
|
|
9
|
+
File.read(help_path)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Convert "foo/bar_baz" → "Foo::BarBaz"
|
|
13
|
+
def path_to_module_name(lib)
|
|
14
|
+
lib
|
|
15
|
+
.sub(/\.rb$/, "")
|
|
16
|
+
.split("/")
|
|
17
|
+
.map { |seg| seg.split("_").map(&:capitalize).join }
|
|
18
|
+
.join("::")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class ContextFile
|
|
22
|
+
def self.read(path_or_io)
|
|
23
|
+
data = if path_or_io.is_a?(StringIO)
|
|
24
|
+
stringio_contents(path_or_io)
|
|
25
|
+
else
|
|
26
|
+
context_file_contents(path_or_io)
|
|
27
|
+
end
|
|
28
|
+
deep_symbolize(data)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.deep_symbolize(obj)
|
|
32
|
+
case obj
|
|
33
|
+
when Hash
|
|
34
|
+
obj.each_with_object({}) do |(k, v), h|
|
|
35
|
+
h[k.to_sym] = deep_symbolize(v)
|
|
36
|
+
end
|
|
37
|
+
when Array
|
|
38
|
+
obj.map { |v| deep_symbolize(v) }
|
|
39
|
+
else
|
|
40
|
+
obj
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.stringio_contents(sio)
|
|
45
|
+
data = Psych.safe_load(sio.read, permitted_classes: [Symbol], aliases: false)
|
|
46
|
+
raise ArgumentError, "-b expects a Hash literal" unless data.is_a?(Hash)
|
|
47
|
+
data
|
|
48
|
+
rescue Psych::DisallowedClass
|
|
49
|
+
raise ArgumentError, "-b expects a Hash literal"
|
|
50
|
+
rescue Psych::SyntaxError
|
|
51
|
+
raise ArgumentError, "Invalid -b hash"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.context_file_contents(path)
|
|
55
|
+
contents = File.read(path)
|
|
56
|
+
data =
|
|
57
|
+
case File.extname(path)
|
|
58
|
+
when ".yml", ".yaml"
|
|
59
|
+
Psych.safe_load(contents, permitted_classes: [Symbol], aliases: false)
|
|
60
|
+
when ".json"
|
|
61
|
+
JSON.parse(contents)
|
|
62
|
+
else
|
|
63
|
+
raise ArgumentError, "Unknown context file format: #{path}"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
raise ArgumentError, "Context file must contain a top-level Hash/Map object" unless data.is_a?(Hash)
|
|
67
|
+
|
|
68
|
+
data
|
|
69
|
+
rescue Psych::DisallowedClass
|
|
70
|
+
raise ArgumentError, "disallowed class"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
data/lib/ruex/tags.yml
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
- name: html
|
|
2
|
+
- name: head
|
|
3
|
+
- name: title
|
|
4
|
+
- name: base
|
|
5
|
+
void: true
|
|
6
|
+
- name: link
|
|
7
|
+
void: true
|
|
8
|
+
boolean:
|
|
9
|
+
- disabled
|
|
10
|
+
- name: meta
|
|
11
|
+
void: true
|
|
12
|
+
- name: style
|
|
13
|
+
- name: script
|
|
14
|
+
boolean:
|
|
15
|
+
- async
|
|
16
|
+
- defer
|
|
17
|
+
- nomodule
|
|
18
|
+
- name: noscript
|
|
19
|
+
- name: template
|
|
20
|
+
|
|
21
|
+
# Sections
|
|
22
|
+
- name: body
|
|
23
|
+
- name: section
|
|
24
|
+
- name: nav
|
|
25
|
+
- name: article
|
|
26
|
+
- name: aside
|
|
27
|
+
- name: h1
|
|
28
|
+
- name: h2
|
|
29
|
+
- name: h3
|
|
30
|
+
- name: h4
|
|
31
|
+
- name: h5
|
|
32
|
+
- name: h6
|
|
33
|
+
- name: header
|
|
34
|
+
- name: footer
|
|
35
|
+
- name: address
|
|
36
|
+
- name: main
|
|
37
|
+
|
|
38
|
+
# Grouping content
|
|
39
|
+
- name: p
|
|
40
|
+
- name: hr
|
|
41
|
+
void: true
|
|
42
|
+
- name: pre
|
|
43
|
+
- name: blockquote
|
|
44
|
+
- name: ol
|
|
45
|
+
- name: ul
|
|
46
|
+
- name: li
|
|
47
|
+
- name: dl
|
|
48
|
+
- name: dt
|
|
49
|
+
- name: dd
|
|
50
|
+
- name: figure
|
|
51
|
+
- name: figcaption
|
|
52
|
+
- name: div
|
|
53
|
+
|
|
54
|
+
# Text-level semantics
|
|
55
|
+
- name: a
|
|
56
|
+
- name: em
|
|
57
|
+
- name: strong
|
|
58
|
+
- name: small
|
|
59
|
+
- name: s
|
|
60
|
+
- name: cite
|
|
61
|
+
- name: q
|
|
62
|
+
- name: dfn
|
|
63
|
+
- name: abbr
|
|
64
|
+
- name: data
|
|
65
|
+
- name: time
|
|
66
|
+
- name: code
|
|
67
|
+
- name: var
|
|
68
|
+
- name: samp
|
|
69
|
+
- name: kbd
|
|
70
|
+
- name: sub
|
|
71
|
+
- name: sup
|
|
72
|
+
- name: i
|
|
73
|
+
- name: b
|
|
74
|
+
- name: u
|
|
75
|
+
- name: mark
|
|
76
|
+
- name: ruby
|
|
77
|
+
- name: rt
|
|
78
|
+
- name: rp
|
|
79
|
+
- name: bdi
|
|
80
|
+
- name: bdo
|
|
81
|
+
- name: span
|
|
82
|
+
- name: br
|
|
83
|
+
void: true
|
|
84
|
+
- name: wbr
|
|
85
|
+
void: true
|
|
86
|
+
|
|
87
|
+
# Edits
|
|
88
|
+
- name: ins
|
|
89
|
+
- name: del
|
|
90
|
+
|
|
91
|
+
# Embedded content
|
|
92
|
+
- name: picture
|
|
93
|
+
- name: source
|
|
94
|
+
void: true
|
|
95
|
+
- name: img
|
|
96
|
+
void: true
|
|
97
|
+
- name: iframe
|
|
98
|
+
- name: embed
|
|
99
|
+
void: true
|
|
100
|
+
- name: object
|
|
101
|
+
- name: param
|
|
102
|
+
void: true
|
|
103
|
+
- name: video
|
|
104
|
+
boolean:
|
|
105
|
+
- autoplay
|
|
106
|
+
- controls
|
|
107
|
+
- loop
|
|
108
|
+
- muted
|
|
109
|
+
- name: audio
|
|
110
|
+
boolean:
|
|
111
|
+
- autoplay
|
|
112
|
+
- controls
|
|
113
|
+
- loop
|
|
114
|
+
- muted
|
|
115
|
+
- name: track
|
|
116
|
+
void: true
|
|
117
|
+
- name: map
|
|
118
|
+
- name: area
|
|
119
|
+
void: true
|
|
120
|
+
|
|
121
|
+
# Forms
|
|
122
|
+
- name: form
|
|
123
|
+
boolean:
|
|
124
|
+
- novalidate
|
|
125
|
+
- name: label
|
|
126
|
+
- name: input
|
|
127
|
+
void: true
|
|
128
|
+
boolean:
|
|
129
|
+
- disabled
|
|
130
|
+
- readonly
|
|
131
|
+
- required
|
|
132
|
+
- autofocus
|
|
133
|
+
- multiple
|
|
134
|
+
- hidden
|
|
135
|
+
- formnovalidate
|
|
136
|
+
- checked
|
|
137
|
+
- name: button
|
|
138
|
+
boolean:
|
|
139
|
+
- disabled
|
|
140
|
+
- autofocus
|
|
141
|
+
- formnovalidate
|
|
142
|
+
- name: select
|
|
143
|
+
boolean:
|
|
144
|
+
- disabled
|
|
145
|
+
- multiple
|
|
146
|
+
- required
|
|
147
|
+
- autofocus
|
|
148
|
+
- name: datalist
|
|
149
|
+
- name: optgroup
|
|
150
|
+
boolean:
|
|
151
|
+
- disabled
|
|
152
|
+
- name: option
|
|
153
|
+
boolean:
|
|
154
|
+
- disabled
|
|
155
|
+
- selected
|
|
156
|
+
- name: textarea
|
|
157
|
+
boolean:
|
|
158
|
+
- disabled
|
|
159
|
+
- readonly
|
|
160
|
+
- required
|
|
161
|
+
- autofocus
|
|
162
|
+
- name: output
|
|
163
|
+
- name: progress
|
|
164
|
+
- name: meter
|
|
165
|
+
- name: fieldset
|
|
166
|
+
boolean:
|
|
167
|
+
- disabled
|
|
168
|
+
- name: legend
|
|
169
|
+
|
|
170
|
+
# Interactive elements
|
|
171
|
+
- name: details
|
|
172
|
+
- name: summary
|
|
173
|
+
- name: dialog
|
|
174
|
+
- name: menu
|
|
175
|
+
- name: menuitem
|
|
176
|
+
|
|
177
|
+
# Table content
|
|
178
|
+
- name: table
|
|
179
|
+
- name: caption
|
|
180
|
+
- name: colgroup
|
|
181
|
+
- name: col
|
|
182
|
+
void: true
|
|
183
|
+
- name: thead
|
|
184
|
+
- name: tbody
|
|
185
|
+
- name: tfoot
|
|
186
|
+
- name: tr
|
|
187
|
+
- name: td
|
|
188
|
+
- name: th
|
|
189
|
+
|
|
190
|
+
# Scripting
|
|
191
|
+
- name: canvas
|
|
192
|
+
- name: slot
|
|
193
|
+
- name: portal
|
|
194
|
+
|
data/lib/ruex/version.rb
ADDED
data/lib/ruex.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ruex
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Takanobu Maekawa
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: |-
|
|
13
|
+
A library and CLI tool that generates HTML using plain Ruby expressions.
|
|
14
|
+
It is intended for static site or page generation, and is not suitable as a dynamic web page renderer.
|
|
15
|
+
executables:
|
|
16
|
+
- ruex
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- LICENSE
|
|
21
|
+
- README.md
|
|
22
|
+
- VERSION
|
|
23
|
+
- bin/ruex
|
|
24
|
+
- lib/ruex.rb
|
|
25
|
+
- lib/ruex/cli.rb
|
|
26
|
+
- lib/ruex/core.rb
|
|
27
|
+
- lib/ruex/helper/cli.rb
|
|
28
|
+
- lib/ruex/tags.yml
|
|
29
|
+
- lib/ruex/version.rb
|
|
30
|
+
homepage: https://github.com/tmkw/ruex
|
|
31
|
+
licenses:
|
|
32
|
+
- BSD-2-Clause
|
|
33
|
+
metadata:
|
|
34
|
+
homepage_uri: https://github.com/tmkw/ruex
|
|
35
|
+
source_code_uri: https://github.com/tmkw/ruex
|
|
36
|
+
rdoc_options: []
|
|
37
|
+
require_paths:
|
|
38
|
+
- lib
|
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
40
|
+
requirements:
|
|
41
|
+
- - ">="
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: 4.0.0
|
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '0'
|
|
49
|
+
requirements: []
|
|
50
|
+
rubygems_version: 4.0.3
|
|
51
|
+
specification_version: 4
|
|
52
|
+
summary: Static HTML generation with plain Ruby expressions
|
|
53
|
+
test_files: []
|