Skip to content

Fix style block support #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 44 additions & 6 deletions src/Compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ public function convert(): string
}

if ($styleBlocks->length) {
$this->styleBuilder->setScopedAttribute('data-v-' . md5($this->document->textContent));
foreach ($styleBlocks as $styleBlock) {
/* @var DOMElement $styleBlock */
$this->rawBlocks[] = $this->styleBuilder->compile($styleBlock);
Expand All @@ -190,6 +191,7 @@ public function convert(): string

$html = $this->addVariableBlocks($html);
$html = $this->replacePlaceholders($html);
$html = $this->replaceScopedPlaceholders($html);

$html = preg_replace('/<template>\s*(.*)\s*<\/template>/ism', '$1', $html);
$html = preg_replace('/<\/?template[^>]*?>/i', '', $html);
Expand Down Expand Up @@ -241,7 +243,7 @@ public function convertNode(DOMNode $node, int $level = 0): DOMNode
$this->stripEventHandlers($node);
$this->handleSlots($node);
$this->cleanupAttributes($node);
$this->addScopedAttribute($node);
$this->addScopedAttribute($node, $level);
}

// Registered Component
Expand Down Expand Up @@ -362,6 +364,20 @@ private function preparePropertiesForInclude(array $variables): array
$values[$name][] = $value;
}
unset($variables[$key]);
} elseif (strpos($name, 'dataV') === 0 && strlen($name) === 37) {
unset($variables[$key]);
$variables[] = new Property(
'dataScopedStyleAttribute',
'"data-v-' . strtolower(substr($name, 5)) . '"',
false
);
} elseif ($name === '__DATA_SCOPED_STYLE_ATTRIBUTE__') {
unset($variables[$key]);
$variables[] = new Property(
'dataScopedStyleAttribute',
'dataScopedStyleAttribute|default(\'\')',
false
);
}
}

Expand Down Expand Up @@ -1068,6 +1084,13 @@ public function setStyleBlockOutputType(int $outputType): Compiler
return $this;
}

public function setStyleBlockScssData(string $scssData): Compiler
{
$this->styleBuilder->setScssData($scssData);

return $this;
}

/**
* @param mixed $value
*/
Expand Down Expand Up @@ -1217,12 +1240,27 @@ private function twigRemove(DOMElement $node): bool
return false;
}

private function addScopedAttribute(DOMElement $node): void
private function addScopedAttribute(DOMElement $node, int $level): void
{
if (!$this->styleBuilder->hasScoped()) {
return;
if ($this->styleBuilder->hasScoped()) {
$scopedAttribute = $this->styleBuilder->getScopedAttribute();
$node->setAttributeNode(new DOMAttr($scopedAttribute, ''));

if ($level !== 1) {
return;
}
}
$scopedAttribute = $this->styleBuilder->getScopedAttribute();
$node->setAttributeNode(new DOMAttr($scopedAttribute, ''));

if ($this->styleBuilder->getOutputType() & StyleBuilder::STYLE_SCOPED) {
$node->setAttributeNode(new DOMAttr('__DATA_SCOPED_STYLE_ATTRIBUTE__', ''));
}
}

private function replaceScopedPlaceholders(string $html): string
{
$html = str_replace('__DATA_SCOPED_STYLE_ATTRIBUTE__=""', '{{ dataScopedStyleAttribute|default(\'\') }}', $html);
$html = preg_replace('/(data-v-[0-9a-f]{32})=""/', '$1', $html);

return $html;
}
}
26 changes: 23 additions & 3 deletions src/Utils/StyleBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use DOMElement;
use Exception;
use Ramsey\Uuid\Uuid;
use ScssPhp\ScssPhp\Compiler as ScssCompiler;

class StyleBuilder
Expand All @@ -21,6 +20,11 @@ class StyleBuilder
*/
private $outputType;

/**
* @var string
*/
private $scssData;

