#!/usr/bin/env ruby # ----------------------------------------------------------------- # # Simple ruby script to traverse wow folder for all macros and create a markdown document # from the results. # # USAGE: # ruby ./macros_to_md.rb [server filter] # # e.g. $ ruby ./macros_to_md.rb atiesh # ----------------------------------------------------------------- # require 'digest' require 'find' # ----------------------------------------------------------------- # # HELPER METHODS # # Create section header for each Character macro set. def section(file) parts = file.split("/") parts.pop section = "#{parts[-2]}/#{parts.last}" section = "Account wide" if section.start_with?("Account") section end def toc_elements(header) anchor = header.downcase.gsub('/', '').gsub(' ', '') "1. [#{header}](##{anchor})" end # Format title for each macro. def title(line, contents, i) "#### #{title_string(line, contents, i)}" end # Try real hard to figure out a good title for each macro. def title_string(line, contents, i) # Handle if there's no "#show..." in the macro. if line.start_with?("/") return title_from_ver(contents[i-1]) end # Handle if there's only "#show..." and no value to set to it, e.g. "#show" # vs. "#show Spell Name" if line.split(" ").length == 1 return title_from_ver(contents[i-1]) end # Parse the title from the "#show..." line, using the value set. line.gsub(/^#show[a-z]* /, '') end # Worse case, pull the macro title from the macro "name" inside # the version string. def title_from_ver(line) title = line.split('"')[1] # This is dumb, I used to use "." as the name of all my macros, I've stopped # doing that, but still, there a few that remain. As such, I'm going to need # to solve for that. if title == "." title = [ "TODO: Name this macro.", "> This is dumb, I used to use `.` as the name of all my macros, I've stopped", "> doing that, but still, there a few that remain." ].join("\n") end title end # / HELPER METHODS # ----------------------------------------------------------------- # # Read the directory we should start in from the first command line arg. start = ARGV[0] # Error if we don't have a directory to start from. abort "ERROR: A valid input directory path is required for the first arg." unless File.directory?(start) # Read server filter from the second command line arg, if present. filter = ARGV[1] || nil # Define the output file name. name = "macro_dump.md" # Traverse the source directory and find all "macros-cache.txt" files. files = Find.find(start) .select { |i| i.end_with?("macros-cache.txt") } .sort_by(&:length) # Set up header to be added to the beginning of the output, after we've parsed # and built the TOC nav. output = [ "# Macro Dump: #{Time.now.to_s}", "", "> Note: This file is generated and macro titles are calculated as best as possible with data from input.", "> This is also just a current snapshot, there's no guarantees that all of these macros work. =P", "", "## TOC" ] # Placeholder to build the TOC nav. headers = [] # Set up output buffer with top level display text. buffer = [] # Iterate of each file. files.each do |file| # Set the section header section = section(file) # Use the section header in conjunction with the filter string # to determine if this macro file should be included. next if filter && section != "Account wide" && \ !file.downcase.include?(filter.downcase) # Add section to headers for TOC headers << section # Write section to output buffer. buffer << "## #{section}" # Read the file (cleanly) from disk. contents = File.open(file).readlines.map(&:strip) # Set up position holders for parsing the file. in_macro = false has_title = false # Iterate over the file. contents.each_with_index do |line, i| # Ignore comments (not sure if this is a good idea or not.) next if line.start_with?("--") # Check for "VER" line indicating the start of a macro and if so, # move on to the next line, as we now know we're parsing a macro. if line.start_with?("VER") # Ignore the macro entry if it's empty. in_macro = true unless contents[i+1].start_with?("END") next end # If we're at the end of the macro, handle that by closing the code # block and mark as done parsing the macro. if in_macro && line.start_with?("END") buffer << "```\n" in_macro = false has_title = false end # If we're not in a macro and none of the above have been activated, # the line is empty or something we should be ignoring. As such, # we're going to just move on to the next line. next unless in_macro # If we've reached this point and have not marked ourselves has having # a title, it's safe to assume that we should use this line to set the # title. unless has_title buffer.concat([ title(line, contents, i), "```", line ]) has_title = true next end # If we've reached this point, then this line is part of the macro, so # add it to the output buffer. buffer << line end end # Put together the header, toc elements and output in to a single output. ## Add formatted toc elements headers.each do |h| output << toc_elements(h) end output << "" ## Add a little spacing format before the body. ## Add the body of the doc. output.concat(buffer) # Print out what file we're writing to. puts "Writing: #{name}" # Write the buffer to a file. File.write(name, output.join("\n"))