@@ -24,7 +24,7 @@ class SyntextPlugin(TextyPlugin): | |||||
""" | """ | ||||
The default pattern for block open text. | The default pattern for block open text. | ||||
""" | """ | ||||
return '^\s*~~~+\s*([A-Za-z0-9_\-\.]+)\s*~*\s*$' | |||||
return '^\s*~~~+\s*([A-Za-z0-9_\-\.:\']+)\s*~*\s*$' | |||||
@property | @property | ||||
def default_close_pattern(self): | def default_close_pattern(self): | ||||
@@ -33,6 +33,18 @@ class SyntextPlugin(TextyPlugin): | |||||
""" | """ | ||||
return '^\s*~~~+\s*$' | return '^\s*~~~+\s*$' | ||||
def get_params(self, match, start=True): | |||||
""" | |||||
~~~css~~~ will return css | |||||
~~~css/style.css will return css,style.css | |||||
""" | |||||
params = super(SyntextPlugin, self).get_params(match, start) | |||||
if ':' in params: | |||||
(lex, _, filename) = params.rpartition(':') | |||||
params = 'lex=\'%(lex)s\',filename=\'%(filename)s\'' % locals() | |||||
return params | |||||
def text_to_tag(self, match, start=True): | def text_to_tag(self, match, start=True): | ||||
""" | """ | ||||
Replace open pattern (default:~~~~~css~~~~~~) | Replace open pattern (default:~~~~~css~~~~~~) | ||||
@@ -64,13 +64,16 @@ class TextyPlugin(Plugin): | |||||
""" | """ | ||||
return None | return None | ||||
def get_params(self, match, start=True): | |||||
return match.groups(1)[0] if match.lastindex else '' | |||||
@abc.abstractmethod | @abc.abstractmethod | ||||
def text_to_tag(self, match, start=True): | def text_to_tag(self, match, start=True): | ||||
""" | """ | ||||
Replaces the matched text with tag statement | Replaces the matched text with tag statement | ||||
given by the template. | given by the template. | ||||
""" | """ | ||||
params = match.groups(1)[0] if match.lastindex else '' | |||||
params = self.get_params(match, start) | |||||
return (self.template.get_open_tag(self.tag_name, params) | return (self.template.get_open_tag(self.tag_name, params) | ||||
if start | if start | ||||
else self.template.get_close_tag(self.tag_name, params)) | else self.template.get_close_tag(self.tag_name, params)) | ||||
@@ -64,11 +64,10 @@ def markdown(env, value): | |||||
@environmentfilter | @environmentfilter | ||||
def syntax(env, value, lexer=None): | |||||
def syntax(env, value, lexer=None, filename=None): | |||||
""" | """ | ||||
Processes the contained block using `pygments` | Processes the contained block using `pygments` | ||||
""" | """ | ||||
try: | try: | ||||
import pygments | import pygments | ||||
from pygments import lexers | from pygments import lexers | ||||
@@ -87,7 +86,10 @@ def syntax(env, value, lexer=None): | |||||
formatter = formatters.HtmlFormatter(**settings) | formatter = formatters.HtmlFormatter(**settings) | ||||
code = pygments.highlight(value, pyg, formatter) | code = pygments.highlight(value, pyg, formatter) | ||||
code = code.replace('\n\n', '\n \n').replace('\n', '<br />') | code = code.replace('\n\n', '\n \n').replace('\n', '<br />') | ||||
return Markup('\n\n<div class="code">%s</div>\n\n' % code) | |||||
caption = filename if filename else pyg.name | |||||
return Markup( | |||||
'\n\n<div class="code"><figcaption>%s</figcaption>%s</div>\n\n' | |||||
% (caption, code)) | |||||
class Markdown(Extension): | class Markdown(Extension): | ||||
""" | """ | ||||
@@ -115,35 +117,66 @@ class Markdown(Extension): | |||||
output = caller().strip() | output = caller().strip() | ||||
return markdown(self.environment, output) | return markdown(self.environment, output) | ||||
def parse_kwargs(parser): | |||||
name = parser.stream.expect('name').value | |||||
parser.stream.expect('assign') | |||||
if parser.stream.current.test('string'): | |||||
value = parser.parse_expression() | |||||
else: | |||||
value = nodes.Const(parser.stream.next().value) | |||||
return (name, value) | |||||
class Syntax(Extension): | class Syntax(Extension): | ||||
""" | """ | ||||
A wrapper around the syntax filter for syntactic sugar. | A wrapper around the syntax filter for syntactic sugar. | ||||
""" | """ | ||||
tags = set(['syntax']) | tags = set(['syntax']) | ||||
def parse(self, parser): | def parse(self, parser): | ||||
""" | """ | ||||
Parses the statements and defers to the callback for pygments processing. | Parses the statements and defers to the callback for pygments processing. | ||||
""" | """ | ||||
lineno = parser.stream.next().lineno | lineno = parser.stream.next().lineno | ||||
lex = None | |||||
if parser.stream.current.type != 'block_end': | |||||
lex = parser.stream.next().value | |||||
lex = nodes.Const(None) | |||||
filename = nodes.Const(None) | |||||
def fail_syntax(): | |||||
parser.fail( | |||||
'Invalid syntax tag. Expected:' | |||||
'{% syntax lex=yaml, filename=abc.yaml %} or' | |||||
'{% syntax yaml, \'abc.yaml\' %}') | |||||
if not parser.stream.current.test('block_end'): | |||||
if parser.stream.look().test('assign'): | |||||
name = value = name1 = value1 = None | |||||
(name, value) = parse_kwargs(parser) | |||||
if parser.stream.skip_if('comma'): | |||||
(name1, value1) = parse_kwargs(parser) | |||||
(lex, filename) = (value, value1) \ | |||||
if name == 'lex' \ | |||||
else (value1, value) | |||||
else: | |||||
lex = nodes.Const(parser.stream.next().value) | |||||
if parser.stream.skip_if('comma'): | |||||
filename = parser.parse_expression() | |||||
body = parser.parse_statements(['name:endsyntax'], drop_needle=True) | body = parser.parse_statements(['name:endsyntax'], drop_needle=True) | ||||
return nodes.CallBlock( | return nodes.CallBlock( | ||||
self.call_method('_render_syntax', args=[nodes.Const(lex)]), | |||||
self.call_method('_render_syntax', | |||||
args=[lex, filename]), | |||||
[], [], body).set_lineno(lineno) | [], [], body).set_lineno(lineno) | ||||
def _render_syntax(self, lex, caller=None): | |||||
def _render_syntax(self, lex, filename, caller=None): | |||||
""" | """ | ||||
Calls the syntax filter to transform the output. | Calls the syntax filter to transform the output. | ||||
""" | """ | ||||
if not caller: | if not caller: | ||||
return '' | return '' | ||||
output = caller().strip() | output = caller().strip() | ||||
return syntax(self.environment, output, lex) | |||||
return syntax(self.environment, output, lex, filename) | |||||
class IncludeText(Extension): | class IncludeText(Extension): | ||||
""" | """ | ||||
@@ -63,11 +63,25 @@ article { | |||||
} | } | ||||
} | } | ||||
.highlight pre{ | |||||
font-size: @gutter; | |||||
.boxshadow(0, 1px, 3px, @qdark); | |||||
padding: @gutter + 4 @gutter @gutter; | |||||
line-height: @gutter * 2; | |||||
margin-bottom: @gutter / 2 + 2; | |||||
.code{ | |||||
position: relative; | |||||
figcaption{ | |||||
font-size: @gutter - 2; | |||||
position:absolute; | |||||
bottom: @gutter * 2.5; | |||||
right: @gutter; | |||||
color: @qdark; | |||||
} | |||||
} | } | ||||
.highlight | |||||
{ | |||||
pre{ | |||||
font-size: @gutter; | |||||
.boxshadow(0, 1px, 3px, @qdark); | |||||
padding: @gutter + 4 @gutter @gutter; | |||||
line-height: @gutter * 2; | |||||
margin-bottom: @gutter / 2 + 2; | |||||
} | |||||
} |
@@ -92,6 +92,7 @@ Hyde is [socially coded][hydepy]. Feel free to [fork][forking]. | |||||
5. Feed / Listing generation | 5. Feed / Listing generation | ||||
6. Translation | 6. Translation | ||||
[hydeid]: http://groups.google.com/group/hyde-dev/web/hyde-1-0 | [hydeid]: http://groups.google.com/group/hyde-dev/web/hyde-1-0 | ||||
[Jekyll]: http://jekyllrb.com | [Jekyll]: http://jekyllrb.com | ||||
[evil twin]: http://ringce.com/blog/2009/introducing_hyde | [evil twin]: http://ringce.com/blog/2009/introducing_hyde | ||||
@@ -24,28 +24,27 @@ know the base template for that page. The plugin will automatically emit an | |||||
The following two configurations are equivalent. | The following two configurations are equivalent. | ||||
~~~~~jinja~~~~ | |||||
~~~~~jinja:hello.html~~~~ | |||||
{% raw %} | {% raw %} | ||||
{% extends "base.html" %} | {% extends "base.html" %} | ||||
<!-- hello.html --> | |||||
{% block content %} | {% block content %} | ||||
Hello World! | Hello World! | ||||
{% endblock %} | {% endblock %} | ||||
{% endraw %} | {% endraw %} | ||||
~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~ | ||||
~~~~~jinja~~~~ | |||||
~~~~~jinja:hello.html~~~~ | |||||
{% raw %} | {% raw %} | ||||
=== | === | ||||
extends: base.html | extends: base.html | ||||
=== | === | ||||
<!-- hello.html --> | |||||
{% block content %} | {% block content %} | ||||
Hello World! | Hello World! | ||||
{% endblock %} | {% endblock %} | ||||
{% endraw %} | {% endraw %} | ||||
~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~ | ||||
## Default blocks | ## Default blocks | ||||
It gets even better. The auto extend plugin also allows you to specify | It gets even better. The auto extend plugin also allows you to specify | ||||
@@ -54,12 +53,11 @@ the default block so that you can take out another wrapping curly brace. | |||||
The following snippet is equivalent to the above ones: | The following snippet is equivalent to the above ones: | ||||
~~~~~jinja~~~~ | |||||
~~~~~jinja:hello.html~~~~ | |||||
=== | === | ||||
extends: base.html | extends: base.html | ||||
default_block: content | default_block: content | ||||
=== | === | ||||
<!-- hello.html --> | |||||
Hello World! | Hello World! | ||||
~~~~~~~~~~~~~~~ | ~~~~~~~~~~~~~~~ | ||||
@@ -71,21 +69,22 @@ As you can see, this makes the page _layout free_. | |||||
In combination with metadata inheritance, this plugin can completely | In combination with metadata inheritance, this plugin can completely | ||||
eliminate redundancy on many sites. | eliminate redundancy on many sites. | ||||
Given the following configuration, the output would be same as what | |||||
is generated by any of the above snippets. | |||||
Given this configuration: | |||||
~~~yaml~~~ | |||||
site_name: Hello World #site.yaml | |||||
~~~yaml:site.yaml~~~ | |||||
site_name: Hello World | |||||
meta: | meta: | ||||
extends: base.html | extends: base.html | ||||
default_block: content | default_block: content | ||||
~~~~~~~~~ | ~~~~~~~~~ | ||||
~~~jinja~~~ | |||||
<!-- hello.html --> | |||||
the output of the following file be same as what | |||||
is generated by any of the above snippets. | |||||
~~~jinja:hello.html~~~ | |||||
Hello World | Hello World | ||||
~~~~~~~~~~~ | ~~~~~~~~~~~ | ||||
Just Content! | |||||
Just content! | |||||
===/doc=== | ===/doc=== |
@@ -25,17 +25,32 @@ Hyde's plugins get loaded if they are listed in the plugins section of | |||||
respective sections. For example, `MyAwesomePlugin` will get parameters | respective sections. For example, `MyAwesomePlugin` will get parameters | ||||
from `myawesome` section in the configuration file. | from `myawesome` section in the configuration file. | ||||
# In the box | |||||
## In the box | |||||
Hyde is shipped with the following plugins: | Hyde is shipped with the following plugins: | ||||
* Autoextend | |||||
* Metadata | |||||
* Sorter | |||||
* Less CSS | |||||
* Text Replacement Plugins | |||||
- Blockdown | |||||
- Mark and Refer | |||||
- Textlinks | |||||
- Syntext | |||||
* Folder flattener | |||||
* [Metadata][] | |||||
* [Autoextend][] | |||||
* [Sorter][] | |||||
* [Less CSS][] | |||||
* [Text Replacement Plugins][] | |||||
- [Blockdown][] | |||||
- [Mark and Refer][] | |||||
- [Textlinks][] | |||||
- [Syntext][] | |||||
* [Folder flattener][] | |||||
[Autoextend]: [[plugins/autoextend]] | |||||
[Blockdown]: [[plugins/blockdown]] | |||||
[Folder flattener]: Folder flattener | |||||
[Less CSS]: Less CSS | |||||
[Mark and Refer]: Mark and Refer | |||||
[Metadata]: Metadata | |||||
[Sorter]: Sorter | |||||
[Syntext]: Syntext | |||||
[Text Replacement Plugins]: Text Replacement Plugins | |||||
[Textlinks]: Textlinks | |||||
[configuration]: configuration | |||||
[devdocs]: devdocs | |||||
@@ -1,3 +1,3 @@ | |||||
extends: site.yaml | extends: site.yaml | ||||
mode: production | mode: production | ||||
deploy_root: ../../../../hydepy.github.com | |||||
deploy_root: ../../../../hyde.github.com |
@@ -15,7 +15,6 @@ TEST_SITE = File(__file__).parent.parent.child_folder('_test') | |||||
def assert_valid_conversion(html): | def assert_valid_conversion(html): | ||||
assert html | assert html | ||||
q = PyQuery(html) | q = PyQuery(html) | ||||
print html | |||||
assert "is_processable" not in html | assert "is_processable" not in html | ||||
assert q("h1") | assert q("h1") | ||||
assert "This is a" in q("h1").text() | assert "This is a" in q("h1").text() | ||||