From fa6a4da8d6f9cd85cd60e505e8eb5a9becc40ed6 Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Fri, 17 Sep 2021 10:16:06 +0200 Subject: Update plugin configuration --- content/Glyphes/2021-01-03-calligraphie.rst | 106 +++++++ content/Informatique/2021-01-03-calligraphie.rst | 106 ------- content/Perso/2013-05-18-traitment.rst | 1 + content/Perso/2013-06-01-marelle.rst | 1 + pelicanconf.py | 4 +- plugins/my_typogrify/__init__.py | 1 + plugins/my_typogrify/mytypogrify.py | 96 ++++++ plugins/typogrify/__init__.py | 1 - plugins/typogrify/filters.py | 386 ----------------------- plugins/typogrify/titlecase/__init__.py | 101 ------ plugins/typogrify/titlecase/tests.py | 174 ---------- plugins/typogrify/typogrify.py | 19 -- readme.rst | 4 +- 13 files changed, 209 insertions(+), 791 deletions(-) create mode 100755 content/Glyphes/2021-01-03-calligraphie.rst delete mode 100755 content/Informatique/2021-01-03-calligraphie.rst create mode 100644 plugins/my_typogrify/__init__.py create mode 100755 plugins/my_typogrify/mytypogrify.py delete mode 100644 plugins/typogrify/__init__.py delete mode 100755 plugins/typogrify/filters.py delete mode 100755 plugins/typogrify/titlecase/__init__.py delete mode 100644 plugins/typogrify/titlecase/tests.py delete mode 100755 plugins/typogrify/typogrify.py diff --git a/content/Glyphes/2021-01-03-calligraphie.rst b/content/Glyphes/2021-01-03-calligraphie.rst new file mode 100755 index 0000000..3fd6e30 --- /dev/null +++ b/content/Glyphes/2021-01-03-calligraphie.rst @@ -0,0 +1,106 @@ +.. -*- mode: rst -*- +.. -*- coding: utf-8 -*- + +================================ +De la calligraphie en javascript +================================ + +:date: 2021-01-03 +:tags: javascript +:summary: |summary| + +.. default-role:: literal + +.. |summary| replace:: + + Un petit bilan après avoir réalisé une application de calligraphie sur le + blog :) + +À la suite de mon article précédent, j'ai essayé d'aller un peu plus loin dans +ce qu'il était possible de faire en javascript. La page pour construire les +graphes montrait déjà qu'il était possible de charger du javascript dans la +page, et modifier directement le contenu du blog à partir du code exécuté. + +En suivant toujours la même démarche (code en OCaml, compilé en javascript), +j'ai mis en place une *ardoise* dans laquelle je souhaitais retrouver sur PC le +rendu que l'on peut avoir avec une plume dans la main : `l'ardoise calligraphique`_. + +.. _l'ardoise calligraphique: {filename}/pages/script.it/script.rst#ardoise-calligraphique + +Ce que j'ai appris +================== + +Les courbes de beziers ! Je ne pensais pas qu'il y aurait autant à faire avec ! +Pour ceux que cela intéresse, la page `A Primer on Bézier Curves`_ est une +référence avec tout ce qu'il faut pour mettre en place ses propres librairies. + +.. _A Primer on Bézier Curves: https://pomax.github.io/bezierinfo/ + +Afin d'avoir un tracé souple de la courbe, j'ai suivi un document de l'UCLA_ +qui explique comment construire les courbes de beziers en suivant une série de +points, ce qui m'a fait faire un détour par les produits matriciels pour +résoudre ce genre d'équations : + +.. _ucla: https://www.math.ucla.edu/~baker/149.1.02w/handouts/dd_splines.pdf + +.. math:: + + \begin{bmatrix}4 && 1 && 0 && 0 \\\\ 1 && 4 && 1 && 0 \\\\0 && 1 && 4 && 1 \\\\0 && 0 && 1 && 4 \end{bmatrix} + \begin{bmatrix} B_1 \\\\ B_2 \\\\ B_3 \\\\ B_4 \end{bmatrix} + = + \begin{bmatrix} (6 S_1 - S_0) \\\\ 6S_2 \\\\ 6 S_3 \\\\ (6S_4 - S_5) \end{bmatrix} + +A priori, il n'existe pas de librairie pour faire de la réduction de matrice en +javascript, mais l'avantage d'utiliser OCaml est d'avoir sous la main `quelques +librairies`_ permettant de faire le boulot directement. + +.. _quelques librairies: https://github.com/kandluis/ocaml-matrix + +Ensuite, travailler le DOM. Vu que le site est statique, j'ai choisi de +modifier la page directement à partir du code javascript. En ajoutant un +élément, en retirant ceux dont je n'avais nécessité, cela permet de changer +l'apparence directement pour se construire son application. Cela m'a permis de +me plonger dans la librairie `brr`_ qui permet d'interagir avec la page via +des évènements fonctionnels. + +.. _brr: https://erratique.ch/software/brr + +Enfin, les webWorkers_, qui sont des threads pouvant être lancés dans le code +javascript. Dans l'application, je les utilise pour *lisser* la courbe une fois +que celle-ci a été construite une première fois. + +.. _webworkers: https://developer.mozilla.org/fr/docs/Web/API/Web_Workers_API/Utilisation_des_web_workers + +Ce qu'il faudrait continuer +=========================== + +Il me manque tout un cadre mathématique pour aller plus loin, j'aurai par +exemple besoin de déterminer l'extrémité_ exacte de la courbe afin de traiter +ces cas de manière précise, et j'ai besoin de comprendre le code avant de m'y +mettre… + +.. _extrémité: https://pomax.github.io/bezierinfo/#extremities + +Par conséquent, l'export SVG est un peu biaisé, on retrouve bien ce qui est +affiché sur l'écran, mais cela donne quelque chose qui n'est pas vraiment +éditable comme je l'aurai souhaité. + +Il faudrait aussi aller plus loin dans les mouvements de plumes, permettre des +rotations locales, juste sur un segment et non pas sur la totalité du tracé, +enfin des petits ajustements pour qu'il y ait vraiment une plus-value. + +D'autres pistes +=============== + +Cela m'a aussi donné d'autres pistes pour continuer avec javascript et le blog. +En utilisant l'API `Web Storage`_, on peut également stocker des données comme +si l'on travaillait sur un fichier, les données étant stockées dans l'espace du +navigateur. En combinant cela avec le côté statique du site, je pense à une +page de prise de note, qui dont le code serait uniquement exécuté dans le +navigateur, sans avoir besoin de serveur comme support. + +.. _web storage: https://developer.mozilla.org/fr/docs/Web/API/Web_Storage_API + +Le blog offrant un espace dans lequel je peux mettre en ligne mes applications, +cela me donne envie de continuer et m'en servir comme petit terrain +d'exipérimentation… diff --git a/content/Informatique/2021-01-03-calligraphie.rst b/content/Informatique/2021-01-03-calligraphie.rst deleted file mode 100755 index 3fd6e30..0000000 --- a/content/Informatique/2021-01-03-calligraphie.rst +++ /dev/null @@ -1,106 +0,0 @@ -.. -*- mode: rst -*- -.. -*- coding: utf-8 -*- - -================================ -De la calligraphie en javascript -================================ - -:date: 2021-01-03 -:tags: javascript -:summary: |summary| - -.. default-role:: literal - -.. |summary| replace:: - - Un petit bilan après avoir réalisé une application de calligraphie sur le - blog :) - -À la suite de mon article précédent, j'ai essayé d'aller un peu plus loin dans -ce qu'il était possible de faire en javascript. La page pour construire les -graphes montrait déjà qu'il était possible de charger du javascript dans la -page, et modifier directement le contenu du blog à partir du code exécuté. - -En suivant toujours la même démarche (code en OCaml, compilé en javascript), -j'ai mis en place une *ardoise* dans laquelle je souhaitais retrouver sur PC le -rendu que l'on peut avoir avec une plume dans la main : `l'ardoise calligraphique`_. - -.. _l'ardoise calligraphique: {filename}/pages/script.it/script.rst#ardoise-calligraphique - -Ce que j'ai appris -================== - -Les courbes de beziers ! Je ne pensais pas qu'il y aurait autant à faire avec ! -Pour ceux que cela intéresse, la page `A Primer on Bézier Curves`_ est une -référence avec tout ce qu'il faut pour mettre en place ses propres librairies. - -.. _A Primer on Bézier Curves: https://pomax.github.io/bezierinfo/ - -Afin d'avoir un tracé souple de la courbe, j'ai suivi un document de l'UCLA_ -qui explique comment construire les courbes de beziers en suivant une série de -points, ce qui m'a fait faire un détour par les produits matriciels pour -résoudre ce genre d'équations : - -.. _ucla: https://www.math.ucla.edu/~baker/149.1.02w/handouts/dd_splines.pdf - -.. math:: - - \begin{bmatrix}4 && 1 && 0 && 0 \\\\ 1 && 4 && 1 && 0 \\\\0 && 1 && 4 && 1 \\\\0 && 0 && 1 && 4 \end{bmatrix} - \begin{bmatrix} B_1 \\\\ B_2 \\\\ B_3 \\\\ B_4 \end{bmatrix} - = - \begin{bmatrix} (6 S_1 - S_0) \\\\ 6S_2 \\\\ 6 S_3 \\\\ (6S_4 - S_5) \end{bmatrix} - -A priori, il n'existe pas de librairie pour faire de la réduction de matrice en -javascript, mais l'avantage d'utiliser OCaml est d'avoir sous la main `quelques -librairies`_ permettant de faire le boulot directement. - -.. _quelques librairies: https://github.com/kandluis/ocaml-matrix - -Ensuite, travailler le DOM. Vu que le site est statique, j'ai choisi de -modifier la page directement à partir du code javascript. En ajoutant un -élément, en retirant ceux dont je n'avais nécessité, cela permet de changer -l'apparence directement pour se construire son application. Cela m'a permis de -me plonger dans la librairie `brr`_ qui permet d'interagir avec la page via -des évènements fonctionnels. - -.. _brr: https://erratique.ch/software/brr - -Enfin, les webWorkers_, qui sont des threads pouvant être lancés dans le code -javascript. Dans l'application, je les utilise pour *lisser* la courbe une fois -que celle-ci a été construite une première fois. - -.. _webworkers: https://developer.mozilla.org/fr/docs/Web/API/Web_Workers_API/Utilisation_des_web_workers - -Ce qu'il faudrait continuer -=========================== - -Il me manque tout un cadre mathématique pour aller plus loin, j'aurai par -exemple besoin de déterminer l'extrémité_ exacte de la courbe afin de traiter -ces cas de manière précise, et j'ai besoin de comprendre le code avant de m'y -mettre… - -.. _extrémité: https://pomax.github.io/bezierinfo/#extremities - -Par conséquent, l'export SVG est un peu biaisé, on retrouve bien ce qui est -affiché sur l'écran, mais cela donne quelque chose qui n'est pas vraiment -éditable comme je l'aurai souhaité. - -Il faudrait aussi aller plus loin dans les mouvements de plumes, permettre des -rotations locales, juste sur un segment et non pas sur la totalité du tracé, -enfin des petits ajustements pour qu'il y ait vraiment une plus-value. - -D'autres pistes -=============== - -Cela m'a aussi donné d'autres pistes pour continuer avec javascript et le blog. -En utilisant l'API `Web Storage`_, on peut également stocker des données comme -si l'on travaillait sur un fichier, les données étant stockées dans l'espace du -navigateur. En combinant cela avec le côté statique du site, je pense à une -page de prise de note, qui dont le code serait uniquement exécuté dans le -navigateur, sans avoir besoin de serveur comme support. - -.. _web storage: https://developer.mozilla.org/fr/docs/Web/API/Web_Storage_API - -Le blog offrant un espace dans lequel je peux mettre en ligne mes applications, -cela me donne envie de continuer et m'en servir comme petit terrain -d'exipérimentation… diff --git a/content/Perso/2013-05-18-traitment.rst b/content/Perso/2013-05-18-traitment.rst index 14a6298..b5613d3 100644 --- a/content/Perso/2013-05-18-traitment.rst +++ b/content/Perso/2013-05-18-traitment.rst @@ -9,6 +9,7 @@ Cachez-moi ce menu que je ne saurais voir :tags: Humeur :summary: |summary| :logo: {static}/images/traitement/logo.jpg +:status: hidden .. figure:: https://farm1.staticflickr.com/214/4555895229_880a76beb7_q.jpg diff --git a/content/Perso/2013-06-01-marelle.rst b/content/Perso/2013-06-01-marelle.rst index f658be9..98cc359 100644 --- a/content/Perso/2013-06-01-marelle.rst +++ b/content/Perso/2013-06-01-marelle.rst @@ -9,6 +9,7 @@ La marelle romaine : les solutions :tags: Jeux :logo: /images/marelle/logo.jpg :summary: |summary| +:status: hidden .. image:: {static}/images/marelle/extract.jpeg :width: 150 diff --git a/pelicanconf.py b/pelicanconf.py index 93b13f6..68081b7 100755 --- a/pelicanconf.py +++ b/pelicanconf.py @@ -47,7 +47,7 @@ THEME_TEMPLATES_OVERRIDES = \ [ 'theme/custom' ] -LINKS= ( ("git","http://git.chimrod.com") +LINKS= ( ("Git", "http://git.chimrod.com") , ) HOME_HIDE_TAGS=False I18N_TEMPLATES_LANG = "fr_FR" @@ -78,7 +78,7 @@ PLUGIN_PATHS = ['plugins'] PLUGINS = \ ( 'related_posts' - , 'typogrify' + , 'my_typogrify' , 'i18n_subsites' , 'render_math' ) diff --git a/plugins/my_typogrify/__init__.py b/plugins/my_typogrify/__init__.py new file mode 100644 index 0000000..b445852 --- /dev/null +++ b/plugins/my_typogrify/__init__.py @@ -0,0 +1 @@ +from .mytypogrify import * diff --git a/plugins/my_typogrify/mytypogrify.py b/plugins/my_typogrify/mytypogrify.py new file mode 100755 index 0000000..490e82b --- /dev/null +++ b/plugins/my_typogrify/mytypogrify.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from pelican import signals +import typogrify.filters as filters +import re + +def french_insecable(text): + """Replace the space between each double sign punctuation by a thin + non-breaking space. + + This conform with the french typographic rules. + + >>> french_insecable('Foo !') + u'Foo!' + + >>> french_insecable('Foo ?') + u'Foo?' + + >>> french_insecable('Foo : bar') + u'Foo: bar' + + >>> french_insecable('Foo ; bar') + u'Foo; bar' + + >>> french_insecable(u'\xab bar \xbb') + u'\\xabbar\\xbb' + + >>> french_insecable('123 456') + u'123456' + + >>> french_insecable('123 %') + u'123%' + + Space inside attributes should be preserved : + + >>> french_insecable('') + '' + """ + + tag_pattern = '\s]+))?)+\s*|\s*)/?>' + intra_tag_finder = re.compile(r'(?P(%s)?)(?P([^<]*))(?P(%s)?)' % (tag_pattern, tag_pattern)) + + nnbsp = u'' + space_finder = re.compile(r"""(?: + (\w\s[:;!\?\xbb])| # Group 1, space before punctuation + ([\xab]\s\w)| + ([0-9]\s[0-9])| + ([0-9]\s\%) + )""", re.VERBOSE) + + def _insecable_wrapper(groups): + """This is necessary to keep dotted cap strings to pick up extra spaces""" + def substitute(matchobj): + return matchobj.group(0).replace(" ", nnbsp) + + prefix = groups.group('prefix') or '' + text = space_finder.sub(substitute, groups.group('text')) + suffix = groups.group('suffix') or '' + return prefix + text + suffix + + output = intra_tag_finder.sub(_insecable_wrapper, text) + return output + +def typogrify(text, ignore_tags=None): + """The super typography filter + + Applies filters to text that are not in tags contained in the + ignore_tags list. + """ + + section_list = filters.process_ignores(text, ignore_tags) + + rendered_text = "" + for text_item, should_process in section_list: + if should_process: + rendered_text += french_insecable(filters.applyfilters(text_item)) + else: + rendered_text += text_item + + # apply widont at the end, as its already smart about tags. Hopefully. + return filters.widont(rendered_text) + +def apply(data): + + if not data._content: + return + + + data._content = typogrify(data._content) + + metadata = data.metadata + metadata['title'] = typogrify(metadata['title']) + +def register(): + signals.content_object_init.connect(apply) diff --git a/plugins/typogrify/__init__.py b/plugins/typogrify/__init__.py deleted file mode 100644 index 8511890..0000000 --- a/plugins/typogrify/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .typogrify import * diff --git a/plugins/typogrify/filters.py b/plugins/typogrify/filters.py deleted file mode 100755 index 41d108d..0000000 --- a/plugins/typogrify/filters.py +++ /dev/null @@ -1,386 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -import re -from typogrify.titlecase import titlecase # NOQA -import locale - -class TypogrifyError(Exception): - """ A base error class so we can catch or scilence typogrify's errors in templates """ - pass - -def process_ignores(text, ignore_tags=None): - """ Creates a list of tuples based on tags to be ignored. - Tags can be added as a list in the `ignore_tags`. - Returns in the following format: - - [ - ('Text here', ), - ('Text here', ), - ] - - >>> process_ignores('
processed

