htx 0.0.9 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 395620b3af20b4da17e4413632418481ee28d6d0fe6b46427af240475087efce
4
- data.tar.gz: bc15b61294daaf218b3a3d5a106de7c9279a7d9e8cb7ebd01002fcd618491b1f
3
+ metadata.gz: bbd968d3152b9ef4c7813f1e08139a4dc386ae99f8822758a0eb2574eb8beab5
4
+ data.tar.gz: e2fa1f7035a09e3518be5e3fe5f8c053fd4d7d8022f6f3d121e8caecea180d6a
5
5
  SHA512:
6
- metadata.gz: 83805b10f30d1846a187b458579a0748339a3956a4123226b7b9ebdb6dcff6cae3dbcd94913c1bbab2c91186ef3f46642f30a4ed9c3f30b072b3efe2f2ceb1ca
7
- data.tar.gz: 26e48419a9a719f1b8b582ef9e525ffcc37affdcb279f0cba95c6fe4cd2108cc6ec66e9ba4d3216a0ef02aad506d56c4743b059916ba78409f0dc672a760a1fc
6
+ metadata.gz: 3c15b1d31a60c7447137bd599bb2e7e767896d4f8ebef93878efb5981138beddd7a712744a974ea4150edd9b511593acf1d8ca0cb6754ae04f17ffbc85ce9ed1
7
+ data.tar.gz: adab39540cfe4261e26697a0a6af1081a620ab55305b38abcae5e446a919dfd5a5ac96cc01b5fa3cdd28bbbd3e6755c1c00a98f492530333ef102da43b4c5381
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2019-2022 Nate Pickens
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
- To compile an HTX template, pass a name (conventionally the path of the template file) and template content
24
- as strings to the `HTX.compile` method (all other arguments are optional):
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
- template = File.read(File.join('some/asset/dir', path))
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
- HTX.compile(path, template)
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
- # window['/components/crew.htx'] = function(htx) {
33
- # // ...
34
- # }
42
+ To compile to an IIFE assigned to a custom object:
35
43
 
36
- HTX.compile(path, template, assign_to: 'myTemplates')
44
+ ```ruby
45
+ HTX.compile(path, content, as_module: false, assign_to: 'myTemplates')
46
+ # => "myTemplates['/components/crew.htx'] = ..."
47
+ ```
37
48
 
38
- # myTemplates['/components/crew.htx'] = function(htx) {
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.0.9
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 false. In the near future when support for the <:> tag has been dropped (in favor of
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
- false # !!defined?(Nokogiri::HTML5)
37
+ defined?(Nokogiri::HTML5)
41
38
  end
42
39
 
43
40
  ##
44
- # Returns Nokogiri's HTML5 parser if available and enabled, and Nokogiri's regular HTML parser
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
- # * +assign_to+ - JavaScript object to assign the template function to (default: +window+).
66
- # * +indent+ - DEPRECATED. Indentation amount (number) or string (must be only spaces or tabs but not
67
- # both) to use for indentation of compiled output (default: indentation of first indented line of
68
- # uncompiled template).
69
- #
70
- def compile(assign_to: nil, indent: (indent_omitted = true; nil))
71
- @assign_to = assign_to || 'window'
72
- @indent =
73
- if indent.kind_of?(Numeric)
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("#{@assign_to}['#{@name}'] = function(htx) {")
162
- @whitespace_buff = "\n"
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}\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("htx.close(#{close_count unless close_count == 1})")
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 +htx.node+ call to the compiled template function string.
293
+ # Appends an +$renderer.node+ call to the compiled template function string.
293
294
  #
294
- # * +args+ - Arguments to use for the +htx.node+ call (any +nil+ ones are removed).
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("htx.node(#{args.join(', ')})")
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 && (node.name == CONTENT_TAG || node.name == 'htx-text' || node.name == ':')
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 HTML parser downcases all tag and attribute names, but SVG tags and attributes are case
406
- # sensitive and often mix cased. These maps are used to restore the correct case of such tags and
407
- # attributes.
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTX
4
- VERSION = '0.0.9'
4
+ VERSION = '0.1.1'
5
5
  end
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.0.9
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: 2022-03-31 00:00:00.000000000 Z
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.2.32
99
+ rubygems_version: 3.4.15
100
100
  signing_key:
101
101
  specification_version: 4
102
102
  summary: A Ruby compiler for HTX templates.