htx 0.0.9 → 0.1.1
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 +4 -4
- data/LICENSE +1 -1
- data/README.md +27 -13
- data/VERSION +1 -1
- data/lib/htx/template.rb +46 -50
- data/lib/htx/version.rb +1 -1
- data/lib/htx.rb +6 -14
- 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: bbd968d3152b9ef4c7813f1e08139a4dc386ae99f8822758a0eb2574eb8beab5
|
4
|
+
data.tar.gz: e2fa1f7035a09e3518be5e3fe5f8c053fd4d7d8022f6f3d121e8caecea180d6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c15b1d31a60c7447137bd599bb2e7e767896d4f8ebef93878efb5981138beddd7a712744a974ea4150edd9b511593acf1d8ca0cb6754ae04f17ffbc85ce9ed1
|
7
|
+
data.tar.gz: adab39540cfe4261e26697a0a6af1081a620ab55305b38abcae5e446a919dfd5a5ac96cc01b5fa3cdd28bbbd3e6755c1c00a98f492530333ef102da43b4c5381
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright 2019-
|
1
|
+
Copyright 2019-2023 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
@@ -1,8 +1,7 @@
|
|
1
1
|
# HTX Ruby Compiler
|
2
2
|
|
3
3
|
HTX templates are compiled to JavaScript before being used. This library provides a Ruby implementation of
|
4
|
-
the compiler. For more information on HTX, see
|
5
|
-
[https://github.com/npickens/htx](https://github.com/npickens/htx).
|
4
|
+
the compiler. For more information on HTX, see the main [README](https://github.com/npickens/htx).
|
6
5
|
|
7
6
|
## Installation
|
8
7
|
|
@@ -20,24 +19,39 @@ gem install htx
|
|
20
19
|
|
21
20
|
## Usage
|
22
21
|
|
23
|
-
|
24
|
-
|
22
|
+
HTX templates can be compiled to either a JavaScript module format or an IIFE assigned to a property on
|
23
|
+
either `globalThis` or a custom object. To compile as a module:
|
25
24
|
|
26
25
|
```ruby
|
27
26
|
path = '/components/crew.htx'
|
28
|
-
|
27
|
+
content = File.read("/assets#{path}")
|
28
|
+
|
29
|
+
HTX.compile(path, content, as_module: true, import_path: 'vendor/htx.js')
|
30
|
+
# => "import * as HTX from 'vendor/htx.js'
|
31
|
+
#
|
32
|
+
# ...
|
33
|
+
#
|
34
|
+
# export function Template { ... }"
|
35
|
+
#
|
36
|
+
```
|
29
37
|
|
30
|
-
|
38
|
+
Note that with the module format the name of the template does not appear anywhere in its compiled form, but
|
39
|
+
is still used/useful for tracking down errors when compilation is handled by an overall asset management
|
40
|
+
system (such as [Darkroom](https://github.com/npickens/darkroom)).
|
31
41
|
|
32
|
-
|
33
|
-
# // ...
|
34
|
-
# }
|
42
|
+
To compile to an IIFE assigned to a custom object:
|
35
43
|
|
36
|
-
|
44
|
+
```ruby
|
45
|
+
HTX.compile(path, content, as_module: false, assign_to: 'myTemplates')
|
46
|
+
# => "myTemplates['/components/crew.htx'] = ..."
|
47
|
+
```
|
37
48
|
|
38
|
-
|
39
|
-
|
40
|
-
|
49
|
+
Options can be configured globally so they don't have to be passed to `HTX.compile` every time:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
HTX.as_module = true # Default: false
|
53
|
+
HTX.import_path = 'vendor/htx.js' # Default: "/htx/htx.js"
|
54
|
+
HTX.assign_to = 'myTemplates' # Default: "globalThis"
|
41
55
|
```
|
42
56
|
|
43
57
|
## Contributing
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.1
|
data/lib/htx/template.rb
CHANGED
@@ -17,7 +17,6 @@ module HTX
|
|
17
17
|
'svg' => 'http://www.w3.org/2000/svg',
|
18
18
|
}.freeze
|
19
19
|
|
20
|
-
INDENT_VALID = /^( +|\t+)$/.freeze
|
21
20
|
INDENT_GUESS = /^( +|\t+)(?=\S)/.freeze
|
22
21
|
INDENT_REGEX = /\n(?=[^\n])/.freeze
|
23
22
|
|
@@ -32,17 +31,14 @@ module HTX
|
|
32
31
|
NON_WHITESPACE = /\S/.freeze
|
33
32
|
|
34
33
|
##
|
35
|
-
# Returns
|
36
|
-
# <htx-content>), will return true if Nokogiri's HTML5 parser is available. To use it now, monkey patch
|
37
|
-
# this method to return true.
|
34
|
+
# Returns true if Nokogiri's HTML5 parser is available.
|
38
35
|
#
|
39
36
|
def self.html5_parser?
|
40
|
-
|
37
|
+
defined?(Nokogiri::HTML5)
|
41
38
|
end
|
42
39
|
|
43
40
|
##
|
44
|
-
# Returns Nokogiri's HTML5 parser if available
|
45
|
-
# otherwise.
|
41
|
+
# Returns Nokogiri's HTML5 parser if available or Nokogiri's default HTML (4) parser otherwise.
|
46
42
|
#
|
47
43
|
def self.nokogiri_parser
|
48
44
|
html5_parser? ? Nokogiri::HTML5 : Nokogiri::HTML
|
@@ -62,24 +58,15 @@ module HTX
|
|
62
58
|
##
|
63
59
|
# Compiles the HTX template.
|
64
60
|
#
|
65
|
-
# * +
|
66
|
-
# * +
|
67
|
-
#
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
@
|
72
|
-
@
|
73
|
-
|
74
|
-
' ' * indent
|
75
|
-
elsif indent && !indent.match?(INDENT_VALID)
|
76
|
-
raise("Invalid indent value #{indent.inspect}: only spaces and tabs (but not both) are allowed")
|
77
|
-
else
|
78
|
-
indent || @content[INDENT_GUESS] || INDENT_DEFAULT
|
79
|
-
end
|
80
|
-
|
81
|
-
warn('The indent: option for HTX template compilation is deprecated.') unless indent_omitted
|
82
|
-
|
61
|
+
# * +as_module+ - Boolean indicating whether or not to compile as a JavaScript module.
|
62
|
+
# * +import_path+ - Path to HTX JavaScript library for module import statement.
|
63
|
+
# * +assign_to+ - JavaScript object to assign the template function to if module not being used.
|
64
|
+
#
|
65
|
+
def compile(as_module: nil, import_path: nil, assign_to: nil)
|
66
|
+
@as_module = as_module.nil? ? HTX.as_module : as_module
|
67
|
+
@import_path = import_path || HTX.import_path
|
68
|
+
@assign_to = assign_to || HTX.assign_to
|
69
|
+
@base_indent = @indent = @content[INDENT_GUESS] || INDENT_DEFAULT
|
83
70
|
@static_key = 0
|
84
71
|
@close_count = 0
|
85
72
|
@whitespace_buff = nil
|
@@ -158,14 +145,33 @@ module HTX
|
|
158
145
|
# * +node+ - Nokogiri node to process.
|
159
146
|
#
|
160
147
|
def process_fragment_node(node)
|
161
|
-
append("#{
|
162
|
-
|
148
|
+
append("#{
|
149
|
+
@as_module ? "import * as HTX from '#{@import_path}'\n\n"
|
150
|
+
: "#{@assign_to}['#{@name}'] = ((HTX) => {\n#{@indent}"
|
151
|
+
}function render($renderer) {\n")
|
152
|
+
|
153
|
+
@indent = @base_indent * 2 unless @as_module
|
163
154
|
|
164
155
|
node.children.each do |child|
|
165
156
|
process(child)
|
166
157
|
end
|
167
158
|
|
168
|
-
append("\n
|
159
|
+
append("\n\n#{@indent}return $renderer.rootNode")
|
160
|
+
|
161
|
+
@indent = @as_module ? '' : @base_indent
|
162
|
+
|
163
|
+
append(
|
164
|
+
<<~JS
|
165
|
+
|
166
|
+
#{@indent}}
|
167
|
+
|
168
|
+
#{@indent}#{@as_module ? 'export' : 'return'} function Template(context) {
|
169
|
+
#{@indent}#{@base_indent}this.render = render.bind(context, new HTX.Renderer)
|
170
|
+
#{@indent}}#{
|
171
|
+
"\n})(globalThis.HTX ||= {});" unless @as_module}
|
172
|
+
JS
|
173
|
+
)
|
174
|
+
|
169
175
|
flush
|
170
176
|
end
|
171
177
|
|
@@ -179,15 +185,10 @@ module HTX
|
|
179
185
|
children = node.children
|
180
186
|
childless = children.empty? || (children.size == 1 && self.class.formatting_node?(children.first))
|
181
187
|
dynamic_key = self.class.attribute_value(node.attr(DYNAMIC_KEY_ATTR))
|
182
|
-
attributes = self.class.process_attributes(node)
|
188
|
+
attributes = self.class.process_attributes(node, xmlns: xmlns)
|
183
189
|
xmlns ||= !!self.class.namespace(node)
|
184
190
|
|
185
191
|
if self.class.htx_content_node?(node)
|
186
|
-
if node.name != CONTENT_TAG
|
187
|
-
warn("#{@name}:#{node.line}: The <#{node.name}> tag has been deprecated. Use <#{CONTENT_TAG}> "\
|
188
|
-
"for identical functionality.")
|
189
|
-
end
|
190
|
-
|
191
192
|
if attributes.size > 0
|
192
193
|
raise(MalformedTemplateError.new("<#{node.name}> tags may not have attributes other than "\
|
193
194
|
"#{DYNAMIC_KEY_ATTR}", @name, node))
|
@@ -269,7 +270,7 @@ module HTX
|
|
269
270
|
close_count = @close_count
|
270
271
|
@close_count = 0
|
271
272
|
|
272
|
-
append("
|
273
|
+
append("$renderer.close(#{close_count unless close_count == 1})")
|
273
274
|
end
|
274
275
|
|
275
276
|
if @whitespace_buff
|
@@ -289,9 +290,9 @@ module HTX
|
|
289
290
|
end
|
290
291
|
|
291
292
|
##
|
292
|
-
# Appends an
|
293
|
+
# Appends an +$renderer.node+ call to the compiled template function string.
|
293
294
|
#
|
294
|
-
# * +args+ - Arguments to use for the
|
295
|
+
# * +args+ - Arguments to use for the +$renderer.node+ call (any +nil+ ones are removed).
|
295
296
|
#
|
296
297
|
def append_htx_node(*args)
|
297
298
|
return if args.first.nil?
|
@@ -300,7 +301,7 @@ module HTX
|
|
300
301
|
args << 0 unless args.last.kind_of?(Integer)
|
301
302
|
args[-1] |= (@static_key += 1) << FLAG_BITS
|
302
303
|
|
303
|
-
append("
|
304
|
+
append("$renderer.node(#{args.join(', ')})")
|
304
305
|
end
|
305
306
|
|
306
307
|
##
|
@@ -336,7 +337,7 @@ module HTX
|
|
336
337
|
# * +node+ - Nokogiri node to check.
|
337
338
|
#
|
338
339
|
def self.htx_content_node?(node)
|
339
|
-
node
|
340
|
+
node&.name == CONTENT_TAG
|
340
341
|
end
|
341
342
|
|
342
343
|
##
|
@@ -344,10 +345,10 @@ module HTX
|
|
344
345
|
#
|
345
346
|
# * +node+ - Nokogiri node to process the attributes of.
|
346
347
|
#
|
347
|
-
def self.process_attributes(node)
|
348
|
+
def self.process_attributes(node, xmlns:)
|
348
349
|
attributes = []
|
349
350
|
|
350
|
-
if !node.attribute('xmlns') && (xmlns = namespace(node))
|
351
|
+
if !xmlns && !node.attribute('xmlns') && (xmlns = namespace(node))
|
351
352
|
attributes.push(
|
352
353
|
attribute_name('xmlns'),
|
353
354
|
attribute_value(xmlns)
|
@@ -402,15 +403,10 @@ module HTX
|
|
402
403
|
text ? TextParser.new(text, statement_allowed: false).parse : nil
|
403
404
|
end
|
404
405
|
|
405
|
-
# The Nokogiri
|
406
|
-
#
|
407
|
-
#
|
408
|
-
#
|
409
|
-
# Note: Nokogiri's newer HTML5 parser resulting from the Nokogumbo merge fixes this issue, but it is
|
410
|
-
# currently not available for JRuby. It also does not parse <:> as a tag, which is why it's been
|
411
|
-
# deprecated in favor of <htx-content>. Once support for <:> has been completely removed, the HTML5
|
412
|
-
# parser will be used for regular Ruby and this tag and attribute mapping hack reserved for JRuby (and
|
413
|
-
# any other potential environments where the HTML5 parser is not available).
|
406
|
+
# The Nokogiri::HTML5 parser is used whenever possible, which correctly handles mix-cased SVG tag and
|
407
|
+
# attribute names. But when falling back to the Nokogiri::HTML parser (e.g. in JRuby environments where
|
408
|
+
# Nokogiri::HTML5 is not available), all tag and attribute names get downcased. These maps are used to
|
409
|
+
# restore the correct case.
|
414
410
|
|
415
411
|
# Source: https://developer.mozilla.org/en-US/docs/Web/SVG/Element
|
416
412
|
TAG_MAP = %w[
|
data/lib/htx/version.rb
CHANGED
data/lib/htx.rb
CHANGED
@@ -11,6 +11,12 @@ require('htx/version')
|
|
11
11
|
module HTX
|
12
12
|
EMPTY_HASH = {}.freeze
|
13
13
|
|
14
|
+
@as_module = false
|
15
|
+
@import_path = '/htx/htx.js'
|
16
|
+
@assign_to = 'globalThis'
|
17
|
+
|
18
|
+
class << self; attr_accessor(:as_module, :import_path, :assign_to); end
|
19
|
+
|
14
20
|
##
|
15
21
|
# Convenience method to create a new Template instance and compile it.
|
16
22
|
#
|
@@ -21,18 +27,4 @@ module HTX
|
|
21
27
|
def self.compile(name, content, options = EMPTY_HASH)
|
22
28
|
Template.new(name, content).compile(**options)
|
23
29
|
end
|
24
|
-
|
25
|
-
##
|
26
|
-
# DEPRECATED. Use HTX::Template.new instead. HTX was formerly a class that would be instantiated for
|
27
|
-
# compilation. This method allows HTX.new calls to continue working (but support will be removed in the
|
28
|
-
# near future).
|
29
|
-
#
|
30
|
-
# * +name+ - Template name. Conventionally the path of the template file.
|
31
|
-
# * +content+ - Template content.
|
32
|
-
#
|
33
|
-
def self.new(name, content)
|
34
|
-
warn('HTX.new is deprecated. Please use HTX::Template.new instead.')
|
35
|
-
|
36
|
-
Template.new(name, content)
|
37
|
-
end
|
38
30
|
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.
|
4
|
+
version: 0.1.1
|
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: 2023-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -96,7 +96,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
98
|
requirements: []
|
99
|
-
rubygems_version: 3.
|
99
|
+
rubygems_version: 3.4.15
|
100
100
|
signing_key:
|
101
101
|
specification_version: 4
|
102
102
|
summary: A Ruby compiler for HTX templates.
|