diff --git a/README.md b/README.md index 2268fdb..ea9cc54 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -#Markdown-Include +# Markdown-Include This is an extension to [Python-Markdown](https://pythonhosted.org/Markdown/) which provides an "include" function, similar to that found in @@ -6,13 +6,13 @@ LaTeX (and also the C pre-processor and Fortran). I originally wrote it for my [FORD](https://github.com/cmacmackin/ford) Fortran auto-documentation generator. -##Installation +## Installation This module can now be installed using ``pip``. pip install markdown-include -##Usage +## Usage This module can be used in a program in the following way: ```python @@ -34,7 +34,26 @@ Markdown is being called. If you would like to change the directory relative to which paths are evaluated, then this can be done by specifying the extension setting ``base_path``. +## Configuration +The following settings can be specified when initialising the plugin. + +- __base_path__: Default location from which to evaluate relative + paths for the include statement. (Default: the run-directory.) +- __encoding__: Encoding of the files used by the include statement. (Default: utf-8.) +- __inheritHeadingDepth__ : If true, increases headings on include + file by amount of previous heading. Combiens with headingOffset + option, below. (Default: False.) +- __headingOffset__: Increases heading depth by a specific ammount, in + addition to the inheritHeadingDepth Option. (Default: 0) +- __throwException__: When true, if the extension is unable to find an + included file it will throw an exception which the user can + catch. If false (default), a warning will be printed and Markdown + will continue parsing the file. + +## Examples + +An example of setting the base path and file encoding is given below: ```python import markdown from markdown_include.include import MarkdownInclude @@ -46,18 +65,69 @@ markdown_include = MarkdownInclude( html = markdown.markdown(source, extensions=[markdown_include]) ``` -##ChangeLog -###Version 0.5.1 +Included files can inherit the heading depth of the location +``inheritHeadingDepth``, as well as receive a specific offset, ``headingOffset`` +For example, consider the files +```markdown +Source file +# Heading Level 1 of main file + +{!included_file.md!} + +## Heading Level 2 of main file + +{!included_file.md!} +``` + +and included_file.md + +```markdown +# This heading will be one level deeper from the previous heading +More included file content. +End of included content. +``` +Then running the script +```python +import markdown +from markdown_include.include import MarkdownInclude + +# Markdown Extensions +markdown_include = MarkdownInclude( + configs={'inheritHeadingDepth':True} +) +html = markdown.markdown(source, extensions=[markdown_include]) +``` +produces +```html +
Source file
+More included file content.
+End of included content.
+More included file content.
+End of included content.
+``` + + +## ChangeLog +### Version 0.6.0 +- Added ability ot offset headers in the included file so they fall under the header level in which the include occurs +- Add option to throw exception when can't find an include file (instead of printing a warning) +- Fixed stripping of last character in file, so only occurs if it is a new-line +- Some behind-the-scenes improvement to code and documentation +### Version 0.5.1 Bugfix for a syntax error. -###Version 0.5 +### Version 0.5 Corrected some errors in documentation and merged in commits of [diegobz](https://github.com/diegobz) to add support for encoding and tidy up the source code. -###Version 0.4 +### Version 0.4 Fixed problem related to passing configurations to the extension. -###Version 0.3 +### Version 0.3 Added support for Python 3. -###Version 0.2 +### Version 0.2 Changed the API to be less likely to conflict with other syntax. -###Version 0.1 +### Version 0.1 Initial release. diff --git a/markdown_include/include.py b/markdown_include/include.py index 0743beb..5463cd5 100644 --- a/markdown_include/include.py +++ b/markdown_include/include.py @@ -30,6 +30,7 @@ from markdown.preprocessors import Preprocessor INC_SYNTAX = re.compile(r'\{!\s*(.+?)\s*!\}') +HEADING_SYNTAX = re.compile( '^#+' ) class MarkdownInclude(Extension): @@ -38,15 +39,23 @@ def __init__(self, configs={}): 'base_path': ['.', 'Default location from which to evaluate ' \ 'relative paths for the include statement.'], 'encoding': ['utf-8', 'Encoding of the files used by the include ' \ - 'statement.'] + 'statement.'], + 'inheritHeadingDepth': [False, 'Increases headings on included ' \ + 'file by amount of previous heading (combines with '\ + 'headingOffset option).'], + 'headingOffset': [0, 'Increases heading depth by a specific ' \ + 'amount (and the inheritHeadingDepth option). Defaults to 0.'], + 'throwException': [False, 'When true, if the extension is unable '\ + 'to find an included file it will throw an '\ + 'exception which the user can catch. If false '\ + '(default), a warning will be printed and '\ + 'Markdown will continue parsing the file.'] } for key, value in configs.items(): self.setConfig(key, value) def extendMarkdown(self, md, md_globals): - md.preprocessors.add( - 'include', IncludePreprocessor(md,self.getConfigs()),'_begin' - ) + md.preprocessors.register(IncludePreprocessor(md,self.getConfigs()), 'include', 101) class IncludePreprocessor(Preprocessor): @@ -62,12 +71,15 @@ def __init__(self, md, config): super(IncludePreprocessor, self).__init__(md) self.base_path = config['base_path'] self.encoding = config['encoding'] + self.inheritHeadingDepth = config['inheritHeadingDepth'] + self.headingOffset = config['headingOffset'] + self.throwException = config['throwException'] def run(self, lines): done = False + bonusHeading = '' while not done: - for line in lines: - loc = lines.index(line) + for loc, line in enumerate(lines): m = INC_SYNTAX.search(line) if m: @@ -80,20 +92,42 @@ def run(self, lines): try: with open(filename, 'r', encoding=self.encoding) as r: text = r.readlines() + except Exception as e: - print('Warning: could not find file {}. Ignoring ' - 'include statement. Error: {}'.format(filename, e)) - lines[loc] = INC_SYNTAX.sub('',line) - break + if not self.throwException: + print('Warning: could not find file {}. Ignoring ' + 'include statement. Error: {}'.format(filename, e)) + lines[loc] = INC_SYNTAX.sub('',line) + break + else: + raise e - line_split = INC_SYNTAX.split(line,maxsplit=0) - if len(text) == 0: text.append('') + line_split = INC_SYNTAX.split(line) + if len(text) == 0: + text.append('') for i in range(len(text)): - text[i] = text[i][0:-1] + # Strip the newline, and optionally increase header depth + if self.inheritHeadingDepth or self.headingOffset: + if HEADING_SYNTAX.search(text[i]): + text[i] = text[i].rstrip('\r\n') + if self.inheritHeadingDepth: + text[i] = bonusHeading + text[i] + if self.headingOffset: + text[i] = '#' * self.headingOffset + text[i] + else: + text[i] = text[i].rstrip('\r\n') + text[0] = line_split[0] + text[0] text[-1] = text[-1] + line_split[2] lines = lines[:loc] + text + lines[loc+1:] break + + else: + h = HEADING_SYNTAX.search(line) + if h: + headingDepth = len(h.group(0)) + bonusHeading = '#' * headingDepth + else: done = True return lines diff --git a/setup.py b/setup.py index c8b7a06..47ef312 100644 --- a/setup.py +++ b/setup.py @@ -11,13 +11,13 @@ setup( name = 'markdown-include', packages = find_packages(), - version = '0.5.1', + version = '0.6.0', description = 'This is an extension to Python-Markdown which provides an "include" function, similar to that found in LaTeX (and also the C pre-processor and Fortran). I originally wrote it for my FORD Fortran auto-documentation generator.', long_description = long_description, author = 'Chris MacMackin', author_email = 'cmacmackin@gmail.com', url = 'https://github.com/cmacmackin/markdown-include/', - download_url = 'https://github.com/cmacmackin/markdown-include/tarball/v0.5.1', + download_url = 'https://github.com/cmacmackin/markdown-include/tarball/v0.6.0', keywords = ['Markdown', 'typesetting', 'include', 'plugin', 'extension'], classifiers=[ # How mature is this project? Common values are