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
+
+
+
+
+
+
+
+
+