/**
* @var ScssCompiler|null
*/
Expand All @@ -44,16 +48,27 @@ class StyleBuilder
public function __construct()
{
$this->outputType = self::STYLE_ALL;
$this->scssData = '';
$this->scssCompiler = null;
$this->hasScoped = false;
$this->scopedAttribute = 'data-v-' . substr(md5(Uuid::uuid4()->toString()), 0, 8);
$this->scopedAttribute = '';
}

public function setOutputType(int $outputType): void
{
$this->outputType = $outputType;
}

public function getOutputType(): int
{
return $this->outputType;
}

public function setScssData(string $data): void
{
$this->scssData = $data;
}

public function compile(?DOMElement $styleElement): ?string
{
if (!$styleElement instanceof DOMElement
Expand All @@ -68,7 +83,7 @@ public function compile(?DOMElement $styleElement): ?string
if ($this->scssCompiler === null) {
$this->scssCompiler = new ScssCompiler();
}
$style = $this->scssCompiler->compile($style);
$style = $this->scssCompiler->compile($this->scssData . ' ' . $style);
}

if ($styleElement->hasAttribute('scoped')) {
Expand All @@ -84,6 +99,11 @@ public function hasScoped(): ?bool
return $this->hasScoped;
}

public function setScopedAttribute(string $scopedAttribute): void
{
$this->scopedAttribute = $scopedAttribute;
}

public function getScopedAttribute(): string
{
return $this->scopedAttribute;
Expand Down
2 changes: 2 additions & 0 deletions tests/AbstractTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Monolog\Handler\StreamHandler;
use Monolog\Logger;
use Paneon\VueToTwig\Compiler;
use Paneon\VueToTwig\Utils\StyleBuilder;
use PHPUnit\Framework\TestCase;

abstract class AbstractTestCase extends TestCase
Expand All @@ -21,6 +22,7 @@ protected function createCompiler(string $template): Compiler
{
$document = $this->createDocumentWithHtml($template);
$compiler = new Compiler($document, $this->createLogger());
$compiler->setStyleBlockOutputType(StyleBuilder::STYLE_NO);

return $compiler;
}
Expand Down
36 changes: 36 additions & 0 deletions tests/CompilerStyleBlockScopedTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Paneon\VueToTwig\Tests;

use Exception;
use Paneon\VueToTwig\Utils\StyleBuilder;

class CompilerStyleBlockScopedTest extends AbstractTestCase
{
/**
* @dataProvider dataProvider
*
* @param mixed $html
* @param mixed $expected
*
* @throws Exception
*/
public function testStyleBlock($html, $expected)
{
$compiler = $this->createCompiler($html);
$compiler->setStyleBlockOutputType(StyleBuilder::STYLE_ALL);
$compiler->registerComponent('ChildComponent', '/templates/ChildComponent.twig');

$actual = $compiler->convert();

$this->assertEqualHtml($expected, $actual);
}

/**
* @return array
*/
public function dataProvider()
{
return $this->loadFixturesFromDir('style-block-scoped');
}
}
4 changes: 2 additions & 2 deletions tests/CompilerStyleBlockTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Paneon\VueToTwig\Tests;

use Exception;
use Paneon\VueToTwig\Utils\StyleBuilder;

class CompilerStyleBlockTest extends AbstractTestCase
{
Expand All @@ -17,11 +18,10 @@ class CompilerStyleBlockTest extends AbstractTestCase
public function testStyleBlock($html, $expected)
{
$compiler = $this->createCompiler($html);
$compiler->setStyleBlockOutputType(StyleBuilder::STYLE);

$actual = $compiler->convert();

$actual = preg_replace('/data-v-[0-9a-z]{8}/', 'data-v-12345678', $actual);

$this->assertEqualHtml($expected, $actual);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<style>
.foo[data-v-a2116698cabca27b45a4db453446b8d2] {
color: red;
}
</style>
<div class="root {{ class|default('') }}" data-v-a2116698cabca27b45a4db453446b8d2 {{ dataScopedStyleAttribute|default('') }} style="{{ style|default('') }}">
<div class="foo" data-v-a2116698cabca27b45a4db453446b8d2>
{% include "/templates/ChildComponent.twig" with { 'dataScopedStyleAttribute': "data-v-a2116698cabca27b45a4db453446b8d2", 'class': "", 'style': "" } %}
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<template>
<div class="root">
<div class="foo">
<ChildComponent />
</div>
</div>
</template>

<script>
export default {
name: 'cstyle-block-scoped-with-child-binding.vue',
component: {
ChildComponent,
}
};
</script>

<style scoped>
.foo {
color: red;
}
</style>
26 changes: 26 additions & 0 deletions tests/fixtures/style-block-scoped/style-block-scoped.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<style>
.foo[data-v-6737f06d5bb113335593e128322855f1] {
color: red;
}
.bar[data-v-6737f06d5bb113335593e128322855f1],
.baz[data-v-6737f06d5bb113335593e128322855f1] {
color: blue;
}
.foo:after[data-v-6737f06d5bb113335593e128322855f1] {
display: none;
}
.root .bar[data-v-6737f06d5bb113335593e128322855f1] {
text-decoration: underline;
}
</style>
<div class="root {{ class|default('') }}" data-v-6737f06d5bb113335593e128322855f1 {{ dataScopedStyleAttribute|default('') }} style="{{ style|default('') }}">
<div class="foo" data-v-6737f06d5bb113335593e128322855f1>
foo
</div>
<div class="bar" data-v-6737f06d5bb113335593e128322855f1>
bar
</div>
<div class="baz" data-v-6737f06d5bb113335593e128322855f1>
baz
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<style>.foo[data-v-eb50964453fb1d39d2d2f020c6639c00] { color: red; } .foo__bar[data-v-eb50964453fb1d39d2d2f020c6639c00] { color: blue; } .foo__baz[data-v-eb50964453fb1d39d2d2f020c6639c00] { color: #00FF00; }</style>
<div data-v-eb50964453fb1d39d2d2f020c6639c00 {{ dataScopedStyleAttribute|default('') }} class="{{ class|default('') }}" style="{{ style|default('') }}">
<div class="foo__bar" data-v-eb50964453fb1d39d2d2f020c6639c00>
baz
</div>
</div>
6 changes: 6 additions & 0 deletions tests/fixtures/style-block-scoped/style-block.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<style> .foo { color: red; }</style>
<div {{ dataScopedStyleAttribute|default('') }} class="{{ class|default('') }}" style="{{ style|default('') }}">
<div class="foo" {{ dataScopedStyleAttribute|default('') }}>
foo
</div>
</div>
18 changes: 18 additions & 0 deletions tests/fixtures/style-block-scoped/style-block.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<div>
<div class="foo">
foo
</div>
</div>
</template>

<style>
.foo {
color: red;
}
</style>

<script>
export default {
}
</script>
8 changes: 8 additions & 0 deletions tests/fixtures/style-block-scoped/style-blocks.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<style> .foo { color: red; }</style>
<style> .bar[data-v-9d8ac5d70d06b0f0d2a21f893932dffe] { color: blue; }</style>
<style>.baz { color: #00FF00; }</style>
<div data-v-9d8ac5d70d06b0f0d2a21f893932dffe {{ dataScopedStyleAttribute|default('') }} class="{{ class|default('') }}" style="{{ style|default('') }}">
<div class="foo bar baz" data-v-9d8ac5d70d06b0f0d2a21f893932dffe>
42
</div>
</div>
26 changes: 0 additions & 26 deletions tests/fixtures/style-block/style-block-scoped.twig

This file was deleted.

6 changes: 0 additions & 6 deletions tests/fixtures/style-block/style-block-scss-scoped.twig

This file was deleted.

8 changes: 0 additions & 8 deletions tests/fixtures/style-block/style-blocks.twig

This file was deleted.