lib/yard/templates/helpers/html_helper.rb in yard-0.6.8 vs lib/yard/templates/helpers/html_helper.rb in yard-0.7.0
- old
+ new
@@ -4,43 +4,42 @@
module Templates::Helpers
# The helper module for HTML templates.
module HtmlHelper
include MarkupHelper
include HtmlSyntaxHighlightHelper
-
+
# @group Escaping Template Data
-
+
# Escapes HTML entities
- #
+ #
# @param [String] text the text to escape
# @return [String] the HTML with escaped entities
def h(text)
CGI.escapeHTML(text.to_s)
end
-
+
# Escapes a URL
- #
+ #
# @param [String] text the URL
# @return [String] the escaped URL
def urlencode(text)
CGI.escape(text.to_s)
end
-
+
# @group Converting Markup to HTML
# Turns text into HTML using +markup+ style formatting.
- #
+ #
# @param [String] text the text to format
# @param [Symbol] markup examples are +:markdown+, +:textile+, +:rdoc+.
# To add a custom markup type, see {MarkupHelper}
# @return [String] the HTML
def htmlify(text, markup = options[:markup])
markup_meth = "html_markup_#{markup}"
return text unless respond_to?(markup_meth)
return "" unless text
return text unless markup
- load_markup_provider(markup)
html = send(markup_meth, text)
if html.respond_to?(:encode)
html = html.force_encoding(text.encoding) # for libs that mess with encoding
html = html.encode(:invalid => :replace, :replace => '?')
end
@@ -50,77 +49,93 @@
str = html_syntax_highlight(CGI.unescapeHTML(str)) unless options[:no_highlight]
%Q{<pre class="code">#{str}</pre>}
end unless markup == :text
html
end
-
+
# Converts Markdown to HTML
# @param [String] text input Markdown text
# @return [String] output HTML
# @since 0.6.0
def html_markup_markdown(text)
# TODO: other libraries might be more complex
- markup_class(:markdown).new(text).to_html
+ provider = markup_class(:markdown)
+ if provider.to_s == 'RDiscount'
+ markup_class(:markdown).new(text, :autolink).to_html
+ else
+ markup_class(:markdown).new(text).to_html
+ end
end
-
+
# Converts Textile to HTML
# @param [String] text the input Textile text
# @return [String] output HTML
# @since 0.6.0
def html_markup_textile(text)
doc = markup_class(:textile).new(text)
doc.hard_breaks = false if doc.respond_to?(:hard_breaks=)
doc.to_html
end
-
+
# Converts RDoc formatting (SimpleMarkup) to HTML
# @param [String] text the input RDoc formatted text
# @return [String] output HTML
# @since 0.6.0
def html_markup_rdoc(text)
doc = markup_class(:rdoc).new(text)
doc.from_path = url_for(object) if doc.respond_to?(:from_path=)
doc.to_html
end
-
+
# Converts plaintext to HTML
# @param [String] text the input text
# @return [String] the output HTML
# @since 0.6.0
def html_markup_text(text)
"<pre>" + text + "</pre>"
end
-
+
# @return [String] the same text with no markup
# @since 0.6.6
def html_markup_none(text)
h(text).gsub(/(?:\r?\n){2}/, '<br/>')
end
-
+
# Converts HTML to HTML
# @param [String] text input html
# @return [String] output HTML
# @since 0.6.0
def html_markup_html(text)
text
end
+ # Highlights Ruby source. Similar to {#html_syntax_highlight}, but
+ # this method is meant to be called from {#htmlify} when markup is
+ # set to "ruby".
+ #
+ # @param [String] source the Ruby source
+ # @return [String] the highlighted HTML
+ # @since 0.7.0
+ def html_markup_ruby(source)
+ '<pre class="code">' + html_syntax_highlight(source, :ruby) + '</pre>'
+ end
+
# @return [String] HTMLified text as a single line (paragraphs removed)
def htmlify_line(*args)
"<div class='inline'>" + htmlify(*args) + "</div>"
end
-
+
# @group Syntax Highlighting Source Code
-
+
# Syntax highlights +source+ in language +type+.
- #
+ #
# @note To support a specific language +type+, implement the method
# +html_syntax_highlight_TYPE+ in this class.
- #
+ #
# @param [String] source the source code to highlight
# @param [Symbol] type the language type (:ruby, :plain, etc). Use
- # :plain for no syntax highlighting.
+ # :plain for no syntax highlighting.
# @return [String] the highlighted source
def html_syntax_highlight(source, type = nil)
return "" unless source
return h(source) if options[:no_highlight]
@@ -129,69 +144,87 @@
# handle !!!LANG prefix to send to html_syntax_highlight_LANG
if source =~ /\A(?:[ \t]*\r?\n)?[ \t]*!!!([\w.+-]+)[ \t]*\r?\n/
type, source = $1, $'
source = $'
end
-
+
meth = "html_syntax_highlight_#{type}"
respond_to?(meth) ? send(meth, source) : h(source)
end
-
+
# @return [String] unhighlighted source
def html_syntax_highlight_plain(source)
h(source)
end
-
+
# @group Linking Objects and URLs
# Resolves any text in the form of +{Name}+ to the object specified by
# Name. Also supports link titles in the form +{Name title}+.
- #
+ #
# @example Linking to an instance method
# resolve_links("{MyClass#method}") # => "<a href='...'>MyClass#method</a>"
# @example Linking to a class with a title
# resolve_links("{A::B::C the C class}") # => "<a href='...'>the c class</a>"
# @param [String] text the text to resolve links in
# @return [String] HTML with linkified references
def resolve_links(text)
code_tags = 0
- text.gsub(/<(\/)?(pre|code|tt)|\{(\S+?)(?:\s(.*?\S))?\}(?=[\W<]|.+<\/|$)/m) do |str|
- closed, tag, name, title, match = $1, $2, $3, $4, $&
+ text.gsub(/<(\/)?(pre|code|tt)|(\\)?\{(?!\})(\S+?)(?:\s([^\}]*?\S))?\}(?=[\W<]|.+<\/|$)/m) do |str|
+ closed, tag, escape, name, title, match = $1, $2, $3, $4, $5, $&
if tag
code_tags += (closed ? -1 : 1)
next str
end
next str unless code_tags == 0
-
+
+ next(match[1..-1]) if escape
+
next(match) if name[0,1] == '|'
if object.is_a?(String)
object
else
link = linkify(name, title)
- if link == name || link == title
+ if (link == name || link == title) && (name+' '+link !~ /\A<a\s.*>/)
match = /(.+)?(\{#{Regexp.quote name}(?:\s.*?)?\})(.+)?/.match(text)
- file = (@file ? @file : object.file) || '(unknown)'
+ file = (@file ? @file.filename : object.file) || '(unknown)'
line = (@file ? 1 : (object.docstring.line_range ? object.docstring.line_range.first : 1)) + (match ? $`.count("\n") : 0)
log.warn "In file `#{file}':#{line}: Cannot resolve link to #{name} from text" + (match ? ":" : ".")
log.warn((match[1] ? '...' : '') + match[2].gsub("\n","") + (match[3] ? '...' : '')) if match
end
-
+
link
end
end
end
-
+
# (see BaseHelper#link_file)
def link_file(filename, title = nil, anchor = nil)
- link_url(url_for_file(filename, anchor), title)
+ if CodeObjects::ExtraFileObject === filename
+ file = filename
+ else
+ contents = File.file?(filename) ? nil : ''
+ file = CodeObjects::ExtraFileObject.new(filename, contents)
+ end
+ return title || file.title unless serializer
+ link_url(url_for_file(file, anchor), title || file.title)
end
+ # (see BaseHelper#link_include_file)
+ def link_include_file(file)
+ unless file.is_a?(CodeObjects::ExtraFileObject)
+ file = CodeObjects::ExtraFileObject.new(file)
+ end
+ file.attributes[:markup] ||= markup_for_file('', file.filename)
+ htmlify(file.contents, file.attributes[:markup] || options[:markup])
+ end
+
# (see BaseHelper#link_include_object)
def link_include_object(obj)
htmlify(obj.docstring)
end
-
+
# (see BaseHelper#link_object)
def link_object(obj, otitle = nil, anchor = nil, relative = true)
return otitle if obj.nil?
obj = Registry.resolve(object, obj, true, true) if obj.is_a?(String)
if !otitle && obj.root?
@@ -203,16 +236,16 @@
else
title = h(obj.to_s)
end
return title unless serializer
return title if obj.is_a?(CodeObjects::Proxy)
-
+
link = url_for(obj, anchor, relative)
link = link ? link_url(link, title, :title => "#{obj.path} (#{obj.type})") : title
"<span class='object_link'>" + link + "</span>"
end
-
+
# (see BaseHelper#link_url)
def link_url(url, title = nil, params = {})
title ||= url
title.gsub!(/[\r\n]/, ' ')
params = SymbolHash.new(false).update(
@@ -220,13 +253,13 @@
:title => h(title)
).update(params)
params[:target] ||= '_parent' if url =~ /^(\w+):\/\//
"<a #{tag_attrs(params)}>#{title}</a>".gsub(/[\r\n]/, ' ')
end
-
+
# @group URL Helpers
-
+
# @param [CodeObjects::Base] object the object to get an anchor for
# @return [String] the anchor for a specific object
def anchor_for(object)
case object
when CodeObjects::MethodObject
@@ -239,102 +272,104 @@
object.path
else
object.to_s
end
end
-
+
# Returns the URL for an object.
- #
+ #
# @param [String, CodeObjects::Base] obj the object (or object path) to link to
# @param [String] anchor the anchor to link to
# @param [Boolean] relative use a relative or absolute link
# @return [String] the URL location of the object
def url_for(obj, anchor = nil, relative = true)
link = nil
return link unless serializer
-
+
if obj.is_a?(CodeObjects::Base) && !obj.is_a?(CodeObjects::NamespaceObject)
# If the obj is not a namespace obj make it the anchor.
anchor, obj = obj, obj.namespace
end
-
+
objpath = serializer.serialized_path(obj)
return link unless objpath
-
+
if relative
fromobj = object
- if object.is_a?(CodeObjects::Base) &&
+ if object.is_a?(CodeObjects::Base) &&
!object.is_a?(CodeObjects::NamespaceObject)
fromobj = fromobj.namespace
end
from = serializer.serialized_path(fromobj)
link = File.relative_path(from, objpath)
else
link = objpath
end
-
+
link + (anchor ? '#' + urlencode(anchor_for(anchor)) : '')
end
-
+
# Returns the URL for a specific file
- #
- # @param [String] filename the filename to link to
+ #
+ # @param [String, CodeObjects::ExtraFileObject] filename the filename to link to
# @param [String] anchor optional anchor
# @return [String] the URL pointing to the file
def url_for_file(filename, anchor = nil)
+ return '' unless serializer
fromobj = object
if CodeObjects::Base === fromobj && !fromobj.is_a?(CodeObjects::NamespaceObject)
fromobj = fromobj.namespace
end
from = serializer.serialized_path(fromobj)
if filename == options[:readme]
- filename = 'index'
+ path = 'index.html'
else
- filename = 'file.' + File.basename(filename).gsub(/\.[^.]+$/, '')
+ path = serializer.serialized_path(filename)
end
- link = File.relative_path(from, filename)
- link + '.html' + (anchor ? '#' + urlencode(anchor) : '')
+ link = File.relative_path(from, path)
+ link += (anchor ? '#' + urlencode(anchor) : '')
+ link
end
-
+
# @group Formatting Objects and Attributes
# Formats a list of objects and links them
# @return [String] a formatted list of objects
def format_object_name_list(objects)
- objects.sort_by {|o| o.name.to_s.downcase }.map do |o|
- "<span class='name'>" + linkify(o, o.name) + "</span>"
+ objects.sort_by {|o| o.name.to_s.downcase }.map do |o|
+ "<span class='name'>" + linkify(o, o.name) + "</span>"
end.join(", ")
end
-
+
# Formats a list of types from a tag.
- #
+ #
# @param [Array<String>, FalseClass] typelist
- # the list of types to be formatted.
- #
- # @param [Boolean] brackets omits the surrounding
+ # the list of types to be formatted.
+ #
+ # @param [Boolean] brackets omits the surrounding
# brackets if +brackets+ is set to +false+.
- #
+ #
# @return [String] the list of types formatted
# as [Type1, Type2, ...] with the types linked
# to their respective descriptions.
- #
+ #
def format_types(typelist, brackets = true)
return unless typelist.is_a?(Array)
- list = typelist.map do |type|
+ list = typelist.map do |type|
type = type.gsub(/([<>])/) { h($1) }
type = type.gsub(/([\w:]+)/) { $1 == "lt" || $1 == "gt" ? $1 : linkify($1, $1) }
"<tt>" + type + "</tt>"
end
list.empty? ? "" : (brackets ? "(#{list.join(", ")})" : list.join(", "))
end
-
+
# Get the return types for a method signature.
- #
+ #
# @param [CodeObjects::MethodObject] meth the method object
# @param [Boolean] link whether to link the types
- # @return [String] the signature types
+ # @return [String] the signature types
# @since 0.5.3
def signature_types(meth, link = true)
meth = convert_method_to_overload(meth)
type = options[:default_return] || ""
@@ -356,23 +391,23 @@
type = link ? h(type) : format_types([type], false)
end
type = "(#{type}) " unless type.empty?
type
end
-
+
# Formats the signature of method +meth+.
- #
+ #
# @param [CodeObjects::MethodObject] meth the method object to list
# the signature of
# @param [Boolean] link whether to link the method signature to the details view
# @param [Boolean] show_extras whether to show extra meta-data (visibility, attribute info)
- # @param [Boolean] full_attr_name whether to show the full attribute name
+ # @param [Boolean] full_attr_name whether to show the full attribute name
# ("name=" instead of "name")
# @return [String] the formatted method signature
def signature(meth, link = true, show_extras = true, full_attr_name = true)
meth = convert_method_to_overload(meth)
-
+
type = signature_types(meth, link)
scope = meth.scope == :class ? "+" : "-"
name = full_attr_name ? meth.name : meth.name.to_s.gsub(/^(\w+)=$/, '\1')
blk = format_block(meth)
args = !full_attr_name && meth.writer? ? "" : format_args(meth)
@@ -397,45 +432,49 @@
link_url(url_for(meth), title, :title => link_title) + extras_text
else
title + extras_text
end
end
-
+
# @group Getting the Character Encoding
-
+
# Returns the current character set. The default value can be overridden
# by setting the +LANG+ environment variable or by overriding this
# method. In Ruby 1.9 you can also modify this value by setting
# +Encoding.default_external+.
- #
+ #
# @return [String] the current character set
# @since 0.5.4
def charset
- return 'utf-8' unless RUBY19 || lang = ENV['LANG']
- if RUBY19
- lang = Encoding.default_external.name.downcase
+ if @file && RUBY19
+ lang = @file.contents.encoding.to_s
else
- lang = lang.downcase.split('.').last
+ return 'utf-8' unless RUBY19 || lang = ENV['LANG']
+ if RUBY19
+ lang = Encoding.default_external.name.downcase
+ else
+ lang = lang.downcase.split('.').last
+ end
end
case lang
when "ascii-8bit", "us-ascii", "ascii-7bit"; 'iso-8859-1'
else; lang
end
end
-
+
# @endgroup
-
+
private
# Converts a set of hash options into HTML attributes for a tag
- #
+ #
# @param [Hash{String => String}] opts the tag options
# @return [String] the tag attributes of an HTML tag
def tag_attrs(opts = {})
opts.sort_by {|k, v| k.to_s }.map {|k,v| "#{k}=#{v.to_s.inspect}" if v }.join(" ")
end
-
+
# Converts a {CodeObjects::MethodObject} into an overload object
# @since 0.5.3
def convert_method_to_overload(meth)
# use first overload tag if it has a return type and method itself does not
if !meth.tag(:return) && meth.tags(:overload).size == 1 && meth.tag(:overload).tag(:return)
@@ -444,6 +483,6 @@
meth
end
end
end
end
-
+