#--
# Copyright protects this work.
# See LICENSE file for details.
#++
desc: web page for the Internet
code: |
ICONS_DIR = File.join(ERBook::FORMATS_DIR, 'xhtml', 'icons')
JQUERY_DIR = File.join(ERBook::FORMATS_DIR, 'xhtml', 'jquery')
# load the String#to_xhtml and String#to_inline_xhtml methods
require 'erbook/to_xhtml'
class String
##
# Transforms this UTF-8 string into XML entities.
#
def to_xml_entities
unpack('U*').map! {|c| "#{c};"}.join
end
##
# Transforms this string into a valid URI fragment.
# See http://www.nmt.edu/tcc/help/pubs/xhtml/id-type.html
#
def to_uri_fragment
# remove XML tags from the input
buf = gsub(/<.*?>/, '')
# The first or only character must be a letter.
buf.insert(0, 'a') unless buf[0,1] =~ /[[:alpha:]]/
# The remaining characters must be letters, digits, hyphens (-),
# underscores (_), colons (:), or periods (.) or Unicode characters
#
# However, colons (:) and periods (.) are special characters
# in jQuery CSS selector syntax, so we sanitize them as well.
#
buf.unpack('U*').map! do |code|
if code > 0xFF or code.chr =~ /[[:alnum:]\-_]/
code
else
32 # ASCII character code for a single space
end
end.pack('U*').strip.gsub(/[[:space:]-]+/, '-')
end
end
class Hash
##
# Transforms this hash into a string of XML attribute key="value" pairs.
#
def to_xml_atts
inject([]) {|s,(k,v)| s << %( #{k}="#{v}") }.join
end
end
require 'erb'
module ERBook
##
# Encodes the given input in base64 format.
#
def ERBook.base_64_encode input #:nodoc:
[input].pack('m')
end
##
# Encodes the contents of the given file in base64 format.
#
def ERBook.base_64_encode_file path #:nodoc:
base_64_encode open(path, 'rb') {|f| f.read }
end
##
# Returns a string denoting embedded, base64 encoded data.
#
def ERBook.base_64_embed data, mime #:nodoc:
"data:#{mime.to_s.downcase};base64,#{data.tr("\n", '')}"
end
def ERBook.base_64_embed_file path # :nodoc:
data = base_64_encode_file(path)
require 'mime/types'
mime = MIME::Types.of(path)
base_64_embed data, mime
end
##
# Returns a string denoting embedded, base64 encoded image data.
#
# [format]
# type of image data (e.g. PNG, JPEG, GIF, etc.)
#
def ERBook.base_64_embed_image_data data, format #:nodoc:
base_64_embed data, "image/#{format}"
end
# admonition icons
ICON_DEFS = YAML.load_file File.join(ICONS_DIR, 'index.yaml')
class Icon < Struct.new(:origin, :path, :name, :format, :data) #:nodoc:
##
# Returns a data URI containing embedded image data.
#
def data_uri
ERBook.base_64_embed_image_data self.data, self.format
end
##
# Returns a CSS url() containing embedded image data.
#
def data_css
%{url("#{data_uri}")}
end
##
# Returns a XML entity reference (to this icon's
# embedded image data) ready for insertion into XML.
#
def entity_xml
"{entity_name};"
end
##
# Returns the name of the XML entity whose
# value contains embedded image data.
#
def entity_name
"icon_#{name}"
end
##
# Returns an tag that renders the image
# data embedded as an ENTITY in the html DOCTYPE.
#
def to_xhtml atts = {}
atts[:alt] ||= name
atts[:src] = entity_xml
atts[:class] = :icon
""
end
end
ICON_BY_NAME = {}
ICON_DEFS.each_pair do |name, path|
format = File.extname(path).sub('.', '')
origin = path[/^\w+/]
path = File.join(ICONS_DIR, path) # make the path absolute
data = base_64_encode_file(path)
ICON_BY_NAME[name] = Icon.new(origin, path, name, format, data)
end
ICONS = ICON_BY_NAME.values
class Template::Sandbox
##
# Protects the given content from the text-to-XHTML conversion process.
#
def verbatim content
::ERB::Util.html_escape content
end
##
# Returns XHTML for a hyperlink to the given
# URL of the given label and mouse-hover title.
#
def hyperlink url, label = url, title = nil
%{#{label}}
end
##
# Returns an tag that embeds the given image file.
#
# [path]
# path to the image file
#
# [format]
# format of the image file (e.g. PNG, JPEG, GIF, etc.)
#
# [atts]
# additional attributes for the tag
#
def embed_image_file path, format = path[/\w+/], atts = {}
data = ERBook.base_64_encode File.read(path)
embed_image_data data, format, atts
end
##
# Returns an tag that embeds the given raw image data.
#
# [data]
# raw image data
#
# [format]
# format of the image file (e.g. PNG, JPEG, GIF, etc.)
#
# [atts]
# additional attributes for the tag
#
def embed_image_data data, format, atts = {}
atts[:src] = ERBook.base_64_embed_image_data(data, format)
""
end
end
class Document::Node
##
# Returns the user-defined title for this node's content.
#
def title
@title ||= args[0]
end
##
# Returns the user-defined indentifer for this node.
#
def id
@id ||= args[1]
end
# utility methods
def type_frag #:nodoc:
"__#{type}__"
end
def type_label #:nodoc:
ERBook::PHRASES[type.to_s.capitalize]
end
##
# Returns the title of this node as XHTML.
#
def title_xhtml
title.to_s.to_inline_xhtml
end
##
# Returns the content of this node as XHTML.
#
def content_xhtml
content.join.to_xhtml
end
##
# Returns the content of this node as XHTML inside a
.
#
def content_xhtml_div #:nodoc:
%{
#{content_xhtml}
}
end
##
# Returns a hyperlink to this node containing its title.
#
def title_link title = nil
title || title_xhtml
end
##
# Returns a hyperlink to this node
# containing its LaTeX-style index number.
#
def index_link
index
end
##
# Returns a hyperlink to this node containing its occurrence number.
#
def number_link
[type_label, number].compact.join(' ')
end
##
# Returns a hyperlink to this node containing
# its ocurrence number and its title.
#
def number_and_title_link #:nodoc:
"#{number_link}. #{title_link}"
end
##
# Returns a hyperlink to this node containing
# its LaTeX-style index number and its title.
#
def index_and_title_link #:nodoc:
"#{index_link} #{title_link}"
end
##
# Returns a navigation menu for this node.
#
def navigation
self.class.navigation(
here_frag,
(list_frag if defn['toc'] || defn['lof']),
(prev_node.here_frag if prev_node),
(next_node.here_frag if next_node)
)
end
def parent_tabs_begin #:nodoc:
if p = parent and pc = p.toc_children and self == pc.first
%{
}
end
end
def parent_tabs_end #:nodoc:
if p = parent and self == p.toc_children.last
'
'
end
end
##
# Returns all children of this node which are
# configured to appear in the table of contents.
#
def toc_children
children.select {|c| c.defn['toc'] }
end
HERE_TEXT = ERBook::PHRASES['Focus this segment']
PREV_TEXT = ERBook::PHRASES['Focus previous segment']
NEXT_TEXT = ERBook::PHRASES['Focus next segment']
LIST_TEXT = ERBook::PHRASES['Return to listing']
HERE_SIGN = ICON_BY_NAME['nav_here'].to_xhtml(:alt => '∗')
PREV_SIGN = ICON_BY_NAME['nav_prev'].to_xhtml(:alt => '←')
NEXT_SIGN = ICON_BY_NAME['nav_next'].to_xhtml(:alt => '→')
LIST_SIGN = ICON_BY_NAME['nav_list'].to_xhtml(:alt => '≡')
##
# Calculates a local navigation menu containing links
# to the given URI fragments (which can be nil).
#
def self.navigation here_frag, list_frag, prev_frag, next_frag
here_link = %{#{HERE_SIGN}} if here_frag
prev_link = %{#{PREV_SIGN}} if prev_frag
next_link = %{#{NEXT_SIGN}} if next_frag
list_link = %{#{LIST_SIGN}} if list_frag
%{
}
end
##
# Returns a hyperlink to this node.
#
# [label]
# Optional label (may contain XHTML) for the hyperlink.
#
# If not specified, the title and designation of
# this node will be used as the label instead.
#
def xref_link label = nil
prefix = [type_label, index || number].compact.join(' ')
caption =
if type == 'reference'
prefix
else
[prefix, (%{"#{title}"} if label && title)].compact.join('. ')
end
label_xhtml = (label || title).to_s.to_inline_xhtml
%{#{label_xhtml}}
end
# URI fragments
@@frags = []
##
# Returns a unique URI fragment for this node.
#
def here_frag #:nodoc:
unless defined? @here_frag
salt = object_id.abs
frag = (id || title || salt).to_s.to_uri_fragment
# make it unique
while @@frags.include? frag
frag = "#{frag} #{index || number || salt}".to_uri_fragment
end
@@frags << frag
@here_frag = frag
end
@here_frag
end
##
# Returns the URI fragment for the location in the table
# of contents / list of figures that points this node.
#
def list_frag #:nodoc:
@list_frag ||= "__toc__#{here_frag}".to_uri_fragment
end
end
end
nodes:
# object model
node:
toc: false
lof: false
depth: false
index: false
number: false
silent: false
inline: true
bypass: true
output: <%= @node.content_xhtml %>
# Structure
header: &header
toc: false
lof: false
depth: false
index: false
number: false
silent: true
inline: true
output: <%= @node.content_xhtml %>
header_outside_above: &header_insert
toc: false
lof: false
depth: false
index: false
number: false
silent: true
inline: true
output: |
<%= @node.parent_tabs_begin %>