htx 0.1.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83c2b45f8852d11b5faa35989c0552a4135c3270d20aaaa2af8d170e696ad840
4
- data.tar.gz: dcbbb3aac2484f55b445a029c9916e282dc75b93197f630b40227110aba02c28
3
+ metadata.gz: d869f62a146bed898334d085ce1dc507d214950d166454b65e502058bc68e6b6
4
+ data.tar.gz: fd81c8b3b82f2bd95e85899f14ee35f881f11a8b0f8b07b38af1f5b0ee599a87
5
5
  SHA512:
6
- metadata.gz: 8a26b13b0f0cdddf7d9338f1876c23e59adaef4abd2d706cae4a984bd74ca207465e93d6c1d1f0877adf5f27999ddbfd59d93c703ffe098ea7cfc239bc8f391d
7
- data.tar.gz: e6ace0fd8c2289e1b2062e6f9e976e017b3e639cfd0eb0777bf5e4bd9ded53d8774c843cfcb1cc55a1c491d0fe6d4f81e337455897ec471bebc0d333db202ba5
6
+ metadata.gz: bd23ac9b3363d467c1e47258654ed3d9a136e32e66379374b2d33a1abeeb358a1957de66364ad5af3dd20768a4ace5226ccb57c256b18b232de0381fe3144d25
7
+ data.tar.gz: e304e3e8b87c093eabc07628c0179c15eef76d9870483d96a129ce9f2f1358d0ec50df14e369e2c052aa59b992bcae2647753f3cb62f9e37de1d06b221332f4b
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2019-2023 Nate Pickens
1
+ Copyright 2019-2024 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
- # globalThis['/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.1.0
1
+ 1.0.0
data/lib/htx/template.rb CHANGED
@@ -20,8 +20,8 @@ module HTX
20
20
  INDENT_GUESS = /^( +|\t+)(?=\S)/.freeze
21
21
  INDENT_REGEX = /\n(?=[^\n])/.freeze
22
22
 
23
- NO_SEMICOLON_BEGIN = /\A\s*[\n;}]/.freeze
24
- NO_SEMICOLON_END = /(\A|[\n;{}][^\S\n]*)\z/.freeze
23
+ AUTO_SEMICOLON_BEGIN = /\A\s*[\n;}]/.freeze
24
+ AUTO_SEMICOLON_END = /(\A|[\n;{}][^\S\n]*)\z/.freeze
25
25
 
26
26
  NEWLINE_BEGIN = /\A\s*\n/.freeze
27
27
  NEWLINE_END = /\n[^\S\n]*\z/.freeze
@@ -58,10 +58,14 @@ module HTX
58
58
  ##
59
59
  # Compiles the HTX template.
60
60
  #
61
- # * +assign_to+ - JavaScript object to assign the template function to (default: +globalThis+).
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.
62
64
  #
63
- def compile(assign_to: nil)
64
- @assign_to = assign_to || 'globalThis'
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
65
69
  @base_indent = @indent = @content[INDENT_GUESS] || INDENT_DEFAULT
66
70
  @static_key = 0
67
71
  @close_count = 0
@@ -141,32 +145,30 @@ module HTX
141
145
  # * +node+ - Nokogiri node to process.
142
146
  #
143
147
  def process_fragment_node(node)
144
- append(
145
- <<~JS
146
- #{@assign_to}['#{@name}'] = ((HTX) => {
147
- #{@indent}function render($rndr) {
148
- JS
149
- )
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")
150
152
 
151
- @indent = @base_indent * 2
153
+ @indent = @base_indent * 2 unless @as_module
152
154
 
153
155
  node.children.each do |child|
154
156
  process(child)
155
157
  end
156
158
 
157
- append("\n\n#{@indent}return $rndr.rootNode")
159
+ append("\n\n#{@indent}return $renderer.rootNode")
158
160
 
159
- @indent = @base_indent
161
+ @indent = @as_module ? '' : @base_indent
160
162
 
161
163
  append(
162
- +<<~JS
164
+ <<~JS
163
165
 
164
166
  #{@indent}}
165
167
 
166
- #{@indent}return function Template(context) {
167
- #{@indent * 2}this.render = render.bind(context, new HTX.Renderer)
168
- #{@indent}}
169
- })(globalThis.HTX ||= {});
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}
170
172
  JS
171
173
  )
172
174
 
@@ -180,6 +182,7 @@ module HTX
180
182
  # * +xmlns+ - True if node is the descendant of a node with an xmlns attribute.
181
183
  #
182
184
  def process_element_node(node, xmlns: false)
185
+ is_template = node.name == 'template'
183
186
  children = node.children
184
187
  childless = children.empty? || (children.size == 1 && self.class.formatting_node?(children.first))
185
188
  dynamic_key = self.class.attribute_value(node.attr(DYNAMIC_KEY_ATTR))
