papercraft 0.26 → 0.28

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: 2b64cff374a2d8fdf50de978d3a4b0ceb6fb939741c00ed7cf63154af7cf6732
4
- data.tar.gz: 67c0fc2aa65a1056f04c378ebe50a0a433bb1cabba75a1fbd522d60604ddcd1d
3
+ metadata.gz: eccca55a3b242b80413bad0c851619062d66c1b68eaa9f2e4a13ca9e4beefddf
4
+ data.tar.gz: a5cf234c36fe286a94d6607bc30e13a24568396f6fe78b2f0e22870618e97941
5
5
  SHA512:
6
- metadata.gz: 690eaec575b4ad635fc913609197d166841536811b1e1d4314d763c6c37fb520b9fc8f2f19d50f4a0cfd242a98b69d59aebf16eaa16f4298bfc74ac0040b516a
7
- data.tar.gz: 66a468eeee29e5c2b9b9e7a2f3adc605fa2f9648ade7a0aa444a798d896de3eb8c5aa02c2e79bf27780769f86d2b1960b8a111be1d8ed6604af739cab5931adb
6
+ metadata.gz: 003a30933c7d7557a346ce02bcc54169427389db2e488ee5516b68b9e99d74f2b5f0464db4e327c1c3064bc7cbfe0df9c4ef0df6322b61a467f14f30a83b415c
7
+ data.tar.gz: cc8d7e819fdefc04a5ffb1966d707d6fb7e533bc0c8f6d3fc39191749c4733593850a4cb046648c010c2ae4daae6fbaa6980b806a1ab61d9746481dc63fd8ecf
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 0.28 2023-03-11
2
+
3
+ - Add `HTML#import_map`, `HTML#js_module` methods
4
+
5
+ ## 0.27 2023-01-19
6
+
7
+ - Fix rendering of HTML void element tags
8
+
1
9
  ## 0.26 2023-01-13
2
10
 
3
11
  - Add support for namespaced local extensions using `#extend`
@@ -71,7 +71,47 @@ module Papercraft
71
71
  @buffer << '></script>'
72
72
  end
73
73
  end
74
+
75
+ # Returns a versioned URL for the given file spec.
76
+ #
77
+ # @param href [String] relative file path
78
+ # @param root_path [String] root path for file
79
+ # @param root_url [String] root URL
80
+ # @return [String] versioned URL
81
+ def versioned_file_href(href, root_path, root_url = '')
82
+ fn = File.join(root_path, href)
83
+ version = File.stat(fn).mtime.to_i rescue 0
84
+ "#{root_url}/#{href}?v=#{version}"
85
+ end
74
86
 
87
+ # Emits an import map scrit tag. If a hash is given, emits the hash as is.
88
+ # If a string is given, searches for all *.js files under the given path,
89
+ # and emits an import map including all found files, with versioned URLs.
90
+ #
91
+ # @param root_path [String, Hash] root path or hash
92
+ # @param root_url [String] root URL to construct URLs against
93
+ # @return [void]
94
+ def import_map(root_path, root_url = '')
95
+ if root_path.is_a?(Hash)
96
+ script(root_path.to_json, type: 'importmap')
97
+ else
98
+ map = Dir["#{root_path}/*.js"].sort.each_with_object({}) do |fn, h|
99
+ name = File.basename(fn)
100
+ m = fn.match(/\/([^\/]+)\.js$/)
101
+ h[m[1]] = versioned_file_href(name, root_path, root_url)
102
+ end
103
+ script(map.to_json, type: 'importmap')
104
+ end
105
+ end
106
+
107
+ # Emits a script tag with type attribute set to module.
108
+ #
109
+ # @param code [String] JS code
110
+ # @return [void]
111
+ def js_module(code)
112
+ script code, type: 'module'
113
+ end
114
+
75
115
  # Converts and emits the given markdown. Papercraft uses
76
116
  # [Kramdown](https://github.com/gettalong/kramdown/) to do the Markdown to
77
117
  # HTML conversion. Optional Kramdown settings can be provided in order to
@@ -88,6 +128,21 @@ module Papercraft
88
128
 
89
129
  private
90
130
 
131
+ # Returns true if the given tag is a void element, in order to render a self
132
+ # closing tag. See spec: https://html.spec.whatwg.org/multipage/syntax.html#void-elements.
133
+ #
134
+ # @param text [String] tag
135
+ # @return [Bool] is it a void element
136
+ def is_void_element_tag?(tag)
137
+ case tag
138
+ #
139
+ when 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'source', 'track', 'wbr'
140
+ true
141
+ else
142
+ false
143
+ end
144
+ end
145
+
91
146
  # Escapes the given text using HTML entities.
92
147
  #
93
148
  # @param text [String] text
