Skip to content

Commit 74cfc89

Browse files
committed
Change the default theme to Aliki
1 parent 14dd4eb commit 74cfc89

File tree

12 files changed

+302
-27
lines changed

12 files changed

+302
-27
lines changed

.rdoc_options

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ main_page: README.md
44
autolink_excluded_words:
55
- RDoc
66

7-
generator_name: aliki
8-
97
exclude:
108
- AGENTS.md
119
- CLAUDE.md

AGENTS.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,13 @@ lib/rdoc/
146146
│ ├── prism_ruby.rb # Prism-based Ruby parser
147147
│ └── ...
148148
├── generator/ # Documentation generators
149-
│ ├── darkfish.rb # HTML generator (default theme)
149+
│ ├── aliki.rb # HTML generator (default theme)
150+
│ ├── darkfish.rb # HTML generator (deprecated, will be removed in v8.0)
150151
│ ├── markup.rb # Markup format generator
151152
│ ├── ri.rb # RI command generator
152-
│ └── template/darkfish/ # ERB templates (.rhtml files)
153+
│ └── template/ # ERB templates (.rhtml files)
154+
│ ├── aliki/ # Aliki theme (default)
155+
│ └── darkfish/ # Darkfish theme (deprecated)
153156
├── markup/ # Markup parsing and formatting
154157
├── code_object/ # AST objects for documented items
155158
├── markdown/ # Markdown parsing
@@ -196,7 +199,7 @@ exe/
196199
### Pluggable System
197200

198201
- **Parsers:** Ruby, C, Markdown, RD, Prism-based Ruby (experimental)
199-
- **Generators:** HTML/Darkfish, RI, POT (gettext), JSON, Markup
202+
- **Generators:** HTML/Aliki (default), HTML/Darkfish (deprecated), RI, POT (gettext), JSON, Markup
200203

201204
## Common Workflows
202205

CONTRIBUTING.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ bundle exec rake coverage
136136

137137
RDoc ships with two HTML themes:
138138

139-
- **Aliki** - Modern theme with improved styling and navigation (will become the default)
140-
- **Darkfish** - Classic theme (entering maintenance mode)
139+
- **Aliki** (default) - Modern theme with improved styling and navigation
140+
- **Darkfish** (deprecated) - Classic theme, will be removed in v8.0
141141

142142
New feature development should focus on the Aliki theme. Darkfish will continue to receive bug fixes but no new features.
143143

@@ -156,12 +156,13 @@ lib/rdoc/
156156
│ ├── prism_ruby.rb # Prism-based Ruby parser
157157
│ └── ...
158158
├── generator/ # Documentation generators
159-
│ ├── darkfish.rb # HTML generator (default theme)
159+
│ ├── aliki.rb # HTML generator (default theme)
160+
│ ├── darkfish.rb # HTML generator (deprecated, will be removed in v8.0)
160161
│ ├── markup.rb # Markup format generator
161162
│ ├── ri.rb # RI command generator
162163
│ └── template/ # ERB templates
163-
│ ├── darkfish/ # Darkfish theme (maintenance mode)
164-
│ └── aliki/ # Aliki theme (active development)
164+
│ ├── aliki/ # Aliki theme (default)
165+
│ └── darkfish/ # Darkfish theme (deprecated)
165166
├── markup/ # Markup parsing and formatting
166167
├── code_object/ # AST objects for documented items
167168
├── markdown.kpeg # Parser source (edit this)

LEGAL.rdoc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44

55
The files in this distribution are covered by the Ruby license (see LICENSE) except the features mentioned below:
66

