Skip to content

Commit b94c021

Browse files
committed
Add new theme 'Aliki'
1 parent 8c2be4e commit b94c021

27 files changed

+2933
-0
lines changed

lib/rdoc/generator.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ module RDoc::Generator
4343

4444
autoload :Markup, "#{__dir__}/generator/markup"
4545

46+
autoload :Aliki, "#{__dir__}/generator/aliki"
4647
autoload :Darkfish, "#{__dir__}/generator/darkfish"
4748
autoload :JsonIndex, "#{__dir__}/generator/json_index"
4849
autoload :RI, "#{__dir__}/generator/ri"

lib/rdoc/generator/aliki.rb

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# frozen_string_literal: true
2+
3+
##
4+
# Aliki RDoc HTML Generator - A modern documentation theme
5+
#
6+
# Based on Darkfish by Michael Granger ([email protected])
7+
#
8+
# == Description
9+
#
10+
# Aliki brings modern design patterns to RDoc documentation with:
11+
#
12+
# * Three-column responsive layout (navigation, content, table of contents)
13+
# * Dark mode support with theme toggle and localStorage persistence
14+
# * Auto-generated right sidebar TOC with scroll spy (Intersection Observer)
15+
# * Mobile-optimized search modal with keyboard shortcuts
16+
# * Enhanced syntax highlighting for light and dark themes
17+
# * Responsive design with mobile navigation
18+
# * Zero additional JavaScript dependencies
19+
# * Modern CSS Grid and Flexbox layout
20+
#
21+
# == Usage
22+
#
23+
# rdoc --format=aliki --op=doc/
24+
#
25+
# == Author
26+
#
27+
# Based on Darkfish by Michael Granger
28+
# Modernized as Aliki theme by Stan Lo
29+
#
30+
31+
class RDoc::Generator::Aliki < RDoc::Generator::Darkfish
32+
33+
RDoc::RDoc.add_generator self
34+
35+
##
36+
# Version of the Aliki generator
37+
38+
VERSION = '1'
39+
40+
##
41+
# Description of this generator
42+
43+
DESCRIPTION = 'Modern HTML generator based on Darkfish'
44+
45+
##
46+
# Initialize the Aliki generator with the aliki template directory
47+
48+
def initialize(store, options)
49+
super
50+
aliki_template_dir = File.expand_path(File.join(__dir__, 'template', 'aliki'))
51+
@template_dir = Pathname.new(aliki_template_dir)
52+
end
53+
54+
##
55+
# Copy only the static assets required by the Aliki theme. Unlike Darkfish we
56+
# don't ship embedded fonts or image sprites, so limit the asset list to keep
57+
# generated documentation lightweight.
58+
59+
def write_style_sheet
60+
debug_msg "Copying Aliki static files"
61+
options = { verbose: $DEBUG_RDOC, noop: @dry_run }
62+
63+
install_rdoc_static_file @template_dir + 'css/rdoc.css', "./css/rdoc.css", options
64+
65+
unless @options.template_stylesheets.empty?
66+
FileUtils.cp @options.template_stylesheets, '.', **options
67+
end
68+
69+
Dir[(@template_dir + 'js/**/*').to_s].each do |path|
70+
next if File.directory?(path)
71+
next if File.basename(path).start_with?('.')
72+
73+
dst = Pathname.new(path).relative_path_from(@template_dir)
74+
75+
install_rdoc_static_file @template_dir + path, dst, options
76+
end
77+
end
78+
end

lib/rdoc/generator/template/aliki/.document

