Skip to content
Open

Aliki #1682

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,33 +1,34 @@
# frozen_string_literal: true

source 'https://rubygems.org'

group :development do
gem 'rspec'
gem 'coveralls_reborn', :require => false if RUBY_VERSION >= '2.7.0'
gem 'json'
gem 'rake'
gem 'rdoc', RUBY_VERSION < '2.7.0' ? '~> 6.0' : nil
gem 'json'
gem 'rspec'
gem 'simplecov' if RUBY_VERSION >= '2.7.0'
gem 'coveralls_reborn', :require => false if RUBY_VERSION >= '2.7.0'
gem 'webrick'
end

group :asciidoc do
gem 'logger' if RUBY_VERSION >= '2.3.0'
gem 'asciidoctor'
gem 'logger' if RUBY_VERSION >= '2.3.0'
end

group :markdown do
gem 'redcarpet'
gem 'commonmarker'
gem 'redcarpet'
end

group :textile do
gem 'RedCloth'
end

group :server do
gem 'rackup' if RUBY_VERSION >= '2.6.0'
gem 'rack', '~> 2.0' if RUBY_VERSION < '2.6.0'
gem 'rackup' if RUBY_VERSION >= '2.6.0'
end

group :i18n do
Expand Down
5 changes: 5 additions & 0 deletions LEGAL
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,8 @@ lib/yard/server/http_utils.rb:
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

templates/aliki/layout/html/css/rdoc.css and templates/aliki/layout/html/js/*:

These files are adapted from RDoc's Aliki theme, written by Stan Lo and
included under the MIT license.
75 changes: 75 additions & 0 deletions spec/templates/aliki_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

require File.expand_path('spec_helper', __dir__)
require 'json'

class AlikiStringSerializer < YARD::Serializers::Base
attr_reader :files, :output

def initialize
super
@files = []
@output = {}
@filesystem = YARD::Serializers::FileSystemSerializer.new
end

def serialize(object, data)
files << object
output[serialized_path(object)] = data
end

def serialized_path(object)
@filesystem.serialized_path(object)
end
end

RSpec.describe "Aliki HTML template" do
before do
Registry.clear
YARD.parse_string <<-RUBY
# A test class.
class A
# Returns foo.
# @return [String]
def foo; 'foo' end
end
RUBY
end

after do
Registry.clear
end

it "generates Aliki assets, pages, object output, and search data" do
serializer = AlikiStringSerializer.new
readme = CodeObjects::ExtraFileObject.new('README', '# Readme')

Templates::Engine.generate Registry.all(:class),
:serializer => serializer,
:template => :aliki,
:format => :html,
:readme => readme,
:files => [readme]

expect(serializer.files).to include(
'css/rdoc.css', 'css/yard.css', 'js/aliki.js', 'js/search_data.js'
)
expect(serializer.output['index.html']).to include('class="file has-toc"')
expect(serializer.output['A.html']).to include('Classes and Modules')
expect(serializer.output['A.html']).to include('<span class="nav-section-title">Pages</span>')
expect(serializer.output['A.html']).to include('method-detail anchor-link')

search_data = serializer.output['js/search_data.js'].
sub(/\Avar search_data = /, '').
sub(/;\z/, '')
index = JSON.parse(search_data).fetch('index')
expect(index).to include(hash_including('name' => 'A', 'type' => 'class', 'path' => 'A.html'))
expect(index).to include(
hash_including(
'name' => 'foo',
'type' => 'instance_method',
'path' => 'A.html#foo-instance_method'
)
)
end
end
3 changes: 3 additions & 0 deletions templates/aliki/class/html/setup.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

include Templates::Engine.template(:default, :class, :html)
3 changes: 3 additions & 0 deletions templates/aliki/docstring/html/setup.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

include Templates::Engine.template(:default, :docstring, :html)
102 changes: 102 additions & 0 deletions templates/aliki/fulldoc/html/setup.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# frozen_string_literal: true

require 'json'

include T('default/fulldoc/html')

def init
options.objects = objects = run_verifier(options.objects)

return serialize_onefile if options.onefile

generate_assets
serialize('_index.html')
options.files.each_with_index do |file, _i|
serialize_file(file, file.title)
end

options.delete(:objects)

objects.each do |object|
begin
serialize(object)
rescue StandardError => e
path = options.serializer.serialized_path(object)
log.error "Exception occurred while generating '#{path}'"
log.backtrace(e)
end
end
end

def generate_assets
layout_template = Templates::Engine.template(:aliki, :layout, :html)
layout = Object.new.extend(layout_template)
(layout.javascripts + layout.stylesheets).uniq.each do |file|
next if file == 'js/search_data.js'

asset(file, File.read(layout_template.find_file(file)))
end

asset('js/search_data.js', aliki_search_data)
end

def aliki_search_data
entries = []
searchable_objects.each do |object|
entries << aliki_search_entry(object)
end

"var search_data = #{JSON.generate(:index => entries.compact)};"
end

def searchable_objects
objects = Registry.all(:class, :module, :method, :constant, :classvariable)
run_verifier(objects).reject do |object|
object.respond_to?(:root?) && object.root?
end
end

def aliki_search_entry(object)
path = url_for(object, nil, false)
return unless path

{
:name => aliki_search_name(object),
:full_name => object.path,
:type => aliki_search_type(object),
:path => path
}.tap do |entry|
snippet = aliki_search_snippet(object)
entry[:snippet] = snippet unless snippet.empty?
end
end

def aliki_search_name(object)
if object.respond_to?(:name)
object.name.to_s
else
object.path.to_s
end
end

def aliki_search_type(object)
case object
when CodeObjects::ClassObject
'class'
when CodeObjects::ModuleObject
'module'
when CodeObjects::MethodObject
object.scope == :class ? 'class_method' : 'instance_method'
when CodeObjects::ConstantObject, CodeObjects::ClassVariableObject
'constant'
else
object.type.to_s
end
end

def aliki_search_snippet(object)
return '' unless object.respond_to?(:docstring)

summary = object.docstring.summary.to_s.strip.gsub(/\s+/, ' ')
h(summary)
end
6 changes: 6 additions & 0 deletions templates/aliki/layout/html/aside_toc.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<aside class="table-of-contents" role="complementary" aria-label="Table of Contents">
<div class="toc-sticky">
<h3 class="toc-heading">On This Page</h3>
<nav class="toc-nav" id="toc-nav" aria-label="Page sections"></nav>
</div>
</aside>
Loading
Loading