diff --git a/components/ILIAS/Data/src/TextHandling/Markup.php b/components/ILIAS/Data/src/TextHandling/Markup.php new file mode 100644 index 000000000000..8c8168730286 --- /dev/null +++ b/components/ILIAS/Data/src/TextHandling/Markup.php @@ -0,0 +1,25 @@ +markdown_to_html_transformation->transform( + $text->getRawRepresentation() + ) + ); + } + + public function toPlainText(Text $text): Text\PlainText + { + if (!$text instanceof Text\Markdown) { + throw new \InvalidArgumentException("Text does not match format."); + } + return new Text\PlainText($text->getRawRepresentation()); + } + + public function getMarkup(): Markup\Markdown + { + return new Markup\Markdown(); + } + + public function fromString(string $text): Text\Markdown + { + return new Text\Markdown($this, $text); + } + + public function isRawStringCompliant(string $text): bool + { + return true; + } +} diff --git a/components/ILIAS/Data/src/TextHandling/Shape/SimpleDocumentMarkdown.php b/components/ILIAS/Data/src/TextHandling/Shape/SimpleDocumentMarkdown.php new file mode 100644 index 000000000000..593f38b9b261 --- /dev/null +++ b/components/ILIAS/Data/src/TextHandling/Shape/SimpleDocumentMarkdown.php @@ -0,0 +1,72 @@ +)+', // blockquote + '(\`)' // code only + ]; + + foreach ($structure_patterns as $pattern) { + if (mb_ereg_match($pattern, $text)) { + return false; + } + } + + return true; + } +} diff --git a/components/ILIAS/Data/src/TextHandling/Structure.php b/components/ILIAS/Data/src/TextHandling/Structure.php new file mode 100644 index 000000000000..c77dd958fff9 --- /dev/null +++ b/components/ILIAS/Data/src/TextHandling/Structure.php @@ -0,0 +1,40 @@ + to
+ case HEADING_1; + case HEADING_2; + case HEADING_3; + case HEADING_4; + case HEADING_5; + case HEADING_6; + case BOLD; + case ITALIC; + case UNORDERED_LIST; + case ORDERED_LIST; + case LINK; + case PARAGRAPH; + case BLOCKQUOTE; + case CODE; +} diff --git a/components/ILIAS/Data/src/TextHandling/Text.php b/components/ILIAS/Data/src/TextHandling/Text.php new file mode 100644 index 000000000000..b917470e980a --- /dev/null +++ b/components/ILIAS/Data/src/TextHandling/Text.php @@ -0,0 +1,34 @@ +isRawStringCompliant($raw)) { + throw new \InvalidArgumentException("The provided string is not compliant with the supported structure!"); + } + } + + public function getShape(): Shape + { + return $this->shape; + } + + public function getMarkup(): Markup + { + return $this->shape->getMarkup(); + } + + /** + * @return Structure[] + */ + public function getSupportedStructure(): array + { + return $this->shape->getSupportedStructure(); + } + + public function toHTML(): Text\HTML + { + return $this->shape->toHTML($this->raw); + } + + public function toPlainText(): Text\PlainText + { + return $this->shape->toPlainText($this->raw); + } + + public function getRawRepresentation(): string + { + return $this->raw; + } +} diff --git a/components/ILIAS/Data/src/TextHandling/Text/HTML.php b/components/ILIAS/Data/src/TextHandling/Text/HTML.php new file mode 100644 index 000000000000..0614f104068e --- /dev/null +++ b/components/ILIAS/Data/src/TextHandling/Text/HTML.php @@ -0,0 +1,34 @@ +html_text = $html_text; + } +} diff --git a/components/ILIAS/Data/src/TextHandling/Text/Markdown.php b/components/ILIAS/Data/src/TextHandling/Text/Markdown.php new file mode 100644 index 000000000000..77792f37fe26 --- /dev/null +++ b/components/ILIAS/Data/src/TextHandling/Text/Markdown.php @@ -0,0 +1,33 @@ +plain_text = $plain_text; + } +} diff --git a/components/ILIAS/Data/src/TextHandling/Text/SimpleDocumentMarkdown.php b/components/ILIAS/Data/src/TextHandling/Text/SimpleDocumentMarkdown.php new file mode 100644 index 000000000000..005be434582e --- /dev/null +++ b/components/ILIAS/Data/src/TextHandling/Text/SimpleDocumentMarkdown.php @@ -0,0 +1,33 @@ +createMock(ilLanguage::class); + $data_factory = new Data\Factory(); + $refinery = new ILIAS\Refinery\Factory($data_factory, $language); + $this->markdown_shape = new Markdown($refinery->string()->markdown()->toHTML()); + } + + public static function stringToHTMLDataProvider(): array + { + return [ + ["lorem", new HTML("

lorem

\n")], + ["lorem **ipsum**", new HTML("

lorem ipsum

\n")], + ["_lorem_ **ipsum**", new HTML("

lorem ipsum

\n")], + ["# Headline", new HTML("

Headline

\n")], + ["## Headline", new HTML("

Headline

\n")], + ["### Headline", new HTML("

Headline

\n")], + ["1. Lorem\n2. Ipsum", new HTML("
    \n
  1. Lorem
  2. \n
  3. Ipsum
  4. \n
\n")], + ["- Lorem\n- Ipsum", new HTML("\n")], + ["[Link Titel](https://www.ilias.de)", new HTML("

Link Titel

\n")] + ]; + } + + public static function stringToPlainDataProvider(): array + { + return [ + ["lorem", new PlainText("lorem")], + ["lorem **ipsum**", new PlainText("lorem **ipsum**")], + ["_lorem_ **ipsum**", new PlainText("_lorem_ **ipsum**")], + ["# Headline", new PlainText("# Headline")], + ["## Headline", new PlainText("## Headline")], + ["### Headline", new PlainText("### Headline")], + ["1. Lorem\n2. Ipsum", new PlainText("1. Lorem\n2. Ipsum")], + ["- Lorem\n- Ipsum", new PlainText("- Lorem\n- Ipsum")], + ["[Link Titel](https://www.ilias.de)", new PlainText("[Link Titel](https://www.ilias.de)")] + ]; + } + + /** + * @dataProvider stringToHTMLDataProvider + */ + public function testToHTML(string $markdown_string, HTML $expected_html): void + { + $text = $this->markdown_shape->fromString($markdown_string); + $this->assertEquals($expected_html, $this->markdown_shape->toHTML($text)); + } + + /** + * @dataProvider stringToPlainDataProvider + */ + public function testToPlainText(string $markdown_string, PlainText $expected_text): void + { + $text = $this->markdown_shape->fromString($markdown_string); + $this->assertEquals($expected_text, $this->markdown_shape->toPlainText($text)); + } +} diff --git a/components/ILIAS/Data/tests/TextHandling/Shape/SimpleDocumentMarkdownShapeTest.php b/components/ILIAS/Data/tests/TextHandling/Shape/SimpleDocumentMarkdownShapeTest.php new file mode 100644 index 000000000000..bf7e841f4905 --- /dev/null +++ b/components/ILIAS/Data/tests/TextHandling/Shape/SimpleDocumentMarkdownShapeTest.php @@ -0,0 +1,119 @@ +createMock(ilLanguage::class); + $data_factory = new Data\Factory(); + $refinery = new ILIAS\Refinery\Factory($data_factory, $language); + $this->simple_doc_markdown_shape = new SimpleDocumentMarkdown($refinery->string()->markdown()->toHTML()); + } + + public static function constructDataProvider(): array + { + return [ + [ + Structure::BOLD, + Structure::ITALIC, + Structure::HEADING_1, + Structure::HEADING_2, + Structure::HEADING_3, + Structure::HEADING_4, + Structure::HEADING_5, + Structure::HEADING_6, + Structure::UNORDERED_LIST, + Structure::ORDERED_LIST, + Structure::PARAGRAPH, + Structure::LINK, + Structure::BLOCKQUOTE, + Structure::CODE + ] + ]; + } + + public static function stringComplianceDataProvider(): array + { + return [ + ["### Heading 3", true], + ["> Quote block", true], + ["![Image text](https://www.ilias.de)", false] + ]; + } + + /** + * @dataProvider constructDataProvider + */ + public function testGetSupportedStructure( + Structure $dp_bold, + Structure $dp_italic, + Structure $dp_heading_1, + Structure $dp_heading_2, + Structure $dp_heading_3, + Structure $dp_heading_4, + Structure $dp_heading_5, + Structure $dp_heading_6, + Structure $dp_unordered_list, + Structure $dp_ordered_list, + Structure $dp_paragraph, + Structure $dp_link, + Structure $dp_blockquote, + Structure $dp_code + ): void { + $supported_structure = $this->simple_doc_markdown_shape->getSupportedStructure(); + + $expected = [ + $dp_bold, + $dp_italic, + $dp_heading_1, + $dp_heading_2, + $dp_heading_3, + $dp_heading_4, + $dp_heading_5, + $dp_heading_6, + $dp_unordered_list, + $dp_ordered_list, + $dp_paragraph, + $dp_link, + $dp_blockquote, + $dp_code + ]; + + $this->assertEquals($expected, $supported_structure); + } + + /** + * @dataProvider stringComplianceDataProvider + */ + public function testIsRawStringCompliant(string $markdown_string, bool $compliance): void + { + $this->assertEquals($this->simple_doc_markdown_shape->isRawStringCompliant($markdown_string), $compliance); + } +} diff --git a/components/ILIAS/Data/tests/TextHandling/Shape/WordOnlyMarkdownShapeTest.php b/components/ILIAS/Data/tests/TextHandling/Shape/WordOnlyMarkdownShapeTest.php new file mode 100644 index 000000000000..dc39f5a2322a --- /dev/null +++ b/components/ILIAS/Data/tests/TextHandling/Shape/WordOnlyMarkdownShapeTest.php @@ -0,0 +1,77 @@ +createMock(Data\TextHandling\Markup::class); + $language = $this->createMock(ilLanguage::class); + $data_factory = new Data\Factory(); + $refinery = new ILIAS\Refinery\Factory($data_factory, $language); + $this->word_only_markdown_shape = new WordOnlyMarkdown($refinery->string()->markdown()->toHTML()); + } + + public static function constructDataProvider(): array + { + return [ + [Structure::BOLD, Structure::ITALIC] + ]; + } + + public static function stringComplianceDataProvider(): array + { + return [ + ["This text has **bold** and _italic_ content", true], + ["> Quote block is not allowed", false] + ]; + } + + /** + * @dataProvider constructDataProvider + */ + public function testGetSupportedStructure(Structure $dp_bold, Structure $dp_italic): void + { + $supported_structure = $this->word_only_markdown_shape->getSupportedStructure(); + $exptected = [ + $dp_bold, + $dp_italic + ]; + + $this->assertEquals($exptected, $supported_structure); + } + + /** + * @dataProvider stringComplianceDataProvider + */ + public function testIsRawStringCompliant(string $markdown_string, bool $compliance): void + { + $this->assertEquals($this->word_only_markdown_shape->isRawStringCompliant($markdown_string), $compliance); + } +} diff --git a/docs/development/text-handling.md b/docs/development/text-handling.md index b18e312a18d4..d2e862dfe41a 100755 --- a/docs/development/text-handling.md +++ b/docs/development/text-handling.md @@ -128,12 +128,12 @@ interface Shape /** * @throws \InvalidArgumentException if $text does not match format. */ - public function toHTML($text) : HTMLText; + public function toHTML(Text $text) : HTMLText; /** * @throws \InvalidArgumentException if $text does not match format. */ - public function toPlainText($text) : PlainText; + public function toPlainText(Text $text) : PlainText; public function getMarkup() : Markup; @@ -157,7 +157,7 @@ class WordOnlyMarkdownShape extends SimpleDocumentMarkdownShape class SimpleDocumentMarkdownShape extends MarkdownShape { - /* will support paragraphs, headlines and lists on top */ + /* will support paragraphs, headlines, lists, blockquotes, code and links on top */ } /* ... */