The End | Top | Appendices and Ephemera |
This just in
I’m using this setup for a book I’m trying to write about software development (surprise!). I’m having to change some things in the setup and script, and as I notice important ones, I’ll add a note here in the “This just in” section.
In the book, I’m using two levels of outline (so far), so I have some Markdown headers with just one pound sign, and some with two. And I wanted the table of contents to reflect that, using an outline structure that looks like this:
The indented bits are done, in Markdown, by putting four spaces for each level, before the asterisk that means list item. My table of contents maker wasn’t that clever, so I added some logic to strip pound signs differently, save the leading ones, and convert them to spaces at the last minute. I also needed to change the way the top of page / bottom of page links were parsed.
The resulting code is here:
#!/usr/bin/ruby
#!/Users/ron/.rvm/rubies/ruby-2.3.0/bin/ruby
require 'tempfile'
require 'fileutils'
SPLIT_MARKER = "----\n\n"
TOC_MARKER = "<!--TOC-->\n"
SCRIPT_FILE = "/Users/ron/Dropbox/bin/splitter"
TAB = ' '
Titles = {}
def add_toc(chunk)
halves = chunk.split(TOC_MARKER)
puts "halves length %d" % halves.length
return chunk if halves.length != 2
return halves[0] + table_of_contents + halves[1]
end
def make_file_name(filenumber)
return "index.md" if filenumber == 0
return sprintf("%02d.md", filenumber)
end
def make_link_line(filenumber, max_length)
link = ""
link += "[%s](%02d.html) | " % [trim_left(Titles[filenumber - 1]), filenumber - 1] unless filenumber == 0
link += "[Top](index.html) | "
link += "[%s](%02d.html)" % [trim_left(Titles[filenumber + 1]), filenumber + 1] unless filenumber >= max_length
return link
end
def record_titles(chunks)
filenumber = 0
chunks.each do | chunk |
title = chunk.split("\n")[0].strip # remove any spaces
Titles[filenumber] = trim_right(title) # remove trailing stuff
filenumber += 1
end
end
def trim_full(string)
trim_left(trim_right(string))
end
def trim_right(string)
string.gsub(/ *#*$/, '')
end
def trim_left(string)
string.gsub(/^#* */, '')
end
def table_of_contents
toc = ""
Titles.each_pair do | number, title |
# looks like: ### title
pounds, *rest = title.split(' ')
the_title = rest.join(' ')
tabs = pounds.gsub(/#/, ' ')
tabs = tabs[4..-1] # remove one set
toc += "%s* [%s](%s)\n" % [tabs, the_title, make_file_name(number)]
end
return toc
end
def update_table_of_contents(chunks)
toc_chunk = chunks.delete_at(0)
updated_toc = add_toc(toc_chunk)
chunks.insert(0, updated_toc)
end
def write_file(chunk, reference_chunk, filenumber, max_length)
filename = make_file_name(filenumber)
title = Titles[filenumber]
puts filename + ": " + title
tf = File.new(filename, "w")
tf.puts make_link_line(filenumber, max_length)
tf.puts
tf.print chunk
tf.puts
tf.puts
tf.puts make_link_line(filenumber, max_length)
tf.puts
tf.puts
tf.print reference_chunk
tf.puts
tf.puts
tf.close
end
def write_files(chunks, reference_chunk)
filenumber = 0
chunks.each do |chunk|
write_file(chunk, reference_chunk, filenumber, chunks.length - 1) unless chunk.length < 1
filenumber += 1
end
end
ARGF.set_encoding(Encoding::UTF_8)
input = ARGF.read
chunks = input.split(SPLIT_MARKER)
reference_chunk = chunks.delete_at(-1)
record_titles(chunks)
update_table_of_contents(chunks)
write_files(chunks, reference_chunk)
FileUtils.cp(SCRIPT_FILE, ".")
I expect that I may go to more than two levels, and I think the above code will handle that.
At present, the splitter only looks for table of contents headings right after a page separator. I can imagine that it might need to be changed to search for all headings in the whole document. We’ll see.
Stay tuned for any other important changes!
The End | Top | Appendices and Ephemera |