diff --git a/composer.json b/composer.json
index caeaed68..2ccb30e4 100644
--- a/composer.json
+++ b/composer.json
@@ -38,6 +38,7 @@
"opdavies/sculpin-twig-markdown-bundle": "^0.1",
"phpstan/phpstan": "^0.11.8",
"sculpin/sculpin": "^3.0",
+ "spatie/string": "^2.2",
"tightenco/collect": "^6.1",
"wikimedia/composer-merge-plugin": "^1.4"
},
diff --git a/composer.lock b/composer.lock
index 43d4f183..787b01ba 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,59 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "f2cef690a3a7c29f5d7ecf57be677451",
+ "content-hash": "b1a531864c4def9f8125f2dd5e8f098b",
"packages": [
+ {
+ "name": "anahkiasen/underscore-php",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Anahkiasen/underscore-php.git",
+ "reference": "48f97b295c82d99c1fe10d8b0684c43f051b5580"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Anahkiasen/underscore-php/zipball/48f97b295c82d99c1fe10d8b0684c43f051b5580",
+ "reference": "48f97b295c82d99c1fe10d8b0684c43f051b5580",
+ "shasum": ""
+ },
+ "require": {
+ "doctrine/inflector": "^1.0",
+ "patchwork/utf8": "^1.2",
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "fabpot/php-cs-fixer": "2.0.*@dev",
+ "phpunit/phpunit": "^4.6"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Underscore\\": [
+ "src",
+ "tests"
+ ]
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Maxime Fabre",
+ "email": "ehtnam6@gmail.com"
+ }
+ ],
+ "description": "A redacted port of Underscore.js for PHP",
+ "keywords": [
+ "internals",
+ "laravel",
+ "toolkit"
+ ],
+ "abandoned": true,
+ "time": "2015-05-16T19:24:58+00:00"
+ },
{
"name": "composer/ca-bundle",
"version": "1.2.5",
@@ -2014,6 +2065,68 @@
],
"time": "2018-07-02T15:55:56+00:00"
},
+ {
+ "name": "patchwork/utf8",
+ "version": "v1.3.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/tchwork/utf8.git",
+ "reference": "d296e0026e7ce10b2a9fe594feca9628ef00e9e8"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/tchwork/utf8/zipball/d296e0026e7ce10b2a9fe594feca9628ef00e9e8",
+ "reference": "d296e0026e7ce10b2a9fe594feca9628ef00e9e8",
+ "shasum": ""
+ },
+ "require": {
+ "lib-pcre": ">=7.3",
+ "php": ">=5.3.0"
+ },
+ "require-dev": {
+ "symfony/phpunit-bridge": "^3.4|^4.4"
+ },
+ "suggest": {
+ "ext-iconv": "Use iconv for best performance",
+ "ext-intl": "Use Intl for best performance",
+ "ext-mbstring": "Use Mbstring for best performance",
+ "ext-wfio": "Use WFIO for UTF-8 filesystem access on Windows"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.3-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Patchwork\\": "src/Patchwork/"
+ },
+ "classmap": [
+ "src/Normalizer.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "(Apache-2.0 or GPL-2.0)"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ }
+ ],
+ "description": "Portable and performant UTF-8, Unicode and Grapheme Clusters for PHP",
+ "homepage": "https://github.com/tchwork/utf8",
+ "keywords": [
+ "grapheme",
+ "i18n",
+ "unicode",
+ "utf-8",
+ "utf8"
+ ],
+ "time": "2019-12-03T14:44:12+00:00"
+ },
{
"name": "php-cs-fixer/diff",
"version": "v1.3.0",
@@ -3044,6 +3157,59 @@
],
"time": "2015-10-13T18:44:15+00:00"
},
+ {
+ "name": "spatie/string",
+ "version": "2.2.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/spatie/string.git",
+ "reference": "28607b9925b4f0499d48570553ca419c6298e26b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/spatie/string/zipball/28607b9925b4f0499d48570553ca419c6298e26b",
+ "reference": "28607b9925b4f0499d48570553ca419c6298e26b",
+ "shasum": ""
+ },
+ "require": {
+ "anahkiasen/underscore-php": "^2.0",
+ "php": ">=5.6.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "5.*",
+ "scrutinizer/ocular": "~1.1"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/string_functions.php"
+ ],
+ "psr-4": {
+ "Spatie\\String\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Freek Van der Herten",
+ "email": "freek@spatie.be",
+ "homepage": "https://murze.be",
+ "role": "Developer"
+ }
+ ],
+ "description": "String handling evolved",
+ "homepage": "https://github.com/spatie/string",
+ "keywords": [
+ "handling",
+ "handy",
+ "spatie",
+ "string"
+ ],
+ "time": "2017-11-08T14:28:57+00:00"
+ },
{
"name": "symfony/config",
"version": "v4.4.2",
diff --git a/generators/blog-post.php b/generators/blog-post.php
new file mode 100644
index 00000000..49b96e39
--- /dev/null
+++ b/generators/blog-post.php
@@ -0,0 +1,135 @@
+addCommands([
+ new class extends Command
+ {
+ /**
+ * {@inheritdoc}
+ */
+ protected static $defaultName = 'main';
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function configure()
+ {
+ $this->addArgument('title', InputArgument::OPTIONAL);
+ $this->addArgument('excerpt', InputArgument::OPTIONAL);
+ $this->addArgument('tags', InputArgument::IS_ARRAY);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function interact(InputInterface $input, OutputInterface $output)
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ if (!$input->getArgument('title')) {
+ $input->setArgument('title', $io->askQuestion(
+ new Question('The post title')
+ ));
+ }
+
+ if (!$input->getArgument('excerpt')) {
+ $input->setArgument('excerpt', $io->askQuestion(
+ new Question('The post excerpt')
+ ));
+ }
+
+ $io->writeln("\nEnter any tags for the post.\nPress enter to continue.\n");
+ $tags = [];
+
+ while (true) {
+ $tag = $io->askQuestion(
+ new Question('Enter a tag')
+ );
+
+ if (empty($tag)) {
+ break;
+ }
+
+ $tags[] = $tag;
+ }
+
+ $input->setArgument('tags', $tags);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $io = new SymfonyStyle($input, $output);
+
+ $title = $input->getArgument('title');
+
+ if (!$title) {
+ throw new \RuntimeException('No title');
+ }
+
+ $excerpt = $input->getArgument('excerpt') ?? $title;
+ $slug = (new Str($title))->slugify();
+ $tags = '[' . implode(', ', $input->getArgument('tags')) . ']';
+ $date = (new \DateTime())->format('Y-m-d');
+
+ $contents = $this->generateFileFromStub(
+ $title,
+ $excerpt,
+ $tags,
+ $date
+ );
+
+ $this->writeFile($slug, $contents);
+ $this->createImagesDirectory($slug);
+
+ $io->listing([
+ "{$slug}.md"
+ ]);
+ }
+
+ private function generateFileFromStub(...$args): string
+ {
+ [$title, $excerpt, $tags, $date] = $args;
+
+ return <<setDefaultCommand('main');
+$application->run();