htx 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +9 -0
- data/lib/htx.rb +41 -20
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ad1aaabd0904124ebc249af10fd5e8e93c11009f0fc0f7cb31f2f8656d4bb47d
|
4
|
+
data.tar.gz: 44e8808f07d173efc4830f07e0732822715e9837764518b780efe300ff08f2e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c7533d1b88bfc3365794cd18b8f26083364a060d4fdc1d4d1b3cef6dcb13af87e2ce4beb06553846da8add2481bda8fae5666a614b1c0ffff8b97d2b5aadd9d
|
7
|
+
data.tar.gz: ef37756cd45b5e7c58ababb1b9350467748816b998f50976055f2541356d282bd15bad20d47325f4ba4a32af1256b7ca407293b45ec496ba23fab494fd4c9f31
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright 2019 Nate Pickens
|
1
|
+
Copyright 2019-2020 Nate Pickens
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
4
4
|
documentation files (the "Software"), to deal in the Software without restriction, including without
|
data/README.md
CHANGED
@@ -29,11 +29,20 @@ template = File.read(File.join('some/asset/dir', path))
|
|
29
29
|
|
30
30
|
HTX.compile(path, template)
|
31
31
|
|
32
|
+
# Or to attach to a custom object instead of `window`:
|
33
|
+
HTX.compile(path, template, assign_to: 'myTemplates')
|
34
|
+
|
32
35
|
# Result:
|
33
36
|
#
|
34
37
|
# window['/my/hot/template.htx'] = function(htx) {
|
35
38
|
# ...
|
36
39
|
# }
|
40
|
+
#
|
41
|
+
# If `assign_to` is specified:
|
42
|
+
#
|
43
|
+
# myTemplates['/components/people.htx'] = function(htx) {
|
44
|
+
# // ...
|
45
|
+
# }
|
37
46
|
```
|
38
47
|
|
39
48
|
## Contributing
|
data/lib/htx.rb
CHANGED
@@ -6,9 +6,7 @@ require('nokogiri')
|
|
6
6
|
# A Ruby compiler for HTX templates.
|
7
7
|
#
|
8
8
|
class HTX
|
9
|
-
|
10
|
-
|
11
|
-
VERSION = '0.0.2'
|
9
|
+
VERSION = '0.0.4'
|
12
10
|
|
13
11
|
CHILDLESS = 0b01
|
14
12
|
TEXT_NODE = 0b10
|
@@ -34,11 +32,13 @@ class HTX
|
|
34
32
|
CONTROL_STATEMENT = /[{}();]/.freeze
|
35
33
|
CLOSE_STATEMENT = /;?\s*htx\.close\((\d*)\);?(\s*)\z/.freeze
|
36
34
|
|
35
|
+
EMPTY_HASH = {}.freeze
|
36
|
+
|
37
37
|
##
|
38
38
|
# Convenience method to create a new instance and immediately call compile on it.
|
39
39
|
#
|
40
|
-
def self.compile(name, template)
|
41
|
-
new(name, template).compile
|
40
|
+
def self.compile(name, template, options = EMPTY_HASH)
|
41
|
+
new(name, template).compile(options)
|
42
42
|
end
|
43
43
|
|
44
44
|
##
|
@@ -53,16 +53,17 @@ class HTX
|
|
53
53
|
##
|
54
54
|
# Compiles the HTX template.
|
55
55
|
#
|
56
|
-
def compile
|
56
|
+
def compile(options = EMPTY_HASH)
|
57
57
|
doc = Nokogiri::HTML::DocumentFragment.parse(@template)
|
58
58
|
root_nodes = doc.children.select { |n| n.element? || (n.text? && n.text.strip != '') }
|
59
59
|
|
60
|
-
if root_nodes.
|
61
|
-
raise(MalformedTemplateError.new('
|
60
|
+
if (text_node = root_nodes.find(&:text?))
|
61
|
+
raise(MalformedTemplateError.new('text nodes are not allowed at root level', @name, text_node))
|
62
62
|
elsif root_nodes.size == 0
|
63
|
-
raise(MalformedTemplateError.new('
|
63
|
+
raise(MalformedTemplateError.new('a root node is required', @name))
|
64
64
|
elsif root_nodes.size > 1
|
65
|
-
raise(MalformedTemplateError.new(
|
65
|
+
raise(MalformedTemplateError.new("root node already defined on line #{root_nodes[0].line}", @name,
|
66
|
+
root_nodes[1]))
|
66
67
|
end
|
67
68
|
|
68
69
|
@compiled = ''.dup
|
@@ -72,7 +73,7 @@ class HTX
|
|
72
73
|
@compiled.rstrip!
|
73
74
|
|
74
75
|
<<~EOS
|
75
|
-
window['#{@name}'] = function(htx) {
|
76
|
+
#{options[:assign_to] || 'window'}['#{@name}'] = function(htx) {
|
76
77
|
#{@compiled}
|
77
78
|
}
|
78
79
|
EOS
|
@@ -90,6 +91,10 @@ class HTX
|
|
90
91
|
dynamic_key = process_value(node.attr(DYNAMIC_KEY_ATTR), :attr)
|
91
92
|
|
92
93
|
if node.text? || node.name == ':'
|
94
|
+
if (non_text_node = node.children.find { |n| !n.text? })
|
95
|
+
raise(MalformedTemplateError.new('dummy tags may not contain child tags', @name, non_text_node))
|
96
|
+
end
|
97
|
+
|
93
98
|
text = (node.text? ? node : node.children).text
|
94
99
|
|
95
100
|
if (value = process_value(text))
|
@@ -113,14 +118,16 @@ class HTX
|
|
113
118
|
attrs << process_value(attr.value, :attr)
|
114
119
|
end
|
115
120
|
|
121
|
+
childless = node.children.empty? || (node.children.size == 1 && node.children[0].text.strip == '')
|
122
|
+
|
116
123
|
append("htx.node(#{[
|
117
124
|
"'#{TAG_MAP[node.name] || node.name}'",
|
118
125
|
attrs,
|
119
126
|
dynamic_key,
|
120
|
-
((@static_key += 1) << FLAG_BITS) | (
|
127
|
+
((@static_key += 1) << FLAG_BITS) | (childless ? CHILDLESS : 0),
|
121
128
|
].compact.flatten.join(', ')})")
|
122
129
|
|
123
|
-
unless
|
130
|
+
unless childless
|
124
131
|
process(node)
|
125
132
|
|
126
133
|
count = ''
|
@@ -198,6 +205,18 @@ class HTX
|
|
198
205
|
value.encode('ascii', fallback: ->(c) { "\\u#{c.ord.to_s(16).rjust(4, '0')}" })
|
199
206
|
end
|
200
207
|
|
208
|
+
class MalformedTemplateError < StandardError
|
209
|
+
def initialize(message, name, node = nil)
|
210
|
+
if node
|
211
|
+
line = node.line
|
212
|
+
line = node.parent.line if line < 1
|
213
|
+
line = nil if line == -1
|
214
|
+
end
|
215
|
+
|
216
|
+
super("Malformed template #{name}#{":#{line}" if line}: #{message}")
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
201
220
|
# The Nokogiri HTML parser downcases all tag and attribute names, but SVG tags and attributes are case
|
202
221
|
# sensitive and often mix cased. These maps are used to restore the correct case of such tags and
|
203
222
|
# attributes.
|
@@ -209,12 +228,14 @@ class HTX
|
|
209
228
|
].map { |tag| [tag.downcase, tag] }.to_h.freeze
|
210
229
|
|
211
230
|
ATTR_MAP = %w[
|
212
|
-
attributeName baseFrequency calcMode clipPathUnits
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
231
|
+
allowReorder attributeName attributeType autoReverse baseFrequency baseProfile calcMode clipPathUnits
|
232
|
+
contentScriptType contentStyleType diffuseConstant edgeMode externalResourcesRequired filterRes
|
233
|
+
filterUnits glyphRef gradientTransform gradientUnits kernelMatrix kernelUnitLength keyPoints keySplines
|
234
|
+
keyTimes lengthAdjust limitingConeAngle markerHeight markerUnits markerWidth maskContentUnits maskUnits
|
235
|
+
numOctaves pathLength patternContentUnits patternTransform patternUnits pointsAtX pointsAtY pointsAtZ
|
236
|
+
preserveAlpha preserveAspectRatio primitiveUnits refX refY referrerPolicy repeatCount repeatDur
|
237
|
+
requiredExtensions requiredFeatures specularConstant specularExponent spreadMethod startOffset
|
238
|
+
stdDeviation stitchTiles surfaceScale systemLanguage tableValues targetX targetY textLength viewBox
|
239
|
+
viewTarget xChannelSelector yChannelSelector zoomAndPan
|
219
240
|
].map { |attr| [attr.downcase, attr] }.to_h.freeze
|
220
241
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: htx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nate Pickens
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-04-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -85,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
85
|
- !ruby/object:Gem::Version
|
86
86
|
version: '0'
|
87
87
|
requirements: []
|
88
|
-
rubygems_version: 3.
|
88
|
+
rubygems_version: 3.1.2
|
89
89
|
signing_key:
|
90
90
|
specification_version: 4
|
91
91
|
summary: A Ruby compiler for HTX templates.
|