#!/usr/bin/python3 # # Script to take the master document and ancillary files and create the # finished manual/website. # # by James Hammons # (C) 2017 Underground Software # # Remnants (could go into the master document as the first header) #bootstrap_path: /bootstrap-3.3.7 #page_title: The Ardour Manual import os import re import shutil import argparse # Global vars # This matches all *non* letter/number, ' ', '.', '-', and '_' chars cleanString = re.compile(r'[^a-zA-Z0-9 \._-]+') # This matches new 'unbreakable' links, up to the closing quote or anchor findLinks = re.compile(r'"@@[^#"]*[#"]') githuburl = 'https://github.com/Ardour/manual/edit/master/include/' # # Create an all lowercase filename without special characters and with spaces # replaced with dashes. # def MakeFilename(s): global cleanString # Clean up the file name, removing all non letter/number or " .-_" chars. # Also, convert to lower case and replace all spaces with dashes. fn = cleanString.sub('', s).lower().replace(' ', '-') # Double dashes can creep in from the above replacement, so we check for # that here. fn = fn.replace('--', '-') return fn # # Parse headers into a dictionary # def ParseHeader(fileObj): header = {} while (True): hdrLine = fileObj.readline().rstrip('\r\n') # Break out of the loop if we hit the end of header marker if hdrLine.startswith('---'): break # Check to see that we have a well-formed header construct match = re.findall(': ', hdrLine) if match: # Parse out foo: bar pairs & put into header dictionary a = re.split(': ', hdrLine, 1) header[a[0]] = a[1] return header # # Turn a "part" name into an int # def PartToLevel(s): level = -1 if s == 'part': level = 0 elif s == 'chapter': level = 1 elif s == 'subchapter': level = 2 elif s == 'section': level = 3 elif s == 'subsection': level = 4 return level # # Converts a integer to a roman number # def num2roman(num): num_map = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')] roman = '' while num > 0: for i, r in num_map: while num >= i: roman += r num -= i return roman # # Capture the master document's structure (and content, if any) in a list # def GetFileStructure(): fs = [] fnames = [None]*6 content = '' grab = False mf = open('master-doc.txt') for ln in mf: if ln.startswith('---'): # First, stuff any content that we may have read into the current # header's dictionary if grab: fs[-1]['content'] = content grab = False content = '' # Then, get the new header and do things to it hdr = ParseHeader(mf) level = PartToLevel(hdr['part']) hdr['level'] = level fnames[level] = MakeFilename(hdr['title']) # Ickyness--user specified URIs if 'uri' in hdr: hdr['filename'] = hdr['uri'] else: fullName = '' for i in range(level + 1): fullName = fullName + fnames[i] + '/' # Strip trailing '/' on filename hdr['filename'] = fullName[:-1] fs.append(hdr) if ('include' not in hdr) and (level > 0): grab = True else: if grab: content = content + ln # Catch the last file, since it would be missed above if grab: fs[-1]['content'] = content mf.close() return fs # # Determine if a particular node has child nodes # def HaveChildren(fs, pos): # If we're at the end of the list, there can be no children if pos == len(fs) - 1: return False # If the next node is at a lower level than the current node, we have # children. if fs[pos]['level'] < fs[pos + 1]['level']: return True # Otherwise, no children at this node. return False # # Get the children at this level, and return them in a list # def GetChildren(fs, pos): children = [] pos = pos + 1 childLevel = fs[pos]['level'] while fs[pos]['level'] >= childLevel: if fs[pos]['level'] == childLevel: children.append(pos) pos = pos + 1 # Sanity check if pos == len(fs): break return children # # Get the parent at this level # def GetParent(fs, pos): thisLevel = fs[pos]['level'] pos = pos - 1 while pos >= 0 and fs[pos]['level'] >= thisLevel: pos = pos - 1 return pos # # Creates the BreadCrumbs # def GetBreadCrumbs(fs, pos): # The > is for Bootstrap pre-3.0 breadcrumbs = '
Ch. ' + str(levelNums[level]) + ': ' + header['title'] + '
\n' oph = '