GithubHelp home page GithubHelp logo

thymeleaf / thymeleaf Goto Github PK

View Code? Open in Web Editor NEW
2.7K 123.0 488.0 44.19 MB

Thymeleaf is a modern server-side Java template engine for both web and standalone environments.

Home Page: http://www.thymeleaf.org

License: Apache License 2.0

Java 89.40% HTML 10.60%
java template-engine server-side-rendering thymeleaf thymeleaf-template-engine html xml javascript

thymeleaf's Introduction

thymeleaf's People

Contributors

anschnapp avatar chkluwe avatar cm-rudolph avatar damianfekete avatar danielfernandez avatar dtrunk90 avatar good92 avatar jkuipers avatar jlacar avatar jmiguelsamper avatar kreuzman avatar lightszentip avatar nithril avatar ogawa-takeshi avatar opensource21 avatar pioto avatar rstoyanchev avatar rtack avatar rustamm avatar rwinch avatar rynkowsw avatar seanhinkley avatar sorayasl avatar strpbrk avatar sunil0791 avatar ultraq avatar vpop avatar yoshikawaa avatar yukihigasi avatar zreed avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

thymeleaf's Issues

Possibility to define custom global formatter.

It would be nice to have opportunity to define global formatter according to Java type. For example define your own formatter for every java.util.Date that you don't have to use #dates.format for every Date.

Replacements in conditional comments

I'm using a conditional comment to load a javascript file only when running within IE7 or earlier.
I'm using the following code for that

<!--[if lte IE 7]>
<script type="text/javascript" src="@{/resources/externals/navigation/jquery.dropdown.js}"></script>
<![endif]-->

Unfortunately the resource link is not resolved, due to the content not beeing part of the actual document but just within a comment.
Is there any change to make thymeleaf handle the replacement anyways?

Compare string with enum.

Ability to compare string with enum. When you try to compare in if statement (th:if="${day == 'MONDAY'}") exception is thrown - org.springframework.expression.spel.SpelEvaluationException: EL1007E:(pos 22): Field or property 'MONDAY' cannot be found on null. You must use cast enum to string (th:if="${day + '' == 'MONDAY'}") in not nice way. So explicit or implicit casting to string would be nice to have.

Support XSD Schema and XML Namespaces

From: http://sourceforge.net/tracker/?func=detail&aid=3406107&group_id=509826&atid=2072662

It is common for XML-based component frameworks to use XSD schemas for validation (and code-assistance), along with the schema's target namespace to identify elements and attributes over which that namespace applies. Accordingly, it would be useful to register dialects that are bound the namespace or schemaLocation, and have the actual prefix used only as a pseudonym for that namespace, rather than the differentiator itself.