7+
Aliki::
8+
Aliki was written by Stan Lo and is included under the MIT license.
9+
10+
* lib/rdoc/generator/aliki.rb
11+
* lib/rdoc/generator/template/aliki/*
12+
713
Darkfish::
814
Darkfish was written by Michael Granger and is included under the BSD 3-Clause
915
license. Darkfish contains images from the Silk Icons set by Mark James.

README.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ require 'rdoc/rdoc'
4848

4949
options = RDoc::Options.new
5050
options.files = ['a.rb', 'b.rb']
51-
options.setup_generator 'darkfish'
51+
options.setup_generator 'aliki'
5252
# see RDoc::Options
5353

5454
rdoc = RDoc::RDoc.new
@@ -90,7 +90,24 @@ To determine how well your project is documented run `rdoc -C lib` to get a docu
9090

9191
## Theme Options
9292

93-
There are a few community-maintained themes for RDoc:
93+
RDoc ships with two built-in themes:
94+
95+
- **Aliki** (default) - A modern, clean theme with improved navigation and search
96+
- **Darkfish** (deprecated) - The classic theme, will be removed in v8.0
97+
98+
To use the Darkfish theme instead of the default Aliki theme:
99+
100+
```shell
101+
rdoc --format darkfish
102+
```
103+
104+
Or in your `.rdoc_options` file:
105+
106+
```yaml
107+
generator_name: darkfish
108+
```
109+
110+
There are also a few community-maintained themes for RDoc:
94111
95112
- [rorvswild-theme-rdoc](https://github.com/BaseSecrete/rorvswild-theme-rdoc)
96113
- [hanna](https://github.com/jeremyevans/hanna) (a fork maintained by [Jeremy Evans](https://github.com/jeremyevans))

lib/rdoc/options.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ def init_ivars # :nodoc:
411411
@files = nil
412412
@force_output = false
413413
@force_update = true
414-
@generator_name = "darkfish"
414+
@generator_name = "aliki"
415415
@generators = RDoc::RDoc::GENERATORS
416416
@generator_options = []
417417
@hyperlink_all = false

lib/rdoc/rubygems_hook.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ def delete_legacy_args(args)
118118
end
119119

120120
##
121-
# Generates documentation using the named +generator+ ("darkfish" or "ri")
121+
# Generates documentation using the named +generator+ ("aliki" or "ri")
122122
# and following the given +options+.
123123
#
124124
# Documentation will be generated into +destination+
@@ -190,7 +190,7 @@ def generate
190190

191191
Dir.chdir @spec.full_gem_path do
192192
# RDoc::Options#finish must be called before parse_files.
193-
# RDoc::Options#finish is also called after ri/darkfish generator setup.
193+
# RDoc::Options#finish is also called after ri/aliki generator setup.
194194
# We need to dup the options to avoid modifying it after finish is called.
195195
parse_options = options.dup
196196
parse_options.finish
@@ -202,7 +202,7 @@ def generate
202202
document 'ri', options, @ri_dir if
203203
@generate_ri and (@force or not File.exist? @ri_dir)
204204

205-
document 'darkfish', options, @rdoc_dir if
205+
document 'aliki', options, @rdoc_dir if
206206
@generate_rdoc and (@force or not File.exist? @rdoc_dir)
207207
end
208208

test/rdoc/generator/aliki_test.rb

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
# frozen_string_literal: true
2+
require_relative '../helper'
3+
4+
class RDocGeneratorAlikiTest < RDoc::TestCase
5+
6+
def setup
7+
super
8+
9+
@lib_dir = "#{@pwd}/lib"
10+
$LOAD_PATH.unshift @lib_dir
11+
12+
@options = RDoc::Options.new
13+
@options.option_parser = OptionParser.new
14+
15+
@tmpdir = File.join Dir.tmpdir, "test_rdoc_generator_aliki_#{$$}"
16+
FileUtils.mkdir_p @tmpdir
17+
Dir.chdir @tmpdir
18+
@options.op_dir = @tmpdir
19+
@options.generator = RDoc::Generator::Aliki
20+
21+
$LOAD_PATH.each do |path|
22+
aliki_dir = File.join path, 'rdoc/generator/template/aliki/'
23+
next unless File.directory? aliki_dir
24+
@options.template_dir = aliki_dir
25+
break
26+
end
27+
28+
@rdoc.options = @options
29+
30+
@g = @options.generator.new @store, @options
31+
@rdoc.generator = @g
32+
33+
@top_level = @store.add_file 'file.rb'
34+
@top_level.parser = RDoc::Parser::Ruby
35+
@klass = @top_level.add_class RDoc::NormalClass, 'Klass'
36+
37+
@meth = RDoc::AnyMethod.new nil, 'method'
38+
@meth_with_html_tag_yield = RDoc::AnyMethod.new nil, 'method_with_html_tag_yield'
39+
@meth_with_html_tag_yield.block_params = '%<<script>alert("atui")</script>>, yield_arg'
40+
41+
@klass.add_method @meth
42+
@klass.add_method @meth_with_html_tag_yield
43+
44+
@store.complete :private
45+
end
46+
47+
def teardown
48+
super
49+
50+
$LOAD_PATH.shift
51+
Dir.chdir @pwd
52+
FileUtils.rm_rf @tmpdir
53+
end
54+
55+
def test_inheritance_and_template_dir
56+
assert_kind_of RDoc::Generator::Darkfish, @g
57+
assert_match %r{/template/aliki\z}, @g.template_dir.to_s
58+
end
59+
60+
def test_write_style_sheet_copies_css_and_js_only
61+
@g.generate
62+
63+
# Aliki should have these assets
64+
assert_file 'css/rdoc.css'
65+
assert_file 'js/aliki.js'
66+
assert_file 'js/search.js'
67+
assert_file 'js/theme-toggle.js'
68+
assert_file 'js/c_highlighter.js'
69+
70+
# Aliki should NOT have fonts (unlike Darkfish)
71+
refute File.exist?('css/fonts.css'), 'Aliki should not copy fonts.css'
72+
refute File.exist?('fonts'), 'Aliki should not copy fonts directory'
73+
end
74+
75+
# Aliki-specific: verify version query strings on asset references
76+
def test_asset_version_query_strings
77+
@g.generate
78+
79+
content = File.binread('index.html')
80+
81+
# CSS should have version query string
82+
assert_match %r{css/rdoc\.css\?v=#{Regexp.escape(RDoc::VERSION)}}, content
83+
84+
# JS files should have version query strings
85+
assert_match %r{js/aliki\.js\?v=#{Regexp.escape(RDoc::VERSION)}}, content
86+
assert_match %r{js/search\.js\?v=#{Regexp.escape(RDoc::VERSION)}}, content
87+
assert_match %r{js/theme-toggle\.js\?v=#{Regexp.escape(RDoc::VERSION)}}, content
88+
end
89+
90+
def test_open_graph_meta_tags_for_index
91+
@options.title = "My Ruby Project"
92+
@g.generate
93+
94+
content = File.binread('index.html')
95+
96+
assert_match %r{<meta property="og:type" content="website">}, content
97+
assert_match %r{<meta property="og:title" content="My Ruby Project">}, content
98+
assert_match %r{<meta\s+property="og:description"\s+content="API documentation for My Ruby Project}m, content
99+
end
100+
101+
def test_open_graph_meta_tags_for_class
102+
top_level = @store.add_file 'file.rb'
103+
top_level.add_class @klass.class, @klass.name
104+
@klass.add_comment "A useful class for doing things.", top_level
105+
106+
@g.generate
107+
108+
content = File.binread('Klass.html')
109+
110+
assert_match %r{<meta property="og:title" content=}, content
111+
assert_match %r{<meta property="og:description" content="A useful class for doing things\.">}, content
112+
end
113+
114+
# Aliki-specific: Twitter meta tags
115+
def test_twitter_meta_tags_for_index
116+
@options.title = "My Ruby Project"
117+
@g.generate
118+
119+
content = File.binread('index.html')
120+
121+
assert_match %r{<meta name="twitter:card" content="summary">}, content
122+
assert_match %r{<meta name="twitter:title" content="My Ruby Project">}, content
123+
assert_match %r{<meta\s+name="twitter:description"\s+content="API documentation for My Ruby Project}m, content
124+
end
125+
126+
def test_twitter_meta_tags_for_class
127+
top_level = @store.add_file 'file.rb'
128+
top_level.add_class @klass.class, @klass.name
129+
@klass.add_comment "A useful class for doing things.", top_level
130+
131+
@g.generate
132+
133+
content = File.binread('Klass.html')
134+
135+
assert_match %r{<meta name="twitter:card" content="summary">}, content
136+
assert_match %r{<meta name="twitter:description" content="A useful class for doing things\.">}, content
137+
end
138+
139+
def test_meta_tags_multiline_format
140+
top_level = @store.add_file 'file.rb'
141+
top_level.add_class @klass.class, @klass.name
142+
inner = @klass.add_class RDoc::NormalClass, 'Inner'
143+
inner.add_comment "This is a normal class.", top_level
144+
145+
@g.generate
146+
147+
content = File.binread('Klass/Inner.html')
148+
149+
# Aliki formats meta tags across multiple lines
150+
assert_match %r{name="keywords"\s+content="ruby,class,Klass::Inner"}m, content
151+
assert_match %r{name="description"\s+content="class Klass::Inner: This is a normal class\."}m, content
152+
end
153+
154+
def test_template_stylesheets_with_version
155+
css = Tempfile.create(%W[custom .css], Dir.mktmpdir('tmp', '.'))
156+
File.write(css, '')
157+
css.close
158+
base = File.basename(css)
159+
160+
@options.template_stylesheets << css
161+
162+
@g.generate
163+
164+
assert_file base
165+
# Aliki includes version in query string for custom stylesheets too
166+
assert_match %r{href="\./#{Regexp.escape(base)}\?v=#{Regexp.escape(RDoc::VERSION)}"}, File.binread('index.html')
167+
end
168+
169+
def test_generated_method_with_html_tag_yield_escapes_xss
170+
top_level = @store.add_file 'file.rb'
171+
top_level.add_class @klass.class, @klass.name
172+
173+
@g.generate
174+
175+
content = File.binread('Klass.html')
176+
177+
# Script tags in yield params should be escaped
178+
assert_match %r{%&lt;&lt;script&gt;alert\(&quot;atui&quot;\)&lt;/script&gt;&gt;}, content
179+
refute_match %r{<script>alert\("atui"\)</script>}, content
180+
end
181+
182+
def test_title_escape_prevents_xss
183+
@options.title = '<script>alert("xss")</script>'
184+
@g.generate
185+
186+
content = File.binread('index.html')
187+
188+
# Title should be HTML escaped
189+
assert_match %r{<title>&lt;script&gt;alert\(&quot;xss&quot;\)&lt;/script&gt;</title>}, content
190+
refute_match %r{<title><script>alert}, content
191+
end
192+
193+
def test_generate
194+
@klass.add_class RDoc::NormalClass, 'Inner'
195+
@klass.add_comment "Test class documentation", @top_level
196+
197+
@g.generate
198+
199+
# Core HTML files
200+
assert_file 'index.html'
201+
assert_file 'Klass.html'
202+
assert_file 'Klass/Inner.html'
203+
204+
# Aliki assets
205+
assert_file 'js/search_index.js'
206+
assert_file 'css/rdoc.css'
207+
assert_file 'js/aliki.js'
208+
209+
# Verify HTML structure
210+
index = File.binread('index.html')
211+
assert_match %r{<html lang="en">}, index
212+
assert_match %r{<body role="document"}, index
213+
assert_match %r{<nav id="navigation" role="navigation">}, index
214+
assert_match %r{<main role="main">}, index
215+
end
216+
217+
def test_canonical_url
218+
@klass.add_class RDoc::NormalClass, 'Inner'
219+
@store.options.canonical_root = @options.canonical_root = "https://example.com/docs/"
220+
@g.generate
221+
222+
index_content = File.binread('index.html')
223+
assert_include index_content, '<link rel="canonical" href="https://example.com/docs/">'
224+
225+
# Open Graph should also include canonical URL
226+
assert_match %r{<meta property="og:url" content="https://example\.com/docs/">}, index_content
227+
228+
inner_content = File.binread('Klass/Inner.html')
229+
assert_include inner_content, '<link rel="canonical" href="https://example.com/docs/Klass/Inner.html">'
230+
end
231+
232+
def test_dry_run_creates_no_files
233+
@g.dry_run = true
234+
235+
@g.generate
236+
237+
refute_file 'index.html'
238+
refute_file 'css/rdoc.css'
239+
refute_file 'js/aliki.js'
240+
end
241+
242+
# Test locale affects html lang attribute
243+
def test_html_lang_from_locale
244+
@options.locale = RDoc::I18n::Locale.new 'ja'
245+
@g.generate
246+
247+
content = File.binread('index.html')
248+
assert_include content, '<html lang="ja">'
249+
end
250+
end

0 commit comments

Comments
 (0)