Giter Club home page Giter Club logo

pug's Introduction

Pug-php

Latest Stable Version Monthly Downloads License StyleCI Test Coverage Code Climate Dependencies

Pug-php adds inline PHP scripting support to the Pug template compiler. Since version 3, it uses Phug, a very customizable Pug template engine made by the tale-pug and pug-php developers as the new PHP Pug engine reference.

Install

First you need composer if you haven't yet: https://getcomposer.org/download/

Then run:

composer require pug-php/pug

Pug in your favorite framework

Phalcon: https://github.com/pug-php/pug-phalcon

Symfony: https://github.com/pug-php/pug-symfony

Laravel: https://github.com/BKWLD/laravel-pug

CodeIgniter: https://github.com/pug-php/ci-pug-engine

Yii 2: https://github.com/rmrevin/yii2-pug

Slim 3: https://github.com/MarcelloDuarte/pug-slim

Zend Expressive: https://github.com/kpicaza/infw-pug

Use

<?php

include 'vendor/autoload.php';

$pug = new Pug([
    // here you can set options
]);

$pug->displayFile('my-pug-template.pug');

Since pug-php 3.1.2, you no longer need to import the class with use Pug\Pug; as we provide an alias.

Main methods are render, renderFile, compile, compileFile, display, displayFile and setOption, see the complete documentation here: phug-lang.com.

You can also use the facade to call methods statically:

<?php

use Pug\Facade as PugFacade;

include 'vendor/autoload.php';

$html = PugFacade::renderFile('my-pug-template.pug');

Pug options

Pug options should be passed to the constructor

$pug = new Pug([
    'pretty' => true,
    'cache' => 'pathto/writable/cachefolder/',
]);

Supports for local variables

$pug = new Pug();
$output = $pug->renderFile('file.pug', [
    'title' => 'Hello World',
]);

New in pug-php 3

pug-php 3 is now aligned on pugjs 2, it aims to be a perfect implementation of the JS project. That's why there are breaking changes in this new version.

See the changelog to know what's new

See the migration guide if you want to upgrade from pug-php 2 to 3

Support for custom filters

Filters must be callable: It can be a class that implements the __invoke() method or an anonymous function.

$pug->filter('escaped', 'My\Callable\Class');

// or

$pug->filter('escaped', function($node, $compiler) {
    foreach ($node->block->nodes as $line) {
        $output[] = $compiler->interpolate($line->value);
    }

    return htmlentities(implode("\n", $output));
});

Built-in filters

  • :css
  • :php
  • :javascript
  • :escaped
  • :cdata

Install other filters with composer

http://pug-filters.selfbuild.fr/

Publish your own filter

https://github.com/pug-php/pug-filter-base#readme

Support for custom keywords

You can add custom keywords, here are some examples:

Anonymous function:

$pug->addKeyword('range', function ($args) {
    list($from, $to) = explode(' ', trim($args));

    return [
        'beginPhp' => 'for ($i = ' . $from . '; $i <= ' . $to . '; $i++) {',
        'endPhp' => '}',
    ];
});

