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 +7 -0
- data/lib/typewriter/attribute.rb +102 -0
- data/lib/typewriter/spec_attributes.rb +254 -0
- data/lib/typewriter/spec_elements.rb +793 -0
- data/lib/typewriter/template.rb +122 -0
- data/lib/typewriter/version.rb +5 -0
- data/lib/typewriter/writer.rb +54 -0
- data/lib/typewriter.rb +9 -0
- data/rbi/attributes.rbx +189 -0
- data/rbi/elements.rbx +924 -0
- data/rbi/typewriter.rbi +936 -0
- data/rbi/typewriter.rbx +107 -0
- metadata +59 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# typed: strict
|
|
3
|
+
|
|
4
|
+
require_relative 'attribute'
|
|
5
|
+
require_relative 'writer'
|
|
6
|
+
require 'erb/escape'
|
|
7
|
+
|
|
8
|
+
module Typewriter
|
|
9
|
+
# Typewriter Template will generate typed HTML. Each tag and attribute has a
|
|
10
|
+
# match method that is typed via Sorbet (which is optional).
|
|
11
|
+
#
|
|
12
|
+
# The template is designed to allow subclassing or using `start` to generate
|
|
13
|
+
# templates without subclassing.
|
|
14
|
+
#
|
|
15
|
+
# When subclassing understand that `new` generatings a "buffer". Each time a
|
|
16
|
+
# tag(div, b, body, etc) is called it will be added to the buffer. Once
|
|
17
|
+
# `render` is called the buffer is is returned and then cleared.
|
|
18
|
+
#
|
|
19
|
+
# class Example < Typewriter::Template
|
|
20
|
+
# def initialize(name)
|
|
21
|
+
# super()
|
|
22
|
+
# @name = name
|
|
23
|
+
# end
|
|
24
|
+
#
|
|
25
|
+
# def view
|
|
26
|
+
# doctype
|
|
27
|
+
# html do
|
|
28
|
+
# body do
|
|
29
|
+
# h1 { text @name }
|
|
30
|
+
# end
|
|
31
|
+
# end
|
|
32
|
+
# end
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# puts Example.new('My Example').view.render
|
|
36
|
+
# <!DOCTYPE html><html><body><h1>My Example</h1></body></html>
|
|
37
|
+
#
|
|
38
|
+
# If you need to create custom tags, create a method that integrates with the
|
|
39
|
+
# Writer#write method.
|
|
40
|
+
class Template
|
|
41
|
+
include Typewriter::Writer
|
|
42
|
+
include Typewriter::SpecElements::HTMLAllElements
|
|
43
|
+
|
|
44
|
+
# To avoid subclassing a template, `start` can be used to yeild and return a Template.
|
|
45
|
+
#
|
|
46
|
+
# html = Typewriter::Template.start do |t|
|
|
47
|
+
# t.doctype
|
|
48
|
+
# t.html do
|
|
49
|
+
# t.body { t.h1 "Body" }
|
|
50
|
+
# end
|
|
51
|
+
# end
|
|
52
|
+
#
|
|
53
|
+
def self.start(&block)
|
|
54
|
+
obj = new
|
|
55
|
+
yield obj if block
|
|
56
|
+
obj
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
JOIN_ERROR = <<~TXT
|
|
60
|
+
You can not join templates which are created by the parent template.
|
|
61
|
+
|
|
62
|
+
This will fail:
|
|
63
|
+
|
|
64
|
+
Typewriter::Template.start { |t| t.join [t.text("hello")] }
|
|
65
|
+
|
|
66
|
+
Instead only join new templates
|
|
67
|
+
Typewriter::Template.start do |t|
|
|
68
|
+
t.join [Typewriter::Template.start { |x| x.text('hello') }]
|
|
69
|
+
end
|
|
70
|
+
TXT
|
|
71
|
+
|
|
72
|
+
# join an array of other templates into this template.
|
|
73
|
+
def join(templates)
|
|
74
|
+
templates.each do |t|
|
|
75
|
+
raise JOIN_ERROR if t == self
|
|
76
|
+
|
|
77
|
+
@__buffer << t.render
|
|
78
|
+
end
|
|
79
|
+
self
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# text will generate the text node, this is the only way to insert strings into the template.
|
|
83
|
+
#
|
|
84
|
+
# Template.start do |t|
|
|
85
|
+
# t.div { t.text "Hello" }
|
|
86
|
+
# end
|
|
87
|
+
#
|
|
88
|
+
def text(value)
|
|
89
|
+
@__buffer << ERB::Escape.html_escape(value)
|
|
90
|
+
self
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# generate a comment block
|
|
94
|
+
def comment(comment_text = nil)
|
|
95
|
+
write('<!--', '-->', nil, closing_char: '') { text comment_text.to_s }
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# generate the doctype
|
|
99
|
+
def doctype
|
|
100
|
+
@__buffer << '<!DOCTYPE html>'
|
|
101
|
+
self
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# generate a script tag. The return the script code to the block.
|
|
105
|
+
# The code is not escaped.
|
|
106
|
+
def script(attributes = nil, &block) # rubocop:disable Lint/UnusedMethodArgument
|
|
107
|
+
body = yield
|
|
108
|
+
write('<script', '</script>', attributes) { send :unsafe_text, body }
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# attr is short cut in the template to return a new Attribute
|
|
112
|
+
#
|
|
113
|
+
# Template.start { |t| t.div(t.attr.id('my-div'), t.text '...') }
|
|
114
|
+
def attr(&blk)
|
|
115
|
+
if blk
|
|
116
|
+
Attribute.new(&blk)
|
|
117
|
+
else
|
|
118
|
+
Attribute.new
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative 'spec_elements'
|
|
5
|
+
require 'erb/escape'
|
|
6
|
+
|
|
7
|
+
module Typewriter
|
|
8
|
+
# Writer collects the rendered elements and attributes into a string.
|
|
9
|
+
module Writer
|
|
10
|
+
include Kernel
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@__buffer = new_string
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Render produces the HTML string and clears the buffer.
|
|
17
|
+
def render
|
|
18
|
+
result = @__buffer
|
|
19
|
+
# empty the buffer to prevent double rendering
|
|
20
|
+
@__buffer = new_string
|
|
21
|
+
result
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def new_string = String.new(capacity: 1024)
|
|
27
|
+
|
|
28
|
+
# used when the text should not be escaped, see `script`
|
|
29
|
+
def unsafe_text(value)
|
|
30
|
+
@__buffer << value
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
CLOSE = '>'
|
|
35
|
+
CLOSE_VOID = '/>'
|
|
36
|
+
|
|
37
|
+
def write(open, close, attr = nil, closing_char: CLOSE, &block)
|
|
38
|
+
if attr
|
|
39
|
+
@__buffer << open << Attribute.to_html(attr) << closing_char
|
|
40
|
+
else
|
|
41
|
+
@__buffer << open << closing_char
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
yield self if block
|
|
45
|
+
@__buffer << close
|
|
46
|
+
|
|
47
|
+
self
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def write_void(open, attr = nil)
|
|
51
|
+
@__buffer << open << Attribute.to_html(attr) << CLOSE_VOID
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/typewriter.rb
ADDED
data/rbi/attributes.rbx
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Typewriter
|
|
4
|
+
# HTML attributes autogenerated, do not edit
|
|
5
|
+
module SpecAttributes
|
|
6
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
7
|
+
def accept(value); end
|
|
8
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
9
|
+
def accept_charset(value); end
|
|
10
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
11
|
+
def accesskey(value); end
|
|
12
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
13
|
+
def action(value); end
|
|
14
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
15
|
+
def align(value); end
|
|
16
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
17
|
+
def alt(value); end
|
|
18
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
19
|
+
def async(value); end
|
|
20
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
21
|
+
def autocomplete(value); end
|
|
22
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
23
|
+
def autofocus(value); end
|
|
24
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
25
|
+
def autoplay(value); end
|
|
26
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
27
|
+
def bgcolor(value); end
|
|
28
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
29
|
+
def border(value); end
|
|
30
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
31
|
+
def charset(value); end
|
|
32
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
33
|
+
def checked(value); end
|
|
34
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
35
|
+
def cols(value); end
|
|
36
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
37
|
+
def colspan(value); end
|
|
38
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
39
|
+
def content(value); end
|
|
40
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
41
|
+
def contenteditable(value); end
|
|
42
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
43
|
+
def controls(value); end
|
|
44
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
45
|
+
def coords(value); end
|
|
46
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
47
|
+
def datetime(value); end
|
|
48
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
49
|
+
def default(value); end
|
|
50
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
51
|
+
def defer(value); end
|
|
52
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
53
|
+
def dir(value); end
|
|
54
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
55
|
+
def disabled(value); end
|
|
56
|
+
sig { params(value: T.any(String, T::Boolean)).returns(Typewriter::Attribute) }
|
|
57
|
+
def download(value); end
|
|
58
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
59
|
+
def draggable(value); end
|
|
60
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
61
|
+
def enctype(value); end
|
|
62
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
63
|
+
def for(value); end
|
|
64
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
65
|
+
def form(value); end
|
|
66
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
67
|
+
def formaction(value); end
|
|
68
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
69
|
+
def headers(value); end
|
|
70
|
+
sig { params(value: T.any(Numeric, String)).returns(Typewriter::Attribute) }
|
|
71
|
+
def height(value); end
|
|
72
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
73
|
+
def hidden(value); end
|
|
74
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
75
|
+
def high(value); end
|
|
76
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
77
|
+
def href(value); end
|
|
78
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
79
|
+
def hreflang(value); end
|
|
80
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
81
|
+
def id(value); end
|
|
82
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
83
|
+
def integrity(value); end
|
|
84
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
85
|
+
def ismap(value); end
|
|
86
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
87
|
+
def kind(value); end
|
|
88
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
89
|
+
def label(value); end
|
|
90
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
91
|
+
def lang(value); end
|
|
92
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
93
|
+
def list(value); end
|
|
94
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
95
|
+
def loop(value); end
|
|
96
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
97
|
+
def low(value); end
|
|
98
|
+
sig { params(value: T.any(Numeric, String)).returns(Typewriter::Attribute) }
|
|
99
|
+
def max(value); end
|
|
100
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
101
|
+
def maxlength(value); end
|
|
102
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
103
|
+
def media(value); end
|
|
104
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
105
|
+
def method(value); end
|
|
106
|
+
sig { params(value: T.any(Numeric, String)).returns(Typewriter::Attribute) }
|
|
107
|
+
def min(value); end
|
|
108
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
109
|
+
def multiple(value); end
|
|
110
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
111
|
+
def muted(value); end
|
|
112
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
113
|
+
def name(value); end
|
|
114
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
115
|
+
def novalidate(value); end
|
|
116
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
117
|
+
def open(value); end
|
|
118
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
119
|
+
def optimum(value); end
|
|
120
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
121
|
+
def pattern(value); end
|
|
122
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
123
|
+
def placeholder(value); end
|
|
124
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
125
|
+
def poster(value); end
|
|
126
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
127
|
+
def preload(value); end
|
|
128
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
129
|
+
def readonly(value); end
|
|
130
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
131
|
+
def rel(value); end
|
|
132
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
133
|
+
def required(value); end
|
|
134
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
135
|
+
def reversed(value); end
|
|
136
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
137
|
+
def rows(value); end
|
|
138
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
139
|
+
def rowspan(value); end
|
|
140
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
141
|
+
def sandbox(value); end
|
|
142
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
143
|
+
def span(value); end
|
|
144
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
145
|
+
def scope(value); end
|
|
146
|
+
sig { params(value: T::Boolean).returns(Typewriter::Attribute) }
|
|
147
|
+
def selected(value); end
|
|
148
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
149
|
+
def shape(value); end
|
|
150
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
151
|
+
def size(value); end
|
|
152
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
153
|
+
def sizes(value); end
|
|
154
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
155
|
+
def spellcheck(value); end
|
|
156
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
157
|
+
def src(value); end
|
|
158
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
159
|
+
def srcdoc(value); end
|
|
160
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
161
|
+
def srclang(value); end
|
|
162
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
163
|
+
def srcset(value); end
|
|
164
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
165
|
+
def start(value); end
|
|
166
|
+
sig { params(value: T.any(Numeric, String)).returns(Typewriter::Attribute) }
|
|
167
|
+
def step(value); end
|
|
168
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
169
|
+
def style(value); end
|
|
170
|
+
sig { params(value: Numeric).returns(Typewriter::Attribute) }
|
|
171
|
+
def tabindex(value); end
|
|
172
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
173
|
+
def target(value); end
|
|
174
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
175
|
+
def title(value); end
|
|
176
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
177
|
+
def translate(value); end
|
|
178
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
179
|
+
def type(value); end
|
|
180
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
181
|
+
def usemap(value); end
|
|
182
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
183
|
+
def value(value); end
|
|
184
|
+
sig { params(value: T.any(Numeric, String)).returns(Typewriter::Attribute) }
|
|
185
|
+
def width(value); end
|
|
186
|
+
sig { params(value: String).returns(Typewriter::Attribute) }
|
|
187
|
+
def wrap(value); end
|
|
188
|
+
end
|
|
189
|
+
end
|