diff --git a/.gitignore b/.gitignore index b932afd..cd2a620 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ /.phpunit.result.cache /composer.lock /vendor/ +/build/ diff --git a/README.md b/README.md index da8e8e1..1a12400 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,33 @@ $fixer = new Fixer(array("Trademark", "SmartQuotes")); $fixedContent = $fixer->fixString('Here is a "protip(c)"!'); // Here is a “protip©”! ``` +CLI usage +========= + +You can run a standalone version of JoliTypo by downloading [the PHAR version](https://github.com/jolicode/JoliTypo/releases/latest) + +Run `jolitypo.phar --help` to know how to configure the Fixer. + +``` +Fix Microtypography glitches inside your HTML content. + +Usage: ./jolitypo.phar [--rules="Ellipsis,Dimension,Unit,Dash,SmartQuotes,NoSpaceBeforeComma,CurlyQuote,Hyphen,Trademark"] --locale locale --file file [--quiet] [--help] + +Required Arguments: + --locale locale + Locale of the content to fix. + --file file + File to fix. + +Optional Arguments: + --rules="Ellipsis,Dimension,Unit,Dash,SmartQuotes,NoSpaceBeforeComma,CurlyQuote,Hyphen,Trademark" + Rules used to fix the content, comma separated. + --quiet + Do not output anything. + --help + Show this help. +``` + Installation ============ @@ -71,6 +98,7 @@ Integrations - (Built-in) [Symfony Bundle](src/JoliTypo/Bridge/Symfony) - (Built-in) [Twig extension](src/JoliTypo/Bridge/Twig) +- (Built-in) [CLI](https://github.com/jolicode/JoliTypo/releases/latest) - [Wordpress plugin](http://wordpress.org/plugins/typofr/) - [Drupal module](https://github.com/Anaethelion/JoliTypo-for-Drupal) - [Joomla plugin](https://github.com/YGomiero/typographe) @@ -247,6 +275,13 @@ Add your own Fixer / Contribute a Fixer - Implement `JoliTypo\FixerInterface`; - Send your Pull request. +Build the PHAR version +====================== + +Install [Box](https://github.com/box-project/box) and its dependencies with `composer bin box require --dev humbug/box` + +Then, run `composer run compile` + ### Contribution guidelines - You MUST write code in english; diff --git a/box.json b/box.json new file mode 100644 index 0000000..9a7de5d --- /dev/null +++ b/box.json @@ -0,0 +1,27 @@ +{ + "chmod": "0755", + "directories": [ + "src" + ], + "files": [ + "LICENSE", + "vendor/autoload.php" + ], + "finder": [ + { + "name": [ + "*.php", + "*.txt", + "*.properties", + "*.ini", + "*.dic" + ], + "exclude": ["tests", "Tests", "phpunit"], + "in": "vendor" + } + ], + "git-version": "git_version", + "main": "jolitypo", + "output": "build/jolitypo.phar", + "stub": true +} diff --git a/composer.json b/composer.json index 64276b3..8e1e7fc 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,9 @@ "php": ">=7.2.0", "ext-mbstring": "*", "lib-libxml": "*", - "org_heigl/hyphenator": "~2.6.0" + "org_heigl/hyphenator": "~2.6.0", + "symfony/console": "^5.3", + "symfony/finder": "^5.3" }, "require-dev": { "friendsofphp/php-cs-fixer": "^2", @@ -36,6 +38,7 @@ }, "scripts": { "test": "vendor/bin/simple-phpunit -c phpunit.xml.dist", - "cs": "vendor/bin/php-cs-fixer fix" + "cs": "vendor/bin/php-cs-fixer fix", + "compile": "bin/box.phar compile" } } diff --git a/jolitypo b/jolitypo new file mode 100755 index 0000000..dbaa3ee --- /dev/null +++ b/jolitypo @@ -0,0 +1,70 @@ +#!/usr/bin/env php +setName('JoliTypo') + ->setDescription('Fix Microtypography glitches inside your HTML content.') + ->addArgument('path', InputArgument::REQUIRED, 'Path of file(s) to fix.') + ->addOption('locale', 'l', InputOption::VALUE_REQUIRED, 'Locale of the content to fix. Ex: "fr_FR"') + ->addOption('depth', 'd', InputOption::VALUE_OPTIONAL, 'Depth to find files if "path" is a directory.', 1) + ->addOption('rules', 'r', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL, 'Set of rules to apply.', []) + ->setCode(function (InputInterface $input, OutputInterface $output) { + $io = new SymfonyStyle($input, $output); + + $path = $input->getArgument('path'); + $depth = $input->getOption('depth'); + $locale = $input->getOption('locale'); + $rules = $input->getOption('rules'); + + $recommendedRulesByLocale = [ + 'en_GB' => ['Ellipsis', 'Dimension', 'Unit', 'Dash', 'SmartQuotes', 'NoSpaceBeforeComma', 'CurlyQuote', 'Hyphen', 'Trademark'], + 'fr_FR' => ['Ellipsis', 'Dimension', 'Unit', 'Dash', 'SmartQuotes', 'FrenchNoBreakSpace', 'NoSpaceBeforeComma', 'CurlyQuote', 'Hyphen', 'Trademark'], + 'fr_CA' => ['Ellipsis', 'Dimension', 'Unit', 'Dash', 'SmartQuotes', 'NoSpaceBeforeComma', 'CurlyQuote', 'Hyphen', 'Trademark'], + 'de_DE' => ['Ellipsis', 'Dimension', 'Unit', 'Dash', 'SmartQuotes', 'NoSpaceBeforeComma', 'CurlyQuote', 'Hyphen', 'Trademark'], + ]; + + if (!is_dir($path) && !file_exists($path)) { + $io->error(sprintf('The path "%s" does not exist.', $path)); + exit(Command::FAILURE); + } + + if ($rules) { + $rules = explode(',', $rules); + } elseif (array_key_exists($locale, $recommendedRulesByLocale)) { + $rules = $recommendedRulesByLocale[$locale]; + } else { + $io->error(sprintf('There is no recommended rules for "%s" locale. Please specify manually the rules to apply.', $locale)); + exit(Command::FAILURE); + } + + $fixer = new Fixer($rules); + $fixer->setLocale($locale); + + if (is_dir($path)) { + $finder = new Finder(); + + foreach ($finder->path($path)->depth($depth)->files() as $file) { + $fixedContent = $fixer->fix(file_get_contents($file->getRealPath())); + file_put_contents($file->getRealPath(), $fixedContent); + } + + $io->success(sprintf('All files in "%s" has been fixed with success!', $path)); + } elseif (is_file($path)) { + $fixedContent = $fixer->fix(file_get_contents($path)); + file_put_contents($path, $fixedContent); + + $io->success(sprintf('"%s" content has been fixed with success!', $path)); + } + }) + ->run();