| #!/usr/bin/env python |
| # Copyright 2015 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| |
| """Reads, parses, and (optionally) writes as HTML the contents of Markdown |
| files passed as arguments. Intended for rendering network stack documentation |
| stored as Markdown in the source tree to a human-readable format.""" |
| |
| |
| import argparse |
| import os.path |
| import sys |
| |
| |
| def nth_parent_directory(path, n): |
| for i in range(n): |
| path = os.path.dirname(path) |
| return path |
| |
| |
| # Go up the directory tree from this script and add src/third_party to sys.path |
| # so "import markdown" can find it in src/third_party/markdown. |
| SCRIPT_PATH = os.path.abspath(__file__) |
| SRC_PATH = nth_parent_directory(SCRIPT_PATH, 4) |
| THIRD_PARTY_PATH = os.path.join(SRC_PATH, 'third_party') |
| sys.path.insert(0, THIRD_PARTY_PATH) |
| import markdown |
| |
| |
| def ReadFile(filename): |
| with open(filename, 'r') as file: |
| return file.read() |
| |
| |
| def WriteFile(filename, contents): |
| dir = os.path.dirname(filename) |
| if not os.path.isdir(dir): |
| os.mkdir(dir) |
| with open(filename, 'w') as file: |
| file.write(contents) |
| |
| |
| TEMPLATE = """ |
| <html> |
| <head> |
| <title>{title}</title> |
| </head> |
| <body> |
| {body} |
| </body> |
| </html>""" |
| |
| |
| def FormatPage(markdown_html, title): |
| # TODO(juliatuttle): Add a navigation list / table of contents of available |
| # Markdown files, perhaps? |
| return TEMPLATE.format(title=title, body=markdown_html) |
| |
| |
| def ProcessDocs(input_filenames, input_pathname, output_pathname, |
| extensions=None): |
| """Processes a list of Markdown documentation files. |
| |
| If input_pathname and output_pathname are specified, outputs HTML files |
| into the corresponding subdirectories of output_pathname. If one or both is |
| not specified, simply ensures the files exist and contain valid Markdown. |
| |
| Args: |
| input_filenames: A list of filenames (absolute, or relative to $PWD) of |
| Markdown files to parse and possibly render. |
| input_pathname: The base directory of the input files. (Needed so they |
| can be placed in the same relative path in the output path.) |
| output_pathname: The output directory into which rendered Markdown files |
| go, using that relative path. |
| extensions: a list of Markdown.extensions to apply if any. |
| |
| Returns: |
| nothing |
| |
| Raises: |
| IOError: if any of the file operations fail (e.g. input_filenames |
| contains a non-existent file). |
| """ |
| |
| outputting = (input_pathname is not None) and (output_pathname is not None) |
| |
| if extensions: |
| markdown_parser = markdown.Markdown(extensions) |
| else: |
| markdown_parser = markdown.Markdown() |
| |
| for input_filename in input_filenames: |
| markdown_text = ReadFile(input_filename) |
| markdown_html = markdown_parser.reset().convert(markdown_text) |
| if not outputting: |
| continue |
| |
| full_html = FormatPage(markdown_html, title=input_filename) |
| rel_filename = os.path.relpath(input_filename, start=input_pathname) |
| output_filename = os.path.join(output_pathname, rel_filename) + '.html' |
| WriteFile(output_filename, full_html) |
| |
| |
| def main(): |
| parser = argparse.ArgumentParser( |
| description='Parse and render Markdown documentation') |
| parser.add_argument('--input_path', default=None, |
| help="Input path for Markdown; required only if output_path set") |
| parser.add_argument('--output_path', default=None, |
| help="Output path for rendered HTML; if unspecified, won't output") |
| parser.add_argument('filenames', nargs=argparse.REMAINDER) |
| args = parser.parse_args() |
| |
| extensions = ['markdown.extensions.def_list'] |
| ProcessDocs(args.filenames, args.input_path, args.output_path, extensions) |
| |
| return 0 |
| |
| |
| if __name__ == '__main__': |
| sys.exit(main()) |