typewriter 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e65fca7aefac8110c0840eabebfbb42f73f69a71cb8f8bce71f6332ec338be10
4
+ data.tar.gz: bf07499e42e5aeb0f78c88d59923dfb6a5b87bafccf8f30d0e9384a6e735b3cd
5
+ SHA512:
6
+ metadata.gz: f6caaa2197822004c423df726fce1e0e8209c04914c5b33bd11ba9abc4697d08bccabedbaea25d8f75f58794ce21bf35a2211da1d85783d8f56bc3e9926e49a0
7
+ data.tar.gz: 98b710decec241e7ea4d0d6a39aba68300eb4afaf74ad4e67cc2f2b5883386e9160b581142b1be82652ee7183b0fe9c3edcac171435058f9eb30b1fcd8270c4a
@@ -0,0 +1,102 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_attributes'
5
+ require 'erb/escape'
6
+
7
+ module Typewriter
8
+ # Attribute generates HTML attributes. It is designed to prevent printing the
9
+ # same attribute twice. The Template elements expect an Attribute object.
10
+ #
11
+ # All attribute values are HTML escaped via ERB::Escape.
12
+ #
13
+ # It is typed to only allow the correct types to be passed to the attribute,
14
+ # if Sorbet is enabled.
15
+ #
16
+ # Attributes can be generated via a block, or chained.
17
+ #
18
+ # Block
19
+ # Attribute.new { _1.id "one" ; _1.klass "big" }
20
+ #
21
+ # Chained
22
+ # Attribute.new.id("one").klass("big")
23
+ #
24
+ # Boolean attributes
25
+ # Some attributes (async, autoplay, disabled) are boolean. When true is
26
+ # passed, the attribute prints, when false, the attribute will be blank.
27
+ #
28
+ # Attribute.new.disabled(true) -> " disabled"
29
+ # Attribute.new.disabled(false) -> " "
30
+ class Attribute
31
+ include Typewriter::SpecAttributes
32
+
33
+ # only allow nil or objects that respond to `safe_attribute`
34
+ def self.to_html(attr)
35
+ return '' if attr.nil?
36
+
37
+ attr.safe_attribute
38
+ end
39
+
40
+ # create a new Attribute object to create reuseable attributes
41
+ def initialize(buffer = {}, &block)
42
+ @__buffer = buffer
43
+ return unless block
44
+
45
+ yield self
46
+ end
47
+
48
+ # Custom data attributes
49
+ # The data attribute takes a suffix and the string value.
50
+ # Attribute.new.data('turbo','false') -> ' data-turbo="false"'
51
+ def data(suffix, value)
52
+ unless suffix.match?(/\A[a-z-]+\z/)
53
+ raise ArgumentError,
54
+ "suffix (#{suffix}) must be lowercase and only contain 'a' to 'z' or hyphens."
55
+ end
56
+
57
+ write(" data-#{suffix}=\"", value)
58
+ end
59
+
60
+ def attribute(name, value)
61
+ write(" #{name}=\"", value)
62
+ end
63
+
64
+ # CSS class name(s) for styling, the name changed to protect the Ruby.
65
+ def klass(value)
66
+ write(' class="', value)
67
+ end
68
+
69
+ # classes takes a hash of class names and boolean values
70
+ # only the names with a true value will be printed
71
+ # classes({'a' => true, 'b' => false, 'c' => true}) -> ' class="a c"'
72
+ def classes(list)
73
+ klass list.select { |_k, v| v == true }.keys.join(' ')
74
+ end
75
+
76
+ # alias so klass has classes
77
+ def klasses(list) = classes(list)
78
+
79
+ # Merge another Attribute to create a new, combined, Attribute.
80
+ def merge(other)
81
+ self.class.new(@__buffer.merge(other.instance_variable_get(:@__buffer)))
82
+ end
83
+
84
+ # output the attributes as string
85
+ def safe_attribute
86
+ @__buffer.values.join
87
+ end
88
+
89
+ private
90
+
91
+ def write(name, value)
92
+ @__buffer[name] = "#{name}#{ERB::Escape.html_escape(value)}\""
93
+ self
94
+ end
95
+
96
+ # for boolean attributes, determin if to print the attribute or not
97
+ def write_boolean(name, print)
98
+ @__buffer[name] = print ? name : ''
99
+ self
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,254 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Typewriter
4
+ # HTML attributes autogenerated, do not edit
5
+ module SpecAttributes
6
+ # Specifies file types browser will accept
7
+ def accept(value) = write(' accept="', value)
8
+ # Character encodings used for form submission
9
+ def accept_charset(value) = write(' accept-charset="', value)
10
+ # Keyboard shortcut to access element
11
+ def accesskey(value) = write(' accesskey="', value)
12
+ # URL where form data is submitted
13
+ def action(value) = write(' action="', value)
14
+ # Alignment of content
15
+ def align(value) = write(' align="', value)
16
+ # Alternative text for images
17
+ def alt(value) = write(' alt="', value)
18
+ # Script should execute asynchronously
19
+ def async(value) = write_boolean(' async', value)
20
+ # Form/input autocompletion
21
+ def autocomplete(value) = write(' autocomplete="', value)
22
+ # Element should be focused on page load
23
+ def autofocus(value) = write_boolean(' autofocus', value)
24
+ # Media will start playing automatically
25
+ def autoplay(value) = write_boolean(' autoplay', value)
26
+ # Background color of element
27
+ def bgcolor(value) = write(' bgcolor="', value)
28
+ # Border width in pixels
29
+ def border(value) = write(' border="', value)
30
+ # Character encoding of document
31
+ def charset(value) = write(' charset="', value)
32
+ # Whether checkbox/radio button is selected
33
+ def checked(value) = write_boolean(' checked', value)
34
+ # Number of columns in textarea
35
+ def cols(value) = write(' cols="', value)
36
+ # Number of columns a cell spans
37
+ def colspan(value) = write(' colspan="', value)
38
+ # Content for meta tags
39
+ def content(value) = write(' content="', value)
40
+ # Whether content is editable
41
+ def contenteditable(value) = write(' contenteditable="', value)
42
+ # Show media playback controls
43
+ def controls(value) = write_boolean(' controls', value)
44
+ # Coordinates for image maps
45
+ def coords(value) = write(' coords="', value)
46
+ # Date/time of element content
47
+ def datetime(value) = write(' datetime="', value)
48
+ # Default track for media
49
+ def default(value) = write_boolean(' default', value)
50
+ # Script should execute after parsing
51
+ def defer(value) = write_boolean(' defer', value)
52
+ # Text direction
53
+ def dir(value) = write(' dir="', value)
54
+ # Element is disabled
55
+ def disabled(value) = write_boolean(' disabled', value)
56
+ # Resource should be downloaded
57
+ def download(value) = write(' download="', value)
58
+ # Element can be dragged
59
+ def draggable(value) = write(' draggable="', value)
60
+ # Form data encoding for submission
61
+ def enctype(value) = write(' enctype="', value)
62
+ # Associates label with form control
63
+ def for(value) = write(' for="', value)
64
+ # Form the element belongs to
65
+ def form(value) = write(' form="', value)
66
+ # URL for form submission
67
+ def formaction(value) = write(' formaction="', value)
68
+ # Related header cells for data cell
69
+ def headers(value) = write(' headers="', value)
70
+ # Height of element
71
+ def height(value) = write(' height="', value)
72
+ # Element is not displayed
73
+ def hidden(value) = write_boolean(' hidden', value)
74
+ # Upper range of meter
75
+ def high(value) = write(' high="', value)
76
+ # URL of linked resource
77
+ def href(value) = write(' href="', value)
78
+ # Language of linked resource
79
+ def hreflang(value) = write(' hreflang="', value)
80
+ # Unique identifier for element
81
+ def id(value) = write(' id="', value)
82
+ # Subresource integrity hash
83
+ def integrity(value) = write(' integrity="', value)
84
+ # Image is server-side image map
85
+ def ismap(value) = write_boolean(' ismap', value)
86
+ # Type of text track
87
+ def kind(value) = write(' kind="', value)
88
+ # Label for form control/option
89
+ def label(value) = write(' label="', value)
90
+ # Language of element content
91
+ def lang(value) = write(' lang="', value)
92
+ # Links input to datalist options
93
+ def list(value) = write(' list="', value)
94
+ # Media will replay when finished
95
+ def loop(value) = write_boolean(' loop', value)
96
+ # Lower range of meter
97
+ def low(value) = write(' low="', value)
98
+ # Maximum allowed value
99
+ def max(value) = write(' max="', value)
100
+ # Maximum length of input
101
+ def maxlength(value) = write(' maxlength="', value)
102
+ # Media type for resource
103
+ def media(value) = write(' media="', value)
104
+ # HTTP method for form submission
105
+ def method(value) = write(' method="', value)
106
+ # Minimum allowed value
107
+ def min(value) = write(' min="', value)
108
+ # Multiple values can be selected
109
+ def multiple(value) = write_boolean(' multiple', value)
110
+ # Media is muted by default
111
+ def muted(value) = write_boolean(' muted', value)
112
+ # Name of form control
113
+ def name(value) = write(' name="', value)
114
+ # Form validation is skipped
115
+ def novalidate(value) = write_boolean(' novalidate', value)
116
+ # Details element is expanded
117
+ def open(value) = write_boolean(' open', value)
118
+ # Optimal value for meter
119
+ def optimum(value) = write(' optimum="', value)
120
+ # Regular expression pattern
121
+ def pattern(value) = write(' pattern="', value)
122
+ # Hint text for input field
123
+ def placeholder(value) = write(' placeholder="', value)
124
+ # Preview image for video
125
+ def poster(value) = write(' poster="', value)
126
+ # How media should be loaded
127
+ def preload(value) = write(' preload="', value)
128
+ # Input field cannot be modified
129
+ def readonly(value) = write_boolean(' readonly', value)
130
+ # Relationship of linked resource
131
+ def rel(value) = write(' rel="', value)
132
+ # Input must be filled out
133
+ def required(value) = write_boolean(' required', value)
134
+ # List is numbered in reverse
135
+ def reversed(value) = write_boolean(' reversed', value)
136
+ # Number of rows in textarea
137
+ def rows(value) = write(' rows="', value)
138
+ # Number of rows a cell spans
139
+ def rowspan(value) = write(' rowspan="', value)
140
+ # Security rules for iframe
141
+ def sandbox(value) = write(' sandbox="', value)
142
+ # Specifies the number of consecutive columns the <colgroup> element spans. The value must be a positive integer greater than zero. If not present, its default value is 1.
143
+ def span(value) = write(' span="', value)
144
+ # Cells header element relates to
145
+ def scope(value) = write(' scope="', value)
146
+ # Option is pre-selected
147
+ def selected(value) = write_boolean(' selected', value)
148
+ # Shape of image map area
149
+ def shape(value) = write(' shape="', value)
150
+ # Size of input/select control
151
+ def size(value) = write(' size="', value)
152
+ # Image sizes for different layouts
153
+ def sizes(value) = write(' sizes="', value)
154
+ # Element should be spellchecked
155
+ def spellcheck(value) = write(' spellcheck="', value)
156
+ # URL of resource
157
+ def src(value) = write(' src="', value)
158
+ # Content for inline frame
159
+ def srcdoc(value) = write(' srcdoc="', value)
160
+ # Language of text track
161
+ def srclang(value) = write(' srclang="', value)
162
+ # Images to use in different situations
163
+ def srcset(value) = write(' srcset="', value)
164
+ # Starting number for ordered list
165
+ def start(value) = write(' start="', value)
166
+ # Increment for numeric input
167
+ def step(value) = write(' step="', value)
168
+ # Inline CSS styles
169
+ def style(value) = write(' style="', value)
170
+ # Position in tab order
171
+ def tabindex(value) = write(' tabindex="', value)
172
+ # Where to open linked document
173
+ def target(value) = write(' target="', value)
174
+ # Advisory information about element
175
+ def title(value) = write(' title="', value)
176
+ # Whether to translate content
177
+ def translate(value) = write(' translate="', value)
178
+ # Type of element or input
179
+ def type(value) = write(' type="', value)
180
+ # Image map to use
181
+ def usemap(value) = write(' usemap="', value)
182
+ # Value of form control
183
+ def value(value) = write(' value="', value)
184
+ # Width of element
185
+ def width(value) = write(' width="', value)
186
+ # How text wraps in textarea
187
+ def wrap(value) = write(' wrap="', value)
188
+ def onabort(value) = write(' onabort="', value)
189
+ def onauxclick(value) = write(' onauxclick="', value)
190
+ def onbeforeinput(value) = write(' onbeforeinput="', value)
191
+ def onbeforematch(value) = write(' onbeforematch="', value)
192
+ def onbeforetoggle(value) = write(' onbeforetoggle="', value)
193
+ def oncancel(value) = write(' oncancel="', value)
194
+ def oncanplay(value) = write(' oncanplay="', value)
195
+ def oncanplaythrough(value) = write(' oncanplaythrough="', value)
196
+ def onchange(value) = write(' onchange="', value)
197
+ def onclick(value) = write(' onclick="', value)
198
+ def onclose(value) = write(' onclose="', value)
199
+ def oncontextlost(value) = write(' oncontextlost="', value)
200
+ def oncontextmenu(value) = write(' oncontextmenu="', value)
201
+ def oncontextrestored(value) = write(' oncontextrestored="', value)
202
+ def oncopy(value) = write(' oncopy="', value)
203
+ def oncuechange(value) = write(' oncuechange="', value)
204
+ def oncut(value) = write(' oncut="', value)
205
+ def ondblclick(value) = write(' ondblclick="', value)
206
+ def ondrag(value) = write(' ondrag="', value)
207
+ def ondragend(value) = write(' ondragend="', value)
208
+ def ondragenter(value) = write(' ondragenter="', value)
209
+ def ondragleave(value) = write(' ondragleave="', value)
210
+ def ondragover(value) = write(' ondragover="', value)
211
+ def ondragstart(value) = write(' ondragstart="', value)
212
+ def ondrop(value) = write(' ondrop="', value)
213
+ def ondurationchange(value) = write(' ondurationchange="', value)
214
+ def onemptied(value) = write(' onemptied="', value)
215
+ def onended(value) = write(' onended="', value)
216
+ def onformdata(value) = write(' onformdata="', value)
217
+ def oninput(value) = write(' oninput="', value)
218
+ def oninvalid(value) = write(' oninvalid="', value)
219
+ def onkeydown(value) = write(' onkeydown="', value)
220
+ def onkeypress(value) = write(' onkeypress="', value)
221
+ def onkeyup(value) = write(' onkeyup="', value)
222
+ def onloadeddata(value) = write(' onloadeddata="', value)
223
+ def onloadedmetadata(value) = write(' onloadedmetadata="', value)
224
+ def onloadstart(value) = write(' onloadstart="', value)
225
+ def onmousedown(value) = write(' onmousedown="', value)
226
+ def onmouseenter(value) = write(' onmouseenter="', value)
227
+ def onmouseleave(value) = write(' onmouseleave="', value)
228
+ def onmousemove(value) = write(' onmousemove="', value)
229
+ def onmouseout(value) = write(' onmouseout="', value)
230
+ def onmouseover(value) = write(' onmouseover="', value)
231
+ def onmouseup(value) = write(' onmouseup="', value)
232
+ def onpaste(value) = write(' onpaste="', value)
233
+ def onpause(value) = write(' onpause="', value)
234
+ def onplay(value) = write(' onplay="', value)
235
+ def onplaying(value) = write(' onplaying="', value)
236
+ def onprogress(value) = write(' onprogress="', value)
237
+ def onratechange(value) = write(' onratechange="', value)
238
+ def onreset(value) = write(' onreset="', value)
239
+ def onscrollend(value) = write(' onscrollend="', value)
240
+ def onsecuritypolicyviolation(value) = write(' onsecuritypolicyviolation="', value)
241
+ def onseeked(value) = write(' onseeked="', value)
242
+ def onseeking(value) = write(' onseeking="', value)
243
+ def onselect(value) = write(' onselect="', value)
244
+ def onslotchange(value) = write(' onslotchange="', value)
245
+ def onstalled(value) = write(' onstalled="', value)
246
+ def onsubmit(value) = write(' onsubmit="', value)
247
+ def onsuspend(value) = write(' onsuspend="', value)
248
+ def ontimeupdate(value) = write(' ontimeupdate="', value)
249
+ def ontoggle(value) = write(' ontoggle="', value)
250
+ def onvolumechange(value) = write(' onvolumechange="', value)
251
+ def onwaiting(value) = write(' onwaiting="', value)
252
+ def onwheel(value) = write(' onwheel="', value)
253
+ end
254
+ end