$pug->render('
range 1 3
    p= i
');

This will render:

<p>1</p>
<p>2</p>
<p>3</p>

Note that the existing for..in operator will have the precedence on this custom for keyword.

Invokable class:

class UserKeyword
{
    public function __invoke($arguments, $block, $keyWord)
    {
        $badges = array();
        foreach ($block->nodes as $index => $tag) {
            if ($tag->name === 'badge') {
                $href = $tag->getAttribute('color');
                $badges[] = $href['value'];
                unset($block->nodes[$index]);
            }
        }

        return [
            'begin' => '<div class="' . $keyWord . '" data-name="' . $arguments . '" data-badges="[' . implode(',', $badges) . ']">',
            'end' => '</div>',
        ];
    }
}

$pug->addKeyword('user', new UserKeyword());

$pug->render('
user Bob
    badge(color="blue")
    badge(color="red")
    em Registered yesterday
');

This will render:

<div class="user" data-name="Bob" data-badges="['blue', 'red']">
    <em>Registered yesterday</em>
</div>

A keyword must return an array (containing begin and/or end entries) or a string (used as a begin entry).

The begin and end are rendered as raw HTML, but you can also use beginPhp and endPhp like in the first example to render PHP code that will wrap the rendered block if there is one.

PHP Helper functions

If you want to make a php function available in a template or in all of them for convenience, use closures and pass them like any other variable:

$myClosure = function ($string) {
    return 'Hey you ' . $string . ', out there on your own, can you hear me?';
};

$pug->render('p=$myClosure("Pink")', array('myClosure' => $myClosure));

This will render:

<p>Hey you Pink, out there on your own, can you hear me?</p>

You can make that closure available to all templates without passing it in render params by using the share method:

// ... $pug instantiation
$pug->share('myClosure', $myClosure);
$pug->render('p=$myClosure("Pink")');

This will render the same HTML than the previous example. Also note that share allow you to pass any type of value.

Cache

Important: to improve performance in production, enable the Pug cache by setting the cache option to a writable directory, you can first cache all your template at once (during deployment):

$pug = new Pug([
    'cache' => 'var/cache/pug',
]);
[$success, $errors] = $pug->cacheDirectory('path/to/pug/templates');
echo "$success files have been cached\n";
echo "$errors errors occurred\n";

Be sure any unexpected error occurred and that all your templates in your template directory have been cached.

Then use the same cache directory and template directory in production with the option upToDateCheck to false to bypass the cache check and automatically use the cache version:

$pug = new Pug([
    'cache' => 'var/cache/pug',
    'basedir' => 'path/to/pug/templates',
    'upToDateCheck' => false,
]);
$pug->render('path/to/pug/templates/my-page.pug');

Templates from pug-js

First remember pug-php is a PHP template engine. Pug-js and Pug-php provide both, a HAML-like syntax for markup and some abstraction of the language behind it (loops, conditions, etc.). But for expressions and raw code, pug-js uses JS, and pug-php uses PHP. By default, we do some magic tricks to transform simple JS syntax into PHP. This should help you to migrate smoother from pug-js if you already have some templates, but benefit from the PHP advantages.

If you start a new project, we highly recommend you to use the following option:

$pug = new Pug([
    'expressionLanguage' => 'php',
]);

It will disable all translations, so you always have to use explicit PHP syntax:

- $concat = $foo . $bar
p=$concat

If you want expressions very close to JS, you can use:

$pug = new Pug([
    'expressionLanguage' => 'js',
]);

It will allow both PHP and JS in a JS-style syntax. But you have to stick to it, you will not be able to mix PHP and JS in this mode.

Finally, you can use the native pug-js engine with:

$pug = new Pug([
    'pugjs' => true,
]);

This mode requires node and npm to be installed as it will install pug-cli and directly call it. This mode will flatten your local variables (it means complex object like DateTime, or classes with magic methods will be stringified in JSON to simple objects) and you will not benefit from some features like mixed indent, pre/post render hooks. But in this mode you will get exact same output as in pug-js.

Write locals object to JSON file with pug-js

If your locals object is large it may cause a RuntimeException. This is because locals object passed directly to pug-cli as argument. To fix this problem you can use the localsJsonFile option:

$pug = new Pug([
    'pugjs' => true,
    'localsJsonFile' => true
]);

Then your locals will be written to a JSON file and the path of the file will be passed to the compiler.

Pug CLI

Pug also provide a CLI tool:

./vendor/bin/pug render-file dir/my-template.pug --output-file

See the complete CLI documentation here

Check requirements

To check if your environment is ready to use Pug, use the requirements method:

$pug = new Pug([
    'cache' => 'pathto/writable/cachefolder/',
]);
$missingRequirements = array_keys(array_filter($pug->requirements(), function ($valid) {
    return $valid === false;
}));
$missings = count($missingRequirements);
if ($missings) {
    echo $missings . ' requirements are missing.<br />';
    foreach ($missingRequirements as $requirement) {
        switch($requirement) {
            case 'streamWhiteListed':
                echo 'Suhosin is enabled and ' . $pug->getOption('stream') . ' is not in suhosin.executor.include.whitelist, please add it to your php.ini file.<br />';
                break;
            case 'cacheFolderExists':
                echo 'The cache folder does not exists, please enter in a command line : <code>mkdir -p ' . $pug->getOption('cache') . '</code>.<br />';
                break;
            case 'cacheFolderIsWritable':
                echo 'The cache folder is not writable, please enter in a command line : <code>chmod -R +w ' . $pug->getOption('cache') . '</code>.<br />';
                break;
            default:
                echo $requirement . ' is false.<br />';
        }
    }
    exit(1);
}

Contributing

All contributions are welcome, for any bug, issue or merge request (except for security issues) please refer to CONTRIBUTING.md

Security

To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure.

Contributors

This project exists thanks to all the people who contribute.

And all the people contributing to our dependencies, in particular: The Phug engine The JS syntax converter Js-Phpize

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. Become a sponsor

And a big thank-you to Jet Brains who provides such a great IDE:

pug's People

Contributors

carusogabriel avatar cjonasw avatar debo avatar djranger avatar everzet avatar fcrosfly avatar fridzema avatar hackaugusto avatar hkjels avatar hustlahusky avatar just-paja avatar kpicaza avatar krizalys avatar kylekatarnls avatar lukegb avatar marcelloduarte avatar mcoenca avatar monkeywithacupcake avatar peniar avatar rmrevin avatar s4msung avatar sadjow avatar sisoftrg avatar soviut avatar spekulatius avatar sszigeti avatar torbenkoehn avatar volter9 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

pug's Issues

Adding a class using the class attributes appends the class without separation.

Simple issue fixable on user side but seems like a missing feature / bug to me.

Taking this code

- $classes = 'MyClasss'

.MyInitialClass(class=$classes)

It returns

<div class="MyInitialClassMyClass"></div>

Expected behaviour

<div class="MyInitialClass MyClass"></div>

Adding a space in my class fixes it but here the example is simplified, I use arrays most of the time and need to add a space to the first entry.

Passing arguments to helper function

Hello,

I have a question and maybe an enhancement proposal concerning helper functions. I created a simple helper function which needs a number as an argument to do some formatting. I've included this function using the share method.

The problem I have is that when I pass a literal value it works perfectly, but when I want to pass a variable managed by the Pug template its not working as expected. Here's an example working as expected with literal value (200) :

each item in items
  li Example #{item.name} #{$format('money', 200)}

Here's an example which do not work using Pug variable.

I expected to get:

each item in items
  li Example #{item.name} #{$format('money', item.price)}

I get an error saying Use of undefined constant item which make perfect sense since the resulting PHP for the segment above is :

<?php foreach ($items as $item) { ?>
    <li>Example <?php echo \Jade\Compiler::getEscapedValue(\Jade\Compiler::getPropertyFromAnything($item, 'name'), '"') ?> <?php echo \Jade\Compiler::getEscapedValue($format('money', item.price), '"') ?>
    </li>
<?php } ?>

The item.price certainly doesn't exists in this context. I found a workaround knowing that what was passed to the function and its simply somehow direct PHP input.

each item in items
  :php $price = $item->getPrice();
  li Example #{item.name} #{$format('money', $price)}

My question : is this the desired way of using arguments with helper function and if there's a better way to to pass an argument?

I'd really love to remove as much php in my Pug as I can. I know my example code may not be the best use of a view since I could do the formatting before sending it to the Pug view, but I have some quick functions like this which can be very helpful when needing.

If there's currently no simpler way to access the Pug variables, I think it could be a nice addition to this phenomenal template engine.

Thanks!

include, extends

in my index.pug
I have

include front/header.pug

Compiler always tell's : "Page not found."
Looking at source of vendor/pug-php/pug/src/Jade/Jade.php:compile:217 method - I see:

$parser = new Parser($input, null, $this->options);

Mb, it should be

$parser = new Parser($input, $FILENAME, $this->options);

So the parser could detected local directory name? And after load dependency?

Object properties cannot concatenate with strings

Consider
input(type="checkbox", name="group["+group.id+ "]")

Compiles to
<input type="checkbox" name="group[{...}].id]">
instead of
<input type="checkbox" name="group[the_id]">

but works when not concatenating

parse php function error

protected function handleArgumentValue($arg)
{
   //fix parse php function error, add **strlen($arg) == 1**
    if (preg_match('/^([\'"]).*?\1/', $arg) && strlen($arg) == 1) {
        return $this->handleString(trim($arg));
    }

    try {
        return $this->handleCode($arg);
    } catch (\Exception $e) {
        // if a bug occur, try to remove comments
        try {
            return $this->handleCode(preg_replace('#/\*(.*)\*/#', '', $arg));
        } catch (\Exception $e) {
            throw new \Exception('Pug.php did not understand ' . $arg, 10, $e);
        }
    }
}

page not found

When template was not found, it silently render "page not found" instead.
I just don't like this approach.

contra:

  • localization
  • issues with templates not found are possibly overlooked

+1 for (maybe optional) raising an exception if a template was not found

pro:

  • testsuite captures uncatched exceptions

How to Include Javascript

Hello, first thanks for this library great work, I'm happy to be able to use Jade/pug as my templating engine. I ran over an issue which I suppose is related to parsing. In pugJS you can include an external Javascript file in a template by writing

script
      include script.js

http://jade-lang.com/reference/includes/

However in pugPHP it's interpreting it as javascript and outputing

<script>
include script.js
</script>

Is it an easy fix? For now I will just put my script in a pug file and include it.

Can't pass arguments to mixin inside a block

I don't know what's the root cause, but

mixin paragraph(text)
    p=text

+paragraph('yolo')

works

but

mixin paragraph(text)
    p=text

block paragraphs
    +paragraph('yolo')

produces an error in MixinVisitor.php Nodes\Mixin\MixinVisitor\parseMixinArguments line 21 : $arguments = ['0' => 'yolo'] and not $arguments = 'yolo' as expected and it makes the call to explode(',' $arguments) well ... explode ;)

Thanks !

Passing helper php function to pug context ?

(Not sure if it's not possible or if I have not found the right way to do it ?? I am not very experienced in php scopes sorry if this is a stupid question...)

I would like to be able to pass a php function to pug at render time, to be able to call it directly in my template. Without resorting to a global function.

That way I would be able to use the same helper function name in all my template, even if its behaviour is dependent of the route context.

Something like:

// in HomeController.php

public function get() {
    function pathFor($pathName) use ($this) {
        return $this->router->pathFor($pathName);
    }

   return $this->pug->render('productPage.pug', $this->templateParams, [pathFor?] )
}
//- in productPage.pug

p
    #[a href=pathFor('/home')) Click here quick quick quick QUICK !]

would get me

<a href="/amazing-product-you-will-like-and-buy-home-page"> Click here quick quick quick QUICK ! </a>

Thanks for your help !
Btw: Amazing package 💯

String behavior is confused and inconsistent

p= '$test'
p= "$test"
p= '#{$test}'
p= "#{$test}"
p #{$test}

p(
	data-a='$test'
	data-b="$test"
	data-c='#{$test}'
	data-d="#{$test}"
) test

With data ['test' => 'testing'] and option expressionLang php or auto, the result is:

<p>testing</p>
<p>#{$test}</p>
<p>#testing</p>
<p>testing</p>
<p data-a="$test" data-b="$test" data-c="testing" data-d="testing">test</p>

= output uses PHP strings syntax and ignore the pug interpolations syntax #{expression}. But attribute output does not use PHP strings syntax and process #{expression} which is not very consistent.

With expressionLang js the result is:

<p>testing</p>
<p>#{$test}</p>
<p>#testing</p>
<p>testing</p>
<p data-a="$test" data-b="$test"
// Notice: Undefined variable: testing in pug.stream

= output still uses PHP strings syntax which confused, and there are bug in process #{expression} in attributes.

Error concerning mixins in JS expressionLanguage mode

Hi,

I have a question concerning how to use mixin when using expressionLanguage js option. I've tried the basic mixin example provided on the Pug website :

mixin list
  ul
    li foo
    li bar
    li baz

doctype html
html
  head
    title Example
  body
    h1 Testing mixins
    +list

I'm constructing the Pug instance with the following code :

$options = [
    'basedir' => ROOT_DIR . '/public',
    'expressionLanguage' => 'js',
    'upToDateCheck' => true
];
$pug = new Pug($options);
echo $pug->render("test.pug");

Which results in an error :

Error on the mixin "list" in test.pug line 13: Unexpected ? in on line 1 near from $attributes)) ?

