Git Product home page Git Product logo

Comments (15)

ryan-mahoney avatar ryan-mahoney commented on August 25, 2024

Hi @Biont I have achieved something similar (I think) to what you are describing by compiling what I call my "layout" which is like an outer template and the "partial" independently such that the output of the compiled partial is proved as input to the compiled layout.

Does this make sense?

Basically, there is some glue code that compiles all of the partials individually and stores there result into an array that is then passed to the layout.

from lightncandy.

Biont avatar Biont commented on August 25, 2024

Hey @virtuecenter thanks for your reply.

I am not sure if I understand the part about the outer template, but you are basically suggesting precompiling everything and then just rendering the stored result.

This is probably a wise idea even if it's just for performance, and might be worth a shot to see if it solves my problem. (Well you are saying it does, so that's great).

But there's a catch: I actually do use runtime compilation at another occasion.

I wrote a "compile" helper which is used to enable handlebars when creating content (think bbCode or WordPress shortcodes). So I'll always run all text content through this helper to catch any templating going on in there.

This is of course a lot less critical to me than my custom partials, so I'll definetely give your workaround a try. However, the main problem remains

from lightncandy.

ryan-mahoney avatar ryan-mahoney commented on August 25, 2024

OK, I have a crazy idea for you -- but I think it would work.

Basically, in your compile-at-run helper, do a check on the string, to see if it has any handlebar variables. If so, make an instance of the other php handlebars engine and interpret the content that way. The other one is not as fast as this one, and doesn't support caching... but it is good for dynamic compilation... because that is basically all it does.

https://github.com/XaminProject/handlebars.php

from lightncandy.

Biont avatar Biont commented on August 25, 2024

That sure sounds crazy :D
I'm actually coming from the XaminProject implementation, but wanted to switch since this one looks so much easier to use. Plus, I've had problems getting helpers to work at all and did could not see where my problem was.

Well, I'm going to have another look at it, I guess. Thank you

from lightncandy.

ryan-mahoney avatar ryan-mahoney commented on August 25, 2024

I'm also coming from Xamin

This might help:

https://github.com/Opine-Org/Semantic-CM/blob/master/src/Manager/public/helpers/DocumentFormLeft.php

from lightncandy.

zordius avatar zordius commented on August 25, 2024

Hello all:

The short story: runtime partial (and recursive partial) will be supported in 1 week.

The long story is:

Runtime partial is my next plan , to be enhance lightncandy and make it more mustache compatible. And, I already open an issue to track it in #64.

Lightncandy try to pass mustache spec ( https://github.com/mustache/spec ) these days and already done some milestone includes: #66 , #67 , #72 , #73 . After these enhancement , lightncandy still good performance by default , and cost a little bit more to include more standard by specific flags.

Runtime partial will be supported by a new flag FLAG_RUNTIMEPARTIAL , this will turn all partials be compiled more like helpers , which also support recursive execution. I was plan to do this today when I done some mustache related issues yesterday. :)

from lightncandy.

Biont avatar Biont commented on August 25, 2024

This is fantastic news, thank you very much!!

from lightncandy.

zordius avatar zordius commented on August 25, 2024
  • After #87 , you may overwrite LightnCandy:: resolvePartial() to provide custom partial naming logic.
  • Now we have flag FLAG_RUNTIMEPARTIAL , which execute partial in more dynamic way.

And, for your partial helper , I think change the echo to return may fix your problem:

$helpers = array(
    'partial'     => function ( $name, $context ) {
        $template = file_get_contents( TPL_DIR . '/' . $name . '.html' );
        $php = LightnCandy::compile( $template );
        $renderer = LightnCandy::prepare( $php );
        return $renderer( $context[ 'data' ][ 'root' ] );
    });

But, this helper do runtime compile , it is not a good practice and do not enjoy the performance benefit of lightncandy.

Anyway, if you have any other requirement , you may open another issue, thanks.

from lightncandy.

Biont avatar Biont commented on August 25, 2024

Hey,
I spent some more time with the PHP side of things and ultimately got back to this issue.
First, thanks again for this great tool and your astonishing dedication to it. And yes, returning instead of echoing does work better indeed :)

However, I need to come back to the core issue of my first post: How do I compile templates from within helpers? I realize that much has changed with regards to compilation of partials, but my handlebars-JS templates are more or less set in stone, so I need this to work with helpers.

With the helpers array being part of the very options that boot up LightnCandy, I fear that this will prove to be an impossible task, unless the API is changed around a bit..

If I just call

LightnCandy::compile( $template );

in my custom helper, I will basically reset LightnCandy to default settings as soon as the Helper runs, right? No specific options are passed, so it will apply the default ones.
I would need to add the whole options array (including the helpers) again while I am declaring it.
Otherwise I'm missing all my settings and helpers - and even worse: I just deleted them globally

