From 18c16611fbdf70f8bc61335863918ddd0c2fafcd Mon Sep 17 00:00:00 2001 From: Wilmer Arambula Date: Wed, 6 Mar 2024 12:55:14 -0300 Subject: [PATCH] Add helper `HTMLBuilder::class`. --- CHANGELOG.md | 1 + README.md | 46 +++++++ src/Base/AbstractHTMLBuilder.php | 203 +++++++++++++++++++++++++++++ src/HTMLBuilder.php | 12 ++ tests/HTMLBuilderExceptionTest.php | 34 +++++ tests/HTMLBuilderTest.php | 35 +++++ tests/Provider/TagProvider.php | 42 ++++++ 7 files changed, 373 insertions(+) create mode 100644 src/Base/AbstractHTMLBuilder.php create mode 100644 src/HTMLBuilder.php create mode 100644 tests/HTMLBuilderExceptionTest.php create mode 100644 tests/HTMLBuilderTest.php create mode 100644 tests/Provider/TagProvider.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 89728d3..f7e653b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,3 +7,4 @@ - Initial release - Enh #2: Add helper `Template::class` (@terabytesoftw) - Bug #3: Fix `README.md` (@terabytesoftw) +- Enh #4: Add helper `HTMLBuilder::class` (@terabytesoftw) diff --git a/README.md b/README.md index 46cac3e..9b6ce5a 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,52 @@ private array $attributes = ['class' => 'btn']; $classes = CssClasses::add($this->attributes, ['btn-primary', 'btn-lg'], true); ``` +### Create a new `HTML` element + +To create a new `HTML` element, you can use the `HTMLBuilder::class` with the `createTag()` method. + +Allowed arguments are: + +- `tag` (string) - The tag name. +- `content` (string) - The content of the tag. +- `attributes` (array) - The attributes of the tag. + +```php + + + 'container']) ?> +``` + +### Create a new `HTML` block element + +To create a new `HTML` block element, you can use the `HTMLBuilder::class` with the `beginTag()` and `endTag()` methods. + +Allowed arguments for `beginTag()` method are: + +- `tag` (string) - The tag name. +- `attributes` (array) - The attributes of the tag. + +Allowed arguments for `endTag()` method are: + +- `tag` (string) - The tag name. + +```php + 'container']) ?> + Hello, World! + +``` + ### Convert regular expression to pattern The `Utils::class` helper can be used to normalize a regular expression. diff --git a/src/Base/AbstractHTMLBuilder.php b/src/Base/AbstractHTMLBuilder.php new file mode 100644 index 0000000..056416c --- /dev/null +++ b/src/Base/AbstractHTMLBuilder.php @@ -0,0 +1,203 @@ +render($attributes) . '>'; + } + + /** + * This method creates a new HTML tag with the specified tag name, content, and attributes. + * + * @param string $tag The tag name. + * @param string $content The content of the tag. + * @param array $attributes The attributes of the tag. + * + * @return string The tag. + */ + public static function createTag(string $tag, string $content = '', array $attributes = []): string + { + $tag = self::validateTag($tag); + $voidElement = "<$tag" . Attributes::render($attributes) . '>'; + + if (self::voidElements($tag)) { + return $voidElement; + } + + if (self::inlinedElements($tag)) { + return "$voidElement$content"; + } + + $content = $content === '' ? '' : $content . PHP_EOL; + + return "$voidElement\n$content"; + } + + /** + * This method creates a new HTML end tag with the specified tag name. + * + * @param string $tag The tag name. + * + * @return string The closing tag. + */ + public static function endTag(string $tag): string + { + if (self::inlinedElements($tag)) { + throw new \InvalidArgumentException('Inline elements cannot be used with begin/end syntax.'); + } + + $tag = self::validateTag($tag); + + return ""; + } + + /** + * @return bool True if tag is inlined element. + * + * @link https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements + */ + private static function inlinedElements(string $tag): bool + { + return in_array($tag, self::INLINE_ELEMENTS, true); + } + + /** + * @return bool True if tag is void element. + * + * @link http://www.w3.org/TR/html-markup/syntax.html#void-element + */ + private static function voidElements(string $tag): bool + { + return in_array($tag, self::VOID_ELEMENT, true); + } + + /** + * @throws \InvalidArgumentException + */ + private static function validateTag(string $tag): string + { + $tag = strtolower($tag); + + if ($tag === '') { + throw new \InvalidArgumentException('Tag name cannot be empty.'); + } + + return $tag; + } +} diff --git a/src/HTMLBuilder.php b/src/HTMLBuilder.php new file mode 100644 index 0000000..7a45f90 --- /dev/null +++ b/src/HTMLBuilder.php @@ -0,0 +1,12 @@ +expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Inline elements cannot be used with begin/end syntax.'); + + HTMLBuilder::beginTag('br'); + } + + public function testEndInlineElement(): void + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Inline elements cannot be used with begin/end syntax.'); + + HTMLBuilder::endTag('br'); + } + + public function testTagEmpty(): void + { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Tag name cannot be empty.'); + + HTMLBuilder::createTag(''); + } +} diff --git a/tests/HTMLBuilderTest.php b/tests/HTMLBuilderTest.php new file mode 100644 index 0000000..c82c647 --- /dev/null +++ b/tests/HTMLBuilderTest.php @@ -0,0 +1,35 @@ +assertSame('
', HTMLBuilder::beginTag('div')); + $this->assertSame('
', HTMLBuilder::beginTag('div', ['class' => 'class'])); + } + + /** + * @dataProvider UIAwesome\Html\Helper\Tests\Provider\TagProvider::create + * + * @param string $tagName Tag name. + * @param string $content Tag content. + * @param array $attributes Tag attributes. + * @param string $expected Expected result. + */ + public function testCreate(string $tagName, string $content, array $attributes, string $expected): void + { + Assert::equalsWithoutLE($expected, HTMLBuilder::createTag($tagName, $content, $attributes)); + } + + public function testEnd(): void + { + $this->assertSame('
', HTMLBuilder::endTag('div')); + } +} diff --git a/tests/Provider/TagProvider.php b/tests/Provider/TagProvider.php new file mode 100644 index 0000000..0a7f440 --- /dev/null +++ b/tests/Provider/TagProvider.php @@ -0,0 +1,42 @@ + 'id-1', + 'class' => 'class', + ], + '
' . PHP_EOL . '
', + ], + ['br', '', [], '
'], + ['BR', '', [], '
'], + ['hr', '', [], '
'], + ['HR', '', [], '
'], + ['div', 'Content', [], '
' . PHP_EOL . 'Content' . PHP_EOL . '
'], + [ + 'input', + '', + [ + 'type' => 'text', + 'name' => 'test', + 'value' => '<>', + ], + '', + ], + ['span', '', [], ''], + ['span', '', [ + 'disabled' => true, + ], ''], + ]; + } +}