@@ -10,6 +10,7 @@ module Papercraft
10
10
  S_LT_SLASH = '</'
11
11
  S_SPACE_LT_SLASH = ' </'
12
12
  S_SLASH_GT = '/>'
13
+ S_GT_LT_SLASH = '></'
13
14
  S_SPACE = ' '
14
15
  S_EQUAL_QUOTE = '="'
15
16
  S_QUOTE = '"'
@@ -21,6 +22,36 @@ module Papercraft
21
22
  S_TAG_%<TAG>s_PRE = %<tag_pre>s
22
23
  S_TAG_%<TAG>s_CLOSE = %<tag_close>s
23
24
 
25
+ def %<tag>s(text = nil, **props, &block)
26
+ if text.is_a?(Hash) && props.empty?
27
+ props = text
28
+ text = nil
29
+ end
30
+
31
+ @buffer << S_TAG_%<TAG>s_PRE
32
+ emit_props(props) unless props.empty?
33
+
34
+ if block
35
+ @buffer << S_GT
36
+ instance_eval(&block)
37
+ @buffer << S_TAG_%<TAG>s_CLOSE
38
+ elsif Proc === text
39
+ @buffer << S_GT
40
+ emit(text)
41
+ @buffer << S_TAG_%<TAG>s_CLOSE
42
+ elsif text
43
+ @buffer << S_GT << escape_text(text.to_s) << S_TAG_%<TAG>s_CLOSE
44
+ else
45
+ @buffer << S_GT << S_TAG_%<TAG>s_CLOSE
46
+ end
47
+ end
48
+ EOF
49
+
50
+ S_VOID_TAG_METHOD_LINE = __LINE__ + 2
51
+ S_VOID_TAG_METHOD = <<~EOF
52
+ S_TAG_%<TAG>s_PRE = %<tag_pre>s
53
+ S_TAG_%<TAG>s_CLOSE = %<tag_close>s
54
+
24
55
  def %<tag>s(text = nil, **props, &block)
25
56
  if text.is_a?(Hash) && props.empty?
26
57
  props = text
@@ -149,8 +180,10 @@ module Papercraft
149
180
  @buffer << S_LT_SLASH << tag << S_GT
150
181
  elsif text
151
182
  @buffer << S_GT << escape_text(text.to_s) << S_LT_SLASH << tag << S_GT
152
- else
183
+ elsif is_void_element_tag?(sym)
153
184
  @buffer << S_SLASH_GT
185
+ else
186
+ @buffer << S_GT_LT_SLASH << tag << S_GT
154
187
  end
155
188
  end
156
189
 
@@ -165,7 +198,6 @@ module Papercraft
165
198
  tag = sym.to_s
166
199
  if tag =~ /^[A-Z]/ && (Object.const_defined?(tag))
167
200
  define_const_tag_method(tag)
168
- # return send(tag, *args, **opts)
169
201
  else
170
202
  define_tag_method(tag)
171
203
  end
@@ -262,13 +294,20 @@ module Papercraft
262
294
  # @return [void]
263
295
  def define_tag_method(tag)
264
296
  repr = tag_repr(tag)
265
- code = S_TAG_METHOD % {
297
+ if is_void_element_tag?(tag)
298
+ tmpl = S_VOID_TAG_METHOD
299
+ line = S_VOID_TAG_METHOD_LINE
300
+ else
301
+ tmpl = S_TAG_METHOD
302
+ line = S_TAG_METHOD_LINE
303
+ end
304
+ code = tmpl % {
266
305
  tag: tag,
267
306
  TAG: tag.upcase,
268
307
  tag_pre: "<#{repr}".inspect,
269
308
  tag_close: "</#{repr}>".inspect
270
309
  }
271
- self.class.class_eval(code, __FILE__, S_TAG_METHOD_LINE)
310
+ self.class.class_eval(code, __FILE__, line)
272
311
  end
273
312
 
274
313
  # Defines a namespace referring to the given module.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Papercraft
4
- VERSION = '0.26'
4
+ VERSION = '0.28'
5
5
  end
@@ -10,7 +10,15 @@ module Papercraft
10
10
 
11
11
  private
12
12
 
13
- # Converts a tag to its string representation. Underscores will be converted
13
+ # Returns false (no void elements in XML)
14
+ #
15
+ # @param tag [String] tag
16
+ # @return [false] false
17
+ def is_void_element_tag?(tag)
18
+ false
19
+ end
20
+
21
+ # Converts a tag to its string representation. Underscores will be converted
14
22
  # to dashes, double underscores will be converted to colon.
15
23
  #
16
24
  # @param tag [Symbol, String] tag
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: papercraft
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.26'
4
+ version: '0.28'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-13 00:00:00.000000000 Z
11
+ date: 2023-03-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: escape_utils