I think all that's really needed is to move the initialization logic out of the compile method, like I proposed in the OP

Bootstrap LightnCandy with

LightnCandy::init( $options);

and then LightnCandy::compile( $template ); would work the same way globally. I believe this is a simple fix. What do you think?

from lightncandy.

zordius avatar zordius commented on August 25, 2024

Well, this is what I think:

Way 1:

  1. store your init/config some where
  2. create your myCompile($template)
  3. inside your myCompile , get the stored init/config, mix, anything, then call compile($template, $options)
  • This can be another extended class

Way 2:
1.extend lightncandy
2.override buildContext() , put your init/config there
3. and yes, you can create your own .init()

Does these 2 way are good for you?

from lightncandy.

zordius avatar zordius commented on August 25, 2024

I reviewed your question , I found the question is about 'how to keep original options be passed into another compile()' , so it is another question.

Maybe we can just do in this way:

  1. extend lightncandy
  2. override buildContext() , make it store original options inside the $context
  3. then when your helper wanna make another compile() , just take the original config from context , then done!

from lightncandy.

zordius avatar zordius commented on August 25, 2024

Hmmm......I missed something between step 2 to step 3. We should put something not only into $context, but also into compiled template. Look into composePHPRender() https://github.com/zordius/lightncandy/blob/master/src/lightncandy.php#L251 I think maybe I can add third param into it to make it extendable , and the third param can be set into render context.

from lightncandy.

Biont avatar Biont commented on August 25, 2024

I guess your suggestions will work, thanks. I'll whip something up after work today.
At a glance, I cannot see the problem with composePHPRenderer(). If I change things around so that the original options aren't touched when called from a helper, the $context stays the same and composePHPRenderer() never touches anything but the $context array. What am I missing?

from lightncandy.

zordius avatar zordius commented on August 25, 2024

composePHPRender() return the final render function, and then the render function can not see compile() context, it only see the render context and it already hardcoded inside composePHPRender() . So, add 3rd param is a chance to extend the render context inside the render function.

from lightncandy.

Biont avatar Biont commented on August 25, 2024

Alright, Here's what I have come up with:

class CustomCandy extends LightnCandy {

    /**
     * @var array<string,array|string|integer> $context Current context
     */
    protected static $context;

    /**
     * @var bool
     */
    protected static $has_inited = FALSE;

    /**
     * Set global options for LightnCandy
     *
     * @param array $options
     */
    public static function init( $options = array( 'flags' => self::FLAG_BESTPERFORMANCE ) ) {

        self::$context    = static::buildContext( $options );
        self::$has_inited = TRUE;

    }

    /**
     * Compile handlebars template into PHP code.
     *
     * @param string $template handlebars template string
     * @param array  $options  LightnCandy compile time and run time options, default is array('flags' =>
     *                         LightnCandy::FLAG_BESTPERFORMANCE)
     *
     * @return string|false Compiled PHP code when successed. If error happened and compile failed, return false.
     */
    public static function compile( $template, $options = NULL ) {

        if ( ! is_null( $options ) || ! self::$has_inited ) {
            if ( is_null( $options ) ) {
                $options = array( 'flags' => self::FLAG_BESTPERFORMANCE );
            }
            self::$context = static::buildContext( $options );

            if ( ! self::$has_inited ) {
                self::$has_inited = TRUE;
            }

        }

        if ( static::handleError( $context ) ) {
            return FALSE;
        }

        // Strip extended comments
        $template = preg_replace( static::EXTENDED_COMMENT_SEARCH, '{{!*}}', $template );

        // Do first time scan to find out used feature, detect template error.
        static::setupToken( self::$context );
        static::verifyTemplate( self::$context, $template );

        if ( static::handleError( self::$context ) ) {
            return FALSE;
        }

        // Do PHP code generation.
        static::setupToken( $context );
        $code = static::compileTemplate( self::$context, static::escapeTemplate( $template ) );

        // return false when fatal error
        if ( static::handleError( self::$context ) ) {
            return FALSE;
        }

        // Or, return full PHP render codes as string
        return static::composePHPRender( self::$context, $code );
    }

}

It seems to work so far. Note that the init() method isn't really needed, I have just made the $options parameter of compile() fully optional and added a static handle to the $context array.

I did not want to break the way LightnCandy usually works, so there's still the possibility to initialize it using just the compile() method, and using the default settings of none were passed.

That's why I added the $has_inited flag and the somewhat spaghettii-esque part at the beginning of compile()

Maybe someone will find this useful

from lightncandy.

Related Issues (20)

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.