├── .github └── workflows │ └── php.yml ├── .gitignore ├── .php_cs ├── LICENSE ├── README.md ├── composer.json ├── composer.lock ├── phpcs.xml ├── phpunit.phar ├── phpunit.xml.dist ├── src ├── Compiler.php ├── Models │ ├── BasicEnum.php │ ├── Component.php │ ├── Concat.php │ ├── Data.php │ ├── Pre.php │ ├── Property.php │ ├── Replacements.php │ └── Slot.php └── Utils │ ├── NodeHelper.php │ ├── StyleBuilder.php │ └── TwigBuilder.php └── tests ├── AbstractTestCase.php ├── AttributeWithIfTest.php ├── CleanupAttributesTest.php ├── CommentNodeTest.php ├── CompilerPropsTest.php ├── CompilerStyleBlockScopedImportTest.php ├── CompilerStyleBlockScopedTest.php ├── CompilerStyleBlockTest.php ├── CompilerTest.php ├── CompilerTwigBlockTest.php ├── ConcatTest.php ├── DataTest.php ├── DataTwigRemoveTest.php ├── TextNodeTest.php ├── TwigConfigTest.php ├── VueBindingsTest.php ├── VueCloakTest.php ├── VueComponentTest.php ├── VueForTest.php ├── VueHtmlTest.php ├── VueIfTest.php ├── VueModelTest.php ├── VueOnTest.php ├── VuePreTest.php ├── VueShowTest.php ├── VueSlotTest.php ├── VueTextTest.php └── fixtures ├── concat ├── concat-typescript.twig ├── concat-typescript.vue ├── concat.twig └── concat.vue ├── data ├── data-config.twig ├── data-config.vue ├── data-typescript.twig ├── data-typescript.vue ├── data-window.twig ├── data-window.vue ├── data-with-comment.twig ├── data-with-comment.vue ├── data.twig └── data.vue ├── style-block-scoped-import ├── imports │ ├── import.scss │ └── subfolder │ │ └── import2.scss ├── style-block-scss-scoped-import.twig └── style-block-scss-scoped-import.vue ├── style-block-scoped ├── include-child-component-with-component-on-root-and-style-block-scoped.twig ├── include-child-component-with-component-on-root-and-style-block-scoped.vue ├── include-child-component-with-component-on-root.twig ├── include-child-component-with-component-on-root.vue ├── include-child-component-with-style-block-scoped.twig ├── include-child-component-with-style-block-scoped.vue ├── style-block-scoped-2.twig ├── style-block-scoped-2.vue ├── style-block-scoped-3.twig ├── style-block-scoped-3.vue ├── style-block-scoped-4.twig ├── style-block-scoped-4.vue ├── style-block-scoped-deep-2.twig ├── style-block-scoped-deep-2.vue ├── style-block-scoped-deep-3.twig ├── style-block-scoped-deep-3.vue ├── style-block-scoped-deep-4.twig ├── style-block-scoped-deep-4.vue ├── style-block-scoped-deep-with-scss-2.twig ├── style-block-scoped-deep-with-scss-2.vue ├── style-block-scoped-deep-with-scss.twig ├── style-block-scoped-deep-with-scss.vue ├── style-block-scoped-deep.twig ├── style-block-scoped-deep.vue ├── style-block-scoped-v-deep-with-scss.twig ├── style-block-scoped-v-deep-with-scss.vue ├── style-block-scoped-v-deep.twig ├── style-block-scoped-v-deep.vue ├── style-block-scoped-with-child-binding.twig ├── style-block-scoped-with-child-binding.vue ├── style-block-scoped.twig ├── style-block-scoped.vue ├── style-block-scss-scoped.twig ├── style-block-scss-scoped.vue ├── style-block.twig ├── style-block.vue ├── style-blocks.twig └── style-blocks.vue ├── style-block ├── style-block-scss-error-handling.twig ├── style-block-scss-error-handling.vue ├── style-block-scss.twig ├── style-block-scss.vue ├── style-block.twig └── style-block.vue ├── twig-block ├── twig-block.twig └── twig-block.vue ├── twig-config ├── attribute-if-2.twig ├── attribute-if-2.vue ├── attribute-if.twig └── attribute-if.vue ├── vue-bind ├── binding-with-array-with-object-binding-2.twig ├── binding-with-array-with-object-binding-2.vue ├── binding-with-array-with-object-binding-3.twig ├── binding-with-array-with-object-binding-3.vue ├── binding-with-array-with-object-binding.twig ├── binding-with-array-with-object-binding.vue ├── binding-with-array-with-template-string.twig ├── binding-with-array-with-template-string.vue ├── binding-with-array.twig ├── binding-with-array.vue ├── binding-with-template-string-2.twig ├── binding-with-template-string-2.vue ├── binding-with-template-string-3.twig ├── binding-with-template-string-3.vue ├── binding-with-template-string-4.twig ├── binding-with-template-string-4.vue ├── binding-with-template-string.twig ├── binding-with-template-string.vue ├── bindings-src.twig ├── bindings-src.vue ├── bindings-style.twig ├── bindings-style.vue ├── bindings-with-encoded-attributes.twig ├── bindings-with-encoded-attributes.vue ├── bindings-with-filter.twig ├── bindings-with-filter.vue ├── bindings.twig ├── bindings.vue ├── double-attribute-binding.twig └── double-attribute-binding.vue ├── vue-component ├── component-with-child-binding-2.twig ├── component-with-child-binding-2.vue ├── component-with-child-binding-3.twig ├── component-with-child-binding-3.vue ├── component-with-child-binding-4.twig ├── component-with-child-binding-4.vue ├── component-with-child-binding.twig ├── component-with-child-binding.vue ├── component-with-child.twig ├── component-with-child.vue ├── component-with-for.twig ├── component-with-for.vue ├── component-with-if.twig ├── component-with-if.vue ├── component-with-inline-condition-prop.twig ├── component-with-inline-condition-prop.vue ├── component-with-prop.twig ├── component-with-prop.vue ├── component-with-v-bind-props.twig ├── component-with-v-bind-props.vue ├── component-with-v-bind.twig └── component-with-v-bind.vue ├── vue-for ├── replaces-v-for-in.twig ├── replaces-v-for-in.vue ├── replaces-v-for.twig └── replaces-v-for.vue ├── vue-html ├── html.twig └── html.vue ├── vue-if ├── if-data-twig.twig ├── if-data-twig.vue ├── if-elseif-else-with-nested-if.twig ├── if-elseif-else-with-nested-if.vue ├── if-elseif-else.twig ├── if-elseif-else.vue ├── if-strict-equal.twig ├── if-strict-equal.vue ├── if-with-statement.twig ├── if-with-statement.vue ├── if-with-template.twig ├── if-with-template.vue ├── multiple-if-occurrences.twig ├── multiple-if-occurrences.vue ├── simple-if-2.twig ├── simple-if-2.vue ├── single-node.twig └── single-node.vue ├── vue-model ├── model-input-checkbox.twig ├── model-input-checkbox.vue ├── model-input-radio.twig ├── model-input-radio.vue ├── model-input.twig ├── model-input.vue ├── model-select-multiple-typescript.twig ├── model-select-multiple-typescript.vue ├── model-select-multiple.twig ├── model-select-multiple.vue ├── model-select-value.twig ├── model-select-value.vue ├── model-select.twig ├── model-select.vue ├── model-textarea.twig └── model-textarea.vue ├── vue-on ├── removes-event-bindings.twig └── removes-event-bindings.vue ├── vue-props ├── binding-props-typescript-default.twig ├── binding-props-typescript-default.vue ├── binding-props.twig └── binding-props.vue ├── vue-show ├── single-node.twig ├── single-node.vue ├── with-v-if.twig └── with-v-if.vue ├── vue-slot ├── child-component-in-slot.twig ├── child-component-in-slot.vue ├── component-has-default-slot-with-fallback-value.twig ├── component-has-default-slot-with-fallback-value.vue ├── component-has-default-slot.twig ├── component-has-default-slot.vue ├── component-has-named-slots-2.twig ├── component-has-named-slots-2.vue ├── component-has-named-slots-with-fallback-value.twig ├── component-has-named-slots-with-fallback-value.vue ├── component-has-named-slots.twig ├── component-has-named-slots.vue ├── component-has-two-default-slots-with-fallback-value.twig ├── component-has-two-default-slots-with-fallback-value.vue ├── include-child-component-with-default-slot-and-props.twig ├── include-child-component-with-default-slot-and-props.vue ├── include-child-component-with-default-slot.twig ├── include-child-component-with-default-slot.vue ├── include-child-component-with-named-default-slot.twig ├── include-child-component-with-named-default-slot.vue ├── include-child-component-with-named-slots-2.twig ├── include-child-component-with-named-slots-2.vue ├── include-child-component-with-named-slots.twig ├── include-child-component-with-named-slots.vue ├── include-child-component-without-default-slot.twig └── include-child-component-without-default-slot.vue └── vue-text ├── text.twig └── text.vue /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: PHP Composer 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Setup PHP 8.0 17 | uses: shivammathur/setup-php@v2 18 | with: 19 | php-version: 8.0 20 | 21 | - name: Validate composer.json and composer.lock 22 | run: composer validate 23 | 24 | - name: Cache Composer packages 25 | id: composer-cache 26 | uses: actions/cache@v2 27 | with: 28 | path: vendor 29 | key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }} 30 | restore-keys: | 31 | ${{ runner.os }}-php- 32 | 33 | - name: Install dependencies 34 | if: steps.composer-cache.outputs.cache-hit != 'true' 35 | run: composer install --prefer-dist --no-progress --no-suggest 36 | 37 | - name: Run PHPUnit 38 | run: composer run phpunit 39 | 40 | - name: Run PHPStan 41 | run: composer run phpstan 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | /var 3 | 4 | # Managed by Composer 5 | /bin/* 6 | !bin/console 7 | /vendor/ 8 | 9 | # PHP CS Fixer 10 | .php_cs.cache 11 | 12 | node_modules 13 | .phpunit.result.cache 14 | -------------------------------------------------------------------------------- /.php_cs: -------------------------------------------------------------------------------- 1 | in([ 5 | __DIR__ . DIRECTORY_SEPARATOR . 'src', 6 | __DIR__ . DIRECTORY_SEPARATOR . 'tests', 7 | ]) 8 | ->name('*.php') 9 | ; 10 | 11 | return PhpCsFixer\Config::create() 12 | ->setRiskyAllowed(true) 13 | ->setRules([ 14 | '@PHP56Migration' => true, 15 | '@Symfony' => true, 16 | 'concat_space' => ['spacing' => 'one'], 17 | 'yoda_style' => null, 18 | ]) 19 | ->setFinder($finder) 20 | ; 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Alexander Pape 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # php-vue-to-twig 2 | 3 | ![CI](https://github.com/Paneon/php-vue-to-twig/workflows/PHP%20Composer/badge.svg) 4 | 5 | Compile vue files to twig templates with PHP 6 | 7 | ## Directives 8 | 9 | |Directive|Implemented| 10 | |---------|:---------:| 11 | |v-text|:white_check_mark:| 12 | |v-html|:white_check_mark:| 13 | |v-show|:white_check_mark:| 14 | |v-if|:white_check_mark:| 15 | |v-else|:white_check_mark:| 16 | |v-else-if|:white_check_mark:| 17 | |v-for|:white_check_mark:| 18 | |v-on|:white_check_mark:| 19 | |v-bind|partially working| 20 | |v-bind:style|:white_check_mark:| 21 | |v-bind:class|:white_check_mark:| 22 | |v-model|partially working| 23 | |v-pre|:white_check_mark:| 24 | |v-cloak|:white_check_mark:| 25 | |v-once|:white_check_mark:| 26 | 27 | 28 | ## Other Functionalities 29 | 30 | |Functionality|Implemented| 31 | |:------------|:---------:| 32 | |Slots|partially working| 33 | |Components|:white_check_mark:| 34 | |Filters|| 35 | 36 | 37 | ## Limitations 38 | 39 | It's difficult to interpret JavaScript language features and translate them into twig. 40 | 41 | For example, string concatenation within attribute binding is not currently working properly: :no_entry_sign: 42 | 43 | This example works: 44 | 45 | ```vue 46 | 49 | 50 | 60 | ``` 61 | 62 | ```twig 63 |
64 | ``` 65 | 66 | But this example doesn't work correct: 67 | 68 | ```vue 69 | 72 | 73 | 83 | ``` 84 | 85 | ```twig 86 |
87 | ``` -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "paneon/php-vue-to-twig", 3 | "description": "", 4 | "type": "library", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Alexander Pape", 9 | "email": "a.pape@paneon.de" 10 | } 11 | ], 12 | "require": { 13 | "php": "^7.3|^8.0", 14 | "ext-dom": "*", 15 | "ext-libxml": "*", 16 | "scssphp/scssphp": "^1.9", 17 | "squizlabs/php_codesniffer": "^3.3", 18 | "ramsey/uuid": "^3.8" 19 | }, 20 | "autoload": { 21 | "psr-4": { 22 | "Paneon\\VueToTwig\\": "src" 23 | } 24 | }, 25 | "autoload-dev": { 26 | "psr-4": { 27 | "Paneon\\VueToTwig\\": "src", 28 | "Paneon\\VueToTwig\\Tests\\": "tests" 29 | }, 30 | "files": [ 31 | "vendor/autoload.php" 32 | ] 33 | }, 34 | "require-dev": { 35 | "ext-simplexml": "*", 36 | "phpunit/phpunit": "^9", 37 | "monolog/monolog": "^1.24", 38 | "phpstan/phpstan": "^0.12", 39 | "friendsofphp/php-cs-fixer": "^2.16" 40 | }, 41 | "scripts": { 42 | "cs:fix": "phpcbf --standard=phpcs.xml", 43 | "cs:check": "phpcs --standard=phpcs.xml --colors -ps", 44 | "phpstan": "@php vendor/bin/phpstan analyse src --level 6", 45 | "phpunit": "@php vendor/phpunit/phpunit/phpunit" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | error 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | ./tests/*/*Test.php 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /phpunit.phar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Paneon/php-vue-to-twig/0ccc87cba8a0a532329f17ae61131a2db51fee36/phpunit.phar -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | tests/ 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/Models/BasicEnum.php: -------------------------------------------------------------------------------- 1 | getConstants(); 29 | } 30 | 31 | return self::$constCacheArray[$calledClass]; 32 | } 33 | 34 | /** 35 | * @return bool|false|int|string 36 | */ 37 | public static function getNameForValue(string $value) 38 | { 39 | try { 40 | $constants = self::getConstants(); 41 | } catch (ReflectionException $e) { 42 | return false; 43 | } 44 | 45 | return array_search($value, $constants); 46 | } 47 | 48 | public static function isValidName(string $name, bool $strict = false): bool 49 | { 50 | try { 51 | $constants = self::getConstants(); 52 | } catch (ReflectionException $e) { 53 | return false; 54 | } 55 | 56 | if ($strict) { 57 | return array_key_exists($name, $constants); 58 | } 59 | 60 | $keys = array_map('strtolower', array_keys($constants)); 61 | 62 | return in_array(strtolower($name), $keys); 63 | } 64 | 65 | /** 66 | * @param mixed $value 67 | */ 68 | public static function isValidValue($value): bool 69 | { 70 | try { 71 | $values = array_values(self::getConstants()); 72 | 73 | return in_array($value, $values, $strict = true); 74 | } catch (ReflectionException $e) { 75 | return false; 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/Models/Component.php: -------------------------------------------------------------------------------- 1 | name = $name; 42 | $this->path = $path; 43 | } 44 | 45 | public function getName(): string 46 | { 47 | return $this->name; 48 | } 49 | 50 | public function getPath(): string 51 | { 52 | return $this->path; 53 | } 54 | 55 | /** 56 | * @return Property[] 57 | */ 58 | public function getProperties(): array 59 | { 60 | return $this->properties; 61 | } 62 | 63 | public function registerComponents(string $name, string $path): void 64 | { 65 | $this->components[$name] = $path; 66 | } 67 | 68 | public function addProperty(string $name, string $value, bool $isBinding = false): void 69 | { 70 | $this->properties[] = new Property( 71 | $this->kebabToCamelCase($name), 72 | $value, 73 | $isBinding 74 | ); 75 | } 76 | 77 | /** 78 | * @throws Exception 79 | */ 80 | public function addSlot(string $name, string $value): Slot 81 | { 82 | $this->slots[$name] = new Slot($name, $value); 83 | 84 | $this->properties[] = new Property( 85 | $this->slots[$name]->getSlotPropertyName(), 86 | $this->slots[$name]->getSlotValueName(), 87 | true 88 | ); 89 | 90 | return $this->slots[$name]; 91 | } 92 | 93 | public function addEmptyDefaultSlot(): void 94 | { 95 | $this->properties[] = new Property(Slot::SLOT_PREFIX . Slot::SLOT_DEFAULT_NAME, '""', false); 96 | } 97 | 98 | public function kebabToCamelCase(string $string, bool $capitalizeFirstCharacter = false): string 99 | { 100 | $str = str_replace('-', '', ucwords($string, '-')); 101 | 102 | if (!$capitalizeFirstCharacter) { 103 | $str = lcfirst($str); 104 | } 105 | 106 | return $str; 107 | } 108 | 109 | public function hasSlots(): bool 110 | { 111 | return !empty($this->slots); 112 | } 113 | 114 | public function hasSlot(string $name): bool 115 | { 116 | return !empty($this->slots[$name]); 117 | } 118 | 119 | /** 120 | * @return Slot[] 121 | */ 122 | public function getSlots(): array 123 | { 124 | return $this->slots; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/Models/Concat.php: -------------------------------------------------------------------------------- 1 | uuid = Uuid::uuid4()->toString(); 37 | $this->value = $value; 38 | $this->isNumeric = $isNumeric; 39 | } 40 | 41 | public function getValue(): string 42 | { 43 | return $this->value; 44 | } 45 | 46 | public function setValue(string $value): void 47 | { 48 | $this->value = $value; 49 | } 50 | 51 | public function isNumeric(): bool 52 | { 53 | return $this->isNumeric; 54 | } 55 | 56 | public function setIsNumeric(bool $isNumeric): void 57 | { 58 | $this->isNumeric = $isNumeric; 59 | } 60 | 61 | public function getConcatContentVariableString(): string 62 | { 63 | return '__CONCAT_' . str_replace('-', '_', $this->uuid) . '__'; 64 | } 65 | 66 | public function getUuid(): string 67 | { 68 | return $this->uuid; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/Models/Data.php: -------------------------------------------------------------------------------- 1 | name = $name; 25 | if (substr_count($value, 'window.')) { 26 | $value = 'null'; 27 | } 28 | $this->value = $value; 29 | } 30 | 31 | public function getName(): string 32 | { 33 | return $this->name; 34 | } 35 | 36 | public function getValue(): string 37 | { 38 | return $this->value; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Models/Pre.php: -------------------------------------------------------------------------------- 1 | uuid = Uuid::uuid4()->toString(); 32 | $this->value = $value; 33 | } 34 | 35 | public function getValue(): string 36 | { 37 | return $this->value; 38 | } 39 | 40 | public function setValue(string $value): void 41 | { 42 | $this->value = $value; 43 | } 44 | 45 | public function getPreContentVariableString(): string 46 | { 47 | return '__PRE_' . str_replace('-', '_', $this->uuid) . '__'; 48 | } 49 | 50 | public function getUuid(): string 51 | { 52 | return $this->uuid; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Models/Property.php: -------------------------------------------------------------------------------- 1 | name = $name; 45 | $this->value = $value; 46 | $this->isBinding = $isBinding; 47 | $this->isRequired = false; 48 | $this->default = null; 49 | } 50 | 51 | public function getName(): string 52 | { 53 | return $this->name; 54 | } 55 | 56 | public function getValue(): string 57 | { 58 | return $this->value; 59 | } 60 | 61 | public function setValue(string $value): Property 62 | { 63 | $this->value = $value; 64 | return $this; 65 | } 66 | 67 | public function isBinding(): bool 68 | { 69 | return $this->isBinding; 70 | } 71 | 72 | public function isRequired(): bool 73 | { 74 | return $this->isRequired; 75 | } 76 | 77 | public function setIsRequired(bool $isRequired): void 78 | { 79 | $this->isRequired = $isRequired; 80 | } 81 | 82 | /** 83 | * @return string|null 84 | */ 85 | public function getDefault() 86 | { 87 | return $this->default; 88 | } 89 | 90 | public function hasDefault(): bool 91 | { 92 | return $this->default !== null; 93 | } 94 | 95 | public function setDefault(string $default): void 96 | { 97 | $this->default = $default; 98 | } 99 | 100 | public function getType(): ?string 101 | { 102 | return $this->type; 103 | } 104 | 105 | public function setType(?string $type): void 106 | { 107 | $this->type = $type; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Models/Replacements.php: -------------------------------------------------------------------------------- 1 | '; 15 | public const SMALLER = '<'; 16 | public const AMPERSAND = '&'; 17 | public const PIPE = '|'; 18 | public const ATTRIBUTE_NAME_HREF = 'href'; 19 | public const ATTRIBUTE_NAME_ACTION = 'action'; 20 | public const ATTRIBUTE_NAME_SRC = 'src'; 21 | public const ATTRIBUTE_NAME_A_NAME = 'name'; 22 | 23 | /** 24 | * Removes all instances of replacements from target. 25 | * 26 | * @throws ReflectionException 27 | */ 28 | public static function sanitize(string $target): string 29 | { 30 | foreach (Replacements::getConstants() as $constant => $value) { 31 | $target = str_replace($value, Replacements::getSanitizedConstant($constant), $target); 32 | } 33 | 34 | return $target; 35 | } 36 | 37 | public static function getSanitizedConstant(string $constant): string 38 | { 39 | return '__' . $constant . '__'; 40 | } 41 | 42 | /** 43 | * Removes all instances of one specified replacement from target. 44 | */ 45 | public static function sanitizeSingleReplacement(string $target, string $singleReplacement): string 46 | { 47 | if (!Replacements::isValidValue($singleReplacement)) { 48 | throw new InvalidArgumentException(sprintf('%s is not a valid Replacement value.', $singleReplacement)); 49 | } 50 | 51 | $constantName = Replacements::getNameForValue($singleReplacement); 52 | 53 | return str_replace( 54 | $singleReplacement, 55 | Replacements::getSanitizedConstant($constantName), 56 | $target 57 | ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Models/Slot.php: -------------------------------------------------------------------------------- 1 | uuid = Uuid::uuid4()->toString(); 44 | $this->name = $name; 45 | $this->value = $value; 46 | } 47 | 48 | public function getName(): string 49 | { 50 | return $this->name; 51 | } 52 | 53 | public function getValue(): string 54 | { 55 | return $this->value; 56 | } 57 | 58 | public function getSlotPropertyName(): string 59 | { 60 | return self::SLOT_PREFIX . $this->name; 61 | } 62 | 63 | public function getSlotValueName(): string 64 | { 65 | return self::SLOT_PREFIX . $this->name . self::SLOT_VALUE_SUFFIX; 66 | } 67 | 68 | public function getSlotContentVariableString(): string 69 | { 70 | return '__SLOT_' . $this->uuid . '__'; 71 | } 72 | 73 | public function getUuid(): string 74 | { 75 | return $this->uuid; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Utils/NodeHelper.php: -------------------------------------------------------------------------------- 1 | removeNode($node); 18 | } 19 | } 20 | 21 | public function removeNode(DOMNode $node): void 22 | { 23 | $node->parentNode->removeChild($node); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/Utils/StyleBuilder.php: -------------------------------------------------------------------------------- 1 | outputType = self::STYLE_ALL; 52 | $this->scssData = ''; 53 | $this->scssCompiler = null; 54 | $this->hasScoped = false; 55 | $this->scopedAttribute = ''; 56 | } 57 | 58 | public function setOutputType(int $outputType): void 59 | { 60 | $this->outputType = $outputType; 61 | } 62 | 63 | public function getOutputType(): int 64 | { 65 | return $this->outputType; 66 | } 67 | 68 | public function setScssData(string $data): void 69 | { 70 | $this->scssData = $data; 71 | } 72 | 73 | public function compile(?DOMElement $styleElement, ?string $path = null): ?string 74 | { 75 | if (!$styleElement instanceof DOMElement 76 | || ($styleElement->hasAttribute('scoped') && !($this->outputType & self::STYLE_SCOPED)) 77 | || (!$styleElement->hasAttribute('scoped') && !($this->outputType & self::STYLE))) { 78 | return null; 79 | } 80 | 81 | $style = preg_replace('/ *(?:\/deep\/|>>>)/', '::v-deep', $styleElement->textContent); 82 | 83 | if ($styleElement->hasAttribute('lang') && $styleElement->getAttribute('lang') === 'scss') { 84 | if ($this->scssCompiler === null) { 85 | $this->scssCompiler = new ScssCompiler(); 86 | } 87 | try { 88 | $style = $this->scssCompiler->compileString($this->scssData . ' ' . $style, $path)->getCss(); 89 | } catch (SassException $e) { 90 | $style = "\n/* Warning: " . $e->getMessage() . " */\n"; 91 | } 92 | } 93 | 94 | if ($styleElement->hasAttribute('scoped')) { 95 | $this->hasScoped = true; 96 | preg_match_all( 97 | '/(?:^|\s)\s*[^@\s][^{}]+?\s*[{]/i', 98 | $style, 99 | $matches, 100 | PREG_SET_ORDER 101 | ); 102 | foreach ($matches as $match) { 103 | $selectors = explode(',', $match[0]); 104 | $selectorsCount = count($selectors); 105 | $count = 0; 106 | foreach ($selectors as $selector) { 107 | if (++$count < $selectorsCount) { 108 | $selector .= ','; 109 | } 110 | if (preg_match('/^[\s}]*::v-deep/', $selector)) { 111 | $style = str_replace( 112 | $selector, 113 | str_replace('::v-deep', '[' . $this->scopedAttribute . ']', $selector), 114 | $style 115 | ); 116 | } else { 117 | $regex = strpos($selector, '::v-deep') !== false 118 | ? '/((?:^|\s)\s*[^@\s][a-z0-9-_]+?)((?::{1,2}[a-z-]+)?\s*)(?:::v-deep)/i' 119 | : '/((?:^|\s)\s*[^@\s][a-z0-9-_]+?)((?::{1,2}[a-z-]+)?\s*(?:[,{]|$))/i'; 120 | $style = str_replace( 121 | $selector, 122 | preg_replace($regex, '$1[' . $this->scopedAttribute . ']$2', $selector), 123 | $style 124 | ); 125 | } 126 | } 127 | } 128 | } 129 | 130 | return ''; 131 | } 132 | 133 | public function hasScoped(): ?bool 134 | { 135 | return $this->hasScoped; 136 | } 137 | 138 | public function setScopedAttribute(string $scopedAttribute): void 139 | { 140 | $this->scopedAttribute = $scopedAttribute; 141 | } 142 | 143 | public function getScopedAttribute(): string 144 | { 145 | return $this->scopedAttribute; 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /src/Utils/TwigBuilder.php: -------------------------------------------------------------------------------- 1 | options = array_merge( 36 | [ 37 | 'tag_comment' => ['{#', '#}'], 38 | 'tag_block' => ['{%', '%}'], 39 | 'tag_variable' => ['{{', '}}'], 40 | 'whitespace_trim' => '-', 41 | 'interpolation' => ['#{', '}'], 42 | ], 43 | $options 44 | ); 45 | } 46 | 47 | public function createSet(string $name): string 48 | { 49 | return $this->createBlock('set ' . $name); 50 | } 51 | 52 | public function closeSet(): string 53 | { 54 | return $this->createBlock('endset'); 55 | } 56 | 57 | public function createVariable(string $name, string $assignment): string 58 | { 59 | return $this->createBlock('set ' . $name . ' = ' . $assignment); 60 | } 61 | 62 | public function createDefaultForVariable(string $name, string $defaultValue): string 63 | { 64 | return $this->createBlock('set ' . $name . ' = ' . $name . '|default(' . $defaultValue . ')'); 65 | } 66 | 67 | public function createMultilineVariable(string $name, string $assignment): string 68 | { 69 | return $this->createBlock('set ' . $name) 70 | . $assignment 71 | . $this->createBlock('endset'); 72 | } 73 | 74 | /** 75 | * @throws ReflectionException 76 | */ 77 | public function createIf(string $condition): string 78 | { 79 | $condition = $this->refactorCondition($condition); 80 | 81 | return $this->createBlock('if ' . $condition); 82 | } 83 | 84 | /** 85 | * @throws ReflectionException 86 | */ 87 | public function createElseIf(string $condition): string 88 | { 89 | $condition = $this->refactorCondition($condition); 90 | 91 | return $this->createBlock('elseif ' . $condition); 92 | } 93 | 94 | public function createElse(): string 95 | { 96 | return $this->createBlock('else'); 97 | } 98 | 99 | public function createEndIf(): string 100 | { 101 | return $this->createBlock('endif'); 102 | } 103 | 104 | public function createForItemInList(string $item, string $list): string 105 | { 106 | return $this->createBlock('for ' . $item . ' in ' . $list); 107 | } 108 | 109 | public function createForKeyInList(string $key, string $list): string 110 | { 111 | return $this->createBlock('for ' . $key . ' in ' . $list); 112 | } 113 | 114 | public function createFor(string $list, ?string $item = null, ?string $key = null): ?string 115 | { 116 | if ($item !== null && $key !== null) { 117 | return $this->createBlock('for ' . $key . ', ' . $item . ' in ' . $list); 118 | } elseif ($item !== null) { 119 | return $this->createForItemInList($item, $list); 120 | } elseif ($key !== null) { 121 | return $this->createForKeyInList($key, $list); 122 | } 123 | 124 | return null; 125 | } 126 | 127 | public function createEndFor(): string 128 | { 129 | return $this->createBlock('endfor'); 130 | } 131 | 132 | public function createComment(string $comment): string 133 | { 134 | return $this->options['tag_comment'][self::OPEN] . ' ' . $comment . ' ' . $this->options['tag_comment'][self::CLOSE]; 135 | } 136 | 137 | /** 138 | * @param string[] $comments 139 | */ 140 | public function createMultilineComment(array $comments): string 141 | { 142 | return $this->options['tag_comment'][self::OPEN] . ' ' . implode( 143 | "\n", 144 | $comments 145 | ) . ' ' . $this->options['tag_comment'][self::CLOSE]; 146 | } 147 | 148 | public function createBlock(string $content): string 149 | { 150 | return "\n" . $this->options['tag_block'][self::OPEN] . ' ' . $content . ' ' . $this->options['tag_block'][self::CLOSE]; 151 | } 152 | 153 | /** 154 | * @param Property[] $variables 155 | */ 156 | public function createIncludePartial(string $partialPath, array $variables = [], ?string $vBind = null): string 157 | { 158 | $serializedProperties = $this->serializeComponentProperties($variables); 159 | 160 | $content = 'include "' . $partialPath . '" with ' . $serializedProperties; 161 | 162 | if ($vBind) { 163 | $content .= '|merge(' . trim($vBind, '"') . ')'; 164 | } 165 | 166 | return $this->createBlock($content); 167 | } 168 | 169 | /** 170 | * @param Property[] $properties 171 | */ 172 | public function serializeComponentProperties(array $properties): string 173 | { 174 | $props = []; 175 | 176 | /** @var Property $property */ 177 | foreach ($properties as $property) { 178 | if ($property->getName() === 'key') { 179 | continue; 180 | } 181 | 182 | $props[] = '\'' . $property->getName() . '\'' . ': ' . $property->getValue(); 183 | } 184 | 185 | return '{ ' . implode(', ', $props) . ' }'; 186 | } 187 | 188 | public function sanitizeAttributeValue(string $value): string 189 | { 190 | $value = Replacements::sanitizeSingleReplacement($value, Replacements::PIPE); 191 | 192 | return $value; 193 | } 194 | 195 | /** 196 | * @throws ReflectionException 197 | */ 198 | public function refactorCondition(string $condition): string 199 | { 200 | $refactoredCondition = ''; 201 | $charsCount = mb_strlen($condition, 'UTF-8'); 202 | $quoteChar = null; 203 | $lastChar = null; 204 | $buffer = ''; 205 | 206 | for ($i = 0; $i < $charsCount; ++$i) { 207 | $char = mb_substr($condition, $i, 1, 'UTF-8'); 208 | if ($quoteChar === null && ($char === '"' || $char === '\'')) { 209 | $quoteChar = $char; 210 | if ($buffer !== '') { 211 | $refactoredCondition .= $this->refactorConditionPart($buffer); 212 | $buffer = ''; 213 | } 214 | $refactoredCondition .= $char; 215 | } elseif ($quoteChar === $char && $lastChar !== '\\') { 216 | $quoteChar = null; 217 | $refactoredCondition .= $char; 218 | } else { 219 | if ($quoteChar === null) { 220 | $buffer .= $char; 221 | } else { 222 | $refactoredCondition .= $char; 223 | } 224 | } 225 | $lastChar = $char; 226 | } 227 | if ($buffer !== '') { 228 | $refactoredCondition .= $this->refactorConditionPart($buffer); 229 | } 230 | 231 | return $refactoredCondition; 232 | } 233 | 234 | /** 235 | * @throws ReflectionException 236 | */ 237 | private function refactorConditionPart(string $condition): string 238 | { 239 | $condition = str_replace('===', '==', $condition); 240 | $condition = str_replace('!==', '!=', $condition); 241 | $condition = str_replace('&&', 'and', $condition); 242 | $condition = str_replace('||', 'or', $condition); 243 | $condition = preg_replace('/!([^=])/', 'not $1', $condition); 244 | $condition = str_replace('.length', '|length', $condition); 245 | $condition = str_replace('.trim', '|trim', $condition); 246 | 247 | foreach (Replacements::getConstants() as $constant => $value) { 248 | $condition = str_replace($value, Replacements::getSanitizedConstant($constant), $condition); 249 | } 250 | 251 | return $condition; 252 | } 253 | 254 | /** 255 | * @throws ReflectionException 256 | */ 257 | public function refactorTextNode(string $content): string 258 | { 259 | $refactoredContent = ''; 260 | $charsCount = mb_strlen($content, 'UTF-8'); 261 | $open = false; 262 | $lastChar = null; 263 | $quoteChar = null; 264 | $buffer = ''; 265 | 266 | for ($i = 0; $i < $charsCount; ++$i) { 267 | $char = mb_substr($content, $i, 1, 'UTF-8'); 268 | if ($open === false) { 269 | $refactoredContent .= $char; 270 | if ($char === '{' && $lastChar === '{') { 271 | $open = true; 272 | } 273 | } else { 274 | $buffer .= $char; 275 | if ($quoteChar === null && ($char === '"' || $char === '\'')) { 276 | $quoteChar = $char; 277 | } elseif ($quoteChar === $char && $lastChar !== '\\') { 278 | $quoteChar = null; 279 | } 280 | if ($quoteChar === null && $char === '}' && $lastChar === '}') { 281 | $open = false; 282 | $buffer = $this->convertTemplateString(trim($buffer, '}')); 283 | $refactoredContent .= $this->refactorCondition($buffer) . '}}'; 284 | $buffer = ''; 285 | } 286 | } 287 | $lastChar = $char; 288 | } 289 | 290 | return $refactoredContent; 291 | } 292 | 293 | private function convertTemplateString(string $content): string 294 | { 295 | if (preg_match_all('/`([^`]+)`/', $content, $matches, PREG_SET_ORDER)) { 296 | foreach ($matches as $match) { 297 | $match[1] = str_replace('${', '\' ~ ', $match[1]); 298 | $match[1] = str_replace('}', ' ~ \'', $match[1]); 299 | $content = str_replace($match[0], '\'' . $match[1] . '\'', $content); 300 | } 301 | } 302 | 303 | return $content; 304 | } 305 | 306 | public function createVariableOutput(string $varName, ?string $fallbackVariableName = null): string 307 | { 308 | if ($fallbackVariableName) { 309 | return '{{ ' . $varName . '|default(' . $fallbackVariableName . ') }}'; 310 | } 311 | 312 | return '{{ ' . $varName . '|default(\'\') }}'; 313 | } 314 | 315 | public function prepareBindingOutput(string $value, bool $twigOutput = true): string 316 | { 317 | $open = Replacements::getSanitizedConstant('DOUBLE_CURLY_OPEN'); 318 | $close = Replacements::getSanitizedConstant('DOUBLE_CURLY_CLOSE'); 319 | 320 | if (!$twigOutput) { 321 | $open = '('; 322 | $close = ')'; 323 | } 324 | 325 | return $open . ' ' . $value . ' ' . $close; 326 | } 327 | 328 | /** 329 | * @param Property[] $properties 330 | * 331 | * @throws Exception 332 | */ 333 | public function concatConvertHandler(string $content, array $properties): string 334 | { 335 | preg_match_all('/{{(.*?)}}/sm', $content, $outputTerms); 336 | foreach ($outputTerms[1] as $outputTerm) { 337 | $oldOutputTerm = $outputTerm; 338 | 339 | while (preg_match('/\(([^()]*)\)/', $outputTerm, $chambersTerm)) { 340 | $outputTerm = str_replace( 341 | '(' . $chambersTerm[1] . ')', 342 | $this->convertConcat($chambersTerm[1], $properties), 343 | $outputTerm 344 | ); 345 | } 346 | 347 | $concat = $this->replaceConcatCharacter($outputTerm, $properties); 348 | $newOutputTerm = $concat->getValue() ?? ''; 349 | 350 | while (preg_match_all(Concat::CONCAT_REGEX, $newOutputTerm, $chambersTerms)) { 351 | foreach ($chambersTerms[0] as $chambersTerm) { 352 | $newOutputTerm = str_replace( 353 | $chambersTerm, 354 | $this->concat[$chambersTerm]->getValue(), 355 | $newOutputTerm 356 | ); 357 | } 358 | } 359 | 360 | $content = str_replace('{{' . $oldOutputTerm . '}}', '{{' . $newOutputTerm . '}}', $content); 361 | 362 | $this->concat = []; 363 | } 364 | 365 | return $content; 366 | } 367 | 368 | /** 369 | * @param Property[] $properties 370 | * 371 | * @throws Exception 372 | */ 373 | private function convertConcat(string $content, array $properties): string 374 | { 375 | $concat = $this->replaceConcatCharacter($content, $properties); 376 | 377 | $concat->setValue('(' . $concat->getValue() . ')'); 378 | 379 | $concatId = $concat->getConcatContentVariableString(); 380 | $this->concat[$concatId] = $concat; 381 | 382 | return $concatId; 383 | } 384 | 385 | /** 386 | * @param Property[] $properties 387 | * 388 | * @throws Exception 389 | */ 390 | private function replaceConcatCharacter(string $content, array $properties): Concat 391 | { 392 | $parts = explode('+', $content); 393 | $isNumericConcat = true; 394 | 395 | foreach ($parts as $part) { 396 | $isNumericConcat = $isNumericConcat && $this->isNumeric($part, $properties); 397 | } 398 | 399 | return new Concat( 400 | implode($isNumericConcat ? '+' : '~', $parts), 401 | $isNumericConcat 402 | ); 403 | } 404 | 405 | /** 406 | * @param Property[] $properties 407 | */ 408 | private function isNumeric(string $value, array $properties): bool 409 | { 410 | $value = trim($value); 411 | 412 | foreach ($properties as $property) { 413 | if (strtolower($property->getName()) === strtolower($value)) { 414 | return $property->getType() && strtolower($property->getType()) === 'number'; 415 | } 416 | } 417 | 418 | if (isset($this->concat[$value])) { 419 | return $this->concat[$value]->isNumeric(); 420 | } 421 | 422 | $mathematicsParts = preg_split('/[-*\/%]+/', $value); 423 | if (count($mathematicsParts) > 1) { 424 | $isNumeric = true; 425 | foreach ($mathematicsParts as $mathematicsPart) { 426 | $isNumeric = $isNumeric && $this->isNumeric($mathematicsPart, $properties); 427 | } 428 | 429 | return $isNumeric; 430 | } 431 | 432 | return is_numeric($value); 433 | } 434 | } 435 | -------------------------------------------------------------------------------- /tests/AbstractTestCase.php: -------------------------------------------------------------------------------- 1 | createDocumentWithHtml($template); 24 | $compiler = new Compiler($document, $this->createLogger()); 25 | $compiler->setStyleBlockOutputType(StyleBuilder::STYLE_NO); 26 | 27 | return $compiler; 28 | } 29 | 30 | /** 31 | * @throws Exception 32 | */ 33 | protected function createLogger(): Logger 34 | { 35 | $logger = new Logger('test'); 36 | $logger->pushHandler(new StreamHandler(__DIR__ . '/../var/dev/test.log')); 37 | 38 | return $logger; 39 | } 40 | 41 | /** 42 | * @param $expected 43 | * @param $actual 44 | */ 45 | protected function assertEqualHtml($expected, $actual) 46 | { 47 | $this->assertEquals( 48 | $this->normalizeHtml($expected), 49 | $this->normalizeHtml($actual) 50 | ); 51 | } 52 | 53 | protected function createDocumentWithHtml(string $html): DOMDocument 54 | { 55 | $vueDocument = new DOMDocument('1.0', 'utf-8'); 56 | @$vueDocument->loadHTML('' . $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); 57 | 58 | return $vueDocument; 59 | } 60 | 61 | protected function normalizeHtml(string $html): string 62 | { 63 | $html = preg_replace('/(\s)+/s', '\\1', $html); 64 | $html = str_replace("\n", '', $html); 65 | 66 | // Trim node text 67 | $html = preg_replace('/>[^\S ]+/s', '>', $html); 68 | $html = preg_replace('/[^\S ]+ <', $html); 71 | $html = preg_replace('/} {/s', '>{', $html); 73 | $html = preg_replace('/} {/s', '}{', $html); 74 | 75 | return $html ?? ''; 76 | } 77 | 78 | protected function loadFixturesFromDir(string $dir): array 79 | { 80 | $fixtureDir = __DIR__ . '/fixtures/' . $dir; 81 | 82 | $cases = []; 83 | 84 | foreach (new DirectoryIterator($fixtureDir) as $fileInfo) { 85 | if ($fileInfo->isDot()) { 86 | continue; 87 | } 88 | 89 | if ($fileInfo->getExtension() !== 'vue') { 90 | continue; 91 | } 92 | 93 | // Skip files which have an "x" prefix 94 | if (substr($fileInfo->getBasename(), 0, 1) === 'x') { 95 | continue; 96 | } 97 | 98 | $templateFile = $fileInfo->getPathname(); 99 | $twigFile = str_replace('.vue', '.twig', $templateFile); 100 | 101 | $template = file_get_contents($templateFile); 102 | $expected = file_get_contents($twigFile); 103 | 104 | $cases[$fileInfo->getBasename('.vue')] = [ 105 | $template, 106 | $expected, 107 | ]; 108 | } 109 | 110 | return $cases; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /tests/AttributeWithIfTest.php: -------------------------------------------------------------------------------- 1 | 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 | '', 31 | '
', 32 | ], 33 | [ 34 | '', 35 | '
', 36 | ], 37 | [ 38 | '', 39 | '
', 40 | ], 41 | [ 42 | '', 43 | '
', 44 | ], 45 | [ 46 | '', 47 | '
', 48 | ], 49 | ]; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/CleanupAttributesTest.php: -------------------------------------------------------------------------------- 1 |
dummy
'; 15 | 16 | $expected = '
dummy
'; 17 | 18 | $compiler = $this->createCompiler($vueTemplate); 19 | 20 | $actual = $compiler->convert(); 21 | 22 | $this->assertEqualHtml($expected, $actual); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/CommentNodeTest.php: -------------------------------------------------------------------------------- 1 |
'; 15 | $expected = '
'; 16 | 17 | $compiler = $this->createCompiler($component); 18 | 19 | $actual = $compiler->convert(); 20 | 21 | $this->assertEqualHtml($expected, $actual); 22 | } 23 | 24 | /** 25 | * @throws Exception 26 | */ 27 | public function testCommentNodeEslintDisable() 28 | { 29 | $component = ''; 30 | $expected = '
'; 31 | 32 | $compiler = $this->createCompiler($component); 33 | 34 | $actual = $compiler->convert(); 35 | 36 | $this->assertEqualHtml($expected, $actual); 37 | } 38 | 39 | /** 40 | * @throws Exception 41 | */ 42 | public function testCommentNodeTodo() 43 | { 44 | $component = ''; 45 | $expected = '
'; 46 | 47 | $compiler = $this->createCompiler($component); 48 | 49 | $actual = $compiler->convert(); 50 | 51 | $this->assertEqualHtml($expected, $actual); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /tests/CompilerPropsTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($component); 26 | 27 | $actual = $compiler->convert(); 28 | 29 | $this->assertEqualHtml($expected, $actual); 30 | } 31 | 32 | /** 33 | * @test 34 | * 35 | * @throws Exception 36 | */ 37 | public function registersTypeScriptProperties() 38 | { 39 | $component = file_get_contents(__DIR__ . '/fixtures/vue-props/binding-props-typescript-default.vue'); 40 | $expected = file_get_contents(__DIR__ . '/fixtures/vue-props/binding-props-typescript-default.twig'); 41 | 42 | if (!$component) { 43 | self::fail('Component not found.'); 44 | 45 | return; 46 | } 47 | 48 | $compiler = $this->createCompiler($component); 49 | 50 | $actual = $compiler->convert(); 51 | 52 | $this->assertEqualHtml($expected, $actual); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /tests/CompilerStyleBlockScopedImportTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 21 | $compiler->setStyleBlockOutputType(StyleBuilder::STYLE_ALL); 22 | $compiler->setRelativePath(__DIR__ . '/fixtures/style-block-scoped-import/style-block-scss-scoped-import.vue'); 23 | 24 | $actual = $compiler->convert(); 25 | 26 | $this->assertEqualHtml($expected, $actual); 27 | } 28 | 29 | /** 30 | * @return array 31 | */ 32 | public function dataProvider() 33 | { 34 | return $this->loadFixturesFromDir('style-block-scoped-import'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/CompilerStyleBlockScopedTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 21 | $compiler->setStyleBlockOutputType(StyleBuilder::STYLE_ALL); 22 | $compiler->registerComponent('ChildComponent', '/templates/ChildComponent.twig'); 23 | 24 | $actual = $compiler->convert(); 25 | 26 | $this->assertEqualHtml($expected, $actual); 27 | } 28 | 29 | /** 30 | * @return array 31 | */ 32 | public function dataProvider() 33 | { 34 | return $this->loadFixturesFromDir('style-block-scoped'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/CompilerStyleBlockTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 21 | $compiler->setStyleBlockOutputType(StyleBuilder::STYLE); 22 | 23 | $actual = $compiler->convert(); 24 | 25 | $this->assertEqualHtml($expected, $actual); 26 | } 27 | 28 | /** 29 | * @return array 30 | */ 31 | public function dataProvider() 32 | { 33 | return $this->loadFixturesFromDir('style-block'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/CompilerTest.php: -------------------------------------------------------------------------------- 1 |
{{ someVariable }}
'; 17 | $expected = '
{{ someVariable }}
'; 18 | $compiler = $this->createCompiler($html); 19 | 20 | $actual = $compiler->convert(); 21 | 22 | $this->assertEqualHtml($expected, $actual); 23 | } 24 | 25 | /** 26 | * @test 27 | * 28 | * @throws Exception 29 | */ 30 | public function stripsOutWhitespaceBetweenTags() 31 | { 32 | $html = ' 33 | '; 40 | 41 | $expected = '
{{ someVariable }}
'; 42 | 43 | $compiler = $this->createCompiler($html); 44 | $actual = $compiler->convert(); 45 | 46 | $this->assertEquals($expected, $actual); 47 | } 48 | 49 | /** 50 | * @test 51 | * 52 | * @throws Exception 53 | */ 54 | public function setBannerWithSingleLineAddsBannerCommentToTheTopOfTheTwigFile() 55 | { 56 | $html = ''; 57 | $expected = '{# This file was generated using VueToTwig #}
{{ someVariable }}
'; 58 | $compiler = $this->createCompiler($html); 59 | $compiler->setBanner('This file was generated using VueToTwig'); 60 | 61 | $actual = $compiler->convert(); 62 | 63 | $this->assertEqualHtml($expected, $actual); 64 | } 65 | 66 | /** 67 | * @test 68 | * 69 | * @throws Exception 70 | */ 71 | public function setBannerAddsMultipleCommentsToTheTopOfTheTwigFile() 72 | { 73 | $html = ''; 74 | $expected = '{# 75 | # This file was generated using VueToTwig 76 | # Source: assets/js/SomeComponent.vue 77 | #} 78 |
{{ someVariable }}
'; 79 | 80 | $compiler = $this->createCompiler($html); 81 | $compiler->setBanner([ 82 | 'This file was generated using VueToTwig', 83 | 'Source: assets/js/SomeComponent.vue', 84 | ]); 85 | 86 | $actual = $compiler->convert(); 87 | 88 | $this->assertEqualHtml($expected, $actual); 89 | } 90 | 91 | /** 92 | * @test 93 | * 94 | * @throws Exception 95 | */ 96 | public function canHandleUTF8() 97 | { 98 | $html = ''; 99 | $expected = '
Äöü: 10,00€
'; 100 | 101 | $compiler = $this->createCompiler($html); 102 | $actual = $compiler->convert(); 103 | 104 | $this->assertEqualHtml($expected, $actual); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /tests/CompilerTwigBlockTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($component); 26 | 27 | $actual = $compiler->convert(); 28 | 29 | $this->assertEqualHtml($expected, $actual); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/ConcatTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 20 | 21 | $actual = $compiler->convert(); 22 | 23 | $this->assertEqualHtml($expected, $actual); 24 | } 25 | 26 | /** 27 | * @return array 28 | */ 29 | public function dataProvider() 30 | { 31 | return $this->loadFixturesFromDir('concat'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/DataTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 20 | 21 | $compiler->enableDataSupport(); 22 | 23 | $actual = $compiler->convert(); 24 | 25 | $this->assertEqualHtml($expected, $actual); 26 | } 27 | 28 | /** 29 | * @return array 30 | */ 31 | public function dataProvider() 32 | { 33 | return $this->loadFixturesFromDir('data'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/DataTwigRemoveTest.php: -------------------------------------------------------------------------------- 1 |
dummy
'; 15 | 16 | $expected = '
'; 17 | 18 | $compiler = $this->createCompiler($vueTemplate); 19 | 20 | $actual = $compiler->convert(); 21 | 22 | $this->assertEqualHtml($expected, $actual); 23 | } 24 | 25 | /** 26 | * @throws Exception 27 | */ 28 | public function testDataTwigRemoveWithIf() 29 | { 30 | $vueTemplate = ''; 31 | 32 | $expected = '
'; 33 | 34 | $compiler = $this->createCompiler($vueTemplate); 35 | 36 | $actual = $compiler->convert(); 37 | 38 | $this->assertEqualHtml($expected, $actual); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /tests/TextNodeTest.php: -------------------------------------------------------------------------------- 1 |
foo {{ bar.trim }}
'; 15 | $expected = '
foo {{ bar|trim }}
'; 16 | 17 | $compiler = $this->createCompiler($html); 18 | 19 | $actual = $compiler->convert(); 20 | 21 | $this->assertEqualHtml($expected, $actual); 22 | } 23 | 24 | /** 25 | * @throws Exception 26 | */ 27 | public function testTextNodeNoReplace() 28 | { 29 | $html = ''; 30 | $expected = '
foo.trim {{ \'foo === bar\' }}
'; 31 | 32 | $compiler = $this->createCompiler($html); 33 | 34 | $actual = $compiler->convert(); 35 | 36 | $this->assertEqualHtml($expected, $actual); 37 | } 38 | 39 | /** 40 | * @throws Exception 41 | */ 42 | public function testTextNodeDontCloseInQuote() 43 | { 44 | $html = ''; 45 | $expected = '
{{ \'}}\' or foo|length }}
'; 46 | 47 | $compiler = $this->createCompiler($html); 48 | 49 | $actual = $compiler->convert(); 50 | 51 | $this->assertEqualHtml($expected, $actual); 52 | } 53 | 54 | /** 55 | * @throws Exception 56 | */ 57 | public function testTextNodeWithTemplateString() 58 | { 59 | $html = ''; 60 | $expected = '
{{ \'Var = \' ~ var ~ \'\' }}
'; 61 | 62 | $compiler = $this->createCompiler($html); 63 | 64 | $actual = $compiler->convert(); 65 | 66 | $this->assertEqualHtml($expected, $actual); 67 | } 68 | 69 | /** 70 | * @throws Exception 71 | */ 72 | public function testTextNodeNumbers() 73 | { 74 | $html = ''; 75 | $expected = '
{{ 1 + 1 }}
'; 76 | 77 | $compiler = $this->createCompiler($html); 78 | 79 | $actual = $compiler->convert(); 80 | 81 | $this->assertEqualHtml($expected, $actual); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /tests/TwigConfigTest.php: -------------------------------------------------------------------------------- 1 | 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 | } 31 | -------------------------------------------------------------------------------- /tests/VueBindingsTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 20 | 21 | $actual = $compiler->convert(); 22 | 23 | $this->assertEqualHtml($expected, $actual); 24 | } 25 | 26 | /** 27 | * @return array 28 | */ 29 | public function dataProvider() 30 | { 31 | return $this->loadFixturesFromDir('vue-bind'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/VueCloakTest.php: -------------------------------------------------------------------------------- 1 |
'; 15 | 16 | $expected = '
'; 17 | 18 | $compiler = $this->createCompiler($vueTemplate); 19 | 20 | $actual = $compiler->convert(); 21 | 22 | $this->assertEqualHtml($expected, $actual); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/VueComponentTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 20 | 21 | $compiler->registerComponent('ChildComponent', '/templates/ChildComponent.twig'); 22 | 23 | $actual = $compiler->convert(); 24 | 25 | $this->assertEqualHtml($expected, $actual); 26 | } 27 | 28 | /** 29 | * @return array 30 | */ 31 | public function dataProvider() 32 | { 33 | return $this->loadFixturesFromDir('vue-component'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/VueForTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 20 | 21 | $actual = $compiler->convert(); 22 | 23 | $this->assertEqualHtml($expected, $actual); 24 | } 25 | 26 | /** 27 | * @return array 28 | */ 29 | public function dataProvider() 30 | { 31 | return $this->loadFixturesFromDir('vue-for'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/VueHtmlTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($component); 24 | 25 | $actual = $compiler->convert(); 26 | 27 | $this->assertEqualHtml($expected, $actual); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/VueIfTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 20 | 21 | $actual = $compiler->convert(); 22 | 23 | $this->assertEqualHtml($expected, $actual); 24 | } 25 | 26 | public function ifProvider() 27 | { 28 | return $this->loadFixturesFromDir('vue-if'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/VueModelTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 20 | 21 | $actual = $compiler->convert(); 22 | 23 | $this->assertEqualHtml($expected, $actual); 24 | } 25 | 26 | /** 27 | * @return array 28 | */ 29 | public function dataProvider() 30 | { 31 | return $this->loadFixturesFromDir('vue-model'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/VueOnTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 20 | 21 | $actual = $compiler->convert(); 22 | 23 | $this->assertEqualHtml($expected, $actual); 24 | } 25 | 26 | /** 27 | * @return array 28 | */ 29 | public function onProvider() 30 | { 31 | return $this->loadFixturesFromDir('vue-on'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/VuePreTest.php: -------------------------------------------------------------------------------- 1 | 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 | '', 31 | '{% verbatim %}
{{ 42 }}
{% endverbatim %}', 32 | ], 33 | [ 34 | '', 35 | '{% verbatim %}

{{ headline }}

{{ button }}
{% endverbatim %}', 36 | ], 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/VueShowTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 20 | 21 | $actual = $compiler->convert(); 22 | 23 | $this->assertEqualHtml($expected, $actual); 24 | } 25 | 26 | public function showProvider() 27 | { 28 | return $this->loadFixturesFromDir('vue-show'); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/VueSlotTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($html); 20 | 21 | $compiler->registerComponent('ChildComponent', '/templates/ChildComponent.twig'); 22 | 23 | $actual = $compiler->convert(); 24 | 25 | $this->assertEqualHtml($expected, $actual); 26 | } 27 | 28 | /** 29 | * @return array 30 | */ 31 | public function dataProvider() 32 | { 33 | return $this->loadFixturesFromDir('vue-slot'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/VueTextTest.php: -------------------------------------------------------------------------------- 1 | createCompiler($component); 24 | 25 | $actual = $compiler->convert(); 26 | 27 | $this->assertEqualHtml($expected, $actual); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/fixtures/concat/concat-typescript.twig: -------------------------------------------------------------------------------- 1 |
2 |
3 |
{{ 'foo' ~ ' bar' }}
4 |
{{ text ~ ' foo' }}
5 |
{{ text ~ 1 }}
6 |
{{ size ~ ' foo' }}
7 |
{{ size + 1 }}
8 |
{{ 1 + 1 }}
9 |
10 | -------------------------------------------------------------------------------- /tests/fixtures/concat/concat-typescript.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/fixtures/concat/concat.twig: -------------------------------------------------------------------------------- 1 |
2 |
3 |
{{ 'foo' ~ ' bar' }}
4 |
{{ text ~ ' foo' }}
5 |
{{ text ~ 1 }}
6 |
{{ size ~ ' foo' }}
7 |
{{ size + 1 }}
8 |
{{ 1 + 1 }}
9 |
{{ 'foo ' ~ size ~ size ~ ' bar' }}
10 |
{{ 'foo ' ~ ( size + size ) ~ ' bar' }}
11 |
{{ 'foo ' ~ ( 1 + size ) ~ ' bar' }}
12 |
{{ 1 ~ ( 'foo' ~ size ) ~ 2 }}
13 |
{{ 'foo ' ~ ( ( 1 + 2 ) ~ ( ' bar ' ~ ' baz ' ) ~ ( ' waz ' ~ 3 ) ) }}
14 |
{{ 'foo ' ~ ( size * size ) ~ ' bar' }}
15 |
{{ ( size * size ) + 2 }}
16 |
{{ ( size * size ) / 2 + 10 }}
17 |
{{ ( size * size ) % 2 + 10 }}
18 |
{{ ( size - 10 ) * 2 + 10 }}
19 |
{{ '20 - 10 - 5' ~ 10 }}
20 |
21 | -------------------------------------------------------------------------------- /tests/fixtures/concat/concat.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 38 | -------------------------------------------------------------------------------- /tests/fixtures/data/data-config.twig: -------------------------------------------------------------------------------- 1 | {% set bar = bar|default('baz') %} 2 |
Hello World!
-------------------------------------------------------------------------------- /tests/fixtures/data/data-config.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | disable-data-support = true; 9 | 10 | 11 | -------------------------------------------------------------------------------- /tests/fixtures/data/data-typescript.twig: -------------------------------------------------------------------------------- 1 | {% set bar = bar|default('baz') %} 2 | {% set myNumber = 1 %} 3 | {% set myString = 'foo' %} 4 | {% set myArray = ['a', 'b', 'c'] %} 5 | {% set myObject = { a: 'x', b: 'y', c: 'z' } %} 6 |
Hello World!
-------------------------------------------------------------------------------- /tests/fixtures/data/data-typescript.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /tests/fixtures/data/data-window.twig: -------------------------------------------------------------------------------- 1 | {% set foo = null %} 2 |
Hello World!
-------------------------------------------------------------------------------- /tests/fixtures/data/data-window.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /tests/fixtures/data/data-with-comment.twig: -------------------------------------------------------------------------------- 1 | {% set bar = bar|default('baz') %} 2 | {% set myObject = { a: 'x', b: 'y', c: 'z', } %} 3 |
Hello World!
-------------------------------------------------------------------------------- /tests/fixtures/data/data-with-comment.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /tests/fixtures/data/data.twig: -------------------------------------------------------------------------------- 1 | {% set bar = bar|default('baz') %} 2 | {% set myNumber = 1 %} 3 | {% set myString = 'foo' %} 4 | {% set myArray = [ 'a', 'b', 'c', ] %} 5 | {% set myObject = { a: 'x', b: 'y', c: 'z', } %} 6 | {% set calculatedNumber = myString|length + 1 %} 7 |
Hello World!
-------------------------------------------------------------------------------- /tests/fixtures/data/data.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped-import/imports/import.scss: -------------------------------------------------------------------------------- 1 | $red: #FF0000; 2 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped-import/imports/subfolder/import2.scss: -------------------------------------------------------------------------------- 1 | $red: #AA0000; 2 | $blue: #0000FF; 3 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped-import/style-block-scss-scoped-import.twig: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | baz 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped-import/style-block-scss-scoped-import.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | 20 | 24 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/include-child-component-with-component-on-root-and-style-block-scoped.twig: -------------------------------------------------------------------------------- 1 | 2 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'dataScopedStyleAttribute': "data-v-858c11a91dcdf48f12d9b6c5ca636873" ~ " " ~ dataScopedStyleAttribute|default(''), 'class': "foo" ~ " " ~ class|default(''), 'style': "color: black" ~ "; " ~ style|default('') } %} 3 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/include-child-component-with-component-on-root-and-style-block-scoped.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | 14 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/include-child-component-with-component-on-root.twig: -------------------------------------------------------------------------------- 1 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'dataScopedStyleAttribute': dataScopedStyleAttribute|default(''), 'class': "foo" ~ " " ~ class|default(''), 'style': "color: black" ~ "; " ~ style|default('') } %} 2 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/include-child-component-with-component-on-root.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/include-child-component-with-style-block-scoped.twig: -------------------------------------------------------------------------------- 1 | 2 |
{% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'dataScopedStyleAttribute': "data-v-858c11a91dcdf48f12d9b6c5ca636873", 'class': "foo", 'style': "color: black" } %}
3 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/include-child-component-with-style-block-scoped.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 15 | 16 | 21 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-2.twig: -------------------------------------------------------------------------------- 1 | 5 |
6 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-2.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 17 | 18 | 22 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-3.twig: -------------------------------------------------------------------------------- 1 | 4 |
-------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-3.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | 13 | 17 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-4.twig: -------------------------------------------------------------------------------- 1 | 2 |
3 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-4.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 13 | 14 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep-2.twig: -------------------------------------------------------------------------------- 1 | 4 |
5 | 10 |
11 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep-2.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 16 | 17 | 21 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep-3.twig: -------------------------------------------------------------------------------- 1 | 4 |
5 | 8 |
9 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep-3.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep-4.twig: -------------------------------------------------------------------------------- 1 | 6 |
7 | 11 | foo 12 |
13 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep-4.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 22 | 23 | 27 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep-with-scss-2.twig: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | test 5 | 6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep-with-scss-2.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 18 | 19 | 23 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep-with-scss.twig: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | foo 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep-with-scss.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 | 22 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep.twig: -------------------------------------------------------------------------------- 1 | 5 |
6 |
7 | foo 8 |
9 |
10 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-deep.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 | 22 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-v-deep-with-scss.twig: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | foo 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-v-deep-with-scss.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 | 22 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-v-deep.twig: -------------------------------------------------------------------------------- 1 | 5 |
6 |
7 | foo 8 |
9 |
10 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-v-deep.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 | 22 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-with-child-binding.twig: -------------------------------------------------------------------------------- 1 | 6 |
7 |
8 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'dataScopedStyleAttribute': "data-v-7ac31a851ab0c4c52bc569b6f256bfe4", 'class': "", 'style': "" } %} 9 |
10 |
11 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped-with-child-binding.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 17 | 18 | 23 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped.twig: -------------------------------------------------------------------------------- 1 | 16 |
17 |
18 | foo 19 |
20 |
21 | bar 22 |
23 |
24 | baz 25 |
26 |
27 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scoped.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 30 | 31 | 35 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scss-scoped.twig: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | baz 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block-scss-scoped.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 21 | 22 | 26 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block.twig: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | foo 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-block.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-blocks.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 | 42 7 |
8 |
9 | -------------------------------------------------------------------------------- /tests/fixtures/style-block-scoped/style-blocks.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 20 | 21 | 27 | 28 | 32 | -------------------------------------------------------------------------------- /tests/fixtures/style-block/style-block-scss-error-handling.twig: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | foo 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/style-block/style-block-scss-error-handling.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 22 | 23 | 27 | -------------------------------------------------------------------------------- /tests/fixtures/style-block/style-block-scss.twig: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | foo 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/style-block/style-block-scss.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 21 | 22 | 26 | -------------------------------------------------------------------------------- /tests/fixtures/style-block/style-block.twig: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | foo 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/style-block/style-block.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/twig-block/twig-block.twig: -------------------------------------------------------------------------------- 1 | {% set myCustomComputedProperty = false %} 2 |
3 |
4 | {% if myCustomComputedProperty %} 5 |

Show something

6 | {% endif %} 7 |
8 |
9 | -------------------------------------------------------------------------------- /tests/fixtures/twig-block/twig-block.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | {% set myCustomComputedProperty = false %} 11 | 12 | 13 | 22 | -------------------------------------------------------------------------------- /tests/fixtures/twig-config/attribute-if-2.twig: -------------------------------------------------------------------------------- 1 | {% set count = count|default(0) %} 2 |
3 |
5 %}foo="{{ count > 5 }}"{% endif %}> 4 | Foo 5 |
6 |
5 %}bar="{{ count > 5 }}"{% endif %}> 7 | Bar 8 |
9 |
-------------------------------------------------------------------------------- /tests/fixtures/twig-config/attribute-if-2.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | attributes-with-if = foo,bar 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/fixtures/twig-config/attribute-if.twig: -------------------------------------------------------------------------------- 1 | {% set count = count|default(0) %} 2 |
3 |
5 %}foo="{{ count > 5 }}"{% endif %}> 4 | Foo 5 |
6 |
7 | Bar 8 |
9 |
-------------------------------------------------------------------------------- /tests/fixtures/twig-config/attribute-if.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 13 | attributes-with-if = foo 14 | 15 | 16 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-array-with-object-binding-2.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default(false) %} 2 | {% set bar = bar|default(false) %} 3 |
4 |
5 | Foo 6 |
7 |
8 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-array-with-object-binding-2.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 23 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-array-with-object-binding-3.twig: -------------------------------------------------------------------------------- 1 | {% set isDisabled = isDisabled|default(false) %} 2 |
3 |
4 | Foo 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-array-with-object-binding-3.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-array-with-object-binding.twig: -------------------------------------------------------------------------------- 1 | {% set isDisabled = isDisabled|default(false) %} 2 |
3 |
4 | Foo 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-array-with-object-binding.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-array-with-template-string.twig: -------------------------------------------------------------------------------- 1 | {% set isDisabled = isDisabled|default(false) %} 2 |
3 |
4 | Foo 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-array-with-template-string.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-array.twig: -------------------------------------------------------------------------------- 1 |
2 |
3 | Foo 4 |
5 |
6 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-array.vue: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-template-string-2.twig: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | Hello World 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-template-string-2.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-template-string-3.twig: -------------------------------------------------------------------------------- 1 |
2 |
3 | Hello World 4 |
5 |
6 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-template-string-3.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-template-string-4.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default('') %} 2 |
3 |
4 | Foo 5 |
6 |
7 | Bar 8 |
9 |
10 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-template-string-4.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 26 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-template-string.twig: -------------------------------------------------------------------------------- 1 |
2 |
3 | Hello World 4 |
5 |
6 |
7 |
8 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/binding-with-template-string.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/bindings-src.twig: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/bindings-src.vue: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/bindings-style.twig: -------------------------------------------------------------------------------- 1 |
2 | 3 | test 4 | 5 | 6 | test 7 | 8 | 9 | test 10 | 11 | 12 | test 13 | 14 | 15 | test 16 | 17 | 18 | test 19 | 20 | 21 | test 22 | 23 | 24 | test 25 | 26 |
27 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/bindings-style.vue: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/bindings-with-encoded-attributes.twig: -------------------------------------------------------------------------------- 1 |
2 | 3 | {{ isBool ? varA.alt : varB.alt }} 4 | 5 |
6 | 9 | 10 |
11 | 12 |
13 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/bindings-with-encoded-attributes.vue: -------------------------------------------------------------------------------- 1 | 15 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/bindings-with-filter.twig: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | Link 5 |
6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/bindings-with-filter.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/bindings.twig: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | 5 | 6 |
7 |
8 |
9 |
Hidden
10 |
Hidden
11 |
Hidden
12 |
13 |
14 |
15 |
16 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/bindings.vue: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/double-attribute-binding.twig: -------------------------------------------------------------------------------- 1 |
2 |
3 | Hello World 4 |
5 |
6 | With Object Binding 7 |
8 |
9 | -------------------------------------------------------------------------------- /tests/fixtures/vue-bind/double-attribute-binding.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 22 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-child-binding-2.twig: -------------------------------------------------------------------------------- 1 | {% set test = test|default(false) %} 2 |
3 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'class': 'foo' ~ " " ~ ( test ? 'bar' ) ~ " " ~ ( not test ? 'baz' ), 'style': "" } %} 4 |
5 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-child-binding-2.vue: -------------------------------------------------------------------------------- 1 | 6 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-child-binding-3.twig: -------------------------------------------------------------------------------- 1 | {% set test = test|default(false) %} 2 |
3 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'class': "foo" ~ " " ~ ( test ? 'bar' ) ~ " " ~ ( not test ? 'baz' ), 'style': "" } %} 4 |
5 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-child-binding-3.vue: -------------------------------------------------------------------------------- 1 | 6 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-child-binding-4.twig: -------------------------------------------------------------------------------- 1 | {% set test = test|default(false) %} 2 |
3 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'class': 'foo' ~ " " ~ ( test ? 'bar' ) ~ " " ~ ( not test ? 'baz' ), 'style': "" } %} 4 |
5 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-child-binding-4.vue: -------------------------------------------------------------------------------- 1 | 6 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-child-binding.twig: -------------------------------------------------------------------------------- 1 |
2 | {% include "/templates/ChildComponent.twig" with { 'test': "test", 'slot_default': "", 'class': "", 'style': ( "fill:" ~ ( color ) ~ ";" ) } %} 3 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'class': "", 'style': "color: red" ~ "; " ~ ( "fill:" ~ ( color ) ~ ";" ) } %} 4 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'class': "foo" ~ " " ~ ( "bar" ), 'style': "" } %} 5 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'class': "foo" ~ " " ~ ( bar ), 'style': "" } %} 6 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'class': "product-column__tile" ~ " " ~ ( isSingleProductTile ? 'product-column__tile--large' ), 'style': "" } %} 7 | {% include "/templates/ChildComponent.twig" with { 'ariaLabelledby': "foo-" ~ ( _uid ) ~ "", 'slot_default': "", 'class': "", 'style': "" } %} 8 |
9 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-child-binding.vue: -------------------------------------------------------------------------------- 1 | 11 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-child.twig: -------------------------------------------------------------------------------- 1 |
2 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'class': "", 'style': "" } %} 3 |
4 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-child.vue: -------------------------------------------------------------------------------- 1 | 6 | 14 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-for.twig: -------------------------------------------------------------------------------- 1 |
2 | {% for a in listOfProducts %}{% include "/templates/ChildComponent.twig" with { 'string': "string", 'product': productA, 'slot_default': "", 'class': "", 'style': "" } %}{% endfor %} 3 |
4 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-for.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-if.twig: -------------------------------------------------------------------------------- 1 |
2 | {% if a > 5 %}{% include "/templates/ChildComponent.twig" with { 'string': "string", 'product': productA, 'slot_default': "", 'class': "", 'style': "" } %}{% endif %} 3 |
4 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-if.vue: -------------------------------------------------------------------------------- 1 | 6 | 11 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-inline-condition-prop.twig: -------------------------------------------------------------------------------- 1 |
2 | {% include "/templates/ChildComponent.twig" with { 3 | 'product': testProduct, 4 | 'showSomething': index > 5 and a == true, 5 | 'testA': "Hello", 'string': "Test", 'slot_default': "", 'class': "", 'style': "" } %} 6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-inline-condition-prop.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 15 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-prop.twig: -------------------------------------------------------------------------------- 1 |
2 | {% include "/templates/ChildComponent.twig" with { 'product': testProduct, 'testA': "Hello", 'string': "Test", 'slot_default': "", 'class': "", 'style': "" } %} 3 |
4 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-prop.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-v-bind-props.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default('foo') %} 2 | {% set bar = bar|default(42) %} 3 |
4 | {% include "/templates/ChildComponent.twig" with { 'slot_default': "", 'foo': foo, 'bar': bar, 'class': "", 'style': "" } %} 5 |
6 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-v-bind-props.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-v-bind.twig: -------------------------------------------------------------------------------- 1 |
2 | {% include "/templates/ChildComponent.twig" with { 'bar': "baz", 'slot_default': "", 'class': "", 'style': "" }|merge(foo) %} 3 |
4 | -------------------------------------------------------------------------------- /tests/fixtures/vue-component/component-with-v-bind.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /tests/fixtures/vue-for/replaces-v-for-in.twig: -------------------------------------------------------------------------------- 1 |
2 | {% for item in 1..5 %} 3 |
4 | {{ item.text }} 5 |
6 | {% endfor %} 7 | {% for n in 1..10 %}{{ n }}{% endfor %} 8 |
9 | -------------------------------------------------------------------------------- /tests/fixtures/vue-for/replaces-v-for-in.vue: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /tests/fixtures/vue-for/replaces-v-for.twig: -------------------------------------------------------------------------------- 1 |
2 | {% for item in items %} 3 |
4 | {{ item.text }} 5 |
6 | {% endfor %} 7 | {% for key, item in items %} 8 |
A
9 | {% endfor %} 10 | {% for key, val in object %} 11 |
B
12 | {% endfor %} 13 | {% for key, val in object %} 14 | {% set index = loop.index0 %} 15 |
C
16 | {% endfor %} 17 |
18 | {% for item in items %} 19 |
20 | {{ item.text }} 21 |
22 | {% endfor %} 23 |
24 |
25 | -------------------------------------------------------------------------------- /tests/fixtures/vue-for/replaces-v-for.vue: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /tests/fixtures/vue-html/html.twig: -------------------------------------------------------------------------------- 1 | {% set rawHtml = 'text' %} 2 |
3 | 4 | {{ rawHtml|raw }} 5 | 6 |
7 | -------------------------------------------------------------------------------- /tests/fixtures/vue-html/html.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | {% set rawHtml = '<strong>text</strong>' %} 9 | 10 | 11 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-data-twig.twig: -------------------------------------------------------------------------------- 1 |
2 | {% if array|length %} 3 |
4 |