@@ -199,19 +202,21 @@ module HTX
199
202
  dynamic_key: dynamic_key,
200
203
  )
201
204
  else
202
- append_htx_node(
203
- "'#{self.class.tag_name(node.name)}'",
204
- *attributes,
205
- dynamic_key,
206
- ELEMENT | (childless ? CHILDLESS : 0) | (xmlns ? XMLNS : 0),
207
- )
205
+ unless is_template
206
+ append_htx_node(
207
+ "'#{self.class.tag_name(node.name)}'",
208
+ *attributes,
209
+ dynamic_key,
210
+ ELEMENT | (childless ? CHILDLESS : 0) | (xmlns ? XMLNS : 0),
211
+ )
212
+ end
208
213
 
209
214
  unless childless
210
215
  children.each do |child|
211
216
  process(child, xmlns: xmlns)
212
217
  end
213
218
 
214
- @close_count += 1
219
+ @close_count += 1 unless is_template
215
220
  end
216
221
  end
217
222
  end
@@ -268,7 +273,7 @@ module HTX
268
273
  close_count = @close_count
269
274
  @close_count = 0
270
275
 
271
- append("$rndr.close(#{close_count unless close_count == 1})")
276
+ append("$renderer.close(#{close_count unless close_count == 1})")
272
277
  end
273
278
 
274
279
  if @whitespace_buff
@@ -279,8 +284,14 @@ module HTX
279
284
 
280
285
  if (confirmed_newline || @statement_buff.match?(NEWLINE_END)) && !text.match?(NEWLINE_BEGIN)
281
286
  @statement_buff << @indent
282
- elsif !@statement_buff.match?(NO_SEMICOLON_END) && !text.match?(NO_SEMICOLON_BEGIN)
283
- @statement_buff << ";#{' ' unless text.match?(WHITESPACE_BEGIN)}"
287
+ else
288
+ unless @statement_buff.match?(AUTO_SEMICOLON_END) || text.match?(AUTO_SEMICOLON_BEGIN)
289
+ @statement_buff << ";"
290
+ end
291
+
292
+ unless @statement_buff.empty? || text.match?(WHITESPACE_BEGIN)
293
+ @statement_buff << ' '
294
+ end
284
295
  end
285
296
 
286
297
  flush if text.match?(NON_WHITESPACE)
@@ -288,9 +299,9 @@ module HTX
288
299
  end
289
300
 
290
301
  ##
291
- # Appends an +htx.node+ call to the compiled template function string.
302
+ # Appends an +$renderer.node+ call to the compiled template function string.
292
303
  #
293
- # * +args+ - Arguments to use for the +htx.node+ call (any +nil+ ones are removed).
304
+ # * +args+ - Arguments to use for the +$renderer.node+ call (any +nil+ ones are removed).
294
305
  #
295
306
  def append_htx_node(*args)
296
307
  return if args.first.nil?
@@ -299,7 +310,7 @@ module HTX
299
310
  args << 0 unless args.last.kind_of?(Integer)
300
311
  args[-1] |= (@static_key += 1) << FLAG_BITS
301
312
 
302
- append("$rndr.node(#{args.join(', ')})")
313
+ append("$renderer.node(#{args.join(', ')})")
303
314
  end
304
315
 
305
316
  ##
@@ -408,24 +419,100 @@ module HTX
408
419
 
409
420
  # Source: https://developer.mozilla.org/en-US/docs/Web/SVG/Element
410
421
  TAG_MAP = %w[
411
- animateMotion animateTransform clipPath feBlend feColorMatrix feComponentTransfer feComposite
412
- feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feDropShadow feFlood feFuncA
413
- feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight
414
- feSpecularLighting feSpotLight feTile feTurbulence foreignObject linearGradient radialGradient
422
+ animateMotion
423
+ animateTransform
424
+ clipPath
425
+ feBlend
426
+ feColorMatrix
427
+ feComponentTransfer
428
+ feComposite
429
+ feConvolveMatrix
430
+ feDiffuseLighting
431
+ feDisplacementMap
432
+ feDistantLight
433
+ feDropShadow
434
+ feFlood
435
+ feFuncA
436
+ feFuncB
437
+ feFuncG
438
+ feFuncR
439
+ feGaussianBlur
440
+ feImage
441
+ feMerge
442
+ feMergeNode
443
+ feMorphology
444
+ feOffset
445
+ fePointLight
446
+ feSpecularLighting
447
+ feSpotLight
448
+ feTile
449
+ feTurbulence
450
+ foreignObject
451
+ linearGradient
452
+ radialGradient
415
453
  textPath
416
454
  ].map { |tag| [tag.downcase, tag] }.to_h.freeze
417
455
 
418
456
  # Source: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute
