Permalink
Browse files

Moved .wrap, .before, and .after from Element to Node for flexibility…

…. Overriding implementations in Element still return Element.
  • Loading branch information...
1 parent e3ddbb8 commit eea130b9196359ede188d65afd619fd788cacf73 @jhy jhy committed Feb 3, 2011
@@ -303,37 +303,31 @@ public Element prepend(String html) {
addChildren(0, fragment.childNodesAsArray());
return this;
}
-
+
/**
* Insert the specified HTML into the DOM before this element (i.e. as a preceeding sibling).
+ *
* @param html HTML to add before this element
* @return this element, for chaining
* @see #after(String)
*/
+ @Override
public Element before(String html) {
- addSiblingHtml(siblingIndex(), html);
- return this;
+ return (Element) super.before(html);
}
-
+
/**
* Insert the specified HTML into the DOM after this element (i.e. as a following sibling).
+ *
* @param html HTML to add after this element
* @return this element, for chaining
* @see #before(String)
*/
+ @Override
public Element after(String html) {
- addSiblingHtml(siblingIndex()+1, html);
- return this;
- }
-
- private void addSiblingHtml(int index, String html) {
- Validate.notNull(html);
- Validate.notNull(parentNode);
-
- Element fragment = Parser.parseBodyFragmentRelaxed(html, baseUri()).body();
- parentNode.addChildren(index, fragment.childNodesAsArray());
+ return (Element) super.after(html);
}
-
+
/**
* Remove all of the element's child nodes. Any attributes are left as-is.
* @return this element
@@ -344,42 +338,16 @@ public Element empty() {
}
/**
- Wrap the supplied HTML around this element.
- @param html HTML to wrap around this element, e.g. {@code <div class="head"></div>}. Can be arbitralily deep.
- @return this element, for chaining.
+ * Wrap the supplied HTML around this element.
+ *
+ * @param html HTML to wrap around this element, e.g. {@code <div class="head"></div>}. Can be arbitrarily deep.
+ * @return this element, for chaining.
*/
+ @Override
public Element wrap(String html) {
- Validate.notEmpty(html);
-
- Element wrapBody = Parser.parseBodyFragmentRelaxed(html, baseUri).body();
- Elements wrapChildren = wrapBody.children();
- Element wrap = wrapChildren.first();
- if (wrap == null) // nothing to wrap with; noop
- return null;
-
- Element deepest = getDeepChild(wrap);
- parentNode.replaceChild(this, wrap);
- deepest.addChildren(this);
-
- // remainder (unbalananced wrap, like <div></div><p></p> -- The <p> is remainder
- if (wrapChildren.size() > 1) {
- for (int i = 1; i < wrapChildren.size(); i++) { // skip first
- Element remainder = wrapChildren.get(i);
- remainder.parentNode.removeChild(remainder);
- wrap.appendChild(remainder);
- }
- }
- return this;
+ return (Element) super.wrap(html);
}
- private Element getDeepChild(Element el) {
- List<Element> children = el.children();
- if (children.size() > 0)
- return getDeepChild(children.get(0));
- else
- return el;
- }
-
/**
* Get sibling elements.
* @return sibling elements
@@ -2,6 +2,8 @@
import org.jsoup.helper.StringUtil;
import org.jsoup.helper.Validate;
+import org.jsoup.parser.Parser;
+import org.jsoup.select.Elements;
import org.jsoup.select.NodeTraversor;
import org.jsoup.select.NodeVisitor;
@@ -230,6 +232,73 @@ public void remove() {
Validate.notNull(parentNode);
parentNode.removeChild(this);
}
+
+ /**
+ * Insert the specified HTML into the DOM before this node (i.e. as a preceeding sibling).
+ * @param html HTML to add before this element
+ * @return this node, for chaining
+ * @see #after(String)
+ */
+ public Node before(String html) {
+ addSiblingHtml(siblingIndex(), html);
+ return this;
+ }
+
+ /**
+ * Insert the specified HTML into the DOM after this node (i.e. as a following sibling).
+ * @param html HTML to add after this element
+ * @return this node, for chaining
+ * @see #before(String)
+ */
+ public Node after(String html) {
+ addSiblingHtml(siblingIndex()+1, html);
+ return this;
+ }
+
+ private void addSiblingHtml(int index, String html) {
+ Validate.notNull(html);
+ Validate.notNull(parentNode);
+
+ Element fragment = Parser.parseBodyFragmentRelaxed(html, baseUri()).body();
+ parentNode.addChildren(index, fragment.childNodesAsArray());
+ }
+
+ /**
+ Wrap the supplied HTML around this node.
+ @param html HTML to wrap around this element, e.g. {@code <div class="head"></div>}. Can be arbitrarily deep.
+ @return this node, for chaining.
+ */
+ public Node wrap(String html) {
+ Validate.notEmpty(html);
+
+ Element wrapBody = Parser.parseBodyFragmentRelaxed(html, baseUri).body();
+ Elements wrapChildren = wrapBody.children();
+ Element wrap = wrapChildren.first();
+ if (wrap == null) // nothing to wrap with; noop
+ return null;
+
+ Element deepest = getDeepChild(wrap);
+ parentNode.replaceChild(this, wrap);
+ deepest.addChildren(this);
+
+ // remainder (unbalanced wrap, like <div></div><p></p> -- The <p> is remainder
+ if (wrapChildren.size() > 1) {
+ for (int i = 1; i < wrapChildren.size(); i++) { // skip first
+ Element remainder = wrapChildren.get(i);
+ remainder.parentNode.removeChild(remainder);
+ wrap.appendChild(remainder);
+ }
+ }
+ return this;
+ }
+
+ private Element getDeepChild(Element el) {
+ List<Element> children = el.children();
+ if (children.size() > 0)
+ return getDeepChild(children.get(0));
+ else
+ return el;
+ }
/**
* Replace this node in the DOM with the supplied node.
@@ -56,4 +56,14 @@
assertEquals("Hello there!", div.text());
assertTrue(tn.parent() == tail.parent());
}
+
+ @Test public void testSplitAnEmbolden() {
+ Document doc = Jsoup.parse("<div>Hello there</div>");
+ Element div = doc.select("div").first();
+ TextNode tn = (TextNode) div.childNode(0);
+ TextNode tail = tn.splitText(6);
+ tail.wrap("<b></b>");
+
+ assertEquals("Hello <b>there</b>", TextUtil.stripNewlines(div.html())); // not great that we get \n<b>there there... must correct
+ }
}

0 comments on commit eea130b

Please sign in to comment.