From 02af9565eaf9d34a8ffce45831fc6513e4587202 Mon Sep 17 00:00:00 2001 From: KyleKatarn Date: Thu, 6 Feb 2020 07:48:54 +0100 Subject: [PATCH 1/5] Postpone engine initialization --- src/Pug/PugSymfonyEngine.php | 12 ++- src/Pug/Symfony/Traits/HelpersHandler.php | 111 ++++++++++------------ src/Pug/Symfony/Traits/Options.php | 26 ++++- src/Pug/Twig/Environment.php | 2 +- 4 files changed, 82 insertions(+), 69 deletions(-) diff --git a/src/Pug/PugSymfonyEngine.php b/src/Pug/PugSymfonyEngine.php index e347db6..4676e93 100644 --- a/src/Pug/PugSymfonyEngine.php +++ b/src/Pug/PugSymfonyEngine.php @@ -82,7 +82,7 @@ protected function crawlDirectories(string $srcDir, array &$assetsDirectories, a } if (is_dir($viewDirectory = $srcDir.'/'.$directory.'/Resources/views')) { - if (is_null($baseDir)) { + if ($baseDir === null) { $baseDir = $viewDirectory; } @@ -131,7 +131,15 @@ protected function getFileFromName(string $name, string $directory = null): stri */ public function share($variables, $value = null): self { - $this->getRenderer()->share(...func_get_args()); + if (func_num_args() === 2) { + $variables = [ + $variables => $value, + ]; + } + + $variables = array_merge($this->getOptionDefault('shared_variables', []), $variables); + + $this->setOption('shared_variables', $variables); return $this; } diff --git a/src/Pug/Symfony/Traits/HelpersHandler.php b/src/Pug/Symfony/Traits/HelpersHandler.php index 41576c4..fb60bdb 100644 --- a/src/Pug/Symfony/Traits/HelpersHandler.php +++ b/src/Pug/Symfony/Traits/HelpersHandler.php @@ -69,23 +69,6 @@ trait HelpersHandler */ protected $nodeHandler; - /** - * @var array - */ - protected $templatingHelpers = [ - 'actions', - 'assets', - 'code', - 'form', - 'request', - 'router', - 'security', - 'session', - 'slots', - 'stopwatch', - 'translator', - ]; - /** * Get the Pug engine. * @@ -94,10 +77,7 @@ trait HelpersHandler public function getRenderer(): Pug { if ($this->pug === null) { - $cache = $this->getCacheDir(); - (new Filesystem())->mkdir($cache); - - $this->pug = $this->createEngine($this->getRendererOptions($cache)); + $this->pug = $this->createEngine($this->getRendererOptions()); $this->copyTwigFunctions(); $this->initializePugPlugins(); $this->share($this->getTwig()->getGlobals()); @@ -112,51 +92,60 @@ public function onNode(callable $nodeHandler): void $this->nodeHandler = $nodeHandler; } - protected function getRendererOptions(string $cache): array + protected function getRendererOptions(): array { - $environment = $this->kernel->getEnvironment(); - $projectDirectory = $this->kernel->getProjectDir(); - $assetsDirectories = [$projectDirectory.'/Resources/assets']; - $viewDirectories = [$projectDirectory.'/templates']; - - if (($loader = $this->getTwig()->getLoader()) instanceof FilesystemLoader && - is_array($paths = $loader->getPaths()) && - isset($paths[0]) - ) { - $viewDirectories[] = $paths[0]; - } + if ($this->options === null) { + $environment = $this->kernel->getEnvironment(); + $projectDirectory = $this->kernel->getProjectDir(); + $assetsDirectories = [$projectDirectory.'/Resources/assets']; + $viewDirectories = [$projectDirectory.'/templates']; + + if (($loader = $this->getTwig()->getLoader()) instanceof FilesystemLoader && + is_array($paths = $loader->getPaths()) && + isset($paths[0]) + ) { + $viewDirectories[] = $paths[0]; + } + + $srcDir = $projectDirectory.'/src'; + $webDir = $projectDirectory.'/public'; + $baseDir = isset($this->userOptions['baseDir']) + ? $this->userOptions['baseDir'] + : $this->crawlDirectories($srcDir, $assetsDirectories, $viewDirectories); + $baseDir = $baseDir && file_exists($baseDir) ? realpath($baseDir) : $baseDir; + $this->defaultTemplateDirectory = $baseDir; + + if (isset($this->userOptions['paths'])) { + $viewDirectories = array_merge($viewDirectories, $this->userOptions['paths'] ?: []); + } + + $debug = $this->kernel->isDebug(); + $options = array_merge([ + 'debug' => $debug, + 'assetDirectory' => static::extractUniquePaths($assetsDirectories), + 'viewDirectories' => static::extractUniquePaths($viewDirectories), + 'baseDir' => $baseDir, + 'cache' => $debug ? false : $this->getCacheDir(), + 'environment' => $environment, + 'extension' => ['.pug', '.jade'], + 'outputDirectory' => $webDir, + 'prettyprint' => $debug, + 'on_node' => $this->nodeHandler, + ], $this->userOptions); + $cache = $options['cache'] ?? $options['cache_dir'] ?? null; + + if ($cache) { + (new Filesystem())->mkdir($cache); + } - $srcDir = $projectDirectory.'/src'; - $webDir = $projectDirectory.'/public'; - $baseDir = isset($this->userOptions['baseDir']) - ? $this->userOptions['baseDir'] - : $this->crawlDirectories($srcDir, $assetsDirectories, $viewDirectories); - $baseDir = $baseDir && file_exists($baseDir) ? realpath($baseDir) : $baseDir; - $this->defaultTemplateDirectory = $baseDir; + $options['paths'] = array_unique(array_filter($options['viewDirectories'], function ($path) use ($baseDir) { + return $path !== $baseDir; + })); - if (isset($this->userOptions['paths'])) { - $viewDirectories = array_merge($viewDirectories, $this->userOptions['paths'] ?: []); + $this->options = $options; } - $debug = $this->kernel->isDebug(); - $options = array_merge([ - 'debug' => $debug, - 'assetDirectory' => static::extractUniquePaths($assetsDirectories), - 'viewDirectories' => static::extractUniquePaths($viewDirectories), - 'baseDir' => $baseDir, - 'cache' => $debug ? false : $cache, - 'environment' => $environment, - 'extension' => ['.pug', '.jade'], - 'outputDirectory' => $webDir, - 'prettyprint' => $debug, - 'on_node' => $this->nodeHandler, - ], $this->userOptions); - - $options['paths'] = array_unique(array_filter($options['viewDirectories'], function ($path) use ($baseDir) { - return $path !== $baseDir; - })); - - return $options; + return $this->options; } protected function createEngine(array $options): Pug diff --git a/src/Pug/Symfony/Traits/Options.php b/src/Pug/Symfony/Traits/Options.php index b4bcbc4..3f881ed 100644 --- a/src/Pug/Symfony/Traits/Options.php +++ b/src/Pug/Symfony/Traits/Options.php @@ -7,10 +7,16 @@ /** * Trait Options. * - * @method Pug getRenderer() + * @method Pug getRenderer() + * @method array getRendererOptions() */ trait Options { + /** + * @var array + */ + protected $options; + /** * Get a Pug engine option or the default value passed as second parameter (null if omitted). * @@ -21,11 +27,9 @@ trait Options */ public function getOptionDefault($name, $default = null) { - $pug = $this->getRenderer(); + $options = $this->getRendererOptions(); - return method_exists($pug, 'hasOption') && !$pug->hasOption($name) - ? $default - : $pug->getOption($name); + return array_key_exists($name, $options) ? $options[$name] : $default; } /** @@ -36,6 +40,12 @@ public function getOptionDefault($name, $default = null) */ public function setOption($name, $value): void { + if ($this->pug === null) { + $this->options[$name] = $value; + + return; + } + $this->getRenderer()->setOption($name, $value); } @@ -46,6 +56,12 @@ public function setOption($name, $value): void */ public function setOptions(array $options): void { + if ($this->pug === null) { + $this->options = array_merge($this->options, $options); + + return; + } + $this->getRenderer()->setOptions($options); } diff --git a/src/Pug/Twig/Environment.php b/src/Pug/Twig/Environment.php index a47c275..7ea921e 100644 --- a/src/Pug/Twig/Environment.php +++ b/src/Pug/Twig/Environment.php @@ -115,7 +115,7 @@ public function compileSourceBase(Source $source) $path = $source->getPath(); if ($this->pugSymfonyEngine->supports($path)) { - $pug = $this->pugSymfonyEngine->getRenderer(); + $pug = $this->getRenderer(); $code = $source->getCode(); $php = $pug->compile($code, $path); $codeFirstLine = $this->isDebug() ? 31 : 25; From ced69e7ab395b4d28ceb5467ed175ea8e0aad9dc Mon Sep 17 00:00:00 2001 From: KyleKatarn Date: Thu, 6 Feb 2020 17:37:12 +0100 Subject: [PATCH 2/5] Fix options laziness --- src/Pug/PugSymfonyEngine.php | 8 ++++++-- src/Pug/Symfony/Traits/Options.php | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/Pug/PugSymfonyEngine.php b/src/Pug/PugSymfonyEngine.php index 4676e93..71f78cd 100644 --- a/src/Pug/PugSymfonyEngine.php +++ b/src/Pug/PugSymfonyEngine.php @@ -163,7 +163,11 @@ public function getCacheDir(): string */ public function getParameters(array $locals = []): array { - $locals = array_merge($this->getOptionDefault('shared_variables'), $locals); + $locals = array_merge( + $this->getOptionDefault('globals', []), + $this->getOptionDefault('shared_variables', []), + $locals + ); foreach (['context', 'blocks', 'macros', 'this'] as $forbiddenKey) { if (array_key_exists($forbiddenKey, $locals)) { @@ -243,7 +247,7 @@ public function exists($name): bool */ public function supports($name): bool { - foreach ($this->getOptionDefault('extensions', []) as $extension) { + foreach ($this->getOptionDefault('extensions', ['.pug', '.jade']) as $extension) { if (substr($name, -strlen($extension)) === $extension) { return true; } diff --git a/src/Pug/Symfony/Traits/Options.php b/src/Pug/Symfony/Traits/Options.php index 3f881ed..2537183 100644 --- a/src/Pug/Symfony/Traits/Options.php +++ b/src/Pug/Symfony/Traits/Options.php @@ -27,9 +27,17 @@ trait Options */ public function getOptionDefault($name, $default = null) { - $options = $this->getRendererOptions(); + if ($this->pug === null) { + $options = $this->getRendererOptions(); + + return array_key_exists($name, $options) ? $options[$name] : $default; + } + + $pug = $this->getRenderer(); - return array_key_exists($name, $options) ? $options[$name] : $default; + return method_exists($pug, 'hasOption') && !$pug->hasOption($name) + ? $default + : $pug->getOption($name); } /** @@ -41,6 +49,7 @@ public function getOptionDefault($name, $default = null) public function setOption($name, $value): void { if ($this->pug === null) { + $this->getRendererOptions(); $this->options[$name] = $value; return; @@ -57,7 +66,7 @@ public function setOption($name, $value): void public function setOptions(array $options): void { if ($this->pug === null) { - $this->options = array_merge($this->options, $options); + $this->options = array_merge($this->getRendererOptions(), $options); return; } From bd3d645e58dc1e2147022736f89688103fc6084c Mon Sep 17 00:00:00 2001 From: KyleKatarn Date: Thu, 6 Feb 2020 23:46:46 +0100 Subject: [PATCH 3/5] Fix parentheses parsing --- src/Pug/Symfony/Traits/HelpersHandler.php | 4 +++- src/Pug/Twig/Environment.php | 12 ++++-------- tests/project-s5/templates/style-php.pug | 4 ++-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Pug/Symfony/Traits/HelpersHandler.php b/src/Pug/Symfony/Traits/HelpersHandler.php index fb60bdb..b2af19c 100644 --- a/src/Pug/Symfony/Traits/HelpersHandler.php +++ b/src/Pug/Symfony/Traits/HelpersHandler.php @@ -221,9 +221,11 @@ protected function interpolateTwigFunctions(string $code): string case ')': if ((--$opening) !== 0) { $argument .= ')'; + + break; } - break; + break 2; case ',': if ($opening > 1) { diff --git a/src/Pug/Twig/Environment.php b/src/Pug/Twig/Environment.php index 7ea921e..f342a31 100644 --- a/src/Pug/Twig/Environment.php +++ b/src/Pug/Twig/Environment.php @@ -110,7 +110,7 @@ public function setContainer(ContainerInterface $container): void $this->container = $container; } - public function compileSourceBase(Source $source) + public function compileSource(Source $source): string { $path = $source->getPath(); @@ -170,11 +170,6 @@ public function compileSourceBase(Source $source) return $html; } - public function compileSource(Source $source): string - { - return $this->compileSourceBase($source); - } - public function loadTemplate(string $cls, string $name, int $index = null): Template { if ($index !== null) { @@ -211,12 +206,13 @@ public function compileCode(TwigFunction $function, string $code) $parser = new Parser($this); $path = '__twig_function_'.$name.'_'.sha1($code).'.html.twig'; $stream = $this->tokenize(new Source($code, $path, $path)); + $output = $this->compile($parser->parse($stream)); - if (!preg_match('/^\s*echo\s(.*);\s*$/m', $this->compile($parser->parse($stream)), $match)) { + if (!preg_match('/^\s*echo\s(.*);\s*$/m', $output, $match)) { throw new RuntimeException('Unable to compile '.$name.' function.'); } - return trim($match[1]); + return '('.trim($match[1]).')'."\n"; } protected static function getPrivateExtensionProperty(TwigEnvironment $twig, string $extension, string $property) diff --git a/tests/project-s5/templates/style-php.pug b/tests/project-s5/templates/style-php.pug index f8aa860..78dcc9d 100644 --- a/tests/project-s5/templates/style-php.pug +++ b/tests/project-s5/templates/style-php.pug @@ -1,2 +1,2 @@ -.foo(style='background-position: 50% -402px; background-image: ' + css_url('assets/img/patterns/5.png') + ';') -.foo(style={'background-position': "50% -402px", 'background-image': css_url('assets/img/patterns/5.png')}) +.foo(style='background-position: 50% -402px; background-image: ' . css_url('assets/img/patterns/5.png') . ';') +.foo(style=array('background-position' => "50% -402px", 'background-image' => css_url('assets/img/patterns/5.png'))) From 3f63fbc505c5d28c61eae73a8f48e9d8405a5583 Mon Sep 17 00:00:00 2001 From: KyleKatarn Date: Thu, 6 Feb 2020 23:53:55 +0100 Subject: [PATCH 4/5] Add tests --- tests/Pug/PugSymfonyEngineTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/Pug/PugSymfonyEngineTest.php b/tests/Pug/PugSymfonyEngineTest.php index dcfe4db..5db3e28 100644 --- a/tests/Pug/PugSymfonyEngineTest.php +++ b/tests/Pug/PugSymfonyEngineTest.php @@ -431,6 +431,7 @@ public function testExists() self::assertTrue($pugSymfony->exists('logout.pug')); self::assertFalse($pugSymfony->exists('login.pug')); + self::assertTrue($pugSymfony->exists('bundle.pug')); } public function testSupports() @@ -613,6 +614,10 @@ public function testDefaultOption() $pugSymfony = new PugSymfonyEngine(self::$kernel); self::assertSame(42, $pugSymfony->getOptionDefault('does-not-exist', 42)); + + $pugSymfony->getRenderer(); + + self::assertSame(42, $pugSymfony->getOptionDefault('does-not-exist', 42)); } public function testGetSharedVariables() From 5c5e64a6614513fdf895281c3ea432b6b95e68e7 Mon Sep 17 00:00:00 2001 From: KyleKatarn Date: Fri, 7 Feb 2020 00:09:45 +0100 Subject: [PATCH 5/5] Document $pug property for Options trait --- src/Pug/Symfony/Traits/Options.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Pug/Symfony/Traits/Options.php b/src/Pug/Symfony/Traits/Options.php index 2537183..ede1b38 100644 --- a/src/Pug/Symfony/Traits/Options.php +++ b/src/Pug/Symfony/Traits/Options.php @@ -7,6 +7,8 @@ /** * Trait Options. * + * @property Pug|null $pug + * * @method Pug getRenderer() * @method array getRendererOptions() */