Compelling reasons include:
a) The prefix is not always known upfront when parsing XML. Consider XML generation for webservice invocations; the prefix is often generated, e.g. ns0, ns1, ... nsN. The schema however will be known upfront.
b) A page author may choose the prefix per-page, rather than having the prefix hard-coded (avoiding ns-collisions when multiple dialects are used within that page)
c) Different dialects per schema version. If the dialect is registered to the versioned schema location (http://x.y.z/schemas/my-schema-1.0.xsd), a smooth migration can be offered when that schema evolves to version 2.0, by having dialects registered for that version specifically.

org.xml.sax.SAXException: Scanner State 24 not Recognized

After upgrading to Thymeleaf 2.0.10 from 2.0.8 I started getting this exception, which was not very clear, it turns out however that it was caused when my layout file didn't start directly with . If I have a space, or a new line before that, then it would result in this. Now, I know HTML dictates that the document should start with <!DOCTYPE..., so why this worked before I don't know, but in any case I think providing a better error message to the end user would be very helpful. Something along the lines of "It was not possible to parse the document, does it start with <!DOCTYPE?" or similar.

org.xml.sax.SAXException: Scanner State 24 not Recognized
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1250)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:568)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl.parse(SAXParserImpl.java:302)
at org.thymeleaf.templateparser.xmlsax.AbstractNonValidatingSAXTemplateParser.doParse(AbstractNonValidatingSAXTemplateParser.java:183)
at org.thymeleaf.templateparser.xmlsax.AbstractNonValidatingSAXTemplateParser.parseTemplateUsingPool(AbstractNonValidatingSAXTemplateParser.java:115)
at org.thymeleaf.templateparser.xmlsax.AbstractNonValidatingSAXTemplateParser.parseTemplate(AbstractNonValidatingSAXTemplateParser.java:96)
at org.thymeleaf.TemplateRepository.getTemplate(TemplateRepository.java:276)
at org.thymeleaf.fragment.FragmentAndTarget.extractFragment(FragmentAndTarget.java:76)
at org.thymeleaf.processor.attr.AbstractFragmentHandlingAttrProcessor.processAttribute(AbstractFragmentHandlingAttrProcessor.java:71)
at org.thymeleaf.processor.attr.AbstractAttrProcessor.doProcess(AbstractAttrProcessor.java:74)
at org.thymeleaf.processor.AbstractProcessor.process(AbstractProcessor.java:212)
at org.thymeleaf.dom.Node.applyNextProcessor(Node.java:809)
at org.thymeleaf.dom.Node.processNode(Node.java:771)
at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
at org.thymeleaf.dom.Node.processNode(Node.java:789)
at org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
at org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
at org.thymeleaf.dom.Node.processNode(Node.java:789)
at org.thymeleaf.dom.Document.process(Document.java:90)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1233)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1145)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1090)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1003)
at org.thymeleaf.TemplateEngine.process(TemplateEngine.java:977)
at XXX.http.results.RenderTemplate.getOutputData(RenderTemplate.java:79)
at XXX.http.results.Response.render(Response.java:70)
at XXX.http.WebserverInvoker.writeDynamicMethod(WebserverInvoker.java:270)
at XXX.http.WebserverInvoker.invokeMethod(WebserverInvoker.java:163)
at XXX.http.WebserverInvoker.invoke(WebserverInvoker.java:106)
at XXX.http.WebserverHandler.messageReceived(WebserverHandler.java:81)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296)
at org.jboss.netty.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:351)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.callDecode(ReplayingDecoder.java:552)
at org.jboss.netty.handler.codec.replay.ReplayingDecoder.messageReceived(ReplayingDecoder.java:431)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296)
at org.jboss.netty.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:354)
at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:336)
at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:209)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:296)
at org.jboss.netty.handler.codec.frame.FrameDecoder.unfoldAndFireMessageReceived(FrameDecoder.java:354)
at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:336)
at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:209)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:94)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.processSelectedKeys(AbstractNioWorker.java:372)
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:246)
at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:38)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)

Boolean literals

Currently, boolean literals in Standard expressions must be computed as text literals (i.e. outside OGNL or SpringEL expressions).

Adding boolean literals to the Standard expression language would allow expressions like:

<div th:if="${user.isAdmin()} == false"> ...

Create dialect for the execution of SQL sentences

A new "extras" dialect could be created for executing SQL sentences directly from the templates, à la JSP's "sql" taglib.

This is weird and goes against all rules of good software architecture, but could be handy for some users (or for extremely-easy prototyping)

Create 'decoupled' template modes

Decoupled template modes would consist of having two files for each template:

  • One with the real HTML template, specifying id attributes for those elements that will be added processors.
  • One with the attributes to be added (those that apply processors like th:*), referencing the id of the elements where they should be added.

Syntax

Possible syntax for the instructions template file could be something like:

[productIter th:each="product : ${products}"]

where productIter would be the id of an element in the template file.

Include fragment in the same template

Add the ability to define a fragment in a page and use the fragment later in the same page that defines it.
Useful to reuse the same pagination toolbar or for representing trees or data structures which depth is not known beforehand.

unescaped inline /*[[${...}]]*/ for scripts/css

At some cases when dealing with javascript, an unescaped string has to be used, what cannot achieved whith the standard
/[[ ... ]]/ syntax.

some examples:

var wordCloudData = /*[[${jsonData}]]*/;
$('body').css('background-image', /*[[${background_url}]]*/ );

in both cases the string should not be escaped. maybe it should be some /[[U${background_url}]]/ syntax invented for getting unescaped values - the same also with the leading and closing single quotes?

