Browse Source

Added syntactic sugar for markings. Also refactored the template class.

main
Lakshmi Vyasarajan 14 years ago
parent
commit
35637209e1
14 changed files with 317 additions and 79 deletions
  1. +2
    -1
      hyde/ext/plugins/auto_extend.py
  2. +26
    -32
      hyde/ext/plugins/blockdown.py
  3. +1
    -0
      hyde/ext/plugins/less.py
  4. +47
    -0
      hyde/ext/plugins/markings.py
  5. +1
    -0
      hyde/ext/plugins/meta.py
  6. +1
    -0
      hyde/ext/plugins/sorter.py
  7. +98
    -0
      hyde/ext/plugins/texty.py
  8. +40
    -0
      hyde/ext/templates/jinja.py
  9. +1
    -0
      hyde/generator.py
  10. +1
    -0
      hyde/loader.py
  11. +1
    -1
      hyde/model.py
  12. +1
    -0
      hyde/server.py
  13. +28
    -45
      hyde/template.py
  14. +69
    -0
      hyde/tests/ext/test_markings.py

+ 2
- 1
hyde/ext/plugins/auto_extend.py View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Autoextend css plugin
"""
@@ -29,7 +30,7 @@ class AutoExtendPlugin(Plugin):
except AttributeError:
pass
if layout:
extends_pattern = self.template.extends_pattern
extends_pattern = self.template.patterns['extends']

if not re.search(extends_pattern, text):
extended_text = self.template.get_extends_statement(layout)


+ 26
- 32
hyde/ext/plugins/blockdown.py View File

@@ -1,34 +1,39 @@
# -*- coding: utf-8 -*-
"""
Blockdown css plugin
Blockdown plugin
"""

from hyde.plugin import Plugin
from hyde.fs import File, Folder
from hyde.ext.plugins.texty import TextyPlugin

import re
from functools import partial

class BlockdownPlugin(Plugin):
class BlockdownPlugin(TextyPlugin):
"""
The plugin class for less css
The plugin class for block text replacement.
"""

def __init__(self, site):
super(BlockdownPlugin, self).__init__(site)
try:
self.open_pattern = site.config.blockdown.open_pattern
except AttributeError:
self.open_pattern = '^\s*===+\s*([A-Za-z0-9_\-.]+)\s*=*\s*$'

try:
self.close_pattern = site.config.blockdown.close_pattern
except AttributeError:
self.close_pattern = '^\s*===+\s*/+\s*=*/*([A-Za-z0-9_\-.]*)[\s=/]*$'
@property
def tag_name(self):
"""
The block tag.
"""
return 'block'

def template_loaded(self, template):
self.template = template
@property
def default_open_pattern(self):
"""
The default pattern for block open text.
"""
return '^\s*===+\s*([A-Za-z0-9_\-\.]+)\s*=*\s*$'

@property
def default_close_pattern(self):
"""
The default pattern for block close text.
"""
return '^\s*===+\s*/+\s*=*/*([A-Za-z0-9_\-\.]*)[\s=/]*$'

def begin_text_resource(self, resource, text):
def text_to_tag(self, match, start=True):
"""
Replace open pattern (default:===[====]blockname[===========])
with
@@ -37,15 +42,4 @@ class BlockdownPlugin(Plugin):
with
{% block blockname %} or equivalent
"""
blocktag_open = re.compile(self.open_pattern, re.MULTILINE)
blocktag_close = re.compile(self.close_pattern, re.MULTILINE)
def blockdown_to_block(match, start_block=True):
if not match.lastindex:
return ''
block_name = match.groups(1)[0]
return (self.template.get_block_open_statement(block_name)
if start_block
else self.template.get_block_close_statement(block_name))
text = blocktag_open.sub(blockdown_to_block, text)
text = blocktag_close.sub(partial(blockdown_to_block, start_block=False), text)
return text
return super(BlockdownPlugin, self).text_to_tag(match, start)

+ 1
- 0
hyde/ext/plugins/less.py View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Less css plugin
"""


+ 47
- 0
hyde/ext/plugins/markings.py View File

@@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
"""
Markings plugin
"""

from hyde.ext.plugins.texty import TextyPlugin

class MarkingsPlugin(TextyPlugin):
"""
The plugin class for mark text replacement.
"""
def __init__(self, site):
super(MarkingsPlugin, self).__init__(site)

@property
def tag_name(self):
"""
The mark tag.
"""
return 'mark'

@property
def default_open_pattern(self):
"""
The default pattern for mark open text.
"""
return u'^§§+\s*([A-Za-z0-9_\-]+)\s*$'

@property
def default_close_pattern(self):
"""
The default pattern for mark close text.
"""
return u'^§§+\s*([A-Za-z0-9_\-]*)\s*\.\s*$'

