Zope资源模板
项目描述
本包提供了一种非常简单的模板系统,用于非SGML数据文件,如CSS和JavaScript。
模板资源
Zope的设计目标之一是允许设计师提交HTML模板、CSS和JavaScript文件,使其(带有一些附加信息)直接可用。对于HTML代码,我们使用Zope的页面模板来实现这一目标。对于CSS和JavaScript,我们之前不需要这样的功能,因为那些文件大多是静态的,或者在运行时可以通过其他方式插入变量。
然而,现在在CSS URL中(例如背景图像),经常插入到CSS指令中。然而,设计师的路径布局可能与资源文件结构不匹配。此包提供了一种简单的机制来替换字符串。
为此,提供了一种模板资源。模板语法以一种不会干扰资源语法的方式提供。对于JavaScript和CSS,这是一种形式为/* ... */的注释。
以下是通用语法
<COMMAND-BEGIN> <ZRT-COMMAND>: <COMMAND-ARGUMENTS> <COMMAND-END>
以下是CSS的一个示例
/* zrt-replace: ".." "@@" */
为了演示此功能,我们首先必须创建一个CSS文件。
>>> import tempfile >>> fn = tempfile.mktemp('.css') >>> open(fn, 'w').write('''\ ... /* zrt-replace: "../img1" "++resource++/img" */ ... /* zrt-replace: "fontName" "Arial, Tahoma" */ ... h1 { ... color: red; ... font: fontName; ... background: url('../img1/mybackground.gif'); ... } ... ... h2 { ... color: red; ... background: url('../img2/mybackground.gif'); ... } ... /* zrt-replace: "../img2" "++resource++/img" */ ... ''')
全局替换命令替换一个字符串为另一个。它仅在声明之后的行中有效。因此,在这种情况下,第二个命令是没有意义的。
现在我们从资源工厂创建一个ZRT资源…
>>> from z3c.zrtresource import ZRTFileResourceFactory >>> cssFactory = ZRTFileResourceFactory(fn, None, 'site.css')>>> from zope.publisher.browser import TestRequest >>> css = cssFactory(TestRequest())
然后渲染该资源
>>> print css.GET() h1 { color: red; font: Arial, Tahoma; background: url('++resource++/img/mybackground.gif'); } <BLANKLINE> h2 { color: red; background: url('../img2/mybackground.gif'); }
如您所见,只有第一个URL被替换了,因为第二个语句的位置不正确。
这就完成了!在您的ZCML中,您可以如下使用此工厂
<zrt-resource name="site.css" path="css/site.css" />
替换字符串
zrt-replace命令将匹配项替换为输出字符串,替换次数与指定次数相同。以下是语法
zrt-replace: <EXPR-TYPE>”<INPUT-EXPR>” <EXPR-TYPE>”<OUTPUT-EXPR>” <NUM>
如上例所示,zrt-replace调用可以放在文件的任何位置。让我们确保一些特殊情况也能正常工作
>>> from z3c.zrtresource import processor, replace >>> def process(text): ... p = processor.ZRTProcessor( ... text, commands={'replace': replace.Replace}) ... return p.process(None, None)>>> print process('''\ ... /* zrt-replace: "foo" "bar" */ ... foo''') bar>>> print process('''\ ... /* zrt-replace: "foo" "bar" */ ... foo''') bar>>> print process('''\ ... /* zrt-replace: "foo" "bar" */ ... foo''') bar
但是以下情况不工作
>>> print process('''\ ... /* zrt-replace : "foo" "bar" */ ... foo''') /* zrt-replace : "foo" "bar" */ foo>>> print process('''\ ... /* zrt -replace : "foo" "bar" */ ... foo''') /* zrt -replace : "foo" "bar" */ foo
到目前为止,我们只考虑了多次替换。现在让我们使用最后一个参数限制替换次数。最初,匹配字符串的所有出现都将被替换
>>> print process('''\ ... /* zrt-replace: "foo" "bar" */ ... foo foo foo foo foo''') bar bar bar bar bar
当我们指定替换次数时,则只替换该次数
>>> print process('''\ ... /* zrt-replace: "foo" "bar" 1 */ ... foo foo foo foo foo''') bar foo foo foo foo>>> print process('''\ ... /* zrt-replace: "foo" "bar" 3 */ ... foo foo foo foo foo''') bar bar bar foo foo>>> print process('''\ ... /* zrt-replace: "foo" "bar" 6 */ ... foo foo foo foo foo''') bar bar bar bar bar
字符串表达式
到目前为止,我们只处理了简单的字符串替换,因为这是默认的表达式类型。另一种拼写表达式类型的方法是
>>> print process('''\ ... /* zrt-replace: str"foo" "bar" */ ... foo''') bar>>> print process('''\ ... /* zrt-replace: "foo" str"bar" */ ... foo''') bar>>> print process('''\ ... /* zrt-replace: str"foo" str"bar" */ ... foo''') bar
正则表达式
正则表达式只有作为输入表达式才有意义,因此它们只在那里受支持
>>> print process('''\ ... /* zrt-replace: re"foo" "bar" */ ... foo''') bar>>> print process('''\ ... /* zrt-replace: re"[a-z]*foo" "bar" */ ... myfoo''') bar
我们也支持分组
>>> print process('''\ ... /* zrt-replace: re"([a-z]*)foo" "bar" */ ... myfoo''') bar>>> print process('''\ ... /* zrt-replace: re"([a-z]*)foo" "bar" */ ... myfoo''') bar>>> print process('''\ ... /* zrt-replace: re"([a-z]*)foo" "bar" */ ... myfoo mybar''') bar mybar
是的,甚至分组替换也工作
>>> print process('''\ ... /* zrt-replace: re"([a-z]*)foo" "bar\\1" */ ... myfoo a9foo''') barmy a9bar>>> print process('''\ ... /* zrt-replace: re"(?P<prefix>[a-z]*)foo" "bar\\g<prefix>" */ ... myfoo a9foo''') barmy a9bar
TALES表达式
一个没有TALES表达式的基于Zope的模板语言会是什么样子?如果您想根据请求和上下文创建绝对URL和其他动态部分,这将特别有用
>>> import zope.interface >>> from zope.traversing.interfaces import IContainmentRoot >>> class Root(object): ... zope.interface.implements(IContainmentRoot)>>> from zope.publisher.browser import TestRequest >>> def process(text): ... p = processor.ZRTProcessor( ... text, commands={'replace': replace.Replace}) ... return p.process(Root(), TestRequest())>>> print process('''\ ... /* zrt-replace: "foo" tal"string:${context/@@absolute_url}/@@/foo" */ ... foo''') http://127.0.0.1/@@/foo
自定义ZRT命令
我们可以创建自定义ZRT命令。为此,我们应该注册一个名为IZRTCommandFactory的实用工具
>>> import re >>> from zope import interface >>> from zope.component import provideUtility>>> from z3c.zrtresource import interfaces>>> class MyCustomCommand(object): ... interface.implements(interfaces.IZRTCommand) ... ... data = {'color1': 'red', 'color2': 'green'} ... ... isAvailable = True ... ... def __init__(self, args, start, end): ... self.args = args ... self.start = start ... self.end = end ... ... def process(self, text, context, request): ... for key, value in self.data.items(): ... regex = re.compile(re.escape(key)) ... text = regex.subn(value, text)[0] ... ... return text>>> from zope.component.factory import Factory >>> my_command = Factory(MyCustomCommand, 'mycommand') >>> interface.directlyProvides(my_command, interfaces.IZRTCommandFactory)>>> provideUtility(my_command, interfaces.IZRTCommandFactory, name='mycommand')>>> open(fn, 'w').write('''\ ... /* zrt-replace: "../img1" "++resource++/img" */ ... /* zrt-replace: "fontFamily" "Arial, Tahoma" */ ... /* zrt-mycommand: */ ... /* oh, and we're testing that when the file changes, it is reloaded */ ... h1 { ... color: color1; ... font: fontFamily; ... background: url('../img1/mybackground.gif'); ... } ... ... h2 { ... color: color2; ... background: url('../img2/mybackground.gif'); ... } ... /* zrt-replace: "../img2" "++resource++/img" */ ... ''')
我们必须重新创建ZRTFileResourceFactory以重新加载更改后的文件内容(不用担心 - 在现实生活中,Zope在每次请求时都会创建这些,因为资源实际上是作为IResourceFactoryFactory实用工具注册的)。
>>> cssFactory = ZRTFileResourceFactory(fn, None, 'site.css') >>> css = cssFactory(TestRequest())>>> print css.GET() /* oh, and we're testing that when the file changes, it is reloaded */ h1 { color: red; font: Arial, Tahoma; background: url('++resource++/img/mybackground.gif'); } <BLANKLINE> h2 { color: green; background: url('../img2/mybackground.gif'); } <BLANKLINE>
边缘情况
在Windows上,结果中留有空白行
>>> open(fn, 'w').write('''\ ... some-head ... /* zrt-replace: "../img1" "++resource++/img" */ ... /* zrt-replace: "fontName" "Arial, Tahoma" */ ... some-in-the-middle ... /* zrt-replace: "../img2" "++resource++/img" */ ... some-at-the-end ... ''')>>> cssFactory = ZRTFileResourceFactory(fn, None, 'site.css')>>> from zope.publisher.browser import TestRequest >>> css = cssFactory(TestRequest())
然后渲染该资源
>>> css.GET().splitlines() ['some-head', 'some-in-the-middle', 'some-at-the-end']
zrt-resource 指令
此包提供一个新的指令来使用特殊资源指令。让我们先注册它
>>> from zope.configuration import xmlconfig >>> context = xmlconfig.string(''' ... <configure i18n_domain="zope"> ... <include package="z3c.zrtresource" file="meta.zcml" /> ... </configure> ... ''')
现在我们可以注册一个资源
>>> import tempfile >>> fn = tempfile.mktemp('.css') >>> open(fn, 'w').write('''\ ... /* zrt-replace: "../img1" "++resource++/img" */ ... h1 { ... color: red; ... background: url('../img1/mybackground.gif'); ... } ... ''')>>> context = xmlconfig.string(''' ... <configure xmlns="http://namespaces.zope.org/browser" i18n_domain="zope"> ... <zrt-resource ... name="test.css" ... file="%s" /> ... </configure> ... ''' %fn, context=context)
现在让我们看看适配器是否已注册
>>> import zope.component >>> import zope.interface >>> from zope.publisher.browser import TestRequest >>> resource = zope.component.getAdapter( ... TestRequest(), zope.interface.Interface, name='test.css')
现在运行它
>>> print resource.GET() h1 { color: red; background: url('++resource++/img/mybackground.gif'); }
我们还可以使用标准的browser:resource指令注册ZRT资源。此包中的configure.zcml文件注册了一个用于“zrt”扩展名的ZRT资源工厂,因此任何扩展名为“zrt”的文件都将是一个ZRT资源。
首先,让我们包含browser:resource指令和资源工厂注册
>>> context = xmlconfig.string(''' ... <configure i18n_domain="zope"> ... <include package="zope.browserresource" file="meta.zcml" /> ... <include package="zope.component" file="meta.zcml" /> ... <include package="z3c.zrtresource" /> ... </configure> ... ''')
现在我们需要创建一个扩展名为“zrt”的文件
>>> fn = tempfile.mktemp('.zrt') >>> open(fn, 'w').write('''\ ... /* zrt-replace: "../img1" "++resource++/img" */ ... h1 { ... color: red; ... background: url('../img1/mybackground.gif'); ... } ... ''')
并使用browser:resource指令将其注册为资源。
>>> context = xmlconfig.string(''' ... <configure xmlns="http://namespaces.zope.org/browser" i18n_domain="zope"> ... <resource ... name="test2.css" ... file="%s" /> ... </configure> ... ''' %fn, context=context)
让我们看看适配器是否已注册
>>> resource2 = zope.component.getAdapter( ... TestRequest(), zope.interface.Interface, name='test2.css')
现在,让我们渲染它并检查ZRT机制是否对其有效。
>>> print resource2.GET() h1 { color: red; background: url('++resource++/img/mybackground.gif'); }
变更记录
1.4.0 (2013-05-31)
使测试与zope.browserresource 3.11兼容,因此至少需要此版本。
修复:绕过Windows:它有一个2个字符的换行序列
1.3.0 (2009-08-27)
使用新的zope.browserresource包代替zope.app.publisher,因为资源机制已移至那里以减少依赖。
在包的configure.zcml中将ZRTFileResourceFactory注册为名为“zrt”的资源工厂。这使使用browser:resource指令为扩展名为“zrt”的文件创建ZRT资源自动。它还将使资源目录中的*.zrt文件成为ZRTFileResource。
删除对zope.app.testing测试依赖的引用。
删除未使用的SETUP.CFG和z3c.zrtresource-meta.zcml文件。
1.2.0 (2009-06-25)
删除了对zope.app.component和zope.app.pagetemplate的依赖。
修复了主页和作者电子邮件地址。
1.1.0 (2007-12-01)
修复了替换表达式中空格的bug
添加了自定义ZRT命令
1.0.1 (2007-10-30)
修复了包的长描述,使其成为有效的reStructuredText。
1.0.0 (2007-10-30)
初始发布。
项目详细信息
z3c.zrtresource-1.4.0.zip 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | b950527bb51a475b30d1327c3e5fed1957b091a7bcc71501dd9aaf96402f9fad |
|
MD5 | ac91a0705235150e30b63d69bb1d0705 |
|
BLAKE2b-256 | 584e71abc6e3b262131165f67332f2ada7a92e8c91260634e393c7accb536dce |