Closed ebrehault closed 9 years ago
I'm uncomfortable with adding in more rule types. We already support <replace content="...">
(docs). I think it should be possible to extend this to support <before content="...">
and <after content="...">
too, which would avoid the extra pass through the document.
My 2c: while it's great to have <replace content="...">
, in all my projects I spend 90% of my diazo work struggling to get some stupid xsl rules to work inside those <replace...>
blocks, because everything else is so easy and effortless. So I would highly welcome some way to make this as easy as the rest of diazo is, whether it's before-content
, after-content
, or <before content="...">
, etc.
@fulv I have an idea on how to help with that. I find that most of the time the XSL between a <replace>
is a mix of html and <xsl copy>
statements. That's not nice for two reasons - you need to know xsl which is a different syntax and it kind of defeats the purpose of diazo if your mockup moves out of the .html and into the .xml. I was thinking of a kind of nested diazo where you can do subreplacements inside a replace statement. And you can pick a different part of the .html mockup to be the sub theme. Would be a lot nicer for repeated elements like lists or portlets I think. I haven't come up with a syntax I really like yet though.
if it was a content to content replacement, the kind of syntax I'm thinking of would be like
<replace-content css:to-content-children="#newportlets" content:css=".portlet" subtheme=".portletmockup">
<replace theme="./myportlettitle/text()" content=".portlet_header"/>
<replace theme="./myportlebody/text()" content=".portlet_body"/>
</replace>
@lrowe, <replace content="..">
only allows to inject static html hard-coded into the rules.xml
file, if we want to manipulate the content, the only option at the moment is inline XSLT, which is too complex for regular users. That is basically why I worked on implementin those *-content
rules.
And manipulating the content implies one extra pass through the doc.
I will run a quick benchmark to estimate precisely if it does impact the perf or not and I will let you know.
I hate to pile on, but I also agree that something like this could be very helpful.
@ebrehault with before/after content your examples would look something like this:
# <prepend-content css:to-content="#header" css:content="h2" />
<before css:content="#header">
<xsl:apply-templates css:select="h2" />
</before>
# <append-content css:to-content="#footer" css:content="h2" href="extra.html"/>
<after css:content="#footer">
<xsl:apply-templates select="document('extra.html', '/')//h2" mode="raw"/>
</after>
As others have said, that xsl:apply-templates is scary, so perhaps we could allow a spelling like this:
<after css:content="#footer">
<include css:content="h2" href="extra.html"/>
</after>
That would minimise the number of new rule types.
Performance-wise, a second pass through the content document approximately doubles xsl execution time. Diazo is about twice as fast as XDV because it only makes a single pass (benchmark.)
(Edit: removed wrong mode attribute from first xsl:apply-temlplates.)
Good, this spelling is probably simple enough (@djay, don't you think?) , so I will work on this approach (=implementing <before content="...">...</before>
and <after content="...">...</after>
+ the <include>
syntax).
Note: regarding the perf, I have run JMeter on a vanilla Plone 5 site with or without my Diazo changes, and surprinsingly, the results are slightly better with my changes (no idea why...).
@ebrehault I would tackle include separately (separate pull request) from before/after content as they are orthogonal. For include I think you can just translate to the appropriate xsl:apply-templates in normalize-rules.xsl.
For before/after content I think this can be implemented by having before/replace/after content/content-children share an xsl:template which then redispatches to per rule templates. So currently in emit-stylesheet.xsl we compile a replace content rule to an xsl:template such as:
# <replace content="//*[@id='foo']"><p>bar</p></replace>
<xsl:template match="//*[@id='foo']">
<p>bar</p>
</xsl:template>
That should change to two rules, the first bringing that element into the before/replace/after processing:
<xsl:template match="//*[@id='foo']">
<xsl:apply-templates select="." mode="before-content" />
<xsl:apply-templates select="." mode="replace-content" />
<xsl:apply-templates select="." mode="after-content" />
</xsl:template>
<xsl:template match="//*[@id='foo']" mode="replace-content">
<p>bar</p>
</xsl:template>
And a default replace-content that redispatches to content-children:
<xsl:template match="*" mode="replace-content">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="." mode="before-content-children" />
<xsl:apply-templates select="." mode="replace-content-children" />
<xsl:apply-templates select="." mode="after-content-children" />
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="replace-content-children">
<xsl:apply-templates select="node()" />
</xsl:template>
overall +1 for the feature (let the details to the diazo experts) - I also ended up with xsl in past where the new rules are a big simplification.
Replaced by #43 + #44
Principle
This PR adds the following rules:
replace-content
,before-content
,after-content
,prepend-content
andappend-content
. Those rules allow to modify the content before applying the theme. A typical example would be:Objective
In many cases, our Diazo themes are based on big blocks (like header / content / side columns / footer). If we want to dispatch very granularly the content elements, it implies to create a very detailed theme markup, which is difficult to maintain, and lakes of flexibility (for instance if we want to refactor our grid system). Those rules provide a powerful way to re-organize elements which might be located in a quite deep location in the content document, and keeping a quite simple theme page structure. Moreover, they also allow (using the
href
attributes) to inject external contents into the current content, which can be handy to aggregate contents without needing specific slots in the theme markup.Implementation
Regarding the implementation, it does not pollute the existing processing, it just adds a new mode (named
content2content
) in the resulting stylesheet, this mode is called before the existingcontent2style
mode. It should have no impact on performances for existing Diazo themes using the currently existing rules.@lrowe, please have a look when you have a moment.