def text_to_tag(self, match, start=True):
"""
Replace open pattern (default:§§ CSS)
with
{% mark CSS %} or equivalent and
Replace close pattern (default: §§ CSS.)
with
{% endmark %} or equivalent
"""
text = super(MarkingsPlugin, self).text_to_tag(match, start)
print text
return text

+ 1
- 0
hyde/ext/plugins/meta.py View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Contains classes and utilities related to meta data in hyde.
"""


+ 1
- 0
hyde/ext/plugins/sorter.py View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Contains classes and utilities related to sortin
resources and nodes in hyde.


+ 98
- 0
hyde/ext/plugins/texty.py View File

@@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
"""
Provides classes and utilities that allow text
to be replaced before the templates are
rendered.
"""

from hyde.plugin import Plugin

import abc
import re
from functools import partial


class TextyPlugin(Plugin):
"""
Base class for text preprocessing plugins.

Plugins that desire to provide syntactic sugar for
commonly used hyde functions for various templates
can inherit from this class.
"""

__metaclass__ = abc.ABCMeta

def __init__(self, site):
super(TextyPlugin, self).__init__(site)

self.open_pattern = self.default_open_pattern
self.close_pattern = self.default_close_pattern
self.template = None
config = getattr(site.config, self.plugin_name, None)

if config and hasattr(config, 'open_pattern'):
self.open_pattern = config.open_pattern

if config and hasattr(config, 'close_pattern'):
self.open_pattern = config.close_pattern

@property
def plugin_name(self):
"""
The name of the plugin. Makes an intelligent guess.
"""
return self.__class__.__name__.replace('Plugin', '').lower()

@abc.abstractproperty
def tag_name(self):
"""
The tag that this plugin tries add syntactic sugar for.
"""
return self.plugin_name

@abc.abstractproperty
def default_open_pattern(self):
"""
The default pattern for opening the tag.
"""
return None

@abc.abstractproperty
def default_close_pattern(self):
"""
The default pattern for closing the tag.
"""
return None

def template_loaded(self, template):
"""
Handles the template loaded event to keep
a reference to the template object.
"""
self.template = template

@abc.abstractmethod
def text_to_tag(self, match, start=True):
"""
Replaces the matched text with tag statement
given by the template.
"""
if not match.lastindex:
return ''
params = match.groups(1)[0]
return (self.template.get_open_tag(self.tag_name, params)
if start
else self.template.get_close_tag(self.tag_name, params))

def begin_text_resource(self, resource, text):
"""
Replace a text base pattern with a template statement.
"""
text_open = re.compile(self.open_pattern, re.MULTILINE)
text_close = re.compile(self.close_pattern, re.MULTILINE)

text = text_open.sub(self.text_to_tag, text)
text = text_close.sub(
partial(self.text_to_tag, start=False), text)
return text

+ 40
- 0
hyde/ext/templates/jinja.py View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Jinja template utilties
"""
@@ -296,6 +297,45 @@ class Jinja2Template(Template):
"""
return TemplateError

@property
def patterns(self):
"""
The pattern for matching selected template statements.
"""
return {
"block_open": '\s*\{\%\s*block\s*([^\s]+)\s*\%\}',
"block_close": '\s*\{\%\s*endblock\s*([^\s]*)\s*\%\}',
"include": '\s*\{\%\s*include\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}',
"extends": '\s*\{\%\s*extends\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}'
}

def get_include_statement(self, path_to_include):
"""
Returns an include statement for the current template,
given the path to include.
"""
return '{%% include \'%s\' %%}' % path_to_include

def get_extends_statement(self, path_to_extend):
"""
Returns an extends statement for the current template,
given the path to extend.
"""
return '{%% extends \'%s\' %%}' % path_to_extend

def get_open_tag(self, tag, params):
"""
Returns an open tag statement.
"""
return '{%% %s %s %%}' % (tag, params)

def get_close_tag(self, tag, params):
"""
Returns an open tag statement.
"""
return '{%% end%s %%}' % tag


def render(self, text, context):
"""
Renders the given resource using the context


+ 1
- 0
hyde/generator.py View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
The generator class and related utility functions.
"""


+ 1
- 0
hyde/loader.py View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Generic loader of extensions (plugins & templates)
"""


+ 1
- 1
hyde/model.py View File

@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
"""
Contains data structures and utilities for hyde.
"""


class Expando(object):
"""
A generic expando class that creates attributes from


+ 1
- 0
hyde/server.py View File

@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
"""
Contains classes and utilities for serving a site
generated from hyde.


+ 28
- 45
hyde/template.py View File

