Skip to content

Commit b70323c

Browse files
authored
Merge pull request #30 from Paneon/master
Update master
2 parents ec18aff + f489443 commit b70323c

File tree

8 files changed

+223
-2
lines changed

8 files changed

+223
-2
lines changed

src/Compiler.php

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ class Compiler
105105
*/
106106
protected $includeAttributes = ['class', 'style'];
107107

108+
/**
109+
* @var string[]
110+
*/
111+
protected $attributesWithIf = ['checked', 'selected', 'disabled'];
112+
108113
/**
109114
* Compiler constructor.
110115
*/
@@ -154,6 +159,15 @@ public function convert(): string
154159

155160
$twigBlocks = $this->document->getElementsByTagName('twig');
156161

162+
$twigConfigBlocks = $this->document->getElementsByTagName('twig-config');
163+
164+
if ($twigConfigBlocks->length) {
165+
foreach ($twigConfigBlocks as $twigConfigBlock) {
166+
/* @var DOMText $twigConfigBlock */
167+
$this->handleTwigConfig(trim($twigConfigBlock->textContent));
168+
}
169+
}
170+
157171
if ($scriptElement) {
158172
$this->registerProperties($scriptElement);
159173
$this->insertDefaultValues();
@@ -192,6 +206,7 @@ public function convert(): string
192206
$html = $this->addVariableBlocks($html);
193207
$html = $this->replacePlaceholders($html);
194208
$html = $this->replaceScopedPlaceholders($html);
209+
$html = $this->replaceAttributeWithIfConditionPlaceholders($html);
195210

196211
$html = preg_replace('/<template>\s*(.*)\s*<\/template>/ism', '$1', $html);
197212
$html = preg_replace('/<\/?template[^>]*?>/i', '', $html);
@@ -211,6 +226,16 @@ public function convert(): string
211226
return $html;
212227
}
213228

229+
private function handleTwigConfig(string $twigConfig): void
230+
{
231+
$config = parse_ini_string($twigConfig);
232+
if ($config['attributes-with-if'] ?? false) {
233+
$attributes = explode(',', $config['attributes-with-if']);
234+
$attributes = array_map(function ($item) { return trim($item); }, $attributes);
235+
$this->attributesWithIf = array_merge($this->attributesWithIf, $attributes);
236+
}
237+
}
238+
214239
/**
215240
* @throws Exception
216241
*/
@@ -513,8 +538,15 @@ private function handleAttributeBinding(DOMElement $node): void
513538
continue;
514539
}
515540

541+
// makes no sense to use this in code, but it must handled.
542+
if ($value === 'false') {
543+
continue;
544+
}
545+
516546
$dynamicValues = $this->handleBinding($value, $name, $node);
517547

548+
$addIfAroundAttribute = in_array($name, $this->attributesWithIf);
549+
518550
/* @see https://gitlab.gnome.org/GNOME/libxml2/-/blob/LIBXML2.6.32/HTMLtree.c#L657 */
519551
switch ($name) {
520552
case 'href':
@@ -535,7 +567,22 @@ private function handleAttributeBinding(DOMElement $node): void
535567
break;
536568
}
537569

538-
$node->setAttribute($name, $this->implodeAttributeValue($name, $dynamicValues, $staticValues));
570+
$value = $this->implodeAttributeValue($name, $dynamicValues, $staticValues);
571+
572+
if ($addIfAroundAttribute && $value) {
573+
$value = $name . '|' . base64_encode(
574+
$this->builder->refactorCondition(
575+
$this->replacePlaceholders($value)
576+
)
577+
);
578+
$name = '__ATTRIBUTE_WITH_IF_CONDITION__';
579+
$oldValue = $node->getAttribute($name);
580+
if ($oldValue) {
581+
$value = $oldValue . ',' . $value;
582+
}
583+
}
584+
585+
$node->setAttribute($name, $value);
539586
}
540587
}
541588

@@ -1263,4 +1310,30 @@ private function replaceScopedPlaceholders(string $html): string
12631310

12641311
return $html;
12651312
}
1313+
1314+
/**
1315+
* @throws ReflectionException
1316+
*/
1317+
private function replaceAttributeWithIfConditionPlaceholders(string $html): string
1318+
{
1319+
$pattern = '/__ATTRIBUTE_WITH_IF_CONDITION__="([^"]+)"/';
1320+
if (preg_match_all($pattern, $html, $matches, PREG_SET_ORDER)) {
1321+
foreach ($matches as $match) {
1322+
$attributes = explode(',', $match[1]);
1323+
$replaceHtml = '';
1324+
foreach ($attributes as $attribute) {
1325+
[$name, $encodedValue] = explode('|', $attribute);
1326+
$value = $this->replacePlaceholders(base64_decode($encodedValue));
1327+
$condition = trim(str_replace(['{{', '}}'], '', $value));
1328+
if (in_array($name, ['checked', 'selected', 'disabled'])) {
1329+
$value = $name;
1330+
}
1331+
$replaceHtml .= ' {% if ' . $condition . ' %}' . $name . '="' . $value . '"{% endif %}';
1332+
}
1333+
$html = str_replace($match[0], trim($replaceHtml), $html);
1334+
}
1335+
}
1336+
1337+
return $html;
1338+
}
12661339
}

