aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/html2bbcode.php38
-rw-r--r--tests/unit/includes/BBCodeTest.php58
-rw-r--r--tests/unit/includes/MarkdownTest.php129
3 files changed, 174 insertions, 51 deletions
diff --git a/include/html2bbcode.php b/include/html2bbcode.php
index aca3ff4f8..e2fa94326 100644
--- a/include/html2bbcode.php
+++ b/include/html2bbcode.php
@@ -10,6 +10,10 @@ Originally made for the syncom project: http://wiki.piratenpartei.de/Syncom
function node2bbcode(&$doc, $oldnode, $attributes, $startbb, $endbb)
{
do {
+ if (empty($startbb) && empty($endbb)) {
+ break;
+ }
+
$done = node2bbcodesub($doc, $oldnode, $attributes, $startbb, $endbb);
} while ($done);
}
@@ -65,6 +69,22 @@ function node2bbcodesub(&$doc, $oldnode, $attributes, $startbb, $endbb)
if ($oldNode->hasChildNodes()) {
foreach ($oldNode->childNodes as $child) {
$newNode = $child->cloneNode(true);
+
+ // Newlines are insignificant in HTML, but not so in BBCode, so let's
+ // unwrap the child nodes of when converting them. Also we compress
+ // consecutive whitespace chars to one.
+ //
+ // The exception is `<pre>` and `<code>` elements which
+ // should keep both newlines and whitespace intact.
+ if ($oldNode->nodeName != 'pre' && $oldNode->nodeName != 'code') {
+ $newNode->nodeValue = str_replace(
+ array("\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"),
+ array("<", ">", "<br />", " ", ""),
+ $newNode->nodeValue);
+
+ $newNode->nodeValue = preg_replace('=[\s]{2,}=i', " ", $newNode->nodeValue);
+ }
+
$oldNode->parentNode->insertBefore($newNode, $oldNode);
}
}
@@ -125,16 +145,6 @@ function html2bbcode($message)
deletenode($doc, 'xml');
deletenode($doc, 'removeme');
- $xpath = new DomXPath($doc);
- $list = $xpath->query("//pre");
- foreach ($list as $node)
- $node->nodeValue = str_replace("\n", "\r", $node->nodeValue);
-
- $message = $doc->saveHTML();
- $message = str_replace(array("\n<", ">\n", "\r", "\n", "\xC3\x82\xC2\xA0"), array("<", ">", "<br />", " ", ""), $message);
- $message = preg_replace('= [\s]*=i', " ", $message);
- @$doc->loadHTML($message);
-
node2bbcode($doc, 'html', array(), "", "");
node2bbcode($doc, 'body', array(), "", "");
@@ -182,7 +192,8 @@ function html2bbcode($message)
node2bbcode($doc, 'blockquote', array(), '[quote]', '[/quote]');
- node2bbcode($doc, 'br', array(), "\n", '');
+ // Use a temporary tag to keep line breaks
+ node2bbcode($doc, 'br', array(), '[br]', '');
node2bbcode($doc, 'p', array('class'=>'MsoNormal'), "\n", "");
node2bbcode($doc, 'div', array('class'=>'MsoNormal'), "\r", "");
@@ -219,6 +230,7 @@ function html2bbcode($message)
node2bbcode($doc, 'a', array('href'=>'/(.+)/'), '[url=$1]', '[/url]');
node2bbcode($doc, 'img', array('src'=>'/(.+)/', 'width'=>'/(\d+)/', 'height'=>'/(\d+)/'), '[img=$2x$3]$1', '[/img]');
+ node2bbcode($doc, 'img', array('src'=>'/(.+)/', 'alt'=>'/(.+)/'), '[img=$1]$2', '[/img]');
node2bbcode($doc, 'img', array('src'=>'/(.+)/'), '[img]$1', '[/img]');
@@ -226,6 +238,7 @@ function html2bbcode($message)
node2bbcode($doc, 'audio', array('src'=>'/(.+)/'), '[audio]$1', '[/audio]');
// node2bbcode($doc, 'iframe', array('src'=>'/(.+)/'), '[iframe]$1', '[/iframe]');
+ node2bbcode($doc, 'code', array('class'=>'/(.+)/'), '[code=$1]', '[/code]');
node2bbcode($doc, 'code', array(), '[code]', '[/code]');
$message = $doc->saveHTML();
@@ -291,6 +304,9 @@ function html2bbcode($message)
$message = str_replace(array('[b][b]', '[/b][/b]', '[i][i]', '[/i][/i]'),
array('[b]', '[/b]', '[i]', '[/i]'), $message);
+ // Restore linebreaks from temp tag
+ $message = str_replace('[br] ', "\n", $message);
+
// Handling Yahoo style of mails
// $message = str_replace('[hr][b]From:[/b]', '[quote][b]From:[/b]', $message);
diff --git a/tests/unit/includes/BBCodeTest.php b/tests/unit/includes/BBCodeTest.php
new file mode 100644
index 000000000..035bcbdc7
--- /dev/null
+++ b/tests/unit/includes/BBCodeTest.php
@@ -0,0 +1,58 @@
+<?php
+/*
+ * Copyright (c) 2024 Hubzilla
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+namespace Zotlabs\Tests\Unit\includes;
+
+use Zotlabs\Tests\Unit\UnitTestCase;
+
+class BBCodeTest extends UnitTestCase {
+ /**
+ * Test converting html to BBCode.
+ *
+ * @dataProvider html2bbcode_provider
+ */
+ public function test_html2bbcode(string $src, string $expected): void {
+ $this->assertEquals($expected, html2bbcode($src));
+ }
+
+ private function html2bbcode_provider(): array {
+ return [
+ 'paragraph over multiple lines' => [
+ "<p>A paragraph over\nmultiple lines\nshould be unwrapped</p>",
+ 'A paragraph over multiple lines should be unwrapped'
+ ],
+ 'image with alt text' => [
+ '<img src="https://example.com/image.jpg" alt="Alt text">',
+ '[img=https://example.com/image.jpg]Alt text[/img]'
+ ],
+ 'code block' => [
+ "<pre><code>some\ncode</code></pre>",
+ "[code]some\ncode[/code]"
+ ],
+ 'code block with indentation' => [
+ "<pre><code>some\n indented\ncode</code></pre>",
+ "[code]some\n indented\ncode[/code]"
+ ],
+ ];
+ }
+}
diff --git a/tests/unit/includes/MarkdownTest.php b/tests/unit/includes/MarkdownTest.php
index 953305074..960c15139 100644
--- a/tests/unit/includes/MarkdownTest.php
+++ b/tests/unit/includes/MarkdownTest.php
@@ -1,30 +1,29 @@
<?php
/*
* Copyright (c) 2017 Hubzilla
-*
-* Permission is hereby granted, free of charge, to any person obtaining a copy
-* of this software and associated documentation files (the "Software"), to deal
-* in the Software without restriction, including without limitation the rights
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-* copies of the Software, and to permit persons to whom the Software is
-* furnished to do so, subject to the following conditions:
-*
-* The above copyright notice and this permission notice shall be included in
-* all copies or substantial portions of the Software.
-*
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-* SOFTWARE.
-*/
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
namespace Zotlabs\Tests\Unit\includes;
use Zotlabs\Tests\Unit\UnitTestCase;
-use phpmock\phpunit\PHPMock;
require_once 'include/markdown.php';
@@ -32,17 +31,80 @@ require_once 'include/markdown.php';
* @brief Unit Test case for markdown functions.
*/
class MarkdownTest extends UnitTestCase {
- use PHPMock;
+
+ /**
+ * @dataProvider markdown_to_bbcode_provider
+ */
+ public function test_markdown_to_bbcode(string $expected, string $src): void {
+ $this->assertEquals($expected, markdown_to_bb($src));
+ }
+
+ private function markdown_to_bbcode_provider(): array {
+ return [
+ 'empty text' => [
+ '',
+ ''
+ ],
+ 'plain text' => [
+ 'This is a test',
+ 'This is a test'
+ ],
+ 'bold and italic' => [
+ 'This is a test of [b]bold text[/b], [i]italic text[/i] and [b][i]bold and italic text[/i][/b]',
+ 'This is a test of **bold text**, *italic text* and ***bold and italic text***'
+ ],
+ 'multiline text' => [
+ 'This text is text wrapped over multiple lines.',
+ "This text is\ntext wrapped\nover multiple\nlines."
+ ],
+ 'text with hard linebreak' => [
+ "Line one\nLine two",
+ "Line one \nLine two"
+ ],
+ 'paragraphs' => [
+ "Paragraph one\n\nParagraph two",
+ "Paragraph one\n\nParagraph two",
+ ],
+ 'inline image' => [
+ '[img=https://example.com/image.jpg]https://example.com/image.jpg[/img]',
+ '![](https://example.com/image.jpg)'
+ ],
+ 'inline image with alt text' => [
+ '[img=https://example.com/image.jpg]Alt text[/img]',
+ '![Alt text](https://example.com/image.jpg)'
+ ],
+ 'inline code' => [
+ '[code]some code[/code]',
+ '`some code`'
+ ],
+ 'inline code with wrapped text' => [
+ '[code]some code unwrapped[/code]',
+ "`some code\n unwrapped`"
+ ],
+ 'code block no language' => [
+ "[code]some code\nover multiple lines[/code]",
+ "```\nsome code\nover multiple lines\n```"
+ ],
+ 'code block no language indented' => [
+ "[code]some code\n over multiple lines\n with indentation[/code]",
+ "```\nsome code\n over multiple lines\n with indentation\n```"
+ ],
+ 'code block with language' => [
+ "[code=php]&lt;?php\necho phpinfo();[/code]",
+ "```php\n<?php\necho phpinfo();\n```"
+ ],
+ ];
+ }
/**
* @covers ::html2markdown
* @dataProvider html2markdownProvider
*/
- public function testHtml2markdown($html, $markdown) {
+ public function testHtml2markdown(string $html, string $markdown): void {
$this->assertEquals($markdown, html2markdown($html));
}
- public function html2markdownProvider() {
+ public function html2markdownProvider(): array {
return [
'empty text' => [
'',
@@ -125,23 +187,10 @@ class MarkdownTest extends UnitTestCase {
];
}
- /*public function testHtml2markdownException() {
- //$this->expectException(\InvalidArgumentException::class);
- // need to stub logger() for this to work
- $this->assertEquals('', html2markdown('<<invalid'));
- }*/
-
-/* public function testBB2diasporaMardown() {
- //stub bbcode() and return our HTML, we just need to test the HTML2Markdown library.
- $html1 = 'test<b>bold</b><br><i>i</i><ul><li>li1</li><li>li2</li></ul><br>';
- $bb1 = 'test';
-
- // php-mock can not mock global functions which is called by a global function.
- // If the calling function is in a namespace it does work.
- $bbc = $this->getFunctionMock(__NAMESPACE__, "bbcode");
- $bbc->expects($this->once())->willReturn('test<b>bold</b><br><i>i</i><ul><li>li1</li><li>li2</li></ul><br>');
+ public function test_bb_to_markdown(): void {
+ $input = "test[b]bold[/b]\n[i]i[/i][ul][li]li1[/li][li]li2[/li][/ul]\n";
+ $expected = "test**bold** \n*i*\n\n- li1\n- li2";
- $this->assertEquals($bb1, bb2diaspora($html1));
+ $this->assertEquals($expected, bb_to_markdown($input));
}
-*/
}