ajout SimpleTag
This commit is contained in:
parent
b274372c41
commit
b09d01c37a
@ -14,8 +14,8 @@ class BlockTag extends Tag {
|
|||||||
protected ?string $endPrefix;
|
protected ?string $endPrefix;
|
||||||
protected ?string $endSuffix;
|
protected ?string $endSuffix;
|
||||||
|
|
||||||
function reset(string $tag, ?array $params=null, $content=null): self {
|
function reset(string $tag, $content=null, ?array $params=null): self {
|
||||||
parent::reset($tag, $params, $content);
|
parent::reset($tag, $content, $params);
|
||||||
$this->startPrefix = $params["start_prefix"] ?? self::START_PREFIX;
|
$this->startPrefix = $params["start_prefix"] ?? self::START_PREFIX;
|
||||||
$this->startSuffix = $params["start_suffix"] ?? self::START_SUFFIX;
|
$this->startSuffix = $params["start_suffix"] ?? self::START_SUFFIX;
|
||||||
$this->endPrefix = $params["end_prefix"] ?? self::END_PREFIX;
|
$this->endPrefix = $params["end_prefix"] ?? self::END_PREFIX;
|
||||||
|
|||||||
@ -1,6 +1,23 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace nulib\web\content;
|
namespace nulib\web\content;
|
||||||
|
|
||||||
class EmptyTag extends Tag {
|
use nulib\A;
|
||||||
const ALLOW_EMPTY = true;
|
use nulib\php\content\c;
|
||||||
|
|
||||||
|
class EmptyTag extends SimpleTag {
|
||||||
|
function getContent($objectOrClass=null): iterable {
|
||||||
|
$attrs = [];
|
||||||
|
$children = [];
|
||||||
|
$this->resolveContents($attrs, $children, $this->contents);
|
||||||
|
$parts = ["<{$this->tag}"];
|
||||||
|
$this->addAttrs($parts, $attrs);
|
||||||
|
if ($children) {
|
||||||
|
$parts[] = ">";
|
||||||
|
A::merge($parts, $children);
|
||||||
|
$parts[] = "</{$this->tag}>";
|
||||||
|
} else {
|
||||||
|
$parts[] = "/>";
|
||||||
|
}
|
||||||
|
return [c::to_string($parts)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
108
src/web/content/SimpleTag.php
Normal file
108
src/web/content/SimpleTag.php
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<?php
|
||||||
|
namespace nulib\web\content;
|
||||||
|
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use nulib\A;
|
||||||
|
use nulib\cl;
|
||||||
|
use nulib\php\content\c;
|
||||||
|
use nulib\php\content\IContent;
|
||||||
|
use nulib\php\content\IPrintable;
|
||||||
|
use nulib\php\func;
|
||||||
|
use nur\str;
|
||||||
|
|
||||||
|
class SimpleTag implements IContent {
|
||||||
|
function __construct(string $tag, $content=null) {
|
||||||
|
$this->reset($tag, $content);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected string $tag;
|
||||||
|
|
||||||
|
protected iterable $contents;
|
||||||
|
|
||||||
|
function reset(string $tag, $content=null, ?array $params=null): self {
|
||||||
|
$this->tag = $tag;
|
||||||
|
$this->contents = c::q($content);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
function add($content): self {
|
||||||
|
if (!is_array($this->contents)) {
|
||||||
|
# si c'est un itérable, le mettre en tant qu'élément dans le tableau
|
||||||
|
$contents = $this->contents;
|
||||||
|
$this->contents = [static function() use ($contents) {
|
||||||
|
return $contents;
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
A::merge($this->contents, c::q($content));
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resolveContents(array &$attrs, array &$children, iterable $contents): void {
|
||||||
|
$index = 0;
|
||||||
|
foreach ($contents as $key => $content) {
|
||||||
|
if ($content instanceof Closure) {
|
||||||
|
# les closure sont appelés dès la résolution
|
||||||
|
$content = func::with($content)->invoke([$this]);
|
||||||
|
if ($key === $index) {
|
||||||
|
$index++;
|
||||||
|
# le résultat est inséré tels quels dans le flux
|
||||||
|
if (is_iterable($content)) {
|
||||||
|
$children[] = $content;
|
||||||
|
} else {
|
||||||
|
A::merge($children, cl::with($content));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
# le résultat est la valeur de l'attribut
|
||||||
|
A::merge($attrs[$key], [$content]);
|
||||||
|
}
|
||||||
|
} elseif (is_array($content)) {
|
||||||
|
if ($key === $index) {
|
||||||
|
$index++;
|
||||||
|
$this->resolveContents($attrs, $children, $content);
|
||||||
|
} else {
|
||||||
|
foreach ($content as &$value) {
|
||||||
|
if ($value instanceof Closure) {
|
||||||
|
$value = func::with($value)->invoke([$this]);
|
||||||
|
}
|
||||||
|
}; unset($value);
|
||||||
|
A::merge($attrs[$key], $content);
|
||||||
|
}
|
||||||
|
} elseif ($key === $index) {
|
||||||
|
$index++;
|
||||||
|
A::merge($children, cl::with($content));
|
||||||
|
} else {
|
||||||
|
A::merge($attrs[$key], [$content]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addAttrs(array &$parts, array $attrs): void {
|
||||||
|
foreach ($attrs as $key => $value) {
|
||||||
|
if ($value === null || $value === false) continue;
|
||||||
|
if ($value === true || $value === [true]) {
|
||||||
|
$value = $key;
|
||||||
|
} elseif (is_array($value)) {
|
||||||
|
$value = str::join3($value);
|
||||||
|
if (!$value) continue;
|
||||||
|
}
|
||||||
|
$parts[] = " ";
|
||||||
|
$parts[] = $key;
|
||||||
|
$parts[] = "=\"";
|
||||||
|
$parts[] = htmlspecialchars($value);
|
||||||
|
$parts[] = "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContent($objectOrClass=null): iterable {
|
||||||
|
$attrs = [];
|
||||||
|
$children = [];
|
||||||
|
$this->resolveContents($attrs, $children, $this->contents);
|
||||||
|
$parts = ["<{$this->tag}"];
|
||||||
|
$this->addAttrs($parts, $attrs);
|
||||||
|
$parts[] = ">";
|
||||||
|
A::merge($parts, $children);
|
||||||
|
$parts[] = "</{$this->tag}>";
|
||||||
|
return [c::to_string($parts)];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,133 +2,52 @@
|
|||||||
namespace nulib\web\content;
|
namespace nulib\web\content;
|
||||||
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use nulib\A;
|
|
||||||
use nulib\cl;
|
|
||||||
use nulib\php\content\c;
|
use nulib\php\content\c;
|
||||||
use nulib\php\content\IContent;
|
|
||||||
use nulib\php\content\IPrintable;
|
use nulib\php\content\IPrintable;
|
||||||
use nulib\php\func;
|
|
||||||
use nur\str;
|
|
||||||
|
|
||||||
class Tag implements IContent, IPrintable {
|
|
||||||
const ALLOW_EMPTY = false;
|
|
||||||
|
|
||||||
|
class Tag extends SimpleTag implements IPrintable {
|
||||||
const REQUIRE_CONTENT = false;
|
const REQUIRE_CONTENT = false;
|
||||||
|
|
||||||
function __construct(string $tag, ?array $params=null, $content=null) {
|
function __construct(string $tag, ?array $params=null, $content=null) {
|
||||||
$this->reset($tag, $params, $content);
|
$this->reset($tag, $content, $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool $allowEmpty;
|
|
||||||
|
|
||||||
protected bool $requireContent;
|
protected bool $requireContent;
|
||||||
|
|
||||||
protected string $tag;
|
|
||||||
|
|
||||||
protected iterable $contents;
|
|
||||||
|
|
||||||
protected ?array $attrs = null;
|
protected ?array $attrs = null;
|
||||||
|
|
||||||
protected ?array $children = null;
|
protected ?array $children = null;
|
||||||
|
|
||||||
protected bool $empty = false;
|
function reset(string $tag, $content=null, ?array $params=null): self {
|
||||||
|
parent::reset($tag, $content, $params);
|
||||||
function reset(string $tag, ?array $params=null, $content=null): self {
|
|
||||||
$this->allowEmpty = $params["allow_empty"] ?? self::ALLOW_EMPTY;
|
|
||||||
$this->requireContent = $params["require_content"] ?? self::REQUIRE_CONTENT;
|
$this->requireContent = $params["require_content"] ?? self::REQUIRE_CONTENT;
|
||||||
$this->tag = $tag;
|
|
||||||
$this->contents = c::q($content);
|
|
||||||
$this->attrs = null;
|
$this->attrs = null;
|
||||||
$this->children = null;
|
$this->children = null;
|
||||||
$this->empty = false;
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
function add($content): self {
|
function add($content): self {
|
||||||
if (!is_array($this->contents)) {
|
parent::add($content);
|
||||||
# si c'est un itérable, l'inclure avec un merge statique, afin de pouvoir
|
|
||||||
# rajouter des éléments
|
|
||||||
$contents = $this->contents;
|
|
||||||
$this->contents = [static function() use ($contents) {
|
|
||||||
return $contents;
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
A::merge($this->contents, c::q($content));
|
|
||||||
$this->attrs = null;
|
$this->attrs = null;
|
||||||
$this->children = null;
|
$this->children = null;
|
||||||
$this->empty = false;
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function add_contents(iterable $source, array &$contents, array &$attrs): void {
|
|
||||||
$index = 0;
|
|
||||||
foreach ($source as $key => $content) {
|
|
||||||
if ($content instanceof Closure) {
|
|
||||||
# les closure sont appelés dès la résolution
|
|
||||||
$content = func::with($content)->invoke([$this]);
|
|
||||||
if ($key === $index) {
|
|
||||||
$index++;
|
|
||||||
# le résultat est inséré tels quels dans le flux
|
|
||||||
if (is_iterable($content)) {
|
|
||||||
$contents[] = $content;
|
|
||||||
} else {
|
|
||||||
A::merge($contents, cl::with($content));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
# le résultat est la valeur de l'attribut
|
|
||||||
A::merge($attrs[$key], [$content]);
|
|
||||||
}
|
|
||||||
} elseif (is_array($content)) {
|
|
||||||
if ($key === $index) {
|
|
||||||
$index++;
|
|
||||||
$this->add_contents($content, $contents, $attrs);
|
|
||||||
} else {
|
|
||||||
foreach ($content as &$value) {
|
|
||||||
if ($value instanceof Closure) {
|
|
||||||
$value = func::with($value)->invoke([$this]);
|
|
||||||
}
|
|
||||||
}; unset($value);
|
|
||||||
A::merge($attrs[$key], $content);
|
|
||||||
}
|
|
||||||
} elseif ($key === $index) {
|
|
||||||
$index++;
|
|
||||||
A::merge($contents, cl::with($content));
|
|
||||||
} else {
|
|
||||||
A::merge($attrs[$key], [$content]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolve($objectOrClass=null): self {
|
function resolve($objectOrClass=null): self {
|
||||||
if ($this->attrs === null) {
|
if ($this->attrs === null) {
|
||||||
$attrs = [];
|
$attrs = [];
|
||||||
$contents = [];
|
$children = [];
|
||||||
$this->add_contents($this->contents, $contents, $attrs);
|
$this->resolveContents($attrs, $children, $this->contents);
|
||||||
$this->attrs = $attrs;
|
$this->attrs = $attrs;
|
||||||
$this->children = c::resolve($contents, $objectOrClass);
|
$this->children = c::resolve($children, $objectOrClass);
|
||||||
$this->empty = $this->allowEmpty && !$this->children;
|
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStart(): array {
|
function getStart(): array {
|
||||||
$parts = ["<{$this->tag}"];
|
$parts = ["<{$this->tag}"];
|
||||||
foreach ($this->attrs as $key => $value) {
|
$this->addAttrs($parts, $this->attrs);
|
||||||
if ($value === null || $value === false) continue;
|
$parts[] = ">";
|
||||||
if ($value === true || $value === [true]) {
|
|
||||||
$value = $key;
|
|
||||||
} elseif (is_array($value)) {
|
|
||||||
$value = str::join3($value);
|
|
||||||
if (!$value) continue;
|
|
||||||
}
|
|
||||||
$parts[] = " ";
|
|
||||||
$parts[] = $key;
|
|
||||||
$parts[] = "=\"";
|
|
||||||
$parts[] = htmlspecialchars($value);
|
|
||||||
$parts[] = "\"";
|
|
||||||
}
|
|
||||||
$parts[] = $this->empty? "/>": ">";
|
|
||||||
return $parts;
|
return $parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,8 +56,7 @@ class Tag implements IContent, IPrintable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getEnd(): array {
|
function getEnd(): array {
|
||||||
if ($this->empty) return [];
|
return ["</{$this->tag}>"];
|
||||||
else return ["</{$this->tag}>"];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getContent($objectOrClass=null): iterable {
|
function getContent($objectOrClass=null): iterable {
|
||||||
|
|||||||
@ -24,10 +24,10 @@ class v {
|
|||||||
static function h6($content): BlockTag { return self::h("h6", $content); }
|
static function h6($content): BlockTag { return self::h("h6", $content); }
|
||||||
const H6 = [BlockTag::class, false, "h6", self::require_content];
|
const H6 = [BlockTag::class, false, "h6", self::require_content];
|
||||||
|
|
||||||
static function hr($content): EmptyTag { return (new EmptyTag("hr", null, $content)); }
|
static function hr($content=null): EmptyTag { return (new EmptyTag("hr", $content)); }
|
||||||
const HR = [EmptyTag::class, false, "hr", null];
|
const HR = [EmptyTag::class, false, "hr"];
|
||||||
static function br($content): EmptyTag { return (new EmptyTag("br", null, $content)); }
|
static function br($content=null): EmptyTag { return (new EmptyTag("br", $content)); }
|
||||||
const BR = [EmptyTag::class, false, "br", null];
|
const BR = [EmptyTag::class, false, "br"];
|
||||||
|
|
||||||
static function div($content): Tag { return (new Tag("div", null, $content)); }
|
static function div($content): Tag { return (new Tag("div", null, $content)); }
|
||||||
const DIV = [Tag::class, false, "div", null];
|
const DIV = [Tag::class, false, "div", null];
|
||||||
@ -36,16 +36,16 @@ class v {
|
|||||||
static function pre($content): Tag { return (new Tag("pre", self::require_content, $content)); }
|
static function pre($content): Tag { return (new Tag("pre", self::require_content, $content)); }
|
||||||
const PRE = [Tag::class, false, "pre", self::require_content];
|
const PRE = [Tag::class, false, "pre", self::require_content];
|
||||||
|
|
||||||
static function span($content): Tag { return (new Tag("span", null, $content)); }
|
static function span($content): SimpleTag { return (new SimpleTag("span", $content)); }
|
||||||
const SPAN = [Tag::class, false, "span", null];
|
const SPAN = [SimpleTag::class, false, "span"];
|
||||||
static function b($content): Tag { return (new Tag("b", null, $content)); }
|
static function b($content): SimpleTag { return (new SimpleTag("b", $content)); }
|
||||||
const B = [Tag::class, false, "b", null];
|
const B = [SimpleTag::class, false, "b"];
|
||||||
static function i($content): Tag { return (new Tag("i", null, $content)); }
|
static function i($content): SimpleTag { return (new SimpleTag("i", $content)); }
|
||||||
const I = [Tag::class, false, "i", null];
|
const I = [SimpleTag::class, false, "i"];
|
||||||
static function em($content): Tag { return (new Tag("em", null, $content)); }
|
static function em($content): SimpleTag { return (new SimpleTag("em", $content)); }
|
||||||
const EM = [Tag::class, false, "em", null];
|
const EM = [SimpleTag::class, false, "em"];
|
||||||
static function strong($content): Tag { return (new Tag("strong", null, $content)); }
|
static function strong($content): SimpleTag { return (new SimpleTag("strong", $content)); }
|
||||||
const STRONG = [Tag::class, false, "strong", null];
|
const STRONG = [SimpleTag::class, false, "strong"];
|
||||||
|
|
||||||
static function ul($content): BlockTag { return (new BlockTag("ul", self::start_nl, $content)); }
|
static function ul($content): BlockTag { return (new BlockTag("ul", self::start_nl, $content)); }
|
||||||
const UL = [BlockTag::class, false, "ul", self::start_nl];
|
const UL = [BlockTag::class, false, "ul", self::start_nl];
|
||||||
|
|||||||
@ -22,7 +22,6 @@ class TagTest extends TestCase {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
self::assertSame([
|
self::assertSame([
|
||||||
null,
|
|
||||||
"<tag",
|
"<tag",
|
||||||
" ", "class", "=\"", "first second", "\"",
|
" ", "class", "=\"", "first second", "\"",
|
||||||
" ", "attr", "=\"", "static true", "\"",
|
" ", "attr", "=\"", "static true", "\"",
|
||||||
@ -31,7 +30,6 @@ class TagTest extends TestCase {
|
|||||||
42,
|
42,
|
||||||
"after",
|
"after",
|
||||||
"</tag>",
|
"</tag>",
|
||||||
null,
|
|
||||||
], $tag->getContent());
|
], $tag->getContent());
|
||||||
|
|
||||||
self::assertSame('<tag class="first second" attr="static true">before 42 after</tag>', c::to_string($tag));
|
self::assertSame('<tag class="first second" attr="static true">before 42 after</tag>', c::to_string($tag));
|
||||||
@ -71,14 +69,12 @@ class TagTest extends TestCase {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
self::assertSame([
|
self::assertSame([
|
||||||
null,
|
|
||||||
"<tag",
|
"<tag",
|
||||||
" ", "class", "=\"", "first second third", "\"",
|
" ", "class", "=\"", "first second third", "\"",
|
||||||
" ", "cond", "=\"", "base ok dynok", "\"",
|
" ", "cond", "=\"", "base ok dynok", "\"",
|
||||||
" ", "plouf", "=\"", "base ok dynok", "\"",
|
" ", "plouf", "=\"", "base ok dynok", "\"",
|
||||||
">",
|
">",
|
||||||
"</tag>",
|
"</tag>",
|
||||||
null,
|
|
||||||
], $tag->getContent());
|
], $tag->getContent());
|
||||||
|
|
||||||
self::assertSame('<tag class="first second third" cond="base ok dynok" plouf="base ok dynok"></tag>', c::to_string($tag));
|
self::assertSame('<tag class="first second third" cond="base ok dynok" plouf="base ok dynok"></tag>', c::to_string($tag));
|
||||||
|
|||||||
@ -7,53 +7,81 @@ use nulib\tests\TestCase;
|
|||||||
|
|
||||||
class vTest extends TestCase {
|
class vTest extends TestCase {
|
||||||
function testStatic() {
|
function testStatic() {
|
||||||
$static = [
|
|
||||||
[v::H1, "title"],
|
|
||||||
[v::P, "text"],
|
|
||||||
];
|
|
||||||
self::assertSame(<<<EOT
|
self::assertSame(<<<EOT
|
||||||
<h1>title</h1>
|
<h1>title</h1>
|
||||||
<p>text</p>
|
<p>text</p>
|
||||||
EOT, c::to_string($static));
|
EOT, c::to_string([
|
||||||
|
[v::H1, "title"],
|
||||||
|
[v::P, "text"],
|
||||||
|
]));
|
||||||
|
|
||||||
$static = [
|
self::assertSame(<<<EOT
|
||||||
|
<h1>title</h1>
|
||||||
|
<p>the<b>bold</b>text<br/>linefeed</p><hr/>
|
||||||
|
EOT, c::to_string([
|
||||||
|
[v::H1, "title"],
|
||||||
|
[v::P, [
|
||||||
|
"the",
|
||||||
|
[v::B, "bold"],
|
||||||
|
"text",
|
||||||
|
[v::BR],
|
||||||
|
"linefeed",
|
||||||
|
]],
|
||||||
|
[v::HR],
|
||||||
|
]));
|
||||||
|
|
||||||
|
self::assertSame(<<<EOT
|
||||||
|
<div class="div" checked="checked">before<span>spanned</span><span class="black">blacked</span>after</div>
|
||||||
|
EOT, c::to_string([
|
||||||
[v::DIV, [
|
[v::DIV, [
|
||||||
"before",
|
"before",
|
||||||
"class" => "div",
|
"class" => "div",
|
||||||
[v::SPAN, "spanned"],
|
[v::SPAN, "spanned"],
|
||||||
|
[v::SPAN, ["class" => "black", "blacked"]],
|
||||||
"disabled" => false,
|
"disabled" => false,
|
||||||
"checked" => true,
|
"checked" => true,
|
||||||
"after",
|
"after",
|
||||||
]],
|
]],
|
||||||
];
|
]));
|
||||||
self::assertSame(<<<EOT
|
|
||||||
<div class="div" checked="checked">before<span>spanned</span>after</div>
|
|
||||||
EOT, c::to_string($static));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDynamic() {
|
function testDynamic() {
|
||||||
$dynamic = [
|
|
||||||
v::h1("title"),
|
|
||||||
v::p("text"),
|
|
||||||
];
|
|
||||||
self::assertSame(<<<EOT
|
self::assertSame(<<<EOT
|
||||||
<h1>title</h1>
|
<h1>title</h1>
|
||||||
<p>text</p>
|
<p>text</p>
|
||||||
EOT, c::to_string($dynamic));
|
EOT, c::to_string([
|
||||||
|
v::h1("title"),
|
||||||
|
v::p("text"),
|
||||||
|
]));
|
||||||
|
|
||||||
$dynamic = [
|
self::assertSame(<<<EOT
|
||||||
|
<h1>title</h1>
|
||||||
|
<p>the<b>bold</b>text<br/>linefeed</p><hr/>
|
||||||
|
EOT, c::to_string([
|
||||||
|
v::h1("title"),
|
||||||
|
v::p([
|
||||||
|
"the",
|
||||||
|
v::b("bold"),
|
||||||
|
"text",
|
||||||
|
v::br(),
|
||||||
|
"linefeed",
|
||||||
|
]),
|
||||||
|
v::hr(),
|
||||||
|
]));
|
||||||
|
|
||||||
|
self::assertSame(<<<EOT
|
||||||
|
<div class="div" checked="checked">before<span>spanned</span><span class="black">blacked</span>after</div>
|
||||||
|
EOT, c::to_string([
|
||||||
v::div([
|
v::div([
|
||||||
"before",
|
"before",
|
||||||
"class" => "div",
|
"class" => "div",
|
||||||
v::span("spanned"),
|
v::span("spanned"),
|
||||||
|
v::span(["class" => "black", "blacked"]),
|
||||||
"disabled" => false,
|
"disabled" => false,
|
||||||
"checked" => true,
|
"checked" => true,
|
||||||
"after",
|
"after",
|
||||||
]),
|
]),
|
||||||
];
|
]));
|
||||||
self::assertSame(<<<EOT
|
|
||||||
<div class="div" checked="checked">before<span>spanned</span>after</div>
|
|
||||||
EOT, c::to_string($dynamic));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDynamic2() {
|
function testDynamic2() {
|
||||||
@ -62,7 +90,19 @@ EOT, c::to_string($dynamic));
|
|||||||
["a" => "un", "b" => "deux", "c" => "trois"],
|
["a" => "un", "b" => "deux", "c" => "trois"],
|
||||||
["a" => "one", "b" => "two", "c" => "three"],
|
["a" => "one", "b" => "two", "c" => "three"],
|
||||||
];
|
];
|
||||||
$dynamic = v::table([
|
self::assertSame(<<<EOT
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th>a</th><th>b</th><th>c</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td>1</td><td>2</td><td>3</td></tr>
|
||||||
|
<tr><td>un</td><td>deux</td><td>trois</td></tr>
|
||||||
|
<tr><td>one</td><td>two</td><td>three</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
EOT, c::to_string(v::table([
|
||||||
v::thead(v::tr(function() use ($rows) {
|
v::thead(v::tr(function() use ($rows) {
|
||||||
$headers = array_keys(cl::first($rows));
|
$headers = array_keys(cl::first($rows));
|
||||||
foreach ($headers as $header) {
|
foreach ($headers as $header) {
|
||||||
@ -78,19 +118,6 @@ EOT, c::to_string($dynamic));
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
]);
|
])));
|
||||||
self::assertSame(<<<EOT
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr><th>a</th><th>b</th><th>c</th></tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr><td>1</td><td>2</td><td>3</td></tr>
|
|
||||||
<tr><td>un</td><td>deux</td><td>trois</td></tr>
|
|
||||||
<tr><td>one</td><td>two</td><td>three</td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
EOT, c::to_string($dynamic));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user