Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Convert Trac Wiki to Markdown
#!/usr/bin/env ruby
# Convert Trac DB Wiki pages to Markdown source files
# This script is based on http://github.com/seven1m/trac_wiki_to_github which
# converted all pages from a Trac DB to GitHub Wiki format (as Textile).
#
# I made two changes:
# - uses MarkDown format instead
# - uses the sqllite3-ruby gem which does not need Ruby 1.9
#
TRAC_DB_PATH = 'trac.db'
OUT_PATH = 'wiki'
GITHUB_WIKI_URL = '/somebox/myproject/wikis/'
require 'rubygems'
gem 'sqlite3-ruby'
require 'sqlite3'
db = SQLite3::Database.new(TRAC_DB_PATH)
pages = db.execute('select name, text from wiki w2 where version = (select max(version) from wiki where name = w2.name);')
pages.each do |title, body|
File.open(File.join(OUT_PATH, title.gsub(/\s/, '')+'.md'), 'w') do |file|
body.gsub!(/\{\{\{([^\n]+?)\}\}\}/, '`\1`')
body.gsub!(/\{\{\{(.+?)\}\}\}/m){|m| m.each_line.map{|x| "\t#{x}".gsub(/[\{\}]{3}/,'')}.join}
body.gsub!(/\=\=\=\=\s(.+?)\s\=\=\=\=/, '### \1')
body.gsub!(/\=\=\=\s(.+?)\s\=\=\=/, '## \1')
body.gsub!(/\=\=\s(.+?)\s\=\=/, '# \1')
body.gsub!(/\=\s(.+?)\s\=[\s\n]*/, '')
body.gsub!(/\[(http[^\s\[\]]+)\s([^\[\]]+)\]/, '[\2](\1)')
body.gsub!(/\!(([A-Z][a-z0-9]+){2,})/, '\1')
body.gsub!(/'''(.+)'''/, '*\1*')
body.gsub!(/''(.+)''/, '_\1_')
body.gsub!(/^\s\*/, '*')
body.gsub!(/^\s\d\./, '1.')
file.write(body)
end
end
@mikehaertl

This comment has been minimized.

Copy link

commented Mar 12, 2016

Great, thanks. I've modified the code a little to fix some markup issues and to also convert tables. I'm by no means a ruby expert, so don't expect elegant code ;).

    row["description"].gsub!(/\{\{\{([^\n]+?)\}\}\}/, '`\1`')
    row["description"].gsub!(/'''(.+?)'''/, '**\1**')
    row["description"].gsub!(/''(.+?)''/, '*\1*')
    row["description"].gsub!(/((^\|\|[^\n\r]+\|\|[ \t]*\r?(\n|$))+)/m) do |m|
        m = m.each_line.map do |x|
            x.gsub(/\t/, ' ')
            .gsub(/(\|\|){2,}/){|k| k.gsub(/\|\|/, '||   ')}
            .gsub(/ {3,}/, '   ')
        end.join
        lines = m.each_line.to_a
        line1 = lines.shift
        line2 = line1.dup.gsub(/[^\n\r\|]/, '-')
        lines.unshift(line1, line2)
        c = lines.join
        c = c.each_line.map do |x|
            x.gsub(/\=\s?(.+?)\s?=/, ' \1 ')
            .gsub(/\|\|/, '|')
        end.join
    end
    row["description"].gsub!(/^\{\{\{(.+?)^\}\}\}/m, '```\1```')
    row["description"].gsub!(/\=\=\=\=\s(.+?)\s\=\=\=\=/, '### \1')
    row["description"].gsub!(/\=\=\=\s(.+?)\s\=\=\=/, '## \1')
    row["description"].gsub!(/\=\=\s(.+?)\s\=\=/, '# \1')
    row["description"].gsub!(/\=\s(.+?)\s\=[\s\n]*/, '')
    row["description"].gsub!(/\[(http[^\s\[\]]+)\s([^\[\]]+)\]/, '[\2](\1)')
    row["description"].gsub!(/\!(([A-Z][a-z0-9]+){2,})/, '\1')
    row["description"].gsub!(/^\s\*/, '*')
    row["description"].gsub!(/^\s\d\./, '1.')
@bretweinraub

This comment has been minimized.

Copy link

commented Dec 6, 2017

I just wanted in a script [no access to the DB]:

class String
  def trac_to_markdown!
    gsub!(/\{\{\{([^\n]+?)\}\}\}/, '`\1`')
    gsub!(/\{\{\{(.+?)\}\}\}/m){|m| m.each_line.map{|x| "\t#{x}".gsub(/[\{\}]{3}/,'')}.join}
    gsub!(/\=\=\=\=\s(.+?)\s\=\=\=\=/, '### \1')
    gsub!(/\=\=\=\s(.+?)\s\=\=\=/, '## \1')
    gsub!(/\=\=\s(.+?)\s\=\=/, '# \1')
    gsub!(/\=\s(.+?)\s\=[\s\n]*/, '')
    gsub!(/\[(http[^\s\[\]]+)\s([^\[\]]+)\]/, '[\2](\1)')
    gsub!(/\!(([A-Z][a-z0-9]+){2,})/, '\1')
    gsub!(/'''(.+)'''/, '*\1*')
    gsub!(/''(.+)''/, '_\1_')
    gsub!(/^\s\*/, '*')
    gsub!(/^\s\d\./, '1.')

    gsub!(/\{\{\{([^\n]+?)\}\}\}/, '`\1`')
    gsub!(/'''(.+?)'''/, '**\1**')
    gsub!(/''(.+?)''/, '*\1*')
    gsub!(/((^\|\|[^\n\r]+\|\|[ \t]*\r?(\n|$))+)/m) do |m|
      m = m.each_line.map do |x|
        x.gsub(/\t/, ' ')
          .gsub(/(\|\|){2,}/){|k| k.gsub(/\|\|/, '||   ')}
        .gsub(/ {3,}/, '   ')
      end.join
      lines = m.each_line.to_a
      line1 = lines.shift
      line2 = line1.dup.gsub(/[^\n\r\|]/, '-')
      lines.unshift(line1, line2)
      c = lines.join
      c = c.each_line.map do |x|
        x.gsub(/\=\s?(.+?)\s?=/, ' \1 ')
          .gsub(/\|\|/, '|')
      end.join
    end
    gsub!(/^\{\{\{(.+?)^\}\}\}/m, '```\1```')
    gsub!(/\=\=\=\=\s(.+?)\s\=\=\=\=/, '### \1')
    gsub!(/\=\=\=\s(.+?)\s\=\=\=/, '## \1')
    gsub!(/\=\=\s(.+?)\s\=\=/, '# \1')
    gsub!(/\=\s(.+?)\s\=[\s\n]*/, '')
    gsub!(/\[(http[^\s\[\]]+)\s([^\[\]]+)\]/, '[\2](\1)')
    gsub!(/\!(([A-Z][a-z0-9]+){2,})/, '\1')
    gsub!(/^\s\*/, '*')
    gsub!(/^\s\d\./, '1.')
  end
end

some_trac = 'my document'

puts some_trac.trac_to_markdown!
@ismangil

This comment has been minimized.

Copy link

commented Mar 6, 2019

I'm trying to convert Trac milestone description to migrate to GitHub via REST API.

The conversion went well but I can't put the resulting string into json to send to rest API - unprocessable entity. How do I escapify the result?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.