From a063b873e28d86573fd148da142bf0ceef8e8b18 Mon Sep 17 00:00:00 2001 From: Nickolay Bukreyev Date: Mon, 12 Nov 2018 22:55:51 +0700 Subject: [PATCH 1/2] Always quote attribute values --- src/html/dom.d | 36 ++++++++++++++++-------------------- src/html/utils.d | 22 ---------------------- 2 files changed, 16 insertions(+), 42 deletions(-) diff --git a/src/html/dom.d b/src/html/dom.d index 32ea81d..edaba36 100644 --- a/src/html/dom.d +++ b/src/html/dom.d @@ -601,14 +601,9 @@ class Node { app.put(attr); if (value.length) { - if (value.requiresQuotes) { - app.put("=\""); - app.writeQuotesEscaped(value); - app.put("\""); - } else { - app.put('='); - app.put(value); - } + app.put("=\""); + app.writeQuotesEscaped(value); + app.put("\""); } } @@ -669,14 +664,9 @@ class Node { app.put(attr); if (value.length) { - if (value.requiresQuotes) { - app.put("=\""); - app.writeQuotesEscaped(value); - app.put("\""); - } else { - app.put('='); - app.put(value); - } + app.put("=\""); + app.writeQuotesEscaped(value); + app.put("\""); } } @@ -1127,6 +1117,12 @@ unittest { assert(doc.root.outerHTML == `
`, doc.root.outerHTML); } +// quotes should be preserved as they are mandatory in SVG +unittest { + auto doc = createDocument(``); + assert(doc.root.outerHTML == ``, doc.root.outerHTML); +} + // toString prints elements with content as unittest { // self-closed element w/o content @@ -1346,8 +1342,8 @@ private: unittest { - const(char)[] src = `text`; - auto doc = createDocument(src); + const(char)[] src = `text`; + auto doc = createDocument(`text`); assert(doc.root.html == src, doc.root.html); const(char)[] srcq = `text`; @@ -1366,11 +1362,11 @@ unittest { auto child = cloned.find("child").front.clone; child.attr("attr", "test"); cloned.find("parent").front.appendChild(child); - assert(cloned.html == `text`, cloned.html); + assert(cloned.html == `text`, cloned.html); assert(doc.root.html == src, doc.root.html); child.text = "text"; - assert(cloned.html == `texttext`, cloned.html); + assert(cloned.html == `texttext`, cloned.html); assert(doc.root.html == src, doc.root.html); // document cloning diff --git a/src/html/utils.d b/src/html/utils.d index 18b97f5..933cea8 100644 --- a/src/html/utils.d +++ b/src/html/utils.d @@ -17,28 +17,6 @@ bool isAllWhite(Char)(Char[] value) { } -bool requiresQuotes(Char)(Char[] value) { - auto ptr = value.ptr; - const end = ptr + value.length; - - while (ptr != end) { - switch (*ptr++) { - case 'a': .. case 'z': - case 'A': .. case 'Z': - case '0': .. case '9': - case '-': - case '_': - case '.': - case ':': - continue; - default: - return true; - } - } - return false; -} - - bool equalsCI(CharA, CharB)(const(CharA)[] a, const(CharB)[] b) { if (a.length == b.length) { for (size_t i; i < a.length; ++i) { From e5492644950eadabd402d8f6da6a4e4880aea64c Mon Sep 17 00:00:00 2001 From: Nickolay Bukreyev Date: Mon, 12 Nov 2018 23:54:50 +0700 Subject: [PATCH 2/2] Escape entities that must be escaped --- src/html/dom.d | 21 ++++++++++++++++----- src/html/utils.d | 42 ++++++++++++++++-------------------------- 2 files changed, 32 insertions(+), 31 deletions(-) diff --git a/src/html/dom.d b/src/html/dom.d index edaba36..904aa8c 100644 --- a/src/html/dom.d +++ b/src/html/dom.d @@ -602,7 +602,7 @@ class Node { if (value.length) { app.put("=\""); - app.writeQuotesEscaped(value); + app.writeHTMLEscaped!(Yes.escapeQuotes)(value); app.put("\""); } } @@ -628,7 +628,7 @@ class Node { } break; case Text: - app.put(tag_); + app.writeHTMLEscaped!(No.escapeQuotes)(tag_); break; case Comment: app.put("