htx 0.1.0 → 1.0.0

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: 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.