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

@mikehaertl mikehaertl 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

@bretweinraub bretweinraub 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

@ismangil ismangil 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