1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
#!/usr/bin/ruby
# This file is part of html2trac.
# Copyright (C) 2008-2009 Dennis Schridde
#
# html2trac is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# html2trac is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with html2trac. If not, see <http://www.gnu.org/licenses/>.
require 'rexml/document'
module REXML
# Trac Wiki formatter
# Transforms XHTML 1.1 into Trac Wiki syntax
#
# This worked for Warzone 2100's ScriptingManual and likely has to be adapted to suit more generic needs.
# Do no forget to look at write_element()'s "skip" variable when adjusting it to your documents.
class Formatters::Trac < Formatters::Default
def initialize()
super()
@listtype = []
@listdepth = 0
@idmap = {}
end
def write( node, output )
case node
when Document
if node.xml_decl.encoding != "UTF-8" && !output.kind_of?(Output)
output = Output.new( output, node.xml_decl.encoding )
end
write_document( node, output )
when Element
write_element( node, output )
when Declaration, ElementDecl, NotationDecl, ExternalEntity, Entity,
Attribute, AttlistDecl
# Ignore
when Instruction
write_instruction( node, output )
when DocType, XMLDecl
# Ignore
when Comment
write_comment( node, output )
when CData
write_cdata( node, output )
when Text
write_text( node, output )
else
raise Exception.new("XML FORMATTING ERROR")
end
end
def write_cdata(node, output)
fail
end
def write_comment(node, output)
output << "\n{{{\n"
output << "#!\n"
output << node.to_s
output << "\n}}}\n"
end
def build_string(node)
result = ""
case node
when Text: result << node.to_s
when Element: node.children.each { |child| result << build_string(child) }
end
result
end
def write_document( node, output )
node.elements.each("//*[@id]") { |id| @idmap[id.attributes["id"]] = build_string(id).delete("(){}[]/+ ") }
node.children.each { |child| write( child, output ) }
end
def write_element(node, output)
begin_tag = ""
end_tag = ""
skip = nil # Set this for nodes you want to skip in your file
case node.name
when "html":
when "head": skip = true
when "body":
when "div": skip = node.elements["p/a[@href='top']"]
when "span":
when "pre": begin_tag = "\n{{{\n#!c\n" ; end_tag = "\n}}}\n"
when "table": begin_tag = "\n"
when "tr": begin_tag = "|" ; end_tag = "|\n"
when "td": begin_tag = "|" ; end_tag = "|"
when "th": begin_tag = "|'''" ; end_tag = "'''|"
when "p": begin_tag = "\n" ; end_tag = "\n"
when "h1": begin_tag = "\n= " ; end_tag = " =\n"
when "h2": begin_tag = "\n== " ; end_tag = " ==\n"
when "h3": begin_tag = "\n=== " ; end_tag = " ===\n"
when "h4": begin_tag = "\n==== " ; end_tag = " ====\n"
when "h5": begin_tag = "\n===== " ; end_tag = " =====\n"
when "b": begin_tag = "'''" ; end_tag = "'''"
when "i": begin_tag = "''" ; end_tag = "''"
when "u": begin_tag = "__" ; end_tag = "__"
when "br": begin_tag = "[[BR]]\n"
when "hr": begin_tag = "\n----\n"
when "dl": begin_tag = "\n"
when "dt": begin_tag = " " ; end_tag = "::\n"
when "dd": begin_tag = " " ; end_tag = "\n" if node.next_element
when "ol":
if node.elements["ancestor::table"]: # Trac does not support lists/linebreaks inside tables!
begin_tag = "[[BR]]"
else
begin_tag = "\n"
end
@listtype.push "ol"
@listdepth += 1
when "ul":
if node.elements["ancestor::table"]: # Trac does not support lists/linebreaks inside tables!
begin_tag = "[[BR]]"
else
begin_tag = "\n"
end
@listtype.push "ul"
@listdepth += 1
when "li":
case @listtype.last
when "ol":
if (@listdepth % 2) == 0: begin_tag = " " * @listdepth + "1. "
else begin_tag = " " * @listdepth + "a. "
end
when "ul": begin_tag = " " * @listdepth + "* "
end
if node.elements["ancestor::table"]: # Trac does not support lists/linebreaks inside tables!
end_tag = "[[BR]]"
elsif node.next_element:
end_tag = "\n"
end
when "a":
href = node.attributes["href"]
if href == "#top": skip = true end
if href[0,1] == "#":
id = href[1..-1]
begin_tag = "[#" + @idmap[id] + " "
else
begin_tag = "[" + href + " "
end
end_tag = "]"
when "acronym": begin_tag = "''" ; end_tag = "''" # Use italic style
when "code": begin_tag = "`" ; end_tag = "`"
else raise Exception.new("XHTML FORMATTING ERROR: Unexpected tag: " + node.name)
end
if node.children.empty?
output << begin_tag
else
output << begin_tag
node.children.each { |child|
write( child, output )
}
output << end_tag
end unless skip
case node.name
when "ol": @listtype.pop ; @listdepth -= 1
when "ul": @listtype.pop ; @listdepth -= 1
end
end
def write_instruction(node, output)
fail
end
def write_text( node, output )
text = node.to_s
if ["table", "tr", "dl", "ol", "ul"].include?(node.parent.name):
text.gsub!(/[[:space:]]+/, '')
elsif node.parent.name != "pre"
text.gsub!(/[[:space:]]+/, ' ')
end
output << Text::unnormalize(text)
end
end
end
xml = REXML::Document.new( STDIN )
REXML::Formatters::Trac.new.write(xml, STDOUT)
|