diff --git a/src/html/dom.d b/src/html/dom.d index d6c69d1..0c430d0 100644 --- a/src/html/dom.d +++ b/src/html/dom.d @@ -791,6 +791,14 @@ struct Node { return c; } + Node* clone(Node* oldnode) { + return document_.clone(oldnode); + } + + Node* clone() { + return document_.clone(&this); + } + package: enum TypeMask = 0x7; enum TypeShift = 0; @@ -883,10 +891,17 @@ static auto createDocument() { struct Document { - auto clone(Node* source) { + Node* clone(Node* source) { return source.clone(&this, alloc_); } + Document clone() { + Document other = Document(); + other.init(); + other.root(other.clone(this.root_)); + return other; + } + auto createElement(HTMLString tagName, Node* parent = null) { auto node = alloc_.alloc(); *node = Node(&this, tagName); @@ -1053,31 +1068,151 @@ private: PageAllocator!(Node, 1024) alloc_; } +version(unittest) { + /* just a quick and dirty unittest thing, so I can actually read the + errors that are going on without a huge useless stack trace + in my face */ + import std.stdio: writeln; + import core.exception: AssertError; + class DUnitIsBetter: AssertError { + this(string msg, string file, size_t line) { + super(msg,file,line); + } + } + shared static this() { + import core.runtime: Runtime, ModuleInfo; + Runtime.moduleUnitTester = function() { + foreach( m; ModuleInfo ) + { + if( m ) + { + auto fp = m.unitTest; + + if( fp ) + { + try + { + fp(); + } catch( DUnitIsBetter e ) + { + writeln(e.msg," at ",e.file,":",e.line); + return false; + } + } + } + } + return true; + }; + } + + template assertEqual(A,B) { + void assertEqual(A actual, B expected, + string file = __FILE__, + size_t line = __LINE__) { + if(actual != expected) { + writeln("Expected:"); + writeln(expected); + writeln("We got:"); + writeln(actual); + throw new DUnitIsBetter("fail",file,line); + } + } + } +} + /// unittest { + import std.stdio; + //import htmld: createDocument; const(char)[] s = `andsometext`; auto doc = createDocument(s); s = doc.root().html(); // normalize - auto c = doc.clone(doc.root()); - assert(s == c.html); - assert(s == doc.root().html()); - auto other = createDocument(); - c = other.clone(doc.root().children.front); - assert(s == c.outerHTML); + auto me = doc.clone(doc.root()); + assertEqual(me.html,s); + assertEqual(doc.root().html(),s); + + auto other = createDocument(""); + auto them = other.root().children.front; + them.appendChild(other.clone(them)); + + assertEqual(them.outerHTML,""); + + import std.regex: regex, replaceAll; + auto noformat = regex(`\s*\n\s*`); // can't kill spaces between attrs + typeof(s) clean(typeof(s) s) { + return s.replaceAll(noformat,""); + } + + me = me.children.front; + + me.attr("shoop", "woop"); + them.appendChild(other.clone(me)); + + s = clean( + ` +andsometext + + andsometext + +`); + s = clean(` + + + andsometext + +`); + assertEqual(them.outerHTML,s); + + assertEqual(other.root().outerHTML(), + ""~s~""); + + other.root().appendChild(other.clone(me)); + me.attr("still","here"); + + assertEqual(other.root.outerHTML, + clean(` + + + + andsometext + + + + andsometext + +`)); + Node* a = doc.root().firstChild; + Node* b = other.root().firstChild; + b.attr("jutsu","henge"); + b.appendChild(b.clone()); + a.appendChild(a.clone(b)); + + assertEqual( + doc.root.outerHTML, + clean(` + + andsometext + + + + andsometext + + + + + andsometext + + + + +`)); + + other = doc.clone(); + assertEqual(doc.toString(),other.toString()); - s = `andsometextandsometext`; - c.appendChild(other.clone(c)); - assert(s == c.outerHTML); - - s = ""~s~""; - other.root().appendChild(c); - - assert(s == other.root().outerHTML()); } - - struct DOMBuilder(Document) { this(ref Document document, Node* parent = null) { document_ = &document; @@ -1202,7 +1337,7 @@ struct DOMBuilder(Document) { } } -private: + Document* document_; Node* element_; States state_; diff --git a/src/html/pushdom.d b/src/html/pushdom.d new file mode 100644 index 0000000..5659dcb --- /dev/null +++ b/src/html/pushdom.d @@ -0,0 +1,163 @@ +module html.pushdom; +import html.dom: Document, Node, DOMBuilder, HTMLString; + import std.stdio: writeln; + +class NodeReceiver(Document) { + Builder!Document parent; + this(Builder!Document parent) { + // for changing parent.receiver + this.parent = parent; + } + void swap(NodeReceiver!Document other) { + this.parent.receiver = other; + } + void onOpenEnd(Node* element) {} + void onClose(Node* element) {} + void onCloseText(HTMLString text) {} + void onSelfClosing(Node* element) { + if(element) + this.onClose(element); + } + void onDocumentEnd(Document* doc) {} +} + +import std.string: replace, strip; +import std.format: format; + +immutable string prefix = "souper."; + +string wrapper(string name, int nargs, string block = "@super@") { + string arg_signature = ""; + string args = ""; + for(int i=0;i + + whatever + + + + +

+ +

+ + `; + parseHTML!(typeof(b), parserOptions)(source, b); + writeln(document.root.html); + string s = ""; + foreach(img; c.images) { + writeln("image: ",img.attr("src")); + s ~= img.attr("src"); + } + assert(s=="one.pngtwo.pngthree.png"); +}