Whitespace-only changes.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<aside class="table-of-contents" role="complementary" aria-label="Table of Contents">
2+
<div class="toc-sticky">
3+
<h3 class="toc-heading">On This Page</h3>
4+
<nav class="toc-nav" id="toc-nav" aria-label="Page sections">
5+
<!-- Generated by JavaScript based on page headings -->
6+
</nav>
7+
</div>
8+
</aside>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<footer class="site-footer">
2+
<div class="footer-content">
3+
<div>
4+
<h3>Documentation</h3>
5+
<ul>
6+
<li><a href="<%= h asset_rel_path %>/index.html">Home</a></li>
7+
</ul>
8+
</div>
9+
10+
<div>
11+
<h3>Resources</h3>
12+
<ul>
13+
<li><a href="https://ruby.github.io/rdoc/">RDoc Documentation</a></li>
14+
<li><a href="https://github.com/ruby/rdoc">RDoc GitHub</a></li>
15+
</ul>
16+
</div>
17+
</div>
18+
19+
<div class="footer-bottom">
20+
<p>
21+
Generated by <a href="https://ruby.github.io/rdoc/">RDoc <%= RDoc::VERSION %></a>
22+
using the Aliki theme by <a href="http://st0012.dev">Stan Lo</a>
23+
</p>
24+
</div>
25+
</footer>
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<meta charset="<%= @options.charset %>">
2+
<meta name="viewport" content="width=device-width, initial-scale=1">
3+
4+
<title><%= h @title %></title>
5+
6+
<%- if defined?(klass) %>
7+
<meta name="keywords" content="ruby,<%= h "#{klass.type},#{klass.full_name}" %>">
8+
9+
<%- if klass.comment.empty? %>
10+
<meta name="description" content="Documentation for the <%= h "#{klass.full_name} #{klass.type}" %>">
11+
<%- else %>
12+
<meta name="description" content="<%= h "#{klass.type} #{klass.full_name}: #{excerpt(klass.comment)}" %>">
13+
<%- end %>
14+
<%- elsif defined?(file) %>
15+
<meta name="keywords" content="ruby,documentation,<%= h file.page_name %>">
16+
<meta name="description" content="<%= h "#{file.page_name}: #{excerpt(file.comment)}" %>">
17+
<%- elsif @title %>
18+
<meta name="keywords" content="ruby,documentation,<%= h @title %>">
19+
20+
<%- if @options.main_page and
21+
main_page = @files.find { |f| f.full_name == @options.main_page } then %>
22+
<meta name="description" content="<%= h "#{@title}: #{excerpt(main_page.comment)}" %>">
23+
<%- else %>
24+
<meta name="description" content="Documentation for <%= h @title %>">
25+
<%- end %>
26+
<%- end %>
27+
28+
<%- if canonical_url = @options.canonical_root %>
29+
<% canonical_url = current.canonical_url if defined?(current) %>
30+
<link rel="canonical" href="<%= canonical_url %>">
31+
<%- end %>
32+
33+
<!-- Open Graph / Facebook -->
34+
<meta property="og:type" content="website">
35+
<meta property="og:title" content="<%= h @title %>">
36+
<%- if defined?(klass) %>
37+
<%- if klass.comment.empty? %>
38+
<meta property="og:description" content="Documentation for <%= h klass.full_name %> <%= h klass.type %> - API reference and code examples">
39+
<%- else %>
40+
<meta property="og:description" content="<%= h excerpt(klass.comment) %>">
41+
<%- end %>
42+
<%- elsif defined?(file) %>
43+
<%- if file.comment.empty? %>
44+
<meta property="og:description" content="<%= h file.page_name %> - <%= h @title %> documentation">
45+
<%- else %>
46+
<meta property="og:description" content="<%= h excerpt(file.comment) %>">
47+
<%- end %>
48+
<%- else %>
49+
<meta property="og:description" content="API documentation for <%= h @title %> - Browse classes, modules, and methods">
50+
<%- end %>
51+
<%- if canonical_url = @options.canonical_root %>
52+
<% canonical_url = current.canonical_url if defined?(current) %>
53+
<meta property="og:url" content="<%= canonical_url %>">
54+
<%- end %>
55+
56+
<!-- Twitter -->
57+
<meta name="twitter:card" content="summary">
58+
<meta name="twitter:title" content="<%= h @title %>">
59+
<%- if defined?(klass) %>
60+
<%- if klass.comment.empty? %>
61+
<meta name="twitter:description" content="Documentation for <%= h klass.full_name %> <%= h klass.type %> - API reference and code examples">
62+
<%- else %>
63+
<meta name="twitter:description" content="<%= h excerpt(klass.comment) %>">
64+
<%- end %>
65+
<%- elsif defined?(file) %>
66+
<%- if file.comment.empty? %>
67+
<meta name="twitter:description" content="<%= h file.page_name %> - <%= h @title %> documentation">
68+
<%- else %>
69+
<meta name="twitter:description" content="<%= h excerpt(file.comment) %>">
70+
<%- end %>
71+
<%- else %>
72+
<meta name="twitter:description" content="API documentation for <%= h @title %> - Browse classes, modules, and methods">
73+
<%- end %>
74+
75+
<script type="text/javascript">
76+
var rdoc_rel_prefix = "<%= h asset_rel_prefix %>/";
77+
var index_rel_prefix = "<%= h rel_prefix %>/";
78+
</script>
79+
80+
<script src="<%= h asset_rel_prefix %>/js/theme-toggle.js"></script>
81+
<script src="<%= h asset_rel_prefix %>/js/navigation.js" defer></script>
82+
<script src="<%= h asset_rel_prefix %>/js/search.js" defer></script>
83+
<script src="<%= h asset_rel_prefix %>/js/search_index.js" defer></script>
84+
<script src="<%= h asset_rel_prefix %>/js/searcher.js" defer></script>
85+
<script src="<%= h asset_rel_prefix %>/js/aliki.js" defer></script>
86+
87+
<link href="<%= h asset_rel_prefix %>/css/rdoc.css" rel="stylesheet">
88+
<%- @options.template_stylesheets.each do |stylesheet| %>
89+
<link href="<%= h asset_rel_prefix %>/<%= File.basename stylesheet %>" rel="stylesheet">
90+
<%- end %>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<header class="top-navbar">
2+
<a href="<%= rel_prefix %>/index.html" class="navbar-brand">
3+
<%= h @options.title %>
4+
</a>
5+
6+
<!-- Desktop search bar -->
7+
<div class="navbar-search navbar-search-desktop" role="search">
8+
<form action="#" method="get" accept-charset="utf-8">
9+
<input id="search-field" role="combobox" aria-label="Search"
10+
aria-autocomplete="list" aria-controls="search-results"
11+
type="text" name="search" placeholder="Search (/) for a class, method..."
12+
spellcheck="false" title="Type to search, Up and Down to navigate, Enter to load">
13+
<ul id="search-results" aria-label="Search Results"
14+
aria-busy="false" aria-expanded="false"
15+
aria-atomic="false" class="initially-hidden"></ul>
16+
</form>
17+
</div>
18+
19+
<!-- Mobile search icon button -->
20+
<button id="search-toggle" class="navbar-search-mobile" aria-label="Open search" type="button">
21+
<span aria-hidden="true">🔍</span>
22+
</button>
23+
24+
<!-- Theme toggle button -->
25+
<button id="theme-toggle" class="theme-toggle" aria-label="Switch to dark mode" type="button">
26+
<span class="theme-toggle-icon" aria-hidden="true">🌙</span>
27+
</button>
28+
</header>
29+
30+
<!-- Search Modal (Mobile) -->
31+
<div id="search-modal" class="search-modal" hidden aria-modal="true" role="dialog" aria-label="Search">
32+
<div class="search-modal-backdrop"></div>
33+
<div class="search-modal-content">
34+
<div class="search-modal-header">
35+
<form class="search-modal-form" action="#" method="get" accept-charset="utf-8">
36+
<span class="search-modal-icon" aria-hidden="true">🔍</span>
37+
<input id="search-field-mobile" role="combobox" aria-label="Search"
38+
aria-autocomplete="list" aria-controls="search-results-mobile"
39+
type="text" name="search" placeholder="Search documentation"
40+
spellcheck="false" autocomplete="off">
41+
<button type="button" class="search-modal-close" aria-label="Close search" id="search-modal-close">
42+
<span aria-hidden="true">esc</span>
43+
</button>
44+
</form>
45+
</div>
46+
<div class="search-modal-body">
47+
<ul id="search-results-mobile" aria-label="Search Results"
48+
aria-busy="false" aria-expanded="false"
49+
aria-atomic="false" class="search-modal-results initially-hidden"></ul>
50+
<div class="search-modal-empty">
51+
<p>No recent searches</p>
52+
</div>
53+
</div>
54+
</div>
55+
</div>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<%- if klass.type == 'class' && (ancestors = klass.super_classes).any? %>
2+
<div id="parent-class-section" class="nav-section">
3+
<h3>Ancestors</h3>
4+
<%= generate_ancestor_list(ancestors, klass) %>
5+
</div>
6+
<%- end %>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<div id="classindex-section" class="nav-section">
2+
<h3>Class and Module Index</h3>
3+
4+
<%= generate_class_index_content(@classes, rel_prefix) %>
5+
</div>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<%- unless klass.extends.empty? then %>
2+
<div id="extends-section" class="nav-section">
3+
<h3>Extended With Modules</h3>
4+
5+
<ul class="link-list">
6+
<%- klass.extends.each do |ext| %>
7+
<%- unless String === ext.module then %>
8+
<li><a class="extend" href="<%= klass.aref_to ext.module.path %>"><%= ext.module.full_name %></a></li>
9+
<%- else %>
10+
<li><span class="extend"><%= ext.name %></span></li>
11+
<%- end %>
12+
<%- end %>
13+
</ul>
14+
</div>
15+
<%- end %>

0 commit comments

Comments
 (0)