there is also a forum entry about this:
http://forum.thymeleaf.org/Spring-Javascript-and-escaped-JSON-td4024739.html

Cheers!
watz

Inline javascript removes javascript code up to 1st ;

The inline javascript removes javascript code up to 1st ;

Example;

messages.push( /*[[#{  OGNL EXPR }]]*/ );

Will output:

messages.push( 'AN STR' ;

Note that Thymeleaf removed ) that result in a not valid javascript expression.

Regards

Enrique

Avoid jsessionid in URLs when indexed by GoogleBot

Thymeleaf currently adds the "jsessionid" fragment to any context-relative or server-relative URLs when a user session is active in the server (request.getSession(false) is not null).

Although most public sites will not be creating sessions for non-authenticated users (and thymeleaf allows this), it might happen that some sites do, and therefore ;jsessionid=xxxxx fragments would be added to the Google index, which is a security risk.

A purpose-specific fix for this would be checking, when adding the ;jsessionid part, that the "User-Agent" header does not include GoogleBot.

Note that this could be nevertheless a problem for session-creating public websites, because Google (which is cookie-less) could be creating a new session for every page it indexes.

Server relative links without Servlet API

Hello,

I am currently working on a project which will use Thymeleaf 2.0 as its template engine. It will not use the servlet API for various reasons, but since it needs a web interface, Thymeleaf will work as its template engine.

This ofcourse means that I will need server relative links, as in /component/method/thing?id=5. I don't want to use absolute urls, because this application can be run on different IPs, domains, and such. But in common, they all will run from the root path. http:///.

I have modified Thymeleaf to make this behaviour possible, and I would like to share how I did that, and hopefully it can make it into the full release. I'll make a pull request soon.

Finally, good work on the template framework, it works really good, and it has good markup!

Create servlet for standalone execution of templates

A specific servlet could enable the standalone execution of thymeleaf templates (à la JSP) for those users that do not want to have any controller-side frameworks. Velocity has something similar to this...

Add line number to nodes of all types

Currently, only Element nodes are added the line number during parsing.

In some situations, it could be possible to specify line number for all types of nodes, so that exception messages could be more precise when inlining or treating other (non-element) kinds of nodes with specific processors.

Add a null-safe #strings.asString() function

Both OGNL and String EL allow the execution of expressions like ${myVar.toString()}, but these will raise an error if myVar is null.

A new asString() function could be added to the #strings utility object to avoid this.

Javascript inlining problem - Multidimensional arrays

<script type="text/javascript" th:inline="javascript">
    /*<![CDATA[*/
        var appId = /*[[${app.id.toString()}]]*/ 'dummy-app-id';  
        var currentThemeId = 1;
        var currentColorId = 1;
        var colorLists = [["#A3AFDE","#DEFAB1","#3C5F1B"]];
    /*]]>*/
</script>

Inlining the javascript causes colorLists to become "#A3AFDE","#DEFAB1","#3C5F1B".
Can I somehow prevent this behavior without moving the colorLists variable to another script block?

Should the Text nodes be escaped when created?

Currently, Text nodes in the Thymeleaf DOM determine whether they should be XML-escaped or not at creation time (this is, when they are instanced).

Isn't it more logical to do this during node writing instead of creation? This will depend on:

  1. What is the reason for a Text node not being XML-escaped? (there will be MacroNodes now...)
  2. Does this have to be with DOM-based parsing (maybe Text nodes from the Standard DOM are already escaped and this arquitecture allows the DOMTranslator not to have to unescape back the nodes...)

Remove initialize() steps in extension points

Many artifacts in extension points (like template resolvers, message resolvers, etc) have initialize() methods which disallow modifications once called.

These initialize() methods often are part of the main interface for the extension point, which means that it is the responsibility of the engine to initialize those components, instead of the responsibility of the component itself.

These methods should be removed from the main extension-point interfaces, and moved to an optional interface (like for example Initializable) which would allow the implementation of the extension point select whether it wants to be automatically initialized or not.

Also, think about the need for the current implementations to be initializable, and especially to forbid any read (call to a get*() method) before initialization takes place.

Add MacroNode nodes to DOM

