hotdocs 0.1.0 → 0.3.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 +4 -4
- data/README.md +3 -3
- data/app/assets/javascript/controllers/fetcher_controller.js +29 -0
- data/app/assets/javascript/controllers/search_controller.js +162 -0
- data/app/assets/stylesheets/hotdocs/application.css +173 -13
- data/app/helpers/hotdocs/application_helper.rb +12 -1
- data/app/views/layouts/hotdocs/application.html.erb +129 -73
- data/config/importmap.rb +1 -1
- data/lib/hotdocs/engine.rb +1 -2
- data/lib/hotdocs/kramdown_alerts.rb +92 -0
- data/lib/hotdocs/markdown.rb +21 -25
- data/lib/hotdocs/version.rb +1 -1
- data/lib/install/install.rb +189 -173
- data/lib/tasks/hotdocs_tasks.rake +88 -4
- metadata +48 -4
- data/lib/hotdocs/markdown.mjs +0 -177
@@ -1,5 +1,5 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
|
-
<html data-theme="light">
|
2
|
+
<html data-theme="light" lang="<%= I18n.locale %>">
|
3
3
|
<head>
|
4
4
|
<title><%= content_for(:title) %></title>
|
5
5
|
|
@@ -9,81 +9,130 @@
|
|
9
9
|
<%= stylesheet_link_tag "hotdocs/application", media: "all", "data-turbo-track": "reload" %>
|
10
10
|
</head>
|
11
11
|
|
12
|
-
<body>
|
13
|
-
<
|
14
|
-
<div class="
|
15
|
-
<
|
16
|
-
<
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
</div>
|
25
|
-
|
26
|
-
<span class="nav__title">HotDocs</span>
|
27
|
-
<% end %>
|
28
|
-
|
29
|
-
<div class="nav__links">
|
30
|
-
<% nav_left_items("nav__link").each do |item| %>
|
31
|
-
<%= item %>
|
32
|
-
<% end %>
|
12
|
+
<body data-controller="search">
|
13
|
+
<dialog data-search-target="search" class="search">
|
14
|
+
<div data-search-target="dialog" class="search__dialog">
|
15
|
+
<div class="search__header">
|
16
|
+
<input autofocus data-action="input->search#search" type="text" class="search__input"></input>
|
17
|
+
<button aria-label="Close search dialog" type="button" class="search__dismiss" data-action="click->search#close">
|
18
|
+
<svg viewBox="0 0 15 15">
|
19
|
+
<g stroke="currentColor" stroke-width="1.2">
|
20
|
+
<path d="M.75.75l13.5 13.5M14.25.75L.75 14.25"></path>
|
21
|
+
</g>
|
22
|
+
</svg>
|
23
|
+
</button>
|
33
24
|
</div>
|
34
|
-
</div>
|
35
25
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
</
|
26
|
+
<template data-search-target="resultTemplate">
|
27
|
+
<li class="search__result">
|
28
|
+
<h1></h1>
|
29
|
+
<a href="#" class="search__result-excerpt"></a>
|
30
|
+
</li>
|
31
|
+
</template>
|
32
|
+
|
33
|
+
<ul data-search-target="results">
|
34
|
+
<li class="search__result search__result--loading">
|
35
|
+
Loading index...
|
36
|
+
</li>
|
37
|
+
</ul>
|
42
38
|
</div>
|
43
39
|
|
44
|
-
<
|
45
|
-
|
46
|
-
|
40
|
+
<script type="application/json" data-search-target="data">
|
41
|
+
<%= raw(Rails.application.assets.resolver.read("search_data.json")&.force_encoding("UTF-8") || [].to_json) %>
|
42
|
+
</script>
|
43
|
+
</dialog>
|
44
|
+
|
45
|
+
<% if content_for?(:hotdocs_nav) %>
|
46
|
+
<%= content_for(:hotdocs_nav) %>
|
47
|
+
|
48
|
+
<% else %>
|
49
|
+
<nav class="nav" data-controller="sidenav" data-sidenav-open-class-value="sidenav--open" data-sidenav-main-menu-class-value="sidenav__sections--main">
|
50
|
+
<div class="nav__section">
|
51
|
+
<button class="nav__toggle" type="button" aria-label="Toggle navigation" aria-expanded="false" data-action="click->sidenav#open">
|
52
|
+
<svg viewBox="0 0 30 30" aria-hidden="true">
|
53
|
+
<path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path>
|
54
|
+
</svg>
|
55
|
+
</button>
|
56
|
+
|
47
57
|
<%= link_to root_path, class: "nav__brand" do %>
|
48
|
-
|
49
|
-
<
|
50
|
-
|
58
|
+
<% unless logo.nil? %>
|
59
|
+
<div class="nav__logo-wrapper">
|
60
|
+
<img class="nav__logo" src="<%= logo.src %>" alt="<%= logo.alt %>" height="32" width="32" />
|
61
|
+
</div>
|
62
|
+
<% end %>
|
51
63
|
|
52
|
-
<span class="nav__title"
|
64
|
+
<span class="nav__title"><%= title %></span>
|
53
65
|
<% end %>
|
54
66
|
|
55
|
-
<
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
67
|
+
<div class="nav__links">
|
68
|
+
<% nav_left_items("nav__link").each do |item| %>
|
69
|
+
<%= item %>
|
70
|
+
<% end %>
|
71
|
+
</div>
|
72
|
+
</div>
|
73
|
+
|
74
|
+
<div class="nav__section">
|
75
|
+
<div class="nav__links">
|
76
|
+
<% nav_right_items("nav__link").each do |item| %>
|
77
|
+
<%= item %>
|
78
|
+
<% end %>
|
79
|
+
</div>
|
80
|
+
|
81
|
+
<button type="button" data-action="click->search#open:stop" class="search-button" aria-label="Open search dialog">
|
82
|
+
<svg class="search-button__icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
|
83
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
|
60
84
|
</svg>
|
85
|
+
|
86
|
+
<span class="search-button__label">Type / to search</span>
|
61
87
|
</button>
|
62
88
|
</div>
|
63
89
|
|
64
|
-
<div class="
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
</li>
|
90
|
+
<div class="sidenav-backdrop"></div>
|
91
|
+
<div class="sidenav">
|
92
|
+
<div class="sidenav__header">
|
93
|
+
<%= link_to root_path, class: "nav__brand" do %>
|
94
|
+
<% unless logo.nil? %>
|
95
|
+
<div class="nav__logo-wrapper">
|
96
|
+
<img class="nav__logo" src="<%= logo.src %>" alt="<%= logo.alt %>" height="32" width="32" />
|
97
|
+
</div>
|
73
98
|
<% end %>
|
74
|
-
|
99
|
+
|
100
|
+
<span class="nav__title"><%= title %></span>
|
101
|
+
<% end %>
|
102
|
+
|
103
|
+
<button aria-label="Close navigation" class="sidenav__toggle" type="button" data-action="click->sidenav#close">
|
104
|
+
<svg viewBox="0 0 15 15">
|
105
|
+
<g stroke="currentColor" stroke-width="1.2">
|
106
|
+
<path d="M.75.75l13.5 13.5M14.25.75L.75 14.25"></path>
|
107
|
+
</g>
|
108
|
+
</svg>
|
109
|
+
</button>
|
75
110
|
</div>
|
76
111
|
|
77
|
-
<div class="
|
78
|
-
<div class="
|
79
|
-
<
|
112
|
+
<div class="sidenav__sections" data-sidenav-target="sections">
|
113
|
+
<div class="sidenav__section">
|
114
|
+
<ul class="menu__section">
|
115
|
+
<% (nav_left_items("menu__link") + nav_right_items("menu__link")).each do |item| %>
|
116
|
+
<li>
|
117
|
+
<div class="menu__row">
|
118
|
+
<%= item %>
|
119
|
+
</div>
|
120
|
+
</li>
|
121
|
+
<% end %>
|
122
|
+
</ul>
|
80
123
|
</div>
|
81
124
|
|
82
|
-
|
125
|
+
<div class="sidenav__section">
|
126
|
+
<div class="menu__section">
|
127
|
+
<button type="button" class="sidenav__back-button" data-action="click->sidenav#back">← Back to main menu</button>
|
128
|
+
</div>
|
129
|
+
|
130
|
+
<%= menu %>
|
131
|
+
</div>
|
83
132
|
</div>
|
84
133
|
</div>
|
85
|
-
</
|
86
|
-
|
134
|
+
</nav>
|
135
|
+
<% end %>
|
87
136
|
|
88
137
|
<div class="content">
|
89
138
|
<aside class="menu">
|
@@ -121,24 +170,31 @@
|
|
121
170
|
</main>
|
122
171
|
</div>
|
123
172
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
173
|
+
<% if content_for?(:hotdocs_footer) %>
|
174
|
+
<%= content_for(:hotdocs_footer) %>
|
175
|
+
|
176
|
+
<% else %>
|
177
|
+
<footer class="footer">
|
178
|
+
<div class="footer__sections">
|
179
|
+
<% footer_items.each do |footer_item| %>
|
180
|
+
<div class="footer__section">
|
181
|
+
<p class="footer__heading"><%= footer_item.fetch(:heading) %></p>
|
182
|
+
|
183
|
+
<ul>
|
184
|
+
<% footer_item.fetch(:items).each do |item| %>
|
185
|
+
<li><%= item %></li>
|
186
|
+
<% end %>
|
187
|
+
</ul>
|
188
|
+
</div>
|
189
|
+
<% end %>
|
190
|
+
</div>
|
129
191
|
|
130
|
-
|
131
|
-
|
132
|
-
<li><%= item %></li>
|
133
|
-
<% end %>
|
134
|
-
</ul>
|
135
|
-
</div>
|
192
|
+
<% unless logo.nil? %>
|
193
|
+
<img class="footer__logo" src="<%= logo.src %>" alt="<%= logo.alt %>" height="150" width="150" />
|
136
194
|
<% end %>
|
137
|
-
</
|
138
|
-
|
139
|
-
<img class="footer__logo" src="<%= logo.src %>" alt="<%= logo.alt %>" height="150" width="150" />
|
195
|
+
</footer>
|
196
|
+
<% end %>
|
140
197
|
|
141
|
-
|
142
|
-
</footer>
|
198
|
+
<p class="credits">Built with Rails & <a class="credits__link" href="https://hotdocsrails.com">HotDocs<img class="credits__logo" src="<%= asset_path "hotdocs/icon.svg" %>" alt="A humanized and happy hot dog" height="32" width="32" /></a></p>
|
143
199
|
</body>
|
144
200
|
</html>
|
data/config/importmap.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
# Pin npm packages by running ./bin/importmap
|
2
2
|
|
3
|
-
pin_all_from Hotdocs::Engine.root.join("app/assets/javascript/controllers"), under: "controllers"
|
3
|
+
pin_all_from Hotdocs::Engine.root.join("app/assets/javascript/controllers"), to: "controllers", under: "hotdocs/controllers", preload: "hotdocs"
|
data/lib/hotdocs/engine.rb
CHANGED
@@ -13,8 +13,7 @@ module Hotdocs
|
|
13
13
|
end
|
14
14
|
|
15
15
|
config.before_initialize do
|
16
|
-
MarkdownHandler.
|
17
|
-
ActionView::Template.register_template_handler :mderb, MarkdownHandler.new(self)
|
16
|
+
ActionView::Template.register_template_handler :mderb, MarkdownHandler.new
|
18
17
|
end
|
19
18
|
end
|
20
19
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
module Kramdown
|
2
|
+
class Element
|
3
|
+
def to_h
|
4
|
+
{
|
5
|
+
children: children.map(&:to_h),
|
6
|
+
type:,
|
7
|
+
value:
|
8
|
+
}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
module Alert
|
14
|
+
PATHS_BY_ALERT_TYPE = {
|
15
|
+
"danger" => [
|
16
|
+
"M15.362 5.214A8.252 8.252 0 0 1 12 21 8.25 8.25 0 0 1 6.038 7.047 8.287 8.287 0 0 0 9 9.601a8.983 8.983 0 0 1 3.361-6.867 8.21 8.21 0 0 0 3 2.48Z",
|
17
|
+
"M12 18a3.75 3.75 0 0 0 .495-7.468 5.99 5.99 0 0 0-1.925 3.547 5.975 5.975 0 0 1-2.133-1.001A3.75 3.75 0 0 0 12 18Z"
|
18
|
+
],
|
19
|
+
"warning" => [
|
20
|
+
"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126ZM12 15.75h.007v.008H12v-.008Z"
|
21
|
+
],
|
22
|
+
"tip" => [
|
23
|
+
"M12 18v-5.25m0 0a6.01 6.01 0 0 0 1.5-.189m-1.5.189a6.01 6.01 0 0 1-1.5-.189m3.75 7.478a12.06 12.06 0 0 1-4.5 0m3.75 2.383a14.406 14.406 0 0 1-3 0M14.25 18v-.192c0-.983.658-1.823 1.508-2.316a7.5 7.5 0 1 0-7.517 0c.85.493 1.509 1.333 1.509 2.316V18"
|
24
|
+
],
|
25
|
+
"info" => [
|
26
|
+
"m11.25 11.25.041-.02a.75.75 0 0 1 1.063.852l-.708 2.836a.75.75 0 0 0 1.063.853l.041-.021M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9-3.75h.008v.008H12V8.25Z"
|
27
|
+
]
|
28
|
+
}
|
29
|
+
|
30
|
+
def convert_blockquote(el, indent)
|
31
|
+
child = el.children[0]
|
32
|
+
|
33
|
+
case child.to_h
|
34
|
+
in {
|
35
|
+
type: :p,
|
36
|
+
children: [
|
37
|
+
{ type: :text, value: /\A\[!(INFO|TIP|WARNING|DANGER)\]\z/ },
|
38
|
+
{ type: :br },
|
39
|
+
*
|
40
|
+
]
|
41
|
+
}
|
42
|
+
alert_type = $+.downcase
|
43
|
+
child.children.slice!(0, 2) # remove :text & :br
|
44
|
+
|
45
|
+
svg = Kramdown::Element.new(
|
46
|
+
:html_element,
|
47
|
+
:svg,
|
48
|
+
{
|
49
|
+
class: "alert__icon",
|
50
|
+
xmlns: "http://www.w3.org/2000/svg",
|
51
|
+
fill: "none",
|
52
|
+
viewBox: "0 0 24 24",
|
53
|
+
"stroke-width": "1.5",
|
54
|
+
stroke: "currentColor"
|
55
|
+
}
|
56
|
+
)
|
57
|
+
|
58
|
+
PATHS_BY_ALERT_TYPE[alert_type].each do |path|
|
59
|
+
svg.children << Kramdown::Element.new(:html_element, :path, {
|
60
|
+
"stroke-linecap": "round",
|
61
|
+
"stroke-linejoin": "round",
|
62
|
+
d: path
|
63
|
+
})
|
64
|
+
end
|
65
|
+
|
66
|
+
label = Kramdown::Element.new(:html_element, :span, { class: "alert__label" })
|
67
|
+
label.children << Kramdown::Element.new(:text, alert_type.upcase)
|
68
|
+
|
69
|
+
header = Kramdown::Element.new(:html_element, :div, { class: "alert__header" })
|
70
|
+
header.children << svg
|
71
|
+
header.children << label
|
72
|
+
|
73
|
+
content = Kramdown::Element.new(:html_element, :div, { class: "alert__content" })
|
74
|
+
content.children.push(*el.children)
|
75
|
+
|
76
|
+
alert = Kramdown::Element.new(:html_element, :div, {})
|
77
|
+
alert.children << header
|
78
|
+
alert.children << content
|
79
|
+
|
80
|
+
format_as_block_html(
|
81
|
+
"div",
|
82
|
+
{ class: "alert alert--#{alert_type}" },
|
83
|
+
format_as_indented_block_html("div", {}, inner(alert, indent), indent),
|
84
|
+
indent
|
85
|
+
)
|
86
|
+
else
|
87
|
+
super
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
Kramdown::Converter::Html.prepend(Alert)
|
data/lib/hotdocs/markdown.rb
CHANGED
@@ -1,32 +1,28 @@
|
|
1
|
-
require "
|
1
|
+
require "kramdown"
|
2
|
+
require "kramdown-parser-gfm"
|
3
|
+
require "rouge"
|
2
4
|
|
3
|
-
|
4
|
-
def self.prepare(engine)
|
5
|
-
# Install npm packages
|
6
|
-
Open3.capture3("deno --allow-read --allow-env --node-modules-dir=auto #{engine.root.join("lib/hotdocs/markdown.mjs")}", stdin_data: "")
|
7
|
-
rescue
|
8
|
-
Rails.logger.info("deno not found: Could not install npm packages.")
|
9
|
-
end
|
10
|
-
|
11
|
-
def initialize(engine)
|
12
|
-
@engine = engine
|
13
|
-
end
|
5
|
+
require_relative "kramdown_alerts"
|
14
6
|
|
7
|
+
class MarkdownHandler
|
15
8
|
def call(template, source)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
# It won't look great, but better than nothing.
|
24
|
-
return <<~STRING
|
25
|
-
@output_buffer.safe_append='#{compiled}'.freeze;
|
26
|
-
@output_buffer
|
27
|
-
STRING
|
9
|
+
# If the template contains a `fetcher`, do not allow Rails to cache the page.
|
10
|
+
if source.match?(%r{<%= fetcher.* do %>})
|
11
|
+
ActionView::PathRegistry.all_resolvers.each do |resolver|
|
12
|
+
resolver.instance_eval do
|
13
|
+
@unbound_templates.delete(template.virtual_path)
|
14
|
+
end
|
15
|
+
end
|
28
16
|
end
|
29
17
|
|
18
|
+
compiled_template = ::HotdocsController.render(inline: source, handler: :erb)
|
19
|
+
out = Kramdown::Document.new(
|
20
|
+
compiled_template,
|
21
|
+
input: "GFM",
|
22
|
+
auto_ids: false,
|
23
|
+
syntax_highlighter_opts: { css_class: "highlight" }
|
24
|
+
).to_html
|
25
|
+
|
30
26
|
content_fors = ActionView::Template::Handlers::ERB
|
31
27
|
.new
|
32
28
|
.call(template, source)
|
@@ -35,7 +31,7 @@ class MarkdownHandler
|
|
35
31
|
|
36
32
|
<<~STRING
|
37
33
|
#{content_fors.join(";")}
|
38
|
-
@output_buffer.safe_append='#{out}'.freeze;
|
34
|
+
@output_buffer.safe_append='#{out.gsub("'", "\\\\'")}'.freeze;
|
39
35
|
@output_buffer
|
40
36
|
STRING
|
41
37
|
end
|
data/lib/hotdocs/version.rb
CHANGED