Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
5e4dc15
FIX shortcode_close_parent closes the shortcode's own wrapping elemen…
micschk Oct 8, 2026
0f8f106
TEST container parents of a block shortcode, pending decision in #9
micschk Oct 8, 2026
c16248d
FIX block shortcode with comma-separated attributes not recognised (#8)
micschk Oct 8, 2026
b32264e
FIX hyphenated custom element names cut at the hyphen (#8)
micschk Oct 8, 2026
d9131b2
FIX reopened inline element repeats its id or name anchor (#8)
micschk Oct 8, 2026
1def126
FIX close-parent walk quadratic on large content (#8)
micschk Oct 8, 2026
78f57b9
TEST close-parent comment, case, self-closed, stray-tag and consume p…
micschk Oct 8, 2026
74bf520
DOCS changelog for the #8 follow-ups
micschk Oct 8, 2026
b67dcaa
FIX shortcode_close_parent leaves containers whole, closes only p/h1-…
micschk Oct 11, 2026
7fe25ca
FIX close-parent tag match stops at a '>' inside a quoted attribute (#8)
micschk Oct 11, 2026
e566607
FIX close-parent leaves address and dt whole: both take flow content …
micschk Oct 11, 2026
7b442ab
FIX reopened inline element: drop only real id/name attributes, not i…
micschk Oct 11, 2026
7d15635
FIX close-parent cost on stray closers in deep nesting, cap inline de…
micschk Oct 11, 2026
8f83a93
FIX close-parent skips tokenising content without a block shortcode (#8)
micschk Oct 11, 2026
fd84fa2
FIX no empty <p></p> between two block shortcodes when the paragraph …
micschk Oct 11, 2026
f35d3db
FIX close-parent: leave a block shortcode in place when the inline ta…
micschk Oct 11, 2026
65c98da
TEST close-parent timing rows: 5 s limit and an exact output check pe…
micschk Oct 11, 2026
5ad58e0
DOCS release is 5.2.0 (behaviour change in #9), not 5.1.1
micschk Oct 11, 2026
fdd8cc3
FIX close-parent tag match quadratic on tags that never close (#8)
micschk Oct 11, 2026
32c6ffb
FIX close-parent reopen cap raised to 8 KB so long real links are sti…
micschk Oct 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
# Changelog

## 5.2.0 (2026-10-11)

### Changed

- **`shortcode_close_parent` only closes elements that cannot hold block content** (#9). A block
shortcode now closes `<p>`, `<h1>`-`<h6>`, `<pre>` and `<summary>`, whose content model is phrasing
content, plus any inline elements (`<strong>`, `<a>`) between it and that element. Containers that
can already hold block content (`<div>`, `<li>`, `<td>`, `<th>`, `<dt>`, `<dd>`, `<address>`,
`<blockquote>`, `<section>`, `<article>`, `<figure>` and the like) are left whole, so a shortcode in a list item or table cell no longer
breaks the list or table. Inline elements inside such a container are still closed and reopened
around the shortcode.
**Behaviour change:** 5.1.0 closed a container when it was on the same line as the shortcode, so
`<div>[sc]</div>` came out as just the shortcode output, without the `<div>`. It now stays
`<div>[sc output]</div>`; the same goes for `<li>[sc]</li>` and `<td>[sc]</td>`. Content that
relied on the wrapping `<div>` being removed needs the shortcode moved out of it.

### Fixed

- **`shortcode_close_parent` closes the shortcode's own wrapping element** (#8). It closed the first
element it could find earlier on the same line instead, so `<h3>Address</h3><p>[sc]</p>` came out
as `<p></h3>[sc]<h3></p>`, which browsers repair into a stray empty `<h3>` with the `<p>` left open.
Also wrong before: an outer `<div>` was closed instead of the `<p>` inside it, a `<hr>` or a tag
inside an HTML comment could be taken as the parent, a second block shortcode in the same
paragraph was left inside it, a shortcode outside any element got a stray empty `<p>`, and
`[sc_block_other]` was handled as `[sc_block]`. The content is now walked tag by tag. When the
shortcode sits inside inline elements (`<strong>`, `<a>`), those are closed too, up to the block
element holding them, and reopened after it with their attributes.
**Multi-line content:** 5.1.0 only looked within one line, so a paragraph or heading on a line of
its own (`<p>\n[sc]\n</p>`) was left alone; it is now closed as well. Containers are not, on any
number of lines (see Changed above).
The walk also covers what the 5.1.0 regex got right or did not need: comma-separated shortcode
attributes (`[sc,id=1]`), custom elements with a hyphen in their name (`<my-el>`, read whole and
treated as inline), reopened inline elements without their `id` (or a link's `name`), so an
anchor is not repeated, and a `>` inside a quoted attribute value.
**Limit:** a block shortcode inside more than 10 nested inline elements, or inside inline
elements whose opening tags add up to more than 8 KB, is left where it is, untouched. Closing
and reopening every level for every shortcode made the output grow with nesting depth (or tag
length) times the number of shortcodes. With the limits, the markup reopened per shortcode is
bounded (10 elements, 8 KB), so the time and the output size grow linearly with the content.

## 5.1.0 (2026-09-25)

**One line for Silverstripe 5 and 6.** `main` now declares `silverstripe/framework ^5 || ^6` on PHP
Expand Down
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,18 @@ In this module, `$shortcodable_is_block` and `$disable_wrapper` have been replac

If you set `$shortcode_close_parent` to true, the parent node will be closed before your shortcode output and reopened after. <br>
Eg `<p>Some [shortcode] content</p>` would become `<p>Some </p>[shortcode]<p> content</p>`;
If the shortcode sits inside inline elements (eg `<p><strong>Some [shortcode]</strong></p>`), those are closed
as well, up to the block element holding them, and reopened after the shortcode. A bare element (no attributes)
that would be left empty on either side is dropped instead.

Only elements that cannot hold block content are closed: `<p>`, `<h1>`-`<h6>`, `<pre>` and `<summary>` (plus
inline elements). Containers that can already hold block content, such as `<div>`, `<li>`, `<td>`, `<dt>`, `<dd>`,
`<address>`, `<blockquote>` and `<section>`, are left whole: `<li>[shortcode]</li>` stays a list item with the shortcode
output inside it. Inline elements inside such a container are still closed and reopened around the shortcode.
A shortcode nested inside more than 10 inline elements, or inside inline elements whose opening tags add up to more
than 8 KB, is left untouched (a guard against pathological markup).
Up to 5.1.0 a container on the same line was closed too, so `<div>[shortcode]</div>` lost its `<div>`; since 5.2.0
it is kept.


## Shortcode placeholder images
Expand Down
Loading
Loading