diff --git a/docs/extensions/api.txt b/docs/extensions/api.txt
index 66daa8685..6812e55ad 100644
--- a/docs/extensions/api.txt
+++ b/docs/extensions/api.txt
@@ -416,6 +416,7 @@ accepts two arguments:
* `md.tab_length`
* `md.enable_attributes`
* `md.smart_emphasis`
+ * `md.start_level`
* **`md_globals`**:
diff --git a/docs/reference.txt b/docs/reference.txt
index b65f2ddf4..31c8dbf04 100644
--- a/docs/reference.txt
+++ b/docs/reference.txt
@@ -249,6 +249,20 @@ The following options are available on the `markdown.markdown` function:
Pears
+* __`start_level`__{: #start_level }: Start level for headings in the output.
+ Default: 0
+
+ Given the following headers:
+
+ # Header 1
+
+ Header 2
+ --------
+
+ By default markdown will turn Header 1 and Header 2 into `h1` and `h2`
+ elements, respectively. The `start_level` option specifies an offset that
+ will be added to the levels. For example, with a `start_level` of 2,
+ Header 1 would result in a `h3` element and Header 2 in a `h4` element.
### `markdown.markdownFromFile (**kwargs)` {: #markdownFromFile }
diff --git a/markdown/__init__.py b/markdown/__init__.py
index 78ea4cbe6..2010f95b5 100644
--- a/markdown/__init__.py
+++ b/markdown/__init__.py
@@ -64,6 +64,7 @@ class Markdown(object):
'enable_attributes': True,
'smart_emphasis': True,
'lazy_ol': True,
+ 'start_level': 0
}
output_formats = {
@@ -109,6 +110,7 @@ def __init__(self, *args, **kwargs):
* enable_attributes: Enable the conversion of attributes. Default: True
* smart_emphasis: Treat `_connected_words_` intelligently Default: True
* lazy_ol: Ignore number of first item of ordered lists. Default: True
+ * start_level: Start level for headings in the output. Default: 0
"""
diff --git a/markdown/blockprocessors.py b/markdown/blockprocessors.py
index 870151bec..61059e8c8 100644
--- a/markdown/blockprocessors.py
+++ b/markdown/blockprocessors.py
@@ -52,6 +52,7 @@ class BlockProcessor(object):
def __init__(self, parser):
self.parser = parser
self.tab_length = parser.markdown.tab_length
+ self.start_level = parser.markdown.start_level
def lastChild(self, parent):
""" Return the last child of an etree element. """
@@ -440,7 +441,8 @@ def run(self, parent, blocks):
# recursively parse this lines as a block.
self.parser.parseBlocks(parent, [before])
# Create header using named groups from RE
- h = util.etree.SubElement(parent, 'h%d' % len(m.group('level')))
+ level = self.start_level + len(m.group('level'))
+ h = util.etree.SubElement(parent, 'h%d' % level)
h.text = m.group('header').strip()
if after:
# Insert remaining lines as first block for future parsing.
@@ -463,9 +465,9 @@ def run(self, parent, blocks):
lines = blocks.pop(0).split('\n')
# Determine level. ``=`` is 1 and ``-`` is 2.
if lines[1].startswith('='):
- level = 1
+ level = self.start_level + 1
else:
- level = 2
+ level = self.start_level + 2
h = util.etree.SubElement(parent, 'h%d' % level)
h.text = lines[0].strip()
if len(lines) > 2:
diff --git a/tests/options/start-level.html b/tests/options/start-level.html
new file mode 100644
index 000000000..61873e9f5
--- /dev/null
+++ b/tests/options/start-level.html
@@ -0,0 +1,4 @@
+Header 1
+Header 2
+Header 3
+Header 4
\ No newline at end of file
diff --git a/tests/options/start-level.txt b/tests/options/start-level.txt
new file mode 100644
index 000000000..a65bb63b1
--- /dev/null
+++ b/tests/options/start-level.txt
@@ -0,0 +1,9 @@
+# Header 1
+
+## Header 2
+
+Header 3
+========
+
+Header 4
+--------
\ No newline at end of file
diff --git a/tests/options/test.cfg b/tests/options/test.cfg
index 2e14f1f45..067eef79b 100644
--- a/tests/options/test.cfg
+++ b/tests/options/test.cfg
@@ -8,4 +8,7 @@ no-attributes:
enable_attributes: False
no-smart-emphasis:
- smart_emphasis: False
\ No newline at end of file
+ smart_emphasis: False
+
+start-level:
+ start_level: 2
\ No newline at end of file