Headline

5 |
6 | {% elseif array|length < 100 %} 7 |
8 |

Headline

9 |
10 | {% endif %} 11 |
12 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-data-twig.vue: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-elseif-else-with-nested-if.twig: -------------------------------------------------------------------------------- 1 |
2 | {% if someCondition %} 3 |
4 |

Headline

5 |
6 | {% elseif someOtherCondition %} 7 |
8 | {% if yetAnotherCondition %} 9 |

Headline 2.1

10 | {% else %} 11 |

Headline 2.2

12 | {% endif %} 13 |
14 | {% else %} 15 |
16 |

Headline 3

17 |
18 | {% endif %} 19 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-elseif-else-with-nested-if.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-elseif-else.twig: -------------------------------------------------------------------------------- 1 |
2 | {% if someCondition %} 3 |
4 |

Headline

5 |
6 | {% elseif someOtherCondition %} 7 |
8 |

Headline 2

9 |
10 | {% else %} 11 |
12 |

Headline 3

13 |
14 | {% endif %} 15 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-elseif-else.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-strict-equal.twig: -------------------------------------------------------------------------------- 1 |
2 | {% if a == 1 %} 3 |
Text
4 | {% endif %} 5 | {% if a|length %} 6 |
Text
7 | {% endif %} 8 |
9 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-strict-equal.vue: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-with-statement.twig: -------------------------------------------------------------------------------- 1 | {% set show = show|default(false) %} 2 |
3 | {% if variable >= 1 %} 4 |
5 |

