docyard 0.2.0 → 0.4.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/CHANGELOG.md +42 -1
- data/LICENSE.vscode-icons +42 -0
- data/README.md +86 -23
- data/lib/docyard/asset_handler.rb +33 -0
- data/lib/docyard/build/asset_bundler.rb +139 -0
- data/lib/docyard/build/file_copier.rb +105 -0
- data/lib/docyard/build/sitemap_generator.rb +57 -0
- data/lib/docyard/build/static_generator.rb +141 -0
- data/lib/docyard/builder.rb +104 -0
- data/lib/docyard/cli.rb +19 -0
- data/lib/docyard/components/base_processor.rb +24 -0
- data/lib/docyard/components/callout_processor.rb +121 -0
- data/lib/docyard/components/code_block_processor.rb +55 -0
- data/lib/docyard/components/code_detector.rb +59 -0
- data/lib/docyard/components/icon_detector.rb +57 -0
- data/lib/docyard/components/icon_processor.rb +51 -0
- data/lib/docyard/components/registry.rb +34 -0
- data/lib/docyard/components/table_wrapper_processor.rb +18 -0
- data/lib/docyard/components/tabs_parser.rb +60 -0
- data/lib/docyard/components/tabs_processor.rb +44 -0
- data/lib/docyard/config/validator.rb +171 -0
- data/lib/docyard/config.rb +135 -0
- data/lib/docyard/constants.rb +5 -0
- data/lib/docyard/icons/LICENSE.phosphor +21 -0
- data/lib/docyard/icons/file_types.rb +92 -0
- data/lib/docyard/icons/phosphor.rb +64 -0
- data/lib/docyard/icons.rb +40 -0
- data/lib/docyard/initializer.rb +93 -9
- data/lib/docyard/language_mapping.rb +52 -0
- data/lib/docyard/markdown.rb +27 -3
- data/lib/docyard/preview_server.rb +72 -0
- data/lib/docyard/rack_application.rb +77 -8
- data/lib/docyard/renderer.rb +56 -9
- data/lib/docyard/server.rb +5 -2
- data/lib/docyard/sidebar/config_parser.rb +180 -0
- data/lib/docyard/sidebar/item.rb +58 -0
- data/lib/docyard/sidebar/renderer.rb +33 -6
- data/lib/docyard/sidebar_builder.rb +54 -2
- data/lib/docyard/templates/assets/css/code.css +150 -2
- data/lib/docyard/templates/assets/css/components/callout.css +169 -0
- data/lib/docyard/templates/assets/css/components/code-block.css +196 -0
- data/lib/docyard/templates/assets/css/components/icon.css +16 -0
- data/lib/docyard/templates/assets/css/components/logo.css +44 -0
- data/lib/docyard/templates/assets/css/{components.css → components/navigation.css} +111 -53
- data/lib/docyard/templates/assets/css/components/tabs.css +299 -0
- data/lib/docyard/templates/assets/css/components/theme-toggle.css +69 -0
- data/lib/docyard/templates/assets/css/layout.css +14 -4
- data/lib/docyard/templates/assets/css/markdown.css +27 -17
- data/lib/docyard/templates/assets/css/reset.css +4 -0
- data/lib/docyard/templates/assets/css/variables.css +94 -3
- data/lib/docyard/templates/assets/favicon.svg +16 -0
- data/lib/docyard/templates/assets/js/components/code-block.js +162 -0
- data/lib/docyard/templates/assets/js/components/navigation.js +221 -0
- data/lib/docyard/templates/assets/js/components/tabs.js +338 -0
- data/lib/docyard/templates/assets/js/theme.js +12 -179
- data/lib/docyard/templates/assets/logo-dark.svg +4 -0
- data/lib/docyard/templates/assets/logo.svg +12 -0
- data/lib/docyard/templates/config/docyard.yml.erb +42 -0
- data/lib/docyard/templates/layouts/default.html.erb +32 -4
- data/lib/docyard/templates/markdown/getting-started/installation.md.erb +46 -12
- data/lib/docyard/templates/markdown/guides/configuration.md.erb +202 -0
- data/lib/docyard/templates/markdown/guides/markdown-features.md.erb +247 -0
- data/lib/docyard/templates/markdown/index.md.erb +55 -59
- data/lib/docyard/templates/partials/_callout.html.erb +11 -0
- data/lib/docyard/templates/partials/_code_block.html.erb +6 -0
- data/lib/docyard/templates/partials/_icon.html.erb +1 -0
- data/lib/docyard/templates/partials/_icon_file_extension.html.erb +1 -0
- data/lib/docyard/templates/partials/_nav_group.html.erb +10 -4
- data/lib/docyard/templates/partials/_nav_leaf.html.erb +9 -1
- data/lib/docyard/templates/partials/_tabs.html.erb +40 -0
- data/lib/docyard/templates/partials/_theme_toggle.html.erb +13 -0
- data/lib/docyard/version.rb +1 -1
- data/lib/docyard.rb +8 -0
- metadata +91 -7
- data/lib/docyard/templates/markdown/core-concepts/file-structure.md.erb +0 -61
- data/lib/docyard/templates/markdown/core-concepts/markdown.md.erb +0 -90
- data/lib/docyard/templates/markdown/getting-started/introduction.md.erb +0 -30
- data/lib/docyard/templates/markdown/getting-started/quick-start.md.erb +0 -56
- data/lib/docyard/templates/partials/_icons.html.erb +0 -11
data/lib/docyard/server.rb
CHANGED
|
@@ -4,22 +4,25 @@ require "webrick"
|
|
|
4
4
|
require "stringio"
|
|
5
5
|
require_relative "file_watcher"
|
|
6
6
|
require_relative "rack_application"
|
|
7
|
+
require_relative "config"
|
|
7
8
|
|
|
8
9
|
module Docyard
|
|
9
10
|
class Server
|
|
10
11
|
DEFAULT_PORT = 4200
|
|
11
12
|
DEFAULT_HOST = "localhost"
|
|
12
13
|
|
|
13
|
-
attr_reader :port, :host, :docs_path
|
|
14
|
+
attr_reader :port, :host, :docs_path, :config
|
|
14
15
|
|
|
15
16
|
def initialize(port: DEFAULT_PORT, host: DEFAULT_HOST, docs_path: "docs")
|
|
16
17
|
@port = port
|
|
17
18
|
@host = host
|
|
18
19
|
@docs_path = docs_path
|
|
20
|
+
@config = Config.load
|
|
19
21
|
@file_watcher = FileWatcher.new(File.expand_path(docs_path))
|
|
20
22
|
@app = RackApplication.new(
|
|
21
23
|
docs_path: File.expand_path(docs_path),
|
|
22
|
-
file_watcher: @file_watcher
|
|
24
|
+
file_watcher: @file_watcher,
|
|
25
|
+
config: @config
|
|
23
26
|
)
|
|
24
27
|
end
|
|
25
28
|
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "item"
|
|
4
|
+
require_relative "title_extractor"
|
|
5
|
+
|
|
6
|
+
module Docyard
|
|
7
|
+
module Sidebar
|
|
8
|
+
class ConfigParser
|
|
9
|
+
attr_reader :config_items, :docs_path, :current_path, :title_extractor
|
|
10
|
+
|
|
11
|
+
def initialize(config_items, docs_path:, current_path: "/", title_extractor: TitleExtractor.new)
|
|
12
|
+
@config_items = config_items || []
|
|
13
|
+
@docs_path = docs_path
|
|
14
|
+
@current_path = Utils::PathResolver.normalize(current_path)
|
|
15
|
+
@title_extractor = title_extractor
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def parse
|
|
19
|
+
parse_items(config_items)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def parse_items(items, base_path = "")
|
|
25
|
+
items.map do |item_config|
|
|
26
|
+
parse_item(item_config, base_path)
|
|
27
|
+
end.compact
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def parse_item(item_config, base_path)
|
|
31
|
+
case item_config
|
|
32
|
+
when String
|
|
33
|
+
resolve_file_item(item_config, base_path)
|
|
34
|
+
when Hash
|
|
35
|
+
parse_hash_item(item_config, base_path)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def parse_hash_item(item_config, base_path)
|
|
40
|
+
return parse_link_item(item_config) if link_item?(item_config)
|
|
41
|
+
return parse_nested_item(item_config, base_path) if nested_item?(item_config)
|
|
42
|
+
return resolve_file_item(item_config.keys.first, base_path, {}) if nil_value_item?(item_config)
|
|
43
|
+
|
|
44
|
+
slug = item_config.keys.first
|
|
45
|
+
options = item_config.values.first || {}
|
|
46
|
+
resolve_file_item(slug, base_path, options)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def link_item?(config)
|
|
50
|
+
config.key?("link") || config.key?(:link)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def nested_item?(config)
|
|
54
|
+
config.size == 1 && config.values.first.is_a?(Hash)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def nil_value_item?(config)
|
|
58
|
+
config.size == 1 && config.values.first.nil?
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def parse_link_item(config)
|
|
62
|
+
link = config["link"] || config[:link]
|
|
63
|
+
text = config["text"] || config[:text]
|
|
64
|
+
icon = config["icon"] || config[:icon]
|
|
65
|
+
target = config["target"] || config[:target] || "_blank"
|
|
66
|
+
|
|
67
|
+
Item.new(
|
|
68
|
+
text: text,
|
|
69
|
+
link: link,
|
|
70
|
+
path: link,
|
|
71
|
+
icon: icon,
|
|
72
|
+
target: target,
|
|
73
|
+
type: :external
|
|
74
|
+
)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def parse_nested_item(item_config, base_path)
|
|
78
|
+
slug = item_config.keys.first.to_s
|
|
79
|
+
options = item_config.values.first || {}
|
|
80
|
+
nested_items = extract_nested_items(options)
|
|
81
|
+
|
|
82
|
+
dir_path = File.join(docs_path, base_path, slug)
|
|
83
|
+
|
|
84
|
+
if File.directory?(dir_path)
|
|
85
|
+
build_directory_item(slug, options, nested_items, base_path)
|
|
86
|
+
elsif nested_items.any?
|
|
87
|
+
build_file_with_children_item(slug, options, nested_items, base_path)
|
|
88
|
+
else
|
|
89
|
+
resolve_file_item(slug, base_path, options)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def extract_nested_items(options)
|
|
94
|
+
options["items"] || options[:items] || []
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def extract_common_options(options)
|
|
98
|
+
{
|
|
99
|
+
text: options["text"] || options[:text],
|
|
100
|
+
icon: options["icon"] || options[:icon],
|
|
101
|
+
collapsed: options["collapsed"] || options[:collapsed] || false
|
|
102
|
+
}
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def build_directory_item(slug, options, nested_items, base_path)
|
|
106
|
+
common_opts = extract_common_options(options)
|
|
107
|
+
new_base_path = File.join(base_path, slug)
|
|
108
|
+
parsed_items = parse_items(nested_items, new_base_path)
|
|
109
|
+
|
|
110
|
+
Item.new(
|
|
111
|
+
slug: slug,
|
|
112
|
+
text: common_opts[:text] || Utils::TextFormatter.titleize(slug),
|
|
113
|
+
icon: common_opts[:icon],
|
|
114
|
+
collapsed: common_opts[:collapsed],
|
|
115
|
+
items: parsed_items,
|
|
116
|
+
type: :directory
|
|
117
|
+
)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def build_file_with_children_item(slug, options, nested_items, base_path)
|
|
121
|
+
common_opts = extract_common_options(options)
|
|
122
|
+
file_path = File.join(docs_path, base_path, "#{slug}.md")
|
|
123
|
+
url_path = Utils::PathResolver.to_url(File.join(base_path, slug))
|
|
124
|
+
resolved_text = common_opts[:text] || extract_file_title(file_path, slug)
|
|
125
|
+
|
|
126
|
+
Item.new(
|
|
127
|
+
slug: slug,
|
|
128
|
+
text: resolved_text,
|
|
129
|
+
path: url_path,
|
|
130
|
+
icon: common_opts[:icon],
|
|
131
|
+
collapsed: common_opts[:collapsed],
|
|
132
|
+
items: parse_items(nested_items, base_path),
|
|
133
|
+
active: current_path == url_path,
|
|
134
|
+
type: :file
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def extract_file_title(file_path, slug)
|
|
139
|
+
File.exist?(file_path) ? title_extractor.extract(file_path) : Utils::TextFormatter.titleize(slug)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def resolve_file_item(slug, base_path, options = {})
|
|
143
|
+
slug_str = slug.to_s
|
|
144
|
+
options ||= {}
|
|
145
|
+
|
|
146
|
+
file_path = File.join(docs_path, base_path, "#{slug_str}.md")
|
|
147
|
+
url_path = Utils::PathResolver.to_url(File.join(base_path, slug_str))
|
|
148
|
+
|
|
149
|
+
frontmatter = extract_frontmatter_metadata(file_path)
|
|
150
|
+
text = resolve_item_text(slug_str, file_path, options, frontmatter[:text])
|
|
151
|
+
icon = resolve_item_icon(options, frontmatter[:icon])
|
|
152
|
+
final_path = options["link"] || options[:link] || url_path
|
|
153
|
+
|
|
154
|
+
Item.new(
|
|
155
|
+
slug: slug_str, text: text, path: final_path, icon: icon,
|
|
156
|
+
active: current_path == final_path, type: :file
|
|
157
|
+
)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def extract_frontmatter_metadata(file_path)
|
|
161
|
+
return { text: nil, icon: nil } unless File.exist?(file_path)
|
|
162
|
+
|
|
163
|
+
markdown = Markdown.new(File.read(file_path))
|
|
164
|
+
{
|
|
165
|
+
text: markdown.sidebar_text || markdown.title,
|
|
166
|
+
icon: markdown.sidebar_icon
|
|
167
|
+
}
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def resolve_item_text(slug, file_path, options, frontmatter_text)
|
|
171
|
+
text = options["text"] || options[:text] || frontmatter_text
|
|
172
|
+
text || extract_file_title(file_path, slug)
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def resolve_item_icon(options, frontmatter_icon)
|
|
176
|
+
options["icon"] || options[:icon] || frontmatter_icon
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Docyard
|
|
4
|
+
module Sidebar
|
|
5
|
+
class Item
|
|
6
|
+
attr_reader :slug, :text, :icon, :link, :target, :collapsed, :items, :path, :active, :type
|
|
7
|
+
|
|
8
|
+
def initialize(**options)
|
|
9
|
+
@slug = options[:slug]
|
|
10
|
+
@text = options[:text]
|
|
11
|
+
@icon = options[:icon]
|
|
12
|
+
@link = options[:link]
|
|
13
|
+
@target = options[:target] || "_self"
|
|
14
|
+
@collapsed = options[:collapsed] || false
|
|
15
|
+
@items = options[:items] || []
|
|
16
|
+
@path = options[:path] || options[:link]
|
|
17
|
+
@active = options[:active] || false
|
|
18
|
+
@type = options[:type] || :file
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def external?
|
|
22
|
+
return false if path.nil?
|
|
23
|
+
|
|
24
|
+
path.start_with?("http://", "https://")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def children?
|
|
28
|
+
items.any?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def title
|
|
32
|
+
text
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def children
|
|
36
|
+
items
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def collapsible?
|
|
40
|
+
children?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def to_h
|
|
44
|
+
{
|
|
45
|
+
title: title,
|
|
46
|
+
path: path,
|
|
47
|
+
icon: icon,
|
|
48
|
+
active: active,
|
|
49
|
+
type: type,
|
|
50
|
+
collapsed: collapsed,
|
|
51
|
+
collapsible: collapsible?,
|
|
52
|
+
target: target,
|
|
53
|
+
children: children.map(&:to_h)
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -7,10 +7,11 @@ module Docyard
|
|
|
7
7
|
class Renderer
|
|
8
8
|
PARTIALS_PATH = File.join(__dir__, "../templates/partials")
|
|
9
9
|
|
|
10
|
-
attr_reader :site_title
|
|
10
|
+
attr_reader :site_title, :base_url
|
|
11
11
|
|
|
12
|
-
def initialize(site_title: "Documentation")
|
|
12
|
+
def initialize(site_title: "Documentation", base_url: "/")
|
|
13
13
|
@site_title = site_title
|
|
14
|
+
@base_url = normalize_base_url(base_url)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def render(tree)
|
|
@@ -34,8 +35,21 @@ module Docyard
|
|
|
34
35
|
ERB.new(template).result(erb_binding)
|
|
35
36
|
end
|
|
36
37
|
|
|
37
|
-
def icon(name)
|
|
38
|
-
|
|
38
|
+
def icon(name, weight = "regular")
|
|
39
|
+
Icons.render(name.to_s.tr("_", "-"), weight) || ""
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def link_path(path)
|
|
43
|
+
return path if path.nil? || path.start_with?("http://", "https://")
|
|
44
|
+
|
|
45
|
+
"#{base_url.chomp('/')}#{path}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def normalize_base_url(url)
|
|
49
|
+
return "/" if url.nil? || url.empty?
|
|
50
|
+
|
|
51
|
+
url = "/#{url}" unless url.start_with?("/")
|
|
52
|
+
url.end_with?("/") ? url : "#{url}/"
|
|
39
53
|
end
|
|
40
54
|
|
|
41
55
|
def render_tree_with_sections(items)
|
|
@@ -98,12 +112,25 @@ module Docyard
|
|
|
98
112
|
end
|
|
99
113
|
|
|
100
114
|
def render_leaf_item(item)
|
|
101
|
-
render_partial(
|
|
115
|
+
render_partial(
|
|
116
|
+
:nav_leaf,
|
|
117
|
+
path: item[:path],
|
|
118
|
+
title: item[:title],
|
|
119
|
+
active: item[:active],
|
|
120
|
+
icon: item[:icon],
|
|
121
|
+
target: item[:target]
|
|
122
|
+
)
|
|
102
123
|
end
|
|
103
124
|
|
|
104
125
|
def render_group_item(item)
|
|
105
126
|
children_html = render_tree(item[:children])
|
|
106
|
-
render_partial(
|
|
127
|
+
render_partial(
|
|
128
|
+
:nav_group,
|
|
129
|
+
title: item[:title],
|
|
130
|
+
children_html: children_html,
|
|
131
|
+
icon: item[:icon],
|
|
132
|
+
collapsed: item[:collapsed]
|
|
133
|
+
)
|
|
107
134
|
end
|
|
108
135
|
end
|
|
109
136
|
end
|
|
@@ -4,12 +4,13 @@ require_relative "sidebar/file_system_scanner"
|
|
|
4
4
|
require_relative "sidebar/title_extractor"
|
|
5
5
|
require_relative "sidebar/tree_builder"
|
|
6
6
|
require_relative "sidebar/renderer"
|
|
7
|
+
require_relative "sidebar/config_parser"
|
|
7
8
|
|
|
8
9
|
module Docyard
|
|
9
10
|
class SidebarBuilder
|
|
10
11
|
attr_reader :docs_path, :current_path, :config
|
|
11
12
|
|
|
12
|
-
def initialize(docs_path:, current_path: "/", config:
|
|
13
|
+
def initialize(docs_path:, current_path: "/", config: nil)
|
|
13
14
|
@docs_path = docs_path
|
|
14
15
|
@current_path = current_path
|
|
15
16
|
@config = config
|
|
@@ -26,10 +27,44 @@ module Docyard
|
|
|
26
27
|
private
|
|
27
28
|
|
|
28
29
|
def build_tree
|
|
30
|
+
if config_sidebar_items?
|
|
31
|
+
build_tree_from_config
|
|
32
|
+
else
|
|
33
|
+
build_tree_from_filesystem
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def build_tree_from_config
|
|
38
|
+
config_parser.parse.map(&:to_h)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def build_tree_from_filesystem
|
|
29
42
|
file_items = scanner.scan
|
|
30
43
|
tree_builder.build(file_items)
|
|
31
44
|
end
|
|
32
45
|
|
|
46
|
+
def config_sidebar_items?
|
|
47
|
+
config_sidebar_items&.any?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def config_sidebar_items
|
|
51
|
+
return [] unless config
|
|
52
|
+
|
|
53
|
+
if config.is_a?(Hash)
|
|
54
|
+
config.dig("sidebar", "items") || config.dig(:sidebar, :items) || []
|
|
55
|
+
else
|
|
56
|
+
config.sidebar&.items || []
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def config_parser
|
|
61
|
+
@config_parser ||= Sidebar::ConfigParser.new(
|
|
62
|
+
config_sidebar_items,
|
|
63
|
+
docs_path: docs_path,
|
|
64
|
+
current_path: current_path
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
|
|
33
68
|
def scanner
|
|
34
69
|
@scanner ||= Sidebar::FileSystemScanner.new(docs_path)
|
|
35
70
|
end
|
|
@@ -43,8 +78,25 @@ module Docyard
|
|
|
43
78
|
|
|
44
79
|
def renderer
|
|
45
80
|
@renderer ||= Sidebar::Renderer.new(
|
|
46
|
-
site_title:
|
|
81
|
+
site_title: extract_site_title,
|
|
82
|
+
base_url: extract_base_url
|
|
47
83
|
)
|
|
48
84
|
end
|
|
85
|
+
|
|
86
|
+
def extract_base_url
|
|
87
|
+
if config.is_a?(Hash)
|
|
88
|
+
config.dig(:build, :base_url) || "/"
|
|
89
|
+
else
|
|
90
|
+
config&.build&.base_url || "/"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def extract_site_title
|
|
95
|
+
if config.is_a?(Hash)
|
|
96
|
+
config[:site_title] || "Documentation"
|
|
97
|
+
else
|
|
98
|
+
config&.site&.title || "Documentation"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
49
101
|
end
|
|
50
102
|
end
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
.highlight table td {
|
|
38
|
-
padding:
|
|
38
|
+
padding: 0.3125rem;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
.highlight table pre {
|
|
@@ -196,7 +196,7 @@
|
|
|
196
196
|
|
|
197
197
|
/* Code block scrollbar */
|
|
198
198
|
.content pre::-webkit-scrollbar {
|
|
199
|
-
height:
|
|
199
|
+
height: 0.5rem;
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
.content pre::-webkit-scrollbar-track {
|
|
@@ -212,3 +212,151 @@
|
|
|
212
212
|
.content pre::-webkit-scrollbar-thumb:hover {
|
|
213
213
|
background: var(--color-text-tertiary);
|
|
214
214
|
}
|
|
215
|
+
|
|
216
|
+
/* Dark Mode Syntax Highlighting - GitHub Dark */
|
|
217
|
+
.dark .highlight,
|
|
218
|
+
.dark .highlight .w {
|
|
219
|
+
color: #e6edf3;
|
|
220
|
+
background-color: #161b22;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/* Keywords */
|
|
224
|
+
.dark .highlight .k,
|
|
225
|
+
.dark .highlight .kd,
|
|
226
|
+
.dark .highlight .kn,
|
|
227
|
+
.dark .highlight .kp,
|
|
228
|
+
.dark .highlight .kr,
|
|
229
|
+
.dark .highlight .kt,
|
|
230
|
+
.dark .highlight .kv {
|
|
231
|
+
color: #ff7b72;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.dark .highlight .gr {
|
|
235
|
+
color: #161b22;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.dark .highlight .gd {
|
|
239
|
+
color: #ffa198;
|
|
240
|
+
background-color: #490202;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Built-in names */
|
|
244
|
+
.dark .highlight .nb,
|
|
245
|
+
.dark .highlight .nc,
|
|
246
|
+
.dark .highlight .no,
|
|
247
|
+
.dark .highlight .nn {
|
|
248
|
+
color: #ffa657;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/* Strings and regex */
|
|
252
|
+
.dark .highlight .sr,
|
|
253
|
+
.dark .highlight .na,
|
|
254
|
+
.dark .highlight .nt {
|
|
255
|
+
color: #7ee787;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
.dark .highlight .gi {
|
|
259
|
+
color: #7ee787;
|
|
260
|
+
background-color: #0f3b17;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* Constants and literals */
|
|
264
|
+
.dark .highlight .kc,
|
|
265
|
+
.dark .highlight .l,
|
|
266
|
+
.dark .highlight .ld,
|
|
267
|
+
.dark .highlight .m,
|
|
268
|
+
.dark .highlight .mb,
|
|
269
|
+
.dark .highlight .mf,
|
|
270
|
+
.dark .highlight .mh,
|
|
271
|
+
.dark .highlight .mi,
|
|
272
|
+
.dark .highlight .il,
|
|
273
|
+
.dark .highlight .mo,
|
|
274
|
+
.dark .highlight .mx,
|
|
275
|
+
.dark .highlight .sb,
|
|
276
|
+
.dark .highlight .bp,
|
|
277
|
+
.dark .highlight .ne,
|
|
278
|
+
.dark .highlight .nl,
|
|
279
|
+
.dark .highlight .py {
|
|
280
|
+
color: #79c0ff;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/* Variables */
|
|
284
|
+
.dark .highlight .nv,
|
|
285
|
+
.dark .highlight .vc,
|
|
286
|
+
.dark .highlight .vg,
|
|
287
|
+
.dark .highlight .vi,
|
|
288
|
+
.dark .highlight .vm {
|
|
289
|
+
color: #79c0ff;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/* Operators */
|
|
293
|
+
.dark .highlight .o,
|
|
294
|
+
.dark .highlight .ow {
|
|
295
|
+
color: #79c0ff;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/* Headers and subheaders in diffs */
|
|
299
|
+
.dark .highlight .gh,
|
|
300
|
+
.dark .highlight .gu {
|
|
301
|
+
color: #79c0ff;
|
|
302
|
+
font-weight: bold;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* Strings */
|
|
306
|
+
.dark .highlight .s,
|
|
307
|
+
.dark .highlight .sa,
|
|
308
|
+
.dark .highlight .sc,
|
|
309
|
+
.dark .highlight .dl,
|
|
310
|
+
.dark .highlight .sd,
|
|
311
|
+
.dark .highlight .s2,
|
|
312
|
+
.dark .highlight .se,
|
|
313
|
+
.dark .highlight .sh,
|
|
314
|
+
.dark .highlight .sx,
|
|
315
|
+
.dark .highlight .s1,
|
|
316
|
+
.dark .highlight .ss {
|
|
317
|
+
color: #a5d6ff;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/* Decorators and functions */
|
|
321
|
+
.dark .highlight .nd,
|
|
322
|
+
.dark .highlight .nf,
|
|
323
|
+
.dark .highlight .fm {
|
|
324
|
+
color: #d2a8ff;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/* Errors */
|
|
328
|
+
.dark .highlight .err {
|
|
329
|
+
color: #161b22;
|
|
330
|
+
background-color: #ffa198;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/* Comments */
|
|
334
|
+
.dark .highlight .c,
|
|
335
|
+
.dark .highlight .ch,
|
|
336
|
+
.dark .highlight .cd,
|
|
337
|
+
.dark .highlight .cm,
|
|
338
|
+
.dark .highlight .cp,
|
|
339
|
+
.dark .highlight .cpf,
|
|
340
|
+
.dark .highlight .c1,
|
|
341
|
+
.dark .highlight .cs,
|
|
342
|
+
.dark .highlight .gl,
|
|
343
|
+
.dark .highlight .gt {
|
|
344
|
+
color: #8b949e;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/* Name indicators */
|
|
348
|
+
.dark .highlight .ni,
|
|
349
|
+
.dark .highlight .si {
|
|
350
|
+
color: #e6edf3;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/* Generic emphasis */
|
|
354
|
+
.dark .highlight .ge {
|
|
355
|
+
color: #e6edf3;
|
|
356
|
+
font-style: italic;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.dark .highlight .gs {
|
|
360
|
+
color: #e6edf3;
|
|
361
|
+
font-weight: bold;
|
|
362
|
+
}
|