papercraft 0.26 → 0.28

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