But, if I use 'expressionLanguage' => 'auto' instead of js it works as expected. Maybe I'm declaring or using the mixin incorrectly in js mode, so I was wondering how I could make it work.

Thanks a lot !

For render as PHP structure

hey first of all,
thanks for make pug for php 👍

I have some ideas for pug.

I think pug is for html, just for html

so what does it mean?
in pug-php, - for ($i = 0; $i < $j; $i++) render as PHP struct
it not right at all

the right way use pug in php

it should base on orther php template engine like blade, twig

@for ($i = 0; $i < $j; $i++)
  p hello {{ $i }}
@endfor

how do u think about it?

Style object value

In pugjs/pug, object can be passed as CSS style list:

h1(style={color: 'red', 'font-size': '12px', 'tab-size': 12 }) Style object value
h1(style-only={color: 'red', 'font-size': '12px', 'tab-size': 12 }) Only for style attribute

It's tunred into the following HTML:

<h1 style="color:red;font-size:12px;tab-size:12">Style object value</h1>
<h1 style-only='{"color":"red","font-size":"12px","0":"tab-size"}'>Only for style attribute</h1>

It will be added to pug-php/pug and it should also allow PHP associative arrays.

Can´t pass variables to &attributes(attributes) in a mixin

I want to pass variables to the mixin within the attributes param.
This doesn´t work as expected because it is not inserting the variables just the variable name as a string. I tried also with $ but it also didn´t help.