A new DOM node type called "MacroNode" would allow thymeleaf to create nodes that would render text or markup without caring at all about things like XML-escaping or such.

A MacroNode would be directly rendered to output. So it could be used for: 1. Markup insertions from external sources and 2. Precomputed markup caches.

Update docs and example apps

Update:

  • #numbers.sequence(to,from,step)
  • #strings.escapeXml(...) [check name]
  • (in extension articles): use "additionalDialects"

Update:

  • sayhello: use "additionalDialects"

Parameter with more than one value

Add support to create an URL that contains one parameter with more than one value

The goal is to process the parameter with String[] ServletRequest.getParameterValues(java.lang.String)

Examples:

@{/getsomething(p1='value1',p1='value2',p1='value3')}
@{
/getsomething(p1=${p1Values})} (here where p1Values is a model attribute with an array or list of values.)

Support query parameters with special characters

I have a use case where I need to be able to create a URL with [] in the parameter name (i.e. /context/url?a[0]=b). However, when I create a link like:

<a href="#" th:href="@{/url(a[0]='b')}">List</a>

I get an Exception

org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression: "@{/url(a[0]='b')}" (home:9)
    org.thymeleaf.standard.expression.StandardExpressionParser.parseExpression(StandardExpressionParser.java:128)
    org.thymeleaf.standard.expression.StandardExpressionParser.parseExpression(StandardExpressionParser.java:70)
    org.thymeleaf.standard.expression.StandardExpressionProcessor.parseExpression(StandardExpressionProcessor.java:53)
    org.thymeleaf.standard.expression.StandardExpressionProcessor.processExpression(StandardExpressionProcessor.java:91)
    org.thymeleaf.standard.processor.attr.AbstractStandardSingleAttributeModifierAttrProcessor.getTargetAttributeValue(AbstractStandardSingleAttributeModifierAttrProcessor.java:59)
    org.thymeleaf.processor.attr.AbstractSingleAttributeModifierAttrProcessor.getModifiedAttributeValues(AbstractSingleAttributeModifierAttrProcessor.java:59)
    org.thymeleaf.processor.attr.AbstractAttributeModifierAttrProcessor.processAttribute(AbstractAttributeModifierAttrProcessor.java:61)
    org.thymeleaf.processor.attr.AbstractAttrProcessor.doProcess(AbstractAttrProcessor.java:74)
    org.thymeleaf.processor.AbstractProcessor.process(AbstractProcessor.java:212)
    org.thymeleaf.dom.Node.applyNextProcessor(Node.java:805)
    org.thymeleaf.dom.Node.processNode(Node.java:767)
    org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
    org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
    org.thymeleaf.dom.Node.processNode(Node.java:785)
    org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
    org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
    org.thymeleaf.dom.Node.processNode(Node.java:785)
    org.thymeleaf.dom.NestableNode.computeNextChild(NestableNode.java:626)
    org.thymeleaf.dom.NestableNode.doAdditionalProcess(NestableNode.java:608)
    org.thymeleaf.dom.Node.processNode(Node.java:785)
    org.thymeleaf.dom.Document.process(Document.java:90)
    org.thymeleaf.TemplateEngine.process(TemplateEngine.java:1029)
    org.thymeleaf.TemplateEngine.process(TemplateEngine.java:978)
    org.thymeleaf.spring3.view.ThymeleafView.render(ThymeleafView.java:460)
    org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1157)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:927)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

I asked on the forum if there were any recommended solutions to this problem and a work around is that I can do something like this:

<a href="#" th:href="@{/url} + '?a[0]=b'">List</a>

