rdoc-f95 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +79 -0
- data/PostInstall.txt +7 -0
- data/README.rdoc +147 -0
- data/Rakefile +28 -0
- data/bin/rdoc-f95 +70 -0
- data/lib/rdoc-f95.rb +306 -0
- data/lib/rdoc-f95/code_objects.rb +776 -0
- data/lib/rdoc-f95/diagram.rb +342 -0
- data/lib/rdoc-f95/dot.rb +249 -0
- data/lib/rdoc-f95/generator.rb +1088 -0
- data/lib/rdoc-f95/generator/chm.rb +113 -0
- data/lib/rdoc-f95/generator/chm/chm.rb +98 -0
- data/lib/rdoc-f95/generator/html.rb +370 -0
- data/lib/rdoc-f95/generator/html/hefss.rb +414 -0
- data/lib/rdoc-f95/generator/html/html.rb +708 -0
- data/lib/rdoc-f95/generator/html/kilmer.rb +418 -0
- data/lib/rdoc-f95/generator/html/one_page_html.rb +121 -0
- data/lib/rdoc-f95/generator/ri.rb +229 -0
- data/lib/rdoc-f95/generator/xhtml.rb +106 -0
- data/lib/rdoc-f95/generator/xhtml/ctop.xsl +1318 -0
- data/lib/rdoc-f95/generator/xhtml/mathml.xsl +42 -0
- data/lib/rdoc-f95/generator/xhtml/pmathml.xsl +612 -0
- data/lib/rdoc-f95/generator/xhtml/pmathmlcss.xsl +872 -0
- data/lib/rdoc-f95/generator/xhtml/xhtml.rb +732 -0
- data/lib/rdoc-f95/generator/xml.rb +120 -0
- data/lib/rdoc-f95/generator/xml/rdf.rb +113 -0
- data/lib/rdoc-f95/generator/xml/xml.rb +111 -0
- data/lib/rdoc-f95/install.rb +166 -0
- data/lib/rdoc-f95/markup.rb +506 -0
- data/lib/rdoc-f95/markup/formatter.rb +14 -0
- data/lib/rdoc-f95/markup/fragments.rb +337 -0
- data/lib/rdoc-f95/markup/inline.rb +361 -0
- data/lib/rdoc-f95/markup/install.rb +57 -0
- data/lib/rdoc-f95/markup/lines.rb +152 -0
- data/lib/rdoc-f95/markup/mathml_wrapper.rb +91 -0
- data/lib/rdoc-f95/markup/preprocess.rb +71 -0
- data/lib/rdoc-f95/markup/sample/rdoc2latex.rb +16 -0
- data/lib/rdoc-f95/markup/sample/sample.rb +42 -0
- data/lib/rdoc-f95/markup/to_flow.rb +185 -0
- data/lib/rdoc-f95/markup/to_html.rb +357 -0
- data/lib/rdoc-f95/markup/to_html_crossref.rb +123 -0
- data/lib/rdoc-f95/markup/to_latex.rb +328 -0
- data/lib/rdoc-f95/markup/to_test.rb +50 -0
- data/lib/rdoc-f95/markup/to_xhtml_texparser.rb +234 -0
- data/lib/rdoc-f95/options.rb +745 -0
- data/lib/rdoc-f95/parsers/parse_c.rb +775 -0
- data/lib/rdoc-f95/parsers/parse_f95.rb +2499 -0
- data/lib/rdoc-f95/parsers/parse_rb.rb +2587 -0
- data/lib/rdoc-f95/parsers/parse_simple.rb +39 -0
- data/lib/rdoc-f95/parsers/parserfactory.rb +99 -0
- data/lib/rdoc-f95/ri.rb +2 -0
- data/lib/rdoc-f95/ri/cache.rb +188 -0
- data/lib/rdoc-f95/ri/descriptions.rb +147 -0
- data/lib/rdoc-f95/ri/display.rb +244 -0
- data/lib/rdoc-f95/ri/driver.rb +435 -0
- data/lib/rdoc-f95/ri/formatter.rb +603 -0
- data/lib/rdoc-f95/ri/paths.rb +105 -0
- data/lib/rdoc-f95/ri/reader.rb +106 -0
- data/lib/rdoc-f95/ri/util.rb +81 -0
- data/lib/rdoc-f95/ri/writer.rb +64 -0
- data/lib/rdoc-f95/stats.rb +23 -0
- data/lib/rdoc-f95/template.rb +64 -0
- data/lib/rdoc-f95/tokenstream.rb +33 -0
- data/lib/rdoc-f95/usage.rb +210 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test/test_helper.rb +3 -0
- data/test/test_rdoc-f95.rb +11 -0
- metadata +156 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'find'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
include Config
|
7
|
+
|
8
|
+
opt = OptionParser.new
|
9
|
+
libdir = nil
|
10
|
+
opt.on('--libdir=VAL') {|v| libdir = v}
|
11
|
+
opt.parse!(ARGV)
|
12
|
+
|
13
|
+
libdir = File.expand_path(libdir) if libdir
|
14
|
+
|
15
|
+
if libdir
|
16
|
+
sitedir = libdir
|
17
|
+
else
|
18
|
+
sitedir = CONFIG["sitelibdir"]
|
19
|
+
unless sitedir
|
20
|
+
version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
|
21
|
+
libdir = File.join(CONFIG["libdir"], "ruby", version)
|
22
|
+
sitedir = $:.find {|x| x =~ /site_ruby/}
|
23
|
+
if !sitedir
|
24
|
+
sitedir = File.join(libdir, "site_ruby")
|
25
|
+
elsif sitedir !~ Regexp.quote(version)
|
26
|
+
sitedir = File.join(sitedir, version)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
unless /^\// =~ sitedir.strip
|
32
|
+
sitedir = File.join("..", sitedir)
|
33
|
+
end
|
34
|
+
|
35
|
+
if !File.directory?(sitedir)
|
36
|
+
$stderr.puts "Cannot find sitedir #{sitedir}"
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
|
40
|
+
rdoc_dest = File.join(sitedir, "rdoc")
|
41
|
+
|
42
|
+
dest = File.join(rdoc_dest, "markup")
|
43
|
+
|
44
|
+
FileUtils::makedirs(dest, {:verbose => true})
|
45
|
+
|
46
|
+
Find.find("./",
|
47
|
+
"sample") do |fname|
|
48
|
+
if File.directory?(fname)
|
49
|
+
next if fname =~ /CVS/
|
50
|
+
FileUtils::makedirs(File.join(dest, fname), {:verbose => true})
|
51
|
+
else
|
52
|
+
next unless fname =~ /\.rb$/
|
53
|
+
next if fname =~ /install.rb$/
|
54
|
+
FileUtils::install(fname, File.join(dest, fname),
|
55
|
+
{:mode => 0444, :verbose => true})
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
class RDocF95::Markup
|
2
|
+
|
3
|
+
##
|
4
|
+
# We store the lines we're working on as objects of class Line. These
|
5
|
+
# contain the text of the line, along with a flag indicating the line type,
|
6
|
+
# and an indentation level.
|
7
|
+
|
8
|
+
class Line
|
9
|
+
INFINITY = 9999
|
10
|
+
|
11
|
+
LINE_TYPES = [
|
12
|
+
:BLANK,
|
13
|
+
:HEADING,
|
14
|
+
:LIST,
|
15
|
+
:PARAGRAPH,
|
16
|
+
:RULE,
|
17
|
+
:VERBATIM,
|
18
|
+
]
|
19
|
+
|
20
|
+
# line type
|
21
|
+
attr_accessor :type
|
22
|
+
|
23
|
+
# The indentation nesting level
|
24
|
+
attr_accessor :level
|
25
|
+
|
26
|
+
# The contents
|
27
|
+
attr_accessor :text
|
28
|
+
|
29
|
+
# A prefix or parameter. For LIST lines, this is
|
30
|
+
# the text that introduced the list item (the label)
|
31
|
+
attr_accessor :param
|
32
|
+
|
33
|
+
# A flag. For list lines, this is the type of the list
|
34
|
+
attr_accessor :flag
|
35
|
+
|
36
|
+
# the number of leading spaces
|
37
|
+
attr_accessor :leading_spaces
|
38
|
+
|
39
|
+
# true if this line has been deleted from the list of lines
|
40
|
+
attr_accessor :deleted
|
41
|
+
|
42
|
+
def initialize(text)
|
43
|
+
@text = text.dup
|
44
|
+
@deleted = false
|
45
|
+
|
46
|
+
# expand tabs
|
47
|
+
1 while @text.gsub!(/\t+/) { ' ' * (8*$&.length - $`.length % 8)} && $~ #`
|
48
|
+
|
49
|
+
# Strip trailing whitespace
|
50
|
+
@text.sub!(/\s+$/, '')
|
51
|
+
|
52
|
+
# and look for leading whitespace
|
53
|
+
if @text.length > 0
|
54
|
+
@text =~ /^(\s*)/
|
55
|
+
@leading_spaces = $1.length
|
56
|
+
else
|
57
|
+
@leading_spaces = INFINITY
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Return true if this line is blank
|
62
|
+
def blank?
|
63
|
+
@text.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
# stamp a line with a type, a level, a prefix, and a flag
|
67
|
+
def stamp(type, level, param="", flag=nil)
|
68
|
+
@type, @level, @param, @flag = type, level, param, flag
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Strip off the leading margin
|
73
|
+
|
74
|
+
def strip_leading(size)
|
75
|
+
if @text.size > size
|
76
|
+
@text[0,size] = ""
|
77
|
+
else
|
78
|
+
@text = ""
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_s
|
83
|
+
"#@type#@level: #@text"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# A container for all the lines.
|
89
|
+
|
90
|
+
class Lines
|
91
|
+
|
92
|
+
include Enumerable
|
93
|
+
|
94
|
+
attr_reader :lines # :nodoc:
|
95
|
+
|
96
|
+
def initialize(lines)
|
97
|
+
@lines = lines
|
98
|
+
rewind
|
99
|
+
end
|
100
|
+
|
101
|
+
def empty?
|
102
|
+
@lines.size.zero?
|
103
|
+
end
|
104
|
+
|
105
|
+
def each
|
106
|
+
@lines.each do |line|
|
107
|
+
yield line unless line.deleted
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# def [](index)
|
112
|
+
# @lines[index]
|
113
|
+
# end
|
114
|
+
|
115
|
+
def rewind
|
116
|
+
@nextline = 0
|
117
|
+
end
|
118
|
+
|
119
|
+
def next
|
120
|
+
begin
|
121
|
+
res = @lines[@nextline]
|
122
|
+
@nextline += 1 if @nextline < @lines.size
|
123
|
+
end while res and res.deleted and @nextline < @lines.size
|
124
|
+
res
|
125
|
+
end
|
126
|
+
|
127
|
+
def unget
|
128
|
+
@nextline -= 1
|
129
|
+
end
|
130
|
+
|
131
|
+
def delete(a_line)
|
132
|
+
a_line.deleted = true
|
133
|
+
end
|
134
|
+
|
135
|
+
def normalize
|
136
|
+
margin = @lines.collect{|l| l.leading_spaces}.min
|
137
|
+
margin = 0 if margin == :INFINITY
|
138
|
+
@lines.each {|line| line.strip_leading(margin) } if margin > 0
|
139
|
+
end
|
140
|
+
|
141
|
+
def as_text
|
142
|
+
@lines.map {|l| l.text}.join("\n")
|
143
|
+
end
|
144
|
+
|
145
|
+
def line_types
|
146
|
+
@lines.map {|l| l.type }
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# This class is MathML module wrapper.
|
2
|
+
# If MathML module can not be loaded, methods in this module return
|
3
|
+
# raw argument without modification.
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
class MathMLWrapper
|
7
|
+
|
8
|
+
# Mathml library name
|
9
|
+
MATHML_NAME = [ "mathml", "math_ml" ]
|
10
|
+
|
11
|
+
# $LOAD_PATH/MATHML_NAME/MACRO_REL_PATH/* files are parsed as TeX macro
|
12
|
+
MACRO_REL_PATH = "macro"
|
13
|
+
|
14
|
+
@@mathml_required = false
|
15
|
+
@@macro_input_flag = false
|
16
|
+
@@macro_path = ''
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
|
20
|
+
err_count = 0
|
21
|
+
if !@@mathml_required
|
22
|
+
MATHML_NAME.each{ |ml|
|
23
|
+
begin
|
24
|
+
require ml
|
25
|
+
@@macro_path = File.join(ml, MACRO_REL_PATH)
|
26
|
+
rescue LoadError
|
27
|
+
err_count = err_count + 1
|
28
|
+
end
|
29
|
+
}
|
30
|
+
if err_count < MATHML_NAME.size
|
31
|
+
@@mathml_required = true
|
32
|
+
else
|
33
|
+
raise LoadError,
|
34
|
+
" Error: \"#{MATHML_NAME.join('" or "')}\" library is not found\n" +
|
35
|
+
" in $LOAD_PATH=[#{$LOAD_PATH.join(',')}]\n\n"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
if (@@mathml_required && !@@macro_input_flag)
|
40
|
+
@@mathml_formula_macro = MathML::LaTeX::Parser.new
|
41
|
+
@@macro_input_flag = true
|
42
|
+
$LOAD_PATH.each{ |lpath|
|
43
|
+
macro_files = Dir::glob(File.join(lpath, @@macro_path, "*"))
|
44
|
+
macro_files.each{ |mfile|
|
45
|
+
if File.file?(mfile)
|
46
|
+
File.open(mfile, "r" ) { |io|
|
47
|
+
if $DEBUG_RDOC
|
48
|
+
puts \
|
49
|
+
"\n##### Debug messages about \"#{__FILE__}\" #####",
|
50
|
+
" \"#{mfile}\" is loading as a TeX macro file.",
|
51
|
+
" Following macros have been included."
|
52
|
+
end
|
53
|
+
io.each{ |line|
|
54
|
+
line.chomp!
|
55
|
+
macroerrormsg = nil
|
56
|
+
begin
|
57
|
+
@@mathml_formula_macro.macro.parse(line)
|
58
|
+
rescue MathML::LaTeX::ParseError
|
59
|
+
macroerrormsg = $!.to_s
|
60
|
+
rescue
|
61
|
+
macroerrormsg = $!.to_s
|
62
|
+
end
|
63
|
+
if macroerrormsg
|
64
|
+
$stderr.puts "Warning: in #{mfile}, following TeX macro causes #{macroerrormsg.to_s}\n\n",
|
65
|
+
" #{line}\n\n"
|
66
|
+
else
|
67
|
+
if $DEBUG_RDOC && !(line.empty?) && !(line =~ /\s*\%/)
|
68
|
+
puts " #{line}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
}
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
def parse(formula, block=false)
|
80
|
+
return formula if !@@mathml_required
|
81
|
+
mathml_formula = @@mathml_formula_macro
|
82
|
+
begin
|
83
|
+
mathml_formula_str = mathml_formula.parse(formula, block).to_s
|
84
|
+
rescue MathML::LaTeX::ParseError
|
85
|
+
return formula, 1
|
86
|
+
rescue
|
87
|
+
return formula, 1
|
88
|
+
end
|
89
|
+
return mathml_formula_str, 0
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rdoc-f95/markup'
|
2
|
+
|
3
|
+
##
|
4
|
+
# Handle common directives that can occur in a block of text:
|
5
|
+
#
|
6
|
+
# : include : filename
|
7
|
+
|
8
|
+
class RDocF95::Markup::PreProcess
|
9
|
+
|
10
|
+
def initialize(input_file_name, include_path)
|
11
|
+
@input_file_name = input_file_name
|
12
|
+
@include_path = include_path
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Look for common options in a chunk of text. Options that we don't handle
|
17
|
+
# are passed back to our caller as |directive, param|
|
18
|
+
|
19
|
+
def handle(text)
|
20
|
+
text.gsub!(/^([ \t#]*):(\w+):\s*(.+)?\n/) do
|
21
|
+
prefix = $1
|
22
|
+
directive = $2.downcase
|
23
|
+
param = $3
|
24
|
+
|
25
|
+
case directive
|
26
|
+
when "include"
|
27
|
+
filename = param.split[0]
|
28
|
+
include_file(filename, prefix)
|
29
|
+
|
30
|
+
else
|
31
|
+
yield(directive, param)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
##
|
39
|
+
# Include a file, indenting it correctly.
|
40
|
+
|
41
|
+
def include_file(name, indent)
|
42
|
+
if full_name = find_include_file(name) then
|
43
|
+
content = File.open(full_name) {|f| f.read}
|
44
|
+
# strip leading '#'s, but only if all lines start with them
|
45
|
+
if content =~ /^[^#]/
|
46
|
+
content.gsub(/^/, indent)
|
47
|
+
else
|
48
|
+
content.gsub(/^#?/, indent)
|
49
|
+
end
|
50
|
+
else
|
51
|
+
$stderr.puts "Couldn't find file to include: '#{name}'"
|
52
|
+
''
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Look for the given file in the directory containing the current file,
|
58
|
+
# and then in each of the directories specified in the RDOC_INCLUDE path
|
59
|
+
|
60
|
+
def find_include_file(name)
|
61
|
+
to_search = [ File.dirname(@input_file_name) ].concat @include_path
|
62
|
+
to_search.each do |dir|
|
63
|
+
full_name = File.join(dir, name)
|
64
|
+
stat = File.stat(full_name) rescue next
|
65
|
+
return full_name if stat.readable?
|
66
|
+
end
|
67
|
+
nil
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
# Illustration of a script to convert an RDoc-style file to a LaTeX
|
3
|
+
# document
|
4
|
+
|
5
|
+
require 'rdoc-f95/markup/simple_markup'
|
6
|
+
require 'rdoc-f95/markup/simple_markup/to_latex'
|
7
|
+
|
8
|
+
p = SM::SimpleMarkup.new
|
9
|
+
h = SM::ToLaTeX.new
|
10
|
+
|
11
|
+
#puts "\\documentclass{report}"
|
12
|
+
#puts "\\usepackage{tabularx}"
|
13
|
+
#puts "\\usepackage{parskip}"
|
14
|
+
#puts "\\begin{document}"
|
15
|
+
puts p.convert(ARGF.read, h)
|
16
|
+
#puts "\\end{document}"
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# This program illustrates the basic use of the SimpleMarkup
|
2
|
+
# class. It extracts the first comment block from the
|
3
|
+
# simple_markup.rb file and converts it into HTML on
|
4
|
+
# standard output. Run it using
|
5
|
+
#
|
6
|
+
# % ruby sample.rb
|
7
|
+
#
|
8
|
+
# You should be in the sample/ directory when you do this,
|
9
|
+
# as it hardwires the path to the files it needs to require.
|
10
|
+
# This isn't necessary in the code you write once you've
|
11
|
+
# installed the package.
|
12
|
+
#
|
13
|
+
# For a better way of formatting code comment blocks (and more)
|
14
|
+
# see the rdoc package.
|
15
|
+
#
|
16
|
+
|
17
|
+
$:.unshift "../../.."
|
18
|
+
|
19
|
+
require 'rdoc-f95/markup/simple_markup'
|
20
|
+
require 'rdoc-f95/markup/simple_markup/to_html'
|
21
|
+
|
22
|
+
# Extract the comment block from the source file
|
23
|
+
|
24
|
+
input_string = ""
|
25
|
+
|
26
|
+
File.foreach("../simple_markup.rb") do |line|
|
27
|
+
break unless line.gsub!(/^\# ?/, '')
|
28
|
+
input_string << line
|
29
|
+
end
|
30
|
+
|
31
|
+
# Create a markup object
|
32
|
+
markup = SM::SimpleMarkup.new
|
33
|
+
|
34
|
+
# Attach it to an HTML formatter
|
35
|
+
h = SM::ToHtml.new
|
36
|
+
|
37
|
+
# And convert out comment block to html. Wrap it a body
|
38
|
+
# tag pair to let browsers view it
|
39
|
+
|
40
|
+
puts "<html><body>"
|
41
|
+
puts markup.convert(input_string, h)
|
42
|
+
puts "</body></html>"
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require 'rdoc-f95/markup/formatter'
|
2
|
+
require 'rdoc-f95/markup/fragments'
|
3
|
+
require 'rdoc-f95/markup/inline'
|
4
|
+
require 'cgi'
|
5
|
+
|
6
|
+
class RDocF95::Markup
|
7
|
+
|
8
|
+
module Flow
|
9
|
+
P = Struct.new(:body)
|
10
|
+
VERB = Struct.new(:body)
|
11
|
+
RULE = Struct.new(:width)
|
12
|
+
class LIST
|
13
|
+
attr_reader :type, :contents
|
14
|
+
def initialize(type)
|
15
|
+
@type = type
|
16
|
+
@contents = []
|
17
|
+
end
|
18
|
+
def <<(stuff)
|
19
|
+
@contents << stuff
|
20
|
+
end
|
21
|
+
end
|
22
|
+
LI = Struct.new(:label, :body)
|
23
|
+
H = Struct.new(:level, :text)
|
24
|
+
end
|
25
|
+
|
26
|
+
class ToFlow < RDocF95::Markup::Formatter
|
27
|
+
LIST_TYPE_TO_HTML = {
|
28
|
+
:BULLET => [ "<ul>", "</ul>" ],
|
29
|
+
:NUMBER => [ "<ol>", "</ol>" ],
|
30
|
+
:UPPERALPHA => [ "<ol>", "</ol>" ],
|
31
|
+
:LOWERALPHA => [ "<ol>", "</ol>" ],
|
32
|
+
:LABELED => [ "<dl>", "</dl>" ],
|
33
|
+
:NOTE => [ "<table>", "</table>" ],
|
34
|
+
}
|
35
|
+
|
36
|
+
InlineTag = Struct.new(:bit, :on, :off)
|
37
|
+
|
38
|
+
def initialize
|
39
|
+
super
|
40
|
+
|
41
|
+
init_tags
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Set up the standard mapping of attributes to HTML tags
|
46
|
+
|
47
|
+
def init_tags
|
48
|
+
@attr_tags = [
|
49
|
+
InlineTag.new(RDocF95::Markup::Attribute.bitmap_for(:BOLD), "<b>", "</b>"),
|
50
|
+
InlineTag.new(RDocF95::Markup::Attribute.bitmap_for(:TT), "<tt>", "</tt>"),
|
51
|
+
InlineTag.new(RDocF95::Markup::Attribute.bitmap_for(:EM), "<em>", "</em>"),
|
52
|
+
]
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Add a new set of HTML tags for an attribute. We allow separate start and
|
57
|
+
# end tags for flexibility
|
58
|
+
|
59
|
+
def add_tag(name, start, stop)
|
60
|
+
@attr_tags << InlineTag.new(RDocF95::Markup::Attribute.bitmap_for(name), start, stop)
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Given an HTML tag, decorate it with class information and the like if
|
65
|
+
# required. This is a no-op in the base class, but is overridden in HTML
|
66
|
+
# output classes that implement style sheets
|
67
|
+
|
68
|
+
def annotate(tag)
|
69
|
+
tag
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Here's the client side of the visitor pattern
|
74
|
+
|
75
|
+
def start_accepting
|
76
|
+
@res = []
|
77
|
+
@list_stack = []
|
78
|
+
end
|
79
|
+
|
80
|
+
def end_accepting
|
81
|
+
@res
|
82
|
+
end
|
83
|
+
|
84
|
+
def accept_paragraph(am, fragment)
|
85
|
+
@res << Flow::P.new((convert_flow(am.flow(fragment.txt))))
|
86
|
+
end
|
87
|
+
|
88
|
+
def accept_verbatim(am, fragment)
|
89
|
+
@res << Flow::VERB.new((convert_flow(am.flow(fragment.txt))))
|
90
|
+
end
|
91
|
+
|
92
|
+
def accept_rule(am, fragment)
|
93
|
+
size = fragment.param
|
94
|
+
size = 10 if size > 10
|
95
|
+
@res << Flow::RULE.new(size)
|
96
|
+
end
|
97
|
+
|
98
|
+
def accept_list_start(am, fragment)
|
99
|
+
@list_stack.push(@res)
|
100
|
+
list = Flow::LIST.new(fragment.type)
|
101
|
+
@res << list
|
102
|
+
@res = list
|
103
|
+
end
|
104
|
+
|
105
|
+
def accept_list_end(am, fragment)
|
106
|
+
@res = @list_stack.pop
|
107
|
+
end
|
108
|
+
|
109
|
+
def accept_list_item(am, fragment)
|
110
|
+
@res << Flow::LI.new(fragment.param, convert_flow(am.flow(fragment.txt)))
|
111
|
+
end
|
112
|
+
|
113
|
+
def accept_blank_line(am, fragment)
|
114
|
+
# @res << annotate("<p />") << "\n"
|
115
|
+
end
|
116
|
+
|
117
|
+
def accept_heading(am, fragment)
|
118
|
+
@res << Flow::H.new(fragment.head_level, convert_flow(am.flow(fragment.txt)))
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def on_tags(res, item)
|
124
|
+
attr_mask = item.turn_on
|
125
|
+
return if attr_mask.zero?
|
126
|
+
|
127
|
+
@attr_tags.each do |tag|
|
128
|
+
if attr_mask & tag.bit != 0
|
129
|
+
res << annotate(tag.on)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def off_tags(res, item)
|
135
|
+
attr_mask = item.turn_off
|
136
|
+
return if attr_mask.zero?
|
137
|
+
|
138
|
+
@attr_tags.reverse_each do |tag|
|
139
|
+
if attr_mask & tag.bit != 0
|
140
|
+
res << annotate(tag.off)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def convert_flow(flow)
|
146
|
+
res = ""
|
147
|
+
flow.each do |item|
|
148
|
+
case item
|
149
|
+
when String
|
150
|
+
res << convert_string(item)
|
151
|
+
when AttrChanger
|
152
|
+
off_tags(res, item)
|
153
|
+
on_tags(res, item)
|
154
|
+
when Special
|
155
|
+
res << convert_special(item)
|
156
|
+
else
|
157
|
+
raise "Unknown flow element: #{item.inspect}"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
res
|
161
|
+
end
|
162
|
+
|
163
|
+
def convert_string(item)
|
164
|
+
CGI.escapeHTML(item)
|
165
|
+
end
|
166
|
+
|
167
|
+
def convert_special(special)
|
168
|
+
handled = false
|
169
|
+
Attribute.each_name_of(special.type) do |name|
|
170
|
+
method_name = "handle_special_#{name}"
|
171
|
+
if self.respond_to? method_name
|
172
|
+
special.text = send(method_name, special)
|
173
|
+
handled = true
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
raise "Unhandled special: #{special}" unless handled
|
178
|
+
|
179
|
+
special.text
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|