Do you think you can fix this?

Mixin

mixin module()
  div.module()&attributes(attributes)
    block

Variables passed to the Template

<?php
array(
  'moduleTitle' => 'I am a module',
  'customClassKey' => 'custom-class-value',
  'customAttributeKey' => 'custom-attribute-value'
)

Template

!!! 5
html(lang="en")
  body
    +module()(class=customClassKey data-customDataAttribute=customAttributeKey)
      h1= moduleTitle

HTML Result
Output which doesn´t have the attribute variable just the keys of the passed variables

<!DOCTYPE html>
<html lang="en">
  <body>
  <div data-customAttribute="customAttributeKey" class="customClassKey module">
    <h1>I am a module</h1>
  </div>
  </body>
</html>

Parenthesis in attribute

I encountered an issue with the following code:

a(b=')')

I expected to get:

<a b=')'></a>

But I actually get:

<a>)'</a>

I will revise all the parentheses regular expression to handle string within them.

Shared variables

Variables should be able to be added before the call to the ->render() methood. This way, we could share variables between several/all templates.

Need more info for parsing error report

I just got many errors like:

( ! ) Fatal error: Uncaught exception 'ErrorException' with message 'Unexpected value: link']}'' in .../htdocs/vendor/pug-php/pug/src/Jade/Compiler.php on line 285

