From 237ae081dbade817f4a2033b6aa2d3cdeb15b8b2 Mon Sep 17 00:00:00 2001
From: Sébastien Dailly <sebastien@chimrod.com>
Date: Sat, 15 Nov 2014 21:22:30 +0100
Subject: Moved typogrify as plugin

---
 plugins/typogrify/titlecase/__init__.py | 101 ++++++++++++++++++
 plugins/typogrify/titlecase/tests.py    | 174 ++++++++++++++++++++++++++++++++
 2 files changed, 275 insertions(+)
 create mode 100755 plugins/typogrify/titlecase/__init__.py
 create mode 100644 plugins/typogrify/titlecase/tests.py

(limited to 'plugins/typogrify/titlecase')

diff --git a/plugins/typogrify/titlecase/__init__.py b/plugins/typogrify/titlecase/__init__.py
new file mode 100755
index 0000000..aeaca97
--- /dev/null
+++ b/plugins/typogrify/titlecase/__init__.py
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# titlecase v0.5.1
+# Copyright (C) 2008-2010, Stuart Colville.
+# https://pypi.python.org/pypi/titlecase
+
+"""
+Original Perl version by: John Gruber http://daringfireball.net/ 10 May 2008
+Python version by Stuart Colville http://muffinresearch.co.uk
+License: http://www.opensource.org/licenses/mit-license.php
+"""
+
+import re
+
+__all__ = ['titlecase']
+__version__ = '0.5.1'
+
+SMALL = 'a|an|and|as|at|but|by|en|for|if|in|of|on|or|the|to|v\.?|via|vs\.?'
+PUNCT = r"""!"#$%&'‘()*+,\-./:;?@[\\\]_`{|}~"""
+
+SMALL_WORDS = re.compile(r'^(%s)$' % SMALL, re.I)
+INLINE_PERIOD = re.compile(r'[a-z][.][a-z]', re.I)
+UC_ELSEWHERE = re.compile(r'[%s]*?[a-zA-Z]+[A-Z]+?' % PUNCT)
+CAPFIRST = re.compile(r"^[%s]*?([A-Za-z])" % PUNCT)
+SMALL_FIRST = re.compile(r'^([%s]*)(%s)\b' % (PUNCT, SMALL), re.I)
+SMALL_LAST = re.compile(r'\b(%s)[%s]?$' % (SMALL, PUNCT), re.I)
+SUBPHRASE = re.compile(r'([:.;?!][ ])(%s)' % SMALL)
+APOS_SECOND = re.compile(r"^[dol]{1}['‘]{1}[a-z]+$", re.I)
+ALL_CAPS = re.compile(r'^[A-Z\s%s]+$' % PUNCT)
+UC_INITIALS = re.compile(r"^(?:[A-Z]{1}\.{1}|[A-Z]{1}\.{1}[A-Z]{1})+$")
+MAC_MC = re.compile(r"^([Mm]a?c)(\w+)")
+
+def titlecase(text):
+
+    """
+    Titlecases input text
+
+    This filter changes all words to Title Caps, and attempts to be clever
+    about *un*capitalizing SMALL words like a/an/the in the input.
+
+    The list of "SMALL words" which are not capped comes from
+    the New York Times Manual of Style, plus 'vs' and 'v'.
+
+    """
+
+    lines = re.split('[\r\n]+', text)
+    processed = []
+    for line in lines:
+        all_caps = ALL_CAPS.match(line)
+        words = re.split('[\t ]', line)
+        tc_line = []
+        for word in words:
+            if all_caps:
+                if UC_INITIALS.match(word):
+                    tc_line.append(word)
+                    continue
+                else:
+                    word = word.lower()
+
+            if APOS_SECOND.match(word):
+                word = word.replace(word[0], word[0].upper())
+                word = word.replace(word[2], word[2].upper())
+                tc_line.append(word)
+                continue
+            if INLINE_PERIOD.search(word) or UC_ELSEWHERE.match(word):
+                tc_line.append(word)
+                continue
+            if SMALL_WORDS.match(word):
+                tc_line.append(word.lower())
+                continue
+
+            match = MAC_MC.match(word)
+            if match:
+                tc_line.append("%s%s" % (match.group(1).capitalize(),
+                                      match.group(2).capitalize()))
+                continue
+
+            hyphenated = []
+            for item in word.split('-'):
+                hyphenated.append(CAPFIRST.sub(lambda m: m.group(0).upper(), item))
+            tc_line.append("-".join(hyphenated))
+
+
+        result = " ".join(tc_line)
+
+        result = SMALL_FIRST.sub(lambda m: '%s%s' % (
+            m.group(1),
+            m.group(2).capitalize()
+        ), result)
+
+        result = SMALL_LAST.sub(lambda m: m.group(0).capitalize(), result)
+
+        result = SUBPHRASE.sub(lambda m: '%s%s' % (
+            m.group(1),
+            m.group(2).capitalize()
+        ), result)
+
+        processed.append(result)
+
+    return "\n".join(processed)
+
diff --git a/plugins/typogrify/titlecase/tests.py b/plugins/typogrify/titlecase/tests.py
new file mode 100644
index 0000000..97a45e4
--- /dev/null
+++ b/plugins/typogrify/titlecase/tests.py
@@ -0,0 +1,174 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+"""Tests for titlecase"""
+
+
+import os
+import sys
+sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../'))
+
+from titlecase import titlecase
+
+TEST_DATA = (
+    (
+        "Q&A with steve jobs: 'that's what happens in technology'",
+        "Q&A With Steve Jobs: 'That's What Happens in Technology'"
+    ),
+    (
+        "What is AT&T's problem?",
+        "What Is AT&T's Problem?"
+    ),
+    (
+        "Apple deal with AT&T falls through",
+        "Apple Deal With AT&T Falls Through"
+    ),
+    (
+        "this v that",
+        "This v That"
+    ),
+    (
+        "this v. that",
+        "This v. That"
+    ),
+    (
+        "this vs that",
+        "This vs That"
+    ),
+    (
+        "this vs. that",
+        "This vs. That"
+    ),
+    (
+        "The SEC's Apple probe: what you need to know",
+        "The SEC's Apple Probe: What You Need to Know"
+    ),
+    (
+        "'by the Way, small word at the start but within quotes.'",
+        "'By the Way, Small Word at the Start but Within Quotes.'"
+    ),
+    (
+        "Small word at end is nothing to be afraid of",
+        "Small Word at End Is Nothing to Be Afraid Of"
+    ),
+    (
+        "Starting Sub-Phrase With a Small Word: a Trick, Perhaps?",
+        "Starting Sub-Phrase With a Small Word: A Trick, Perhaps?"
+    ),
+    (    
+        "Sub-Phrase With a Small Word in Quotes: 'a Trick, Perhaps?'",
+        "Sub-Phrase With a Small Word in Quotes: 'A Trick, Perhaps?'"
+    ),
+    (
+        'sub-phrase with a small word in quotes: "a trick, perhaps?"',
+        'Sub-Phrase With a Small Word in Quotes: "A Trick, Perhaps?"'
+    ),
+    (
+        '"Nothing to Be Afraid of?"',
+        '"Nothing to Be Afraid Of?"'
+    ),
+    (
+        '"Nothing to be Afraid Of?"',
+        '"Nothing to Be Afraid Of?"'    
+    ),
+    (   
+        'a thing',
+        'A Thing'
+    ),
+    (
+        "2lmc Spool: 'gruber on OmniFocus and vapo(u)rware'",
+        "2lmc Spool: 'Gruber on OmniFocus and Vapo(u)rware'"
+    ),
+    (
+        'this is just an example.com',
+        'This Is Just an example.com'
+    ),
+    (
+        'this is something listed on del.icio.us',
+        'This Is Something Listed on del.icio.us'
+    ),
+    (
+        'iTunes should be unmolested',
+        'iTunes Should Be Unmolested'
+    ),
+    (
+        'reading between the lines of steve jobs’s ‘thoughts on music’',
+        'Reading Between the Lines of Steve Jobs’s ‘Thoughts on Music’'
+    ),
+    (
+        'seriously, ‘repair permissions’ is voodoo',
+        'Seriously, ‘Repair Permissions’ Is Voodoo'
+    ),
+    (
+        'generalissimo francisco franco: still dead; kieren McCarthy: still a jackass',
+        'Generalissimo Francisco Franco: Still Dead; Kieren McCarthy: Still a Jackass'
+    ),
+    (
+        "O'Reilly should be untouched",
+        "O'Reilly Should Be Untouched"
+    ),
+    (
+        "my name is o'reilly",
+        "My Name Is O'Reilly"
+    ),
+    (
+        "WASHINGTON, D.C. SHOULD BE FIXED BUT MIGHT BE A PROBLEM",
+        "Washington, D.C. Should Be Fixed but Might Be a Problem"
+    ),
+    (
+        "THIS IS ALL CAPS AND SHOULD BE ADDRESSED",
+        "This Is All Caps and Should Be Addressed"
+    ),
+    (
+        "Mr McTavish went to MacDonalds",
+        "Mr McTavish Went to MacDonalds"
+    ),
+    (
+        "this shouldn't\nget mangled",
+        "This Shouldn't\nGet Mangled"
+    ),
+    ( 
+        "this is http://foo.com",
+        "This Is http://foo.com"
+    )
+)
+
+def test_all_caps_regex():
+    """Test - all capitals regex"""
+    from titlecase import ALL_CAPS
+    assert bool(ALL_CAPS.match('THIS IS ALL CAPS')) is True
+
+def test_initials_regex():
+    """Test - uppercase initals regex with A.B"""
+    from titlecase import UC_INITIALS
+    assert bool(UC_INITIALS.match('A.B')) is True
+
+def test_initials_regex_2():
+    """Test - uppercase initals regex with A.B."""
+    from titlecase import UC_INITIALS
+    assert bool(UC_INITIALS.match('A.B.')) is True
+
+def test_initials_regex_3():
+    """Test - uppercase initals regex with ABCD"""
+    from titlecase import UC_INITIALS
+    assert bool(UC_INITIALS.match('ABCD')) is False
+
+def check_input_matches_expected_output(in_, out):
+    """Function yielded by test generator"""
+    try :
+        assert  titlecase(in_) == out
+    except AssertionError:
+        print("%s != %s" % (titlecase(in_), out))
+        raise
+
+
+def test_input_output():
+    """Generated tests"""
+    for data in TEST_DATA:
+        yield check_input_matches_expected_output, data[0], data[1]
+       
+
+if __name__ == "__main__":
+    import nose
+    nose.main()
+
-- 
cgit v1.2.3