Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8bd76a8
adds html escaping functionality, first pass
roborourke May 7, 2015
89de6dc
Merge pull request #1 from sanchothefat/html-in-attributes
roborourke May 7, 2015
0f62cc0
fix phpcs warnings
roborourke May 7, 2015
c7aada1
Merge branch 'master' into html-in-attributes
mattheu Oct 5, 2015
abaa232
Handle escaped data
mattheu Oct 5, 2015
08a75c7
Store escape logic on attribute model
mattheu Oct 5, 2015
19d6de2
Update dev file to handle new encoded attributes
mattheu Oct 5, 2015
da1c6b6
Merge branch 'master' of github.com:fusioneng/Shortcake into html-in-…
mattheu Oct 5, 2015
ce13acd
recompile
mattheu Oct 5, 2015
d8cd197
encode/decode in format and parse methods
mattheu Oct 6, 2015
903adb1
Tests for encoded attributes
mattheu Oct 6, 2015
27b0f96
Use encoded not escaped as property
mattheu Oct 6, 2015
3142e50
don't use closure for filter callback
mattheu Oct 6, 2015
1928826
update docs and simplify code
mattheu Oct 6, 2015
2c7f809
recompile JS
mattheu Oct 6, 2015
89f76bb
don't set default to true
mattheu Oct 6, 2015
1a98c85
Don't set a default for encoded from shortcodeUIFieldData
mattheu Oct 6, 2015
e416daa
docs
mattheu Oct 6, 2015
75d42d7
escape all the things
mattheu Oct 6, 2015
111cacd
fix typo
mattheu Oct 6, 2015
09bd2b9
PHP test attribute decoding
mattheu Oct 6, 2015
095963e
fix error if shortcode_atts called incorrectly
mattheu Oct 6, 2015
6d1b861
fix test
mattheu Oct 6, 2015
2906c29
Merge branch 'master' into html-in-attributes
danielbachhuber Oct 6, 2015
586c55f
Rename 'encoded' to 'encode'
mattheu Oct 7, 2015
fb975d7
Merge branch 'html-in-attributes' of github.com:fusioneng/Shortcake i…
mattheu Oct 7, 2015
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
92 changes: 48 additions & 44 deletions dev.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,64 +61,68 @@ function shortcode_ui_dev_advanced_example() {
*/
shortcode_ui_register_for_shortcode(
'shortcake_dev', array(
'label' => 'Shortcake Dev', // Display label. String. Required.
'listItemImage' => 'dashicons-editor-quote', // Icon/attachment for shortcode. Optional. src or dashicons-$icon. Defaults to carrot.
'inner_content' => array(
'label' => 'Quote',
),
'post_type' => array( 'post' ), //Post type support
// Available shortcode attributes and default values. Required. Array.
// Attribute model expects 'attr', 'type' and 'label'
// Supported field types: text, checkbox, textarea, radio, select, email, url, number, and date.
'attrs' => array(
array(
'label' => __( 'Attachment', 'your-text-domain' ), // Field label
'attr' => 'attachment', // Field type
'type' => 'attachment',
'libraryType' => array( 'image' ), // Media type to insert
'addButton' => __( 'Select Image', 'your-text-domain' ), // Button text that opens Media Library
'frameTitle' => __( 'Select Image', 'your-text-domain ' ), // Media Library frame title
),
array(
'label' => __( 'Citation Source', 'your-text-domain' ),
'attr' => 'source',
'type' => 'text',
'meta' => array( // Holds custom field attributes.
'placeholder' => 'Test placeholder',
'data-test' => 1, // Custom data attribute
),
),
array(
'label' => 'Select Page',
'attr' => 'page',
'type' => 'post_select',
'query' => array( 'post_type' => 'page' ),
'multiple' => true,
),
),
'label' => 'Shortcake Dev', // Display label. String. Required.
'listItemImage' => 'dashicons-editor-quote', // Icon/attachment for shortcode. Optional. src or dashicons-$icon. Defaults to carrot.
'inner_content' => array(
'label' => 'Quote',
),
'post_type' => array( 'post' ), //Post type support
// Available shortcode attributes and default values. Required. Array.
// Attribute model expects 'attr', 'type' and 'label'
// Supported field types: text, checkbox, textarea, radio, select, email, url, number, and date.
'attrs' => array(
array(
'label' => esc_html__( 'Attachment', 'your-text-domain' ), // Field label
'attr' => 'attachment', // Field type
'type' => 'attachment',
'libraryType' => array( 'image' ), // Media type to insert
'addButton' => esc_html__( 'Select Image', 'your-text-domain' ), // Button text that opens Media Library
'frameTitle' => esc_html__( 'Select Image', 'your-text-domain ' ), // Media Library frame title
),
array(
'label' => esc_html__( 'Citation Source', 'your-text-domain' ),
'attr' => 'source',
'type' => 'text',
'encode' => true,
'meta' => array( // Holds custom field attributes.
'placeholder' => 'Test placeholder',
'data-test' => 1, // Custom data attribute
),
),
array(
'label' => 'Select Page',
'attr' => 'page',
'type' => 'post_select',
'query' => array( 'post_type' => 'page' ),
'multiple' => true,
),
),
)
);
}

