', pre) + html = html.replace('
', post) + html = html.replace('', post+bfit_pre) + html = html.replace('', post+pre) + html = html.replace('', post+it_pre) + html = html.replace('', post+pre) + html = html.replace('', post+bf_pre) + html = html.replace('', post+pre) + + # xml cleanup + while pre+post in html: + html = html.replace(pre+post,'') + + # convert to a rich text paragraph + par = RichText() + par.xml = html + if len(html) == 0: + print(md_paragraph) + return par + +def novel_parser(source_file, context = None): + if not context: + context = {'author_address': 'Street\nTown, State ZIP\nCountry', + 'author_email': 'name@email.com', + 'author_phone': 'PhoneNumber(s)', + 'author_website': 'https://www.author.com'} + context['chapters'] = [] + + wc = 0 + chapter = Chapter('') + for line in source_file: + if line.startswith(TITLE_MARKER): + title = line[len(TITLE_MARKER):].strip('()\n') + context['project_title'] = title + wc += count_words(title) + elif line.startswith(AUTHOR_MARKER): + author_name = line[len(AUTHOR_MARKER):].strip('()\n') + if 'author_name' not in context: + context['author_name'] = author_name + context['penname'] = author_name + elif line.startswith(CHAPTER_MARKER): + if chapter.heading or chapter.paragraphs: + context['chapters'].append(chapter) + chapter = Chapter(line[len(CHAPTER_MARKER):].strip('()\n')) + wc += count_words(chapter.heading) + elif line.startswith(STATUS_MARKER) or line.startswith(ACT_MARKER) or line.startswith(COMMENT_MARKER): + pass + else: + stripped = line.strip() + if stripped: + wc += count_words(stripped) + chapter.paragraphs.append(md_re_parser(stripped)) + context['chapters'].append(chapter) + + source_file.close() + + context['wc_1000'] = f'{(wc//1000)*1000:,}' + + if 'header' not in context: + context['header'] = context['author_name'].split()[-1] + ' - ' + context['project_title'] + ' - ' + + return context + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + 'markdown_file', + type=argparse.FileType('r'), + help='The markdown file for the novel, main file if a multi-file novel', + ) + parser.add_argument( + '-pp', + action='store_true', + help='run markdown pre-processor, this allows for a multi-file input (e.g. each chapter in its own file), but requires the MarkdownPP python library', + ) + parser.add_argument( + '--settings', + '-s', + type=argparse.FileType('r'), + help='setting json file', + ) + parser.add_argument( + '--template', + '-t', + type=argparse.FileType('r'), + help='template docx file', + ) + parser.add_argument( + '--output', + '-o', + type=argparse.FileType('w'), + help='output docx file', + ) + arguments = parser.parse_args() + + arguments.template.close() + doc = DocxTemplate(arguments.template.name) + if arguments.pp: + mdfile = tempfile.TemporaryFile(mode='w+') + MarkdownPP.MarkdownPP( + input=arguments.markdown_file, output=mdfile, modules=list(MarkdownPP.modules) + ) + mdfile.seek(0) + else: + mdfile = arguments.markdown_file + if arguments.settings: + context = json.load(arguments.settings) + else: + context = None + context = novel_parser(mdfile, context = context) + doc.render(context) + arguments.output.close() + doc.save(arguments.output.name) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/novel_compiler/settings.json b/novel_compiler/settings.json new file mode 100644 index 0000000..908ec34 --- /dev/null +++ b/novel_compiler/settings.json @@ -0,0 +1,6 @@ +{ +"author_address": "Address", +"author_email": "Email", +"author_phone": "Phone number", +"author_website": "Website" +} \ No newline at end of file diff --git a/novel_compiler/template.docx b/novel_compiler/template.docx new file mode 100644 index 0000000..801e5e5 Binary files /dev/null and b/novel_compiler/template.docx differ