From 25abf40684f598f93b1fdbb7ca80a99bf8107c94 Mon Sep 17 00:00:00 2001 From: Abdullah <89297042+AzazelSensei@users.noreply.github.com> Date: Thu, 20 Aug 2026 06:08:50 +0300 Subject: [PATCH 1/3] Add Elements.before(Node) and after/prepend/append(Node) #953 (#2567) Fix #953 --------- Co-authored-by: Jonathan Hedley --- CHANGES.md | 1 + src/main/java/org/jsoup/select/Elements.java | 61 ++++++++++++++++++- .../java/org/jsoup/select/ElementsTest.java | 28 +++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 117558e131..30caabdf83 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ * Improved `W3CDom` conversion performance for documents with many nested namespace declarations. The W3C converter now uses the same optimized namespace tracking as the XML parser. [#2559](https://github.com/jhy/jsoup/pull/2559) * Improved `W3CDom` XML conversion to retain processing instructions, comments outside the root element, and CDATA sections, which were previously dropped or converted to text. [#2572](https://github.com/jhy/jsoup/issues/2572) * DOM mutation methods, including child insertion and replacement, now reject operations that would create a cycle, such as making a node its own child or moving an ancestor beneath a descendant. [#2552](https://github.com/jhy/jsoup/issues/2552) +* Added `Elements#before(Node)`, `after(Node)`, `prepend(Node)`, and `append(Node)` to match the existing HTML string methods. [#953](https://github.com/jhy/jsoup/issues/953) * XML serialization now repairs element and attribute names that start with an invalid character, rather than outputting `` elements or dropping attributes. For example, an attribute named `1a` is written as `_1a`. Additional leading underscores keep repaired attribute names unique if they conflict with another attribute. [#2573](https://github.com/jhy/jsoup/issues/2573) ### Changes diff --git a/src/main/java/org/jsoup/select/Elements.java b/src/main/java/org/jsoup/select/Elements.java index e84e2a0e7b..aaca336fd1 100644 --- a/src/main/java/org/jsoup/select/Elements.java +++ b/src/main/java/org/jsoup/select/Elements.java @@ -14,10 +14,9 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; -import java.util.function.Predicate; +import java.util.function.BiConsumer; import java.util.function.UnaryOperator; /** @@ -314,6 +313,17 @@ public Elements prepend(String html) { } return this; } + + /** + Add the supplied node to the start of each matched element's inner HTML. The node is cloned for each target. + + @param node the node to add inside each element, before the existing HTML + @return this, for chaining + @see Element#prependChild(Node) + */ + public Elements prepend(Node node) { + return insert(node, Element::prependChild); + } /** * Add the supplied HTML to the end of each matched element's inner HTML. @@ -328,6 +338,17 @@ public Elements append(String html) { return this; } + /** + Add the supplied node to the end of each matched element's inner HTML. The node is cloned for each target. + + @param node the node to add inside each element, after the existing HTML + @return this, for chaining + @see Element#appendChild(Node) + */ + public Elements append(Node node) { + return insert(node, Element::appendChild); + } + /** Insert the supplied HTML before each matched element's outer HTML. @@ -341,6 +362,17 @@ public Elements before(String html) { return this; } + /** + Insert the supplied node before each matched element's outer HTML. The node is cloned for each target. + + @param node the node to insert before each element + @return this, for chaining + @see Element#before(Node) + */ + public Elements before(Node node) { + return insert(node, Element::before); + } + /** Insert the supplied HTML after each matched element's outer HTML. @@ -354,6 +386,31 @@ public Elements after(String html) { return this; } + /** + Insert the supplied node after each matched element's outer HTML. The node is cloned for each target. + + @param node the node to insert after each element + @return this, for chaining + @see Element#after(Node) + */ + public Elements after(Node node) { + return insert(node, Element::after); + } + + /** + Applies a node insertion to each matched element, cloning the node for each target. + + @param node the node to insert + @param inserter the insertion operation + @return this, for chaining + */ + private Elements insert(Node node, BiConsumer inserter) { + Validate.notNull(node); + for (Element element : this) + inserter.accept(element, node.clone()); + return this; + } + /** Wrap the supplied HTML around each matched elements. For example, with HTML {@code

