Re: Per-Template-configuration feature in FM 2.3.24
Daniel Dekany <[email protected]> Mon, 10 Aug 2015 21:02:35 +0200
| Newsgroups | gmane.comp.web.freemarker.devel |
|---|---|
| Message-ID | <[email protected]> |
Monday, August 10, 2015, 2:35:04 PM, Woonsan Ko wrote:
> Is it about a setting overriding option in "Layer 2: Template" level" [1]?
Exactly.
> Regarding the "hypothetical" HTML or XML format configuration option, is
> it similar to automatic addition of escape directive [2]?
As far as most users are concerned, yes. It will work very differently
though, if it will work as I have planned but that's another subject.
(A noticeable effect will be that #noescape will give an error,
instead you can use ${foo?noEsc}, which is generally more convenient.
Though I also plant to add block directives like
<#autoEsc false>...</#autoEsc>. The point is, that #escape/#noescape
with expression rewriting, while the new feature meant to use a more
specialized approach. So #escape/#noescape will be probably banned if
the new auto-escaping is on, to prevent confusion.)
I also intend to introduce a few new "standard" file extensions (in
additionally to "ftl"), which are: "ftlh" which sets the output format
to HTML, "ftlx" which sets it to "XML", maybe "ftlxh" for "XHTML" (I
will check if we still need that with today's browsers), and "ftlr"
for "RTF" (because, we traditionally support that...). So if someone
sets incompatibleImprovemetns to at least "2.3.24", these will just
work. You will also be able to register your own output formats and
associate them with file extension (or whatever name pattern) with
cfg.setTemplateConfigurer(...).
It's also possible to write <#ftl outputFormat="HTML">, to specify the
output format right in the template.
> If that can be done easily in programmatic way as well as configuration
> way, then it seems good to me.
For the lowest level of control, you can pass a ParserConfiguration to
the Template constructor, and in the ParserConfiguration you can set
the outputFormat and autoEscaping properties. Of course most users
never instantiate Templates in their own code
(Configuration.getTemplate does that for them), and that's when
cfg.setTemplateConfigurers comes into play.
Even if you are relying on cfg.setTemplateConfigurers, you can
implement your own TemplateConfigurerFactory that can decide what
TemplateConfigurer, and hence, what ParserConfiguration to use.
> Regards,
>
> Woonsan
>
> [1] http://freemarker.org/docs/pgui_config_settings.html
> [2] http://freemarker.org/docs/ref_directive_escape.html
>
> On 8/8/15 11:29 AM, Daniel Dekany wrote:
>> Any insight with the below new feature? It's implemented and committed
>> BTW (2.3-gae), but can be seen as a proof-of-the-concept...
>>
>>
>> Something FM was missing is a way of specifying different
>> Configuration settings for different templates. You have a common
>> Configuration, and all templates that you get from that via
>> getTemplate(...) has the same configuration settings, inherited from
>> the Configuration (apart from locale that you can specify to
>> getTemplate(...)). While Template always had setter methods to
>> override the settings, with Configurable.getTemplate(...) you have no
>> chance to call them. (You could call them after getTemplate, but that
>> would not thread safe, etc.)
>>
>> Planned features, such as true auto-escaping will need such
>> functionality. Like you might want *.ftlh to be automatically HTML
>> escaped, but not for *.ftl. (That's something I ran into recently,
>> though I have used Velocity there...)
>>
>> So I came up with TemplateConfigurer, which is an object on which you
>> can set settings (from freemarker.core.Configurable), which it can set
>> in Template like myTemplateCfger.configure(template). A
>> TemplateConfigurer can also hold settings that influence parsing (like
>> tag_syntax, etc., from freemarker.core.ParserConfiguration, which is
>> also new in 2.3.24), and can even specify the charset to used for
>> loading the template (if you ever had a mix of UTF-8 and
>> ISO-8859-<x>/CP<x> templates...).
>>
>> Then, I have added a new Configuration setting, called
>> "templateConfigurers". It's type is
>> freemarker.cache.TemplateConfigurerFactory, which is basically a
>> collection of TemplateConfigurer-s, plus rules that tell that
>> depending on the name of the template (the "source name" that the
>> TemplateLoader uses), when to apply which. Using the Properties-based
>> configuration syntax of FreeMarker for brevity (the Java config would
>> be the same, but with bunch of `new`-s and setXxx-s), it's something
>> like this:
>>
>> MergingTemplateConfigurerFactory(
>> FirstMatchTemplateConfigurerFactory(
>> ConditionalTemplateConfigurerFactory(
>> FileNameGlobMatcher('*.de.*'),
>> TemplateConfigurer(timeZone=TimeZone('GMT+01'), locale=Locale('de', 'DE'))),
>> ConditionalTemplateConfigurerFactory(
>> FileNameGlobMatcher('*.fr.*'),
>> TemplateConfigurer(timeZone=TimeZone('GMT'), locale=Locale('fr', 'FR'))),
>> allowNoMatch=true
>> ),
>> FirstMatchTemplateConfigurerFactory(
>> ConditionalTemplateConfigurerFactory(
>> FileNameGlobMatcher('*.ftlh'),
>> TemplateConfigurer(outputFormat='HTML')),
>> ConditionalTemplateConfigurerFactory(
>> FileNameGlobMatcher('*.ftlx'),
>> TemplateConfigurer(outputFormat='XML')),
>> noMatchErrorDetails='Unrecognized template file extension'
>> ),
>> ConditionalTemplateConfigurerFactory(
>> PathGlobMatcher('stat/**')
>> TemplateConfigurer(timeZone=TimeZone('UTC'))
>> )
>> )
>>
>> The "outputFormat" setting above is hypothetical, we don't yet have
>> it.
>>
>> So if you set this as the "templateConfigurers", and you get a
>> template called "foo.de.ftlh", then that Template will have locale
>> de_DE, time zone GMT+01 and outoutFormat (again, hypothetical) "HTML".
>> For "stats/foo.de.ftlh" the time zone will be UTC instead (because
>> when merging, the last setting value assignment wins).
>>
>> So that's it. Opinions, ideas?
>>
>
>
--
Thanks,
Daniel Dekany
------------------------------------------------------------------------------