#!/www/server/bin/php -qC
<?php

it::getopt(""); #handle possible --debug parameter

#  Tests for html.class

# Traditional html5 generation
ini_set('default_charset', "utf-8");
new it_html(['htmltype' => "html5", 'prettyprint' => false, 'error_on_redefine' => false]);

is(
	a(['href' => "&foo", 'true' => true, 'false' => false, 'null' => null, 'empty' => ""], "bar"),
	'<a href="&amp;foo" true empty="">bar</a>',
	"tag with attributes"
);

is(
	div(),
	"<div></div>\n",
	"empty div tag"
);

is(
	h1(),
	"<h1></h1>\n",
	"empty h1 tag"
);

is(
	input(),
	"<input>",
	"no closing tag for void elements"
);

is(
	img(['src' => "foo.png", 'alt' => "ALT"]),
	'<img src="foo.png" alt="ALT">',
	"img tag with attributes"
);

is(
	tag('link'),
	"<link>\n",
	"empty link tag"
);

is(
	tag('link', "foo"),
	"<link>foo</link>\n",
	"link tag with data"
);

is(
	it::replace(['\n+\s*' => ""], select(['name' => "gna", 'multiple' => true], '1:foo,2:bar', '1,2')),
	'<select name="gna" multiple><option value="1" selected>foo</option><option value="2" selected>bar</option></select>',
	"select tag with multiselect"
);

is(
	it::replace(['\n+\s*' => ""], select(['name' => "gna"], ["1" => "foo", "2" => 'bar', '1,2' => "qux"], '1,2')),
	'<select name="gna"><option value="1">foo</option><option value="2">bar</option><option value="1,2" selected>qux</option></select>',
	"select tag without multiselect"
);

is(
	div(['arg' => "val: \x03, \x0e, \x0f, \x0c, \xc2\x80, \xc2\x9f, \t, \n, \r", "\x02, \x0e, \x0f, \x0c, \xc2\x80, \xc2\x9f, \t, \n, \r"]),
	"<div arg=\"val:  ,  ,  ,  ,  ,  , &#9;, &#10;, &#13;\">\x02, \x0e, \x0f, \x0c, \xc2\x80, \xc2\x9f, \t, \n, \r</div>\n",
	"blank unprintable characters and illegal utf8 in attributes but not in normal text"
);

is(
	div(["arg\x03\x0e\x0f\xc2\x80\xc2\x9fendarg" => "value", "content"]),
	"<div arg\x03\x0e\x0f\xc2\x80\xc2\x9fendarg=\"value\">content</div>\n",
	"don't blank unprintable characters and illegal utf8 in attribute names"
);

is(
	div(['arg' => "abc äüö éá© œàè îôÇ xyz", "abc äüö éá© œàè îôÇ xyz"]),
	"<div arg=\"abc äüö éá© œàè îôÇ xyz\">abc äüö éá© œàè îôÇ xyz</div>\n",
	"leave legal utf8 intact"
);

unset($GLOBALS['debug_utf8check']);
is(
	div(['arg' => "value \xc2", "content"]),
	"<div arg=\"value \xc2\">content</div>\n",
	"handle single \\xc2 at end of attribute value"
);

is(
	div(["arg\x00end" => "value \x00 end", "content \x00 content end"]),
	"<div arg\x00end=\"value   end\">content \x00 content end</div>\n",
	"handle 0-bytes"
);

is(
	div(['arg' => "& \" < > \n '", "& \" < > \n '"]),
	"<div arg=\"&amp; &quot; &lt; &gt; &#10; '\">& \" < > \n '</div>\n",
	"use html entities in attributes but not in normal text"
);

is(
	html(),
	"<!DOCTYPE html>\n<html lang=\"de\">\n</html>\n",
	"html5 doctype"
);

# Test different html types
foreach (['html5' => "<br flag>", 'html' => "<br flag>", 'xhtml' => "<br flag=\"flag\" />", 'xhtml-mobile' => "<br flag=\"flag\" />"] as $type => $value)
{
	unset($GLOBALS['it_html']);
	new it_html(['htmltype' => $type, 'error_on_redefine' => false]);
	is (trim(br(['flag' => true])), $value, "Check empty tag and attribute for $type");
}

# XHTML generation
unset($GLOBALS['it_html']);
new it_html(['htmltype' => "xhtml", 'tags' => "script", 'error_on_redefine' => false]);

is(
	script(),
	"<script></script>\n",
	"script may not be shortened (see xhtml spec)"
);

is(
	h1(),
	"<h1></h1>\n",
	"empty h1 tag in xhtml context"
);

is(
	html(),
	"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"de\">\n</html>\n",
	"xhtml doctype"
);


# XML generation
unset($GLOBALS['it_html']);
new it_html(['htmltype' => "xml", 'name' => 'it_html', 'tags' => "xmltest", 'error_on_redefine' => false]);

is(
	xmltest(),
	"<xmltest />\n",
	"empty xmltest tag"
);

