diff --git a/src/Html.php b/src/Html.php
index 5d512ed..d6f207b 100644
--- a/src/Html.php
+++ b/src/Html.php
@@ -3,6 +3,9 @@
use DOMDocument;
use DOMDocumentType;
+use DOMElement;
+use DOMNode;
+use DOMText;
class Html {
@@ -69,6 +72,39 @@ public function toSnippet(string $id): Snippet {
return new SimpleSnippet($id, $imported);
}
+ public function extractAsSnippets(Selector $selector, string $targetId): SnippetList {
+ $selection = $selector->select($this->dom->documentElement);
+ if ($selection->isEmpty()) {
+ throw new TempladoException('Selection result is empty - cannot extract');
+ }
+
+ $list = new SnippetList();
+ foreach($selection as $item) {
+ assert($item instanceof DOMNode);
+
+ if ($item instanceof DOMText) {
+ $list->addSnippet(
+ new TextSnippet($targetId, $item)
+ );
+
+ continue;
+ }
+
+ if ($item instanceof DOMElement) {
+ $list->addSnippet(
+ new SimpleSnippet($targetId, $item)
+ );
+
+ continue;
+ }
+
+ throw new TempladoException('Unspported node type - cannot extract to snippet');
+ }
+
+ return $list;
+ }
+
+
public function asString(Filter $filter = null): string {
$content = $this->serializeDomDocument();
$content = (new EmptyElementsFilter())->apply($content);
diff --git a/tests/HTMLTest.php b/tests/HTMLTest.php
index aa2eb7f..961cc85 100644
--- a/tests/HTMLTest.php
+++ b/tests/HTMLTest.php
@@ -228,4 +228,96 @@ public function testCanBeConvertedToSnippet(): void {
$this->assertInstanceOf(Snippet::class, $snippet);
$this->assertEquals('test', $snippet->getTargetId());
}
+
+ /**
+ * @uses \Templado\Engine\XPathSelector
+ * @uses \Templado\Engine\Selection
+ * @uses \Templado\Engine\TempladoException
+ */
+ public function testEmptySelectionOnExtractThrowsException(): void {
+ $dom = new \DOMDocument();
+ $dom->loadXML('');
+
+ $selector = new XPathSelector('//no-match');
+
+ $this->expectException(TempladoException::class);
+ (new Html($dom))->extractAsSnippets($selector, 'some-id');
+ }
+
+ /**
+ * @uses \Templado\Engine\XPathSelector
+ * @uses \Templado\Engine\SimpleSnippet
+ * @uses \Templado\Engine\SnippetList
+ * @uses \Templado\Engine\Selection
+ */
+ public function testSimpleSnippetsCanBeExtracted(): void {
+ $dom = new \DOMDocument();
+ $dom->loadXML('');
+
+ $selector = new XPathSelector('//a');
+
+ $list = (new Html($dom))->extractAsSnippets($selector, 'some-id');
+
+ $testDom = new DOMDocument();
+
+ $this->assertCount(3, $list);
+ foreach($list as $snippet) {
+ $this->assertInstanceOf(SimpleSnippet::class, $snippet);
+ $this->assertSame('some-id', $snippet->getTargetId());
+
+ $targetNode = $testDom->createElement('target');
+
+ $snippet->applyTo($targetNode);
+
+ $this->assertSame('', $testDom->saveXML($targetNode));
+ }
+ }
+
+ /**
+ * @uses \Templado\Engine\XPathSelector
+ * @uses \Templado\Engine\SimpleSnippet
+ * @uses \Templado\Engine\TextSnippet
+ * @uses \Templado\Engine\SnippetList
+ * @uses \Templado\Engine\Selection
+ */
+ public function testTextSnippetsCanBeExtracted(): void {
+ $dom = new \DOMDocument();
+ $dom->loadXML('Text');
+
+ $selector = new XPathSelector('/root/text()');
+
+ $list = (new Html($dom))->extractAsSnippets($selector, 'some-id');
+
+ $testDom = new DOMDocument();
+
+ $this->assertCount(1, $list);
+
+ foreach($list as $snippet) {
+ $this->assertInstanceOf(TextSnippet::class, $snippet);
+ $this->assertSame('some-id', $snippet->getTargetId());
+
+ $targetNode = $testDom->createElement('target');
+
+ $snippet->applyTo($targetNode);
+
+ $this->assertSame('Text', $testDom->saveXML($targetNode));
+ }
+ }
+
+ /**
+ * @uses \Templado\Engine\Selection
+ * @uses \Templado\Engine\TempladoException
+ * @uses \Templado\Engine\XPathSelector
+ */
+ public function testTryingToExtractNonElementNodeThrowsException(): void {
+ $dom = new \DOMDocument();
+ $dom->loadXML('');
+
+ $selector = new XPathSelector('//processing-instruction("php")');
+
+ $this->expectException(TempladoException::class);
+ (new Html($dom))->extractAsSnippets($selector, 'some-id');
+
+ }
+
}