hot_docs 0.0.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/.rubocop.yml +8 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +39 -0
- data/Rakefile +12 -0
- data/lib/hot_docs/version.rb +5 -0
- data/lib/hot_docs.rb +8 -0
- data/sig/hot_docs.rbs +4 -0
- data/website/.dockerignore +51 -0
- data/website/.gitattributes +9 -0
- data/website/.github/dependabot.yml +12 -0
- data/website/.github/images/hot_docs.svg +17 -0
- data/website/.github/workflows/ci.yml +90 -0
- data/website/.gitignore +37 -0
- data/website/.kamal/hooks/docker-setup.sample +3 -0
- data/website/.kamal/hooks/post-deploy.sample +14 -0
- data/website/.kamal/hooks/post-proxy-reboot.sample +3 -0
- data/website/.kamal/hooks/pre-build.sample +51 -0
- data/website/.kamal/hooks/pre-connect.sample +47 -0
- data/website/.kamal/hooks/pre-deploy.sample +109 -0
- data/website/.kamal/hooks/pre-proxy-reboot.sample +3 -0
- data/website/.kamal/secrets +17 -0
- data/website/.rubocop.yml +8 -0
- data/website/.ruby-version +1 -0
- data/website/Dockerfile +72 -0
- data/website/Gemfile +65 -0
- data/website/Gemfile.lock +394 -0
- data/website/LICENSE.txt +21 -0
- data/website/README.md +49 -0
- data/website/Rakefile +6 -0
- data/website/app/assets/images/.keep +0 -0
- data/website/app/assets/images/hot_docs_components_desktop.png +0 -0
- data/website/app/assets/images/hot_docs_components_mobile.png +0 -0
- data/website/app/assets/stylesheets/hot_docs.css +999 -0
- data/website/app/assets/stylesheets/website.css +245 -0
- data/website/app/controllers/application_controller.rb +4 -0
- data/website/app/controllers/concerns/.keep +0 -0
- data/website/app/controllers/hot_docs_controller.rb +3 -0
- data/website/app/helpers/application_helper.rb +25 -0
- data/website/app/helpers/hot_docs_helper.rb +99 -0
- data/website/app/javascript/application.js +3 -0
- data/website/app/javascript/controllers/accordion_controller.js +36 -0
- data/website/app/javascript/controllers/application.js +9 -0
- data/website/app/javascript/controllers/index.js +4 -0
- data/website/app/javascript/controllers/sidenav_controller.js +39 -0
- data/website/app/javascript/controllers/toc_controller.js +91 -0
- data/website/app/javascript/controllers/typewriter_controller.js +59 -0
- data/website/app/jobs/application_job.rb +7 -0
- data/website/app/mailers/application_mailer.rb +4 -0
- data/website/app/models/application_record.rb +3 -0
- data/website/app/models/concerns/.keep +0 -0
- data/website/app/views/hot_docs/_menu_row.html.erb +11 -0
- data/website/app/views/hot_docs/components.html.mderb +32 -0
- data/website/app/views/hot_docs/embedded.html.mderb +12 -0
- data/website/app/views/hot_docs/footer.html.mderb +13 -0
- data/website/app/views/hot_docs/helpers.html.mderb +33 -0
- data/website/app/views/hot_docs/index.html.erb +143 -0
- data/website/app/views/hot_docs/light_dark.html.mderb +29 -0
- data/website/app/views/hot_docs/markdown.html.mderb +27 -0
- data/website/app/views/hot_docs/nav.html.mderb +15 -0
- data/website/app/views/hot_docs/quickstart.html.mderb +11 -0
- data/website/app/views/hot_docs/search.html.mderb +7 -0
- data/website/app/views/hot_docs/standalone.html.mderb +11 -0
- data/website/app/views/hot_docs/static_export.html.mderb +7 -0
- data/website/app/views/hot_docs/toc.html.mderb +11 -0
- data/website/app/views/layouts/hot_docs.html.erb +175 -0
- data/website/app/views/layouts/mailer.html.erb +13 -0
- data/website/app/views/layouts/mailer.text.erb +1 -0
- data/website/app/views/layouts/website.html.erb +175 -0
- data/website/app/views/pwa/manifest.json.erb +22 -0
- data/website/app/views/pwa/service-worker.js +26 -0
- data/website/bin/brakeman +7 -0
- data/website/bin/bundle +109 -0
- data/website/bin/dev +2 -0
- data/website/bin/docker-entrypoint +14 -0
- data/website/bin/embed_hot_docs +33 -0
- data/website/bin/importmap +4 -0
- data/website/bin/jobs +6 -0
- data/website/bin/kamal +27 -0
- data/website/bin/rails +4 -0
- data/website/bin/rake +4 -0
- data/website/bin/rubocop +8 -0
- data/website/bin/setup +34 -0
- data/website/bin/thrust +5 -0
- data/website/config/application.rb +27 -0
- data/website/config/boot.rb +4 -0
- data/website/config/cable.yml +17 -0
- data/website/config/cache.yml +16 -0
- data/website/config/credentials.yml.enc +1 -0
- data/website/config/database.yml +41 -0
- data/website/config/deploy.yml +116 -0
- data/website/config/environment.rb +5 -0
- data/website/config/environments/development.rb +72 -0
- data/website/config/environments/production.rb +90 -0
- data/website/config/environments/test.rb +53 -0
- data/website/config/importmap.rb +7 -0
- data/website/config/initializers/assets.rb +7 -0
- data/website/config/initializers/content_security_policy.rb +25 -0
- data/website/config/initializers/filter_parameter_logging.rb +8 -0
- data/website/config/initializers/inflections.rb +16 -0
- data/website/config/initializers/markdown.mjs +26 -0
- data/website/config/initializers/markdown.rb +35 -0
- data/website/config/locales/en.yml +31 -0
- data/website/config/puma.rb +41 -0
- data/website/config/queue.yml +18 -0
- data/website/config/recurring.yml +10 -0
- data/website/config/routes.rb +28 -0
- data/website/config/storage.yml +34 -0
- data/website/config.ru +6 -0
- data/website/db/cable_schema.rb +11 -0
- data/website/db/cache_schema.rb +14 -0
- data/website/db/queue_schema.rb +129 -0
- data/website/db/seeds.rb +9 -0
- data/website/lib/tasks/.keep +0 -0
- data/website/log/.keep +0 -0
- data/website/public/400.html +114 -0
- data/website/public/404.html +114 -0
- data/website/public/406-unsupported-browser.html +114 -0
- data/website/public/422.html +114 -0
- data/website/public/500.html +114 -0
- data/website/public/apple-touch-icon.png +0 -0
- data/website/public/favicon.ico +0 -0
- data/website/public/hot_docs.svg +17 -0
- data/website/public/robots.txt +1 -0
- data/website/script/.keep +0 -0
- data/website/storage/.keep +0 -0
- data/website/test/application_system_test_case.rb +5 -0
- data/website/test/controllers/.keep +0 -0
- data/website/test/fixtures/files/.keep +0 -0
- data/website/test/helpers/.keep +0 -0
- data/website/test/helpers/hot_docs_helper_test.rb +94 -0
- data/website/test/integration/.keep +0 -0
- data/website/test/mailers/.keep +0 -0
- data/website/test/models/.keep +0 -0
- data/website/test/system/.keep +0 -0
- data/website/test/test_helper.rb +15 -0
- data/website/tmp/.keep +0 -0
- data/website/tmp/pids/.keep +0 -0
- data/website/tmp/storage/.keep +0 -0
- data/website/vendor/.keep +0 -0
- data/website/vendor/javascript/.keep +0 -0
- metadata +183 -0
@@ -0,0 +1,245 @@
|
|
1
|
+
:root {
|
2
|
+
--docs-background-active-color: #d9d9d9;
|
3
|
+
--docs-background-color: #e9e9e9;
|
4
|
+
--docs-border-color: #dadada;
|
5
|
+
--docs-code-background-color: #eee;
|
6
|
+
--docs-code-border-color: #00000022;
|
7
|
+
--docs-text-color: #1c1e21;
|
8
|
+
}
|
9
|
+
|
10
|
+
[data-theme=dark]:root {
|
11
|
+
--docs-background-active-color: #5a5a5a;
|
12
|
+
--docs-background-color: #444444;
|
13
|
+
--docs-border-color: #535353;
|
14
|
+
--docs-code-background-color: #2b2b2b;
|
15
|
+
--docs-code-border-color: #ffffff22;
|
16
|
+
--docs-text-color: #e3e1de;
|
17
|
+
}
|
18
|
+
|
19
|
+
.article {
|
20
|
+
color: var(--docs-text-color);
|
21
|
+
|
22
|
+
.supertitle {
|
23
|
+
font-size: 1.25rem;
|
24
|
+
font-style: italic;
|
25
|
+
margin-bottom: 0;
|
26
|
+
margin-top: 2rem;
|
27
|
+
text-align: center;
|
28
|
+
}
|
29
|
+
|
30
|
+
.title {
|
31
|
+
font-size: 3.5rem;
|
32
|
+
line-height: 4rem;
|
33
|
+
margin-block: 0;
|
34
|
+
text-align: center;
|
35
|
+
}
|
36
|
+
|
37
|
+
.subtitle {
|
38
|
+
display: flex;
|
39
|
+
flex-direction: column;
|
40
|
+
font-size: 1.25rem;
|
41
|
+
column-gap: 0.5ch;
|
42
|
+
justify-content: center;
|
43
|
+
margin-top: 1rem;
|
44
|
+
text-align: center;
|
45
|
+
|
46
|
+
@media (min-width: 32rem) {
|
47
|
+
flex-direction: row;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
.subtitle__fixed {
|
52
|
+
margin: 0;
|
53
|
+
}
|
54
|
+
|
55
|
+
.subtitle__typewriter {
|
56
|
+
align-self: center;
|
57
|
+
border-right: 0.08em solid var(--docs-text-color);
|
58
|
+
font-weight: bold;
|
59
|
+
margin: 0;
|
60
|
+
white-space: pre;
|
61
|
+
}
|
62
|
+
|
63
|
+
.logo {
|
64
|
+
display: block;
|
65
|
+
height: 10rem;
|
66
|
+
margin-block: 5rem;
|
67
|
+
margin-inline: auto;
|
68
|
+
width: 10rem;
|
69
|
+
}
|
70
|
+
|
71
|
+
.actions {
|
72
|
+
align-items: center;
|
73
|
+
display: flex;
|
74
|
+
flex-direction: column;
|
75
|
+
gap: 0.5rem;
|
76
|
+
margin-block: 5rem;
|
77
|
+
}
|
78
|
+
|
79
|
+
.actions__buttons {
|
80
|
+
gap: 1rem;
|
81
|
+
display: flex;
|
82
|
+
justify-content: center;
|
83
|
+
}
|
84
|
+
|
85
|
+
.actions__button {
|
86
|
+
background-color: var(--docs-background-color);
|
87
|
+
border-radius: 0.375rem;
|
88
|
+
color: var(--docs-text-color);
|
89
|
+
display: flex;
|
90
|
+
flex-direction: column;
|
91
|
+
font-weight: bold;
|
92
|
+
padding: 0.5rem 1rem;
|
93
|
+
text-align: center;
|
94
|
+
text-decoration: none;
|
95
|
+
|
96
|
+
&:hover {
|
97
|
+
background-color: var(--docs-background-active-color);
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
.actions__footnote {
|
102
|
+
font-size: 0.8rem;
|
103
|
+
margin: 0;
|
104
|
+
}
|
105
|
+
|
106
|
+
.benefits {
|
107
|
+
container-type: inline-size;
|
108
|
+
margin-block: 10rem;
|
109
|
+
}
|
110
|
+
|
111
|
+
.benefits__cards {
|
112
|
+
column-gap: 5rem;
|
113
|
+
display: flex;
|
114
|
+
flex-direction: column;
|
115
|
+
justify-content: space-between;
|
116
|
+
|
117
|
+
@container (min-width: 35rem) {
|
118
|
+
flex-direction: row;
|
119
|
+
row-gap: 1rem;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
.benefits__card {
|
124
|
+
flex: 1 0 0;
|
125
|
+
}
|
126
|
+
|
127
|
+
.benefits__card-title {
|
128
|
+
font-weight: bold;
|
129
|
+
}
|
130
|
+
|
131
|
+
.comparison {
|
132
|
+
margin-block: 10rem;
|
133
|
+
}
|
134
|
+
|
135
|
+
.comparison__table-wrapper {
|
136
|
+
overflow-x: auto;
|
137
|
+
}
|
138
|
+
|
139
|
+
.comparison__table {
|
140
|
+
border-collapse: collapse;
|
141
|
+
white-space: nowrap;
|
142
|
+
width: 100%;
|
143
|
+
}
|
144
|
+
|
145
|
+
.comparison__table tr:nth-child(even) {
|
146
|
+
background-color: var(--docs-background-color);
|
147
|
+
}
|
148
|
+
|
149
|
+
.comparison__table th, .comparison__table td {
|
150
|
+
border: 1px solid var(--docs-border-color);
|
151
|
+
padding: 0.5rem;
|
152
|
+
table-layout: fixed;
|
153
|
+
}
|
154
|
+
|
155
|
+
.comparison__what {
|
156
|
+
text-align: left;
|
157
|
+
}
|
158
|
+
|
159
|
+
.comparison__who {
|
160
|
+
text-align: center;
|
161
|
+
min-width: 7rem;
|
162
|
+
}
|
163
|
+
|
164
|
+
.comparison__note {
|
165
|
+
font-size: 0.8rem;
|
166
|
+
}
|
167
|
+
|
168
|
+
.comparison__how {
|
169
|
+
text-align: center;
|
170
|
+
}
|
171
|
+
|
172
|
+
a {
|
173
|
+
color: var(--docs-text-color);
|
174
|
+
|
175
|
+
&:has(code) {
|
176
|
+
text-underline-position: under;
|
177
|
+
text-decoration-thickness: 1px;
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
h1 {
|
182
|
+
font-size: 2rem;
|
183
|
+
}
|
184
|
+
|
185
|
+
h2 code {
|
186
|
+
font-size: 1.5rem;
|
187
|
+
}
|
188
|
+
|
189
|
+
.screenshot {
|
190
|
+
max-width: 400px;
|
191
|
+
}
|
192
|
+
|
193
|
+
.screenshot--desktop {
|
194
|
+
max-width: 600px;
|
195
|
+
}
|
196
|
+
|
197
|
+
.screenshot__image {
|
198
|
+
border-radius: 0.375rem;
|
199
|
+
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
200
|
+
height: auto;
|
201
|
+
width: 100%;
|
202
|
+
}
|
203
|
+
|
204
|
+
hr {
|
205
|
+
border: 0;
|
206
|
+
border-top: 1px solid var(--docs-border-color);
|
207
|
+
}
|
208
|
+
|
209
|
+
pre {
|
210
|
+
overflow-x: auto;
|
211
|
+
-webkit-overflow-scrolling: touch;
|
212
|
+
margin-bottom: 1rem;
|
213
|
+
margin-left: 0;
|
214
|
+
width: 100%;
|
215
|
+
border-radius: .375rem;
|
216
|
+
box-shadow: 0 0 #0000, 0 0 #0000, 0 10px 15px -3px rgba(0, 0, 0, .1), 0 4px 6px -4px rgba(0, 0, 0, .1);;
|
217
|
+
scrollbar-color: hsla(0,0%,0%,0.1) transparent;
|
218
|
+
}
|
219
|
+
|
220
|
+
code {
|
221
|
+
background: var(--docs-code-background-color);
|
222
|
+
border: .1rem solid var(--docs-code-border-color);
|
223
|
+
border-radius: 0.375rem;
|
224
|
+
display: inline;
|
225
|
+
font-size: 0.8rem;
|
226
|
+
overflow-x: auto;
|
227
|
+
overflow: auto;
|
228
|
+
padding: 0.1rem 0.2rem;
|
229
|
+
word-break: break-word;
|
230
|
+
}
|
231
|
+
|
232
|
+
pre code {
|
233
|
+
border: none;
|
234
|
+
display: block;
|
235
|
+
padding: 1em;
|
236
|
+
}
|
237
|
+
|
238
|
+
.imagemap {
|
239
|
+
display: none;
|
240
|
+
|
241
|
+
@media (min-width: 64rem) {
|
242
|
+
display: initial;
|
243
|
+
}
|
244
|
+
}
|
245
|
+
}
|
File without changes
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ApplicationHelper
|
2
|
+
def website_menu_items
|
3
|
+
[
|
4
|
+
{ label: "Welcome", url: root_path },
|
5
|
+
{
|
6
|
+
label: "Quickstart", url: quickstart_path, children: [
|
7
|
+
{ label: "Embedded", url: embedded_path },
|
8
|
+
{ label: "Standalone", url: standalone_path }
|
9
|
+
]
|
10
|
+
},
|
11
|
+
{ label: "Markdown", url: markdown_path },
|
12
|
+
{ label: "Static export", url: static_export_path },
|
13
|
+
{
|
14
|
+
label: "Components", url: components_path, children: [
|
15
|
+
{ label: "Nav / Sidenav", url: nav_path },
|
16
|
+
{ label: "Table of contents", url: toc_path },
|
17
|
+
{ label: "Search", url: search_path },
|
18
|
+
{ label: "Light / Dark", url: light_dark_path },
|
19
|
+
{ label: "Footer", url: footer_path },
|
20
|
+
{ label: "Helpers", url: helpers_path }
|
21
|
+
]
|
22
|
+
}
|
23
|
+
]
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module HotDocsHelper
|
2
|
+
def active_link_to(name = nil, options = nil, html_options = nil, &block)
|
3
|
+
if options.is_a?(String) && active_link?(options)
|
4
|
+
html_options = html_options.to_h.merge(class: "active") do |_, old, new|
|
5
|
+
[ *Array(old), new ].join(" ")
|
6
|
+
end
|
7
|
+
link_to(name, options, html_options, &block)
|
8
|
+
else
|
9
|
+
link_to(name, options, html_options, &block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def external_link_to(name = nil, options = nil, html_options = nil)
|
14
|
+
default_html_options = {
|
15
|
+
class: "external-link",
|
16
|
+
target: "_blank",
|
17
|
+
rel: [ "noopener", "noreferrer" ]
|
18
|
+
}
|
19
|
+
|
20
|
+
html_options = html_options.to_h.merge(default_html_options) do |_, old, new|
|
21
|
+
[ *Array(old), *Array(new) ].join(" ")
|
22
|
+
end
|
23
|
+
|
24
|
+
link_to(options, html_options) do
|
25
|
+
concat(content_tag(:span, name))
|
26
|
+
|
27
|
+
concat(<<~SVG.html_safe)
|
28
|
+
<svg aria-hidden="true" viewBox="0 0 24 24" class="external-link__icon">
|
29
|
+
<path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"></path>
|
30
|
+
</svg>
|
31
|
+
SVG
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def active_link?(url)
|
36
|
+
request.path == url
|
37
|
+
end
|
38
|
+
|
39
|
+
def nav_left_items(classes)
|
40
|
+
require "ostruct"
|
41
|
+
|
42
|
+
[
|
43
|
+
active_link_to("Docs", root_path, class: Array(classes))
|
44
|
+
]
|
45
|
+
end
|
46
|
+
|
47
|
+
def nav_right_items(classes)
|
48
|
+
require "ostruct"
|
49
|
+
|
50
|
+
[
|
51
|
+
external_link_to("GitHub", "https://github.com/3v0k4/hot_docs", class: Array(classes))
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
# { label: "", url: *_path, children: [], expanded: false/true }
|
56
|
+
def menu_items
|
57
|
+
[
|
58
|
+
{ label: "Page", url: hot_docs_page_path }
|
59
|
+
]
|
60
|
+
end
|
61
|
+
|
62
|
+
def menu(items = menu_items)
|
63
|
+
menu_r(compute_menu(items))
|
64
|
+
end
|
65
|
+
|
66
|
+
def compute_menu(items)
|
67
|
+
compute_menu_r(items).first
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def compute_menu_r(items)
|
73
|
+
return [ [], false ] if items.nil?
|
74
|
+
|
75
|
+
new_items = items.map do |item|
|
76
|
+
children, expanded_below = compute_menu_r(item[:children])
|
77
|
+
active = active_link?(item.fetch(:url))
|
78
|
+
expanded = expanded_below || item[:expanded] || active
|
79
|
+
{ **item, expanded: expanded, children: children }
|
80
|
+
end
|
81
|
+
|
82
|
+
[ new_items, new_items.any? { _1[:expanded] } ]
|
83
|
+
end
|
84
|
+
|
85
|
+
def menu_r(items)
|
86
|
+
return nil if items.size == 0
|
87
|
+
|
88
|
+
content_tag(:ul, class: "menu__section") do
|
89
|
+
items.each do |item|
|
90
|
+
concat(content_tag(:li) do
|
91
|
+
locals = { expanded: item.fetch(:expanded), label: item.fetch(:label), url: item.fetch(:url) }
|
92
|
+
concat(render partial: "hot_docs/menu_row", locals: locals)
|
93
|
+
|
94
|
+
concat(menu_r(item.fetch(:children)))
|
95
|
+
end)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static values = {
|
5
|
+
expanded: Boolean,
|
6
|
+
expandedClass: String,
|
7
|
+
collapsedAriaLabel: String,
|
8
|
+
expandedAriaLabel: String,
|
9
|
+
};
|
10
|
+
|
11
|
+
static targets = ["toggle"];
|
12
|
+
|
13
|
+
connect() {
|
14
|
+
this._setStatus();
|
15
|
+
|
16
|
+
if (this.expandedValue) {
|
17
|
+
this.element.classList.add(this.expandedClassValue);
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
toggle() {
|
22
|
+
this.expandedValue = !this.expandedValue;
|
23
|
+
this._setStatus();
|
24
|
+
this.element.classList.toggle(this.expandedClassValue);
|
25
|
+
}
|
26
|
+
|
27
|
+
_setStatus() {
|
28
|
+
if (this.expandedValue) {
|
29
|
+
this.toggleTarget.ariaExpanded = true;
|
30
|
+
this.toggleTarget.ariaLabel = this.expandedAriaLabelValue;
|
31
|
+
} else {
|
32
|
+
this.toggleTarget.ariaExpanded = false;
|
33
|
+
this.toggleTarget.ariaLabel = this.collapsedAriaLabelValue;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
@@ -0,0 +1,4 @@
|
|
1
|
+
// Import and register all your controllers from the importmap via controllers/**/*_controller
|
2
|
+
import { application } from "controllers/application"
|
3
|
+
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
|
4
|
+
eagerLoadControllersFrom("controllers", application)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ["sections"];
|
5
|
+
|
6
|
+
static values = {
|
7
|
+
openClass: String,
|
8
|
+
mainSectionClass: String,
|
9
|
+
};
|
10
|
+
|
11
|
+
open(event) {
|
12
|
+
this.opener = event.currentTarget;
|
13
|
+
this.opener.ariaExpanded = true;
|
14
|
+
this._toggleOpen();
|
15
|
+
}
|
16
|
+
|
17
|
+
close() {
|
18
|
+
this._toggleOpen();
|
19
|
+
this.opener.ariaExpanded = false;
|
20
|
+
if (this.resetSection) {
|
21
|
+
this.resetSection();
|
22
|
+
this.resetSection = null;
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
back() {
|
27
|
+
this.sectionsTarget.classList.add(this.mainSectionClassValue);
|
28
|
+
this.resetSection = () => {
|
29
|
+
setTimeout(
|
30
|
+
() => this.sectionsTarget.classList.remove(this.mainSectionClassValue),
|
31
|
+
200 // Give time to the CSS transition to finish
|
32
|
+
);
|
33
|
+
};
|
34
|
+
}
|
35
|
+
|
36
|
+
_toggleOpen(event) {
|
37
|
+
document.body.classList.toggle(this.openClassValue);
|
38
|
+
}
|
39
|
+
}
|
@@ -0,0 +1,91 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
// `templates`s must contain an `<a>`
|
5
|
+
static targets = [
|
6
|
+
"article",
|
7
|
+
"sidetoc",
|
8
|
+
"sidetocTemplate",
|
9
|
+
"toc",
|
10
|
+
"tocTemplate",
|
11
|
+
];
|
12
|
+
|
13
|
+
connect() {
|
14
|
+
this._slugHeadings();
|
15
|
+
this._createEntries();
|
16
|
+
this._trackActiveEntry();
|
17
|
+
}
|
18
|
+
|
19
|
+
_slugHeadings() {
|
20
|
+
this._headings().forEach((heading) => {
|
21
|
+
if (heading.id !== "") {
|
22
|
+
return;
|
23
|
+
}
|
24
|
+
|
25
|
+
heading.id = slug(heading.innerText);
|
26
|
+
});
|
27
|
+
}
|
28
|
+
|
29
|
+
_createEntries() {
|
30
|
+
this._headings().forEach((heading) => {
|
31
|
+
const a = this._createEntry(
|
32
|
+
heading,
|
33
|
+
this.sidetocTemplateTarget,
|
34
|
+
this.sidetocTarget
|
35
|
+
);
|
36
|
+
a.id = `toc-${heading.id}`;
|
37
|
+
|
38
|
+
this._createEntry(heading, this.tocTemplateTarget, this.tocTarget);
|
39
|
+
});
|
40
|
+
}
|
41
|
+
|
42
|
+
_createEntry(heading, templateTarget, tocTarget) {
|
43
|
+
const clone = templateTarget.content.cloneNode(true);
|
44
|
+
const a = clone.querySelector("a");
|
45
|
+
a.classList.add(heading.tagName.toLowerCase());
|
46
|
+
a.href = `#${heading.id}`;
|
47
|
+
a.innerHTML = heading.innerHTML;
|
48
|
+
tocTarget.appendChild(clone);
|
49
|
+
return a;
|
50
|
+
}
|
51
|
+
|
52
|
+
_trackActiveEntry() {
|
53
|
+
const callback = (entries) => {
|
54
|
+
entries.forEach((entry) => {
|
55
|
+
if (!entry.isIntersecting) {
|
56
|
+
return;
|
57
|
+
}
|
58
|
+
this.sidetocTarget.querySelectorAll("a").forEach((a) => {
|
59
|
+
a.classList.remove("active");
|
60
|
+
});
|
61
|
+
this.sidetocTarget
|
62
|
+
.querySelector(`#toc-${entry.target.id}`)
|
63
|
+
.classList.add("active");
|
64
|
+
});
|
65
|
+
};
|
66
|
+
const options = { threshold: 1.0, rootMargin: "0px 0px -75% 0px" };
|
67
|
+
const observer = new IntersectionObserver(callback, options);
|
68
|
+
|
69
|
+
this._headings().forEach((heading) => {
|
70
|
+
observer.observe(heading);
|
71
|
+
});
|
72
|
+
}
|
73
|
+
|
74
|
+
_headings() {
|
75
|
+
return this.articleTarget.querySelectorAll("h1, h2, h3, h4, h5, h6");
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
// Copyright (c) 2015, Dan Flettre <fletd01@yahoo.com>
|
80
|
+
//
|
81
|
+
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
82
|
+
//
|
83
|
+
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
84
|
+
//
|
85
|
+
// https://github.com/Flet/github-slugger
|
86
|
+
|
87
|
+
const REGEX =
|
88
|
+
/[\0-\x1F!-,\.\/:-@\[-\^`\{-\xA9\xAB-\xB4\xB6-\xB9\xBB-\xBF\xD7\xF7\u02C2-\u02C5\u02D2-\u02DF\u02E5-\u02EB\u02ED\u02EF-\u02FF\u0375\u0378\u0379\u037E\u0380-\u0385\u0387\u038B\u038D\u03A2\u03F6\u0482\u0530\u0557\u0558\u055A-\u055F\u0589-\u0590\u05BE\u05C0\u05C3\u05C6\u05C8-\u05CF\u05EB-\u05EE\u05F3-\u060F\u061B-\u061F\u066A-\u066D\u06D4\u06DD\u06DE\u06E9\u06FD\u06FE\u0700-\u070F\u074B\u074C\u07B2-\u07BF\u07F6-\u07F9\u07FB\u07FC\u07FE\u07FF\u082E-\u083F\u085C-\u085F\u086B-\u089F\u08B5\u08C8-\u08D2\u08E2\u0964\u0965\u0970\u0984\u098D\u098E\u0991\u0992\u09A9\u09B1\u09B3-\u09B5\u09BA\u09BB\u09C5\u09C6\u09C9\u09CA\u09CF-\u09D6\u09D8-\u09DB\u09DE\u09E4\u09E5\u09F2-\u09FB\u09FD\u09FF\u0A00\u0A04\u0A0B-\u0A0E\u0A11\u0A12\u0A29\u0A31\u0A34\u0A37\u0A3A\u0A3B\u0A3D\u0A43-\u0A46\u0A49\u0A4A\u0A4E-\u0A50\u0A52-\u0A58\u0A5D\u0A5F-\u0A65\u0A76-\u0A80\u0A84\u0A8E\u0A92\u0AA9\u0AB1\u0AB4\u0ABA\u0ABB\u0AC6\u0ACA\u0ACE\u0ACF\u0AD1-\u0ADF\u0AE4\u0AE5\u0AF0-\u0AF8\u0B00\u0B04\u0B0D\u0B0E\u0B11\u0B12\u0B29\u0B31\u0B34\u0B3A\u0B3B\u0B45\u0B46\u0B49\u0B4A\u0B4E-\u0B54\u0B58-\u0B5B\u0B5E\u0B64\u0B65\u0B70\u0B72-\u0B81\u0B84\u0B8B-\u0B8D\u0B91\u0B96-\u0B98\u0B9B\u0B9D\u0BA0-\u0BA2\u0BA5-\u0BA7\u0BAB-\u0BAD\u0BBA-\u0BBD\u0BC3-\u0BC5\u0BC9\u0BCE\u0BCF\u0BD1-\u0BD6\u0BD8-\u0BE5\u0BF0-\u0BFF\u0C0D\u0C11\u0C29\u0C3A-\u0C3C\u0C45\u0C49\u0C4E-\u0C54\u0C57\u0C5B-\u0C5F\u0C64\u0C65\u0C70-\u0C7F\u0C84\u0C8D\u0C91\u0CA9\u0CB4\u0CBA\u0CBB\u0CC5\u0CC9\u0CCE-\u0CD4\u0CD7-\u0CDD\u0CDF\u0CE4\u0CE5\u0CF0\u0CF3-\u0CFF\u0D0D\u0D11\u0D45\u0D49\u0D4F-\u0D53\u0D58-\u0D5E\u0D64\u0D65\u0D70-\u0D79\u0D80\u0D84\u0D97-\u0D99\u0DB2\u0DBC\u0DBE\u0DBF\u0DC7-\u0DC9\u0DCB-\u0DCE\u0DD5\u0DD7\u0DE0-\u0DE5\u0DF0\u0DF1\u0DF4-\u0E00\u0E3B-\u0E3F\u0E4F\u0E5A-\u0E80\u0E83\u0E85\u0E8B\u0EA4\u0EA6\u0EBE\u0EBF\u0EC5\u0EC7\u0ECE\u0ECF\u0EDA\u0EDB\u0EE0-\u0EFF\u0F01-\u0F17\u0F1A-\u0F1F\u0F2A-\u0F34\u0F36\u0F38\u0F3A-\u0F3D\u0F48\u0F6D-\u0F70\u0F85\u0F98\u0FBD-\u0FC5\u0FC7-\u0FFF\u104A-\u104F\u109E\u109F\u10C6\u10C8-\u10CC\u10CE\u10CF\u10FB\u1249\u124E\u124F\u1257\u1259\u125E\u125F\u1289\u128E\u128F\u12B1\u12B6\u12B7\u12BF\u12C1\u12C6\u12C7\u12D7\u1311\u1316\u1317\u135B\u135C\u1360-\u137F\u1390-\u139F\u13F6\u13F7\u13FE-\u1400\u166D\u166E\u1680\u169B-\u169F\u16EB-\u16ED\u16F9-\u16FF\u170D\u1715-\u171F\u1735-\u173F\u1754-\u175F\u176D\u1771\u1774-\u177F\u17D4-\u17D6\u17D8-\u17DB\u17DE\u17DF\u17EA-\u180A\u180E\u180F\u181A-\u181F\u1879-\u187F\u18AB-\u18AF\u18F6-\u18FF\u191F\u192C-\u192F\u193C-\u1945\u196E\u196F\u1975-\u197F\u19AC-\u19AF\u19CA-\u19CF\u19DA-\u19FF\u1A1C-\u1A1F\u1A5F\u1A7D\u1A7E\u1A8A-\u1A8F\u1A9A-\u1AA6\u1AA8-\u1AAF\u1AC1-\u1AFF\u1B4C-\u1B4F\u1B5A-\u1B6A\u1B74-\u1B7F\u1BF4-\u1BFF\u1C38-\u1C3F\u1C4A-\u1C4C\u1C7E\u1C7F\u1C89-\u1C8F\u1CBB\u1CBC\u1CC0-\u1CCF\u1CD3\u1CFB-\u1CFF\u1DFA\u1F16\u1F17\u1F1E\u1F1F\u1F46\u1F47\u1F4E\u1F4F\u1F58\u1F5A\u1F5C\u1F5E\u1F7E\u1F7F\u1FB5\u1FBD\u1FBF-\u1FC1\u1FC5\u1FCD-\u1FCF\u1FD4\u1FD5\u1FDC-\u1FDF\u1FED-\u1FF1\u1FF5\u1FFD-\u203E\u2041-\u2053\u2055-\u2070\u2072-\u207E\u2080-\u208F\u209D-\u20CF\u20F1-\u2101\u2103-\u2106\u2108\u2109\u2114\u2116-\u2118\u211E-\u2123\u2125\u2127\u2129\u212E\u213A\u213B\u2140-\u2144\u214A-\u214D\u214F-\u215F\u2189-\u24B5\u24EA-\u2BFF\u2C2F\u2C5F\u2CE5-\u2CEA\u2CF4-\u2CFF\u2D26\u2D28-\u2D2C\u2D2E\u2D2F\u2D68-\u2D6E\u2D70-\u2D7E\u2D97-\u2D9F\u2DA7\u2DAF\u2DB7\u2DBF\u2DC7\u2DCF\u2DD7\u2DDF\u2E00-\u2E2E\u2E30-\u3004\u3008-\u3020\u3030\u3036\u3037\u303D-\u3040\u3097\u3098\u309B\u309C\u30A0\u30FB\u3100-\u3104\u3130\u318F-\u319F\u31C0-\u31EF\u3200-\u33FF\u4DC0-\u4DFF\u9FFD-\u9FFF\uA48D-\uA4CF\uA4FE\uA4FF\uA60D-\uA60F\uA62C-\uA63F\uA673\uA67E\uA6F2-\uA716\uA720\uA721\uA789\uA78A\uA7C0\uA7C1\uA7CB-\uA7F4\uA828-\uA82B\uA82D-\uA83F\uA874-\uA87F\uA8C6-\uA8CF\uA8DA-\uA8DF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA954-\uA95F\uA97D-\uA97F\uA9C1-\uA9CE\uA9DA-\uA9DF\uA9FF\uAA37-\uAA3F\uAA4E\uAA4F\uAA5A-\uAA5F\uAA77-\uAA79\uAAC3-\uAADA\uAADE\uAADF\uAAF0\uAAF1\uAAF7-\uAB00\uAB07\uAB08\uAB0F\uAB10\uAB17-\uAB1F\uAB27\uAB2F\uAB5B\uAB6A-\uAB6F\uABEB\uABEE\uABEF\uABFA-\uABFF\uD7A4-\uD7AF\uD7C7-\uD7CA\uD7FC-\uD7FF\uE000-\uF8FF\uFA6E\uFA6F\uFADA-\uFAFF\uFB07-\uFB12\uFB18-\uFB1C\uFB29\uFB37\uFB3D\uFB3F\uFB42\uFB45\uFBB2-\uFBD2\uFD3E-\uFD4F\uFD90\uFD91\uFDC8-\uFDEF\uFDFC-\uFDFF\uFE10-\uFE1F\uFE30-\uFE32\uFE35-\uFE4C\uFE50-\uFE6F\uFE75\uFEFD-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF3E\uFF40\uFF5B-\uFF65\uFFBF-\uFFC1\uFFC8\uFFC9\uFFD0\uFFD1\uFFD8\uFFD9\uFFDD-\uFFFF]|\uD800[\uDC0C\uDC27\uDC3B\uDC3E\uDC4E\uDC4F\uDC5E-\uDC7F\uDCFB-\uDD3F\uDD75-\uDDFC\uDDFE-\uDE7F\uDE9D-\uDE9F\uDED1-\uDEDF\uDEE1-\uDEFF\uDF20-\uDF2C\uDF4B-\uDF4F\uDF7B-\uDF7F\uDF9E\uDF9F\uDFC4-\uDFC7\uDFD0\uDFD6-\uDFFF]|\uD801[\uDC9E\uDC9F\uDCAA-\uDCAF\uDCD4-\uDCD7\uDCFC-\uDCFF\uDD28-\uDD2F\uDD64-\uDDFF\uDF37-\uDF3F\uDF56-\uDF5F\uDF68-\uDFFF]|\uD802[\uDC06\uDC07\uDC09\uDC36\uDC39-\uDC3B\uDC3D\uDC3E\uDC56-\uDC5F\uDC77-\uDC7F\uDC9F-\uDCDF\uDCF3\uDCF6-\uDCFF\uDD16-\uDD1F\uDD3A-\uDD7F\uDDB8-\uDDBD\uDDC0-\uDDFF\uDE04\uDE07-\uDE0B\uDE14\uDE18\uDE36\uDE37\uDE3B-\uDE3E\uDE40-\uDE5F\uDE7D-\uDE7F\uDE9D-\uDEBF\uDEC8\uDEE7-\uDEFF\uDF36-\uDF3F\uDF56-\uDF5F\uDF73-\uDF7F\uDF92-\uDFFF]|\uD803[\uDC49-\uDC7F\uDCB3-\uDCBF\uDCF3-\uDCFF\uDD28-\uDD2F\uDD3A-\uDE7F\uDEAA\uDEAD-\uDEAF\uDEB2-\uDEFF\uDF1D-\uDF26\uDF28-\uDF2F\uDF51-\uDFAF\uDFC5-\uDFDF\uDFF7-\uDFFF]|\uD804[\uDC47-\uDC65\uDC70-\uDC7E\uDCBB-\uDCCF\uDCE9-\uDCEF\uDCFA-\uDCFF\uDD35\uDD40-\uDD43\uDD48-\uDD4F\uDD74\uDD75\uDD77-\uDD7F\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDFF\uDE12\uDE38-\uDE3D\uDE3F-\uDE7F\uDE87\uDE89\uDE8E\uDE9E\uDEA9-\uDEAF\uDEEB-\uDEEF\uDEFA-\uDEFF\uDF04\uDF0D\uDF0E\uDF11\uDF12\uDF29\uDF31\uDF34\uDF3A\uDF45\uDF46\uDF49\uDF4A\uDF4E\uDF4F\uDF51-\uDF56\uDF58-\uDF5C\uDF64\uDF65\uDF6D-\uDF6F\uDF75-\uDFFF]|\uD805[\uDC4B-\uDC4F\uDC5A-\uDC5D\uDC62-\uDC7F\uDCC6\uDCC8-\uDCCF\uDCDA-\uDD7F\uDDB6\uDDB7\uDDC1-\uDDD7\uDDDE-\uDDFF\uDE41-\uDE43\uDE45-\uDE4F\uDE5A-\uDE7F\uDEB9-\uDEBF\uDECA-\uDEFF\uDF1B\uDF1C\uDF2C-\uDF2F\uDF3A-\uDFFF]|\uD806[\uDC3B-\uDC9F\uDCEA-\uDCFE\uDD07\uDD08\uDD0A\uDD0B\uDD14\uDD17\uDD36\uDD39\uDD3A\uDD44-\uDD4F\uDD5A-\uDD9F\uDDA8\uDDA9\uDDD8\uDDD9\uDDE2\uDDE5-\uDDFF\uDE3F-\uDE46\uDE48-\uDE4F\uDE9A-\uDE9C\uDE9E-\uDEBF\uDEF9-\uDFFF]|\uD807[\uDC09\uDC37\uDC41-\uDC4F\uDC5A-\uDC71\uDC90\uDC91\uDCA8\uDCB7-\uDCFF\uDD07\uDD0A\uDD37-\uDD39\uDD3B\uDD3E\uDD48-\uDD4F\uDD5A-\uDD5F\uDD66\uDD69\uDD8F\uDD92\uDD99-\uDD9F\uDDAA-\uDEDF\uDEF7-\uDFAF\uDFB1-\uDFFF]|\uD808[\uDF9A-\uDFFF]|\uD809[\uDC6F-\uDC7F\uDD44-\uDFFF]|[\uD80A\uD80B\uD80E-\uD810\uD812-\uD819\uD824-\uD82B\uD82D\uD82E\uD830-\uD833\uD837\uD839\uD83D\uD83F\uD87B-\uD87D\uD87F\uD885-\uDB3F\uDB41-\uDBFF][\uDC00-\uDFFF]|\uD80D[\uDC2F-\uDFFF]|\uD811[\uDE47-\uDFFF]|\uD81A[\uDE39-\uDE3F\uDE5F\uDE6A-\uDECF\uDEEE\uDEEF\uDEF5-\uDEFF\uDF37-\uDF3F\uDF44-\uDF4F\uDF5A-\uDF62\uDF78-\uDF7C\uDF90-\uDFFF]|\uD81B[\uDC00-\uDE3F\uDE80-\uDEFF\uDF4B-\uDF4E\uDF88-\uDF8E\uDFA0-\uDFDF\uDFE2\uDFE5-\uDFEF\uDFF2-\uDFFF]|\uD821[\uDFF8-\uDFFF]|\uD823[\uDCD6-\uDCFF\uDD09-\uDFFF]|\uD82C[\uDD1F-\uDD4F\uDD53-\uDD63\uDD68-\uDD6F\uDEFC-\uDFFF]|\uD82F[\uDC6B-\uDC6F\uDC7D-\uDC7F\uDC89-\uDC8F\uDC9A-\uDC9C\uDC9F-\uDFFF]|\uD834[\uDC00-\uDD64\uDD6A-\uDD6C\uDD73-\uDD7A\uDD83\uDD84\uDD8C-\uDDA9\uDDAE-\uDE41\uDE45-\uDFFF]|\uD835[\uDC55\uDC9D\uDCA0\uDCA1\uDCA3\uDCA4\uDCA7\uDCA8\uDCAD\uDCBA\uDCBC\uDCC4\uDD06\uDD0B\uDD0C\uDD15\uDD1D\uDD3A\uDD3F\uDD45\uDD47-\uDD49\uDD51\uDEA6\uDEA7\uDEC1\uDEDB\uDEFB\uDF15\uDF35\uDF4F\uDF6F\uDF89\uDFA9\uDFC3\uDFCC\uDFCD]|\uD836[\uDC00-\uDDFF\uDE37-\uDE3A\uDE6D-\uDE74\uDE76-\uDE83\uDE85-\uDE9A\uDEA0\uDEB0-\uDFFF]|\uD838[\uDC07\uDC19\uDC1A\uDC22\uDC25\uDC2B-\uDCFF\uDD2D-\uDD2F\uDD3E\uDD3F\uDD4A-\uDD4D\uDD4F-\uDEBF\uDEFA-\uDFFF]|\uD83A[\uDCC5-\uDCCF\uDCD7-\uDCFF\uDD4C-\uDD4F\uDD5A-\uDFFF]|\uD83B[\uDC00-\uDDFF\uDE04\uDE20\uDE23\uDE25\uDE26\uDE28\uDE33\uDE38\uDE3A\uDE3C-\uDE41\uDE43-\uDE46\uDE48\uDE4A\uDE4C\uDE50\uDE53\uDE55\uDE56\uDE58\uDE5A\uDE5C\uDE5E\uDE60\uDE63\uDE65\uDE66\uDE6B\uDE73\uDE78\uDE7D\uDE7F\uDE8A\uDE9C-\uDEA0\uDEA4\uDEAA\uDEBC-\uDFFF]|\uD83C[\uDC00-\uDD2F\uDD4A-\uDD4F\uDD6A-\uDD6F\uDD8A-\uDFFF]|\uD83E[\uDC00-\uDFEF\uDFFA-\uDFFF]|\uD869[\uDEDE-\uDEFF]|\uD86D[\uDF35-\uDF3F]|\uD86E[\uDC1E\uDC1F]|\uD873[\uDEA2-\uDEAF]|\uD87A[\uDFE1-\uDFFF]|\uD87E[\uDE1E-\uDFFF]|\uD884[\uDF4B-\uDFFF]|\uDB40[\uDC00-\uDCFF\uDDF0-\uDFFF]/g;
|
89
|
+
|
90
|
+
export const slug = (string) =>
|
91
|
+
string.toLowerCase().replace(REGEX, "").replace(/ /g, "-");
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus";
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
EMPTY = " ";
|
5
|
+
|
6
|
+
static targets = ["typewrite"];
|
7
|
+
|
8
|
+
static values = {
|
9
|
+
phrases: Array,
|
10
|
+
};
|
11
|
+
|
12
|
+
connect() {
|
13
|
+
this.typewriteTarget.innerHTML = this.phrasesValue[0];
|
14
|
+
this.typed = this.phrasesValue[0];
|
15
|
+
this.phrase = this.phrasesValue[0];
|
16
|
+
this.timeout = setTimeout(() => this._delete(), 2000);
|
17
|
+
}
|
18
|
+
|
19
|
+
disconnect() {
|
20
|
+
clearTimeout(this.timeout);
|
21
|
+
}
|
22
|
+
|
23
|
+
_type() {
|
24
|
+
if (this.typed === this.EMPTY) {
|
25
|
+
this.typed = this.phrase.substring(0, 1);
|
26
|
+
} else {
|
27
|
+
this.typed = this.phrase.substring(0, this.typed.length + 1);
|
28
|
+
}
|
29
|
+
|
30
|
+
this.typewriteTarget.innerHTML = this.typed;
|
31
|
+
|
32
|
+
if (this.typed === this.phrase) {
|
33
|
+
this.timeout = setTimeout(() => this._delete(), 2000);
|
34
|
+
} else {
|
35
|
+
const delay = 200 - Math.random() * 100;
|
36
|
+
this.timeout = setTimeout(() => this._type(), delay);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
|
40
|
+
_delete() {
|
41
|
+
this.typed = this.phrase.substring(0, this.typed.length - 1);
|
42
|
+
if (this.typed.length === 0) this.typed = this.EMPTY;
|
43
|
+
this.typewriteTarget.innerHTML = this.typed;
|
44
|
+
|
45
|
+
if (this.typed === this.EMPTY) {
|
46
|
+
this._nextPhrase();
|
47
|
+
this.timeout = setTimeout(() => this._type(), 500);
|
48
|
+
} else {
|
49
|
+
const delay = (200 - Math.random() * 100) / 2;
|
50
|
+
this.timeout = setTimeout(() => this._delete(), delay);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
_nextPhrase() {
|
55
|
+
const currentIndex = this.phrasesValue.findIndex((x) => this.phrase === x);
|
56
|
+
const nextIndex = (currentIndex + 1) % this.phrasesValue.length;
|
57
|
+
this.phrase = this.phrasesValue[nextIndex];
|
58
|
+
}
|
59
|
+
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class ApplicationJob < ActiveJob::Base
|
2
|
+
# Automatically retry jobs that encountered a deadlock
|
3
|
+
# retry_on ActiveRecord::Deadlocked
|
4
|
+
|
5
|
+
# Most jobs are safe to ignore if the underlying records are no longer available
|
6
|
+
# discard_on ActiveJob::DeserializationError
|
7
|
+
end
|
File without changes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<%# locals: (label:, url:, expanded: false) -%>
|
2
|
+
|
3
|
+
<%= content_tag :div, class: "menu__row", data: { "controller": "accordion", "accordion-expanded-class-value": "menu__row--expanded", "accordion-expanded-value": expanded, "accordion-collapsed-aria-label-value": "Expand menu row '#{label}'", "accordion-expanded-aria-label-value": "Collapse menu row '#{label}'" } do %>
|
4
|
+
<%= active_link_to label, url, class: "menu__link" %>
|
5
|
+
|
6
|
+
<button type="button" class="menu__toggle" data-action="click->accordion#toggle" data-accordion-target="toggle">
|
7
|
+
<svg class="menu__toggle-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
8
|
+
<path fill="currentColor" d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path>
|
9
|
+
</svg>
|
10
|
+
</button>
|
11
|
+
<% end %>
|