You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@freemarker.apache.org by Daniel Dekany <da...@gmail.com> on 2023/11/02 17:51:03 UTC

Re: Feature Request

Kind of a niche use case... I would prefer avoiding much complexity and
backward compatibility burden for it. But, maybe it's actually already
doable. See my answer on Stack Overflow.

On Mon, Oct 30, 2023 at 6:57 PM Cavan Morris <ca...@softcoil.com>
wrote:

> Hello All,
> I am developing an internal content management system using freemarker
> templates and have run across a speed bump I've detailed in
> a stackoverflow question here:
>
> https://stackoverflow.com/questions/77390595/freemarker-how-to-get-unprocessed-content-of-custom-directive
>
> The long and short of it is that I would like to access the RAW,
> unprocessed content of the <#nested/> tag in my macro. I've looked through
> the source for a way to do this and haven't found one. If it exists
> please let me know!
>
> If not, I think it would be very useful to add this feature. Perhaps
> through a simple flag on the existing <#nested> tag? Perhaps with the
> addition of a new <#nested_raw> tag?
>
> Please let me know if you have any questions or if there is a way that I
> can help make this happen.
>
> Thank you!
>


-- 
Best regards,
Daniel Dekany

Re: Feature Request

Posted by Daniel Dekany <da...@gmail.com>.
I thought you wanted both to store the FTL source code of the nested
content  (i.e, the raw content), and then also *immediately* execute the
nested content. Because then, if you just execute the nested content as
normally, with TemplateDirectiveBody.render(Writer), then it will see the
same variables as the macro call nested content. If you need to execute the
stored nested content at a later point instead, then you can create
a Template from the captured FTL source code, and then use
Environment.include(Template).

Anyway, if it still won't work, can you show the TemplateDirectiveModel
implementation on SO? SO is much better for providing help, as people are
more likely to find the solution, and also answer can be updated/commented.

On Mon, Nov 6, 2023 at 6:31 PM Cavan Morris <ca...@softcoil.com>
wrote:

