Browse files

Use py-gfm for Github-Flavored Markdown compatibility.

  • Loading branch information...
1 parent 94157af commit c9df0bacc51575f4001cc072d428f92ffa0da6c2 @nex3 nex3 committed Jan 2, 2013
View
2 LICENSE
@@ -10,6 +10,8 @@ decorator - in third_party/decorator.py
PyYaml - in third_party/yaml
Markdown - in third_party/markdown
Pygments - in third_party/pygments
+PyGFM - in third_party/gfm, third_party/mdx_gfm, and
+ third_party/mdx_partial_gfm
The libraries may have their own licenses; we recommend you read them,
as their terms may differ from the terms below.
View
7 handlers/__init__.py
@@ -17,6 +17,7 @@
from models.package import Package
from models.package_version import PackageVersion
+from models.private_key import PrivateKey
_renderer = pystache.Renderer(search_dirs = [
os.path.join(os.path.dirname(__file__), '../views')])
@@ -214,6 +215,12 @@ def requires_uploader(fn, *args, **kwargs):
return fn(*args, **kwargs)
+@decorator
+def requires_private_key(fn, *args, **kwargs):
+ """A decorator for actions that require a private key to be set."""
+ if PrivateKey.get() is None: http_error(500, 'No private key set.')
+ return fn(*args, **kwargs)
+
def get_current_user():
"""Return the current db.User object, or None.
View
6 models/readme.py
@@ -56,10 +56,8 @@ def render(self):
def _render_markdown(text):
return markdown.markdown(
- text, output_format="html5", safe_mode='escape', extensions=[
- 'fenced_code', 'tables', 'smart_strong', 'nl2br', 'sane_lists',
- 'codehilite(guess_lang=False, css_class=highlight)',
- ])
+ text, output_format="html5", safe_mode='escape',
+ extensions=['partial_gfm'])
def _render_text(text):
return '<pre>%s</pre>' % cgi.escape(text)
View
24 third_party/gfm/LICENSE
@@ -0,0 +1,24 @@
+Copyright 2012, the Dart project authors. 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 of Google Inc. 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.
View
13 third_party/gfm/__init__.py
@@ -0,0 +1,13 @@
+# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+import autolink
+import automail
+import hidden_hilite
+import semi_sane_lists
+
+AutolinkExtension = autolink.AutolinkExtension
+AutomailExtension = automail.AutomailExtension
+HiddenHiliteExtension = hidden_hilite.HiddenHiliteExtension
+SemiSaneListExtension = semi_sane_lists.SemiSaneListExtension
View
44 third_party/gfm/autolink.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+import re
+import markdown
+
+# We can't re-use the built-in AutolinkPattern because we need to add protocols
+# to links without them.
+class AutolinkPattern(markdown.inlinepatterns.Pattern):
+ def handleMatch(self, m):
+ el = markdown.util.etree.Element("a")
+
+ href = m.group(2)
+ if not re.match('^(ftp|https?)://', href, flags=re.IGNORECASE):
+ href = 'http://%s' % href
+ el.set('href', self.unescape(href))
+
+ el.text = markdown.util.AtomicString(m.group(2))
+ return el
+
+class AutolinkExtension(markdown.Extension):
+ """An extension that turns all URLs into links.
+
+ This is based on the web-only URL regex by John Gruber that's listed on
+ http://daringfireball.net/2010/07/improved_regex_for_matching_urls (which is
+ in the public domain).
+
+ This regex seems to line up pretty closely with GitHub's URL matching. There
+ are only two cases I've found where they differ. In both cases, I've
+ modified the regex slightly to bring it in line with GitHub's parsing:
+
+ * GitHub accepts FTP-protocol URLs.
+ * GitHub only accepts URLs with protocols or "www.", whereas Gruber's regex
+ accepts things like "foo.com/bar".
+ """
+
+ def extendMarkdown(self, md, md_globals):
+ url_re = r'(?i)\b((?:(?:ftp|https?)://|www\d{0,3}[.])(?:[^\s()<>]+|' + \
+ '\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()' + \
+ '<>]+\)))*\)|[^\s`!()\[\]{};:' + "'" + '".,<>?«»“”‘’]))'
+ autolink = AutolinkPattern(url_re, md)
+ md.inlinePatterns.add('gfm-autolink', autolink, '_end')
View
24 third_party/gfm/automail.py
@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+import re
+import markdown
+
+# We can't re-use the built-in AutomailPattern because we need to add mailto:.
+# We also don't care about HTML-encoding the email.
+class AutomailPattern(markdown.inlinepatterns.Pattern):
+ def handleMatch(self, m):
+ el = markdown.util.etree.Element("a")
+ el.set('href', self.unescape('mailto:' + m.group(2)))
+ el.text = markdown.util.AtomicString(m.group(2))
+ return el
+
+class AutomailExtension(markdown.Extension):
+ """An extension that turns all email addresses into links."""
+
+ def extendMarkdown(self, md, md_globals):
+ mail_re = r'\b(?i)([a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]+)\b'
+ automail = AutomailPattern(mail_re, md)
+ md.inlinePatterns.add('gfm-automail', automail, '_end')
View
16 third_party/gfm/hidden_hilite.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+from markdown.extensions.codehilite import CodeHiliteExtension
+
+class HiddenHiliteExtension(CodeHiliteExtension):
+ """A subclass of CodeHiliteExtension that doesn't highlight on its own.
+
+ This just enables the fenced code extension to use syntax highlighting,
+ without adding syntax highlighting or line numbers to any additional code
+ blocks.
+ """
+
+ def extendMarkdown(self, md, md_globals):
+ md.registerExtension(self)
View
30 third_party/gfm/semi_sane_lists.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+import re
+import markdown
+
+class SemiSaneOListProcessor(markdown.blockprocessors.OListProcessor):
+ SIBLING_TAGS = ['ol']
+
+class SemiSaneUListProcessor(markdown.blockprocessors.UListProcessor):
+ SIBLING_TAGS = ['ul']
+
+class SemiSaneListExtension(markdown.Extension):
+ """An extension that causes lists to be treated the same way GitHub does.
+
+ Like the sane_lists extension, GitHub considers a list to end if it's
+ separated by multiple newlines from another list of a different type. Unlike
+ the sane_lists extension, GitHub will mix list types if they're not
+ separated by multiple newlines.
+
+ Github also recognizes lists that start in the middle of a paragraph. This
+ is currently not supported by this extension, since the Python parser has a
+ deeply-ingrained belief that blocks are always separated by multiple
+ newlines.
+ """
+
+ def extendMarkdown(self, md, md_globals):
+ md.parser.blockprocessors['olist'] = SemiSaneOListProcessor(md.parser)
+ md.parser.blockprocessors['ulist'] = SemiSaneUListProcessor(md.parser)
View
24 third_party/mdx_gfm/LICENSE
@@ -0,0 +1,24 @@
+Copyright 2012, the Dart project authors. 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 of Google Inc. 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.
View
28 third_party/mdx_gfm/__init__.py
@@ -0,0 +1,28 @@
+# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+from markdown.extensions.nl2br import Nl2BrExtension
+
+from mdx_partial_gfm import PartialGithubFlavoredMarkdownExtension
+
+def makeExtension(configs=None):
+ return GithubFlavoredMarkdownExtension(configs=configs)
+
+class GithubFlavoredMarkdownExtension(PartialGithubFlavoredMarkdownExtension):
+ """An extension that's as compatible as possible with GFM.
+
+ This extension aims to be compatible with the standard GFM that GitHub uses
+ for comments and issues. It has all the extensions described in the `GFM
+ documentation`_, except for intra-Github links to commits, repostiories, and
+ issues.
+
+ Note that Markdown-formatted gists and files (including READMEs) on GitHub
+ use a slightly different variant of GFM. For that, use
+ :class:`~mdx_partial_gfm.PartialGithubFlavoredMarkdownExtension`.
+ """
+
+ def extendMarkdown(self, md, md_globals):
+ PartialGithubFlavoredMarkdownExtension.extendMarkdown(self, md, md_globals)
+
+ Nl2BrExtension().extendMarkdown(md, md_globals)
View
24 third_party/mdx_partial_gfm/LICENSE
@@ -0,0 +1,24 @@
+Copyright 2012, the Dart project authors. 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 of Google Inc. 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.
View
42 third_party/mdx_partial_gfm/__init__.py
@@ -0,0 +1,42 @@
+# Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+from markdown.extensions import Extension
+from markdown.extensions.fenced_code import FencedCodeExtension
+from markdown.extensions.smart_strong import SmartEmphasisExtension
+from markdown.extensions.tables import TableExtension
+
+import gfm
+
+def makeExtension(configs=None):
+ return PartialGithubFlavoredMarkdownExtension(configs=configs)
+
+class PartialGithubFlavoredMarkdownExtension(Extension):
+ """An extension that's as compatible as possible with GFM.
+
+ This extension aims to be compatible with the variant of GFM that GitHub
+ uses for Markdown-formatted gists and files (including READMEs). This
+ variant seems to have all the extensions described in the `GFM
+ documentation`_, except:
+
+ - Newlines in paragraphs are not transformed into ``br`` tags.
+ - Intra-Github links to commits, repositories, and issues are not supported.
+
+ .. _the GFM documentation: http://github.github.com/github-flavored-markdown
+ """
+
+ def extendMarkdown(self, md, md_globals):
+ # Built-in extensions
+ FencedCodeExtension().extendMarkdown(md, md_globals)
+ SmartEmphasisExtension().extendMarkdown(md, md_globals)
+ TableExtension().extendMarkdown(md, md_globals)
+
+ # Custom extensions
+ gfm.AutolinkExtension().extendMarkdown(md, md_globals)
+ gfm.AutomailExtension().extendMarkdown(md, md_globals)
+ gfm.HiddenHiliteExtension([
+ ('guess_lang', 'False'),
+ ('css_class', 'highlight')
+ ]).extendMarkdown(md, md_globals)
+ gfm.SemiSaneListExtension().extendMarkdown(md, md_globals)

0 comments on commit c9df0ba

Please sign in to comment.