@@ -6,6 +6,8 @@ Abstract classes and utilities for template engines
from hyde.exceptions import HydeException
from hyde.util import getLoggerWithNullHandler

import abc

class HtmlWrap(object):
"""
A wrapper class for raw html.
@@ -38,10 +40,13 @@ class Template(object):
the following interface must be implemented.
"""

__metaclass__ = abc.ABCMeta

def __init__(self, sitepath):
self.sitepath = sitepath
self.logger = getLoggerWithNullHandler(self.__class__.__name__)

@abc.abstractmethod
def configure(self, site, engine):
"""
The site object should contain a config attribute. The config object is
@@ -64,7 +69,7 @@ class Template(object):
context object that is populated with the appropriate variables for the given
path.
"""
abstract
return

def get_dependencies(self, text):
"""
@@ -73,77 +78,55 @@ class Template(object):
"""
return None

@abc.abstractmethod
def render(self, text, context):
"""
Given the text, and the context, this function must return the
rendered string.
"""

abstract
return ''

@property
@abc.abstractproperty
def exception_class(self):
return HydeException

@property
def include_pattern(self):
@abc.abstractproperty
def patterns(self):
"""
The pattern for matching include statements
Patterns for matching selected template statements.
"""
return {}

return '\s*\{\%\s*include\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}'

@abc.abstractmethod
def get_include_statement(self, path_to_include):
"""
Returns an include statement for the current template,
given the path to include.
"""
return "{%% include '%s' %%}" % path_to_include

@property
def block_open_pattern(self):
"""
The pattern for matching include statements
"""

return '\s*\{\%\s*block\s*([^\s]+)\s*\%\}'

@property
def block_close_pattern(self):
"""
The pattern for matching include statements
"""

return '\s*\{\%\s*endblock\s*([^\s]*)\s*\%\}'
return '{%% include \'%s\' %%}' % path_to_include

def get_block_open_statement(self, block_name):
"""
Returns a open block statement for the current template,
given the block name.
"""
return "{%% block %s %%}" % block_name

def get_block_close_statement(self, block_name):
@abc.abstractmethod
def get_extends_statement(self, path_to_extend):
"""
Returns a close block statement for the current template,
given the block name.
Returns an extends statement for the current template,
given the path to extend.
"""
return "{%% endblock %s %%}" % block_name
return '{%% extends \'%s\' %%}' % path_to_extend

@property
def extends_pattern(self):
@abc.abstractmethod
def get_open_tag(self, tag, params):
"""
The pattern for matching include statements
Returns an open tag statement.
"""
return '{%% %s %s %%}' % (tag, params)

return '\s*\{\%\s*extends\s*(?:\'|\")(.+?\.[^.]*)(?:\'|\")\s*\%\}'

def get_extends_statement(self, path_to_extend):
@abc.abstractmethod
def get_close_tag(self, tag, params):
"""
Returns an extends statement for the current template,
given the path to extend.
Returns an open tag statement.
"""
return "{%% extends '%s' %%}" % path_to_extend
return '{%% end%s %%}' % tag

@staticmethod
def find_template(site):


+ 69
- 0
hyde/tests/ext/test_markings.py View File

@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*-
"""
Use nose
`$ pip install nose`
`$ nosetests`
"""
from hyde.fs import File, Folder
from hyde.generator import Generator
from hyde.site import Site

from pyquery import PyQuery

TEST_SITE = File(__file__).parent.parent.child_folder('_test')


class TestMarkings(object):

def setUp(self):
TEST_SITE.make()
TEST_SITE.parent.child_folder(
'sites/test_jinja').copy_contents_to(TEST_SITE)

def tearDown(self):
TEST_SITE.delete()

def test_markings(self):
text = u"""
===
is_processable: False
===
{% filter markdown|typogrify %}
§§ heading
This is a heading
=================
§§ heading.

§§ content
Hyde & Jinja.
§§ .

{% endfilter %}
"""

text2 = """
{% refer to "inc.md" as inc %}
{% filter markdown|typogrify %}
{{ inc.heading }}
{{ inc.content }}
{% endfilter %}
"""
site = Site(TEST_SITE)
site.config.plugins = [
'hyde.ext.plugins.meta.MetaPlugin',
'hyde.ext.plugins.markings.MarkingsPlugin']
inc = File(TEST_SITE.child('content/inc.md'))
inc.write(text)
site.load()
gen = Generator(site)
gen.load_template_if_needed()
template = gen.template
html = template.render(text2, {}).strip()
assert html
q = PyQuery(html)
assert "is_processable" not in html
assert "This is a" in q("h1").text()
assert "heading" in q("h1").text()
assert q(".amp").length == 1
assert "mark" not in html
assert "reference" not in html

Loading…
Cancel
Save