> Hey Daniel,
> I read the reply and tried creating a TemplateDirectiveModel to handle it
> as you suggested. It seemed cleaner than calling internal freemarker
> methods. The issue I ran up against was that when rendering the final
> output it would miss model attributes that were defined in the external
> template.
>
> So this would work:
>
> <@content name='help.h2'>
>     <#assign test='A test string'/>
>     <h2>This is a test: ${test}</h2>
> </...@content>
>
> But this would not:
>
> <#assign test='A test string'/>
> <@content name='help.h2'>
>     <h2>This is a test: ${test}</h2>
> </...@content>
>
> Using my original code I was able to solve that by defining the macro as
> below:
>
> <#macro content name>
>     <#local temlateSource = hd.processElement(name)/> <-- This calls
> the code I originally sent you to get the nested content as a String
> or pull it from the DB if available.
>     <#local inlineTemplate = temlateSource?interpret/>
>     <@inlineTemplate/>
> </#macro>
>
> I think because of that I'm going to have to stick with my original
> method. Unless I can replicate what macro is doing to get the full
> model from the environment.
>
>
> On Sat, Nov 4, 2023 at 5:01 AM Daniel Dekany <da...@gmail.com>
> wrote:
>
> > Have you read my answer on SO, i.e., using DirectiveCallPlace (public
> > API-s)? Did you try to go in that direction?
> >
> > On Thu, Nov 2, 2023 at 8:40 PM Cavan Morris <ca...@softcoil.com>
> > wrote:
> >
> > > Thank you Daniel.
> > > I was able to solve the problem in my case by creating my own util
> class
> > in
> > > the freemarker.core package inside my own project's source tree. This
> > > allowed me to access the package-private deprecated methods that I
> > believe
> > > are used for <#nested> handling.
> > >
> > > I plan to clean it up a bit and submit a PR once I have a moment away
> > from
> > > my current project. My thought is that even though this relies on
> > > deprecated methods, those methods are required for <#nested> support so
> > if
> > > they are refactored in the future there will have to be similar
> > > functionality supplied by the refactor. It should be simple to maintain
> > my
> > > PR in that case.
> > >
> > > Here is a preview of what I have now. At a minimum it will need some
> > > modifications to use the Freemarker logging system and I will need to
> > find
> > > an appropriate place for it in the existing source. Any thoughts
> > > appreciated.
> > >
> > > public static String getRawMacroContent(boolean trim) {
> > >     log.trace("Getting Raw Macro Content");
> > >
> > >     StringBuilder sb = new StringBuilder();
> > >
> > >     Environment environment = Environment.getCurrentEnvironment();
> > >     Macro.Context invokingMacroContext =
> > > environment.getCurrentMacroContext();
> > >     TemplateObject callPlace = invokingMacroContext.callPlace;
> > >     TemplateElement[] nestedContentBuffer = callPlace instanceof
> > > TemplateElement ? ((TemplateElement) callPlace).getChildBuffer() :
> > > null;
> > >     if (nestedContentBuffer != null) {
> > >         for (TemplateElement templateElement : nestedContentBuffer) {
> > >             log.trace("templateElement = {}", templateElement);
> > >             sb.append(templateElement.getSource());
> > >         }
> > >     }
> > >
> > >     if(trim) {
> > >         return sb.toString().trim();
> > >     } else {
> > >         return sb.toString();
> > >     }
> > > }
> > >
> > >
> > >
> > > On Thu, Nov 2, 2023 at 10:51 AM Daniel Dekany <daniel.dekany@gmail.com
> >
> > > wrote:
> > >
> > > > Kind of a niche use case... I would prefer avoiding much complexity
> and
> > > > backward compatibility burden for it. But, maybe it's actually
> already
> > > > doable. See my answer on Stack Overflow.
> > > >
> > > > On Mon, Oct 30, 2023 at 6:57 PM Cavan Morris <
> cavanmorris@softcoil.com
> > >
> > > > wrote:
> > > >
> > > > > Hello All,
> > > > > I am developing an internal content management system using
> > freemarker
> > > > > templates and have run across a speed bump I've detailed in
> > > > > a stackoverflow question here:
> > > > >
> > > > >
> > > >
> > >
> >
> https://stackoverflow.com/questions/77390595/freemarker-how-to-get-unprocessed-content-of-custom-directive
> > > > >
> > > > > The long and short of it is that I would like to access the RAW,
> > > > > unprocessed content of the <#nested/> tag in my macro. I've looked
> > > > through
> > > > > the source for a way to do this and haven't found one. If it exists
> > > > > please let me know!
> > > > >
> > > > > If not, I think it would be very useful to add this feature.
> Perhaps
> > > > > through a simple flag on the existing <#nested> tag? Perhaps with
> the
> > > > > addition of a new <#nested_raw> tag?
> > > > >
> > > > > Please let me know if you have any questions or if there is a way
> > that
> > > I
> > > > > can help make this happen.
> > > > >
> > > > > Thank you!
> > > > >
> > > >
> > > >
> > > > --
> > > > Best regards,
> > > > Daniel Dekany
> > > >
> > >
> >
> >
> > --
> > Best regards,
> > Daniel Dekany
> >
>


-- 
Best regards,
Daniel Dekany

Re: Feature Request

Posted by Cavan Morris <ca...@softcoil.com>.
Hey Daniel,
I read the reply and tried creating a TemplateDirectiveModel to handle it
as you suggested. It seemed cleaner than calling internal freemarker
methods. The issue I ran up against was that when rendering the final
output it would miss model attributes that were defined in the external
template.

So this would work:

<@content name='help.h2'>
    <#assign test='A test string'/>
    <h2>This is a test: ${test}</h2>
</...@content>

But this would not:

<#assign test='A test string'/>
<@content name='help.h2'>
    <h2>This is a test: ${test}</h2>
</...@content>

Using my original code I was able to solve that by defining the macro as below:

<#macro content name>
    <#local temlateSource = hd.processElement(name)/> <-- This calls
the code I originally sent you to get the nested content as a String
or pull it from the DB if available.
    <#local inlineTemplate = temlateSource?interpret/>
    <@inlineTemplate/>
</#macro>

I think because of that I'm going to have to stick with my original
method. Unless I can replicate what macro is doing to get the full
model from the environment.


On Sat, Nov 4, 2023 at 5:01 AM Daniel Dekany <da...@gmail.com>
wrote:

