pug-php / pug

Pug template engine for PHP
https://www.phug-lang.com
MIT License
387 stars 42 forks source link

cannot include pug files #217

Closed ivitaly closed 5 years ago

ivitaly commented 5 years ago

Hello,

I use latest version, but since legacy still use old extensions name like *.jade, I encountered an issue with the following abstract code after upgrade from 2.x.x version to 3.x.x:

$pug = new Pug(array('prettyprint' => true, 'basedir' => '/', 'extension' => '.jade'));

pug->render("

body
       include layouts/main.jade

");

Result:

Fatal error: Uncaught Phug\CompilerException: Failed to compile: Source file /home/protasov/public_html/sitepro/layouts/main.jade not found Paths: /, / Extensions: , .pug, .jade Line: 0 Offset: 0 in /home/protasov/vendor/phug/compiler/src/Phug/Compiler.php:855 Stack trace: #0 /home/protasov/vendor/phug/compiler/src/Phug/Compiler.php(870): Phug\Compiler->throwException('Source file /ho...', NULL, 0, NULL) #1 /home/protasov/vendor/phug/compiler/src/Phug/Compiler.php(335): Phug\Compiler->assert(false, 'Source file /ho...') #2 /home/protasov/vendor/phug/compiler/src/Phug/Compiler/NodeCompiler/ImportNodeCompiler.php(54): Phug\Compiler->resolve('/home/protasov/...', NULL) #3 /home/protasov/vendor/phug/compiler/src/Phug/Compiler.php(497): Phug\Compiler\NodeCompiler\ImportNodeCompiler->compileNode(Object(Phug\Parser\Node\ImportNode), Object(Phug\Formatter\Element\MarkupElement)) #4 /home/protasov/vendor/phug/compiler/src/Phug/Compiler/AbstractNodeCompiler.php(24): Phug\Compiler->compileNode(Object(Phug\Parser\Node\ImportNo in /home/protasov/vendor/phug/compiler/src/Phug/Compiler.php on line 855

I wondering, I was fine in old versions, I tried use absolute paths, relative path, stepping back and forward and it's not possible that compiler.php find that damn directory 'layouts' with main.jade.

I tried {$dir} insertion like that, basedir changes also doesn't help.

$dir = __DIR__ . "/layouts/";

$code = "
body
       include {$dir}/main.jade

";

pug->render($code);

And inline in php pug code works fine, but when I include something theres line 855 error. Where is I'm wrong?

Thanks!

kylekatarnls commented 5 years ago

Hello,

As you can see in your error message, it tries to load /home/protasov/public_html/sitepro/layouts/main.jade

If this path is not right with your hosting, change your 'basedir' to get the right depth (__DIR__, __DIR__ . '/.., etc.) but you should not inject if in the pug code, keep include layouts/main.jade in your templates so you can easily move those templates elsewhere later if needed.

ivitaly commented 5 years ago

the path is true, I tried set basedir to DIR and in pug code I tried include layouts/main.jade also include /layouts/main.jade

the pug is based in: /home/protasov/vendor/phug

the file main.jade is lying in /home/protasov/public_html/sitepro/layouts

code is excecuting from file util.php lying in

/home/protasov/public_html/sitepro

And the error peresves like:

Source file main.jade not found Paths: /home/protasov/public_html/sitepro/layouts, /home/protasov/public_html/sitepro/layouts

or here is my last iteration,

// this is util.php lying at /home/protasov/public_html/sitepro

require_once __DIR__ . '/../../vendor/autoload.php';

..

// basedir => __DIR__
body 
   include /layouts/main.jade

Fatal error: Uncaught Phug\CompilerException: Failed to compile: Source file /layouts/main.jade not found Paths: /home/protasov/public_html/sitepro, /home/protasov/public_html/sitepro Extensions: , .pug, .jade Line: 0 Offset: 0 in /home/protasov/vendor/phug/compiler/src/Phug/Compiler.php:855 Stack trace: #0 /home/protasov/vendor/phug/compiler/src/Phug/Compiler.php(870): Phug\Compiler->throwException('Source file /la...', NULL, 0, NULL) #1 /home/protasov/vendor/phug/compiler/src/Phug/Compiler.php(335): Phug\Compiler->assert(false, 'Source file /la...') #2 /home/protasov/vendor/phug/compiler/src/Phug/Compiler/NodeCompiler/ImportNodeCompiler.php(54): Phug\Compiler->resolve('/layouts/main.j...', NULL) #3 /home/protasov/vendor/phug/compiler/src/Phug/Compiler.php(497): Phug\Compiler\NodeCompiler\ImportNodeCompiler->compileNode(Object(Phug\Parser\Node\ImportNode), Object(Phug\Formatter\Element\MarkupElement)) #4 /home/protasov/vendor/phug/compiler/src/Phug/Compiler/AbstractNodeCompiler.php(24): Phug\Compiler->compileNode( in /home/protasov/vendor/phug/compiler/src/Phug/Compiler.php on line 855

with or without trailing slash depends on do I add it to base dir or after include directive, what else I missing?

ivitaly commented 5 years ago

solution next:

at php file in initial section

basedir set to (dot) same dir => '.'

in code procedures where I would call something like

echo $pug->render("$string_with_pug_code");`

I call ch dir:

chdir(__DIR__.'/layouts');
//for short direct name of layout that need to include
$string_with_pug_code = "
body
     include some_layout.jade
     section
          include some_other.jade
";

then somewhere I need a parametric inclusion, based on string injection, so I use next hack

$layoyt_for_section = " /* some random (code generated) file name to include like header.pug etc... */ ";

$layoyt_for_section = getcwd() . '/' . $layoyt_for_section ;

// go insert it somewhere

$to_render = "
section
        include {$layoyt_for_section}
";

echo $pug->render($to_render);

takes me tons of time to figure out that kinda workarounds.

Seems like base dir doesn't works with DIR and anything excep that dot

after dot, we can use relative patches in direct code, and absolute in injected strings.

kylekatarnls commented 5 years ago

I see, it's right, if you use ->renderFile('some_template.jade') then inside some_template.jade relative path are from the template file, if you run ->render($to_render) with dynamic code, relative path are from the current script directory (chdir). But in both case, you can use absolute path called from basedir.

ivitaly commented 5 years ago

I see, it's right, if you use ->renderFile('some_template.jade') then inside some_template.jade relative path are from the template file, if you run ->render($to_render) with dynamic code, relative path are from the current script directory (chdir). But in both case, you can use absolute path called from basedir.

The problem I meet is that compiler when using basedir seems to do internal conversions, somewhy not working same as working separatedly with chdir, If I pass with dynamic code same path from chdir instead to basedir, compiler doesn't see path, but all correct and stays same in both cases, (maybe it's expecting physical one with drive name etc) and with chdir works fine in 1. (semi absolute) for static file names, and 2. absolute for dynamic names both injected in dynamic code.

In my solution I use render function as runtime dynamic code generator for all html layout, and load few not changable templates from files, but through include in pug syntax at this code.