<commit_before><?php

namespace Handle\Commands;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Yaml\Parser as YamlParser;
use Parsedown;
use Windwalker\Renderer\BladeRenderer;

class BuildCommand extends Command
{
    protected $configDefaults = [
        'site_title'   => 'Handle',
        'theme'        => 'default',
        'cache_path'   => '_cache',
        'content_path' => '_content',
        'themes_path'  => '_themes',
        'build_path'   => '',
    ];

    protected $metaDefaults = [
        'title'    => '',
        'template' => 'index',
    ];

    protected function configure()
    {
        $this->setName('build')
             ->setDescription('Build your Handle site by generating the static output')
             ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Path to your Handle site');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $path = $input->getOption('path');
        if (!$path || $path == '.') {
            $path = getcwd();
        }

        try {
            $config = $this->getConfig($path);

            $config['cache_path']   = $this->prepPath($config['cache_path'], $path . DIRECTORY_SEPARATOR . '_cache', 'cache');
            $config['content_path'] = $this->prepPath($config['content_path'], $path . DIRECTORY_SEPARATOR . '_content', 'content');
            $config['themes_path']  = $this->prepPath($config['themes_path'], $path . DIRECTORY_SEPARATOR . '_themes', 'themes');
            $config['build_path']   = $this->prepPath($config['build_path'], $path, 'build');

            $themePath = $config['themes_path'] . DIRECTORY_SEPARATOR . $config['theme'];
            if (!is_dir($themePath)) {
                throw new \Exception('The theme "' . $themePath . '" does not exist');
            }

            $renderer = $this->getRenderer($themePath, $config['cache_path']);

            $output->writeln('Cleaning...');
            $this->cleanBuiltContent($config['build_path'], $output);

            $output->writeln('Building...');
            $contentFiles = $this->getContentFiles($config['content_path']);
            foreach ($contentFiles as $contentFile) {
                $content       = file_get_contents($contentFile);
                $meta          = $this->parseMeta($content);
                $parsedContent = $this->parseContent($content);

                $filename     = basename($contentFile, '.md');
                $filepath     = str_replace($config['content_path'], $config['build_path'], dirname($contentFile));
                $fullFilepath = $filepath . DIRECTORY_SEPARATOR . $filename . '.html';

                if (!is_dir($filepath)) {
                    mkdir($filepath, 0777, true);
                }

                $html = $renderer->render($meta['template'], [
                    'config'  => $config,
                    'title'   => $meta['title'],
                    'content' => $parsedContent,
                ]);
                file_put_contents($fullFilepath, $html);

                $output->writeln(str_replace($config['build_path'], '', $fullFilepath) . ' generated...');
            }

            $output->writeln('<info>Finished building site</info>');
        } catch (\Exception $e) {
            $output->writeln('<error>' . $e->getMessage() . '</error>');
        }
    }

    /**
     * Get the site config
     *
     * @param string $sitePath
     * @return array
     */
    protected function getConfig($sitePath)
    {
        if (file_exists($sitePath . DIRECTORY_SEPARATOR . 'config.yml')) {
            $config = file_get_contents($sitePath . DIRECTORY_SEPARATOR . 'config.yml');

            $yaml         = new YamlParser();
            $parsedConfig = $yaml->parse($config);

            if (is_array($parsedConfig) && !empty($parsedConfig)) {
                $parsedConfig = array_merge($this->configDefaults, $parsedConfig);
            } else {
                $parsedConfig = $this->configDefaults;
            }

            return $parsedConfig;
        }

        return $this->configDefaults;
    }

    /**
     * Get the renderer
     *
     * @param string $themePath
     * @param string $cachePath
     * @return AbstractEngineRenderer
     */
    protected function getRenderer($themePath, $cachePath)
    {
        return new BladeRenderer([$themePath], ['cache_path' => $cachePath]);
    }

