SE7ENSKY / jade2php

Unlock Jade for PHP! Convert Jade templates into raw PHP templates. CLI tool and JavaScript API. Test covered.
43 stars 10 forks source link

Prerendered attributes #19

Open OnkelTem opened 9 years ago

OnkelTem commented 9 years ago

I need to generate this PHP output:

<body class="<?php print $classes; ?>" <?php print $attributes;?>>

which seems currently impossible to achieve with canonical jade syntax, so I used this workaround as a temporarily solution:

body(class=body_classes, "<?php print $attributes?>")

Ideas?

ivankravchenko commented 9 years ago

It can be done via &attributes(attributes) or with

doctype html
html
  head
    ...
  <body !{bodyAttributes}>
  ...
  </body>

There is no native-like Jade implementation for PHP's <body<?php body_class()?>> construct.

OnkelTem commented 9 years ago

It can be done via &attributes(attributes) or with

This is true if $attributes would be an array, but in my case (a Drupal template) $attributes is just a string of rendered attributes (in Drupal theming loop).

From my observations a construct:

body(class=class, attributes)

generates the code:

<body attributes<?php attr_class($body_classes) ?>></body>

So it seems the resolution could be probably as simple as 1) finding unresolved variables in jade attributes '(...)'-list 2) replacing each with simple php's print call

Then we would get:

<body <?php print $attributes?><?php attr_class($body_classes) ?>></body>
ivankravchenko commented 9 years ago

That would introduce Jade incompatibility. body(class=class, attributes) expected to be <body class="..." attributes>

ivankravchenko commented 9 years ago

Added example test in 7a607f8.

OnkelTem commented 9 years ago

Ok, then let's go anther way.

The attrs() PHP function could support setting rendered attributes either.

First shot (my modifications are commented with //):

function attrs() {
  $args = func_get_args();
  $attrs = array();
  // $rendered_attrs = array();
  foreach ($args as $arg) {
    // if (is_array($arg)) {
      foreach ($arg as $key => $value) {
        if ($key == 'class') {
          if (!isset($attrs[$key])) $attrs[$key] = array();
          $attrs[$key] = array_merge($attrs[$key], is_array($value) ? $value : explode(' ', $value));
        }
        else {
          $attrs[$key] = $value;
        }
      }
    // }
    // elseif (is_string($arg)) {
      // $rendered_attrs[] = $arg;
    // }
  }
  foreach ($attrs as $key => $value) {
    if ($key == 'class') {
      attr_class($value);
    } else {
      attr($key, $value);
    }
  }
  // foreach ($rendered_attrs as $attrs) {
    // echo " $attrs";
  // }
}

Now it is possible to set attributes in several ways:

Using fully rendered attributes: attrs('title="This is title" lang="en"')

Using array (as before): attrs(array('color' => 'red'))

Using both: attrs('title="This is title" lang="ru"', array('color' => 'red'))

OnkelTem commented 9 years ago

Possible bug. This snippet:

    body(class=classes)&attributes(attributes)

generates erroneous PHP:

<body<?php attrs(array("class" => $jade_interp = array(true), $jade->joinClasses(array($classes)->map($jade->joinClasses)->map(function ($cls, $i) use (&$jade_interp) {
return ($jade_interp[$i]) ? htmlspecialchars($cls) : $cls; }
));), $attributes); ?>>
</body>
ivankravchenko commented 9 years ago

That behavior IS a bug and is non-implemented part of Compiler.attrs method. Unfortunately, I can't figure out how to fix quickly, so leaving it into background.

janwirth commented 9 years ago

@OnkelTem this is a possible duplicate of https://github.com/SE7ENSKY/jade2php/issues/11