This works, but it feels like a workaround for two reasons:

  1. It appears there is no way to escape the [ bracket. There should be some way to treat a[0] as a literal.
  2. It requires manual escaping of the query parameters. For example if b were replaced with a ? I would need to manually URL encode the ? for it to work.

It would be nice to be able to use the standard URL mechanism even if special characters were used in the parameter names or values. I'm not particular on the syntax on how this would be supported, but one way of representing this might be something like:

<a href="#" th:href="@{/url('a[0]'='?')}">List</a>

Create OSGi bundle

Currently the MANIFEST.MF is pretty empty, would be nice if there could be some headers (imports etc.) be added so that it can be used as an OSGI bundle. This goes for the subprojects as well (spring integration for instance).

Create an extra for JSP integration

Basing on the techniques for variable sharing between JSPs and Thymeleaf templates developed for the Tiles2 integration module, another extra module could be developed for direct JSP-Thymeleaf integration.

This could have processors like:

<div jsp:include="/WEB-INF/jsps/footer.jsp">...</div>

And also, a JSP TagLib could be developed for including a Thymeleaf template into a JSP template:

<th:include fragment="myTemplate :: myFragment"/>

StandardMessageResolver should default to included files' properties

In the standard message resolution mechanism, properties are not explored for the included fragments, and they are only for the including template.

This might cause the repetition of properties in messages files between the included and including templates.

What could be done is to (optionally) add the Node itself to the message resolution request, so that if the Node contains information about the template where it comes from this information could be used for defaulting. That way, if a message key is not found in the including template, the included one will be tested before returning a defaulted string.

Study the usage of the thread context classloader

According to this: http://forums.gradle.org/gradle/topics/gradle_classloader_problems_with_jetty_plugin also reported here http://forum.thymeleaf.org/Thymyleaf-Gradle-Jetty-td4024844.html there is a problem when using Gradle+Jetty for starting a Thymeleaf application.

Study the possibility of modifying that "catch" to include NoClassDefFound, and also check what happens if the current thread's classloader is not present (it happened in Jasypt before!)

On upgrade to 2.0.10, template output contains a <THYMELEAF_ROOT> element

On output, my templates begin with:

<!DOCTYPE html>
<HTML><head></head><BODY><THYMELEAF_ROOT>

after upgrading Thymeleaf from 2.0.8 to 2.0.10.

If I revert to 2.0.8, the templates return to their normal output:

<!DOCTYPE html>
<html lang="en"><head>
    (header scripts and tags here)
</head><body>

Add a "dirty" flag to nodes to enable second-pass processing

In order to allow a second processing of already-processed elements (for example, when a processor modifies an already processed element and add some th:* attributes to it), a "dirty" boolean flag could be added to the Node class.

When set to true, this flag should be automatically propagated towards the root of the node tree up to the Document node, so that after the first pass of processing we can know whether a second pass has to be executed just by checking the root node (instead of performing a full-depth search).

This node could be automatically set when an already-processed node is changed (change in children or attributes).

Also, it should be noted that in order for this to work OK, we should avoid that already-executed processors remain in the list of to-be-processed processors for their respective nodes (so that they are not executed again and --potentially-- fail on the non-existence of the attribute). See http://forum.thymeleaf.org/Adding-elements-with-th-annotation-in-custom-processor-td4024907.html

Add JavaScript escaping method to #strings

Add new methods to the #strings utility objects (therefore to the "Strings" utility class) to include methods for manually escaping and unescaping text both to-from JavaScript.

Use array instead of Stack in SAXParser?

The SAXParser (DocumentHandler implementation) currently uses a Stack object for pushing the read markup elements.

Maybe performance in no-cache scenarios could be improved by using an array instead of this Stack?

Add "additionalDialects" method to TemplateEngine

In order to make it easier to add dialects to a template engine besides the Standard one, these methods would allow a more elegant configuration without the need to also specify the Standar Dialect:

addAdditionalDialect(IDialect)
setAdditionalDialects(Set<IDialect>)

Base main actors in interface + abstract imple

Review main actors in the core to make sure they are structured as an interface (I*) plus an abstract implementation (which allows to easily implement and make implementations less affected by change.

Modify template modes amd add "Text" template mode

In order to being able to process non-HTML email templates or maybe some other kinds of templates, it could be useful to add a "Text" template mode that:

  • Considers the entire template to be a Text node.
  • Applies text inlining by default.

Should utexts be rendered as macros instead of parsing them?

Now Macro nodes exist (from 2.0.9), maybe they would be a better representation for utext. What would we be losing? Does parsing a utext add something useful? Do we need to access those nodes afterwards?

If not a Macro... what about a non-escaping Text node?

CSS inlining

Some kind of CSS inlining could be added in the same way as today's JavaScript inlining.

This would allow the addition of expression-dependent in-template styles.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.