Browse Source

Enhance Markdown pages with :meta tags

pull/2/head
Noah Petherbridge 6 years ago
parent
commit
66230a3059
1 changed files with 55 additions and 6 deletions
  1. +55
    -6
      rophako/utils.py

+ 55
- 6
rophako/utils.py View File

@@ -57,30 +57,71 @@ def template(name, **kwargs):


def markdown_template(path):
"""Render a Markdown page to the browser."""
"""Render a Markdown page to the browser.

The first line in the Markdown page should be an H1 header beginning with
the # sign. This will set the page's <title> to match the header value.

Pages can include lines that begin with the keyword `:meta` to apply
meta information to control the Markdown parser. Supported meta lines
and examples:

To 'blacklist' extensions, i.e. to turn off line breaks inside a paragraph
getting translated into a <br> tag (the key is the minus sign):
:meta extensions -nl2br

To add an extension, i.e. the abbreviations from PHP Markdown Extra:
:meta extensions abbr"""

# The path is the absolute path to the Markdown file, so open it directly.
fh = codecs.open(path, "r", "utf-8")
body = fh.read()
fh.close()

# Look for meta information in the file.
lines = body.split("\n")
content = list() # New set of lines, without meta info.
extensions = set()
blacklist = set() # Blacklisted extensions
for line in lines:
if line.startswith(":meta"):
parts = line.split(" ")
if len(parts) >= 3:
# Supported meta commands.
if parts[1] == "extensions":
# Extension toggles.
for extension in parts[2:]:
if extension.startswith("-"):
extension = extension[1:]
blacklist.add(extension)
else:
extensions.add(extension)
else:
content.append(line)

# Extract a title from the first line.
first = body.split("\n")[0]
first = content[0]
if first.startswith("#"):
first = first[1:].strip()

rendered = render_markdown(body)
rendered = render_markdown("\n".join(content),
extensions=extensions,
blacklist=blacklist,
)
return template("markdown.inc.html",
title=first,
markdown=rendered,
)


def render_markdown(body, html_escape=True):
def render_markdown(body, html_escape=True, extensions=None, blacklist=None):
"""Render a block of Markdown text.

This will default to escaping literal HTML characters. Set
`html_escape=False` to trust HTML."""
`html_escape=False` to trust HTML.

* extensions should be a set() of extensions to add.
* blacklist should be a set() of extensions to blacklist."""

args = dict(
lazy_ol=False, # If a numbered list starts at e.g. 4, show the <ol> there
@@ -101,6 +142,14 @@ def render_markdown(body, html_escape=True):
if html_escape:
args["safe_mode"] = "escape"

# Additional extensions?
if extensions is not None:
for ext in extensions:
args["extensions"].append(ext)
if blacklist is not None:
for ext in blacklist:
args["extensions"].remove(str(ext))

return markdown.markdown(body, **args)


@@ -157,4 +206,4 @@ def sanitize_name(name):
"""Sanitize a name that may be used in the filesystem.

Only allows numbers, letters, and some symbols."""
return re.sub(r'[^A-Za-z0-9 .\-_]+', '', name)
return re.sub(r'[^A-Za-z0-9 .\-_]+', '', name)

Loading…
Cancel
Save