Skip to content

Commit

Permalink
Inline processor (#220)
Browse files Browse the repository at this point in the history
* Compatibility for new inline processor

ref #215

* Skip future coverage for now

* Exclude coverage on non-legacy import

* Bump version and update changelog
  • Loading branch information
facelessuser authored Jan 18, 2018
1 parent adcd9b2 commit 658bd25
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 40 deletions.
4 changes: 4 additions & 0 deletions docs/src/markdown/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 4.8.1

- **FIX**: Compatibility changes for next Markdown release.

## 4.8.0

- **NEW**: Set progress bar class level increments via `progress_increment` instead of using the hard coded value of `20`.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pymdown-extensions",
"version": "4.8.0",
"version": "4.8.1",
"description": "Extensions for Python Markdown",
"repository": "https://github.com/facelessuser/pymdown-extensions.git",
"author": "Isaac Muse <[email protected]>",
Expand Down
2 changes: 1 addition & 1 deletion pymdownx/__version__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Version."""

# (major, minor, micro, release type, pre-release build, post-release build)
version_info = (4, 8, 0, 'final', 0, 0)
version_info = (4, 8, 1, 'final', 0, 0)


def _version():
Expand Down
76 changes: 54 additions & 22 deletions pymdownx/magiclink.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
"""
from __future__ import unicode_literals
from markdown import Extension
from markdown.inlinepatterns import LinkPattern, Pattern
from markdown.treeprocessors import Treeprocessor
from markdown import util as md_util
from . import util
Expand All @@ -34,12 +33,20 @@
import re
import os

try:
from markdown.inlinepatterns import LinkPattern, Pattern
LEGACY = True
except ImportError: # pragma: no cover
from markdown.inlinepatterns import LinkInlineProcessor, Pattern
LEGACY = False

MAGIC_LINK = 1
MAGIC_AUTO_LINK = 2


# Bare link/email detection
RE_MAIL = r'''(?xi)
(
(?P<mail>
(?<![-/\+@a-z\d_])(?:[-+a-z\d_]([-a-z\d_+]|\.(?!\.))*) # Local part
(?<!\.)@(?:[-a-z\d_]+\.) # @domain part start
(?:(?:[-a-z\d_]|(?<!\.)\.(?!\.))*)[a-z]\b # @domain.end (allow multiple dot names)
Expand All @@ -48,7 +55,7 @@
'''

RE_LINK = r'''(?xi)
(
(?P<link>
(?:(?<=\b)|(?<=_))(?:
(?:ht|f)tps?://(?:(?:[^_\W][-\w]*(?:\.[-\w.]+)+)|localhost)| # (http|ftp)://
(?P<www>w{3}\.)[^_\W][-\w]*(?:\.[-\w.]+)+ # www.
Expand Down Expand Up @@ -481,28 +488,53 @@ def run(self, root):
return root


class MagiclinkPattern(LinkPattern):
"""Convert html, ftp links to clickable links."""
if LEGACY:
class MagiclinkPattern(LinkPattern):
"""Convert html, ftp links to clickable links."""

ANCESTOR_EXCLUDES = ('a',)
ANCESTOR_EXCLUDES = ('a',)

def handleMatch(self, m):
"""Handle URL matches."""
def handleMatch(self, m):
"""Handle URL matches."""

el = md_util.etree.Element("a")
el.text = md_util.AtomicString(m.group(2))
if m.group("www"):
href = "http://%s" % m.group(2)
else:
href = m.group(2)
if self.config['hide_protocol']:
el.text = md_util.AtomicString(el.text[el.text.find("://") + 3:])
el.set("href", self.sanitize_url(self.unescape(href.strip())))
el = md_util.etree.Element("a")
el.text = md_util.AtomicString(m.group('link'))
if m.group("www"):
href = "http://%s" % m.group('link')
else:
href = m.group('link')
if self.config['hide_protocol']:
el.text = md_util.AtomicString(el.text[el.text.find("://") + 3:])
el.set("href", self.sanitize_url(self.unescape(href.strip())))

if self.config.get('repo_url_shortener', False):
el.set('magiclink', md_util.text_type(MAGIC_LINK))
if self.config.get('repo_url_shortener', False):
el.set('magiclink', md_util.text_type(MAGIC_LINK))

return el
return el

else: # pragma: no cover
class MagiclinkPattern(LinkInlineProcessor):
"""Convert html, ftp links to clickable links."""

ANCESTOR_EXCLUDES = ('a',)

def handleMatch(self, m, data):
"""Handle URL matches."""

el = md_util.etree.Element("a")
el.text = md_util.AtomicString(m.group('link'))
if m.group("www"):
href = "http://%s" % m.group('link')
else:
href = m.group('link')
if self.config['hide_protocol']:
el.text = md_util.AtomicString(el.text[el.text.find("://") + 3:])
el.set("href", self.sanitize_url(self.unescape(href.strip())))

if self.config.get('repo_url_shortener', False):
el.set('magiclink', md_util.text_type(MAGIC_LINK))

return el, m.start(0), m.end(0)


class MagiclinkAutoPattern(Pattern):
Expand All @@ -523,7 +555,7 @@ def handleMatch(self, m):
return el


class MagiclinkMailPattern(LinkPattern):
class MagiclinkMailPattern(Pattern):
"""Convert emails to clickable email links."""

ANCESTOR_EXCLUDES = ('a',)
Expand All @@ -536,7 +568,7 @@ def handleMatch(self, m):
"""Handle email link patterns."""

el = md_util.etree.Element("a")
email = self.unescape(m.group(2))
email = self.unescape(m.group('mail'))
href = "mailto:%s" % email
el.text = md_util.AtomicString(''.join([self.email_encode(ord(c)) for c in email]))
el.set("href", ''.join([md_util.AMP_SUBSTITUTE + '#%d;' % ord(c) for c in href]))
Expand Down
58 changes: 42 additions & 16 deletions pymdownx/smartsymbols.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,15 @@
"""
from __future__ import unicode_literals
from markdown import Extension
from markdown.inlinepatterns import HtmlPattern
from markdown.odict import OrderedDict
from markdown.treeprocessors import InlineProcessor
from markdown import treeprocessors

try:
from markdown.inlinepatterns import HtmlPattern
LEGACY = True
except ImportError: # pragma: no cover
from markdown.inlinepatterns import HtmlInlineProcessor
LEGACY = False

RE_TRADE = ("smart-trademark", r'\(tm\)', r'&trade;')
RE_COPY = ("smart-copyright", r'\(c\)', r'&copy;')
Expand Down Expand Up @@ -112,23 +118,43 @@
}


class SmartSymbolsPattern(HtmlPattern):
"""Smart symbols patterns handler."""
if LEGACY:
class SmartSymbolsPattern(HtmlPattern):
"""Smart symbols patterns handler."""

def __init__(self, pattern, replace, md):
"""Setup replace pattern."""
def __init__(self, pattern, replace, md):
"""Setup replace pattern."""

super(SmartSymbolsPattern, self).__init__(pattern)
self.replace = replace
self.md = md
super(SmartSymbolsPattern, self).__init__(pattern)
self.replace = replace
self.md = md

def handleMatch(self, m):
"""Replace symbol."""
def handleMatch(self, m):
"""Replace symbol."""

return self.md.htmlStash.store(
m.expand(self.replace(m) if callable(self.replace) else self.replace),
safe=True
)
return self.md.htmlStash.store(
m.expand(self.replace(m) if callable(self.replace) else self.replace),
safe=True
)

else: # pragma: no cover
class SmartSymbolsPattern(HtmlInlineProcessor):
"""Smart symbols patterns handler."""

def __init__(self, pattern, replace, md):
"""Setup replace pattern."""

super(SmartSymbolsPattern, self).__init__(pattern)
self.replace = replace
self.md = md

def handleMatch(self, m, data):
"""Replace symbol."""

return self.md.htmlStash.store(
m.expand(self.replace(m) if callable(self.replace) else self.replace),
safe=True
), m.start(0), m.end(0)


class SmartSymbolsExtension(Extension):
Expand Down Expand Up @@ -169,7 +195,7 @@ def extendMarkdown(self, md, md_globals):
if configs[k]:
self.add_pattern(v, md)

inline_processor = InlineProcessor(md)
inline_processor = treeprocessors.InlineProcessor(md)
inline_processor.inlinePatterns = self.patterns
md.treeprocessors.add('smart-symbols', inline_processor, '_end')
if "smarty" in md.treeprocessors.keys():
Expand Down

0 comments on commit 658bd25

Please sign in to comment.