    /**
     * Clean all previously built files
     *
     * @param string $buildPath
     */
    protected function cleanBuiltContent($buildPath, OutputInterface $output)
    {
        if (!is_dir($buildPath)) {
            return;
        }

        $rdi = new \RecursiveDirectoryIterator($buildPath, \RecursiveDirectoryIterator::SKIP_DOTS);
        $rii = new \RecursiveIteratorIterator($rdi, \RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($rii as $fileInfo) {
            if ($fileInfo->isFile() && $fileInfo->getExtension() == 'html') {
                $output->writeln('Removing file: ' . str_replace($buildPath, '', $fileInfo->getRealPath()) . '...');
                unlink($fileInfo->getRealPath());
            }
        }
    }

    /**
     * Get all of the valid files from the contents directory
     *
     * @param string $contentPath
     * @return array
     */
    protected function getContentFiles($contentPath)
    {
        $contentFiles = [];
        $rdi          = new \RecursiveDirectoryIterator($contentPath);
        $rii          = new \RecursiveIteratorIterator($rdi);
        foreach ($rii as $fileInfo) {
            if ($fileInfo->isFile() && $fileInfo->getExtension() == 'md') {
                $contentFiles[] = $fileInfo->getPathname();
            }
        }

        return $contentFiles;
    }

    /**
     * Parse the file meta from the content
     *
     * @param string $content
     * @return array
     */
    protected function parseMeta($content)
    {
        $parts = preg_split('/\-{3,}/m', $content, 2);
        $meta  = isset($parts[0]) ? $parts[0] : '';

        $yaml       = new YamlParser();
        $parsedMeta = $yaml->parse($meta);

        if (is_array($parsedMeta)) {
            $parsedMeta = array_merge($this->metaDefaults, $parsedMeta);
        } else {
            $parsedMeta = $this->metaDefaults;
        }
<commit_msg>Fix parseMeta function<commit_after><?php

namespace Handle\Commands;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Yaml\Parser as YamlParser;
use Parsedown;
use Windwalker\Renderer\BladeRenderer;

class BuildCommand extends Command
{
    protected $configDefaults = [
        'site_title'   => 'Handle',
        'theme'        => 'default',
        'cache_path'   => '_cache',
        'content_path' => '_content',
        'themes_path'  => '_themes',
        'build_path'   => '',
    ];

    protected $metaDefaults = [
        'title'    => '',
        'template' => 'index',
    ];

    protected function configure()
    {
        $this->setName('build')
             ->setDescription('Build your Handle site by generating the static output')
             ->addOption('path', null, InputOption::VALUE_REQUIRED, 'Path to your Handle site');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $path = $input->getOption('path');
        if (!$path || $path == '.') {
            $path = getcwd();
        }

        try {
            $config = $this->getConfig($path);

            $config['cache_path']   = $this->prepPath($config['cache_path'], $path . DIRECTORY_SEPARATOR . '_cache', 'cache');
            $config['content_path'] = $this->prepPath($config['content_path'], $path . DIRECTORY_SEPARATOR . '_content', 'content');
            $config['themes_path']  = $this->prepPath($config['themes_path'], $path . DIRECTORY_SEPARATOR . '_themes', 'themes');
            $config['build_path']   = $this->prepPath($config['build_path'], $path, 'build');

            $themePath = $config['themes_path'] . DIRECTORY_SEPARATOR . $config['theme'];
            if (!is_dir($themePath)) {
                throw new \Exception('The theme "' . $themePath . '" does not exist');
            }

            $renderer = $this->getRenderer($themePath, $config['cache_path']);

            $output->writeln('Cleaning...');
            $this->cleanBuiltContent($config['build_path'], $output);

            $output->writeln('Building...');
            $contentFiles = $this->getContentFiles($config['content_path']);
            foreach ($contentFiles as $contentFile) {
                $content       = file_get_contents($contentFile);
                $meta          = $this->parseMeta($content);
                $parsedContent = $this->parseContent($content);

                $filename     = basename($contentFile, '.md');
                $filepath     = str_replace($config['content_path'], $config['build_path'], dirname($contentFile));
                $fullFilepath = $filepath . DIRECTORY_SEPARATOR . $filename . '.html';

                if (!is_dir($filepath)) {
                    mkdir($filepath, 0777, true);
                }

                $html = $renderer->render($meta['template'], [
                    'config'  => $config,
                    'title'   => $meta['title'],
                    'content' => $parsedContent,
                ]);
                file_put_contents($fullFilepath, $html);

                $output->writeln(str_replace($config['build_path'], '', $fullFilepath) . ' generated...');
            }

            $output->writeln('<info>Finished building site</info>');
        } catch (\Exception $e) {
            $output->writeln('<error>' . $e->getMessage() . '</error>');
        }
    }

    /**
     * Get the site config
     *
     * @param string $sitePath
     * @return array
     */
    protected function getConfig($sitePath)
    {
        if (file_exists($sitePath . DIRECTORY_SEPARATOR . 'config.yml')) {
            $config = file_get_contents($sitePath . DIRECTORY_SEPARATOR . 'config.yml');

            $yaml         = new YamlParser();
            $parsedConfig = $yaml->parse($config);

            if (is_array($parsedConfig) && !empty($parsedConfig)) {
                $parsedConfig = array_merge($this->configDefaults, $parsedConfig);
            } else {
                $parsedConfig = $this->configDefaults;
            }

            return $parsedConfig;
        }

        return $this->configDefaults;
    }

    /**
     * Get the renderer
     *
     * @param string $themePath
     * @param string $cachePath
     * @return AbstractEngineRenderer
     */
    protected function getRenderer($themePath, $cachePath)
    {
        return new BladeRenderer([$themePath], ['cache_path' => $cachePath]);
    }

    /**
     * Clean all previously built files
     *
     * @param string $buildPath
     */
    protected function cleanBuiltContent($buildPath, OutputInterface $output)
    {
        if (!is_dir($buildPath)) {
            return;
        }

        $rdi = new \RecursiveDirectoryIterator($buildPath, \RecursiveDirectoryIterator::SKIP_DOTS);
        $rii = new \RecursiveIteratorIterator($rdi, \RecursiveIteratorIterator::CHILD_FIRST);
        foreach ($rii as $fileInfo) {
            if ($fileInfo->isFile() && $fileInfo->getExtension() == 'html') {
                $output->writeln('Removing file: ' . str_replace($buildPath, '', $fileInfo->getRealPath()) . '...');
                unlink($fileInfo->getRealPath());
            }
        }
    }

    /**
     * Get all of the valid files from the contents directory
     *
     * @param string $contentPath
     * @return array
     */
    protected function getContentFiles($contentPath)
    {
        $contentFiles = [];
        $rdi          = new \RecursiveDirectoryIterator($contentPath);
        $rii          = new \RecursiveIteratorIterator($rdi);
        foreach ($rii as $fileInfo) {
            if ($fileInfo->isFile() && $fileInfo->getExtension() == 'md') {
                $contentFiles[] = $fileInfo->getPathname();
            }
        }

        return $contentFiles;
    }

    /**
     * Parse the file meta from the content
     *
     * @param string $content
     * @return array
     */
    protected function parseMeta($content)
    {
        if (!preg_match('/\-{3,}/m', $content)) {
            return $this->metaDefaults;
        }

        $parts = preg_split('/\-{3,}/m', $content, 2);
        $meta  = isset($parts[0]) ? $parts[0] : '';

        $yaml       = new YamlParser();
        $parsedMeta = $yaml->parse($meta);

        if (is_array($parsedMeta)) {
            $parsedMeta = array_merge($this->metaDefaults, $parsedMeta);
        } else {
            $parsedMeta = $this->metaDefaults;
        }

{'fraction_non_alphanumeric': 0.14977238239757207, 'fraction_numerical': 0.0012898330804248861, 'mean_word_length': 2.1458233890214795, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 108, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1438536', 'n_tokens_mistral': 3761, 'n_tokens_neox': 3643, 'n_words': 689}