Such error report is not very helpful. I guess it come from some syntax error in my pug source, but current error report give no clue.

About the behavior of `prettyprint` option

This is an old issue of original jade-php (or original jade/pug), but I'd wish it be fixed in pug-php.

Currently, when prettyprint is false, all generated code will be compressed to one line which make line position meaningless and make debug painful.

IMO prettyprint=true have no real use case, especially in PHP. Even in JS, if we want to compress the generated code to save bytes, we could just use tools like uglify.

But prettyprint affect the output of html in whether it compress whitespace between tags.

span 'a'
span 'b'

output

<span>a</span><span>b</span>

result ab if prettyprint=false,

but output

<span>a</span>
<span>b</span>

result a b (extra space between a and b) if prettyprint=true.

In fact, with prettyprint=true we have no way to output <span>a</span><span>b</span> at all.

So prettyprint is a BAD designed option which not only affect generated code, but also affect html output semantic.

I suggest drop this option (at least deprecate it), and make the generated code always multilines.

To achieve that, the generated code should not be

<span>a</span>
<span>b</span>

but should be

<?php
echo '<span>a</span>';
echo '<span>b</span>';

There are other methods to output the same result, but this transformation may be the easiest.

Can't pass function result to mixin directly

This code:

.form__element
  +site-select(trans('auth.signin.site'))

results in trans('auth.signin.site' Missing closing: ).

However this code works just fine:

.form__element
  - $placeholder = trans('auth.signin.site')
  +site-select($placeholder)

Same code in JS syntax works as well:

.form__element
  - placeholder = trans('auth.signin.site')
  +site-select(placeholder)

MWE for site-select:

mixin site-select(placeholder)
  = placeholder

Possibly related: #84

Array values not converted to objects during interpolation in attributes

With this data:

[ 
  'feature' => [
    'image' => '/img/path.jpg'
  ]
]

This pug...

.featured(style='background-image: url(/img/#{feature.image});')

... fails with an Array to string conversion exception. But this works:

.featured(style='background-image: url(/img/#{feature["image"]});')

I should be able to use feature.image, right?

Thanks for the package! Incidentally, I set up this Laravel adapter https://github.com/BKWLD/laravel-pug

Can't use array member in jade / pug inline attributes directly?

I want to show array member in foreach loop. It works fine except inline code combination like this:

each i in ModuleAtMenu
   li: a.indent(href='?act=module&module=' + i.module_key)=i.module_title

But this one is ok

each i in ModuleAtMenu
   li: a.indent(href=i.module_key)=i.module_title

Single method to assign variable?

I see only render is the method can assign variable to the template.
Is there any way or method to assign variable separately like:
$pug->assign('abc',$abc);

Don't require a leading slash to use the `basedir` option when extending

The Jade extends syntax doesn't require a leading slash.
https://pugjs.org/language/extends.html

Currently, for our Laravel parser, the leading slash is required for the basedir option to be used when searching for the template path.
https://github.com/BKWLD/laravel-pug#extending-layouts

Is it possible to use the basedir option regardless of the leading slash, in order to stay closer to the Jade/Pug syntax?
https://github.com/pug-php/pug/blob/master/src/Jade/Parser.php#L66

Allow extra semicolon in output

= test;
!= test;

Currently extra ; will cause parser error. Though it's redundant, old jade-php allow this and there are many in the repo of my team. So for compatibility could you allow this?

Inline filters

It seems only Block-Style filters are supported:

h1
  :i18n
    msg_id

Inline-Style filters

h1
  | ...
  :i18n msg_id
  | ...
h1 ... #[:i18n msg_id] ...

are currently throwing ErrorException with "Expected indent, but got text in 1th line: ..."

pug-php version 2.4.1

some names not recognized as varaiables

p= a + b

expect compiled to $a + $b,
actual $a + b, which cause runtime exception Notice: Use of undefined constant b

It seems all binary operators (+, -, *, /, %, &&, ||, etc.) have same problem.

Double quote by default

As in pugjs, the double quote " should be used by default instead of the single quote ' but as it would break retro-compatibility, it should be done on the version 2.0 or it should be just mentioned as recommanded setting before 2.0.

But pugjs use single quote for data- attributes as it is optimized for JSON values. Here is a point of complexity for our singleQuote setting.

mixin parameters affect variable of out scope

It's a very serious bug...

mixin test(a)
    div

- var_dump(a)
+test(a[0])
- var_dump(a)
+test(a[1])
- var_dump(a)

send 'a' => [1, 2, 3], you get:

array (size=3)
  0 => int 1
  1 => int 2
  2 => int 3
int 1
null

😱

Get the current compiler and path/filename from the callback of a custom filter

in custom filter we need to get template path.
for example, i make include-markdown filter and can support insert by relative paths.
or insert images by relative paths.
Compiler class contain $filename property, but protected.

example in custom filter usage:

public function __invoke(Filter $node, Compiler $compiler)
{
    $templateFilename = $compiler->getFilename();
}

Support for magic methods in JS syntax

(original, misleading description below)

When using JS syntax it is not currently possible to access methods and properties that are handled by magic methods such as __get() or __call(). For example, this code:

= errors.first('email_address')

leads to an error when errors has a __call method but not a first method.


Pretty self-explaining. This code snippet:

if errors.has('email')
  = errors.first('email')

leads to the error Function name must be a string (View: [redacted]/resources/views/signin.pug). Here's the context:

error

When using PHP syntax there's no such error

if $errors->has('email')
  = $errors->first('email')

And for the record, this hybrid syntax works as well:

if errors->has('email')
  = errors->first('email')

So this is probably a bug with the JS-PHP conversion.

How to pass an array as mixin param?

How we can pass array as param with pug 2.4.5?

mixin asd(params)
    div= params.name
+asd(["name":"Pug","lang":"PHP"])

Result
Fatal error: Uncaught exception 'ErrorException' with message '['name':"Pug" Missing closing: ]'

If just pass one value, works fine:

+asd(["name":"Pug"])

Return json:

{"name":"Pug"}

Regards!

Current examples and project not working

I am trying to adopt this library for one of my pet projects but I don't seem to be able to achieve any working result. As last resource I did try to run the provided examples using the PHP built-in web server but also in that case I didn't seem to be able to make it work.

Out of the box after starting the built-in web server within the example folder produces an E_NOTICE that PATH_INFO is not set, that's easy to temporarily work around suppressing notice errors, however, even with notice suppressed I can't get anything but a blank page.

It has to be noted that pug defaults to .pug as extension but all the file presents in the folder are .jade so I decided to force the latter upon creation of the pug object but again without success, I always get a blank page.

The disconcerting thing is that there are no visible errors reported.