function shortcode_ui_dev_shortcode( $attr, $content = '' ) {
function shortcode_ui_dev_shortcode( $attr, $content = '', $shortcode_tag ) {

//Parse the attribute of the shortcode
$attr = wp_parse_args( $attr, array(
'source' => '',
'attachment' => 0
) );
$attr = shortcode_atts( array(
'source' => '',
'attachment' => 0,
'source' => null,
), $attr, $shortcode_tag );

ob_start();

?>

<section class="pullquote" style="padding: 20px; background: rgba(0,0,0,0.1);">
<p style="margin:0; padding: 0;">
<p style="margin:0; padding: 0;">
<b>Content:</b> <?php echo wpautop( wp_kses_post( $content ) ); ?></br>
<b>Source:</b> <?php echo esc_html( $attr[ 'source' ] ); ?></br>
<b>Source:</b> <?php echo wp_kses_post( $attr[ 'source' ] ); ?></br>
<b>Image:</b> <?php echo wp_kses_post( wp_get_attachment_image( $attr[ 'attachment' ], array( 50, 50 ) ) ); ?></br>
</p>
</p>
</section>

<?php

return ob_get_clean();

}
39 changes: 39 additions & 0 deletions inc/class-shortcode-ui.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ public function register_shortcode_ui( $shortcode_tag, $args = array() ) {
$args['shortcode_tag'] = $shortcode_tag;
$this->shortcodes[ $shortcode_tag ] = $args;

// Setup filter to handle decoding encoded attributes.
add_filter( "shortcode_atts_{$shortcode_tag}", array( $this, 'filter_shortcode_atts_decode_encoded' ), 5, 3 );

}

/**
Expand Down Expand Up @@ -384,4 +387,40 @@ public function handle_ajax_bulk_do_shortcode() {
}

}

/**
* Decode any encoded attributes.
*
* @param array $out The output array of shortcode attributes.
* @param array $pairs The supported attributes and their defaults.
* @param array $atts The user defined shortcode attributes.
* @return array $out The output array of shortcode attributes.
*/
public function filter_shortcode_atts_decode_encoded( $out, $pairs, $atts ) {

// Get current shortcode tag from the current filter
// by stripping `shortcode_atts_` from start of string.
$shortcode_tag = substr( current_filter(), 15 );

if ( ! isset( $this->shortcodes[ $shortcode_tag ] ) ) {
return $out;
}

$fields = Shortcode_UI_Fields::get_instance()->get_fields();
$args = $this->shortcodes[ $shortcode_tag ];

foreach ( $args['attrs'] as $attr ) {

$default = isset( $fields[ $attr['type'] ]['encode'] ) ? $fields[ $attr['type'] ]['encode'] : false;
$encoded = isset( $attr['encode'] ) ? $attr['encode'] : $default;

if ( $encoded && isset( $out[ $attr['attr'] ] ) ) {
$out[ $attr['attr'] ] = rawurldecode( $out[ $attr['attr'] ] );
}
}

return $out;

}

}
1 change: 1 addition & 0 deletions inc/fields/class-shortcode-ui-fields.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Shortcode_UI_Fields {
private $field_defaults = array(
'template' => 'shortcode-ui-field-text',
'view' => 'editAttributeField',
'encode' => false,
);

/**
Expand Down
91 changes: 77 additions & 14 deletions js-tests/build/specs.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ describe( "Shortcode Attribute Model", function() {
type: 'text',
value: 'test value',
description: 'test description',
encode: false,
meta: {
placeholder: 'test placeholder'
},
Expand Down Expand Up @@ -73,7 +74,7 @@ describe( "Shortcode Model", function() {
label: 'Attribute',
type: 'text',
value: 'test value',
placeholder: 'test placeholder',
placeholder: 'test placeholder'
}
],
inner_content: {
Expand Down Expand Up @@ -126,8 +127,30 @@ describe( "Shortcode Model", function() {

});

});
it( 'Format shortcode with encoded attributes.', function() {

var shortcode_encoded_attribute, formatted, expected;

shortcode_encoded_attribute = new Shortcode({
label: 'Test Label',
shortcode_tag: 'test_shortcode_encoded',
attrs: [
{
attr: 'attr',
type: 'text',
value: '<b class="foo">bar</b>',
encode: true,
},
],
});

formatted = shortcode_encoded_attribute.formatShortcode();
expected = '[test_shortcode_encoded attr="%3Cb%20class%3D%22foo%22%3Ebar%3C%2Fb%3E"]';
expect( formatted ).toEqual( expected );

});

});

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"../../js/src/collections/shortcode-attributes":7,"../../js/src/models/inner-content":9,"../../js/src/models/shortcode":11,"../../js/src/models/shortcode-attribute":10}],4:[function(require,module,exports){
Expand Down Expand Up @@ -224,6 +247,18 @@ describe( "MCE View Constructor", function() {
},
} ) );

sui.shortcodes.push( new Shortcode( {
label: 'Test Label',
shortcode_tag: 'test_shortcode_encoded',
attrs: [
{
attr: 'attr',
label: 'Attribute',
encode: true,
}
],
} ) );

it ( 'test get shortcode model', function() {

var constructor = jQuery.extend( true, {}, MceViewConstructor );
Expand Down Expand Up @@ -349,6 +384,12 @@ describe( "MCE View Constructor", function() {
expect( shortcode.get( 'attrs' ).findWhere( { attr: 'test-attr' }).get('value') ).toEqual( 'test' );
});

it( 'parses shortcode with encoded attribute', function() {
var shortcode = MceViewConstructor.parseShortcodeString( '[test_shortcode_encoded attr="%3Cb%20class%3D%22foo%22%3Ebar%3C%2Fb%3E"]');
expect( shortcode instanceof Shortcode ).toEqual( true );
expect( shortcode.get( 'attrs' ).findWhere({ attr: 'attr' }).get('value') ).toEqual( '<b class="foo">bar</b>' );
});

} );

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
Expand Down Expand Up @@ -428,16 +469,19 @@ module.exports = InnerContent;
var Backbone = (typeof window !== "undefined" ? window['Backbone'] : typeof global !== "undefined" ? global['Backbone'] : null);

var ShortcodeAttribute = Backbone.Model.extend({

defaults: {
attr: '',
label: '',
type: '',
value: '',
description: '',
encode: false,
meta: {
placeholder: '',
},
},

});

module.exports = ShortcodeAttribute;
Expand Down Expand Up @@ -520,6 +564,11 @@ Shortcode = Backbone.Model.extend({
return;
}

// Encode textareas incase HTML
if ( attr.get( 'encode' ) ) {
attr.set( 'value', encodeURIComponent( decodeURIComponent( attr.get( 'value' ) ) ), { silent: true } );
}

attrs.push( attr.get( 'attr' ) + '="' + attr.get( 'value' ) + '"' );

} );
Expand Down Expand Up @@ -684,16 +733,23 @@ var shortcodeViewConstructor = {

shortcodeModel = shortcodeModel.clone();

shortcodeModel.get('attrs').each(
function( attr ) {
if ( attr.get('attr') in options.attrs.named ) {
attr.set(
'value',
options.attrs.named[ attr.get('attr') ]
);
}
shortcodeModel.get('attrs').each( function( attr ) {

// Verify value exists for attribute.
if ( ! ( attr.get('attr') in options.attrs.named ) ) {
return;
}

var value = options.attrs.named[ attr.get('attr') ];

// Maybe decode value.
if ( attr.get('encode') ) {
value = decodeURIComponent( value );
}
);

attr.set( 'value', value );

} );

if ( 'content' in options ) {
var innerContent = shortcodeModel.get('inner_content');
Expand Down Expand Up @@ -815,20 +871,27 @@ var shortcodeViewConstructor = {

var attributes_backup = {};
var attributes = wp.shortcode.attrs( matches[3] );

for ( var key in attributes.named ) {

if ( ! attributes.named.hasOwnProperty( key ) ) {
continue;
}

value = attributes.named[ key ];
attr = currentShortcode.get( 'attrs' ).findWhere({
attr : key
});
attr = currentShortcode.get( 'attrs' ).findWhere({ attr: key });

if ( attr && attr.get('encode') ) {
value = decodeURIComponent( value );
}

if ( attr ) {
attr.set( 'value', value );
} else {
attributes_backup[ key ] = value;
}
}

currentShortcode.set( 'attributes_backup', attributes_backup );

if ( matches[5] ) {
Expand Down
1 change: 1 addition & 0 deletions js-tests/src/shortcodeAttributeModelSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ describe( "Shortcode Attribute Model", function() {
type: 'text',
value: 'test value',
description: 'test description',
encode: false,
meta: {
placeholder: 'test placeholder'
},
Expand Down
26 changes: 24 additions & 2 deletions js-tests/src/shortcodeModelSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe( "Shortcode Model", function() {
label: 'Attribute',
type: 'text',
value: 'test value',
placeholder: 'test placeholder',
placeholder: 'test placeholder'
}
],
inner_content: {
Expand Down Expand Up @@ -70,5 +70,27 @@ describe( "Shortcode Model", function() {

});

});
it( 'Format shortcode with encoded attributes.', function() {

var shortcode_encoded_attribute, formatted, expected;

shortcode_encoded_attribute = new Shortcode({
label: 'Test Label',
shortcode_tag: 'test_shortcode_encoded',
attrs: [
{
attr: 'attr',
type: 'text',
value: '<b class="foo">bar</b>',
encode: true,
},
],
});

formatted = shortcode_encoded_attribute.formatShortcode();
expected = '[test_shortcode_encoded attr="%3Cb%20class%3D%22foo%22%3Ebar%3C%2Fb%3E"]';
expect( formatted ).toEqual( expected );

});

});
Loading