is(
	xmltest("foo"),
	"<xmltest>foo</xmltest>\n",
	"non-empty xmltest tag"
);

is(
	xmltest(['href' => "&foo", 'true' => true, 'false' => false, 'null' => null, 'empty' => ""]),
	'<xmltest href="&amp;foo" true="true" empty="" />' . "\n",
	"xmltest tag with attributes"
);

is(
	h1(),
	"<h1 />\n",
	"empty h1 tag in xml context"
);

is(
	input(),
	"<input />",
	"empty input tag in xml context"
);

# Inheriting and extending it_html
class myhtml extends it_html
{

function __construct($p = [])
{
	parent::__construct($p + ['moretags' => 'overriddentag,defaulttag', 'nonewlinetags' => 'a,b,defaulttag,em,img,input,overriddentag,span,div']);
}

function myimg($args)
{
	array_unshift($args, ['alt' => "ALT", 'bar' => "BAR"]);
	return parent::img(array_filter(it_parse_args($args)));
}

function overriddentag($args)
{
	return parent::overriddentag($args);
}

}

unset($GLOBALS['it_html']);
new myhtml(['htmltype' => "html", 'error_on_redefine' => false]);

is(
	myimg(['src' => "foo.gif", 'alt' => "foo"]),
	'<img alt="foo" bar="BAR" src="foo.gif">',
	"it_html inheritance"
);

is(
	div(['attr' => 'value'], 'content'),
	'<div attr="value">content</div>',
	"different nonewlinetags respected"
);

is(
	overriddentag("one ", ['src' => "evil", 'alt' => ""], "two ", ['foo' => "bar"], "three"),
	'<overriddentag src="evil" alt="" foo="bar">one two three</overriddentag>',
	"moretags override"
);

is(
	defaulttag("one ", ['src' => "evil", 'alt' => ""], "two ", ['foo' => "bar"], "three"),
	'<defaulttag src="evil" alt="" foo="bar">one two three</defaulttag>',
	"moretags default"
);

is(
	it_html::sanitize(" \r \n " . '                        <p><a href="http://www.flickr.com/people/swisspics%/">swisspics</a> posted < &lt; &auml; &amp; yesterday <b>a <i>photo</i></b> <b><i>tag missmatch</b></i>:</p><br><BR />

<P><a href="javascript:window.close()" title="Wolken"><img src="http://farm1.static.flickr.com/177/377214376_bcba167a7d_m.jpg" width="240" height="180" alt="Wolken" style="border: 1px solid #ddd;" /></a></p>
'),
	 ' <p><a href="http://www.flickr.com/people/swisspics%25/">swisspics</a> posted &lt; &lt; ä &amp; yesterday <b>a <i>photo</i></b> <b>tag missmatch</b>:</p><br /><br /> <p><img src="http://farm1.static.flickr.com/177/377214376_bcba167a7d_m.jpg" alt="" /></p> ',
	'it_html::sanitize tag soup'
);

is(
	it_html::sanitize('q&#8592;x'),
	 "q←x",
	'it_html::sanitize preserve numeric entities'
);

is(
	it_html::sanitize('q&uuml;x'),
	 "q\xc3\xbcx",
	'it_html::sanitize with utf-8'
);

is(
	it_html::sanitize('<b>a<br>b</b>'),
	 "<b>a<br />b</b>",
	'it_html::sanitize with b and br (tag prefix of other tag bug)'
);

is(
	it_html::sanitize('<div></div>'),
	'',
	'empty tags removal'
);

foreach (json_decode(it::file_get_contents(dirname($argv[0]) . '/U_tests.json'), true) as $test)
	is(U(...$test['args']), $test['exp'], $test['name']);

is(it_html::entity_decode("&auml;"),  "ä");
is(it_html::entity_decode("&#x4a;"),  "J");
is(it_html::entity_decode("&#x4A;"),  "J");
is(it_html::entity_decode("&#65;"),   "A");

# tests for itools extension
is(table(null), "<table></table>\n", "table() null argument");
list($data, $attr) = it_parse_args([null]);
ok($data === "", "it_parse_args compatiblity: treat null like empty string");

#
# check transliterations in iso-8859-1
#

it_html::configure(['charset' => "iso-8859-1"]);
ini_set('default_charset', "iso-8859-1");

is(
	it_html::sanitize('q&uuml;x'),
	 "q\xfcx",
	'it_html::sanitize with latin1'
);

is(
	it_html::sanitize('q&#8592;x'),
	 "q&#8592;x",
	'it_html::sanitize preserve non-decodable numeric entities'
);
is(it_html::entity_decode("&#8217;"), "'", "it_html::entity_decode numeric decimal entity");
is(it_html::entity_decode("&#xfff;"), " ", "it_html::entity_decode invalid numeric hex entity");
is(it_html::entity_decode("&#999;"),  " ", "it_html::entity_decode invalid numeric decimal entity");
is(it_html::entity_decode("&#x8b;"),   " ", "it_html::entity_decode entity von 0x80-0x9f");