Any ideas?

$pug->requirements() should return true for cache if the cache is set to false.

Setting the cache option to false when using the requirements throws:

2 requirements are missing.
The cache folder does not exists, please enter in a command line : mkdir -p .
The cache folder is not writable, please enter in a command line : chmod -R +w .

I would like to enable the cache only on production and staging environments but can't unless the requirements test is also done on these environments.

Names for Functions

I make heavy use of ProcessWires translation function called by __('String to translate') sadly this does not work with pug/jade, any other function named doSomething() works as expected. Anywhere I can change this?

Boolean attributes

With literal values this works as expected:

input(type="checkbox", checked=true)
<input type="checkbox" checked>

Using variable assignment it renders boolean attributes wrong:

input(type="checkbox", checked=isChecked)
<input type="checkbox" checked="true">

Extra space added when echoing value using #{} syntax.

Hello, might be related to the other issue also but if I use this notation

'#{$bar->foo}'

The content is outputted like so 'Hello world '.
It's not really problematic as I remove the space later in Javascript (the goal is to pass variables).

But when trying to concatenate to get a file url it can become problematic. Something along the lines of '#{base}/file.png' even if here I use the notation $base.'/file.png' as a workaround.

Maybe it's related to the other issue I raised? Thanks in advance, hope it's nothing too hard to fix.

Compile an entire directory

In a production environment, we could render all templates in a directory and its sub-directories during the deployement to make them available in the cache. And then all client would only load cached PHP versions of the templates.

And so, in production, it will be no longer necessary to check if templates are up to date. They will always be loaded from cache.

Improve caching performance

In order to enable dynamic attributes, some PHP had to be added in rendered PHP contents. This made the cached file a little bigger and slower to be executed and re-executed. To improve performance in production environement, we need to detect in the compilation phase is a tag and its attributes are static or dynamic and use PHP middle code only if it can be needed.

Currently, the most critic point is the class attribute.

Blanks between HTML tags

Just a simple problem, but this leads me to a real issue.

When I want to display a textarea, the code is really simple:

textarea(name="comments")
But actually, the output code is
<textarea name="comments"><!-- some spaces here --></textarea>

And that's the problem: I don't want any blanks in my textarea as there is nothing inside, it will appear weird to the user when filling the form.
It appears no matter I set the pretty print to true or false. Cache (or not) does not change a thing too.

Is there a way like Twig, for example, to remove those blanks. (e.g. in Twig: {{- myVar -}} will remove the blanks between the Twig tag and the HTML tag, in both left and right side)

Handle PHP expressions properly

The following pug code:

p(answear=substr("foo-bar", strlen("foo") + 1))

Turns into the following PHP (simplified):

<p answear="<?php echo substr("foo-bar", strlen("foo")); ?>"></p>

The + 1 is missing, we expect:

<p answear="<?php echo substr("foo-bar", strlen("foo") + 1); ?>"></p>

It's most likely caused by a bad handling of parentheses in CodeHandler::parseBetweenSeparators().

Error while setting dynamic HTML attributes

While I'm trying to achieve a dynamic A tag with its href attribute, I'm facing an error with PHP. Actually, Pug does not parse the content correctly in this example of code:

a(href="?id=#{myObj.id}")

This will throw an error like trying to convert an object to string. Actually, it is trying to achieve the PHP's concatenation (the result looks like "<?php echo $myObj . $id ?>"), that's why there is the bug.

The workaround for me was to do something like this:

a(href="?id=#{myObj->id}")

which is not a Pug syntax, but it actually works.

EDIT:
To be more complete, still the same issue if writting the code with the equivalent:
a(href="?id=" + myObj.id)

Issue with parenthesis in attributes

This pug:

.featured(class=(true==true)?'on':'off')

Produces a syntax error, unexpected ')', expecting variable (T_VARIABLE) or '$' exception. It is fixed by:

.featured(class=true==true?'on':'off')

I ran into this while porting a jade-js project to PHP

Can't use block unbuffered code with Pug PHP

pug offers a nice way to do tests, assign variables... within a pug template by using the unbuffered code block style. See:
https://pugjs.org/language/code.html#unbuffered-code

With pug-php it's not possible, as the Parser crashes with Unexpected token "indent" error.
Would it be possible to implement? Saying that using this syntax would actually be executed as a php block with the current scope. Would love to see this feature coming to pug-php.

Thanks.

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.