This is Jsoup

}, diff --git a/src/test/java/org/jsoup/select/ElementsTest.java b/src/test/java/org/jsoup/select/ElementsTest.java index b1b9b3dde4..2a39215d6f 100644 --- a/src/test/java/org/jsoup/select/ElementsTest.java +++ b/src/test/java/org/jsoup/select/ElementsTest.java @@ -169,12 +169,40 @@ public class ElementsTest { assertEquals("

This foois foojsoup.

", TextUtil.stripNewlines(doc.body().html())); } + @Test public void beforeNode() { + Document doc = Jsoup.parse("

This is jsoup.

"); + Element span = new Element("span").text("foo"); + doc.select("a").before(span); + assertEquals("

This foois foojsoup.

", TextUtil.stripNewlines(doc.body().html())); + assertNull(span.parent()); // cloned per target; original is left alone + assertNotSame(span, doc.selectFirst("span")); + } + @Test public void after() { Document doc = Jsoup.parse("

This is jsoup.

"); doc.select("a").after("foo"); assertEquals("

This isfoo jsoupfoo.

", TextUtil.stripNewlines(doc.body().html())); } + @Test public void afterNode() { + Document doc = Jsoup.parse("

This is jsoup.

"); + Element span = new Element("span").text("foo"); + doc.select("a").after(span); + assertEquals("

This isfoo jsoupfoo.

", TextUtil.stripNewlines(doc.body().html())); + assertNull(span.parent()); + } + + @Test public void prependAppendNode() { + Document doc = Jsoup.parse("

One

Two

Three

"); + Elements ps = doc.select("p"); + Element bold = new Element("b").text("Bold"); + Element ital = new Element("i").text("Ital"); + ps.prepend(bold).append(ital); + assertEquals("

BoldTwoItal

", TextUtil.stripNewlines(ps.get(1).outerHtml())); + assertNull(bold.parent()); + assertNull(ital.parent()); + } + @Test public void wrap() { String h = "

This is jsoup

"; Document doc = Jsoup.parse(h); From d8cd95525749500a3c4644de55a8d69ea4a2e8b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Aug 2026 13:13:08 +1000 Subject: [PATCH 2/3] Bump io.netty:netty-bom from 4.2.16.Final to 4.2.17.Final (#2574) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [io.netty:netty-bom](https://github.com/netty/netty) from 4.2.16.Final to 4.2.17.Final.
Release notes

Sourced from io.netty:netty-bom's releases.

netty-4.2.17.Final

What's Changed

New Contributors

... (truncated)

Commits
  • e0789d3 [maven-release-plugin] prepare release netty-4.2.17.Final
  • 1b5abc6 Merge changes from forks (#17213)
  • 36fbf57 Update surefire plugin to latest version (#17210)
  • a96226c Add .editorconfig to enforce consistent coding style (#17052)
  • 14a4e6a OpenSSL: Allow to obtain used named group via OpenSslSession (#17058)
  • 26255b1 Weakly reference engines from the OpenSSL engine map (#17199)
  • ae41417 HttpServerCodec: do not consume the method queue for 1xx interim responses ...
  • 41f1db5 Do not write WebSocket handshake response to the tail of the pipeline (#17192)
  • 035d76e Update compress-lzf to 1.2.1 (#17194)
  • 7681aff Fix JdkZlibDecompressor losing the tail of highly compressible streams (#17191)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=io.netty:netty-bom&package-manager=maven&previous-version=4.2.16.Final&new-version=4.2.17.Final)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5113f5037b..812268399a 100644 --- a/pom.xml +++ b/pom.xml @@ -625,7 +625,7 @@ io.netty netty-bom - 4.2.16.Final + 4.2.17.Final pom import From 7106824525712bfd84d40c51f430fa87e96e3476 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Aug 2026 13:13:24 +1000 Subject: [PATCH 3/3] Bump github/codeql-action from 4.37.4 to 4.37.6 (#2575) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.37.4 to 4.37.6.
Release notes

Sourced from github/codeql-action's releases.

v4.37.6

  • Changed the default filepath for the new remote file address format that was introduced in CodeQL Action 4.37.0 / 3.37.0 to .github/codeql-config.yml to align it with the suggested path that is used elsewhere. #4070

v4.37.5

  • Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the init Action instead of falling back to downloading the bundle before extracting it. #4061
Changelog

Sourced from github/codeql-action's changelog.

4.37.6 - 04 Aug 2026

  • Changed the default filepath for the new remote file address format that was introduced in CodeQL Action 4.37.0 / 3.37.0 to .github/codeql-config.yml to align it with the suggested path that is used elsewhere. #4070

4.37.5 - 03 Aug 2026

  • Fixed a bug where a network error while streaming the download of the CodeQL bundle could terminate the init Action instead of falling back to downloading the bundle before extracting it. #4061
Commits
  • 5595cca Merge pull request #4071 from github/update-v4.37.6-6a9359a1b
  • ec9c757 Add change note for PR 4070
  • 45c8742 Update changelog for v4.37.6
  • 6a9359a Merge pull request #4070 from github/mbg/remote-address/change-file-default
  • 065cdc0 Change DEFAULT_CONFIG_FILE_NAME
  • f99dd5a Merge pull request #4066 from github/dependabot/npm_and_yarn/js-yaml-5.2.2
  • 1804b21 Merge pull request #4068 from github/mergeback/v4.37.5-to-main-d1ba80a1
  • 3020a2f Rebuild
  • 93c3a5a Update changelog and version after v4.37.5
  • d1ba80a Merge pull request #4067 from github/update-v4.37.5-1cd4d01d5
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github/codeql-action&package-manager=github_actions&previous-version=4.37.4&new-version=4.37.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3f482eea04..6c5a744694 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -20,11 +20,11 @@ jobs: distribution: 'temurin' cache: 'maven' - name: CodeQL Initialization - uses: github/codeql-action/init@v4.37.4 + uses: github/codeql-action/init@v4.37.6 with: languages: java queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@v4.37.4 + uses: github/codeql-action/autobuild@v4.37.6 - name: CodeQL Analysis - uses: github/codeql-action/analyze@v4.37.4 + uses: github/codeql-action/analyze@v4.37.6