From 4a1961b315aeeb7ac9eac5f866ca7b4448316da3 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Sun, 1 May 2022 20:07:04 +0300 Subject: [PATCH 01/16] Bump up dev version --- CHANGELOG.textile | 2 ++ src/Netcarver/Textile/Parser.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.textile b/CHANGELOG.textile index 6f13c2ef..fb3a03a7 100644 --- a/CHANGELOG.textile +++ b/CHANGELOG.textile @@ -2,6 +2,8 @@ h1. Changelog Here's a summary of changes in each release. The list doesn't include some small changes or updates to test cases. +h2. Version 3.7.8 - upcoming + h2. "Version 3.7.7 - 2022/05/01":https://github.com/textile/php-textile/releases/tag/v3.7.7 * Fix deprecation errors that appear on PHP >= 8.1 about preg_split limit argument's NULL value. diff --git a/src/Netcarver/Textile/Parser.php b/src/Netcarver/Textile/Parser.php index 0d052416..e94ffb6f 100644 --- a/src/Netcarver/Textile/Parser.php +++ b/src/Netcarver/Textile/Parser.php @@ -370,7 +370,7 @@ class Parser * * @var string */ - protected $ver = '3.7.7'; + protected $ver = '3.7.8-dev'; /** * Regular expression snippets. From 8b62935763d431deb0ff1324e1c72f35ff92b008 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Sun, 1 May 2022 22:29:16 +0300 Subject: [PATCH 02/16] Add setAlignClasses option This allows enabling alignment classes independent of the HTML5 document type. This avoid generating the invalid align="center" attribute when using XHTML and trying to center align images. The generated align-center, align-left and align-right classes can be styled using CSS to fit one's specific usage case. Fixes #218 Closes #219 --- src/Netcarver/Textile/Parser.php | 81 +++++++++++++++++++++-- test/Netcarver/Textile/Test/BasicTest.php | 39 +++++++++++ 2 files changed, 114 insertions(+), 6 deletions(-) diff --git a/src/Netcarver/Textile/Parser.php b/src/Netcarver/Textile/Parser.php index e94ffb6f..d8088e8e 100644 --- a/src/Netcarver/Textile/Parser.php +++ b/src/Netcarver/Textile/Parser.php @@ -365,6 +365,9 @@ class Parser { + const DOCTYPE_HTML5 = 'html5'; + const DOCTYPE_XHTML = 'xhtml'; + /** * Version number. * @@ -623,6 +626,13 @@ class Parser */ protected $lineWrapEnabled = true; + /** + * Whether aligning with class selectors is enabled. + * + * @var bool|null + */ + protected $isAlignClassesEnabled = null; + /** * Pattern for punctation. * @@ -843,8 +853,8 @@ class Parser * @since 3.6.0 */ protected $doctypes = array( - 'xhtml', - 'html5', + self::DOCTYPE_XHTML, + self::DOCTYPE_HTML5, ); /** @@ -1031,7 +1041,8 @@ class Parser * a whole, such as the output doctype. To instruct the parser to return * HTML5 markup instead of XHTML, set $doctype argument to 'html5'. * - * bc. $parser = new \Netcarver\Textile\Parser('html5'); + * bc. use Netcarver\Textile\Parser; + * $parser = new Parser(Parser::DOCTYPE_HTML5); * echo $parser->parse('HTML(HyperText Markup Language)"); * * @param string $doctype The output document type, either 'xhtml' or 'html5' @@ -1039,6 +1050,8 @@ class Parser * @see Parser::configure() * @see Parser::parse() * @see Parser::setDocumentType() + * @see Parser::DOCTYPE_HTML5 + * @see Parser::DOCTYPE_XHTML * @api */ public function __construct($doctype = 'xhtml') @@ -1137,15 +1150,18 @@ protected function configure() /** * Sets the output document type. * - * bc. $parser = new \Netcarver\Textile\Parser(); + * bc. use Netcarver\Textile\Parser; + * $parser = new Parser(); * echo $parser - * ->setDocumentType('html5') + * ->setDocumentType(Parser::DOCTYPE_HTML5) * ->parse('HTML(HyperText Markup Language)"); * * @param string $doctype Either 'xhtml' or 'html5' * @return Parser This instance * @since 3.6.0 * @see Parser::getDocumentType() + * @see Parser::DOCTYPE_HTML5 + * @see Parser::DOCTYPE_XHTML * @api */ public function setDocumentType($doctype) @@ -1477,6 +1493,59 @@ public function isRawBlocksEnabled() return (bool) $this->rawBlocksEnabled; } + /** + * Sets class alignment mode independent of the document type. + * + * In HTML5 document type, img elements are generated with align-left, + * align-center and align-right class selectors rather than align + * attribute being added to the image. + * + * With this option you can enable that functionality in XHTML document type mode too. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * $parser + * ->setAlignClasses(true) + * ->parse(!<image.png!); + * + * Generates: + * + * bc. <p><img alt="" class="align-left" src="image.png" /></p> + * + * @param bool $enabled TRUE to enable, FALSE to disable + * @return Parser This instance + * @since 3.8.0 + * @api + */ + public function setAlignClasses($enabled) + { + $this->isAlignClassesEnabled = (bool) $enabled; + return $this; + } + + /** + * Whether class alignment mode is enabled. + * + * bc. $parser = new \Netcarver\Textile\Parser(); + * if ($parser->isAlignClassesEnabled() === true) { + * echo 'Images are aligned with class instead of align attribute'; + * } + * + * @return bool TRUE if enabled, FALSE otherwise + * @since 3.8.0 + * @see Parser::setAlignClasses() + * @api + */ + public function isAlignClassesEnabled() + { + if ($this->isAlignClassesEnabled === null + && $this->getDocumentType() === self::DOCTYPE_HTML5 + ) { + return true; + } + + return (bool) $this->isAlignClassesEnabled; + } + /** * Enables and disables block-level tags and formatting features. * @@ -4623,7 +4692,7 @@ protected function fImage($m) ); if (isset($alignments[$align])) { - if ($this->getDocumentType() === 'html5') { + if ($this->isAlignClassesEnabled()) { $extras = 'align-'.$alignments[$align]; $align = ''; } else { diff --git a/test/Netcarver/Textile/Test/BasicTest.php b/test/Netcarver/Textile/Test/BasicTest.php index 0d03b29f..1512a778 100644 --- a/test/Netcarver/Textile/Test/BasicTest.php +++ b/test/Netcarver/Textile/Test/BasicTest.php @@ -273,4 +273,43 @@ public function testLinkPrefix() $parser = new Textile(); $this->assertEquals('test', $parser->setImagePrefix('test')->getImagePrefix()); } + + public function testAlignClasses() + { + $parser = new Textile(); + + $this->assertFalse( + $parser->isAlignClassesEnabled() + ); + + $parser->setDocumentType(Textile::DOCTYPE_HTML5); + + $this->assertTrue( + $parser->isAlignClassesEnabled() + ); + + $parser->setAlignClasses(false); + + $this->assertFalse( + $parser->isAlignClassesEnabled() + ); + + $parser->setDocumentType(Textile::DOCTYPE_XHTML); + + $this->assertFalse( + $parser->isAlignClassesEnabled() + ); + + $parser->setAlignClasses(true); + + $this->assertTrue( + $parser->isAlignClassesEnabled() + ); + + $parser->setAlignClasses(false); + + $this->assertFalse( + $parser->isAlignClassesEnabled() + ); + } } From 631d839c136d0e93288aa9d1d02f9e97c94a31b0 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Sun, 1 May 2022 22:34:44 +0300 Subject: [PATCH 03/16] Update changelog --- CHANGELOG.textile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.textile b/CHANGELOG.textile index fb3a03a7..c226896d 100644 --- a/CHANGELOG.textile +++ b/CHANGELOG.textile @@ -2,7 +2,9 @@ h1. Changelog Here's a summary of changes in each release. The list doesn't include some small changes or updates to test cases. -h2. Version 3.7.8 - upcoming +h2. Version 3.8.0 - upcoming + +* Added @Parser::setAlignClasses()@ and @Parser::isAlignClassesEnabled@. This can be used to enable img alignment classes in XHTML output document mode, instead of the default align attribute. h2. "Version 3.7.7 - 2022/05/01":https://github.com/textile/php-textile/releases/tag/v3.7.7 From 997caf101220dcfd58efff308fd3fc30de179e14 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Sun, 1 May 2022 22:42:38 +0300 Subject: [PATCH 04/16] Document DOCTYPE constant addition --- CHANGELOG.textile | 1 + src/Netcarver/Textile/Parser.php | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/CHANGELOG.textile b/CHANGELOG.textile index c226896d..4a5d795a 100644 --- a/CHANGELOG.textile +++ b/CHANGELOG.textile @@ -5,6 +5,7 @@ Here's a summary of changes in each release. The list doesn't include some small h2. Version 3.8.0 - upcoming * Added @Parser::setAlignClasses()@ and @Parser::isAlignClassesEnabled@. This can be used to enable img alignment classes in XHTML output document mode, instead of the default align attribute. +* Added @Parser::DOCTYPE_HTML5@ and @Parser::DOCTYPE_XHTML@ constants. These can be used with @Parser::setDocumentType()@ to specify the output document type. h2. "Version 3.7.7 - 2022/05/01":https://github.com/textile/php-textile/releases/tag/v3.7.7 diff --git a/src/Netcarver/Textile/Parser.php b/src/Netcarver/Textile/Parser.php index d8088e8e..4ae468e6 100644 --- a/src/Netcarver/Textile/Parser.php +++ b/src/Netcarver/Textile/Parser.php @@ -365,7 +365,18 @@ class Parser { + /** + * HTML5 document type. + * + * @since 3.8.0 + */ const DOCTYPE_HTML5 = 'html5'; + + /** + * XHTML document type. + * + * @since 3.8.0 + */ const DOCTYPE_XHTML = 'xhtml'; /** From d03daef779e326d05264759645d0d7ef38714d14 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Tue, 3 May 2022 20:38:31 +0300 Subject: [PATCH 05/16] Add REPL using PsySH --- Makefile | 8 +++++++- composer.json | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e41115ac..a77b2b3b 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all clean help lint lint-fix test test-static test-unit bump bump-dev process-reports +.PHONY: all clean help lint lint-fix repl test test-static test-unit bump bump-dev process-reports IMAGE?=php_8_1 PHP = docker-compose run --rm $(IMAGE) @@ -26,6 +26,9 @@ test-static: vendor test-unit: vendor $(PHP) composer test:unit +repl: vendor + $(PHP) composer repl + bump: vendor $(PHP) composer bump @@ -60,6 +63,9 @@ help: @echo " $$ make test-static" @echo " Run static tests" @echo "" + @echo " $$ make repl" + @echo " Launch read-print-eval loop" + @echo "" @echo " $$ make bump" @echo " Bump version" @echo "" diff --git a/composer.json b/composer.json index 0632b995..e958b85d 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,8 @@ "phpstan/phpstan": "1.6.3", "phpunit/phpunit": "^9.5.20", "squizlabs/php_codesniffer": "3.*", - "symfony/yaml": "^4.4.3" + "symfony/yaml": "^4.4.3", + "psy/psysh": "^0.11.2" }, "extra": { "branch-alias": { @@ -44,6 +45,7 @@ "bump-dev": "@php ./scripts/release.php --dev", "lint": "phpcs", "lint-fix": "phpcbf", + "repl": "psysh", "test:static": "phpstan analyse --level 8 src", "test:unit": "XDEBUG_MODE=coverage phpunit" } From 1c74a11f1942de8c782bf36ee97645dcdca572de Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Wed, 4 May 2022 22:04:21 +0300 Subject: [PATCH 06/16] Update multi-target image support --- Makefile | 18 +++++++++++++++--- docker-compose.yml | 4 ++-- docker/image/{php/8_1 => php_8_1}/Dockerfile | 0 3 files changed, 17 insertions(+), 5 deletions(-) rename docker/image/{php/8_1 => php_8_1}/Dockerfile (100%) diff --git a/Makefile b/Makefile index a77b2b3b..06aec936 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ -.PHONY: all clean help lint lint-fix repl test test-static test-unit bump bump-dev process-reports +.PHONY: all clean docker-build docker-images help lint lint-fix repl test test-static test-unit bump bump-dev process-reports IMAGE?=php_8_1 -PHP = docker-compose run --rm $(IMAGE) +PHP = docker-compose run --rm php all: test @@ -38,6 +38,12 @@ bump-dev: vendor process-reports: $(PHP) bash -c "test -e build/logs/clover.xml && sed -i 's/\/app\///' build/logs/clover.xml" +docker-build: + docker-compose build php + +docker-images: + @$(PHP) bash -c "cd docker/image && ls ." + help: @echo "Manage project" @echo "" @@ -81,8 +87,14 @@ help: @echo " $$ make process-reports" @echo " Formats test reports to use relative local file paths" @echo "" + @echo " $$ make docker-images" + @echo " Lists available Docker images" + @echo "" + @echo " $$ make docker-build" + @echo " Re-builds the Docker image" + @echo "" @echo "Environment variables:" @echo "" @echo " IMAGE" - @echo " docker-compose service name that is used to run the command" + @echo " Docker image that is used to run the command" @echo "" diff --git a/docker-compose.yml b/docker-compose.yml index a2928fde..9797397c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,8 +1,8 @@ version: '3' services: - php_8_1: - build: ./docker/image/php/8_1 + php: + build: ./docker/image/${IMAGE:-php_8_1} volumes: - .:/app - ${COMPOSER_HOME:-$HOME/.composer}:/tmp diff --git a/docker/image/php/8_1/Dockerfile b/docker/image/php_8_1/Dockerfile similarity index 100% rename from docker/image/php/8_1/Dockerfile rename to docker/image/php_8_1/Dockerfile From b2abb7b7aa2c6b5aad1760c54835151ab727b781 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Wed, 4 May 2022 22:34:52 +0300 Subject: [PATCH 07/16] Support slashes and brackets in class names Fixes #216 --- src/Netcarver/Textile/Parser.php | 24 ++++++++++++------------ test/fixtures/issue-216.yaml | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 test/fixtures/issue-216.yaml diff --git a/src/Netcarver/Textile/Parser.php b/src/Netcarver/Textile/Parser.php index 4ae468e6..fc59a718 100644 --- a/src/Netcarver/Textile/Parser.php +++ b/src/Netcarver/Textile/Parser.php @@ -2514,25 +2514,15 @@ protected function parseAttribsToArray($in, $element = '', $include_id = true, $ $matched = str_replace($sty[0], '', $matched); } - if (preg_match("/\[([^]]+)\]/U", $matched, $lng)) { - // Consume entire lang block -- valid or invalid. - $matched = str_replace($lng[0], '', $matched); - if ($element === 'code' && preg_match("/\[([a-zA-Z0-9_-]+)\]/U", $lng[0], $lng1)) { - $lang = $lng1[1]; - } elseif (preg_match("/\[([a-zA-Z]{2}(?:[\-\_][a-zA-Z]{2})?)\]/U", $lng[0], $lng2)) { - $lang = $lng2[1]; - } - } - if (preg_match("/\(([^()]+)\)/U", $matched, $cls)) { - $class_regex = "/^([-a-zA-Z 0-9_\.]*)$/"; + $class_regex = "/^([-a-zA-Z 0-9_\.\/\[\]]*)$/"; // Consume entire class block -- valid or invalid. $matched = str_replace($cls[0], '', $matched); // Only allow a restricted subset of the CSS standard characters for classes/ids. // No encoding markers allowed. - if (preg_match("/\(([-a-zA-Z 0-9_\.\:\#]+)\)/U", $cls[0], $cls)) { + if (preg_match("/\(([-a-zA-Z 0-9_\/\[\]\.\:\#]+)\)/U", $cls[0], $cls)) { $hashpos = strpos($cls[1], '#'); // If a textile class block attribute was found with a '#' in it // split it into the css class and css id... @@ -2552,6 +2542,16 @@ protected function parseAttribsToArray($in, $element = '', $include_id = true, $ } } + if (preg_match("/\[([^]]+)\]/U", $matched, $lng)) { + // Consume entire lang block -- valid or invalid. + $matched = str_replace($lng[0], '', $matched); + if ($element === 'code' && preg_match("/\[([a-zA-Z0-9_-]+)\]/U", $lng[0], $lng1)) { + $lang = $lng1[1]; + } elseif (preg_match("/\[([a-zA-Z]{2}(?:[\-\_][a-zA-Z]{2})?)\]/U", $lng[0], $lng2)) { + $lang = $lng2[1]; + } + } + if (preg_match("/([(]+)/", $matched, $pl)) { $style[] = "padding-left:" . strlen($pl[1]) . "em"; $matched = str_replace($pl[0], '', $matched); diff --git a/test/fixtures/issue-216.yaml b/test/fixtures/issue-216.yaml new file mode 100644 index 00000000..3a715349 --- /dev/null +++ b/test/fixtures/issue-216.yaml @@ -0,0 +1,14 @@ +Support slashes and brackets in class names: + input: | + p(m-auto w-6/12). Paragraph + + p(max-w-[140px]). Paragraph + + p(m-auto w-6/12 #unique). Paragraph + + expect: | + <p class="m-auto w-6/12">Paragraph</p> + + <p class="max-w-[140px]">Paragraph</p> + + <p class="m-auto w-6/12" id="unique">Paragraph</p> From b5c59225b3d9fe6cb74afa01c85e2b9f70032110 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Thu, 5 May 2022 11:25:17 +0300 Subject: [PATCH 08/16] Breakpoint support --- docker-compose.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index 9797397c..7375e787 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,6 +8,11 @@ services: - ${COMPOSER_HOME:-$HOME/.composer}:/tmp networks: - app + environment: + - XDEBUG_CONFIG + - XDEBUG_MODE + - XDEBUG_TRIGGER + - PHP_IDE_CONFIG networks: app: From 94bc325e5cbec20a22c14b47f0e58df0ddb5dc58 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Thu, 5 May 2022 20:55:07 +0300 Subject: [PATCH 09/16] Clean composer package meta and contents --- .gitattributes | 6 +++++- composer.json | 1 - 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index d95bec5c..3f83c868 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,10 +1,14 @@ +/docker export-ignore /scripts export-ignore /test export-ignore /.editorconfig export-ignore /.github export-ignore /.gitignore export-ignore -/.travis.yml export-ignore +/Makefile export-ignore +/docker-compose.yml export-ignore /phpcs.xml export-ignore +/phpstan.neon export-ignore /phpunit.xml export-ignore +/sonar-project.properties export-ignore /textile-wordmark.png export-ignore /.gitattributes export-ignore diff --git a/composer.json b/composer.json index e958b85d..54041811 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,6 @@ "homepage": "https://github.com/textile/php-textile", "keywords": ["php-textile", "textile", "parser", "markup", "language", "html", "format", "plaintext", "document"], "support": { - "irc": "irc://irc.freenode.net/textile", "wiki": "https://github.com/textile/php-textile/wiki", "issues": "https://github.com/textile/php-textile/issues", "source": "https://github.com/textile/php-textile" From e7a0fa8dec86b11a4c784df92a1f7b63a83c7c56 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Thu, 5 May 2022 21:10:21 +0300 Subject: [PATCH 10/16] Add development link to README --- README.textile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.textile b/README.textile index ef8db27d..b5504bfc 100644 --- a/README.textile +++ b/README.textile @@ -77,3 +77,7 @@ $parser h2. Getting in contact The PHP-Textile project welcomes constructive input and bug reports from users. Please "open an issue":https://github.com/textile/php-textile/issues on the repository for a comment, feature request or bug. + +h2. Development + +See "CONTRIBUTING.textile":https://github.com/textile/php-textile/blob/master/.github/CONTRIBUTING.textile. From 88abb355555517187ecd5933d56c10debd05dfa5 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Thu, 5 May 2022 21:21:32 +0300 Subject: [PATCH 11/16] Bump version number, fix script composer.json handling --- composer.json | 2 +- scripts/release.php | 4 ++-- src/Netcarver/Textile/Parser.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 54041811..6549133a 100644 --- a/composer.json +++ b/composer.json @@ -31,7 +31,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.7-dev" + "dev-master": "3.8-dev" } }, "scripts": { diff --git a/scripts/release.php b/scripts/release.php index 8b9c71da..ec61315f 100644 --- a/scripts/release.php +++ b/scripts/release.php @@ -72,8 +72,8 @@ }, ], 'composer.json' => [ - '/("dev-master": ")([^"])(")/' => function ($m) use ($dev) { - return $m[1] . $dev . $m[2]; + '/("dev-master": ")([^"]+)(")/' => function ($m) use ($dev) { + return $m[1] . $dev . $m[3]; } ] ]; diff --git a/src/Netcarver/Textile/Parser.php b/src/Netcarver/Textile/Parser.php index fc59a718..b4626b75 100644 --- a/src/Netcarver/Textile/Parser.php +++ b/src/Netcarver/Textile/Parser.php @@ -384,7 +384,7 @@ class Parser * * @var string */ - protected $ver = '3.7.8-dev'; + protected $ver = '3.8.0-dev'; /** * Regular expression snippets. From 79f9f903da25b17f203aca03f114fb83e25f18a5 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Fri, 20 May 2022 19:11:36 +0300 Subject: [PATCH 12/16] Split unit test files --- test/Netcarver/Textile/Test/BasicTest.php | 315 ----------------- .../Textile/Test/ParserFixtureTest.php | 112 ++++++ test/Netcarver/Textile/Test/ParserTest.php | 324 ++++++++++++++++++ test/Netcarver/Textile/Test/TagTest.php | 21 ++ 4 files changed, 457 insertions(+), 315 deletions(-) delete mode 100644 test/Netcarver/Textile/Test/BasicTest.php create mode 100644 test/Netcarver/Textile/Test/ParserFixtureTest.php create mode 100644 test/Netcarver/Textile/Test/ParserTest.php create mode 100644 test/Netcarver/Textile/Test/TagTest.php diff --git a/test/Netcarver/Textile/Test/BasicTest.php b/test/Netcarver/Textile/Test/BasicTest.php deleted file mode 100644 index 1512a778..00000000 --- a/test/Netcarver/Textile/Test/BasicTest.php +++ /dev/null @@ -1,315 +0,0 @@ -<?php - -namespace Netcarver\Textile\Test; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Yaml\Yaml; -use Netcarver\Textile\Parser as Textile; -use Netcarver\Textile\Tag; - -class BasicTest extends TestCase -{ - /** - * @dataProvider provider - */ - public function testAdd($file, $name, $test) - { - if (isset($test['class'])) { - $class = $test['class']; - } else { - $class = '\Netcarver\Textile\Parser'; - } - - $textile = new $class; - - if (isset($test['doctype'])) { - $textile->setDocumentType($test['doctype']); - } - - if (isset($test['setup'])) { - foreach ($test['setup'] as $setup) { - foreach ($setup as $method => $value) { - $textile = $textile->$method($value); - } - } - } - - if (isset($test['method'])) { - $method = trim($test['method']); - } else { - $method = 'parse'; - } - - $args = array(); - - if (isset($test['arguments'])) { - foreach ($test['arguments'] as $argument) { - foreach ($argument as $value) { - $args[] = $value; - } - } - } - - foreach (array('expect', 'input') as $field) { - $test[$field] = strtr($test[$field], array( - '\x20' => ' ', - )); - } - - $expect = rtrim($test['expect']); - array_unshift($args, $test['input']); - $input = rtrim(call_user_func_array(array($textile, $method), $args)); - - foreach (array('expect', 'input') as $variable) { - $$variable = preg_replace( - array( - '/ id="(fn|note)[a-z0-9\-]*"/', - '/ href="#(fn|note)[a-z0-9\-]*"/', - ), - '', - $$variable - ); - } - - $this->assertEquals($expect, $input, $name . ' in ' . $file); - $public = implode(', ', array_keys(get_object_vars($textile))); - $this->assertEquals('', $public, 'Leaking public class properties.'); - } - - public function testGetVersion() - { - $textile = new Textile(); - - $this->assertIsString( - $textile->getVersion() - ); - } - - public function testInvalidSymbol() - { - $this->expectException('\InvalidArgumentException'); - $textile = new Textile(); - $textile->getSymbol('invalidSymbolName'); - } - - public function testSetGetSymbol() - { - $textile = new Textile(); - $this->assertEquals('TestValue', $textile->setSymbol('test', 'TestValue')->getSymbol('test')); - $this->assertArrayHasKey('test', $textile->getSymbol()); - } - - public function testSetRelativeImagePrefixChaining() - { - $this->expectError(); - $textile = new Textile(); - $symbol = $textile->setRelativeImagePrefix('abc')->setSymbol('test', 'TestValue')->getSymbol('test'); - $this->assertEquals('TestValue', $symbol); - } - - public function testSetGetDimensionlessImage() - { - $textile = new Textile(); - $this->assertFalse($textile->getDimensionlessImages()); - $this->assertTrue($textile->setDimensionlessImages(true)->getDimensionlessImages()); - } - - public function testEncode() - { - $textile = new Textile(); - $encoded = $textile->textileEncode('& & | " "'); - $this->assertEquals('& & | &#x0022 "', $encoded); - } - - public function provider() - { - chdir(dirname(dirname(dirname(__DIR__)))); - $out = array(); - - if ($files = glob('*/*.yaml')) { - foreach ($files as $file) { - $yaml = Yaml::parseFile($file); - - foreach ($yaml as $name => $test) { - if (!is_array($test) || !isset($test['input']) || !isset($test['expect'])) { - continue; - } - - if (isset($test['assert']) && $test['assert'] === 'skip') { - continue; - } - - $out[] = array($file, $name, $test); - } - } - } - - return $out; - } - - public function testTagAttributesGenerator() - { - $attributes = new Tag(null, array('name' => 'value')); - $this->assertEquals(' name="value"', (string) $attributes); - } - - public function testDeprecatedEncodingArgument() - { - $this->expectDeprecation(); - $parser = new Textile(); - $this->assertEquals('content', @$parser->textileThis('content', false, true)); - $this->assertEquals('content', $parser->textileEncode('content')); - $parser->textileThis('content', false, true); - } - - public function testDeprecatedTextileCommon() - { - $this->expectDeprecation(); - $parser = new Parser\DeprecatedTextileCommon(); - $this->assertEquals(' content', @$parser->testTextileCommon(' content', false)); - $this->assertEquals(' content', @$parser->testTextileCommon(' content', true)); - $parser->testTextileCommon('content', false); - } - - public function testDeprecatedPrepare() - { - $this->expectDeprecation(); - $parser = new Parser\DeprecatedPrepare(); - $this->assertEquals(' content', @$parser->parse(' content')); - $parser->parse('content'); - } - - public function testDeprecatedTextileRestricted() - { - $this->expectDeprecation(); - $parser = new Textile(); - $this->assertEquals(' content', @$parser->textileRestricted(' content')); - $parser->textileRestricted('content'); - } - - public function testDeprecatedTextileThis() - { - $this->expectDeprecation(); - $parser = new Textile(); - $this->assertEquals(' content', @$parser->textileThis(' content')); - $parser->textileThis('content'); - } - - public function testDeprecatedSetRelativeImagePrefix() - { - $this->expectDeprecation(); - $parser = new Textile(); - @$parser->setRelativeImagePrefix('/1/'); - $this->assertEquals( - ' <img alt="" src="/1/2.jpg" /> <a href="/1/2">1</a>', - $parser->parse(' !2.jpg! "1":2') - ); - $parser->setRelativeImagePrefix('/1/'); - } - - public function testInvalidDocumentType() - { - $this->expectException('\InvalidArgumentException'); - new Textile('InvalidDocumentType'); - } - - public function testInstanceSharingAndFootnoteIndex() - { - $parser = new Textile(); - $previous = array('', '<p><strong>strong</strong></p>'); - - for ($i = 1; $i <= 100; $i++) { - $content = "Note[1]\n\nfn1. Footnote"; - $parsed[0] = $parser->parse($content); - $parsed[1] = $parser->parse('*strong*'); - $this->assertTrue($parsed[0] !== $previous[0]); - $this->assertEquals($previous[1], $parsed[1]); - $previous[0] = $parsed[0]; - $previous[1] = $parsed[1]; - } - } - - public function testLineSpaceEscaping() - { - $parser = new Textile(); - $this->assertEquals(' <strong>line</strong>', $parser->parse(' *line*')); - } - - public function testDocumentRoot() - { - $parser = new Textile(); - $parser->setDocumentRootDirectory(__DIR__); - $this->assertEquals(__DIR__, rtrim($parser->getDocumentRootDirectory(), '\\/')); - } - - public function testDisallowImages() - { - $parser = new Textile(); - $this->assertFalse($parser->setImages(false)->isImageTagEnabled()); - $this->assertTrue($parser->setImages(true)->isImageTagEnabled()); - } - - public function testLinkRelationShip() - { - $parser = new Textile(); - $this->assertEquals('test', $parser->setLinkRelationShip('test')->getLinkRelationShip()); - } - - public function testEnableRestrictedMode() - { - $parser = new Textile(); - $this->assertTrue($parser->setRestricted(true)->isRestrictedModeEnabled()); - $this->assertFalse($parser->setRestricted(false)->isRestrictedModeEnabled()); - } - - public function testImagePrefix() - { - $parser = new Textile(); - $this->assertEquals('test', $parser->setLinkPrefix('test')->getLinkPrefix()); - } - - public function testLinkPrefix() - { - $parser = new Textile(); - $this->assertEquals('test', $parser->setImagePrefix('test')->getImagePrefix()); - } - - public function testAlignClasses() - { - $parser = new Textile(); - - $this->assertFalse( - $parser->isAlignClassesEnabled() - ); - - $parser->setDocumentType(Textile::DOCTYPE_HTML5); - - $this->assertTrue( - $parser->isAlignClassesEnabled() - ); - - $parser->setAlignClasses(false); - - $this->assertFalse( - $parser->isAlignClassesEnabled() - ); - - $parser->setDocumentType(Textile::DOCTYPE_XHTML); - - $this->assertFalse( - $parser->isAlignClassesEnabled() - ); - - $parser->setAlignClasses(true); - - $this->assertTrue( - $parser->isAlignClassesEnabled() - ); - - $parser->setAlignClasses(false); - - $this->assertFalse( - $parser->isAlignClassesEnabled() - ); - } -} diff --git a/test/Netcarver/Textile/Test/ParserFixtureTest.php b/test/Netcarver/Textile/Test/ParserFixtureTest.php new file mode 100644 index 00000000..bd8bbf14 --- /dev/null +++ b/test/Netcarver/Textile/Test/ParserFixtureTest.php @@ -0,0 +1,112 @@ +<?php + +/** + * Textile - A Humane Web Text Generator. + * + * @link https://github.com/textile/php-textile + */ + +namespace Netcarver\Textile\Test; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Yaml\Yaml; + +class ParserFixtureTest extends TestCase +{ + /** + * @dataProvider dataProvider + */ + public function testFixture($test) + { + if (isset($test['class'])) { + $class = $test['class']; + } else { + $class = '\Netcarver\Textile\Parser'; + } + + $textile = new $class; + + if (isset($test['doctype'])) { + $textile->setDocumentType($test['doctype']); + } + + if (isset($test['setup'])) { + foreach ($test['setup'] as $setup) { + foreach ($setup as $method => $value) { + $textile = $textile->$method($value); + } + } + } + + if (isset($test['method'])) { + $method = trim($test['method']); + } else { + $method = 'parse'; + } + + $args = array(); + + if (isset($test['arguments'])) { + foreach ($test['arguments'] as $argument) { + foreach ($argument as $value) { + $args[] = $value; + } + } + } + + foreach (array('expect', 'input') as $field) { + $test[$field] = strtr($test[$field], array( + '\x20' => ' ', + )); + } + + $expect = rtrim($test['expect']); + array_unshift($args, $test['input']); + $input = rtrim(call_user_func_array(array($textile, $method), $args)); + + foreach (array('expect', 'input') as $variable) { + $$variable = preg_replace( + array( + '/ id="(fn|note)[a-z0-9\-]*"/', + '/ href="#(fn|note)[a-z0-9\-]*"/', + ), + '', + $$variable + ); + } + + $this->assertSame($expect, $input); + + $public = implode(', ', array_keys(get_object_vars($textile))); + + $this->assertEmpty($public, 'Leaking public class properties.'); + } + + public function dataProvider() + { + chdir(dirname(dirname(dirname(__DIR__)))); + $out = array(); + + if ($files = glob('*/*.yaml')) { + foreach ($files as $file) { + $yaml = Yaml::parseFile($file); + + foreach ($yaml as $name => $test) { + if (!is_array($test) || !isset($test['input']) || !isset($test['expect'])) { + continue; + } + + if (isset($test['assert']) && $test['assert'] === 'skip') { + continue; + } + + $out[$file . ':' . $name] = array( + 'test' => $test, + ); + } + } + } + + return $out; + } +} diff --git a/test/Netcarver/Textile/Test/ParserTest.php b/test/Netcarver/Textile/Test/ParserTest.php new file mode 100644 index 00000000..8c14b8e3 --- /dev/null +++ b/test/Netcarver/Textile/Test/ParserTest.php @@ -0,0 +1,324 @@ +<?php + +/** + * Textile - A Humane Web Text Generator. + * + * @link https://github.com/textile/php-textile + */ + +namespace Netcarver\Textile\Test; + +use Netcarver\Textile\Test\Parser\DeprecatedPrepare; +use Netcarver\Textile\Test\Parser\DeprecatedTextileCommon; +use PHPUnit\Framework\TestCase; +use Netcarver\Textile\Parser; + +class ParserTest extends TestCase +{ + /** + * @var Parser + */ + private $parser; + + protected function setUp(): void + { + $this->parser = new Parser(); + } + + public function testGetVersion() + { + $this->assertIsString( + $this->parser->getVersion() + ); + } + + public function testInvalidSymbol() + { + $this->expectException('\InvalidArgumentException'); + $this->parser->getSymbol('invalidSymbolName'); + } + + public function testSetGetSymbol() + { + $value = 'TestValue'; + + $this->parser->setSymbol('test', $value); + + $this->assertSame( + $value, + $this->parser->getSymbol('test') + ); + + $result = $this->parser->getSymbol(); + + $this->assertArrayHasKey( + 'test', + $result + ); + + $this->assertSame( + $value, + $result['test'] + ); + } + + public function testSetRelativeImagePrefixChaining() + { + $this->expectError(); + + $symbol = $this->parser + ->setRelativeImagePrefix('abc') + ->setSymbol('test', 'TestValue') + ->getSymbol('test'); + + $this->assertEquals('TestValue', $symbol); + } + + public function testSetGetDimensionlessImage() + { + $this->assertFalse( + $this->parser->getDimensionlessImages() + ); + + $this->parser->setDimensionlessImages(true); + + $this->assertTrue( + $this->parser->getDimensionlessImages() + ); + } + + public function testEncode() + { + $result = $this->parser->textileEncode('& & | " "'); + + $this->assertSame( + '& & | &#x0022 "', + $result + ); + } + + public function testDeprecatedEncodingArgument() + { + $this->expectDeprecation(); + + $this->assertSame( + 'content', + @$this->parser->textileThis('content', false, true) + ); + + $this->assertSame( + 'content', + $this->parser->textileEncode('content') + ); + + $this->parser->textileThis('content', false, true); + } + + public function testDeprecatedTextileCommon() + { + $this->expectDeprecation(); + + $parser = new DeprecatedTextileCommon(); + + $this->assertSame( + ' content', + @$parser->testTextileCommon(' content', false) + ); + + $this->assertSame( + ' content', + @$parser->testTextileCommon(' content', true) + ); + + $parser->testTextileCommon('content', false); + } + + public function testDeprecatedPrepare() + { + $this->expectDeprecation(); + + $parser = new DeprecatedPrepare(); + + $this->assertSame( + ' content', + @$parser->parse(' content') + ); + + $parser->parse('content'); + } + + public function testDeprecatedTextileRestricted() + { + $this->expectDeprecation(); + + $this->assertSame( + ' content', + @$this->parser->textileRestricted(' content') + ); + + $this->parser->textileRestricted('content'); + } + + public function testDeprecatedTextileThis() + { + $this->expectDeprecation(); + + $this->assertSame( + ' content', + @$this->parser->textileThis(' content') + ); + + $this->parser->textileThis('content'); + } + + public function testDeprecatedSetRelativeImagePrefix() + { + $this->expectDeprecation(); + + @$this->parser->setRelativeImagePrefix('/1/'); + + $this->assertSame( + ' <img alt="" src="/1/2.jpg" /> <a href="/1/2">1</a>', + $this->parser->parse(' !2.jpg! "1":2') + ); + + $this->parser->setRelativeImagePrefix('/1/'); + } + + public function testInvalidDocumentType() + { + $this->expectException('\InvalidArgumentException'); + + new Parser('InvalidDocumentType'); + } + + public function testInstanceSharingAndFootnoteIndex() + { + $previous = array('', '<p><strong>strong</strong></p>'); + + for ($i = 1; $i <= 100; $i++) { + $content = "Note[1]\n\nfn1. Footnote"; + $parsed[0] = $this->parser->parse($content); + $parsed[1] = $this->parser->parse('*strong*'); + $this->assertTrue($parsed[0] !== $previous[0]); + $this->assertSame($previous[1], $parsed[1]); + $previous[0] = $parsed[0]; + $previous[1] = $parsed[1]; + } + } + + public function testLineSpaceEscaping() + { + $this->assertSame( + ' <strong>line</strong>', + $this->parser->parse(' *line*') + ); + } + + public function testDocumentRoot() + { + $this->parser->setDocumentRootDirectory(__DIR__); + + $this->assertSame( + __DIR__, + rtrim($this->parser->getDocumentRootDirectory(), '\\/') + ); + } + + public function testDisallowImages() + { + $this->parser->setImages(false); + + $this->assertFalse( + $this->parser->isImageTagEnabled() + ); + + $this->parser->setImages(true); + + $this->assertTrue( + $this->parser->isImageTagEnabled() + ); + } + + public function testLinkRelationShip() + { + $this->parser->setLinkRelationShip('test'); + + $this->assertSame( + 'test', + $this->parser->getLinkRelationShip() + ); + } + + public function testEnableRestrictedMode() + { + $this->parser->setRestricted(true); + + $this->assertTrue( + $this->parser->isRestrictedModeEnabled() + ); + + $this->parser->setRestricted(false); + + $this->assertFalse( + $this->parser->isRestrictedModeEnabled() + ); + } + + public function testImagePrefix() + { + $this->parser->setLinkPrefix('test'); + + $this->assertSame( + 'test', + $this->parser->getLinkPrefix() + ); + } + + public function testLinkPrefix() + { + $this->parser->setImagePrefix('test'); + + $this->assertSame( + 'test', + $this->parser->getImagePrefix() + ); + } + + public function testAlignClasses() + { + $this->assertFalse( + $this->parser->isAlignClassesEnabled() + ); + + $this->parser->setDocumentType(Parser::DOCTYPE_HTML5); + + $this->assertTrue( + $this->parser->isAlignClassesEnabled() + ); + + $this->parser->setAlignClasses(false); + + $this->assertFalse( + $this->parser->isAlignClassesEnabled() + ); + + $this->parser->setDocumentType(Parser::DOCTYPE_XHTML); + + $this->assertFalse( + $this->parser->isAlignClassesEnabled() + ); + + $this->parser->setAlignClasses(true); + + $this->assertTrue( + $this->parser->isAlignClassesEnabled() + ); + + $this->parser->setAlignClasses(false); + + $this->assertFalse( + $this->parser->isAlignClassesEnabled() + ); + } +} diff --git a/test/Netcarver/Textile/Test/TagTest.php b/test/Netcarver/Textile/Test/TagTest.php new file mode 100644 index 00000000..fb8ae789 --- /dev/null +++ b/test/Netcarver/Textile/Test/TagTest.php @@ -0,0 +1,21 @@ +<?php + +/** + * Textile - A Humane Web Text Generator. + * + * @link https://github.com/textile/php-textile + */ + +namespace Netcarver\Textile\Test; + +use PHPUnit\Framework\TestCase; +use Netcarver\Textile\Tag; + +class TagTest extends TestCase +{ + public function testTagAttributesGenerator() + { + $attributes = new Tag(null, array('name' => 'value')); + $this->assertEquals(' name="value"', (string) $attributes); + } +} From 561eeb6328fdf6cb9e9a6aacfee2e8d63251f93f Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Fri, 10 Jun 2022 18:41:19 +0300 Subject: [PATCH 13/16] Reduce code smells --- src/Netcarver/Textile/Parser.php | 48 +++++++++++----------- test/Netcarver/Textile/Test/ParserTest.php | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/Netcarver/Textile/Parser.php b/src/Netcarver/Textile/Parser.php index b4626b75..e8b7fea5 100644 --- a/src/Netcarver/Textile/Parser.php +++ b/src/Netcarver/Textile/Parser.php @@ -2500,10 +2500,10 @@ protected function parseAttribsToArray($in, $element = '', $include_id = true, $ } } - if ($element == 'td' or $element == 'tr') { - if (preg_match("/^($this->vlgn)/", $matched, $vert)) { - $style[] = "vertical-align:" . $this->vAlign($vert[1]); - } + if (($element === 'td' || $element === 'tr') + && preg_match("/^($this->vlgn)/", $matched, $vert) + ) { + $style[] = "vertical-align:" . $this->vAlign($vert[1]); } if (preg_match("/\{([^}]*)\}/", $matched, $sty)) { @@ -2552,12 +2552,12 @@ protected function parseAttribsToArray($in, $element = '', $include_id = true, $ } } - if (preg_match("/([(]+)/", $matched, $pl)) { + if (preg_match("/(\(+)/", $matched, $pl)) { $style[] = "padding-left:" . strlen($pl[1]) . "em"; $matched = str_replace($pl[0], '', $matched); } - if (preg_match("/([)]+)/", $matched, $pr)) { + if (preg_match("/(\)+)/", $matched, $pr)) { $style[] = "padding-right:" . strlen($pr[1]) . "em"; $matched = str_replace($pr[0], '', $matched); } @@ -2566,11 +2566,11 @@ protected function parseAttribsToArray($in, $element = '', $include_id = true, $ $style[] = "text-align:" . $this->hAlign($horiz[1]); } - if ($element == 'col') { - if (preg_match("/(?:\\\\([0-9]+))?{$this->regex_snippets['space']}*([0-9]+)?/", $matched, $csp)) { - $span = isset($csp[1]) ? $csp[1] : ''; - $width = isset($csp[2]) ? $csp[2] : ''; - } + if ($element == 'col' + && preg_match("/(?:\\\\([0-9]+))?{$this->regex_snippets['space']}*([0-9]+)?/", $matched, $csp) + ) { + $span = isset($csp[1]) ? $csp[1] : ''; + $width = isset($csp[2]) ? $csp[2] : ''; } if ($this->isRestrictedModeEnabled()) { @@ -2894,7 +2894,7 @@ protected function fRedclothList($m) $out = array(); /** @var array<int, string> $text */ - $text = preg_split('/\n(?=[-])/m', $in); + $text = preg_split('/\n(?=-)/m', $in); foreach ($text as $line) { $m = array(); @@ -4265,12 +4265,12 @@ protected function fLink($m) // eg. "text":url][otherstuff... will have "[otherstuff" popped back out. // "text":url?q[]=x][123] will have "[123]" popped off the back, the remaining closing square brackets // will later be tested for balance - if ($counts[']']) { - if (1 === preg_match('@(?P<url>^.*\])(?P<tight>\[.*?)$@' . $this->regex_snippets['mod'], $url, $m)) { - $url = $m['url']; - $tight = $m['tight']; - $m = array(); - } + if ($counts[']'] + && 1 === preg_match('@(?P<url>^.*\])(?P<tight>\[.*?)$@' . $this->regex_snippets['mod'], $url, $m) + ) { + $url = $m['url']; + $tight = $m['tight']; + $m = array(); } // Split off any trailing text that isn't part of an array assignment. @@ -4278,12 +4278,12 @@ protected function fLink($m) // "text":...?q[]=value1]following ... would have "following" // popped back out and the remaining square bracket // will later be tested for balance - if ($counts[']']) { - if (1 === preg_match('@(?P<url>^.*\])(?!=)(?P<end>.*?)$@' . $this->regex_snippets['mod'], $url, $m)) { - $url = $m['url']; - $tight = $m['end'] . $tight; - $m = array(); - } + if ($counts[']'] + && 1 === preg_match('@(?P<url>^.*\])(?!=)(?P<end>.*?)$@' . $this->regex_snippets['mod'], $url, $m) + ) { + $url = $m['url']; + $tight = $m['end'] . $tight; + $m = array(); } // Does this need to be mb_ enabled? We are only searching for text in the ASCII charset anyway diff --git a/test/Netcarver/Textile/Test/ParserTest.php b/test/Netcarver/Textile/Test/ParserTest.php index 8c14b8e3..dcbbd27a 100644 --- a/test/Netcarver/Textile/Test/ParserTest.php +++ b/test/Netcarver/Textile/Test/ParserTest.php @@ -200,7 +200,7 @@ public function testInstanceSharingAndFootnoteIndex() $content = "Note[1]\n\nfn1. Footnote"; $parsed[0] = $this->parser->parse($content); $parsed[1] = $this->parser->parse('*strong*'); - $this->assertTrue($parsed[0] !== $previous[0]); + $this->assertNotSame($parsed[0], $previous[0]); $this->assertSame($previous[1], $parsed[1]); $previous[0] = $parsed[0]; $previous[1] = $parsed[1]; From a11ce072735008daf425642200e2bea959055e8c Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Sat, 19 Nov 2022 02:30:32 +0200 Subject: [PATCH 14/16] Update GitHub actions --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 18 +++++------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 828d548f..a7bdffa9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: fetch-depth: 0 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2a68188d..59c557de 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,25 +13,17 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Changelog id: changelog run: | - contents="$(sed -e '1,/h2./d' -e '/h2./,$d' CHANGELOG.textile)" - contents="${contents//'%'/'%25'}" - contents="${contents//$'\n'/'%0A'}" - contents="${contents//$'\r'/'%0D'}" - echo "::set-output name=contents::$contents" + echo "contents<<CHANGELOGEOF" >> $GITHUB_OUTPUT + sed -e '1,/h2./d' -e '/h2./,$d' CHANGELOG.textile >> $GITHUB_OUTPUT + echo "CHANGELOGEOF" >> $GITHUB_OUTPUT - name: Create Release id: create_release - uses: actions/create-release@master - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + uses: shogo82148/actions-create-release@v1 with: - tag_name: ${{ github.ref }} - release_name: ${{ github.ref }} body: ${{ steps.changelog.outputs.contents }} - draft: false - prerelease: false From 226ab8d3ebe162b7972c7e28fef3193b47dff879 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Sat, 3 Dec 2022 19:17:41 +0200 Subject: [PATCH 15/16] Update pull-request template --- .github/PULL_REQUEST_TEMPLATE.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 6f57fa64..8f2e5d52 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -18,6 +18,5 @@ <!--- Put an `x` in all the boxes that apply. --> - [ ] I documented my additions and changes using PHPdoc. - [ ] I wrote fixtures to cover my additions. -- [ ] `$ composer update` -- [ ] `$ composer test` -- [ ] `$ composer cs` +- [ ] `$ make clean` +- [ ] `$ make test` From 02ed0cbe6832c2100342dabb6d01d7ba558cb8e7 Mon Sep 17 00:00:00 2001 From: Jukka Svahn <void@rah.pw> Date: Sat, 3 Dec 2022 20:19:42 +0200 Subject: [PATCH 16/16] Marks 3.8.0 --- CHANGELOG.textile | 4 ++-- src/Netcarver/Textile/Parser.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.textile b/CHANGELOG.textile index 4a5d795a..20f36462 100644 --- a/CHANGELOG.textile +++ b/CHANGELOG.textile @@ -2,9 +2,9 @@ h1. Changelog Here's a summary of changes in each release. The list doesn't include some small changes or updates to test cases. -h2. Version 3.8.0 - upcoming +h2. "Version 3.8.0 - 2022/12/03":https://github.com/textile/php-textile/releases/tag/v3.8.0 -* Added @Parser::setAlignClasses()@ and @Parser::isAlignClassesEnabled@. This can be used to enable img alignment classes in XHTML output document mode, instead of the default align attribute. +* Added @Parser::setAlignClasses()@ and @Parser::isAlignClassesEnabled()@. This can be used to enable img alignment classes in XHTML output document mode, instead of the default align attribute. * Added @Parser::DOCTYPE_HTML5@ and @Parser::DOCTYPE_XHTML@ constants. These can be used with @Parser::setDocumentType()@ to specify the output document type. h2. "Version 3.7.7 - 2022/05/01":https://github.com/textile/php-textile/releases/tag/v3.7.7 diff --git a/src/Netcarver/Textile/Parser.php b/src/Netcarver/Textile/Parser.php index e8b7fea5..e9f0e29a 100644 --- a/src/Netcarver/Textile/Parser.php +++ b/src/Netcarver/Textile/Parser.php @@ -384,7 +384,7 @@ class Parser * * @var string */ - protected $ver = '3.8.0-dev'; + protected $ver = '3.8.0'; /** * Regular expression snippets.