419
457
  ATTR_MAP = %w[
420
- attributeName attributeType baseFrequency baseProfile calcMode clipPathUnits contentScriptType
421
- contentStyleType diffuseConstant edgeMode filterRes filterUnits glyphRef gradientTransform
422
- gradientUnits kernelMatrix kernelUnitLength keyPoints keySplines keyTimes lengthAdjust
423
- limitingConeAngle markerHeight markerUnits markerWidth maskContentUnits maskUnits numOctaves
424
- pathLength patternContentUnits patternTransform patternUnits pointsAtX pointsAtY pointsAtZ
425
- preserveAlpha preserveAspectRatio primitiveUnits refX refY referrerPolicy repeatCount repeatDur
426
- requiredExtensions requiredFeatures specularConstant specularExponent spreadMethod startOffset
427
- stdDeviation stitchTiles surfaceScale systemLanguage tableValues targetX targetY textLength viewBox
428
- viewTarget xChannelSelector yChannelSelector zoomAndPan
458
+ attributeName
459
+ attributeType
460
+ baseFrequency
461
+ baseProfile
462
+ calcMode
463
+ clipPathUnits
464
+ diffuseConstant
465
+ edgeMode
466
+ filterUnits
467
+ glyphRef
468
+ gradientTransform
469
+ gradientUnits
470
+ kernelMatrix
471
+ kernelUnitLength
472
+ keyPoints
473
+ keySplines
474
+ keyTimes
475
+ lengthAdjust
476
+ limitingConeAngle
477
+ markerHeight
478
+ markerUnits
479
+ markerWidth
480
+ maskContentUnits
481
+ maskUnits
482
+ numOctaves
483
+ pathLength
484
+ patternContentUnits
485
+ patternTransform
486
+ patternUnits
487
+ pointsAtX
488
+ pointsAtY
489
+ pointsAtZ
490
+ preserveAlpha
491
+ preserveAspectRatio
492
+ primitiveUnits
493
+ refX
494
+ refY
495
+ referrerPolicy
496
+ repeatCount
497
+ repeatDur
498
+ requiredExtensions
499
+ requiredFeatures
500
+ specularConstant
501
+ specularExponent
502
+ spreadMethod
503
+ startOffset
504
+ stdDeviation
505
+ stitchTiles
506
+ surfaceScale
507
+ systemLanguage
508
+ tableValues
509
+ targetX
510
+ targetY
511
+ textLength
512
+ viewBox
513
+ xChannelSelector
514
+ yChannelSelector
515
+ zoomAndPan
429
516
  ].map { |attr| [attr.downcase, attr] }.to_h.freeze
430
517
  end
431
518
  end
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.1.0'
4
+ VERSION = '1.0.0'
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
  #
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.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Pickens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-07 00:00:00.000000000 Z
11
+ date: 2024-05-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -42,22 +42,16 @@ dependencies:
42
42
  name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: 5.11.2
48
- - - "<"
45
+ - - "~>"
49
46
  - !ruby/object:Gem::Version
50
- version: 6.0.0
47
+ version: '5.21'
51
48
  type: :development
52
49
  prerelease: false
53
50
  version_requirements: !ruby/object:Gem::Requirement
54
51
  requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- version: 5.11.2
58
- - - "<"
52
+ - - "~>"
59
53
  - !ruby/object:Gem::Version
60
- version: 6.0.0
54
+ version: '5.21'
61
55
  description: HTX is a full-featured HTML template system that is simple, lightweight,
62
56
  and highly performant. This library is a Ruby implementation of the HTX template
63
57
  compiler--it converts HTX templates to their compiled JavaScript form.
@@ -78,9 +72,9 @@ homepage: https://github.com/npickens/htx
78
72
  licenses:
79
73
  - MIT
80
74
  metadata:
81
- allowed_push_host: https://rubygems.org
82
- homepage_uri: https://github.com/npickens/htx
83
- source_code_uri: https://github.com/npickens/htx
75
+ bug_tracker_uri: https://github.com/npickens/htx/issues
76
+ documentation_uri: https://github.com/npickens/htx/blob/1.0.0/README.md
77
+ source_code_uri: https://github.com/npickens/htx/tree/1.0.0
84
78
  post_install_message:
85
79
  rdoc_options: []
86
80
  require_paths:
@@ -89,14 +83,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
89
83
  requirements:
90
84
  - - ">="
91
85
  - !ruby/object:Gem::Version
92
- version: 2.6.0
86
+ version: 3.0.0
93
87
  required_rubygems_version: !ruby/object:Gem::Requirement
94
88
  requirements:
95
89
  - - ">="
96
90
  - !ruby/object:Gem::Version
97
- version: '0'
91
+ version: 2.0.0
98
92
  requirements: []
99
- rubygems_version: 3.4.6
93
+ rubygems_version: 3.5.10
100
94
  signing_key:
101
95
  specification_version: 4
102
96
  summary: A Ruby compiler for HTX templates.