Skip to content

Commit 37f2f8e

Browse files
committed
Add a simple HTML5 output formatter (closes #13)
Signed-off-by: Youhei SASAKI <[email protected]>
1 parent 6a6dd37 commit 37f2f8e

4 files changed

Lines changed: 265 additions & 1 deletion

File tree

README.rd

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,48 @@ the indication of format-library. For example,
4242
4343
rd2 load "${HOME}/.rd2rc" when it runs.
4444
45-
To generate HTML explicitly, for example:
45+
Bundled format libraries include:
46+
47+
:((%rd/rd2html-lib%))
48+
XHTML-style HTML output. Main options include ((%--with-css=FILE%)),
49+
((%--html-charset=CHARSET%)), ((%--html-lang=LANG%)),
50+
((%--html-title=TITLE%)), ((%--html-link-rel=REL%)),
51+
((%--html-link-rev=REV%)), and ((%--output-rbl%)).
52+
53+
:((%rd/rd2html-ext-lib%))
54+
Extended HTML output with headline numbering and related features.
55+
Main additional options include ((%--ref-extension%)),
56+
((%--headline-title%)), ((%--headline-secno%)),
57+
((%--enable-br%)), ((%--native-inline%)), and ((%--head-element%)).
58+
59+
:((%rd/rd2html5-lib%))
60+
HTML5 output. It accepts the same main options as ((%rd/rd2html-lib%)),
61+
such as ((%--with-css=FILE%)), ((%--html-charset=CHARSET%)),
62+
((%--html-lang=LANG%)), and ((%--html-title=TITLE%)).
63+
64+
:((%rd/rd2man-lib%))
65+
man page output. The main option is ((%--man-section=SECTION%)).
66+
67+
:((%rd/rd2rdo-lib%))
68+
Dumps the parsed RD tree as Marshal data.
69+
70+
:((%rd/rd2rmi-lib%))
71+
Outputs method index data for reference lookup.
72+
73+
For example, to generate HTML explicitly:
4674
4775
% rd2 -r rd/rd2html-lib rdfile.rd > output.html
4876
77+
To generate HTML5 or a man page:
78+
79+
% rd2 -r rd/rd2html5-lib rdfile.rd > output.html
80+
% rd2 -r rd/rd2man-lib rdfile.rd > output.1
81+
82+
To check detailed options for a specific formatter, run:
83+
84+
% rd2 -r rd/rd2html-ext-lib --help
85+
% rd2 -r rd/rd2man-lib --help
86+
4987
RDtool also includes ((%rdswap.rb%)), which merges translated RD blocks
5088
back into a Ruby script. This is intended for maintaining one source
5189
script with embedded RD comments and generating language-specific copies.

README.rd.ja

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,51 @@ utils/rd-mode.el を使いたいなら、
4545
rd2はホームディレクトリにある".rd2rc"というファイルを読み込みます。
4646
これはRubyスクリプトです。
4747

48+
同梱されている主なフォーマットライブラリは次の通りです。
49+
50+
:((%rd/rd2html-lib%))
51+
XHTML 風の HTML を出力します。主なオプションは
52+
((%--with-css=FILE%)), ((%--html-charset=CHARSET%)),
53+
((%--html-lang=LANG%)), ((%--html-title=TITLE%)),
54+
((%--html-link-rel=REL%)), ((%--html-link-rev=REV%)),
55+
((%--output-rbl%)) です。
56+
57+
:((%rd/rd2html-ext-lib%))
58+
見出し番号などを追加した拡張 HTML を出力します。
59+
主な追加オプションは ((%--ref-extension%)),
60+
((%--headline-title%)), ((%--headline-secno%)),
61+
((%--enable-br%)), ((%--native-inline%)),
62+
((%--head-element%)) です。
63+
64+
:((%rd/rd2html5-lib%))
65+
HTML5 を出力します。主なオプションは ((%rd/rd2html-lib%)) と同様で、
66+
((%--with-css=FILE%)), ((%--html-charset=CHARSET%)),
67+
((%--html-lang=LANG%)), ((%--html-title=TITLE%)) などが使えます。
68+
69+
:((%rd/rd2man-lib%))
70+
man page を出力します。主なオプションは
71+
((%--man-section=SECTION%)) です。
72+
73+
:((%rd/rd2rdo-lib%))
74+
解析済みの RD tree を Marshal data として出力します。
75+
76+
:((%rd/rd2rmi-lib%))
77+
参照解決用の method index data を出力します。
78+
4879
例えば HTML を明示的に生成するなら:
4980

5081
% rd2 -r rd/rd2html-lib rdfile.rd > output.html
5182

83+
HTML5 や man page を生成するなら:
84+
85+
% rd2 -r rd/rd2html5-lib rdfile.rd > output.html
86+
% rd2 -r rd/rd2man-lib rdfile.rd > output.1
87+
88+
各 formatter の詳細なオプションを確認するには、例えば:
89+
90+
% rd2 -r rd/rd2html-ext-lib --help
91+
% rd2 -r rd/rd2man-lib --help
92+
5293
また、RDtool には ((%rdswap.rb%)) も含まれています。
5394
これは翻訳済みの RD block を Ruby スクリプトへ差し戻すための
5495
ツールです。RD コメントを埋め込んだ 1 つの Ruby スクリプトを保ちつつ、

lib/rd/rd2html5-lib.rb

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
=begin
2+
= rd2html5-lib.rb
3+
=end
4+
5+
require "rd/rd2html-lib"
6+
7+
module RD
8+
class RD2HTML5Visitor < RD2HTMLVisitor
9+
SYSTEM_NAME = "RDtool -- RD2HTML5Visitor"
10+
SYSTEM_VERSION = "$Version: " + RD::VERSION + "$"
11+
VERSION = Version.new_from_version_string(SYSTEM_NAME, SYSTEM_VERSION)
12+
13+
def self.version
14+
VERSION
15+
end
16+
17+
def xml_decl
18+
nil
19+
end
20+
private :xml_decl
21+
22+
def apply_to_DocumentElement(element, content)
23+
ret = ""
24+
ret << doctype_decl + "\n"
25+
ret << html_open_tag + "\n"
26+
ret << html_head + "\n"
27+
ret << html_body(content) + "\n"
28+
ret << "</html>\n"
29+
ret
30+
end
31+
32+
def doctype_decl
33+
"<!DOCTYPE html>"
34+
end
35+
private :doctype_decl
36+
37+
def html_open_tag
38+
lang_attr = %[ lang="#{@lang}"] if @lang
39+
%|<html#{lang_attr}>|
40+
end
41+
private :html_open_tag
42+
43+
def html_content_type
44+
%Q[<meta charset="#{@charset}">] if @charset
45+
end
46+
private :html_content_type
47+
48+
def apply_to_Headline(element, title)
49+
anchor = get_anchor(element)
50+
label = hyphen_escape(element.label)
51+
title = title.join("")
52+
%Q[<h#{element.level} id="#{anchor}">#{title}</h#{element.level}>] +
53+
%Q[<!-- RDLabel: "#{label}" -->]
54+
end
55+
56+
def apply_to_DescListItem(element, term, description)
57+
anchor = get_anchor(element.term)
58+
label = hyphen_escape(element.label)
59+
term = term.join("")
60+
if description.empty?
61+
%Q[<dt id="#{anchor}">#{term}</dt><!-- RDLabel: "#{label}" -->]
62+
else
63+
%Q[<dt id="#{anchor}">#{term}</dt><!-- RDLabel: "#{label}" -->\n] +
64+
%Q[<dd>\n#{description.join("\n").chomp}\n</dd>]
65+
end
66+
end
67+
68+
def apply_to_MethodListItem(element, term, description)
69+
term = parse_method(term)
70+
anchor = get_anchor(element.term)
71+
label = hyphen_escape(element.label)
72+
if description.empty?
73+
%Q[<dt id="#{anchor}"><code>#{term}</code></dt><!-- RDLabel: "#{label}" -->]
74+
else
75+
%Q[<dt id="#{anchor}"><code>#{term}</code></dt><!-- RDLabel: "#{label}" -->\n] +
76+
%Q[<dd>\n#{description.join("\n")}</dd>]
77+
end
78+
end
79+
80+
def apply_to_Index(element, content)
81+
tmp = []
82+
element.each do |i|
83+
tmp.push(i) if i.is_a?(String)
84+
end
85+
key = meta_char_escape(tmp.join(""))
86+
if @index.has_key?(key)
87+
%Q[<!-- Index, but conflict -->#{content.join("")}<!-- Index end -->]
88+
else
89+
num = @index[key] = @index.size
90+
anchor = a_name("index", num)
91+
%Q[<span id="#{anchor}">#{content.join("")}</span>]
92+
end
93+
end
94+
95+
def apply_to_Footnote(element, content)
96+
num = get_footnote_num(element)
97+
raise ArgumentError, "[BUG?] #{element} is not registered." unless num
98+
99+
add_foottext(num, content)
100+
anchor = a_name("footmark", num)
101+
href = a_name("foottext", num)
102+
%Q|<a id="#{anchor}" href="##{href}"><sup><small>*#{num}</small></sup></a>|
103+
end
104+
105+
def apply_to_Foottext(element, content)
106+
num = get_footnote_num(element)
107+
raise ArgumentError, "[BUG] #{element} isn't registered." unless num
108+
anchor = a_name("foottext", num)
109+
href = a_name("footmark", num)
110+
content = content.join("")
111+
%|<a id="#{anchor}" href="##{href}"><sup><small>*#{num}</small></sup></a>| +
112+
%|<small>#{content}</small><br>|
113+
end
114+
end
115+
end
116+
117+
$Visitor_Class = RD::RD2HTML5Visitor
118+
$RD2_Sub_OptionParser = "rd/rd2html-opt"

test/test-rd2html5-lib.rb

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
require "test/unit"
2+
3+
require "rd/rd2html5-lib"
4+
require "rd/tree"
5+
require "rd/block-element"
6+
require "rd/desclist"
7+
require "rd/methodlist"
8+
require "rd/inline-element"
9+
require "rd/rd-struct"
10+
11+
include RD
12+
13+
class TestRD2HTML5Visitor < Test::Unit::TestCase
14+
def setup
15+
@vis = RD2HTML5Visitor.new
16+
@vis.class.module_eval do
17+
public :xml_decl
18+
public :doctype_decl
19+
public :html_open_tag
20+
public :html_content_type
21+
end
22+
end
23+
24+
def test_html5_head_pieces
25+
@vis.lang = "en"
26+
@vis.charset = "utf-8"
27+
28+
assert_equal(nil, @vis.xml_decl)
29+
assert_equal("<!DOCTYPE html>", @vis.doctype_decl)
30+
assert_equal('<html lang="en">', @vis.html_open_tag)
31+
assert_equal('<meta charset="utf-8">', @vis.html_content_type)
32+
end
33+
34+
def test_apply_to_headline_uses_id_without_anchor_tag
35+
tr = Tree.new_with_document_struct(DocumentStructure::RD)
36+
tr.root = DocumentElement.new
37+
headline = nil
38+
tr.root.build do
39+
headline = new Headline, 1 do
40+
new StringElement, "headline"
41+
end
42+
end
43+
@vis.prepare_labels(tr, "label:")
44+
45+
assert_equal('<h1 id="label:0">headline</h1><!-- RDLabel: "headline" -->',
46+
@vis.apply_to_Headline(headline, ["headline"]))
47+
end
48+
49+
def test_apply_to_desclist_item_uses_id_on_dt
50+
tr = Tree.new_with_document_struct(DocumentStructure::RD)
51+
tr.root = DocumentElement.new
52+
item = nil
53+
tr.root.build do
54+
new DescList do
55+
item = new DescListItem do
56+
make_term do
57+
new StringElement, "term"
58+
end
59+
end
60+
end
61+
end
62+
@vis.prepare_labels(tr, "label:")
63+
64+
assert_equal('<dt id="label:0">term</dt><!-- RDLabel: "term" -->',
65+
@vis.apply_to_DescListItem(item, ["term"], []))
66+
end
67+
end

0 commit comments

Comments
 (0)