> Have you read my answer on SO, i.e., using DirectiveCallPlace (public
> API-s)? Did you try to go in that direction?
>
> On Thu, Nov 2, 2023 at 8:40 PM Cavan Morris <ca...@softcoil.com>
> wrote:
>
> > Thank you Daniel.
> > I was able to solve the problem in my case by creating my own util class
> in
> > the freemarker.core package inside my own project's source tree. This
> > allowed me to access the package-private deprecated methods that I
> believe
> > are used for <#nested> handling.
> >
> > I plan to clean it up a bit and submit a PR once I have a moment away
> from
> > my current project. My thought is that even though this relies on
> > deprecated methods, those methods are required for <#nested> support so
> if
> > they are refactored in the future there will have to be similar
> > functionality supplied by the refactor. It should be simple to maintain
> my
> > PR in that case.
> >
> > Here is a preview of what I have now. At a minimum it will need some
> > modifications to use the Freemarker logging system and I will need to
> find
> > an appropriate place for it in the existing source. Any thoughts
> > appreciated.
> >
> > public static String getRawMacroContent(boolean trim) {
> >     log.trace("Getting Raw Macro Content");
> >
> >     StringBuilder sb = new StringBuilder();
> >
> >     Environment environment = Environment.getCurrentEnvironment();
> >     Macro.Context invokingMacroContext =
> > environment.getCurrentMacroContext();
> >     TemplateObject callPlace = invokingMacroContext.callPlace;
> >     TemplateElement[] nestedContentBuffer = callPlace instanceof
> > TemplateElement ? ((TemplateElement) callPlace).getChildBuffer() :
> > null;
> >     if (nestedContentBuffer != null) {
> >         for (TemplateElement templateElement : nestedContentBuffer) {
> >             log.trace("templateElement = {}", templateElement);
> >             sb.append(templateElement.getSource());
> >         }
> >     }
> >
> >     if(trim) {
> >         return sb.toString().trim();
> >     } else {
> >         return sb.toString();
> >     }
> > }
> >
> >
> >
> > On Thu, Nov 2, 2023 at 10:51 AM Daniel Dekany <da...@gmail.com>
> > wrote:
> >
> > > Kind of a niche use case... I would prefer avoiding much complexity and
> > > backward compatibility burden for it. But, maybe it's actually already
> > > doable. See my answer on Stack Overflow.
> > >
> > > On Mon, Oct 30, 2023 at 6:57 PM Cavan Morris <cavanmorris@softcoil.com
> >
> > > wrote:
> > >
> > > > Hello All,
> > > > I am developing an internal content management system using
> freemarker
> > > > templates and have run across a speed bump I've detailed in
> > > > a stackoverflow question here:
> > > >
> > > >
> > >
> >
> https://stackoverflow.com/questions/77390595/freemarker-how-to-get-unprocessed-content-of-custom-directive
> > > >
> > > > The long and short of it is that I would like to access the RAW,
> > > > unprocessed content of the <#nested/> tag in my macro. I've looked
> > > through
> > > > the source for a way to do this and haven't found one. If it exists
> > > > please let me know!
> > > >
> > > > If not, I think it would be very useful to add this feature. Perhaps
> > > > through a simple flag on the existing <#nested> tag? Perhaps with the
> > > > addition of a new <#nested_raw> tag?
> > > >
> > > > Please let me know if you have any questions or if there is a way
> that
> > I
> > > > can help make this happen.
> > > >
> > > > Thank you!
> > > >
> > >
> > >
> > > --
> > > Best regards,
> > > Daniel Dekany
> > >
> >
>
>
> --
> Best regards,
> Daniel Dekany
>

Re: Feature Request

Posted by Daniel Dekany <da...@gmail.com>.
Have you read my answer on SO, i.e., using DirectiveCallPlace (public
API-s)? Did you try to go in that direction?

On Thu, Nov 2, 2023 at 8:40 PM Cavan Morris <ca...@softcoil.com>
wrote:

> Thank you Daniel.
> I was able to solve the problem in my case by creating my own util class in
> the freemarker.core package inside my own project's source tree. This
> allowed me to access the package-private deprecated methods that I believe
> are used for <#nested> handling.
>
> I plan to clean it up a bit and submit a PR once I have a moment away from
> my current project. My thought is that even though this relies on
> deprecated methods, those methods are required for <#nested> support so if
> they are refactored in the future there will have to be similar
> functionality supplied by the refactor. It should be simple to maintain my
> PR in that case.
>
> Here is a preview of what I have now. At a minimum it will need some
> modifications to use the Freemarker logging system and I will need to find
> an appropriate place for it in the existing source. Any thoughts
> appreciated.
>
> public static String getRawMacroContent(boolean trim) {
>     log.trace("Getting Raw Macro Content");
>
>     StringBuilder sb = new StringBuilder();
>
>     Environment environment = Environment.getCurrentEnvironment();
>     Macro.Context invokingMacroContext =
> environment.getCurrentMacroContext();
>     TemplateObject callPlace = invokingMacroContext.callPlace;
>     TemplateElement[] nestedContentBuffer = callPlace instanceof
> TemplateElement ? ((TemplateElement) callPlace).getChildBuffer() :
> null;
>     if (nestedContentBuffer != null) {
>         for (TemplateElement templateElement : nestedContentBuffer) {
>             log.trace("templateElement = {}", templateElement);
>             sb.append(templateElement.getSource());
>         }
>     }
>
>     if(trim) {
>         return sb.toString().trim();
>     } else {
>         return sb.toString();
>     }
> }
>
>
>
> On Thu, Nov 2, 2023 at 10:51 AM Daniel Dekany <da...@gmail.com>
> wrote:
>
> > Kind of a niche use case... I would prefer avoiding much complexity and
> > backward compatibility burden for it. But, maybe it's actually already
> > doable. See my answer on Stack Overflow.
> >
> > On Mon, Oct 30, 2023 at 6:57 PM Cavan Morris <ca...@softcoil.com>
> > wrote:
> >
> > > Hello All,
> > > I am developing an internal content management system using freemarker
> > > templates and have run across a speed bump I've detailed in
> > > a stackoverflow question here:
> > >
> > >
> >
> https://stackoverflow.com/questions/77390595/freemarker-how-to-get-unprocessed-content-of-custom-directive
> > >
> > > The long and short of it is that I would like to access the RAW,
> > > unprocessed content of the <#nested/> tag in my macro. I've looked
> > through
> > > the source for a way to do this and haven't found one. If it exists
> > > please let me know!
> > >
> > > If not, I think it would be very useful to add this feature. Perhaps
> > > through a simple flag on the existing <#nested> tag? Perhaps with the
> > > addition of a new <#nested_raw> tag?
> > >
> > > Please let me know if you have any questions or if there is a way that
> I
> > > can help make this happen.
> > >
> > > Thank you!
> > >
> >
> >
> > --
> > Best regards,
> > Daniel Dekany
> >
>


-- 
Best regards,
Daniel Dekany

Re: Feature Request

Posted by Cavan Morris <ca...@softcoil.com>.
Thank you Daniel.
I was able to solve the problem in my case by creating my own util class in
the freemarker.core package inside my own project's source tree. This
allowed me to access the package-private deprecated methods that I believe
are used for <#nested> handling.

I plan to clean it up a bit and submit a PR once I have a moment away from
my current project. My thought is that even though this relies on
deprecated methods, those methods are required for <#nested> support so if
they are refactored in the future there will have to be similar
functionality supplied by the refactor. It should be simple to maintain my
PR in that case.

Here is a preview of what I have now. At a minimum it will need some
modifications to use the Freemarker logging system and I will need to find
an appropriate place for it in the existing source. Any thoughts
appreciated.

public static String getRawMacroContent(boolean trim) {
    log.trace("Getting Raw Macro Content");

    StringBuilder sb = new StringBuilder();

    Environment environment = Environment.getCurrentEnvironment();
    Macro.Context invokingMacroContext = environment.getCurrentMacroContext();
    TemplateObject callPlace = invokingMacroContext.callPlace;
    TemplateElement[] nestedContentBuffer = callPlace instanceof
TemplateElement ? ((TemplateElement) callPlace).getChildBuffer() :
null;
    if (nestedContentBuffer != null) {
        for (TemplateElement templateElement : nestedContentBuffer) {
            log.trace("templateElement = {}", templateElement);
            sb.append(templateElement.getSource());
        }
    }

    if(trim) {
        return sb.toString().trim();
    } else {
        return sb.toString();
    }
}



On Thu, Nov 2, 2023 at 10:51 AM Daniel Dekany <da...@gmail.com>
wrote:

> Kind of a niche use case... I would prefer avoiding much complexity and
> backward compatibility burden for it. But, maybe it's actually already
> doable. See my answer on Stack Overflow.
>
> On Mon, Oct 30, 2023 at 6:57 PM Cavan Morris <ca...@softcoil.com>
> wrote:
>
> > Hello All,
> > I am developing an internal content management system using freemarker
> > templates and have run across a speed bump I've detailed in
> > a stackoverflow question here:
> >
> >
> https://stackoverflow.com/questions/77390595/freemarker-how-to-get-unprocessed-content-of-custom-directive
> >
> > The long and short of it is that I would like to access the RAW,
> > unprocessed content of the <#nested/> tag in my macro. I've looked
> through
> > the source for a way to do this and haven't found one. If it exists
> > please let me know!
> >
> > If not, I think it would be very useful to add this feature. Perhaps
> > through a simple flag on the existing <#nested> tag? Perhaps with the
> > addition of a new <#nested_raw> tag?
> >
> > Please let me know if you have any questions or if there is a way that I
> > can help make this happen.
> >
> > Thank you!
> >
>
>
> --
> Best regards,
> Daniel Dekany
>