Headline

6 |
7 | {% elseif variable < 100 and variable >= 1 %} 8 |
9 |

Headline

10 |
11 | {% endif %} 12 | {% if showIcon %} 13 | Oh no. 14 | {% endif %} 15 |
16 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-with-statement.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 28 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-with-template.twig: -------------------------------------------------------------------------------- 1 |
2 | {% if someVar %} 3 |

Headline

4 | {% else %} 5 |

Other headline

6 | {% endif %} 7 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-if/if-with-template.vue: -------------------------------------------------------------------------------- 1 | 11 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/multiple-if-occurrences.twig: -------------------------------------------------------------------------------- 1 |
2 | {% if someCondition %} 3 |
4 |

Headline

5 |
6 | {% endif %} 7 | {% if someOtherCondition %} 8 |
9 |

Headline

10 |
11 | {% endif %} 12 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-if/multiple-if-occurrences.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/simple-if-2.twig: -------------------------------------------------------------------------------- 1 |
2 | {% if someVar %} 3 |
Text
4 | {% endif %} 5 | {% if not someVar and mobile != true %} 6 |
Mobile
7 | {% endif %} 8 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-if/simple-if-2.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/fixtures/vue-if/single-node.twig: -------------------------------------------------------------------------------- 1 | {% if someVar %} 2 |
Text
3 | {% endif %} -------------------------------------------------------------------------------- /tests/fixtures/vue-if/single-node.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-input-checkbox.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default(['2', '4', '5']) %} 2 |
3 | {% if (foo is iterable and "1" in foo) or (foo is not iterable and foo) %} 4 | 5 | {% else %} 6 | 7 | {% endif %} 8 | {% if (foo is iterable and "2" in foo) or (foo is not iterable and foo) %} 9 | 10 | {% else %} 11 | 12 | {% endif %} 13 | {% if (foo is iterable and "3" in foo) or (foo is not iterable and foo) %} 14 | 15 | {% else %} 16 | 17 | {% endif %} 18 | {% if (foo is iterable and "4" in foo) or (foo is not iterable and foo) %} 19 | 20 | {% else %} 21 | 22 | {% endif %} 23 | {% if (foo is iterable and "5" in foo) or (foo is not iterable and foo) %} 24 | 25 | {% else %} 26 | 27 | {% endif %} 28 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-input-checkbox.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-input-radio.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default('2') %} 2 |
3 | {% if foo == "1" %} 4 | 5 | {% else %} 6 | 7 | {% endif %} 8 | {% if foo == "2" %} 9 | 10 | {% else %} 11 | 12 | {% endif %} 13 | {% if foo == "3" %} 14 | 15 | {% else %} 16 | 17 | {% endif %} 18 | {% if foo == "4" %} 19 | 20 | {% else %} 21 | 22 | {% endif %} 23 | {% if foo == "5" %} 24 | 25 | {% else %} 26 | 27 | {% endif %} 28 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-input-radio.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-input.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default('bar') %} 2 |
3 | 4 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-input.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | -------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-select-multiple-typescript.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default(['2', '3']) %} 2 |
3 | 20 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-select-multiple-typescript.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-select-multiple.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default(['2', '3']) %} 2 |
3 | 20 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-select-multiple.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | -------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-select-value.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default('2') %} 2 |
3 | 20 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-select-value.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-select.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default('bar') %} 2 |
3 | 20 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-select.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | -------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-textarea.twig: -------------------------------------------------------------------------------- 1 | {% set foo = foo|default('bar') %} 2 |
3 | 6 |
-------------------------------------------------------------------------------- /tests/fixtures/vue-model/model-textarea.vue: -------------------------------------------------------------------------------- 1 |