tests/AttributeWithIfTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace Paneon\VueToTwig\Tests;
4+
5+
use Exception;
6+
7+
class AttributeWithIfTest extends AbstractTestCase
8+
{
9+
/**
10+
* @dataProvider dataProvider
11+
*
12+
* @throws Exception
13+
*/
14+
public function testAttributeIfTrue($template, $expected)
15+
{
16+
$compiler = $this->createCompiler($template);
17+
18+
$actual = $compiler->convert();
19+
20+
$this->assertEqualHtml($expected, $actual);
21+
}
22+
23+
/**
24+
* @return array
25+
*/
26+
public function dataProvider()
27+
{
28+
return [
29+
[
30+
'<template><form><input type="checkbox" :checked="false"></form></template>',
31+
'<form class="{{ class|default(\'\') }}" style="{{ style|default(\'\') }}"><input type="checkbox"></form>',
32+
],
33+
[
34+
'<template><form><input type="checkbox" :checked="foo"></form></template>',
35+
'<form class="{{ class|default(\'\') }}" style="{{ style|default(\'\') }}"><input type="checkbox" {% if foo %}checked="checked"{% endif %}></form>',
36+
],
37+
[
38+
'<template><form><input type="checkbox" :checked="foo || bar"></form></template>',
39+
'<form class="{{ class|default(\'\') }}" style="{{ style|default(\'\') }}"><input type="checkbox" {% if foo or bar %}checked="checked"{% endif %}></form>',
40+
],
41+
[
42+
'<template><form><input type="checkbox" :checked="foo === 1"></form></template>',
43+
'<form class="{{ class|default(\'\') }}" style="{{ style|default(\'\') }}"><input type="checkbox" {% if foo == 1 %}checked="checked"{% endif %}></form>',
44+
],
45+
[
46+
'<template><form><input type="checkbox" :disabled="foo === 0" :checked="foo === 1"></form></template>',
47+
'<form class="{{ class|default(\'\') }}" style="{{ style|default(\'\') }}"><input type="checkbox" {% if foo == 0 %}disabled="disabled"{% endif %} {% if foo == 1 %}checked="checked"{% endif %}></form>',
48+
],
49+
];
50+
}
51+
}

tests/TwigConfigTest.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
namespace Paneon\VueToTwig\Tests;
4+
5+
use Exception;
6+
7+
class TwigConfigTest extends AbstractTestCase
8+
{
9+
/**
10+
* @dataProvider ifProvider
11+
*
12+
* @param mixed $html
13+
* @param mixed $expected
14+
*
15+
* @throws Exception
16+
*/
17+
public function testTwigConfig($html, $expected)
18+
{
19+
$compiler = $this->createCompiler($html);
20+
21+
$actual = $compiler->convert();
22+
23+
$this->assertEqualHtml($expected, $actual);
24+
}
25+
26+
public function ifProvider()
27+
{
28+
return $this->loadFixturesFromDir('twig-config');
29+
}
30+
}

tests/VuePreTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ class VuePreTest extends AbstractTestCase
88
{
99
/**
1010
* @dataProvider dataProvider
11-
1211
*
1312
* @throws Exception
1413
*/
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% set count = count|default(0) %}
2+
<div class="{{ class|default('') }}" style="{{ style|default('') }}">
3+
<div {% if count > 5 %}foo="{{ count > 5 }}"{% endif %}>
4+
Foo
5+
</div>
6+
<div {% if count > 5 %}bar="{{ count > 5 }}"{% endif %}>
7+
Bar
8+
</div>
9+
</div>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<template>
2+
<div>
3+
<div :foo="count > 5">
4+
Foo
5+
</div>
6+
<div :bar="count > 5">
7+
Bar
8+
</div>
9+
</div>
10+
</template>
11+
12+
<twig-config>
13+
attributes-with-if = foo,bar
14+
</twig-config>
15+
16+
<script>
17+
export default {
18+
props: {
19+
count: {
20+
type: Number,
21+
default: 0,
22+
},
23+
},
24+
};
25+
</script>
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% set count = count|default(0) %}
2+
<div class="{{ class|default('') }}" style="{{ style|default('') }}">
3+
<div {% if count > 5 %}foo="{{ count > 5 }}"{% endif %}>
4+
Foo
5+
</div>
6+
<div bar="{{ count > 5 }}">
7+
Bar
8+
</div>
9+
</div>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<template>
2+
<div>
3+
<div :foo="count > 5">
4+
Foo
5+
</div>
6+
<div :bar="count > 5">
7+
Bar
8+
</div>
9+
</div>
10+
</template>
11+
12+
<twig-config>
13+
attributes-with-if = foo
14+
</twig-config>
15+
16+
<script>
17+
export default {
18+
props: {
19+
count: {
20+
type: Number,
21+
default: 0,
22+
},
23+
},
24+
};
25+
</script>

0 commit comments

Comments
 (0)