Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix nested shortcode bugs #261

Merged
merged 6 commits into from
Aug 25, 2023
Merged
Changes from all commits
Commits
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
46 changes: 35 additions & 11 deletions syntaxhighlighter.php
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,24 @@ function output_shortcodes_for_tinymce() {
}


/**
* Returns all shortcodes not handled by SyntaxHighlighter unchanged, so they
* can be processed by their original handlers after SyntaxHighlighter has
* run.
*
* @param mixed $output The shortcode's returned value (false by default).
* @param string $tag The name of the shortcode.
* @param array|null $attr The shortcode attributes.
* @param array $m Regular expression match array.
* @return string|false Return the matched shortcode as-is for all shortcodes not handled by SyntaxHighlighter, returns $output otherwise.
*/
function pre_do_shortcode_shortcode_hack_skip_others( $output, $tag, $attr, $m ) {
if ( ! in_array( $tag, $this->shortcodes, true ) ) {
return $m[0];
}
return $output;
}

/**
* Process only this plugin's shortcodes.
*
Expand All @@ -628,7 +646,11 @@ function output_shortcodes_for_tinymce() {
*
* First we need to clear out all existing shortcodes, then register
* just this plugin's ones, process them, and then restore the original
* list of shortcodes.
* list of shortcodes. Additionally, we have to add another hack to other
* shortcodes, such as [gallery], to return the entire shortcode string as
* it appears in the original content to allow SyntaxHighlighter's shortcode
* strings (e.g., [c]) be used within other shortcodes without interference
* from SyntaxHighlighter.
*
* To make matters more complicated, if someone has done [[code]foo[/code]]
* in order to display the shortcode (not render it), then do_shortcode()
Expand All @@ -639,10 +661,6 @@ function output_shortcodes_for_tinymce() {
* even more brackets escaped shortcodes in order to result in
* the shortcodes actually being displayed instead rendered.
*
* We only need to do this for this plugin's shortcodes however
* as all other shortcodes such as [[gallery]] will be untouched
* by this pass of do_shortcode.
*
* Phew!
*
* @param string $content The post content.
Expand All @@ -659,16 +677,22 @@ function shortcode_hack( $content, $callback, $ignore_html = true ) {
return $content;
}

// Backup current registered shortcodes and clear them all out
$orig_shortcode_tags = $shortcode_tags;
// Backup current registered shortcodes and clear them all out (we do not backup our own, because we will add and parse them below)
$orig_shortcode_tags = array_diff_key( $shortcode_tags, array_flip( $this->shortcodes ) );
remove_all_shortcodes();

// Register all of this plugin's shortcodes
foreach ( $this->shortcodes as $shortcode ) {
add_shortcode( $shortcode, $callback );
}

$regex = '/' . get_shortcode_regex( $this->shortcodes ) . '/';
// Register all other shortcodes, ensuring their content remains unchanged using yet another hack.
foreach ( $orig_shortcode_tags as $shortcode_tagname => $shortcode ) {
add_shortcode( $shortcode_tagname, '__return_empty_string' );
}
add_filter( 'pre_do_shortcode_tag', array( $this, 'pre_do_shortcode_shortcode_hack_skip_others' ), 10, 4 );

$regex = '/' . get_shortcode_regex() . '/';

// Parse the shortcodes (only this plugins's are registered)
if ( $ignore_html ) {
Expand All @@ -692,8 +716,9 @@ function shortcode_hack( $content, $callback, $ignore_html = true ) {
);
}

// Put the original shortcodes back
// Put the original shortcodes back, and remove the hacky pre_do_shortcode_tag filter
$shortcode_tags = $orig_shortcode_tags;
remove_filter('pre_do_shortcode_tag', array($this, 'pre_do_shortcode_shortcode_hack_skip_others'), 10);

return $content;
}
Expand Down Expand Up @@ -749,7 +774,6 @@ function shortcode_hack_extra_escape_escaped_shortcodes_and_parse( $match ) {
return do_shortcode_tag( $match );
}


// The main filter for the post contents. The regular shortcode filter can't be used as it's post-wpautop().
function parse_shortcodes( $content ) {
return $this->shortcode_hack( $content, array( $this, 'shortcode_callback' ) );
Expand Down Expand Up @@ -1377,7 +1401,7 @@ function shortcode_callback( $atts, $code = '', $tag = false ) {
$code = ( false === strpos( $code, '<' ) && false === strpos( $code, '>' ) && 2 == $this->get_code_format( $post ) ) ? strip_tags( $code ) : htmlspecialchars( $code );

// Escape shortcodes
$code = preg_replace( '/\[/', '&#91;', $code );
$code = preg_replace( '/\[/', '&#x5B;', $code );
gogdzl marked this conversation as resolved.
Show resolved Hide resolved

$params[] = 'notranslate'; // For Google, see http://otto42.com/9k

Expand Down