mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 10:00:01 -03:30
Revert "Upgrade Markdown to 2.5.2" due to issues with logging in python
2.6. This reverts commit 6787490e6d854eecea70b511673290277ea3bccc.
This commit is contained in:
parent
57e2548265
commit
d9a2acb252
@ -33,7 +33,7 @@ importlib==1.0.3 (importlib/*, needed for Python 2.6 support)
|
||||
iso8601==0.1.10 (iso8601/*)
|
||||
keyring==4.1 (keyring/*, excluded bin/keyring)
|
||||
kombu==3.0.21 (kombu/*)
|
||||
Markdown==2.5.2 (markdown/*, excluded bin/markdown_py)
|
||||
Markdown==2.4.1 (markdown/*, excluded bin/markdown_py)
|
||||
mock==1.0.1 (mock.py)
|
||||
ordereddict==1.1 (ordereddict.py, needed for Python 2.6 support)
|
||||
os-diskconfig-python-novaclient-ext==0.1.2 (os_diskconfig_python_novaclient_ext/*)
|
||||
|
||||
@ -10,7 +10,7 @@ called from the command line.
|
||||
import markdown
|
||||
html = markdown.markdown(your_text_string)
|
||||
|
||||
See <https://pythonhosted.org/Markdown/> for more
|
||||
See <http://packages.python.org/Markdown/> for more
|
||||
information and instructions on how to extend the functionality of
|
||||
Python Markdown. Read that before you try modifying this file.
|
||||
|
||||
@ -36,8 +36,6 @@ from .__version__ import version, version_info
|
||||
import codecs
|
||||
import sys
|
||||
import logging
|
||||
import warnings
|
||||
import importlib
|
||||
from . import util
|
||||
from .preprocessors import build_preprocessors
|
||||
from .blockprocessors import build_block_parser
|
||||
@ -50,7 +48,6 @@ from .serializers import to_html_string, to_xhtml_string
|
||||
__all__ = ['Markdown', 'markdown', 'markdownFromFile']
|
||||
|
||||
logger = logging.getLogger('MARKDOWN')
|
||||
logging.captureWarnings(True)
|
||||
|
||||
|
||||
class Markdown(object):
|
||||
@ -99,8 +96,8 @@ class Markdown(object):
|
||||
Note that it is suggested that the more specific formats ("xhtml1"
|
||||
and "html4") be used as "xhtml" or "html" may change in the future
|
||||
if it makes sense at that time.
|
||||
* safe_mode: Deprecated! Disallow raw html. One of "remove", "replace" or "escape".
|
||||
* html_replacement_text: Deprecated! Text used when safe_mode is set to "replace".
|
||||
* safe_mode: Disallow raw html. One of "remove", "replace" or "escape".
|
||||
* html_replacement_text: Text used when safe_mode is set to "replace".
|
||||
* tab_length: Length of tabs in the source. Default: 4
|
||||
* enable_attributes: Enable the conversion of attributes. Default: True
|
||||
* smart_emphasis: Treat `_connected_words_` intelligently Default: True
|
||||
@ -110,16 +107,14 @@ class Markdown(object):
|
||||
|
||||
# For backward compatibility, loop through old positional args
|
||||
pos = ['extensions', 'extension_configs', 'safe_mode', 'output_format']
|
||||
for c, arg in enumerate(args):
|
||||
c = 0
|
||||
for arg in args:
|
||||
if pos[c] not in kwargs:
|
||||
kwargs[pos[c]] = arg
|
||||
if c+1 == len(pos): #pragma: no cover
|
||||
c += 1
|
||||
if c == len(pos):
|
||||
# ignore any additional args
|
||||
break
|
||||
if len(args):
|
||||
warnings.warn('Positional arguments are pending depreacted in Markdown '
|
||||
'and will be deprecated in version 2.6. Use keyword '
|
||||
'arguments only.', PendingDeprecationWarning)
|
||||
|
||||
# Loop through kwargs and assign defaults
|
||||
for option, default in self.option_defaults.items():
|
||||
@ -130,18 +125,6 @@ class Markdown(object):
|
||||
# Disable attributes in safeMode when not explicitly set
|
||||
self.enable_attributes = False
|
||||
|
||||
if 'safe_mode' in kwargs:
|
||||
warnings.warn('"safe_mode" is pending deprecation in Python-Markdown '
|
||||
'and will be deprecated in version 2.6. Use an HTML '
|
||||
'sanitizer (like Bleach http://bleach.readthedocs.org/) '
|
||||
'if you are parsing untrusted markdown text. See the '
|
||||
'2.5 release notes for more info', PendingDeprecationWarning)
|
||||
|
||||
if 'html_replacement_text' in kwargs:
|
||||
warnings.warn('The "html_replacement_text" keyword is pending deprecation '
|
||||
'in Python-Markdown and will be deprecated in version 2.6 '
|
||||
'along with "safe_mode".', PendingDeprecationWarning)
|
||||
|
||||
self.registeredExtensions = []
|
||||
self.docType = ""
|
||||
self.stripTopLevelTags = True
|
||||
@ -177,11 +160,9 @@ class Markdown(object):
|
||||
"""
|
||||
for ext in extensions:
|
||||
if isinstance(ext, util.string_type):
|
||||
ext = self.build_extension(ext, configs.get(ext, {}))
|
||||
ext = self.build_extension(ext, configs.get(ext, []))
|
||||
if isinstance(ext, Extension):
|
||||
ext.extendMarkdown(self, globals())
|
||||
logger.debug('Successfully loaded extension "%s.%s".'
|
||||
% (ext.__class__.__module__, ext.__class__.__name__))
|
||||
elif ext is not None:
|
||||
raise TypeError(
|
||||
'Extension "%s.%s" must be of type: "markdown.Extension"'
|
||||
@ -189,87 +170,52 @@ class Markdown(object):
|
||||
|
||||
return self
|
||||
|
||||
def build_extension(self, ext_name, configs):
|
||||
def build_extension(self, ext_name, configs = []):
|
||||
"""Build extension by name, then return the module.
|
||||
|
||||
The extension name may contain arguments as part of the string in the
|
||||
following format: "extname(key1=value1,key2=value2)"
|
||||
|
||||
"""
|
||||
|
||||
configs = dict(configs)
|
||||
|
||||
|
||||
# Parse extensions config params (ignore the order)
|
||||
configs = dict(configs)
|
||||
pos = ext_name.find("(") # find the first "("
|
||||
if pos > 0:
|
||||
ext_args = ext_name[pos+1:-1]
|
||||
ext_name = ext_name[:pos]
|
||||
pairs = [x.split("=") for x in ext_args.split(",")]
|
||||
configs.update([(x.strip(), y.strip()) for (x, y) in pairs])
|
||||
warnings.warn('Setting configs in the Named Extension string is pending deprecation. '
|
||||
'It is recommended that you pass an instance of the extension class to '
|
||||
'Markdown or use the "extension_configs" keyword. The current behavior '
|
||||
'will be deprecated in version 2.6 and raise an error in version 2.7. '
|
||||
'See the Release Notes for Python-Markdown version 2.5 for more info.',
|
||||
PendingDeprecationWarning)
|
||||
|
||||
# Get class name (if provided): `path.to.module:ClassName`
|
||||
ext_name, class_name = ext_name.split(':', 1) if ':' in ext_name else (ext_name, '')
|
||||
# Setup the module name
|
||||
module_name = ext_name
|
||||
if '.' not in ext_name:
|
||||
module_name = '.'.join(['markdown.extensions', ext_name])
|
||||
|
||||
# Try loading the extension first from one place, then another
|
||||
try:
|
||||
# Assume string uses dot syntax (`path.to.some.module`)
|
||||
module = importlib.import_module(ext_name)
|
||||
logger.debug('Successfuly imported extension module "%s".' % ext_name)
|
||||
# For backward compat (until deprecation) check that this is an extension
|
||||
if '.' not in ext_name and not (hasattr(module, 'extendMarkdown') or (class_name and hasattr(module, class_name))):
|
||||
# We have a name conflict (eg: extensions=['tables'] and PyTables is installed)
|
||||
raise ImportError
|
||||
try: # New style (markdown.extensions.<extension>)
|
||||
module = __import__(module_name, {}, {}, [module_name.rpartition('.')[0]])
|
||||
except ImportError:
|
||||
# Preppend `markdown.extensions.` to name
|
||||
module_name = '.'.join(['markdown.extensions', ext_name])
|
||||
try:
|
||||
module = importlib.import_module(module_name)
|
||||
logger.debug('Successfuly imported extension module "%s".' % module_name)
|
||||
warnings.warn('Using short names for Markdown\'s builtin extensions is pending deprecation. '
|
||||
'Use the full path to the extension with Python\'s dot notation '
|
||||
'(eg: "%s" instead of "%s"). The current behavior will be deprecated in '
|
||||
'version 2.6 and raise an error in version 2.7. See the Release Notes for '
|
||||
'Python-Markdown version 2.5 for more info.' % (module_name, ext_name),
|
||||
PendingDeprecationWarning)
|
||||
except ImportError:
|
||||
# Preppend `mdx_` to name
|
||||
module_name_old_style = '_'.join(['mdx', ext_name])
|
||||
try:
|
||||
module = importlib.import_module(module_name_old_style)
|
||||
logger.debug('Successfuly imported extension module "%s".' % module_name_old_style)
|
||||
warnings.warn('Markdown\'s behavuor of appending "mdx_" to an extension name '
|
||||
'is pending deprecation. Use the full path to the extension with '
|
||||
'Python\'s dot notation (eg: "%s" instead of "%s"). The '
|
||||
'current behavior will be deprecated in version 2.6 and raise an '
|
||||
'error in version 2.7. See the Release Notes for Python-Markdown '
|
||||
'version 2.5 for more info.' % (module_name_old_style, ext_name),
|
||||
PendingDeprecationWarning)
|
||||
except ImportError as e:
|
||||
message = "Failed loading extension '%s' from '%s', '%s' or '%s'" \
|
||||
% (ext_name, ext_name, module_name, module_name_old_style)
|
||||
e.args = (message,) + e.args[1:]
|
||||
raise
|
||||
|
||||
if class_name:
|
||||
# Load given class name from module.
|
||||
return getattr(module, class_name)(**configs)
|
||||
else:
|
||||
# Expect makeExtension() function to return a class.
|
||||
try:
|
||||
return module.makeExtension(**configs)
|
||||
except AttributeError as e:
|
||||
message = e.args[0]
|
||||
message = "Failed to initiate extension " \
|
||||
"'%s': %s" % (ext_name, message)
|
||||
module_name_old_style = '_'.join(['mdx', ext_name])
|
||||
try: # Old style (mdx_<extension>)
|
||||
module = __import__(module_name_old_style)
|
||||
except ImportError as e:
|
||||
message = "Failed loading extension '%s' from '%s' or '%s'" \
|
||||
% (ext_name, module_name, module_name_old_style)
|
||||
e.args = (message,) + e.args[1:]
|
||||
raise
|
||||
|
||||
# If the module is loaded successfully, we expect it to define a
|
||||
# function called makeExtension()
|
||||
try:
|
||||
return module.makeExtension(configs.items())
|
||||
except AttributeError as e:
|
||||
message = e.args[0]
|
||||
message = "Failed to initiate extension " \
|
||||
"'%s': %s" % (ext_name, message)
|
||||
e.args = (message,) + e.args[1:]
|
||||
raise
|
||||
|
||||
def registerExtension(self, extension):
|
||||
""" This gets called by the extension """
|
||||
self.registeredExtensions.append(extension)
|
||||
@ -357,7 +303,7 @@ class Markdown(object):
|
||||
start = output.index('<%s>'%self.doc_tag)+len(self.doc_tag)+2
|
||||
end = output.rindex('</%s>'%self.doc_tag)
|
||||
output = output[start:end].strip()
|
||||
except ValueError: #pragma: no cover
|
||||
except ValueError:
|
||||
if output.strip().endswith('<%s />'%self.doc_tag):
|
||||
# We have an empty document
|
||||
output = ''
|
||||
@ -488,10 +434,6 @@ def markdownFromFile(*args, **kwargs):
|
||||
c += 1
|
||||
if c == len(pos):
|
||||
break
|
||||
if len(args):
|
||||
warnings.warn('Positional arguments are pending depreacted in Markdown '
|
||||
'and will be deprecated in version 2.6. Use keyword '
|
||||
'arguments only.', PendingDeprecationWarning)
|
||||
|
||||
md = Markdown(**kwargs)
|
||||
md.convertFile(kwargs.get('input', None),
|
||||
|
||||
@ -7,25 +7,20 @@ COMMAND-LINE SPECIFIC STUFF
|
||||
import markdown
|
||||
import sys
|
||||
import optparse
|
||||
import codecs
|
||||
try:
|
||||
import yaml
|
||||
except ImportError: #pragma: no cover
|
||||
import json as yaml
|
||||
|
||||
import logging
|
||||
from logging import DEBUG, INFO, CRITICAL
|
||||
|
||||
logger = logging.getLogger('MARKDOWN')
|
||||
|
||||
def parse_options(args=None, values=None):
|
||||
def parse_options():
|
||||
"""
|
||||
Define and parse `optparse` options for command-line usage.
|
||||
"""
|
||||
usage = """%prog [options] [INPUTFILE]
|
||||
(STDIN is assumed if no INPUTFILE is given)"""
|
||||
desc = "A Python implementation of John Gruber's Markdown. " \
|
||||
"https://pythonhosted.org/Markdown/"
|
||||
"http://packages.python.org/Markdown/"
|
||||
ver = "%%prog %s" % markdown.version
|
||||
|
||||
parser = optparse.OptionParser(usage=usage, description=desc, version=ver)
|
||||
@ -34,36 +29,28 @@ def parse_options(args=None, values=None):
|
||||
metavar="OUTPUT_FILE")
|
||||
parser.add_option("-e", "--encoding", dest="encoding",
|
||||
help="Encoding for input and output files.",)
|
||||
parser.add_option("-s", "--safe", dest="safe", default=False,
|
||||
metavar="SAFE_MODE",
|
||||
help="Deprecated! 'replace', 'remove' or 'escape' HTML tags in input")
|
||||
parser.add_option("-o", "--output_format", dest="output_format",
|
||||
default='xhtml1', metavar="OUTPUT_FORMAT",
|
||||
help="'xhtml1' (default), 'html4' or 'html5'.")
|
||||
parser.add_option("-n", "--no_lazy_ol", dest="lazy_ol",
|
||||
action='store_false', default=True,
|
||||
help="Observe number of first item of ordered lists.")
|
||||
parser.add_option("-x", "--extension", action="append", dest="extensions",
|
||||
help = "Load extension EXTENSION.", metavar="EXTENSION")
|
||||
parser.add_option("-c", "--extension_configs", dest="configfile", default=None,
|
||||
help="Read extension configurations from CONFIG_FILE. "
|
||||
"CONFIG_FILE must be of JSON or YAML format. YAML format requires "
|
||||
"that a python YAML library be installed. The parsed JSON or YAML "
|
||||
"must result in a python dictionary which would be accepted by the "
|
||||
"'extension_configs' keyword on the markdown.Markdown class. "
|
||||
"The extensions must also be loaded with the `--extension` option.",
|
||||
metavar="CONFIG_FILE")
|
||||
parser.add_option("-q", "--quiet", default = CRITICAL,
|
||||
action="store_const", const=CRITICAL+10, dest="verbose",
|
||||
help="Suppress all warnings.")
|
||||
parser.add_option("-v", "--verbose",
|
||||
action="store_const", const=INFO, dest="verbose",
|
||||
help="Print all warnings.")
|
||||
parser.add_option("-s", "--safe", dest="safe", default=False,
|
||||
metavar="SAFE_MODE",
|
||||
help="'replace', 'remove' or 'escape' HTML tags in input")
|
||||
parser.add_option("-o", "--output_format", dest="output_format",
|
||||
default='xhtml1', metavar="OUTPUT_FORMAT",
|
||||
help="'xhtml1' (default), 'html4' or 'html5'.")
|
||||
parser.add_option("--noisy",
|
||||
action="store_const", const=DEBUG, dest="verbose",
|
||||
help="Print debug messages.")
|
||||
parser.add_option("-x", "--extension", action="append", dest="extensions",
|
||||
help = "Load extension EXTENSION.", metavar="EXTENSION")
|
||||
parser.add_option("-n", "--no_lazy_ol", dest="lazy_ol",
|
||||
action='store_false', default=True,
|
||||
help="Observe number of first item of ordered lists.")
|
||||
|
||||
(options, args) = parser.parse_args(args, values)
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if len(args) == 0:
|
||||
input_file = None
|
||||
@ -73,26 +60,15 @@ def parse_options(args=None, values=None):
|
||||
if not options.extensions:
|
||||
options.extensions = []
|
||||
|
||||
extension_configs = {}
|
||||
if options.configfile:
|
||||
with codecs.open(options.configfile, mode="r", encoding=options.encoding) as fp:
|
||||
try:
|
||||
extension_configs = yaml.load(fp)
|
||||
except Exception as e:
|
||||
message = "Failed parsing extension config file: %s" % options.configfile
|
||||
e.args = (message,) + e.args[1:]
|
||||
raise
|
||||
|
||||
return {'input': input_file,
|
||||
'output': options.filename,
|
||||
'safe_mode': options.safe,
|
||||
'extensions': options.extensions,
|
||||
'extension_configs': extension_configs,
|
||||
'encoding': options.encoding,
|
||||
'output_format': options.output_format,
|
||||
'lazy_ol': options.lazy_ol}, options.verbose
|
||||
|
||||
def run(): #pragma: no cover
|
||||
def run():
|
||||
"""Run Markdown from the command line."""
|
||||
|
||||
# Parse options and adjust logging level if necessary
|
||||
@ -104,7 +80,7 @@ def run(): #pragma: no cover
|
||||
# Run
|
||||
markdown.markdownFromFile(**options)
|
||||
|
||||
if __name__ == '__main__': #pragma: no cover
|
||||
if __name__ == '__main__':
|
||||
# Support running module as a commandline command.
|
||||
# Python 2.5 & 2.6 do: `python -m markdown.__main__ [options] [args]`.
|
||||
# Python 2.7 & 3.x do: `python -m markdown [options] [args]`.
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
# (major, minor, micro, alpha/beta/rc/final, #)
|
||||
# (1, 1, 2, 'alpha', 0) => "1.1.2.dev"
|
||||
# (1, 2, 0, 'beta', 2) => "1.2b2"
|
||||
version_info = (2, 5, 2, 'final', 0)
|
||||
version_info = (2, 4, 1, 'final', 0)
|
||||
|
||||
def _get_version():
|
||||
" Returns a PEP 386-compliant version number from version_info. "
|
||||
|
||||
@ -99,7 +99,7 @@ class BlockProcessor:
|
||||
* ``block``: A block of text from the source which has been split at
|
||||
blank lines.
|
||||
"""
|
||||
pass #pragma: no cover
|
||||
pass
|
||||
|
||||
def run(self, parent, blocks):
|
||||
""" Run processor. Must be overridden by subclasses.
|
||||
@ -123,7 +123,7 @@ class BlockProcessor:
|
||||
* ``parent``: A etree element which is the parent of the current block.
|
||||
* ``blocks``: A list of all remaining blocks of the document.
|
||||
"""
|
||||
pass #pragma: no cover
|
||||
pass
|
||||
|
||||
|
||||
class ListIndentProcessor(BlockProcessor):
|
||||
@ -433,7 +433,7 @@ class HashHeaderProcessor(BlockProcessor):
|
||||
if after:
|
||||
# Insert remaining lines as first block for future parsing.
|
||||
blocks.insert(0, after)
|
||||
else: #pragma: no cover
|
||||
else:
|
||||
# This should never happen, but just in case...
|
||||
logger.warn("We've got a problem header: %r" % block)
|
||||
|
||||
|
||||
@ -4,45 +4,17 @@ Extensions
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from ..util import parseBoolValue
|
||||
import warnings
|
||||
|
||||
class Extension(object):
|
||||
""" Base class for extensions to subclass. """
|
||||
|
||||
# Default config -- to be overriden by a subclass
|
||||
# Must be of the following format:
|
||||
# {
|
||||
# 'key': ['value', 'description']
|
||||
# }
|
||||
# Note that Extension.setConfig will raise a KeyError
|
||||
# if a default is not set here.
|
||||
config = {}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
""" Initiate Extension and set up configs. """
|
||||
def __init__(self, configs = {}):
|
||||
"""Create an instance of an Extention.
|
||||
|
||||
# check for configs arg for backward compat.
|
||||
# (there only ever used to be one so we use arg[0])
|
||||
if len(args):
|
||||
self.setConfigs(args[0])
|
||||
warnings.warn('Extension classes accepting positional args is pending Deprecation. '
|
||||
'Each setting should be passed into the Class as a keyword. Positional '
|
||||
'args will be deprecated in version 2.6 and raise an error in version '
|
||||
'2.7. See the Release Notes for Python-Markdown version 2.5 for more info.',
|
||||
PendingDeprecationWarning)
|
||||
# check for configs kwarg for backward compat.
|
||||
if 'configs' in kwargs.keys():
|
||||
self.setConfigs(kwargs.pop('configs', {}))
|
||||
warnings.warn('Extension classes accepting a dict on the single keyword "config" is '
|
||||
'pending Deprecation. Each setting should be passed into the Class as '
|
||||
'a keyword directly. The "config" keyword will be deprecated in version '
|
||||
'2.6 and raise an error in version 2.7. See the Release Notes for '
|
||||
'Python-Markdown version 2.5 for more info.',
|
||||
PendingDeprecationWarning)
|
||||
# finally, use kwargs
|
||||
self.setConfigs(kwargs)
|
||||
|
||||
Keyword arguments:
|
||||
|
||||
* configs: A dict of configuration setting used by an Extension.
|
||||
"""
|
||||
self.config = configs
|
||||
|
||||
def getConfig(self, key, default=''):
|
||||
""" Return a setting for the given key or an empty string. """
|
||||
@ -61,20 +33,8 @@ class Extension(object):
|
||||
|
||||
def setConfig(self, key, value):
|
||||
""" Set a config setting for `key` with the given `value`. """
|
||||
if isinstance(self.config[key][0], bool):
|
||||
value = parseBoolValue(value)
|
||||
if self.config[key][0] is None:
|
||||
value = parseBoolValue(value, preserve_none=True)
|
||||
self.config[key][0] = value
|
||||
|
||||
def setConfigs(self, items):
|
||||
""" Set multiple config settings given a dict or list of tuples. """
|
||||
if hasattr(items, 'items'):
|
||||
# it's a dict
|
||||
items = items.items()
|
||||
for key, value in items:
|
||||
self.setConfig(key, value)
|
||||
|
||||
def extendMarkdown(self, md, md_globals):
|
||||
"""
|
||||
Add the various proccesors and patterns to the Markdown Instance.
|
||||
|
||||
@ -4,15 +4,22 @@ Abbreviation Extension for Python-Markdown
|
||||
|
||||
This extension adds abbreviation handling to Python-Markdown.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/abbreviations.html>
|
||||
for documentation.
|
||||
Simple Usage:
|
||||
|
||||
Oringinal code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/) and
|
||||
[Seemant Kulleen](http://www.kulleen.org/)
|
||||
>>> import markdown
|
||||
>>> text = """
|
||||
... Some text with an ABBR and a REF. Ignore REFERENCE and ref.
|
||||
...
|
||||
... *[ABBR]: Abbreviation
|
||||
... *[REF]: Abbreviation Reference
|
||||
... """
|
||||
>>> print markdown.markdown(text, ['abbr'])
|
||||
<p>Some text with an <abbr title="Abbreviation">ABBR</abbr> and a <abbr title="Abbreviation Reference">REF</abbr>. Ignore REFERENCE and ref.</p>
|
||||
|
||||
All changes Copyright 2008-2014 The Python Markdown Project
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
Copyright 2007-2008
|
||||
* [Waylan Limberg](http://achinghead.com/)
|
||||
* [Seemant Kulleen](http://www.kulleen.org/)
|
||||
|
||||
|
||||
'''
|
||||
|
||||
@ -85,5 +92,5 @@ class AbbrPattern(Pattern):
|
||||
abbr.set('title', self.title)
|
||||
return abbr
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return AbbrExtension(*args, **kwargs)
|
||||
def makeExtension(configs=None):
|
||||
return AbbrExtension(configs=configs)
|
||||
|
||||
@ -4,16 +4,39 @@ Admonition extension for Python-Markdown
|
||||
|
||||
Adds rST-style admonitions. Inspired by [rST][] feature with the same name.
|
||||
|
||||
The syntax is (followed by an indented block with the contents):
|
||||
!!! [type] [optional explicit title]
|
||||
|
||||
Where `type` is used as a CSS class name of the div. If not present, `title`
|
||||
defaults to the capitalized `type`, so "note" -> "Note".
|
||||
|
||||
rST suggests the following `types`, but you're free to use whatever you want:
|
||||
attention, caution, danger, error, hint, important, note, tip, warning
|
||||
|
||||
|
||||
A simple example:
|
||||
!!! note
|
||||
This is the first line inside the box.
|
||||
|
||||
Outputs:
|
||||
<div class="admonition note">
|
||||
<p class="admonition-title">Note</p>
|
||||
<p>This is the first line inside the box</p>
|
||||
</div>
|
||||
|
||||
You can also specify the title and CSS class of the admonition:
|
||||
!!! custom "Did you know?"
|
||||
Another line here.
|
||||
|
||||
Outputs:
|
||||
<div class="admonition custom">
|
||||
<p class="admonition-title">Did you know?</p>
|
||||
<p>Another line here.</p>
|
||||
</div>
|
||||
|
||||
[rST]: http://docutils.sourceforge.net/docs/ref/rst/directives.html#specific-admonitions
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/admonition.html>
|
||||
for documentation.
|
||||
|
||||
Original code Copyright [Tiago Serafim](http://www.tiagoserafim.com/).
|
||||
|
||||
All changes Copyright The Python Markdown Project
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
By [Tiago Serafim](http://www.tiagoserafim.com/).
|
||||
|
||||
"""
|
||||
|
||||
@ -91,6 +114,5 @@ class AdmonitionProcessor(BlockProcessor):
|
||||
return klass, title
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return AdmonitionExtension(*args, **kwargs)
|
||||
|
||||
def makeExtension(configs={}):
|
||||
return AdmonitionExtension(configs=configs)
|
||||
|
||||
@ -6,14 +6,15 @@ Adds attribute list syntax. Inspired by
|
||||
[maruku](http://maruku.rubyforge.org/proposal.html#attribute_lists)'s
|
||||
feature of the same name.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/attr_list.html>
|
||||
for documentation.
|
||||
Copyright 2011 [Waylan Limberg](http://achinghead.com/).
|
||||
|
||||
Original code Copyright 2011 [Waylan Limberg](http://achinghead.com/).
|
||||
Contact: markdown@freewisdom.org
|
||||
|
||||
All changes Copyright 2011-2014 The Python Markdown Project
|
||||
License: BSD (see ../LICENSE.md for details)
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
Dependencies:
|
||||
* [Python 2.4+](http://python.org)
|
||||
* [Markdown 2.1+](http://packages.python.org/Markdown/)
|
||||
|
||||
"""
|
||||
|
||||
@ -26,7 +27,7 @@ import re
|
||||
|
||||
try:
|
||||
Scanner = re.Scanner
|
||||
except AttributeError: #pragma: no cover
|
||||
except AttributeError:
|
||||
# must be on Python 2.4
|
||||
from sre import Scanner
|
||||
|
||||
@ -163,5 +164,5 @@ class AttrListExtension(Extension):
|
||||
md.treeprocessors.add('attr_list', AttrListTreeprocessor(md), '>prettify')
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return AttrListExtension(*args, **kwargs)
|
||||
def makeExtension(configs={}):
|
||||
return AttrListExtension(configs=configs)
|
||||
|
||||
@ -4,14 +4,17 @@ CodeHilite Extension for Python-Markdown
|
||||
|
||||
Adds code/syntax highlighting to standard Python-Markdown code blocks.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/code_hilite.html>
|
||||
for documentation.
|
||||
Copyright 2006-2008 [Waylan Limberg](http://achinghead.com/).
|
||||
|
||||
Original code Copyright 2006-2008 [Waylan Limberg](http://achinghead.com/).
|
||||
Project website: <http://packages.python.org/Markdown/extensions/code_hilite.html>
|
||||
Contact: markdown@freewisdom.org
|
||||
|
||||
All changes Copyright 2008-2014 The Python Markdown Project
|
||||
License: BSD (see ../LICENSE.md for details)
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
Dependencies:
|
||||
* [Python 2.3+](http://python.org/)
|
||||
* [Markdown 2.0+](http://packages.python.org/Markdown/)
|
||||
* [Pygments](http://pygments.org/)
|
||||
|
||||
"""
|
||||
|
||||
@ -22,8 +25,8 @@ from ..treeprocessors import Treeprocessor
|
||||
import warnings
|
||||
try:
|
||||
from pygments import highlight
|
||||
from pygments.lexers import get_lexer_by_name, guess_lexer
|
||||
from pygments.formatters import get_formatter_by_name
|
||||
from pygments.lexers import get_lexer_by_name, guess_lexer, TextLexer
|
||||
from pygments.formatters import HtmlFormatter
|
||||
pygments = True
|
||||
except ImportError:
|
||||
pygments = False
|
||||
@ -109,15 +112,14 @@ class CodeHilite(object):
|
||||
if self.guess_lang:
|
||||
lexer = guess_lexer(self.src)
|
||||
else:
|
||||
lexer = get_lexer_by_name('text')
|
||||
lexer = TextLexer()
|
||||
except ValueError:
|
||||
lexer = get_lexer_by_name('text')
|
||||
formatter = get_formatter_by_name('html',
|
||||
linenos=self.linenums,
|
||||
cssclass=self.css_class,
|
||||
style=self.style,
|
||||
noclasses=self.noclasses,
|
||||
hl_lines=self.hl_lines)
|
||||
lexer = TextLexer()
|
||||
formatter = HtmlFormatter(linenos=self.linenums,
|
||||
cssclass=self.css_class,
|
||||
style=self.style,
|
||||
noclasses=self.noclasses,
|
||||
hl_lines=self.hl_lines)
|
||||
return highlight(self.src, lexer, formatter)
|
||||
else:
|
||||
# just escape and build markup usable by JS highlighting libs
|
||||
@ -223,7 +225,7 @@ class HiliteTreeprocessor(Treeprocessor):
|
||||
class CodeHiliteExtension(Extension):
|
||||
""" Add source code hilighting to markdown codeblocks. """
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
def __init__(self, configs):
|
||||
# define default configs
|
||||
self.config = {
|
||||
'linenums': [None, "Use lines numbers. True=yes, False=no, None=auto"],
|
||||
@ -235,7 +237,22 @@ class CodeHiliteExtension(Extension):
|
||||
'noclasses': [False, 'Use inline styles instead of CSS classes - Default false']
|
||||
}
|
||||
|
||||
super(CodeHiliteExtension, self).__init__(*args, **kwargs)
|
||||
# Override defaults with user settings
|
||||
for key, value in configs:
|
||||
# convert strings to booleans
|
||||
if value == 'True': value = True
|
||||
if value == 'False': value = False
|
||||
if value == 'None': value = None
|
||||
|
||||
if key == 'force_linenos':
|
||||
warnings.warn('The "force_linenos" config setting'
|
||||
' to the CodeHilite extension is deprecrecated.'
|
||||
' Use "linenums" instead.', DeprecationWarning)
|
||||
if value:
|
||||
# Carry 'force_linenos' over to new 'linenos'.
|
||||
self.setConfig('linenums', True)
|
||||
|
||||
self.setConfig(key, value)
|
||||
|
||||
def extendMarkdown(self, md, md_globals):
|
||||
""" Add HilitePostprocessor to Markdown instance. """
|
||||
@ -246,5 +263,6 @@ class CodeHiliteExtension(Extension):
|
||||
md.registerExtension(self)
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return CodeHiliteExtension(*args, **kwargs)
|
||||
def makeExtension(configs={}):
|
||||
return CodeHiliteExtension(configs=configs)
|
||||
|
||||
|
||||
@ -2,16 +2,19 @@
|
||||
Definition List Extension for Python-Markdown
|
||||
=============================================
|
||||
|
||||
Adds parsing of Definition Lists to Python-Markdown.
|
||||
Added parsing of Definition Lists to Python-Markdown.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/definition_lists.html>
|
||||
for documentation.
|
||||
A simple example:
|
||||
|
||||
Original code Copyright 2008 [Waylan Limberg](http://achinghead.com)
|
||||
Apple
|
||||
: Pomaceous fruit of plants of the genus Malus in
|
||||
the family Rosaceae.
|
||||
: An american computer company.
|
||||
|
||||
All changes Copyright 2008-2014 The Python Markdown Project
|
||||
Orange
|
||||
: The fruit of an evergreen tree of the genus Citrus.
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
Copyright 2008 - [Waylan Limberg](http://achinghead.com)
|
||||
|
||||
"""
|
||||
|
||||
@ -110,6 +113,6 @@ class DefListExtension(Extension):
|
||||
'>ulist')
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return DefListExtension(*args, **kwargs)
|
||||
def makeExtension(configs={}):
|
||||
return DefListExtension(configs=configs)
|
||||
|
||||
|
||||
@ -11,6 +11,10 @@ convenience so that only one extension needs to be listed when
|
||||
initiating Markdown. See the documentation for each individual
|
||||
extension for specifics about that extension.
|
||||
|
||||
In the event that one or more of the supported extensions are not
|
||||
available for import, Markdown will issue a warning and simply continue
|
||||
without that extension.
|
||||
|
||||
There may be additional extensions that are distributed with
|
||||
Python-Markdown that are not included here in Extra. Those extensions
|
||||
are not part of PHP Markdown Extra, and therefore, not part of
|
||||
@ -20,13 +24,6 @@ under a differant name. You could also edit the `extensions` global
|
||||
variable defined below, but be aware that such changes may be lost
|
||||
when you upgrade to any future version of Python-Markdown.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/extra.html>
|
||||
for documentation.
|
||||
|
||||
Copyright The Python Markdown Project
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
@ -36,25 +33,19 @@ from ..blockprocessors import BlockProcessor
|
||||
from .. import util
|
||||
import re
|
||||
|
||||
extensions = [
|
||||
'markdown.extensions.smart_strong',
|
||||
'markdown.extensions.fenced_code',
|
||||
'markdown.extensions.footnotes',
|
||||
'markdown.extensions.attr_list',
|
||||
'markdown.extensions.def_list',
|
||||
'markdown.extensions.tables',
|
||||
'markdown.extensions.abbr'
|
||||
]
|
||||
extensions = ['smart_strong',
|
||||
'fenced_code',
|
||||
'footnotes',
|
||||
'attr_list',
|
||||
'def_list',
|
||||
'tables',
|
||||
'abbr',
|
||||
]
|
||||
|
||||
|
||||
class ExtraExtension(Extension):
|
||||
""" Add various extensions to Markdown class."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
""" config is just a dumb holder which gets passed to actual ext later. """
|
||||
self.config = kwargs.pop('configs', {})
|
||||
self.config.update(kwargs)
|
||||
|
||||
def extendMarkdown(self, md, md_globals):
|
||||
""" Register extension instances. """
|
||||
md.registerExtensions(extensions, self.config)
|
||||
@ -69,8 +60,8 @@ class ExtraExtension(Extension):
|
||||
r'^(p|h[1-6]|li|dd|dt|td|th|legend|address)$', re.IGNORECASE)
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return ExtraExtension(*args, **kwargs)
|
||||
def makeExtension(configs={}):
|
||||
return ExtraExtension(configs=dict(configs))
|
||||
|
||||
|
||||
class MarkdownInHtmlProcessor(BlockProcessor):
|
||||
|
||||
@ -4,15 +4,87 @@ Fenced Code Extension for Python Markdown
|
||||
|
||||
This extension adds Fenced Code Blocks to Python-Markdown.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/fenced_code_blocks.html>
|
||||
for documentation.
|
||||
>>> import markdown
|
||||
>>> text = '''
|
||||
... A paragraph before a fenced code block:
|
||||
...
|
||||
... ~~~
|
||||
... Fenced code block
|
||||
... ~~~
|
||||
... '''
|
||||
>>> html = markdown.markdown(text, extensions=['fenced_code'])
|
||||
>>> print html
|
||||
<p>A paragraph before a fenced code block:</p>
|
||||
<pre><code>Fenced code block
|
||||
</code></pre>
|
||||
|
||||
Original code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/).
|
||||
Works with safe_mode also (we check this because we are using the HtmlStash):
|
||||
|
||||
>>> print markdown.markdown(text, extensions=['fenced_code'], safe_mode='replace')
|
||||
<p>A paragraph before a fenced code block:</p>
|
||||
<pre><code>Fenced code block
|
||||
</code></pre>
|
||||
|
||||
All changes Copyright 2008-2014 The Python Markdown Project
|
||||
Include tilde's in a code block and wrap with blank lines:
|
||||
|
||||
>>> text = '''
|
||||
... ~~~~~~~~
|
||||
...
|
||||
... ~~~~
|
||||
... ~~~~~~~~'''
|
||||
>>> print markdown.markdown(text, extensions=['fenced_code'])
|
||||
<pre><code>
|
||||
~~~~
|
||||
</code></pre>
|
||||
|
||||
Language tags:
|
||||
|
||||
>>> text = '''
|
||||
... ~~~~{.python}
|
||||
... # Some python code
|
||||
... ~~~~'''
|
||||
>>> print markdown.markdown(text, extensions=['fenced_code'])
|
||||
<pre><code class="python"># Some python code
|
||||
</code></pre>
|
||||
|
||||
Optionally backticks instead of tildes as per how github's code block markdown is identified:
|
||||
|
||||
>>> text = '''
|
||||
... `````
|
||||
... # Arbitrary code
|
||||
... ~~~~~ # these tildes will not close the block
|
||||
... `````'''
|
||||
>>> print markdown.markdown(text, extensions=['fenced_code'])
|
||||
<pre><code># Arbitrary code
|
||||
~~~~~ # these tildes will not close the block
|
||||
</code></pre>
|
||||
|
||||
If the codehighlite extension and Pygments are installed, lines can be highlighted:
|
||||
|
||||
>>> text = '''
|
||||
... ```hl_lines="1 3"
|
||||
... line 1
|
||||
... line 2
|
||||
... line 3
|
||||
... ```'''
|
||||
>>> print markdown.markdown(text, extensions=['codehilite', 'fenced_code'])
|
||||
<pre><code><span class="hilight">line 1</span>
|
||||
line 2
|
||||
<span class="hilight">line 3</span>
|
||||
</code></pre>
|
||||
|
||||
Copyright 2007-2008 [Waylan Limberg](http://achinghead.com/).
|
||||
|
||||
Project website: <http://packages.python.org/Markdown/extensions/fenced_code_blocks.html>
|
||||
Contact: markdown@freewisdom.org
|
||||
|
||||
License: BSD (see ../docs/LICENSE for details)
|
||||
|
||||
Dependencies:
|
||||
* [Python 2.4+](http://python.org)
|
||||
* [Markdown 2.0+](http://packages.python.org/Markdown/)
|
||||
* [Pygments (optional)](http://pygments.org)
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
@ -103,6 +175,5 @@ class FencedBlockPreprocessor(Preprocessor):
|
||||
return txt
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return FencedCodeExtension(*args, **kwargs)
|
||||
|
||||
def makeExtension(configs=None):
|
||||
return FencedCodeExtension(configs=configs)
|
||||
|
||||
@ -1,15 +1,25 @@
|
||||
"""
|
||||
Footnotes Extension for Python-Markdown
|
||||
=======================================
|
||||
========================= FOOTNOTES =================================
|
||||
|
||||
Adds footnote handling to Python-Markdown.
|
||||
This section adds footnote handling to markdown. It can be used as
|
||||
an example for extending python-markdown with relatively complex
|
||||
functionality. While in this case the extension is included inside
|
||||
the module itself, it could just as easily be added from outside the
|
||||
module. Not that all markdown classes above are ignorant about
|
||||
footnotes. All footnote functionality is provided separately and
|
||||
then added to the markdown instance at the run time.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/footnotes.html>
|
||||
for documentation.
|
||||
Footnote functionality is attached by calling extendMarkdown()
|
||||
method of FootnoteExtension. The method also registers the
|
||||
extension to allow it's state to be reset by a call to reset()
|
||||
method.
|
||||
|
||||
Copyright The Python Markdown Project
|
||||
Example:
|
||||
Footnotes[^1] have a label[^label] and a definition[^!DEF].
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
[^1]: This is a footnote
|
||||
[^label]: A footnote on "label"
|
||||
[^!DEF]: The footnote for definition
|
||||
|
||||
"""
|
||||
|
||||
@ -32,23 +42,23 @@ TABBED_RE = re.compile(r'((\t)|( ))(.*)')
|
||||
class FootnoteExtension(Extension):
|
||||
""" Footnote Extension. """
|
||||
|
||||
def __init__ (self, *args, **kwargs):
|
||||
def __init__ (self, configs):
|
||||
""" Setup configs. """
|
||||
self.config = {'PLACE_MARKER':
|
||||
["///Footnotes Go Here///",
|
||||
"The text string that marks where the footnotes go"],
|
||||
'UNIQUE_IDS':
|
||||
[False,
|
||||
"Avoid name collisions across "
|
||||
"multiple calls to reset()."],
|
||||
"BACKLINK_TEXT":
|
||||
["↩",
|
||||
"The text string that links from the footnote to the reader's place."]
|
||||
}
|
||||
|
||||
for key, value in configs:
|
||||
self.config[key][0] = value
|
||||
|
||||
self.config = {
|
||||
'PLACE_MARKER':
|
||||
["///Footnotes Go Here///",
|
||||
"The text string that marks where the footnotes go"],
|
||||
'UNIQUE_IDS':
|
||||
[False,
|
||||
"Avoid name collisions across "
|
||||
"multiple calls to reset()."],
|
||||
"BACKLINK_TEXT":
|
||||
["↩",
|
||||
"The text string that links from the footnote to the reader's place."]
|
||||
}
|
||||
super(FootnoteExtension, self).__init__(*args, **kwargs)
|
||||
|
||||
# In multiple invocations, emit links that don't get tangled.
|
||||
self.unique_prefix = 0
|
||||
|
||||
@ -299,7 +309,7 @@ class FootnotePostprocessor(Postprocessor):
|
||||
text = text.replace(FN_BACKLINK_TEXT, self.footnotes.getConfig("BACKLINK_TEXT"))
|
||||
return text.replace(NBSP_PLACEHOLDER, " ")
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
def makeExtension(configs=[]):
|
||||
""" Return an instance of the FootnoteExtension """
|
||||
return FootnoteExtension(*args, **kwargs)
|
||||
return FootnoteExtension(configs=configs)
|
||||
|
||||
|
||||
@ -4,14 +4,73 @@ HeaderID Extension for Python-Markdown
|
||||
|
||||
Auto-generate id attributes for HTML headers.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/header_id.html>
|
||||
for documentation.
|
||||
Basic usage:
|
||||
|
||||
Original code Copyright 2007-2011 [Waylan Limberg](http://achinghead.com/).
|
||||
>>> import markdown
|
||||
>>> text = "# Some Header #"
|
||||
>>> md = markdown.markdown(text, ['headerid'])
|
||||
>>> print md
|
||||
<h1 id="some-header">Some Header</h1>
|
||||
|
||||
All changes Copyright 2011-2014 The Python Markdown Project
|
||||
All header IDs are unique:
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
>>> text = '''
|
||||
... #Header
|
||||
... #Header
|
||||
... #Header'''
|
||||
>>> md = markdown.markdown(text, ['headerid'])
|
||||
>>> print md
|
||||
<h1 id="header">Header</h1>
|
||||
<h1 id="header_1">Header</h1>
|
||||
<h1 id="header_2">Header</h1>
|
||||
|
||||
To fit within a html template's hierarchy, set the header base level:
|
||||
|
||||
>>> text = '''
|
||||
... #Some Header
|
||||
... ## Next Level'''
|
||||
>>> md = markdown.markdown(text, ['headerid(level=3)'])
|
||||
>>> print md
|
||||
<h3 id="some-header">Some Header</h3>
|
||||
<h4 id="next-level">Next Level</h4>
|
||||
|
||||
Works with inline markup.
|
||||
|
||||
>>> text = '#Some *Header* with [markup](http://example.com).'
|
||||
>>> md = markdown.markdown(text, ['headerid'])
|
||||
>>> print md
|
||||
<h1 id="some-header-with-markup">Some <em>Header</em> with <a href="http://example.com">markup</a>.</h1>
|
||||
|
||||
Turn off auto generated IDs:
|
||||
|
||||
>>> text = '''
|
||||
... # Some Header
|
||||
... # Another Header'''
|
||||
>>> md = markdown.markdown(text, ['headerid(forceid=False)'])
|
||||
>>> print md
|
||||
<h1>Some Header</h1>
|
||||
<h1>Another Header</h1>
|
||||
|
||||
Use with MetaData extension:
|
||||
|
||||
>>> text = '''header_level: 2
|
||||
... header_forceid: Off
|
||||
...
|
||||
... # A Header'''
|
||||
>>> md = markdown.markdown(text, ['headerid', 'meta'])
|
||||
>>> print md
|
||||
<h2>A Header</h2>
|
||||
|
||||
Copyright 2007-2011 [Waylan Limberg](http://achinghead.com/).
|
||||
|
||||
Project website: <http://packages.python.org/Markdown/extensions/header_id.html>
|
||||
Contact: markdown@freewisdom.org
|
||||
|
||||
License: BSD (see ../docs/LICENSE for details)
|
||||
|
||||
Dependencies:
|
||||
* [Python 2.3+](http://python.org)
|
||||
* [Markdown 2.0+](http://packages.python.org/Markdown/)
|
||||
|
||||
"""
|
||||
|
||||
@ -68,7 +127,7 @@ def stashedHTML2text(text, md):
|
||||
def _html_sub(m):
|
||||
""" Substitute raw html with plain text. """
|
||||
try:
|
||||
raw, safe = md.htmlStash.rawHtmlBlocks[int(m.group(1))]
|
||||
raw, safe = md.htmlStash.rawHtmlBlocks[int(m.group(1))]
|
||||
except (IndexError, TypeError):
|
||||
return m.group(0)
|
||||
if md.safeMode and not safe:
|
||||
@ -117,7 +176,7 @@ class HeaderIdTreeprocessor(Treeprocessor):
|
||||
|
||||
|
||||
class HeaderIdExtension(Extension):
|
||||
def __init__(self, *args, **kwargs):
|
||||
def __init__(self, configs):
|
||||
# set defaults
|
||||
self.config = {
|
||||
'level' : ['1', 'Base level for headers.'],
|
||||
@ -126,7 +185,8 @@ class HeaderIdExtension(Extension):
|
||||
'slugify' : [slugify, 'Callable to generate anchors'],
|
||||
}
|
||||
|
||||
super(HeaderIdExtension, self).__init__(*args, **kwargs)
|
||||
for key, value in configs:
|
||||
self.setConfig(key, value)
|
||||
|
||||
def extendMarkdown(self, md, md_globals):
|
||||
md.registerExtension(self)
|
||||
@ -144,6 +204,5 @@ class HeaderIdExtension(Extension):
|
||||
self.processor.IDs = set()
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return HeaderIdExtension(*args, **kwargs)
|
||||
|
||||
def makeExtension(configs=None):
|
||||
return HeaderIdExtension(configs=configs)
|
||||
|
||||
@ -4,14 +4,38 @@ Meta Data Extension for Python-Markdown
|
||||
|
||||
This extension adds Meta Data handling to markdown.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/meta_data.html>
|
||||
for documentation.
|
||||
Basic Usage:
|
||||
|
||||
Original code Copyright 2007-2008 [Waylan Limberg](http://achinghead.com).
|
||||
>>> import markdown
|
||||
>>> text = '''Title: A Test Doc.
|
||||
... Author: Waylan Limberg
|
||||
... John Doe
|
||||
... Blank_Data:
|
||||
...
|
||||
... The body. This is paragraph one.
|
||||
... '''
|
||||
>>> md = markdown.Markdown(['meta'])
|
||||
>>> print md.convert(text)
|
||||
<p>The body. This is paragraph one.</p>
|
||||
>>> print md.Meta
|
||||
{u'blank_data': [u''], u'author': [u'Waylan Limberg', u'John Doe'], u'title': [u'A Test Doc.']}
|
||||
|
||||
All changes Copyright 2008-2014 The Python Markdown Project
|
||||
Make sure text without Meta Data still works (markdown < 1.6b returns a <p>).
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
>>> text = ' Some Code - not extra lines of meta data.'
|
||||
>>> md = markdown.Markdown(['meta'])
|
||||
>>> print md.convert(text)
|
||||
<pre><code>Some Code - not extra lines of meta data.
|
||||
</code></pre>
|
||||
>>> md.Meta
|
||||
{}
|
||||
|
||||
Copyright 2007-2008 [Waylan Limberg](http://achinghead.com).
|
||||
|
||||
Project website: <http://packages.python.org/Markdown/meta_data.html>
|
||||
Contact: markdown@freewisdom.org
|
||||
|
||||
License: BSD (see ../LICENSE.md for details)
|
||||
|
||||
"""
|
||||
|
||||
@ -31,7 +55,7 @@ class MetaExtension (Extension):
|
||||
def extendMarkdown(self, md, md_globals):
|
||||
""" Add MetaPreprocessor to Markdown instance. """
|
||||
|
||||
md.preprocessors.add("meta", MetaPreprocessor(md), ">normalize_whitespace")
|
||||
md.preprocessors.add("meta", MetaPreprocessor(md), "_begin")
|
||||
|
||||
|
||||
class MetaPreprocessor(Preprocessor):
|
||||
@ -65,6 +89,5 @@ class MetaPreprocessor(Preprocessor):
|
||||
return lines
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return MetaExtension(*args, **kwargs)
|
||||
|
||||
def makeExtension(configs={}):
|
||||
return MetaExtension(configs=configs)
|
||||
|
||||
@ -5,14 +5,18 @@ NL2BR Extension
|
||||
A Python-Markdown extension to treat newlines as hard breaks; like
|
||||
GitHub-flavored Markdown does.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/nl2br.html>
|
||||
for documentation.
|
||||
Usage:
|
||||
|
||||
Oringinal code Copyright 2011 [Brian Neal](http://deathofagremmie.com/)
|
||||
>>> import markdown
|
||||
>>> print markdown.markdown('line 1\\nline 2', extensions=['nl2br'])
|
||||
<p>line 1<br />
|
||||
line 2</p>
|
||||
|
||||
All changes Copyright 2011-2014 The Python Markdown Project
|
||||
Copyright 2011 [Brian Neal](http://deathofagremmie.com/)
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
Dependencies:
|
||||
* [Python 2.4+](http://python.org)
|
||||
* [Markdown 2.1+](http://packages.python.org/Markdown/)
|
||||
|
||||
"""
|
||||
|
||||
@ -30,6 +34,5 @@ class Nl2BrExtension(Extension):
|
||||
md.inlinePatterns.add('nl', br_tag, '_end')
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return Nl2BrExtension(*args, **kwargs)
|
||||
|
||||
def makeExtension(configs=None):
|
||||
return Nl2BrExtension(configs)
|
||||
|
||||
@ -2,16 +2,19 @@
|
||||
Sane List Extension for Python-Markdown
|
||||
=======================================
|
||||
|
||||
Modify the behavior of Lists in Python-Markdown to act in a sane manor.
|
||||
Modify the behavior of Lists in Python-Markdown t act in a sane manor.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/sane_lists.html>
|
||||
for documentation.
|
||||
In standard Markdown syntax, the following would constitute a single
|
||||
ordered list. However, with this extension, the output would include
|
||||
two lists, the first an ordered list and the second and unordered list.
|
||||
|
||||
Original code Copyright 2011 [Waylan Limberg](http://achinghead.com)
|
||||
1. ordered
|
||||
2. list
|
||||
|
||||
All changes Copyright 2011-2014 The Python Markdown Project
|
||||
* unordered
|
||||
* list
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
Copyright 2011 - [Waylan Limberg](http://achinghead.com)
|
||||
|
||||
"""
|
||||
|
||||
@ -43,6 +46,6 @@ class SaneListExtension(Extension):
|
||||
md.parser.blockprocessors['ulist'] = SaneUListProcessor(md.parser)
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return SaneListExtension(*args, **kwargs)
|
||||
def makeExtension(configs={}):
|
||||
return SaneListExtension(configs=configs)
|
||||
|
||||
|
||||
@ -4,14 +4,21 @@ Smart_Strong Extension for Python-Markdown
|
||||
|
||||
This extention adds smarter handling of double underscores within words.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/smart_strong.html>
|
||||
for documentation.
|
||||
Simple Usage:
|
||||
|
||||
Original code Copyright 2011 [Waylan Limberg](http://achinghead.com)
|
||||
>>> import markdown
|
||||
>>> print markdown.markdown('Text with double__underscore__words.',
|
||||
... extensions=['smart_strong'])
|
||||
<p>Text with double__underscore__words.</p>
|
||||
>>> print markdown.markdown('__Strong__ still works.',
|
||||
... extensions=['smart_strong'])
|
||||
<p><strong>Strong</strong> still works.</p>
|
||||
>>> print markdown.markdown('__this__works__too__.',
|
||||
... extensions=['smart_strong'])
|
||||
<p><strong>this__works__too</strong>.</p>
|
||||
|
||||
All changes Copyright 2011-2014 The Python Markdown Project
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
Copyright 2011
|
||||
[Waylan Limberg](http://achinghead.com)
|
||||
|
||||
'''
|
||||
|
||||
@ -31,5 +38,5 @@ class SmartEmphasisExtension(Extension):
|
||||
md.inlinePatterns['strong'] = SimpleTagPattern(STRONG_RE, 'strong')
|
||||
md.inlinePatterns.add('strong2', SimpleTagPattern(SMART_STRONG_RE, 'strong'), '>emphasis2')
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return SmartEmphasisExtension(*args, **kwargs)
|
||||
def makeExtension(configs={}):
|
||||
return SmartEmphasisExtension(configs=dict(configs))
|
||||
|
||||
@ -1,91 +1,73 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Smarty extension for Python-Markdown
|
||||
====================================
|
||||
|
||||
Adds conversion of ASCII dashes, quotes and ellipses to their HTML
|
||||
entity equivalents.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/smarty.html>
|
||||
for documentation.
|
||||
|
||||
Author: 2013, Dmitry Shachnev <mitya57@gmail.com>
|
||||
|
||||
All changes Copyright 2013-2014 The Python Markdown Project
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
SmartyPants license:
|
||||
|
||||
Copyright (c) 2003 John Gruber <http://daringfireball.net/>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name "SmartyPants" nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
This software is provided by the copyright holders and contributors "as
|
||||
is" and any express or implied warranties, including, but not limited
|
||||
to, the implied warranties of merchantability and fitness for a
|
||||
particular purpose are disclaimed. In no event shall the copyright
|
||||
owner or contributors be liable for any direct, indirect, incidental,
|
||||
special, exemplary, or consequential damages (including, but not
|
||||
limited to, procurement of substitute goods or services; loss of use,
|
||||
data, or profits; or business interruption) however caused and on any
|
||||
theory of liability, whether in contract, strict liability, or tort
|
||||
(including negligence or otherwise) arising in any way out of the use
|
||||
of this software, even if advised of the possibility of such damage.
|
||||
|
||||
|
||||
smartypants.py license:
|
||||
|
||||
smartypants.py is a derivative work of SmartyPants.
|
||||
Copyright (c) 2004, 2007 Chad Miller <http://web.chad.org/>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
This software is provided by the copyright holders and contributors "as
|
||||
is" and any express or implied warranties, including, but not limited
|
||||
to, the implied warranties of merchantability and fitness for a
|
||||
particular purpose are disclaimed. In no event shall the copyright
|
||||
owner or contributors be liable for any direct, indirect, incidental,
|
||||
special, exemplary, or consequential damages (including, but not
|
||||
limited to, procurement of substitute goods or services; loss of use,
|
||||
data, or profits; or business interruption) however caused and on any
|
||||
theory of liability, whether in contract, strict liability, or tort
|
||||
(including negligence or otherwise) arising in any way out of the use
|
||||
of this software, even if advised of the possibility of such damage.
|
||||
|
||||
'''
|
||||
# Smarty extension for Python-Markdown
|
||||
# Author: 2013, Dmitry Shachnev <mitya57@gmail.com>
|
||||
|
||||
# SmartyPants license:
|
||||
#
|
||||
# Copyright (c) 2003 John Gruber <http://daringfireball.net/>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# * Neither the name "SmartyPants" nor the names of its contributors
|
||||
# may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
#
|
||||
# This software is provided by the copyright holders and contributors "as
|
||||
# is" and any express or implied warranties, including, but not limited
|
||||
# to, the implied warranties of merchantability and fitness for a
|
||||
# particular purpose are disclaimed. In no event shall the copyright
|
||||
# owner or contributors be liable for any direct, indirect, incidental,
|
||||
# special, exemplary, or consequential damages (including, but not
|
||||
# limited to, procurement of substitute goods or services; loss of use,
|
||||
# data, or profits; or business interruption) however caused and on any
|
||||
# theory of liability, whether in contract, strict liability, or tort
|
||||
# (including negligence or otherwise) arising in any way out of the use
|
||||
# of this software, even if advised of the possibility of such damage.
|
||||
#
|
||||
#
|
||||
# smartypants.py license:
|
||||
#
|
||||
# smartypants.py is a derivative work of SmartyPants.
|
||||
# Copyright (c) 2004, 2007 Chad Miller <http://web.chad.org/>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
#
|
||||
# This software is provided by the copyright holders and contributors "as
|
||||
# is" and any express or implied warranties, including, but not limited
|
||||
# to, the implied warranties of merchantability and fitness for a
|
||||
# particular purpose are disclaimed. In no event shall the copyright
|
||||
# owner or contributors be liable for any direct, indirect, incidental,
|
||||
# special, exemplary, or consequential damages (including, but not
|
||||
# limited to, procurement of substitute goods or services; loss of use,
|
||||
# data, or profits; or business interruption) however caused and on any
|
||||
# theory of liability, whether in contract, strict liability, or tort
|
||||
# (including negligence or otherwise) arising in any way out of the use
|
||||
# of this software, even if advised of the possibility of such damage.
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from . import Extension
|
||||
from ..inlinepatterns import HtmlPattern
|
||||
from ..odict import OrderedDict
|
||||
from ..treeprocessors import InlineProcessor
|
||||
from ..util import parseBoolValue
|
||||
|
||||
# Constants for quote education.
|
||||
@ -101,25 +83,12 @@ openingQuotesBase = (
|
||||
'|&[mn]dash;' # or named dash entities
|
||||
'|–|—' # or decimal entities
|
||||
')'
|
||||
)
|
||||
|
||||
substitutions = {
|
||||
'mdash': '—',
|
||||
'ndash': '–',
|
||||
'ellipsis': '…',
|
||||
'left-angle-quote': '«',
|
||||
'right-angle-quote': '»',
|
||||
'left-single-quote': '‘',
|
||||
'right-single-quote': '’',
|
||||
'left-double-quote': '“',
|
||||
'right-double-quote': '”',
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
# Special case if the very first character is a quote
|
||||
# followed by punctuation at a non-word-break. Close the quotes by brute force:
|
||||
singleQuoteStartRe = r"^'(?=%s\B)" % punctClass
|
||||
doubleQuoteStartRe = r'^"(?=%s\B)' % punctClass
|
||||
singleQuoteStartRe = r"^'(?=%s\\B)" % punctClass
|
||||
doubleQuoteStartRe = r'^"(?=%s\\B)' % punctClass
|
||||
|
||||
# Special case for double sets of quotes, e.g.:
|
||||
# <p>He said, "'Quoted' words in a larger quote."</p>
|
||||
@ -144,6 +113,8 @@ closingSingleQuotesRegex2 = r"(?<=%s)'(\s|s\b)" % closeClass
|
||||
remainingSingleQuotesRegex = "'"
|
||||
remainingDoubleQuotesRegex = '"'
|
||||
|
||||
lsquo, rsquo, ldquo, rdquo = '‘', '’', '“', '”'
|
||||
|
||||
class SubstituteTextPattern(HtmlPattern):
|
||||
def __init__(self, pattern, replace, markdown_instance):
|
||||
""" Replaces matches with some text. """
|
||||
@ -161,56 +132,35 @@ class SubstituteTextPattern(HtmlPattern):
|
||||
return result
|
||||
|
||||
class SmartyExtension(Extension):
|
||||
def __init__(self, *args, **kwargs):
|
||||
def __init__(self, configs):
|
||||
self.config = {
|
||||
'smart_quotes': [True, 'Educate quotes'],
|
||||
'smart_angled_quotes': [False, 'Educate angled quotes'],
|
||||
'smart_dashes': [True, 'Educate dashes'],
|
||||
'smart_ellipses': [True, 'Educate ellipses'],
|
||||
'substitutions' : [{}, 'Overwrite default substitutions'],
|
||||
'smart_ellipses': [True, 'Educate ellipses']
|
||||
}
|
||||
super(SmartyExtension, self).__init__(*args, **kwargs)
|
||||
self.substitutions = dict(substitutions)
|
||||
self.substitutions.update(self.getConfig('substitutions', default={}))
|
||||
for key, value in configs:
|
||||
self.setConfig(key, parseBoolValue(value))
|
||||
|
||||
def _addPatterns(self, md, patterns, serie):
|
||||
for ind, pattern in enumerate(patterns):
|
||||
pattern += (md,)
|
||||
pattern = SubstituteTextPattern(*pattern)
|
||||
after = ('>smarty-%s-%d' % (serie, ind - 1) if ind else '_begin')
|
||||
after = ('>smarty-%s-%d' % (serie, ind - 1) if ind else '>entity')
|
||||
name = 'smarty-%s-%d' % (serie, ind)
|
||||
self.inlinePatterns.add(name, pattern, after)
|
||||
md.inlinePatterns.add(name, pattern, after)
|
||||
|
||||
def educateDashes(self, md):
|
||||
emDashesPattern = SubstituteTextPattern(r'(?<!-)---(?!-)',
|
||||
(self.substitutions['mdash'],), md)
|
||||
enDashesPattern = SubstituteTextPattern(r'(?<!-)--(?!-)',
|
||||
(self.substitutions['ndash'],), md)
|
||||
self.inlinePatterns.add('smarty-em-dashes', emDashesPattern, '_begin')
|
||||
self.inlinePatterns.add('smarty-en-dashes', enDashesPattern,
|
||||
emDashesPattern = SubstituteTextPattern(r'(?<!-)---(?!-)', ('—',), md)
|
||||
enDashesPattern = SubstituteTextPattern(r'(?<!-)--(?!-)', ('–',), md)
|
||||
md.inlinePatterns.add('smarty-em-dashes', emDashesPattern, '>entity')
|
||||
md.inlinePatterns.add('smarty-en-dashes', enDashesPattern,
|
||||
'>smarty-em-dashes')
|
||||
|
||||
def educateEllipses(self, md):
|
||||
ellipsesPattern = SubstituteTextPattern(r'(?<!\.)\.{3}(?!\.)',
|
||||
(self.substitutions['ellipsis'],), md)
|
||||
self.inlinePatterns.add('smarty-ellipses', ellipsesPattern, '_begin')
|
||||
|
||||
def educateAngledQuotes(self, md):
|
||||
leftAngledQuotePattern = SubstituteTextPattern(r'\<\<',
|
||||
(self.substitutions['left-angle-quote'],), md)
|
||||
rightAngledQuotePattern = SubstituteTextPattern(r'\>\>',
|
||||
(self.substitutions['right-angle-quote'],), md)
|
||||
self.inlinePatterns.add('smarty-left-angle-quotes',
|
||||
leftAngledQuotePattern, '_begin')
|
||||
self.inlinePatterns.add('smarty-right-angle-quotes',
|
||||
rightAngledQuotePattern, '>smarty-left-angle-quotes')
|
||||
ellipsesPattern = SubstituteTextPattern(r'(?<!\.)\.{3}(?!\.)', ('…',), md)
|
||||
md.inlinePatterns.add('smarty-ellipses', ellipsesPattern, '>entity')
|
||||
|
||||
def educateQuotes(self, md):
|
||||
configs = self.getConfigs()
|
||||
lsquo = self.substitutions['left-single-quote']
|
||||
rsquo = self.substitutions['right-single-quote']
|
||||
ldquo = self.substitutions['left-double-quote']
|
||||
rdquo = self.substitutions['right-double-quote']
|
||||
patterns = (
|
||||
(singleQuoteStartRe, (rsquo,)),
|
||||
(doubleQuoteStartRe, (rdquo,)),
|
||||
@ -229,19 +179,13 @@ class SmartyExtension(Extension):
|
||||
|
||||
def extendMarkdown(self, md, md_globals):
|
||||
configs = self.getConfigs()
|
||||
self.inlinePatterns = OrderedDict()
|
||||
if configs['smart_ellipses']:
|
||||
self.educateEllipses(md)
|
||||
if configs['smart_quotes']:
|
||||
self.educateQuotes(md)
|
||||
if configs['smart_angled_quotes']:
|
||||
self.educateAngledQuotes(md)
|
||||
if configs['smart_dashes']:
|
||||
self.educateDashes(md)
|
||||
inlineProcessor = InlineProcessor(md)
|
||||
inlineProcessor.inlinePatterns = self.inlinePatterns
|
||||
md.treeprocessors.add('smarty', inlineProcessor, '_end')
|
||||
if configs['smart_ellipses']:
|
||||
self.educateEllipses(md)
|
||||
md.ESCAPED_CHARS.extend(['"', "'"])
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return SmartyExtension(*args, **kwargs)
|
||||
def makeExtension(configs=None):
|
||||
return SmartyExtension(configs)
|
||||
|
||||
@ -4,15 +4,14 @@ Tables Extension for Python-Markdown
|
||||
|
||||
Added parsing of tables to Python-Markdown.
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/tables.html>
|
||||
for documentation.
|
||||
A simple example:
|
||||
|
||||
Original code Copyright 2009 [Waylan Limberg](http://achinghead.com)
|
||||
|
||||
All changes Copyright 2008-2014 The Python Markdown Project
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
First Header | Second Header
|
||||
------------- | -------------
|
||||
Content Cell | Content Cell
|
||||
Content Cell | Content Cell
|
||||
|
||||
Copyright 2009 - [Waylan Limberg](http://achinghead.com)
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
@ -72,7 +71,7 @@ class TableProcessor(BlockProcessor):
|
||||
c = etree.SubElement(tr, tag)
|
||||
try:
|
||||
c.text = cells[i].strip()
|
||||
except IndexError: #pragma: no cover
|
||||
except IndexError:
|
||||
c.text = ""
|
||||
if a:
|
||||
c.set('align', a)
|
||||
@ -97,6 +96,5 @@ class TableExtension(Extension):
|
||||
'<hashheader')
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return TableExtension(*args, **kwargs)
|
||||
|
||||
def makeExtension(configs={}):
|
||||
return TableExtension(configs=configs)
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
"""
|
||||
Table of Contents Extension for Python-Markdown
|
||||
===============================================
|
||||
* * *
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/toc.html>
|
||||
for documentation.
|
||||
(c) 2008 [Jack Miller](http://codezen.org)
|
||||
|
||||
Oringinal code Copyright 2008 [Jack Miller](http://codezen.org)
|
||||
|
||||
All changes Copyright 2008-2014 The Python Markdown Project
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
Dependencies:
|
||||
* [Markdown 2.1+](http://packages.python.org/Markdown/)
|
||||
|
||||
"""
|
||||
|
||||
@ -27,59 +23,60 @@ def order_toc_list(toc_list):
|
||||
[{'level': 1}, {'level': 2}]
|
||||
=>
|
||||
[{'level': 1, 'children': [{'level': 2, 'children': []}]}]
|
||||
|
||||
|
||||
A wrong list is also converted:
|
||||
[{'level': 2}, {'level': 1}]
|
||||
=>
|
||||
[{'level': 2, 'children': []}, {'level': 1, 'children': []}]
|
||||
"""
|
||||
|
||||
ordered_list = []
|
||||
if len(toc_list):
|
||||
# Initialize everything by processing the first entry
|
||||
last = toc_list.pop(0)
|
||||
last['children'] = []
|
||||
levels = [last['level']]
|
||||
ordered_list.append(last)
|
||||
parents = []
|
||||
|
||||
# Walk the rest nesting the entries properly
|
||||
while toc_list:
|
||||
t = toc_list.pop(0)
|
||||
current_level = t['level']
|
||||
t['children'] = []
|
||||
|
||||
# Reduce depth if current level < last item's level
|
||||
if current_level < levels[-1]:
|
||||
# Pop last level since we know we are less than it
|
||||
levels.pop()
|
||||
|
||||
# Pop parents and levels we are less than or equal to
|
||||
to_pop = 0
|
||||
for p in reversed(parents):
|
||||
if current_level <= p['level']:
|
||||
to_pop += 1
|
||||
else:
|
||||
break
|
||||
if to_pop:
|
||||
levels = levels[:-to_pop]
|
||||
parents = parents[:-to_pop]
|
||||
|
||||
# Note current level as last
|
||||
levels.append(current_level)
|
||||
|
||||
# Level is the same, so append to the current parent (if available)
|
||||
if current_level == levels[-1]:
|
||||
(parents[-1]['children'] if parents else ordered_list).append(t)
|
||||
|
||||
# Current level is > last item's level,
|
||||
# So make last item a parent and append current as child
|
||||
|
||||
def build_correct(remaining_list, prev_elements=[{'level': 1000}]):
|
||||
|
||||
if not remaining_list:
|
||||
return [], []
|
||||
|
||||
current = remaining_list.pop(0)
|
||||
if not 'children' in current.keys():
|
||||
current['children'] = []
|
||||
|
||||
if not prev_elements:
|
||||
# This happens for instance with [8, 1, 1], ie. when some
|
||||
# header level is outside a scope. We treat it as a
|
||||
# top-level
|
||||
next_elements, children = build_correct(remaining_list, [current])
|
||||
current['children'].append(children)
|
||||
return [current] + next_elements, []
|
||||
|
||||
prev_element = prev_elements.pop()
|
||||
children = []
|
||||
next_elements = []
|
||||
# Is current part of the child list or next list?
|
||||
if current['level'] > prev_element['level']:
|
||||
#print "%d is a child of %d" % (current['level'], prev_element['level'])
|
||||
prev_elements.append(prev_element)
|
||||
prev_elements.append(current)
|
||||
prev_element['children'].append(current)
|
||||
next_elements2, children2 = build_correct(remaining_list, prev_elements)
|
||||
children += children2
|
||||
next_elements += next_elements2
|
||||
else:
|
||||
#print "%d is ancestor of %d" % (current['level'], prev_element['level'])
|
||||
if not prev_elements:
|
||||
#print "No previous elements, so appending to the next set"
|
||||
next_elements.append(current)
|
||||
prev_elements = [current]
|
||||
next_elements2, children2 = build_correct(remaining_list, prev_elements)
|
||||
current['children'].extend(children2)
|
||||
else:
|
||||
last['children'].append(t)
|
||||
parents.append(last)
|
||||
levels.append(current_level)
|
||||
last = t
|
||||
|
||||
#print "Previous elements, comparing to those first"
|
||||
remaining_list.insert(0, current)
|
||||
next_elements2, children2 = build_correct(remaining_list, prev_elements)
|
||||
children.extend(children2)
|
||||
next_elements += next_elements2
|
||||
|
||||
return next_elements, children
|
||||
|
||||
ordered_list, __ = build_correct(toc_list)
|
||||
return ordered_list
|
||||
|
||||
|
||||
@ -207,26 +204,26 @@ class TocExtension(Extension):
|
||||
|
||||
TreeProcessorClass = TocTreeprocessor
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.config = {
|
||||
"marker" : ["[TOC]",
|
||||
"Text to find and replace with Table of Contents - "
|
||||
"Defaults to \"[TOC]\""],
|
||||
"slugify" : [slugify,
|
||||
"Function to generate anchors based on header text - "
|
||||
"Defaults to the headerid ext's slugify function."],
|
||||
"title" : ["",
|
||||
"Title to insert into TOC <div> - "
|
||||
"Defaults to an empty string"],
|
||||
"anchorlink" : [0,
|
||||
"1 if header should be a self link - "
|
||||
"Defaults to 0"],
|
||||
"permalink" : [0,
|
||||
"1 or link text if a Sphinx-style permalink should be added - "
|
||||
"Defaults to 0"]
|
||||
}
|
||||
def __init__(self, configs=[]):
|
||||
self.config = { "marker" : ["[TOC]",
|
||||
"Text to find and replace with Table of Contents -"
|
||||
"Defaults to \"[TOC]\""],
|
||||
"slugify" : [slugify,
|
||||
"Function to generate anchors based on header text-"
|
||||
"Defaults to the headerid ext's slugify function."],
|
||||
"title" : [None,
|
||||
"Title to insert into TOC <div> - "
|
||||
"Defaults to None"],
|
||||
"anchorlink" : [0,
|
||||
"1 if header should be a self link"
|
||||
"Defaults to 0"],
|
||||
"permalink" : [0,
|
||||
"1 or link text if a Sphinx-style permalink should be added",
|
||||
"Defaults to 0"]
|
||||
}
|
||||
|
||||
super(TocExtension, self).__init__(*args, **kwargs)
|
||||
for key, value in configs:
|
||||
self.setConfig(key, value)
|
||||
|
||||
def extendMarkdown(self, md, md_globals):
|
||||
tocext = self.TreeProcessorClass(md)
|
||||
@ -239,5 +236,5 @@ class TocExtension(Extension):
|
||||
md.treeprocessors.add("toc", tocext, "_end")
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs):
|
||||
return TocExtension(*args, **kwargs)
|
||||
def makeExtension(configs={}):
|
||||
return TocExtension(configs=configs)
|
||||
|
||||
@ -2,17 +2,78 @@
|
||||
WikiLinks Extension for Python-Markdown
|
||||
======================================
|
||||
|
||||
Converts [[WikiLinks]] to relative links.
|
||||
Converts [[WikiLinks]] to relative links. Requires Python-Markdown 2.0+
|
||||
|
||||
See <https://pythonhosted.org/Markdown/extensions/wikilinks.html>
|
||||
for documentation.
|
||||
Basic usage:
|
||||
|
||||
Original code Copyright [Waylan Limberg](http://achinghead.com/).
|
||||
>>> import markdown
|
||||
>>> text = "Some text with a [[WikiLink]]."
|
||||
>>> html = markdown.markdown(text, ['wikilinks'])
|
||||
>>> print html
|
||||
<p>Some text with a <a class="wikilink" href="/WikiLink/">WikiLink</a>.</p>
|
||||
|
||||
All changes Copyright The Python Markdown Project
|
||||
Whitespace behavior:
|
||||
|
||||
>>> print markdown.markdown('[[ foo bar_baz ]]', ['wikilinks'])
|
||||
<p><a class="wikilink" href="/foo_bar_baz/">foo bar_baz</a></p>
|
||||
>>> print markdown.markdown('foo [[ ]] bar', ['wikilinks'])
|
||||
<p>foo bar</p>
|
||||
|
||||
To define custom settings the simple way:
|
||||
|
||||
>>> print markdown.markdown(text,
|
||||
... ['wikilinks(base_url=/wiki/,end_url=.html,html_class=foo)']
|
||||
... )
|
||||
<p>Some text with a <a class="foo" href="/wiki/WikiLink.html">WikiLink</a>.</p>
|
||||
|
||||
Custom settings the complex way:
|
||||
|
||||
>>> md = markdown.Markdown(
|
||||
... extensions = ['wikilinks'],
|
||||
... extension_configs = {'wikilinks': [
|
||||
... ('base_url', 'http://example.com/'),
|
||||
... ('end_url', '.html'),
|
||||
... ('html_class', '') ]},
|
||||
... safe_mode = True)
|
||||
>>> print md.convert(text)
|
||||
<p>Some text with a <a href="http://example.com/WikiLink.html">WikiLink</a>.</p>
|
||||
|
||||
Use MetaData with mdx_meta.py (Note the blank html_class in MetaData):
|
||||
|
||||
>>> text = """wiki_base_url: http://example.com/
|
||||
... wiki_end_url: .html
|
||||
... wiki_html_class:
|
||||
...
|
||||
... Some text with a [[WikiLink]]."""
|
||||
>>> md = markdown.Markdown(extensions=['meta', 'wikilinks'])
|
||||
>>> print md.convert(text)
|
||||
<p>Some text with a <a href="http://example.com/WikiLink.html">WikiLink</a>.</p>
|
||||
|
||||
MetaData should not carry over to next document:
|
||||
|
||||
>>> print md.convert("No [[MetaData]] here.")
|
||||
<p>No <a class="wikilink" href="/MetaData/">MetaData</a> here.</p>
|
||||
|
||||
Define a custom URL builder:
|
||||
|
||||
>>> def my_url_builder(label, base, end):
|
||||
... return '/bar/'
|
||||
>>> md = markdown.Markdown(extensions=['wikilinks'],
|
||||
... extension_configs={'wikilinks' : [('build_url', my_url_builder)]})
|
||||
>>> print md.convert('[[foo]]')
|
||||
<p><a class="wikilink" href="/bar/">foo</a></p>
|
||||
|
||||
From the command line:
|
||||
|
||||
python markdown.py -x wikilinks(base_url=http://example.com/,end_url=.html,html_class=foo) src.txt
|
||||
|
||||
By [Waylan Limberg](http://achinghead.com/).
|
||||
|
||||
License: [BSD](http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Dependencies:
|
||||
* [Python 2.3+](http://python.org)
|
||||
* [Markdown 2.0+](http://packages.python.org/Markdown/)
|
||||
'''
|
||||
|
||||
from __future__ import absolute_import
|
||||
@ -29,17 +90,19 @@ def build_url(label, base, end):
|
||||
|
||||
|
||||
class WikiLinkExtension(Extension):
|
||||
|
||||
def __init__ (self, *args, **kwargs):
|
||||
def __init__(self, configs):
|
||||
# set extension defaults
|
||||
self.config = {
|
||||
'base_url' : ['/', 'String to append to beginning or URL.'],
|
||||
'end_url' : ['/', 'String to append to end of URL.'],
|
||||
'html_class' : ['wikilink', 'CSS hook. Leave blank for none.'],
|
||||
'build_url' : [build_url, 'Callable formats URL from label.'],
|
||||
'base_url' : ['/', 'String to append to beginning or URL.'],
|
||||
'end_url' : ['/', 'String to append to end of URL.'],
|
||||
'html_class' : ['wikilink', 'CSS hook. Leave blank for none.'],
|
||||
'build_url' : [build_url, 'Callable formats URL from label.'],
|
||||
}
|
||||
configs = dict(configs) or {}
|
||||
# Override defaults with user settings
|
||||
for key, value in configs.items():
|
||||
self.setConfig(key, value)
|
||||
|
||||
super(WikiLinkExtension, self).__init__(*args, **kwargs)
|
||||
|
||||
def extendMarkdown(self, md, md_globals):
|
||||
self.md = md
|
||||
|
||||
@ -84,5 +147,5 @@ class WikiLinks(Pattern):
|
||||
return base_url, end_url, html_class
|
||||
|
||||
|
||||
def makeExtension(*args, **kwargs) :
|
||||
return WikiLinkExtension(*args, **kwargs)
|
||||
def makeExtension(configs=None) :
|
||||
return WikiLinkExtension(configs=configs)
|
||||
|
||||
@ -46,13 +46,13 @@ from __future__ import unicode_literals
|
||||
from . import util
|
||||
from . import odict
|
||||
import re
|
||||
try: #pragma: no cover
|
||||
try:
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
except ImportError: #pragma: no cover
|
||||
except ImportError:
|
||||
from urlparse import urlparse, urlunparse
|
||||
try: #pragma: no cover
|
||||
try:
|
||||
from html import entities
|
||||
except ImportError: #pragma: no cover
|
||||
except ImportError:
|
||||
import htmlentitydefs as entities
|
||||
|
||||
|
||||
@ -75,8 +75,7 @@ def build_inlinepatterns(md_instance, **kwargs):
|
||||
inlinePatterns["html"] = HtmlPattern(HTML_RE, md_instance)
|
||||
inlinePatterns["entity"] = HtmlPattern(ENTITY_RE, md_instance)
|
||||
inlinePatterns["not_strong"] = SimpleTextPattern(NOT_STRONG_RE)
|
||||
inlinePatterns["em_strong"] = DoubleTagPattern(EM_STRONG_RE, 'strong,em')
|
||||
inlinePatterns["strong_em"] = DoubleTagPattern(STRONG_EM_RE, 'em,strong')
|
||||
inlinePatterns["strong_em"] = DoubleTagPattern(STRONG_EM_RE, 'strong,em')
|
||||
inlinePatterns["strong"] = SimpleTagPattern(STRONG_RE, 'strong')
|
||||
inlinePatterns["emphasis"] = SimpleTagPattern(EMPHASIS_RE, 'em')
|
||||
if md_instance.smart_emphasis:
|
||||
@ -101,8 +100,7 @@ BACKTICK_RE = r'(?<!\\)(`+)(.+?)(?<!`)\2(?!`)' # `e=f()` or ``e=f("`")``
|
||||
ESCAPE_RE = r'\\(.)' # \<
|
||||
EMPHASIS_RE = r'(\*)([^\*]+)\2' # *emphasis*
|
||||
STRONG_RE = r'(\*{2}|_{2})(.+?)\2' # **strong**
|
||||
EM_STRONG_RE = r'(\*|_)\2{2}(.+?)\2(.*?)\2{2}' # ***strongem*** or ***em*strong**
|
||||
STRONG_EM_RE = r'(\*|_)\2{2}(.+?)\2{2}(.*?)\2' # ***strong**em*
|
||||
STRONG_EM_RE = r'(\*{3}|_{3})(.+?)\2' # ***strong***
|
||||
SMART_EMPHASIS_RE = r'(?<!\w)(_)(?!_)(.+?)(?<!_)\2(?!\w)' # _smart_emphasis_
|
||||
EMPHASIS_2_RE = r'(_)(.+?)\2' # _emphasis_
|
||||
LINK_RE = NOIMG + BRK + \
|
||||
@ -158,7 +156,7 @@ class Pattern(object):
|
||||
|
||||
"""
|
||||
self.pattern = pattern
|
||||
self.compiled_re = re.compile("^(.*?)%s(.*?)$" % pattern,
|
||||
self.compiled_re = re.compile("^(.*?)%s(.*?)$" % pattern,
|
||||
re.DOTALL | re.UNICODE)
|
||||
|
||||
# Api for Markdown to pass safe_mode into instance
|
||||
@ -180,7 +178,7 @@ class Pattern(object):
|
||||
* m: A re match object containing a match of the pattern.
|
||||
|
||||
"""
|
||||
pass #pragma: no cover
|
||||
pass
|
||||
|
||||
def type(self):
|
||||
""" Return class name, to define pattern type """
|
||||
@ -190,9 +188,9 @@ class Pattern(object):
|
||||
""" Return unescaped text given text with an inline placeholder. """
|
||||
try:
|
||||
stash = self.markdown.treeprocessors['inline'].stashed_nodes
|
||||
except KeyError: #pragma: no cover
|
||||
except KeyError:
|
||||
return text
|
||||
def itertext(el): #pragma: no cover
|
||||
def itertext(el):
|
||||
' Reimplement Element.itertext for older python versions '
|
||||
tag = el.tag
|
||||
if not isinstance(tag, util.string_type) and tag is not None:
|
||||
@ -212,14 +210,17 @@ class Pattern(object):
|
||||
return value
|
||||
else:
|
||||
# An etree Element - return text content only
|
||||
return ''.join(itertext(value))
|
||||
return ''.join(itertext(value))
|
||||
return util.INLINE_PLACEHOLDER_RE.sub(get_stash, text)
|
||||
|
||||
|
||||
class SimpleTextPattern(Pattern):
|
||||
""" Return a simple text of group(2) of a Pattern. """
|
||||
def handleMatch(self, m):
|
||||
return m.group(2)
|
||||
text = m.group(2)
|
||||
if text == util.INLINE_PLACEHOLDER_PREFIX:
|
||||
return None
|
||||
return text
|
||||
|
||||
|
||||
class EscapePattern(Pattern):
|
||||
@ -230,7 +231,7 @@ class EscapePattern(Pattern):
|
||||
if char in self.markdown.ESCAPED_CHARS:
|
||||
return '%s%s%s' % (util.STX, ord(char), util.ETX)
|
||||
else:
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
class SimpleTagPattern(Pattern):
|
||||
@ -278,8 +279,6 @@ class DoubleTagPattern(SimpleTagPattern):
|
||||
el1 = util.etree.Element(tag1)
|
||||
el2 = util.etree.SubElement(el1, tag2)
|
||||
el2.text = m.group(3)
|
||||
if len(m.groups())==5:
|
||||
el2.tail = m.group(4)
|
||||
return el1
|
||||
|
||||
|
||||
@ -294,7 +293,7 @@ class HtmlPattern(Pattern):
|
||||
""" Return unescaped text given text with an inline placeholder. """
|
||||
try:
|
||||
stash = self.markdown.treeprocessors['inline'].stashed_nodes
|
||||
except KeyError: #pragma: no cover
|
||||
except KeyError:
|
||||
return text
|
||||
def get_stash(m):
|
||||
id = m.group(1)
|
||||
@ -304,7 +303,7 @@ class HtmlPattern(Pattern):
|
||||
return self.markdown.serializer(value)
|
||||
except:
|
||||
return '\%s' % value
|
||||
|
||||
|
||||
return util.INLINE_PLACEHOLDER_RE.sub(get_stash, text)
|
||||
|
||||
|
||||
@ -324,7 +323,7 @@ class LinkPattern(Pattern):
|
||||
el.set("href", "")
|
||||
|
||||
if title:
|
||||
title = dequote(self.unescape(title))
|
||||
title = dequote(self.unescape(title))
|
||||
el.set("title", title)
|
||||
return el
|
||||
|
||||
@ -348,20 +347,20 @@ class LinkPattern(Pattern):
|
||||
if not self.markdown.safeMode:
|
||||
# Return immediately bipassing parsing.
|
||||
return url
|
||||
|
||||
|
||||
try:
|
||||
scheme, netloc, path, params, query, fragment = url = urlparse(url)
|
||||
except ValueError: #pragma: no cover
|
||||
except ValueError:
|
||||
# Bad url - so bad it couldn't be parsed.
|
||||
return ''
|
||||
|
||||
|
||||
locless_schemes = ['', 'mailto', 'news']
|
||||
allowed_schemes = locless_schemes + ['http', 'https', 'ftp', 'ftps']
|
||||
if scheme not in allowed_schemes:
|
||||
# Not a known (allowed) scheme. Not safe.
|
||||
return ''
|
||||
|
||||
if netloc == '' and scheme not in locless_schemes: #pragma: no cover
|
||||
|
||||
if netloc == '' and scheme not in locless_schemes:
|
||||
# This should not happen. Treat as suspect.
|
||||
return ''
|
||||
|
||||
|
||||
@ -82,11 +82,11 @@ class OrderedDict(dict):
|
||||
for key in self.keyOrder:
|
||||
yield self[key]
|
||||
|
||||
if util.PY3: #pragma: no cover
|
||||
if util.PY3:
|
||||
items = _iteritems
|
||||
keys = _iterkeys
|
||||
values = _itervalues
|
||||
else: #pragma: no cover
|
||||
else:
|
||||
iteritems = _iteritems
|
||||
iterkeys = _iterkeys
|
||||
itervalues = _itervalues
|
||||
|
||||
@ -42,7 +42,7 @@ class Postprocessor(util.Processor):
|
||||
(possibly modified) string.
|
||||
|
||||
"""
|
||||
pass #pragma: no cover
|
||||
pass
|
||||
|
||||
|
||||
class RawHtmlPostprocessor(Postprocessor):
|
||||
|
||||
@ -41,7 +41,7 @@ class Preprocessor(util.Processor):
|
||||
the (possibly modified) list of lines.
|
||||
|
||||
"""
|
||||
pass #pragma: no cover
|
||||
pass
|
||||
|
||||
|
||||
class NormalizeWhitespace(Preprocessor):
|
||||
@ -174,10 +174,9 @@ class HtmlBlockPreprocessor(Preprocessor):
|
||||
else: # raw html
|
||||
if len(items) - right_listindex <= 1: # last element
|
||||
right_listindex -= 1
|
||||
offset = 1 if i == right_listindex else 0
|
||||
placeholder = self.markdown.htmlStash.store('\n\n'.join(
|
||||
items[i:right_listindex + offset]))
|
||||
del items[i:right_listindex + offset]
|
||||
items[i:right_listindex + 1]))
|
||||
del items[i:right_listindex + 1]
|
||||
items.insert(i, placeholder)
|
||||
return items
|
||||
|
||||
|
||||
@ -42,9 +42,9 @@ from __future__ import unicode_literals
|
||||
from . import util
|
||||
ElementTree = util.etree.ElementTree
|
||||
QName = util.etree.QName
|
||||
if hasattr(util.etree, 'test_comment'): #pragma: no cover
|
||||
if hasattr(util.etree, 'test_comment'):
|
||||
Comment = util.etree.test_comment
|
||||
else: #pragma: no cover
|
||||
else:
|
||||
Comment = util.etree.Comment
|
||||
PI = util.etree.PI
|
||||
ProcessingInstruction = util.etree.ProcessingInstruction
|
||||
@ -56,7 +56,7 @@ HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr",
|
||||
|
||||
try:
|
||||
HTML_EMPTY = set(HTML_EMPTY)
|
||||
except NameError: #pragma: no cover
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
_namespace_map = {
|
||||
@ -73,7 +73,7 @@ _namespace_map = {
|
||||
}
|
||||
|
||||
|
||||
def _raise_serialization_error(text): #pragma: no cover
|
||||
def _raise_serialization_error(text):
|
||||
raise TypeError(
|
||||
"cannot serialize %r (type %s)" % (text, type(text).__name__)
|
||||
)
|
||||
@ -81,7 +81,7 @@ def _raise_serialization_error(text): #pragma: no cover
|
||||
def _encode(text, encoding):
|
||||
try:
|
||||
return text.encode(encoding, "xmlcharrefreplace")
|
||||
except (TypeError, AttributeError): #pragma: no cover
|
||||
except (TypeError, AttributeError):
|
||||
_raise_serialization_error(text)
|
||||
|
||||
def _escape_cdata(text):
|
||||
@ -97,7 +97,7 @@ def _escape_cdata(text):
|
||||
if ">" in text:
|
||||
text = text.replace(">", ">")
|
||||
return text
|
||||
except (TypeError, AttributeError): #pragma: no cover
|
||||
except (TypeError, AttributeError):
|
||||
_raise_serialization_error(text)
|
||||
|
||||
|
||||
@ -115,7 +115,7 @@ def _escape_attrib(text):
|
||||
if "\n" in text:
|
||||
text = text.replace("\n", " ")
|
||||
return text
|
||||
except (TypeError, AttributeError): #pragma: no cover
|
||||
except (TypeError, AttributeError):
|
||||
_raise_serialization_error(text)
|
||||
|
||||
def _escape_attrib_html(text):
|
||||
@ -130,7 +130,7 @@ def _escape_attrib_html(text):
|
||||
if "\"" in text:
|
||||
text = text.replace("\"", """)
|
||||
return text
|
||||
except (TypeError, AttributeError): #pragma: no cover
|
||||
except (TypeError, AttributeError):
|
||||
_raise_serialization_error(text)
|
||||
|
||||
|
||||
@ -240,7 +240,7 @@ def _namespaces(elem, default_namespace=None):
|
||||
"default_namespace option"
|
||||
)
|
||||
qnames[qname] = qname
|
||||
except TypeError: #pragma: no cover
|
||||
except TypeError:
|
||||
_raise_serialization_error(qname)
|
||||
|
||||
# populate qname and namespaces table
|
||||
|
||||
@ -34,11 +34,11 @@ class Treeprocessor(util.Processor):
|
||||
def run(self, root):
|
||||
"""
|
||||
Subclasses of Treeprocessor should implement a `run` method, which
|
||||
takes a root ElementTree. This method can return another ElementTree
|
||||
object, and the existing root ElementTree will be replaced, or it can
|
||||
takes a root ElementTree. This method can return another ElementTree
|
||||
object, and the existing root ElementTree will be replaced, or it can
|
||||
modify the current tree and return None.
|
||||
"""
|
||||
pass #pragma: no cover
|
||||
pass
|
||||
|
||||
|
||||
class InlineProcessor(Treeprocessor):
|
||||
@ -53,7 +53,6 @@ class InlineProcessor(Treeprocessor):
|
||||
+ len(self.__placeholder_suffix)
|
||||
self.__placeholder_re = util.INLINE_PLACEHOLDER_RE
|
||||
self.markdown = md
|
||||
self.inlinePatterns = md.inlinePatterns
|
||||
|
||||
def __makePlaceholder(self, type):
|
||||
""" Generate a placeholder """
|
||||
@ -71,7 +70,7 @@ class InlineProcessor(Treeprocessor):
|
||||
* index: index, from which we start search
|
||||
|
||||
Returns: placeholder id and string index, after the found placeholder.
|
||||
|
||||
|
||||
"""
|
||||
m = self.__placeholder_re.search(data, index)
|
||||
if m:
|
||||
@ -100,9 +99,9 @@ class InlineProcessor(Treeprocessor):
|
||||
"""
|
||||
if not isinstance(data, util.AtomicString):
|
||||
startIndex = 0
|
||||
while patternIndex < len(self.inlinePatterns):
|
||||
while patternIndex < len(self.markdown.inlinePatterns):
|
||||
data, matched, startIndex = self.__applyPattern(
|
||||
self.inlinePatterns.value_for_index(patternIndex),
|
||||
self.markdown.inlinePatterns.value_for_index(patternIndex),
|
||||
data, patternIndex, startIndex)
|
||||
if not matched:
|
||||
patternIndex += 1
|
||||
@ -129,10 +128,11 @@ class InlineProcessor(Treeprocessor):
|
||||
text = subnode.tail
|
||||
subnode.tail = None
|
||||
|
||||
childResult = self.__processPlaceholders(text, subnode, isText)
|
||||
childResult = self.__processPlaceholders(text, subnode)
|
||||
|
||||
if not isText and node is not subnode:
|
||||
pos = list(node).index(subnode) + 1
|
||||
pos = list(node).index(subnode)
|
||||
node.remove(subnode)
|
||||
else:
|
||||
pos = 0
|
||||
|
||||
@ -140,7 +140,7 @@ class InlineProcessor(Treeprocessor):
|
||||
for newChild in childResult:
|
||||
node.insert(pos, newChild)
|
||||
|
||||
def __processPlaceholders(self, data, parent, isText=True):
|
||||
def __processPlaceholders(self, data, parent):
|
||||
"""
|
||||
Process string with placeholders and generate ElementTree tree.
|
||||
|
||||
@ -150,7 +150,7 @@ class InlineProcessor(Treeprocessor):
|
||||
* parent: Element, which contains processing inline data
|
||||
|
||||
Returns: list with ElementTree elements with applied inline patterns.
|
||||
|
||||
|
||||
"""
|
||||
def linkText(text):
|
||||
if text:
|
||||
@ -159,11 +159,6 @@ class InlineProcessor(Treeprocessor):
|
||||
result[-1].tail += text
|
||||
else:
|
||||
result[-1].tail = text
|
||||
elif not isText:
|
||||
if parent.tail:
|
||||
parent.tail += text
|
||||
else:
|
||||
parent.tail = text
|
||||
else:
|
||||
if parent.text:
|
||||
parent.text += text
|
||||
@ -187,7 +182,7 @@ class InlineProcessor(Treeprocessor):
|
||||
for child in [node] + list(node):
|
||||
if child.tail:
|
||||
if child.tail.strip():
|
||||
self.__processElementText(node, child, False)
|
||||
self.__processElementText(node, child,False)
|
||||
if child.text:
|
||||
if child.text.strip():
|
||||
self.__processElementText(child, child)
|
||||
@ -244,7 +239,7 @@ class InlineProcessor(Treeprocessor):
|
||||
# We need to process current node too
|
||||
for child in [node] + list(node):
|
||||
if not isString(node):
|
||||
if child.text:
|
||||
if child.text:
|
||||
child.text = self.__handleInline(child.text,
|
||||
patternIndex + 1)
|
||||
if child.tail:
|
||||
@ -292,10 +287,11 @@ class InlineProcessor(Treeprocessor):
|
||||
if child.tail:
|
||||
tail = self.__handleInline(child.tail)
|
||||
dumby = util.etree.Element('d')
|
||||
child.tail = None
|
||||
tailResult = self.__processPlaceholders(tail, dumby, False)
|
||||
if dumby.tail:
|
||||
child.tail = dumby.tail
|
||||
tailResult = self.__processPlaceholders(tail, dumby)
|
||||
if dumby.text:
|
||||
child.tail = dumby.text
|
||||
else:
|
||||
child.tail = None
|
||||
pos = list(currElement).index(child) + 1
|
||||
tailResult.reverse()
|
||||
for newChild in tailResult:
|
||||
@ -307,7 +303,7 @@ class InlineProcessor(Treeprocessor):
|
||||
if self.markdown.enable_attributes:
|
||||
if element.text and isString(element.text):
|
||||
element.text = \
|
||||
inlinepatterns.handleAttributes(element.text,
|
||||
inlinepatterns.handleAttributes(element.text,
|
||||
element)
|
||||
i = 0
|
||||
for newChild in lst:
|
||||
@ -361,4 +357,4 @@ class PrettifyTreeprocessor(Treeprocessor):
|
||||
pres = root.getiterator('pre')
|
||||
for pre in pres:
|
||||
if len(pre) and pre[0].tag == 'code':
|
||||
pre[0].text = util.AtomicString(pre[0].text.rstrip() + '\n')
|
||||
pre[0].text = pre[0].text.rstrip() + '\n'
|
||||
|
||||
@ -10,11 +10,11 @@ Python 3 Stuff
|
||||
"""
|
||||
PY3 = sys.version_info[0] == 3
|
||||
|
||||
if PY3: #pragma: no cover
|
||||
if PY3:
|
||||
string_type = str
|
||||
text_type = str
|
||||
int2str = chr
|
||||
else: #pragma: no cover
|
||||
else:
|
||||
string_type = basestring
|
||||
text_type = unicode
|
||||
int2str = unichr
|
||||
@ -58,15 +58,14 @@ RTL_BIDI_RANGES = ( ('\u0590', '\u07FF'),
|
||||
# Extensions should use "markdown.util.etree" instead of "etree" (or do `from
|
||||
# markdown.util import etree`). Do not import it by yourself.
|
||||
|
||||
try: #pragma: no cover
|
||||
# Is the C implementation of ElementTree available?
|
||||
try: # Is the C implementation of ElementTree available?
|
||||
import xml.etree.cElementTree as etree
|
||||
from xml.etree.ElementTree import Comment
|
||||
# Serializers (including ours) test with non-c Comment
|
||||
etree.test_comment = Comment
|
||||
if etree.VERSION < "1.0.5":
|
||||
raise RuntimeError("cElementTree version 1.0.5 or higher is required.")
|
||||
except (ImportError, RuntimeError): #pragma: no cover
|
||||
except (ImportError, RuntimeError):
|
||||
# Use the Python implementation of ElementTree?
|
||||
import xml.etree.ElementTree as etree
|
||||
if etree.VERSION < "1.1":
|
||||
@ -86,20 +85,15 @@ def isBlockLevel(tag):
|
||||
# Some ElementTree tags are not strings, so return False.
|
||||
return False
|
||||
|
||||
def parseBoolValue(value, fail_on_errors=True, preserve_none=False):
|
||||
def parseBoolValue(value, fail_on_errors=True):
|
||||
"""Parses a string representing bool value. If parsing was successful,
|
||||
returns True or False. If preserve_none=True, returns True, False,
|
||||
or None. If parsing was not successful, raises ValueError, or, if
|
||||
fail_on_errors=False, returns None."""
|
||||
returns True or False. If parsing was not successful, raises
|
||||
ValueError, or, if fail_on_errors=False, returns None."""
|
||||
if not isinstance(value, string_type):
|
||||
if preserve_none and value is None:
|
||||
return value
|
||||
return bool(value)
|
||||
elif preserve_none and value.lower() == 'none':
|
||||
return None
|
||||
elif value.lower() in ('true', 'yes', 'y', 'on', '1'):
|
||||
return True
|
||||
elif value.lower() in ('false', 'no', 'n', 'off', '0', 'none'):
|
||||
elif value.lower() in ('false', 'no', 'n', 'off', '0'):
|
||||
return False
|
||||
elif fail_on_errors:
|
||||
raise ValueError('Cannot parse bool value: %r' % value)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user