processed

') - [('
processed
', False), ('

processed

', True)] - >>> process_ignores('processed

processed

processed

') - [('processed', False), ('

processed', True), ('

processed
', False), ('

', True)] - >>> process_ignores('processed

processed

processed

',['p']) - [('processed', False), ('

processed

processed

', False)] - """ - - position = 0 - sections = [] - if ignore_tags is None: - ignore_tags = [] - - ignore_tags = ignore_tags + ['pre', 'code'] # default tags - ignore_regex = r'<(%s)(?:\s.*?)?>.*?' % '|'.join(ignore_tags) - ignore_finder = re.compile(ignore_regex, re.IGNORECASE | re.DOTALL) - - for section in ignore_finder.finditer(text): - start, end = section.span() - - if position != start: - # if the current position isn't the match we - # need to process everything in between - sections.append((text[position:start], True)) - - # now we mark the matched section as ignored - sections.append((text[start:end], False)) - - position = end - - # match the rest of the text if necessary - # (this could in fact be the entire string) - if position < len(text): - sections.append((text[position:len(text)], True)) - - return sections - -def amp(text): - """Wraps apersands in HTML with ```` so they can be - styled with CSS. Apersands are also normalized to ``&``. Requires - ampersands to have whitespace or an `` `` on both sides. - - >>> amp('One & two') - 'One & two' - >>> amp('One & two') - 'One & two' - >>> amp('One & two') - 'One & two' - - >>> amp('One & two') - 'One & two' - - It won't mess up & that are already wrapped, in entities or URLs - - >>> amp('One & two') - 'One & two' - >>> amp('“this” &
that') - '“this” & that' - - It should ignore standalone amps that are in attributes - >>> amp('xyz') - 'xyz' - """ - # tag_pattern from http://haacked.com/archive/2004/10/25/usingregularexpressionstomatchhtml.aspx - # it kinda sucks but it fixes the standalone amps in attributes bug - tag_pattern = '\s]+))?)+\s*|\s*)/?>' - amp_finder = re.compile(r"(\s| )(&|&|&\#38;)(\s| )") - intra_tag_finder = re.compile(r'(?P(%s)?)(?P([^<]*))(?P(%s)?)' % (tag_pattern, tag_pattern)) - - def _amp_process(groups): - prefix = groups.group('prefix') or '' - text = amp_finder.sub(r"""\1&\3""", groups.group('text')) - suffix = groups.group('suffix') or '' - return prefix + text + suffix - - output = intra_tag_finder.sub(_amp_process, text) - return output - - -def caps(text): - """Wraps multiple capital letters in ```` - so they can be styled with CSS. - - >>> caps("A message from KU") - 'A message from KU' - - Uses the smartypants tokenizer to not screw with HTML or with tags it shouldn't. - - >>> caps("
CAPS
more CAPS") - '
CAPS
more CAPS' - - >>> caps("A message from 2KU2 with digits") - 'A message from 2KU2 with digits' - - >>> caps("Dotted caps followed by spaces should never include them in the wrap D.O.T. like so.") - 'Dotted caps followed by spaces should never include them in the wrap D.O.T. like so.' - - All caps with with apostrophes in them shouldn't break. Only handles dump apostrophes though. - >>> caps("JIMMY'S") - 'JIMMY\\'S' - - >>> caps("D.O.T.HE34TRFID") - 'D.O.T.HE34TRFID' - """ - try: - import smartypants - except ImportError: - raise TypogrifyError("Error in {% caps %} filter: The Python SmartyPants library isn't installed.") - - tokens = smartypants._tokenize(text) - result = [] - in_skipped_tag = False - - cap_finder = re.compile(r"""( - (\b[A-Z\d]* # Group 2: Any amount of caps and digits - [A-Z]\d*[A-Z] # A cap string much at least include two caps (but they can have digits between them) - [A-Z\d']*\b) # Any amount of caps and digits or dumb apostsrophes - | (\b[A-Z]+\.\s? # OR: Group 3: Some caps, followed by a '.' and an optional space - (?:[A-Z]+\.\s?)+) # Followed by the same thing at least once more - (?:\s|\b|$)) - """, re.VERBOSE) - - def _cap_wrapper(matchobj): - """This is necessary to keep dotted cap strings to pick up extra spaces""" - if matchobj.group(2): - return """%s""" % matchobj.group(2) - else: - if matchobj.group(3)[-1] == " ": - caps = matchobj.group(3)[:-1] - tail = ' ' - else: - caps = matchobj.group(3) - tail = '' - return """%s%s""" % (caps, tail) - - # Add additional tags whose content should be - # ignored here. Note -
 and  tag are
-    # ignored by default and therefore are not here
-    tags_to_skip_regex = re.compile("<(/)?(?:kbd|script)[^>]*>", re.IGNORECASE)
-
-    for token in tokens:
-        if token[0] == "tag":
-            # Don't mess with tags.
-            result.append(token[1])
-            close_match = tags_to_skip_regex.match(token[1])
-            if close_match and close_match.group(1) == None:
-                in_skipped_tag = True
-            else:
-                in_skipped_tag = False
-        else:
-            if in_skipped_tag:
-                result.append(token[1])
-            else:
-                result.append(cap_finder.sub(_cap_wrapper, token[1]))
-    output = "".join(result)
-    return output
-
-
-def initial_quotes(text):
-    """Wraps initial quotes in ``class="dquo"`` for double quotes or
-    ``class="quo"`` for single quotes. Works in these block tags ``(h1-h6, p, li, dt, dd)``
-    and also accounts for potential opening inline elements ``a, em, strong, span, b, i``
-
-    >>> initial_quotes('"With primes"')
-    '"With primes"'
-    >>> initial_quotes("'With single primes'")
-    '\\'With single primes\\''
-
-    >>> initial_quotes('"With primes and a link"')
-    '"With primes and a link"'
-
-    >>> initial_quotes('“With smartypanted quotes”')
-    'With smartypanted quotes”'
-    """
-    quote_finder = re.compile(r"""((<(p|h[1-6]|li|dt|dd)[^>]*>|^)              # start with an opening p, h1-6, li, dd, dt or the start of the string
-                                  \s*                                          # optional white space!
-                                  (<(a|em|span|strong|i|b)[^>]*>\s*)*)         # optional opening inline tags, with more optional white space for each.
-                                  (("|“|&\#8220;)|('|‘|&\#8216;))  # Find me a quote! (only need to find the left quotes and the primes)
-                                                                               # double quotes are in group 7, singles in group 8
-                                  """, re.VERBOSE)
-
-    def _quote_wrapper(matchobj):
-        if matchobj.group(7):
-            classname = "dquo"
-            quote = matchobj.group(7)
-        else:
-            classname = "quo"
-            quote = matchobj.group(8)
-        return """%s%s""" % (matchobj.group(1), classname, quote)
-    output = quote_finder.sub(_quote_wrapper, text)
-    return output
-
-
-def smartypants(text):
-    """Applies smarty pants to curl quotes.
-
-    >>> smartypants('The "Green" man')
-    'The “Green” man'
-    """
-    try:
-        import smartypants
-    except ImportError:
-        raise TypogrifyError("Error in {% smartypants %} filter: The Python smartypants library isn't installed.")
-    else:
-        output = smartypants.smartypants(text)
-        return output
-
-def french_insecable(text):
-    """Replace the space between each double sign punctuation by a thin
-    non-breaking space.
-
-    This conform with the french typographic rules.
-
-    >>> french_insecable('Foo !')
-    u'Foo!'
-
-    >>> french_insecable('Foo ?')
-    u'Foo?'
-
-    >>> french_insecable('Foo : bar')
-    u'Foo: bar'
-
-    >>> french_insecable('Foo ; bar')
-    u'Foo; bar'
-
-    >>> french_insecable(u'\xab bar \xbb')
-    u'\\xabbar\\xbb'
-
-    >>> french_insecable('123 456')
-    u'123456'
-
-    >>> french_insecable('123 %')
-    u'123%'
-
-    Space inside attributes should be preserved :
-
-    >>> french_insecable('')
-    ''
-    """
-
-    tag_pattern = '\s]+))?)+\s*|\s*)/?>'
-    intra_tag_finder = re.compile(r'(?P(%s)?)(?P([^<]*))(?P(%s)?)' % (tag_pattern, tag_pattern))
-
-    nnbsp = u''
-    space_finder = re.compile(r"""(?:
-                            (\w\s[:;!\?\xbb])|       # Group 1, space before punctuation
-                            ([\xab]\s\w)|
-                            ([0-9]\s[0-9])|
-                            ([0-9]\s\%)
-                            )""", re.VERBOSE)
-
-    def _insecable_wrapper(groups):
-        """This is necessary to keep dotted cap strings to pick up extra spaces"""
-        def substitute(matchobj):
-            return matchobj.group(0).replace(" ", nnbsp)
-
-        prefix = groups.group('prefix') or ''
-        text = space_finder.sub(substitute, groups.group('text'))
-        suffix = groups.group('suffix') or ''
-        return prefix + text + suffix
-
-    output = intra_tag_finder.sub(_insecable_wrapper, text)
-    return output
-
-def localize(text):
-    """ Return the text processed with the appropriate system locale
-    """
-    table = {"fr_FR" : lambda x : french_insecable(x)}
-
-    lang = locale.getdefaultlocale()[0]
-    processor = table.get(lang, lambda x : x)
-
-    return processor(text)
-
-def widont(text):
-    """Replaces the space between the last two words in a string with `` ``
-    Works in these block tags ``(h1-h6, p, li, dd, dt)`` and also accounts for
-    potential closing inline elements ``a, em, strong, span, b, i``
-
-    >>> widont('A very simple test')
-    'A very simple test'
-
-    Single word items shouldn't be changed
-    >>> widont('Test')
-    'Test'
-    >>> widont(' Test')
-    ' Test'
-    >>> widont('
  • Test

    • ') - '
      • Test

        • ' - >>> widont('
          • Test

            • ') - '
              • Test

                • ' - - >>> widont('

                  In a couple of paragraphs

                  paragraph two

                  ') - '

                  In a couple of paragraphs

                  paragraph two

                  ' - - >>> widont('

                  In a link inside a heading

                  ') - '

                  In a link inside a heading

                  ' - - >>> widont('

                  In a link followed by other text

                  ') - '

                  In a link followed by other text

                  ' - - Empty HTMLs shouldn't error - >>> widont('

                  ') - '

                  ' - - >>> widont('
                  Divs get no love!
                  ') - '
                  Divs get no love!
                  ' - - >>> widont('
                  Neither do PREs
                  ') - '
                  Neither do PREs
                  ' - - >>> widont('

                  But divs with paragraphs do!

                  ') - '

                  But divs with paragraphs do!

                  ' - """ - - widont_finder = re.compile(r"""((?:]*>)|[^<>\s]) # must be proceeded by an approved inline opening or closing tag or a nontag/nonspace - \s+ # the space to replace - ([^<>\s]+ # must be flollowed by non-tag non-space characters - \s* # optional white space! - (\s*)* # optional closing inline tags with optional white space after each - (()|$)) # end with a closing p, h1-6, li or the end of the string - """, re.VERBOSE) - output = widont_finder.sub(r'\1 \2', text) - - return output - -def applyfilters(text): - """Applies the following filters: smartypants, caps, amp, initial_quotes - - >>> typogrify('

                  "Jayhawks" & KU fans act extremely obnoxiously

                  ') - '

                  Jayhawks” & KU fans act extremely obnoxiously

                  ' - """ - text = amp(text) - text = smartypants(text) - text = caps(text) - text = initial_quotes(text) - text = localize(text) - - return text - -def typogrify(text, ignore_tags=None): - """The super typography filter - - Applies filters to text that are not in tags contained in the - ignore_tags list. - """ - - section_list = process_ignores(text, ignore_tags) - - rendered_text = "" - for text_item, should_process in section_list: - if should_process: - rendered_text += applyfilters(text_item) - else: - rendered_text += text_item - - # apply widont at the end, as its already smart about tags. Hopefully. - return widont(rendered_text) - -def _test(): - import doctest - doctest.testmod(verbose=True) - -if __name__ == "__main__": - _test() diff --git a/plugins/typogrify/titlecase/__init__.py b/plugins/typogrify/titlecase/__init__.py deleted file mode 100755 index aeaca97..0000000 --- a/plugins/typogrify/titlecase/__init__.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/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 deleted file mode 100644 index 97a45e4..0000000 --- a/plugins/typogrify/titlecase/tests.py +++ /dev/null @@ -1,174 +0,0 @@ -#!/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() - diff --git a/plugins/typogrify/typogrify.py b/plugins/typogrify/typogrify.py deleted file mode 100755 index 7f5f568..0000000 --- a/plugins/typogrify/typogrify.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -from pelican import signals -from typogrify.filters import typogrify - -def apply(data): - - if not data._content: - return - - - data._content = typogrify(data._content) - - metadata = data.metadata - metadata['title'] = typogrify(metadata['title']) - -def register(): - signals.content_object_init.connect(apply) diff --git a/readme.rst b/readme.rst index 268e963..eec60e2 100755 --- a/readme.rst +++ b/readme.rst @@ -1,5 +1,5 @@ -Ce dépôt contient le blog hébergé à l'adresse suivante : http://blog.chimrod.com/ +Ce dépôt contient le blog hébergé à l'adresse suivante : https://blog.chimrod.com/ Installation ============ @@ -13,7 +13,7 @@ Installer pélican dans un environnement virtuel : mkvirtualenv pelican workon pelican - pip3 install pelican i18n_subsites3 smartypants pygments + pip3 install pelican smartypants pygments typogrify Copie du dépôt -------------- -- cgit v1.2.3