Skip to content
This repository has been archived by the owner on Nov 17, 2022. It is now read-only.

Adding support for sphinx-style directives on mdinclude #42

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions docs/example.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,37 +142,75 @@ The below is reST-style math-block.

### Include Markdown file

To include markdown file:
To include a markdown file:

```rest
.. mdinclude:: path-to-file.md
```

To include markdown file with specific lines:
To include a markdown file with a specific start and end line:

```rest
.. mdinclude:: included.md
:start-line: 2
:end-line: -2
```

Original ``included.md`` file is:
The original ``included.md`` file is:

.. include:: included.md
:code: md

This file included as:
This file is included as:

```md
#### Include this line
```

and results in HTML as below:
and the results in HTML are as shown below:

.. mdinclude:: included.md
:start-line: 2
:end-line: -2

To include a markdown file with specific line ranges:

```rest
.. mdinclude:: line_inclusion.md
:lines: 1, 3-4, 7-
```

The original ``line_inclusion.md`` file is:

.. include:: line_inclusion.md
:code: md

And the resulting HTML output is:

.. mdinclude:: line_inclusion.md
:lines: 1, 3-4, 7-


To include a markdown file by specific text:

```rest
.. mdinclude:: text_inclusion.md
:start-after: Start Here
:end-before: End Here
```

The original ``text_inclusion.md`` file is:

.. include:: text_inclusion.md
:code: md

And the resulting HTML output is:

.. mdinclude:: text_inclusion.md
:start-after: Start Here
:end-before: End Here


### Footnote

Footnote[^1] and footnote[^key] with markdown.
Expand Down
9 changes: 9 additions & 0 deletions docs/line_inclusion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#### Include
#### Skip
#### Include
#### Include
#### Skip
#### Skip
#### Include
#### Include
#### Include
14 changes: 14 additions & 0 deletions docs/text_inclusion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#### Skip
#### Skip

#### Start Here
#### Include

#### Include
#### Include
#### Include
#### End Here (Skip)

#### Skip
#### Skip
#### Skip
74 changes: 57 additions & 17 deletions m2r.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,17 @@ def parse_options():

class RestBlockGrammar(mistune.BlockGrammar):
directive = re.compile(
r'^( *\.\..*?)\n(?=\S)',
re.DOTALL | re.MULTILINE,
)
r'^( *\.\..*?)\n(?=\S)',
re.DOTALL | re.MULTILINE,
)
oneline_directive = re.compile(
r'^( *\.\..*?)$',
re.DOTALL | re.MULTILINE,
)
r'^( *\.\..*?)$',
re.DOTALL | re.MULTILINE,
)
rest_code_block = re.compile(
r'^::\s*$',
re.DOTALL | re.MULTILINE,
)
r'^::\s*$',
re.DOTALL | re.MULTILINE,
)


class RestBlockLexer(mistune.BlockLexer):
Expand Down Expand Up @@ -483,6 +483,7 @@ def footnotes(self, text):
return ''

"""Below outputs are for rst."""

def image_link(self, url, target, alt):
return '\n'.join([
'',
Expand Down Expand Up @@ -575,6 +576,9 @@ class MdInclude(rst.Directive):
option_spec = {
'start-line': int,
'end-line': int,
'lines': str,
'start-after': str,
'end-before': str,
}

def run(self):
Expand Down Expand Up @@ -614,19 +618,55 @@ def run(self):
raise self.severe('Problems with "%s" directive path:\n%s.' %
(self.name, ErrorString(error)))

# read from the file
startline = self.options.get('start-line', None)
endline = self.options.get('end-line', None)
# get all of the lines and reduce as needed
try:
if startline or (endline is not None):
lines = include_file.readlines()
rawtext = ''.join(lines[startline:endline])
else:
rawtext = include_file.read()
lines = include_file.readlines()
line_count = len(lines)
except UnicodeError as error:
raise self.severe('Problem with "%s" directive:\n%s' %
(self.name, ErrorString(error)))

# read from the file
start_line = self.options.get('start-line', 1) - 1
end_line = self.options.get('end-line', line_count)
line_ranges = self.options.get('lines', None)
start_marker = self.options.get('start-after', None)
end_marker = self.options.get('end-before', None)

if start_marker:
for i, line in enumerate(lines[start_line:end_line], start_line):
if start_marker in line:
if i > start_line:
start_line = i
break
if i == len(lines):
start_line = i

if end_marker:
for i, line in enumerate(lines[start_line:end_line], start_line):
if end_marker in line:
if i < end_line:
end_line = i
break

keep = set(range(start_line, end_line))

if line_ranges:
keep_line_ranges = set()
line_range_list = line_ranges.split(',')
for line_range in line_range_list:
endpoints = [int(number) if len(number) else len(lines)
for number in line_range.split('-', 1)]
if len(endpoints) > 1:
keep_line_ranges.update(
set(range(endpoints[0]-1, endpoints[1])))
else:
keep_line_ranges.add(endpoints[0]-1)
keep = keep.intersection(keep_line_ranges)

lines = [lines[i] for i in sorted(keep)]
rawtext = ''.join(lines)

config = self.state.document.settings.env.config
converter = M2R(
no_underscore_emphasis=config.no_underscore_emphasis,
Expand Down