|
2 | 2 | # -*- coding: utf-8 -*- |
3 | 3 | # |
4 | 4 | # include.py |
5 | | -# |
| 5 | +# |
6 | 6 | # Copyright 2015 Christopher MacMackin <cmacmackin@gmail.com> |
7 | | -# |
| 7 | +# |
8 | 8 | # This program is free software; you can redistribute it and/or modify |
9 | 9 | # it under the terms of the GNU General Public License as published by |
10 | 10 | # the Free Software Foundation; either version 2 of the License, or |
11 | 11 | # (at your option) any later version. |
12 | | -# |
| 12 | +# |
13 | 13 | # This program is distributed in the hope that it will be useful, |
14 | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | 16 | # GNU General Public License for more details. |
17 | | -# |
| 17 | +# |
18 | 18 | # You should have received a copy of the GNU General Public License |
19 | 19 | # along with this program; if not, write to the Free Software |
20 | 20 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, |
21 | 21 | # MA 02110-1301, USA. |
22 | | -# |
23 | | -# |
24 | | - |
25 | | - |
| 22 | +# |
| 23 | +# |
26 | 24 |
|
27 | 25 | from __future__ import print_function |
28 | | -from markdown.extensions import Extension |
29 | | -from markdown.preprocessors import Preprocessor |
30 | 26 | import re |
31 | 27 | import os.path |
| 28 | +from codecs import open |
| 29 | +from markdown.extensions import Extension |
| 30 | +from markdown.preprocessors import Preprocessor |
32 | 31 |
|
33 | 32 | INC_SYNTAX = re.compile(r'\{!\s*(.+?)\s*!\}') |
34 | 33 |
|
35 | 34 |
|
36 | 35 | class MarkdownInclude(Extension): |
37 | 36 | def __init__(self, configs=[]): |
38 | | - self.config = {'base_path': ['.', 'Location from which to evaluate relative paths for the include statement.'],} |
| 37 | + self.config = { |
| 38 | + 'base_path': ['.', 'Default location from which to evaluate ' \ |
| 39 | + 'relative paths for the include statement.'], |
| 40 | + 'encoding': ['utf-8', 'Encoding of the files used by the include ' \ |
| 41 | + 'statement.'] |
| 42 | + } |
39 | 43 | for key, value in configs.items(): |
40 | 44 | self.setConfig(key, value) |
41 | | - |
| 45 | + |
42 | 46 | def extendMarkdown(self, md, md_globals): |
43 | | - md.preprocessors.add('include', IncludePreprocessor(md,self.getConfigs()),'_begin') |
44 | | - |
| 47 | + md.preprocessors.add( |
| 48 | + 'include', IncludePreprocessor(md,self.getConfigs()),'_begin' |
| 49 | + ) |
45 | 50 |
|
46 | 51 |
|
47 | 52 | class IncludePreprocessor(Preprocessor): |
48 | 53 | ''' |
49 | 54 | This provides an "include" function for Markdown, similar to that found in |
50 | | - LaTeX (also the C pre-processor and Fortran). The syntax is {{filename}}, |
| 55 | + LaTeX (also the C pre-processor and Fortran). The syntax is {!filename!}, |
51 | 56 | which will be replaced by the contents of filename. Any such statements in |
52 | 57 | filename will also be replaced. This replacement is done prior to any other |
53 | 58 | Markdown processing. All file-names are evaluated relative to the location |
54 | 59 | from which Markdown is being called. |
55 | 60 | ''' |
56 | | - def __init__(self,md,config): |
| 61 | + def __init__(self, md, config): |
57 | 62 | super(IncludePreprocessor, self).__init__(md) |
58 | 63 | self.base_path = config['base_path'] |
59 | | - |
| 64 | + self.encoding = config['encoding'] |
| 65 | + |
60 | 66 | def run(self, lines): |
61 | 67 | done = False |
62 | | - |
63 | 68 | while not done: |
64 | 69 | for line in lines: |
65 | 70 | loc = lines.index(line) |
66 | 71 | m = INC_SYNTAX.search(line) |
67 | | - |
| 72 | + |
68 | 73 | if m: |
69 | 74 | filename = m.group(1) |
70 | 75 | filename = os.path.expanduser(filename) |
71 | 76 | if not os.path.isabs(filename): |
72 | | - filename = os.path.normpath(os.path.join(self.base_path,filename)) |
| 77 | + filename = os.path.normpath( |
| 78 | + os.path.join(self.base_path,filename) |
| 79 | + ) |
73 | 80 | try: |
74 | | - with open(filename, 'r') as r: |
| 81 | + with open(filename, 'r', encoding=self.encoding) as r: |
75 | 82 | text = r.readlines() |
76 | | - except: |
77 | | - print('Warning: could not find file {}. Ignoring include statement.'.format(filename)) |
| 83 | + except Exception, e: |
| 84 | + print('Warning: could not find file {}. Ignoring ' |
| 85 | + 'include statement. Error: {}'.format(filename, e)) |
78 | 86 | lines[loc] = INC_SYNTAX.sub('',line) |
79 | | - |
80 | 87 | break |
81 | | - |
| 88 | + |
82 | 89 | line_split = INC_SYNTAX.split(line,maxsplit=0) |
83 | 90 | if len(text) == 0: text.append('') |
84 | 91 | for i in range(len(text)): |
85 | 92 | text[i] = text[i][0:-1] |
86 | | - text[0] = line_split[0] + text[0] |
| 93 | + text[0] = line_split[0] + text[0] |
87 | 94 | text[-1] = text[-1] + line_split[2] |
88 | 95 | lines = lines[:loc] + text + lines[loc+1:] |
89 | 96 | break |
90 | | - |
91 | 97 | else: |
92 | 98 | done = True |
93 | | - |
94 | 99 | return lines |
95 | 100 |
|
96 | 101 |
|
97 | | - |
98 | 102 | def makeExtension(*args,**kwargs): |
99 | 103 | return MarkdownInclude(kwargs) |
0 commit comments