first commit

This commit is contained in:
Roman Pyrih
2026-03-10 09:50:10 +01:00
commit 64c4a90405
7289 changed files with 2645777 additions and 0 deletions

View File

@@ -0,0 +1,102 @@
# SVG Support
A powerful WordPress plugin that enables SVG uploads and provides advanced features for working with SVG files in WordPress.
> **⚠️ Development Repository Notice**
>
> This is the latest development version of SVG Support. Code here may be unstable during active development. For production sites, please use the official release from the [WordPress.org plugin repository](https://wordpress.org/plugins/svg-support/).
>
> The official plugin is managed via SVN as per WordPress.org standards. This GitHub repository serves as a development workspace and for issue tracking. Once changes are stable, they will be copied to the SVN repository for release.
## Description
SVG Support allows you to securely upload SVG files to your WordPress Media Library and use them like any other image, with additional features for inline rendering, styling, and animation.
### Key Features
- **SVG Upload Support**: Easily upload SVG files to your media library
- **Automatic Sanitization**: All SVG uploads are sanitized by default for security
- **Minification Options**: Reduce SVG file sizes with optional minification
- **Inline Rendering**: Render SVG code inline by adding the `"style-svg"` class
- **Role-Based Control**: Restrict SVG upload capabilities to specific user roles
- **Custom Target Class**: Define your own CSS class for targeting SVGs
- **Featured Image Support**: Special handling for SVG files as featured images
- **Advanced Mode**: Toggle advanced features for more control
## Installation
1. Install through the WordPress plugin repository or upload to your `/wp-plugins/` directory
2. Activate the plugin through the 'Plugins' menu in WordPress
3. Go to "Settings > SVG Support" to configure the plugin
## Basic Usage
Once activated, you can upload SVG files to your media library like any other image file.
### Inline SVG Rendering
To render an SVG inline (enabling CSS/JS targeting of internal elements):
```
<img class="style-svg" alt="alt-text" src="image-source.svg" />
```
Or with a custom class:
```
<img class="your-custom-class" alt="alt-text" src="image-source.svg" />
```
## Security
SVG Support takes security seriously and provides several features to ensure safe SVG handling:
- Sanitization by default (since v2.5.8)
- Role-based upload restrictions
- Optional sanitization bypass for trusted users
- Secure file handling through WordPress APIs
## Development
This is the development repository for SVG Support. The official release version is maintained on WordPress.org's SVN repository.
- [Plugin Page on WordPress.org](https://wordpress.org/plugins/svg-support/)
- [SVN Repository](https://plugins.svn.wordpress.org/svg-support/)
### Quick Test
Want to try it out? Spin up a test site instantly:
[Click here to create a test site with SVG Support pre-installed](https://tastewp.com/new?pre-installed-plugin-slug=svg-support&redirect=options-general.php%3Fpage%3Dsvg-support&ni=true)
## Contributing
Contributions are welcome! Feel free to:
- Submit bug reports or feature requests through the [issue tracker](https://github.com/your-username/svg-support/issues)
- Create pull requests for bug fixes or new features
- Help with translations through [WordPress.org's translation platform](https://translate.wordpress.org/projects/wp-plugins/svg-support)
## Support
- For general support, please use the [WordPress.org support forums](https://wordpress.org/support/plugin/svg-support/)
- For bug reports and feature requests, use the GitHub issues
## License
This plugin is licensed under the GPL v2 or later.
## Author
Created and maintained by [Benbodhi](https://benbodhi.com)
### Follow SVG Support
- [@SVGSupport on Twitter](https://twitter.com/svgsupport)
- [@benbodhi on Twitter](https://twitter.com/benbodhi)
- [@benbodhi on Warpcast](https://warpcast.com/benbodhi)
## Support the Development
If you find this plugin useful, please consider:
- [Rating it on WordPress.org](https://wordpress.org/support/plugin/svg-support/reviews/#new-post)
- [Making a donation](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z9R7JERS82EQQ)

View File

@@ -0,0 +1,240 @@
<?php
/**
* Admin init
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Add menu item to wp-admin
*/
function bodhi_svgs_admin_menu() {
$bodhi_svgs_options_page = add_options_page(
__('SVG Support Settings and Usage', 'svg-support'),
__('SVG Support', 'svg-support'),
'manage_options',
'svg-support',
'bodhi_svg_support_settings_page'
);
// load the help menu on the SVG Support settings page
add_action( 'load-' . $bodhi_svgs_options_page, 'bodhi_svgs_help_tab' );
require( BODHI_SVGS_PLUGIN_PATH . 'admin/svgs-settings-page-help.php' );
}
add_action( 'admin_menu', 'bodhi_svgs_admin_menu' );
/**
* Create settings page
*/
function bodhi_svg_support_settings_page() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( esc_html__('You can\'t play with this.', 'svg-support') );
}
$bodhi_svgs_options = get_option( 'bodhi_svgs_settings' );
require( BODHI_SVGS_PLUGIN_PATH . 'admin/svgs-settings-page.php' );
}
/**
* Sanitize and save settings
*/
function bodhi_svgs_settings_sanitize($input) {
// Process all settings
$output = $input;
// Sanitize css_target
if (isset($output['css_target'])) {
$output['css_target'] = esc_attr( sanitize_text_field( $output['css_target'] ) );
}
// Handle sanitize_svg_front_end setting
if (!isset($output['sanitize_svg_front_end']) || $output['sanitize_svg_front_end'] !== 'on') {
$output['sanitize_svg_front_end'] = false;
}
// Handle sanitize_on_upload_roles setting
if (!isset($output['sanitize_on_upload_roles'])) {
$output['sanitize_on_upload_roles'] = array("none");
} else {
$output['sanitize_on_upload_roles'] = (array)$output['sanitize_on_upload_roles'];
}
// Handle restrict setting
if (!isset($output['restrict'])) {
$output['restrict'] = array("none");
} else {
$output['restrict'] = (array)$output['restrict'];
}
return $output;
}
/**
* Register settings in the database
*/
function bodhi_svgs_register_settings() {
$args = array(
'sanitize_callback' => 'bodhi_svgs_settings_sanitize'
);
register_setting( 'bodhi_svgs_settings_group', 'bodhi_svgs_settings', $args );
}
add_action( 'admin_init', 'bodhi_svgs_register_settings' );
/**
* Remove old sanitize setting
*/
function bodhi_svgs_remove_old_sanitize_setting() {
// Fetch current settings
$bodhi_svgs_options = get_option('bodhi_svgs_settings');
// Remove the old 'sanitize_svg' setting if it exists
if (isset($bodhi_svgs_options['sanitize_svg'])) {
unset($bodhi_svgs_options['sanitize_svg']);
update_option('bodhi_svgs_settings', $bodhi_svgs_options);
}
}
add_action('admin_init', 'bodhi_svgs_remove_old_sanitize_setting');
/**
* Advanced Mode Check
* Creates a usable function for conditionals around the plugin
*/
function bodhi_svgs_advanced_mode() {
global $bodhi_svgs_options;
if ( ! empty( $bodhi_svgs_options['advanced_mode'] ) ) {
return true;
} else {
return false;
}
}
add_action( 'admin_init', 'bodhi_svgs_advanced_mode' );
/**
* Screen check function
* Checks if current page is SVG Support settings page
*/
function bodhi_svgs_specific_pages_settings() {
// check current page
$screen = get_current_screen();
// check if we're on SVG Support settings page
if ( is_object( $screen ) && $screen->id == 'settings_page_svg-support' ) {
return true;
} else {
return false;
}
}
/**
* Screen check function
* Checks if the current page is the Media Library page
*/
function bodhi_svgs_specific_pages_media_library() {
// check current page
$screen = get_current_screen();
// check if we're on Media Library page
if ( is_object( $screen ) && $screen->id == 'upload' ) {
return true;
} else {
return false;
}
}
/**
* Screen check function
* Check if the current page is a post edit page
*/
function bodhi_svgs_is_edit_page( $new_edit = null ) {
global $pagenow;
if ( ! is_admin() ) return false;
if ( $new_edit == 'edit' ) {
return in_array( $pagenow, array( 'post.php', ) );
} elseif ( $new_edit == "new" ) { //check for new post page
return in_array( $pagenow, array( 'post-new.php' ) );
} else { //check for either new or edit
return in_array( $pagenow, array( 'post.php', 'post-new.php' ) );
}
}
/**
* Add rating text to footer on settings page
*/
function bodhi_svgs_admin_footer_text( $default ) {
if ( bodhi_svgs_specific_pages_settings() || bodhi_svgs_specific_pages_media_library() ) {
$strong_open = '<strong>';
$strong_close = '</strong>';
$link_open = '<a href="https://wordpress.org/support/view/plugin-reviews/svg-support?filter=5#postform" target="_blank" class="svgs-rating-link">';
$link_close = '</a>';
// translators: %1$s: Opening strong tag, %2$s: Closing strong tag, %3$s: Opening anchor tag for rating link, %4$s: Closing anchor tag
$text = esc_html__( 'If you like %1$sSVG Support%2$s please leave a %3$s★★★★★%4$s rating. A huge thanks in advance!', 'svg-support' );
echo wp_kses(
sprintf(
$text,
$strong_open,
$strong_close,
$link_open,
$link_close
),
array(
'strong' => array(),
'a' => array(
'href' => array(),
'target' => array(),
'class' => array()
)
)
);
} else {
return $default;
}
}
add_filter( 'admin_footer_text', 'bodhi_svgs_admin_footer_text' );

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,45 @@
<?php
/**
* Plugin action and row meta links
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Add plugin_action_links
*/
function bodhi_svgs_plugin_action_links( $links ) {
return array_merge(
array(
'<a href="' . admin_url( 'options-general.php?page=svg-support' ) . '" title="' . __( 'SVG Support Settings', 'svg-support' ) . '">' . __( 'Settings', 'svg-support') . '</a>'
), $links
);
return $links;
}
add_filter( 'plugin_action_links_' . plugin_basename(BODHI_SVGS_PLUGIN_FILE), 'bodhi_svgs_plugin_action_links' );
/**
* Add plugin_row_meta links
*/
function bodhi_svgs_plugin_meta_links( $links, $file ) {
if ( $file == plugin_basename(BODHI_SVGS_PLUGIN_FILE) ) {
return array_merge(
$links,
array(
'<a target="_blank" href="https://wordpress.org/support/plugin/svg-support">' . __( 'Get Support', 'svg-support') . '</a>',
'<a target="_blank" href="https://wordpress.org/support/plugin/svg-support/reviews/">' . __( 'Leave a Review', 'svg-support' ) . '</a>',
'<a target="_blank" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z9R7JERS82EQQ&source=url">' . __( 'Donate to author', 'svg-support') . '</a>'
)
);
}
return $links;
}
add_filter( 'plugin_row_meta', 'bodhi_svgs_plugin_meta_links', 10, 2 );

View File

@@ -0,0 +1,160 @@
<?php
/**
* Add SVG Support help tab to the top of the settings page
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
function bodhi_svgs_help_tab () {
$screen = get_current_screen();
/**
* Overview Tab
*/
// overview tab content
$bodhi_svgs_help_tab_overview = '<h3>' . __( 'Overview', 'svg-support' ) . '</h3>';
$bodhi_svgs_help_tab_overview .= '<p>' . __( 'At it\'s core, SVG Support allows you to upload SVG files and use them as you would any regular image with the added benefit of being scalable and looking great on any screen size, no matter what size it\'s displayed. Additionally, SVG file sizes are (more often than not) much smaller than conventional image formats.', 'svg-support' ) . '</p><p>' . __( 'Even this most basic of usage is very powerful for modern websites, however, there\'s lots of cool stuff you can do with SVG files!', 'svg-support' ) . '</p><p>' . __( 'SVG Support features an "Advanced Mode" which toggles extra features, allowing you to take more control of how your SVG files are used. By rendering SVG files inline, it opens up a huge number of possibilities including animations, embedded links within the SVG, odd shaped link areas, custom CSS targeting elements within the SVG and whole lot more!', 'svg-support' ) . '</p><p>' . __( 'So let\'s get into some more details! Simply click the tabs to the left to get more of an understanding of how powerful SVG Support is.', 'svg-support' ) . '</p>';
// register overview tab
$screen->add_help_tab( array(
'id' => 'bodhi_svgs_help_tab-overview',
'title' => __( 'Overview', 'svg-support' ),
'content' => $bodhi_svgs_help_tab_overview
));
/**
* The Settings Tab
*/
// the settings tab content
$bodhi_svgs_help_tab_the_settings = '<h3>' . __( 'The Settings', 'svg-support' ) . '</h3>';
$bodhi_svgs_help_tab_the_settings .= '<p><strong>' . __( 'Restrict To Administrators:', 'svg-support' ) . '</strong><br>' . __( 'SVG files are actually XML code, so allowing regular users to upload them can pose serious security risks. Please leave this checked unless you really know what you\'re doing.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_the_settings .= '<p><strong>' . __( 'Enable Advanced Mode:', 'svg-support' ) . '</strong><br>' . __( 'When using SVG files like regular images just isn\'t enough ;)', 'svg-support' ) . '<br>' . __( 'Enabling "Advanced Mode" displays options to give you more control over how you use SVG files on your site. It also includes extra JS on the front end, so leave this disabled unless you\'re actually using any of the advanced features.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_the_settings .= '<p><strong>' . __( 'Output JS in Footer:', 'svg-support' ) . '</strong><br>' . __( 'This setting allows you to choose whether the SVG Support JS file is enqueued in the header or the footer of the site. Usually you would enqueue in the footer unless you need it to be loaded sooner for some reason.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_the_settings .= '<p><strong>' . __( 'Use Expanded JS:', 'svg-support' ) . '</strong><br>' . __( 'This setting gives you the choice of JS file that is enqueued, the full expanded version or the minified version. You would usually enqueue the minified version, but if you want to bundle the JS file using a caching or minification plugin or similar, then you might want to enqueue the expanded, non-minified version.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_the_settings .= '<p><strong>' . __( 'CSS Class To Target:', 'svg-support' ) . '</strong><br>' . __( 'This allows you to set your own custom class that you will use in your SVG source IMG tags that you would like rendered inline. For example, it might be easier for you to remember to add the class "inline-svg" or something, in which case you would use your desired class name in this field to be used across your site.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_the_settings .= '<p><strong>' . __( 'Automatically Insert Class:', 'svg-support' ) . '</strong><br>' . __( 'When this is checked, you won\'t have to add the class to your SVG files during the embed process in the editor. When you pick your SVG, it will be placed in the editor with just the SVG Support class and others stripped. It does not change existing code, it\'s only a helper to allow you to quickly embed your SVG files and have them render inline without having to fiddle with the classes.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_the_settings .= '<p><strong>' . __( 'Force Inline SVG:', 'svg-support' ) . '</strong><br>' . __( 'This feature is to force all SVG files that are found in your site to be rendered inline. This can help if you aren\'t able to set a custom class on your IMG tags for some reason, usually when used in theme options or page builder elements.', 'svg-support' ) . '</p>';
// register the settings tab
$screen->add_help_tab( array(
'id' => 'bodhi_svgs_help_tab-the_settings',
'title' => __( 'The Settings', 'svg-support' ),
'content' => $bodhi_svgs_help_tab_the_settings
));
/**
* Standard Usage Tab
*/
// standard usage tab content
$bodhi_svgs_help_tab_usage_standard = '<h3>' . __( 'Standard Usage', 'svg-support' ) . '</h3>';
$bodhi_svgs_help_tab_usage_standard .= '<p>' . __( 'You can simply upload SVG files to your media library like any other image.<br>Make sure to select "Restrict to Administrators" if you only want to allow admins to upload SVG files.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_usage_standard .= '<p>' . __( 'If you want to enable sanitization or minification of uploaded SVG files, please enable advanced settings and then enable sanitization and/or minification.', 'svg-support' ) . '</p>';
// register standard usage tab
$screen->add_help_tab( array(
'id' => 'bodhi_svgs_help_tab_usage-standard',
'title' => __( 'Standard Usage', 'svg-support' ),
'content' => $bodhi_svgs_help_tab_usage_standard
));
/**
* Inline SVG Tab
*/
// inline SVG tab content
$bodhi_svgs_help_tab_inlining_svg = '<h3>' . __( 'Render SVG Inline', 'svg-support' ) . '</h3>';
$bodhi_svgs_help_tab_inlining_svg .= '<p>' . __( 'You can embed your SVG image like any standard image with the addition of adding the class <code>style-svg</code> (or your custom class) to any IMG tags that you want this plugin to swap out with your actual SVG code.', 'svg-support' ) . '<br>' . __( 'For example:', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_inlining_svg .= '<pre><code>&lt;img class="style-svg" alt="alt-text" src="image-source.svg" /&gt;</code></pre>' . __( 'or', 'svg-support' ) . '<pre><code>&lt;img class="your-custom-class" alt="alt-text" src="image-source.svg" /&gt;</code></pre>';
$bodhi_svgs_help_tab_inlining_svg .= '<p>' . __( 'The whole IMG tag element will now be dynamically replaced by the actual code of your SVG, making the inner content targetable.', 'svg-support' ) . '<br>' . __( 'This allows you to target elements within your SVG using CSS.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_inlining_svg .= '<p><em>' . __( 'Please Note:', 'svg-support' ) . '</em><br><em>- ' . __( 'You will likely need to set your own height and width in your CSS for SVG files to display correctly.', 'svg-support' ) . '</em><br><em>- ' . __( 'Your uploaded image needs to be an SVG file for this plugin to replace the img tag with the inline SVG code. It will not create SVG files for you.', 'svg-support' ) . '</em><br><em>- ' . __( 'You can set this target class on any element and the script will traverse all children of that target element looking for IMG tags with SVG in the src to replace.', 'svg-support' ) . '</em></p>';
// register inline SVG tab
$screen->add_help_tab( array(
'id' => 'bodhi_svgs_help_tab-inlining_svg',
'title' => __( 'Render SVG Inline', 'svg-support' ),
'content' => $bodhi_svgs_help_tab_inlining_svg
));
/**
* Featured Images Tab
*/
// featured images tab content
$bodhi_svgs_help_tab_featured_images = '<h3>' . __( 'Featured Images', 'svg-support' ) . '</h3>';
$bodhi_svgs_help_tab_featured_images .= '<p>' . __( 'You can use SVG files as featured images just like any other image format, with the addition of being able to render your featured SVG inline on a per-post basis.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_featured_images .= '<p>' . __( 'To render your featured SVG inline:', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_featured_images .= '<ol><li>' . __( 'Make sure "Advanced Mode" is enabled.', 'svg-support' ) . '</li><li>' . __( 'Add your featured SVG like you would any regular featured image format.', 'svg-support' ) . '</li><li>' . __( 'Publish, Save Draft, or Update the post.', 'svg-support' ) . '</li><li>' . __( 'Once the screen reloads, click the new checkbox below the featured image to render your SVG inline.', 'svg-support' ) . '</li><li>' . __( 'Publish, Save Draft, or Update the post a final time to render the SVG inline.', 'svg-support' ) . '</li></ol>';
// register featured images tab
$screen->add_help_tab( array(
'id' => 'bodhi_svgs_help_tab-featured_images',
'title' => __( 'Featured Images', 'svg-support' ),
'content' => $bodhi_svgs_help_tab_featured_images
));
/**
* Animation Tab
*/
$bodhi_svgs_help_tab_animation = '<h3>' . __( 'Animation', 'svg-support' ) . '</h3>';
$bodhi_svgs_help_tab_animation .= '<p>' . __( 'So you want to animate your SVG?', 'svg-support' ) . '<br>' . __( 'There\'s a number of ways you can animate an SVG. You could use CSS or JS to target elements within your SVG or even embed the animations in the file itself. Whichever way you choose, there is always a little bit of preparation required before uploading your SVG to your media library.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_animation .= '<p><strong>' . __( 'First, let\'s talk about using CSS or JS to target elements within your SVG.', 'svg-support' ) . '</strong><br>' . __( 'Before you upload your SVG, you\'re going to need some classes to target inside your SVG. To do this, open your SVG file in the code editor of choice (I use Sublime Text). You will see each element within your SVG file written in XML code. Each little part of your SVG has it\'s own bit of code, so it\'s up to you which ones you want to target. It\'s in here that you\'ll place your new classes on each element you want to target.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_animation .= '<p>' . __( 'Then there\'s the option of animating the SVG file itself. There is a number of online tools to do this, or you can use the software of your choice. Once your SVG is animated and ready to go, you then upload it like any other image to your WordPress media library. When you embed it on a page/post, you will need to make sure to add the class to the IMG tag so SVG Support can render it inline. This will ensure your animations are displayed.', 'svg-support' ) . '</p>';
// register animation tab
$screen->add_help_tab( array(
'id' => 'bodhi_svgs_help_tab-animation',
'title' => __( 'Animation', 'svg-support' ),
'content' => $bodhi_svgs_help_tab_animation
));
/**
* DONATIONS Tab
*/
// donations tab content
$bodhi_svgs_help_tab_donations = '<h3>' . __( 'Donations', 'svg-support' ) . '</h3>';
$bodhi_svgs_help_tab_donations .= '<p>' . __( 'SVG Support (this plugin) has grown to be used by over 1 million websites actively and is maintained solely by one person. I couldn\'t possibly tell you how many hours have gone into the development, maintenance and support of this plugin. If you find it useful and would like to donate to help keep it going, that would be amazing! I truly appreciate the support and how far this has come.', 'svg-support' ) . '</p>';
$bodhi_svgs_help_tab_donations .= '<p><strong>' . __( 'Donation Methods:', 'svg-support' ) . '</strong></p>';
$bodhi_svgs_help_tab_donations .= '<p><strong>' . __( 'PayPal: ', 'svg-support' ) . '</strong><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z9R7JERS82EQQ" target="_blank">Click Here</a><br/><strong>' . __( 'BTC: 1qF8r2HkTLifND7WLGfWmvxfXc9ze55DZ', 'svg-support' ) . '</strong><br/><strong>' . __( 'LTC: LUnQPJrSk6cVFmMqBMv5FAqweJbnzRUz4o', 'svg-support' ) . '</strong><br/><strong>' . __( 'ETH: 0x599695Eb51aFe2e5a0DAD60aD9c89Bc8f10B54f4', 'svg-support' ) . '</strong></p>';
$bodhi_svgs_help_tab_donations .= '<p>' . __( 'Need to buy some crypto to donate?', 'svg-support' ) . '</br>' . __( 'My Coinbase referral link will get $10 USD worth of BTC for free when you spend $100.', 'svg-support' ) . '</br>' . __( '(You don\'t need to send me that much though, anything is appreciated!)', 'svg-support' ) . '<br/><a href="https://www.coinbase.com/join/59be646cb87715012bbdcc6b" target="_blank">https://www.coinbase.com/join/59be646cb87715012bbdcc6b</a></p>';
// register featured images tab
$screen->add_help_tab( array(
'id' => 'bodhi_svgs_help_tab-donations',
'title' => __( 'DONATIONS', 'svg-support' ),
'content' => $bodhi_svgs_help_tab_donations
));
/**
* Help Tab Sidebar
*/
// add help tab sidebar
$screen->set_help_sidebar(
'<p><strong>' . __( 'For more help, visit:', 'svg-support' ) . '</strong></p>' .
'<p>' . __( '<a target="_blank" href="https://wordpress.org/support/plugin/svg-support">SVG Support Forum</a>', 'svg-support' ) . '</p>'
);
}

View File

@@ -0,0 +1,503 @@
<?php
/**
* Settings Page Markup
*/
?>
<div class="wrap">
<div id="icon-upload" class="icon32"></div>
<h2><?php esc_html_e( 'SVG Support Settings and Usage', 'svg-support' ); ?><span class="svgs-version">Version <?php echo esc_attr(BODHI_SVGS_VERSION); ?></span></h2>
<div id="poststuff">
<div class="meta-box-sortables ui-sortable">
<div class="postbox">
<h3><span><?php esc_html_e( 'Introduction', 'svg-support' ); ?></span></h3>
<div class="inside">
<p>
<?php esc_html_e( 'When using SVG images on your WordPress site, it can be hard to style elements within the SVG using CSS.', 'svg-support' ); ?>
<strong><?php esc_html_e( 'Now you can, easily!', 'svg-support' ); ?></strong>
</p>
<p>
<?php esc_html_e( 'When you enable advanced mode, this plugin not only provides SVG Support like the name says, it also allows you to easily embed your full SVG file\'s code using a simple IMG tag. By adding the class', 'svg-support' ); ?>
<code><?php esc_html_e( 'style-svg', 'svg-support' ); ?></code>
<?php esc_html_e( 'to your IMG elements, this plugin dynamically replaces any IMG elements containing the', 'svg-support' ); ?>
<code><?php esc_html_e( 'style-svg', 'svg-support' ); ?></code>
<?php esc_html_e( 'class with your complete SVG.', 'svg-support' ); ?>
</p>
<p>
<?php esc_html_e( 'The main purpose of this is to allow styling of SVG elements. Usually your styling options are restricted when using', 'svg-support' ); ?>
<code><?php esc_html_e( 'embed', 'svg-support' ); ?></code>,
<code><?php esc_html_e( 'object', 'svg-support' ); ?></code>,
<?php esc_html_e( 'or', 'svg-support' ); ?>
<code><?php esc_html_e( 'img', 'svg-support' ); ?></code>
<?php esc_html_e( 'tags alone.', 'svg-support' ); ?>
</p>
<p>
<strong><?php esc_html_e( 'For help and more information, please check the help tab (top right of your screen).', 'svg-support' ); ?></strong>
</p>
</div> <!-- .inside -->
</div> <!-- .postbox -->
</div> <!-- .meta-box-sortables .ui-sortable -->
<div class="meta-box-sortables ui-sortable">
<div class="postbox">
<h3><span><?php esc_html_e( 'Send Some Love', 'svg-support' ); ?></span></h3>
<div class="inside">
<p><?php esc_html_e( 'SVG Support has grown to be installed on 1,000,000+ active websites. That\'s insane! It\'s developed and maintained by one person alone. If you find it useful, please consider donating to help keep it going. I truly appreciate any contribution.', 'svg-support' ); ?></p>
<p><strong>
<?php esc_html_e( 'BTC: 1qF8r2HkTLifND7WLGfWmvxfXc9ze55DZ', 'svg-support' ); ?><br/>
<?php esc_html_e( 'ETH: 0x599695Eb51aFe2e5a0DAD60aD9c89Bc8f10B54f4', 'svg-support' ); ?>
</strong></p>
<p><?php esc_html_e( 'You can also', 'svg-support' ); ?> <a target="_blank" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z9R7JERS82EQQ&source=url"><?php esc_html_e( 'Donate using PayPal', 'svg-support' ); ?></a></p>
</div> <!-- .inside -->
</div> <!-- .postbox -->
</div> <!-- .meta-box-sortables .ui-sortable -->
<div id="post-body" class="metabox-holder columns-2">
<!-- main content -->
<div id="post-body-content">
<div class="meta-box-sortables ui-sortable">
<div class="postbox">
<h3><span><?php esc_html_e( 'Settings', 'svg-support' ); ?></span></h3>
<div class="inside">
<form name="bodhi_svgs_settings_form" method="post" action="options.php">
<?php settings_fields('bodhi_svgs_settings_group'); ?>
<table class="form-table svg-settings">
<tr valign="top">
<th scope="row">
<strong><?php esc_html_e( 'Restrict SVG Uploads to?', 'svg-support' ); ?></strong>
</th>
<td>
<div class="upload_allowed_roles">
<?php $allowed_roles_array = $bodhi_svgs_options['restrict']; ?>
<select style="display:none" name="bodhi_svgs_settings[restrict][]" multiple>
<?php
global $wp_roles;
$all_roles = $wp_roles->roles;
foreach ($all_roles as $role => $details) {
$user_role_slug = esc_attr($role);
$user_role_name = translate_user_role($details['name']);
$role_selected = in_array($user_role_slug, $allowed_roles_array) ? 'selected' : '';
?>
<option value="<?php echo esc_attr($user_role_slug); ?>" <?php echo esc_attr($role_selected); ?>><?php echo esc_html($user_role_name); ?></option>
<?php } ?>
</select>
</div>
<small class="description"><?php esc_html_e('Select the user roles that are allowed to upload SVG files.', 'svg-support' ); ?></small>
</td>
</tr>
<tr valign="top">
<th scope="row">
<strong><?php esc_html_e( 'Do not sanitize for these roles', 'svg-support' ); ?></strong>
</th>
<td>
<div class="sanitize_on_upload_roles">
<?php
global $wp_roles;
$all_roles = $wp_roles->roles; // Fetch all available roles
$sanitize_roles_array = $bodhi_svgs_options['sanitize_on_upload_roles'];
?>
<select name="bodhi_svgs_settings[sanitize_on_upload_roles][]" multiple>
<?php
foreach ($all_roles as $role => $details) {
$user_role_slug = esc_attr($role);
$user_role_name = translate_user_role($details['name']);
$role_selected = in_array($user_role_slug, $sanitize_roles_array) ? 'selected' : '';
?>
<option value="<?php echo esc_attr($user_role_slug); ?>" <?php echo esc_attr($role_selected); ?>><?php echo esc_html($user_role_name); ?></option>
<?php } ?>
</select>
</div>
<small class="description"><?php esc_html_e('Select the user roles that should bypass SVG sanitization.', 'svg-support' ); ?></small>
</td>
</tr>
<tr valign="top">
<th scope="row">
<strong><?php esc_html_e( 'Sanitize SVG on Front-end', 'svg-support' ); ?></strong>
</th>
<td>
<label for="bodhi_svgs_settings[sanitize_svg_front_end]">
<input id="bodhi_svgs_settings[sanitize_svg_front_end]" name="bodhi_svgs_settings[sanitize_svg_front_end]" type="checkbox" <?php checked( $bodhi_svgs_options['sanitize_svg_front_end'], 'on' ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?><br /><small class="description"><?php esc_html_e('Enhance security by sanitizing svg images on Front-end. This will help to prevent XSS and Injection attacks.', 'svg-support' ); ?></small>
</label>
</td>
</tr>
<tr valign="top">
<th scope="row">
<label for="bodhi_svgs_settings[minify_svg]"><strong><?php esc_html_e( 'Minify SVG', 'svg-support' ); ?></strong>
</th>
<td>
<label for="bodhi_svgs_settings[minify_svg]">
<input id="bodhi_svgs_settings[minify_svg]" name="bodhi_svgs_settings[minify_svg]" type="checkbox" <?php checked( isset( $bodhi_svgs_options['minify_svg'] ), true ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?><br /><small class="description"><?php esc_html_e('Enabling this option will auto-minify all svg uploads.', 'svg-support' ); ?></small>
</label>
</td>
</tr>
<tr valign="top">
<th scope="row">
<strong><?php esc_html_e( 'Load frontend CSS?', 'svg-support' ); ?></strong>
</th>
<td>
<label for="bodhi_svgs_settings[frontend_css]">
<input id="bodhi_svgs_settings[frontend_css]" name="bodhi_svgs_settings[frontend_css]" type="checkbox" <?php checked( isset( $bodhi_svgs_options['frontend_css'] ), true ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?><br /><small class="description"><?php esc_html_e('A very small piece of code that helps with displaying SVGs on the frontend in some cases.', 'svg-support' ); ?></small>
</label>
</td>
</tr>
<tr valign="top">
<th scope="row">
<strong><?php esc_html_e( 'Enable Advanced Mode?', 'svg-support' ); ?></strong>
</th>
<td>
<label for="bodhi_svgs_settings[advanced_mode]">
<input id="bodhi_svgs_settings[advanced_mode]" name="bodhi_svgs_settings[advanced_mode]" type="checkbox" <?php checked( isset( $bodhi_svgs_options['advanced_mode'] ), true ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?><br /><small class="description"><?php esc_html_e('You don\'t need to enable this to simply use SVG files as images. Enabling this will trigger advanced options and SVG functionality such as inline rendering.', 'svg-support' ); ?></small>
</label>
</td>
</tr>
<tr valign="top" class="svgs-advanced">
<th scope="row">
<h3 class="inner-title"><?php esc_html_e( 'Advanced', 'svg-support' ); ?></h3>
</th>
<td>
<hr>
</td>
</tr>
<tr valign="top" class="svgs-advanced">
<th scope="row">
<strong><?php esc_html_e( 'CSS Class to target', 'svg-support' ); ?></strong>
</th>
<td>
<label for="bodhi_svgs_settings[css_target]">
<input id="bodhi_svgs_settings[css_target]" class="all-options code" name="bodhi_svgs_settings[css_target]" type="text" value="<?php echo isset( $bodhi_svgs_options['css_target'] ) ? esc_attr($bodhi_svgs_options['css_target']) : ''; ?>"><br />
<small class="description">
<?php esc_html_e( 'The default target class is', 'svg-support' ); ?>
<code><?php echo esc_html( 'style-svg' ); ?></code>.
<?php esc_html_e( 'You can change it to your own class such as', 'svg-support' ); ?>
<code><?php echo esc_html( 'my-class' ); ?></code>
<?php esc_html_e( 'by typing it here. Leave blank to use the default class.', 'svg-support' ); ?>
<br>
<em><?php esc_html_e( 'Plugin can now go any level down to find your SVG! It will keep looking as long as the element with the target class has children. If it finds any IMG tags with .svg in the src URL, it will replace the IMG tag with your SVG code.', 'svg-support' ); ?></em>
</small>
</label>
</td>
</tr>
<tr valign="top" class="svgs-advanced">
<th scope="row">
<strong><?php esc_html_e( 'Skip Nested SVGs', 'svg-support' ); ?></strong>
</th>
<td>
<label for="bodhi_svgs_settings[skip_nested_svg]">
<input id="bodhi_svgs_settings[skip_nested_svg]" name="bodhi_svgs_settings[skip_nested_svg]" type="checkbox" value="1" <?php checked( isset( $bodhi_svgs_options['skip_nested_svg'] ) && $bodhi_svgs_options['skip_nested_svg'] == 1 ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?>
<br><small class="description"><?php esc_html_e( 'When enabled, only the first SVG in a .style-svg container will be inlined. Useful for Gutenberg Cover blocks with nested SVG images.', 'svg-support' ); ?></small>
</label>
</td>
</tr>
<tr valign="top" class="svgs-advanced">
<th scope="row">
<strong><?php esc_html_e( 'Output JS in Footer?', 'svg-support' ); ?></strong>
</th>
<td>
<label for="bodhi_svgs_settings[js_foot_choice]">
<input id="bodhi_svgs_settings[js_foot_choice]" name="bodhi_svgs_settings[js_foot_choice]" type="checkbox" <?php checked( isset( $bodhi_svgs_options['js_foot_choice'] ), true ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?><br /><small class="description"><?php esc_html_e('Normally, scripts are placed in head of the HTML document. If "Yes" is selected, the script is placed before the closing body tag. This requires the theme to have the wp_footer() template tag in the appropriate place.', 'svg-support' ); ?></small>
</label>
</td>
</tr>
<tr valign="top" class="svgs-advanced">
<th scope="row">
<strong><?php esc_html_e( 'Use Vanilla JS?', 'svg-support' ); ?></strong>
</th>
<td>
<label for="bodhi_svgs_settings[use_vanilla_js]">
<input id="bodhi_svgs_settings[use_vanilla_js]" name="bodhi_svgs_settings[use_vanilla_js]" type="checkbox" <?php checked( isset( $bodhi_svgs_options['use_vanilla_js'] ), true ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?><br /><small class="description"><?php esc_html_e('Checking this will use vanilla JS file instead of the jQuery.', 'svg-support' ); ?></small>
</label>
</td>
</tr>
<tr valign="top" class="svgs-advanced">
<th scope="row">
<strong><?php esc_html_e( 'Use Expanded JS?', 'svg-support' ); ?></strong>
</th>
<td>
<label for="bodhi_svgs_settings[use_expanded_js]">
<input id="bodhi_svgs_settings[use_expanded_js]" name="bodhi_svgs_settings[use_expanded_js]" type="checkbox" <?php checked( isset( $bodhi_svgs_options['use_expanded_js'] ), true ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?><br /><small class="description"><?php esc_html_e('Checking this will use the expanded JS file instead of the minified JS file. Useful if you want to minify this externally using a caching plugin or similar.', 'svg-support' ); ?></small>
</label>
</td>
</tr>
<tr valign="top" class="svgs-advanced">
<th scope="row">
<h3 class="inner-title"><?php esc_html_e( 'Legacy Settings', 'svg-support' ); ?></h3>
</th>
<td>
<hr>
</td>
</tr>
<tr valign="top" class="svgs-advanced">
<th scope="row">
<strong><?php esc_html_e( 'Force Inline SVG?', 'svg-support' ); ?></strong></label>
</th>
<td>
<label for="bodhi_svgs_settings[force_inline_svg]">
<input id="bodhi_svgs_settings[force_inline_svg]" name="bodhi_svgs_settings[force_inline_svg]" type="checkbox" <?php checked( isset( $bodhi_svgs_options['force_inline_svg'] ), true ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?><br />
<small class="description">
<strong><?php esc_html_e( 'Use with caution!', 'svg-support' ); ?></strong>
<?php esc_html_e( 'Checking this will automatically add the SVG class to ALL image tags containing SVG file sources in the rendered HTML via javascript and will therefore render all of your SVG files inline.', 'svg-support' ); ?>
<br />
<em><?php esc_html_e( 'Use case scenario: When using a visual builder such as in the Divi Theme or The Divi Builder, the class is not automatically added with the "Automatically insert class?" option selected or the builder module doesn\'t give you the option to manually add a CSS class directly to your image.', 'svg-support' ); ?></em>
</small>
</label>
</td>
</tr>
<tr valign="top" class="svgs-advanced">
<th scope="row">
<strong><?php esc_html_e( 'Automatically insert class?', 'svg-support' ); ?></strong></label>
</th>
<td>
<label for="bodhi_svgs_settings[auto_insert_class]">
<input id="bodhi_svgs_settings[auto_insert_class]" name="bodhi_svgs_settings[auto_insert_class]" type="checkbox" <?php checked( isset( $bodhi_svgs_options['auto_insert_class'] ), true ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?><br />
<small class="description">
<?php esc_html_e('(Classic Editor Only) Checking this will make sure that either the default class or the custom one you set in "CSS Class to target" option will be inserted into the style attributes of img tags when you insert SVG images into a post. Additionally, it will remove all of the default WordPress classes. It will leave normal image types as default and only affect SVG files.', 'svg-support' ); ?>
</small>
</label>
</td>
</tr>
</table>
<div class="postbox">
<h3><span><?php esc_html_e( 'Danger Zone', 'svg-support' ); ?></span></h3>
<div class="inside">
<table class="form-table">
<tr valign="top">
<th scope="row">
<label for="bodhi_svgs_settings[del_plugin_data]"><strong><?php esc_html_e( 'Delete Plugin Data', 'svg-support' ); ?></strong></label>
</th>
<td>
<label for="bodhi_svgs_settings[del_plugin_data]">
<input id="bodhi_svgs_settings[del_plugin_data]" name="bodhi_svgs_settings[del_plugin_data]" type="checkbox" <?php checked( isset( $bodhi_svgs_options['del_plugin_data'] ), true ); ?> />
<?php esc_html_e( 'Yes', 'svg-support' ); ?><br /><small class="description"><?php esc_html_e('Delete all plugin\'s data during uninstallation process.', 'svg-support' ); ?></small>
</label>
</td>
</tr>
</table>
</div>
</div>
<p>
<input class="button-primary" type="submit" name="bodhi_svgs_settings_submit" value="<?php esc_html_e( 'Save Changes', 'svg-support' ); ?>" />
</p>
</form>
</div> <!-- .inside -->
</div> <!-- .postbox -->
<div class="postbox">
<?php
if ( empty( $bodhi_svgs_options['advanced_mode'] ) ) {
echo '<h3><span>';
esc_html_e( 'Usage', 'svg-support' );
echo '</span></h3>';
} else {
echo '<h3><span>';
esc_html_e( 'Advanced Usage', 'svg-support' );
echo '</span></h3>';
}
?>
<div class="inside">
<p><?php esc_html_e( 'You can simply upload SVG files to your media library like any other image. Make sure to select "Restrict to Administrators" if you only want to allow admins to upload SVG files.', 'svg-support' ); ?></p>
<div class="svgs-advanced">
<p>
<?php
esc_html_e( 'Now, embed your SVG image like a standard image with the addition of adding the class', 'svg-support' );
?>
<code><?php echo esc_html( 'style-svg' ); ?></code>
<?php
esc_html_e( '(or your custom class from above) to any IMG tags that you want this plugin to swap out with your actual SVG code.', 'svg-support' );
?>
<br />
<?php esc_html_e( 'You can even use the class on an outer container and it will traverse all child elements to find all of the IMG tags with SVG files in the src and replace them.', 'svg-support' ); ?>
</p>
<p>
<?php esc_html_e( 'For example:', 'svg-support' ); ?>
<pre><code>&lt;img class="style-svg" alt="alt-text" src="image-source.svg" /&gt;</code></pre>
<?php esc_html_e( 'or', 'svg-support' ); ?>
<pre><code>&lt;img class="your-custom-class" alt="alt-text" src="image-source.svg" /&gt;</code></pre>
</p>
<p>
<?php esc_html_e( 'The whole IMG tag element will now be dynamically replaced by the actual code of your SVG, making the inner content targetable.', 'svg-support' ); ?><br />
<?php esc_html_e( 'This allows you to target elements within your SVG using CSS.', 'svg-support' ); ?>
</p>
<p><em><?php esc_html_e( 'Please Note:', 'svg-support' ); ?></em>
<br><em><?php esc_html_e( '- You will need to set your own height and width in your CSS for SVG files to display correctly.', 'svg-support' ); ?></em>
<br><em><?php esc_html_e( '- Your uploaded image needs to be an SVG file for this plugin to replace the img tag with the inline SVG code. It will not create SVG files for you.', 'svg-support' ); ?></em>
<br><em><?php esc_html_e( '- You can set this target class on any element and the script will traverse all children of that target element looking for IMG tags with SVG in the src to replace.', 'svg-support' ); ?></em></p>
</div>
</div> <!-- .inside -->
</div> <!-- .postbox -->
<div class="postbox">
<h3><span><?php esc_html_e( 'Compress and Optimize Images with ShortPixel', 'svg-support' ); ?></span></h3>
<div class="inside">
<?php
printf(
'<a target="_blank" class="shortpixel-logo" href="https://shortpixel.com/h/af/OLKMLXE207471"><img src="%s" alt="%s" /></a>',
esc_url(plugins_url('admin/img/shortpixel.png', BODHI_SVGS_PLUGIN_FILE)),
esc_attr__('ShortPixel logo', 'svg-support')
);
?>
<p><?php esc_html_e( 'Now that you\'ve set up SVG Support on your site, it\'s time to look at optimizing your existing images (jpg & png).', 'svg-support' ); ?></p>
<p><?php esc_html_e( 'ShortPixel improves website performance by reducing the size of your images. The results are no different in quality from the original, plus your originals are stored in a backup folder for you.', 'svg-support' ); ?></p>
<p><?php esc_html_e( 'If you upgrade to a paid plan, I\'ll receive a small commission... And that\'s really nice!', 'svg-support' ); ?></p>
<p><a class="shortpixel-button button-primary" href="https://shortpixel.com/h/af/OLKMLXE207471"><?php esc_html_e( 'Try ShortPixel WordPress Plugin for FREE', 'svg-support' ); ?></a></p>
</div> <!-- .inside -->
</div> <!-- .postbox -->
<div class="postbox">
<h3><span><?php esc_html_e( 'Animate and Optimize your SVG files using these open source projects', 'svg-support' ); ?></span></h3>
<div class="inside">
<p><a href="https://maxwellito.github.io/vivus-instant/" target="_blank">Vivus Instant for SVG animation</a> <?php esc_html_e( 'Upload your SVG files and use the tools provided to animate strokes.', 'svg-support' ); ?></p>
<p><a href="https://jakearchibald.github.io/svgomg/" target="_blank">SVGOMG for SVG optimisation</a> <?php esc_html_e( 'An online tool to optimize your SVG files.', 'svg-support' ); ?></p>
</div> <!-- .inside -->
</div> <!-- .postbox -->
</div> <!-- .meta-box-sortables .ui-sortable -->
</div> <!-- post-body-content -->
<!-- sidebar -->
<div id="postbox-container-1" class="postbox-container">
<div class="meta-box-sortables">
<div class="postbox">
<h3><span><?php esc_html_e( 'Ratings & Reviews', 'svg-support' ); ?></span></h3>
<div class="inside">
<p>
<?php esc_html_e( 'If you like', 'svg-support' ); ?>
<strong><?php esc_html_e( 'SVG Support', 'svg-support' ); ?></strong>
<?php esc_html_e( 'please consider leaving a', 'svg-support' ); ?>
<a href="https://wordpress.org/support/view/plugin-reviews/svg-support?filter=5#postform" target="_blank" class="svgs-rating-link">&#9733;&#9733;&#9733;&#9733;&#9733;</a>
<?php esc_html_e( 'rating.', 'svg-support' ); ?>
<br />
<?php esc_html_e( 'A huge thanks in advance!', 'svg-support' ); ?>
</p>
<p><a href="https://wordpress.org/support/view/plugin-reviews/svg-support?filter=5#postform" target="_blank" class="button-primary">Leave a rating</a></p>
</div> <!-- .inside -->
</div> <!-- .postbox -->
<div class="postbox">
<h3><span><?php esc_html_e( 'Having Issues?', 'svg-support' ); ?></span></h3>
<div class="inside">
<p><?php esc_html_e( 'I\'m always happy to help out!', 'svg-support' ); ?>
<br><?php esc_html_e( 'Support is handled exclusively through WordPress.org by my one man team - me.', 'svg-support' ); ?></p>
<p><a href="https://wordpress.org/support/plugin/svg-support/" target="_blank" class="button-primary"><?php esc_html_e('Get Support', 'svg-support'); ?></a></p>
</div> <!-- .inside -->
</div> <!-- .postbox -->
<div class="postbox">
<h3><span><?php esc_html_e( 'SVG Support Features', 'svg-support' ); ?></span></h3>
<div class="inside">
<ul>
<li><strong><?php esc_html_e( 'Basic Use', 'svg-support' ); ?></strong></li>
<li><?php esc_html_e( 'SVG Support for your media library', 'svg-support' ); ?></li>
<li><?php esc_html_e( 'Restrict to Administrators only', 'svg-support' ); ?></li>
<hr>
<li><strong><?php esc_html_e( 'Advanced Mode', 'svg-support' ); ?></strong></li>
<li><?php esc_html_e( 'Sanitize SVG files on upload', 'svg-support' ); ?></li>
<li><?php esc_html_e( 'Style SVG elements using CSS', 'svg-support' ); ?></li>
<li><?php esc_html_e( 'Animate SVG using CSS or JS', 'svg-support' ); ?></li>
<li><?php esc_html_e( 'Include multiple URLs inside single SVG', 'svg-support' ); ?></li>
<li><?php esc_html_e( 'Use odd shapes as links', 'svg-support' ); ?></li>
<li><?php esc_html_e( 'Inline SVG featured image support', 'svg-support' ); ?></li>
<li><?php esc_html_e( 'Force all SVG files to be rendered inline', 'svg-support' ); ?></li>
</ul>
</div> <!-- .inside -->
</div> <!-- .postbox -->
<div class="postbox">
<h3><span><?php esc_html_e( 'About The Plugin', 'svg-support' ); ?></span></h3>
<div class="inside">
<p><?php esc_html_e( 'Learn more about SVG Support on:', 'svg-support' ); ?><br/><a target="_blank" href="http://wordpress.org/plugins/svg-support/"><?php esc_html_e( 'The WordPress Plugin Repository', 'svg-support' ); ?></a></p>
<p><?php esc_html_e( 'Need help?', 'svg-support' ); ?><br/><a target="_blank" href="http://wordpress.org/support/plugin/svg-support"><?php esc_html_e( 'Visit The Support Forum', 'svg-support' ); ?></a></p>
<p>
<?php esc_html_e( 'Follow', 'svg-support' ); ?>
<a target="_blank" href="https://twitter.com/svgsupport"><?php esc_html_e( '@SVGSupport', 'svg-support' ); ?></a>
<?php esc_html_e( 'on Twitter', 'svg-support' ); ?>
</p>
<p>
<?php esc_html_e( 'Follow Benbodhi on:', 'svg-support' ); ?><br/>
<a target="_blank" href="https://twitter.com/benbodhi"><?php esc_html_e( 'Twitter', 'svg-support' ); ?></a> |
<a target="_blank" href="https://warpcast.com/benbodhi"><?php esc_html_e( 'Warpcast', 'svg-support' ); ?></a>
</p>
<p>&copy; <?php esc_html_e( 'Benbodhi', 'svg-support' ); ?> | <a target="_blank" href="https://benbodhi.com/">Benbodhi.com</a></p>
<p>
<?php esc_html_e( 'Thanks for your support, please consider donating.', 'svg-support' ); ?><br/>
<a target="_blank" href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z9R7JERS82EQQ&source=url"><?php esc_html_e( 'Donate using PayPal', 'svg-support' ); ?></a>
</p>
</div> <!-- .inside -->
</div> <!-- .postbox -->
</div> <!-- .meta-box-sortables -->
</div> <!-- #postbox-container-1 .postbox-container -->
</div> <!-- #post-body .metabox-holder .columns-2 -->
<br class="clear">
</div> <!-- #poststuff -->
</div> <!-- .wrap -->

View File

@@ -0,0 +1,39 @@
{
"name": "benbodhi/svg-support",
"description": "Upload SVG files to the Media Library and render SVG files inline for direct styling/animation of an SVG's internal elements using CSS/JS.",
"type": "wordpress-plugin",
"license": "GPL-2.0-or-later",
"repositories": [
{
"type": "package",
"package": {
"name": "cure53/dompurify",
"version": "2.5.8",
"dist": {
"url": "https://github.com/cure53/DOMPurify/archive/refs/tags/2.5.8.zip",
"type": "zip"
}
}
}
],
"require": {
"php": ">=7.4",
"cure53/dompurify": "2.5.8",
"enshrined/svg-sanitize": "^0.21.0"
},
"scripts": {
"post-install-cmd": [
"mkdir -p vendor/DOMPurify",
"cp vendor/cure53/dompurify/dist/purify.min.js vendor/DOMPurify/DOMPurify.min.js"
],
"post-update-cmd": [
"mkdir -p vendor/DOMPurify",
"cp vendor/cure53/dompurify/dist/purify.min.js vendor/DOMPurify/DOMPurify.min.js"
]
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
body #set-post-thumbnail,body #postimagediv .inside img[src$=".svg"]{width:100%}body .block-editor__container .components-panel .editor-post-featured-image__container img[src$='.svg']{position:relative}body .block-editor__container .edit-post-sidebar .components-panel .components-checkbox-control{margin-top:10px}

View File

@@ -0,0 +1 @@
.svgs-advanced{display:none}

View File

@@ -0,0 +1 @@
.svgs-version{font-size:10px;margin-left:7px}.postbox .inside a{text-decoration:none}h3{padding:0 12px}.help-tab-content h3{padding:0}h3.inner-title{padding:0;font-size:1.2em}.metabox-holder .postbox>h3,.metabox-holder .stuffbox>h3,.metabox-holder h2.hndle,.metabox-holder h3.hndle{font-size:1.3em;font-weight:600}.shortpixel-logo img{position:absolute;right:10px;bottom:0;width:140px}table.media .column-title .media-icon img{width:60px}

View File

@@ -0,0 +1 @@
.attachment svg,.widget_media_image svg{max-width:100%;height:auto}

View File

@@ -0,0 +1,563 @@
<?php
/**
* SVG Support in attachment modal
*
* This file contains functions to manage and manipulate SVG attachments in WordPress.
* It includes functionality for displaying SVGs in the attachment modal, generating metadata,
* sanitizing SVG files, and handling specific SVG-related scenarios.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Add SVG dimensions and other details to the response for displaying in the attachment modal.
*
* @param array $response The prepared attachment response data.
* @param object $attachment The attachment object.
* @param array $meta The attachment meta data.
*
* @return array Modified response with SVG dimensions and URL.
*/
function bodhi_svgs_response_for_svg( $response, $attachment, $meta ) {
if ( $response['mime'] == 'image/svg+xml' && empty( $response['sizes'] ) ) {
$svg_path = get_attached_file( $attachment->ID );
if ( ! file_exists( $svg_path ) ) {
// If SVG is external, use the URL instead of the path
$svg_path = $response['url'];
}
$dimensions = bodhi_svgs_get_dimensions( $svg_path );
$response['sizes'] = array(
'full' => array(
'url' => $response['url'],
'width' => $dimensions->width,
'height' => $dimensions->height,
'orientation' => $dimensions->width > $dimensions->height ? 'landscape' : 'portrait'
)
);
}
return $response;
}
add_filter( 'wp_prepare_attachment_for_js', 'bodhi_svgs_response_for_svg', 10, 3 );
/**
* Get the dimensions of an SVG file.
*
* This function checks if the SVG is a local file or a remote URL, retrieves its content, and
* parses the width and height from the SVG attributes.
*
* @param string $svg The file path or URL of the SVG.
*
* @return object An object containing the width and height of the SVG.
*/
function bodhi_svgs_get_dimensions( $svg ) {
$svg_content = '';
// Check if $svg is a URL or a local file path
if ( filter_var( $svg, FILTER_VALIDATE_URL ) ) {
// For remote SVGs, use wp_remote_get()
$response = wp_remote_get( $svg );
if ( is_wp_error( $response ) ) {
return (object) array( 'width' => 0, 'height' => 0 );
}
$svg_content = wp_remote_retrieve_body( $response );
} else {
// For local files, use WP_Filesystem to read the file content
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
global $wp_filesystem;
WP_Filesystem();
$svg_content = $wp_filesystem->get_contents( $svg );
}
if ( empty( $svg_content ) ) {
return (object) array( 'width' => 0, 'height' => 0 );
}
$svg = simplexml_load_string( $svg_content );
if ( $svg === FALSE ) {
$width = '0';
$height = '0';
} else {
$attributes = $svg->attributes();
$width = (string) $attributes->width;
$height = (string) $attributes->height;
}
return (object) array( 'width' => $width, 'height' => $height );
}
/**
* Generate attachment metadata for SVGs. (Thanks @surml)
*
* This function generates metadata for SVG attachments, including dimensions and file path.
* It is used to fix warnings related to missing width and height metadata for SVGs.
*
* @param array $metadata The attachment metadata.
* @param int $attachment_id The attachment ID.
*
* @return array Modified metadata including SVG dimensions.
*/
function bodhi_svgs_generate_svg_attachment_metadata( $metadata, $attachment_id ) {
$mime = get_post_mime_type( $attachment_id );
if ( $mime == 'image/svg+xml' ) {
$svg_path = get_attached_file( $attachment_id );
$upload_dir = wp_upload_dir();
// Get the path relative to /uploads/
$relative_path = $svg_path ? str_replace($upload_dir['basedir'], '', $svg_path) : '';
$filename = basename( $svg_path );
$dimensions = bodhi_svgs_get_dimensions( $svg_path );
$metadata = array(
'width' => intval($dimensions->width),
'height' => intval($dimensions->height),
'file' => $relative_path
);
$height = intval($dimensions->height);
$width = intval($dimensions->width);
// Generate sizes array for future implementations, if needed
$sizes = array();
foreach ( get_intermediate_image_sizes() as $s ) {
$sizes[$s] = array( 'width' => '', 'height' => '', 'crop' => false );
if ( $width !== 0 && $height !== 0 ) {
if ( isset( $_wp_additional_image_sizes[$s]['width'] ) ) {
$width_current_size = intval( $_wp_additional_image_sizes[$s]['width'] );
} else {
$width_current_size = get_option( "{$s}_size_w" );
}
if ( $width > $height ) {
$ratio = round($width / $height, 2);
$new_height = round($width_current_size / $ratio);
} else {
$ratio = round($height / $width, 2);
$new_height = round($width_current_size * $ratio);
}
$sizes[$s]['width'] = $width_current_size;
$sizes[$s]['height'] = $new_height;
$sizes[$s]['crop'] = false;
} else {
if ( isset( $_wp_additional_image_sizes[$s]['width'] ) ) {
$sizes[$s]['width'] = intval( $_wp_additional_image_sizes[$s]['width'] );
} else {
$sizes[$s]['width'] = get_option( "{$s}_size_w" );
}
if ( isset( $_wp_additional_image_sizes[$s]['height'] ) ) {
$sizes[$s]['height'] = intval( $_wp_additional_image_sizes[$s]['height'] );
} else {
$sizes[$s]['height'] = get_option( "{$s}_size_h" );
}
if ( isset( $_wp_additional_image_sizes[$s]['crop'] ) ) {
$sizes[$s]['crop'] = intval( $_wp_additional_image_sizes[$s]['crop'] );
} else {
$sizes[$s]['crop'] = get_option( "{$s}_crop" );
}
}
$sizes[$s]['file'] = $filename;
$sizes[$s]['mime-type'] = 'image/svg+xml';
}
$metadata['sizes'] = $sizes;
}
return $metadata;
}
add_filter( 'wp_generate_attachment_metadata', 'bodhi_svgs_generate_svg_attachment_metadata', 10, 3 );
/**
* Sanitize SVG files.
*
* This function sanitizes SVG files by removing potentially harmful elements and attributes.
* It also optionally minifies the SVG content and re-encodes it if it was originally gzipped.
*
* @param string $file The file path of the SVG to sanitize.
*
* @return bool True if the file was successfully sanitized, false otherwise.
*/
function bodhi_svgs_sanitize( $file ){
global $sanitizer;
$sanitizer->setAllowedTags( new bodhi_svg_tags() );
$sanitizer->setAllowedAttrs( new bodhi_svg_attributes() );
$dirty = '';
// Using WP_Filesystem to read the SVG file content
if ( ! function_exists( 'WP_Filesystem' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
global $wp_filesystem;
WP_Filesystem();
$dirty = $wp_filesystem->get_contents( $file );
// Try to decode if gzipped is enabled
if ( $is_zipped = bodhi_svgs_is_gzipped( $dirty ) ) {
$dirty = gzdecode( $dirty );
// Return on failure, since we can't read file
if ( $dirty === false ) {
return false;
}
}
// Remove remote references since they are dangerous and lead to injection
$sanitizer->removeRemoteReferences(true);
// Enable minify in library if its enabled in admin panel
bodhi_svgs_minify();
$clean = $sanitizer->sanitize( $dirty );
if ( $clean === false ) {
return false;
}
// If the file was gzipped, we need to re-zip it
if ( $is_zipped ) {
$clean = gzencode( $clean );
}
// Use WP_Filesystem to write the sanitized content back
if ( ! $wp_filesystem->put_contents( $file, $clean, FS_CHMOD_FILE ) ) {
return false;
}
return true;
}
/**
* Enable minification for SVG files.
*
* This function enables minification for SVG files if the option is set in the plugin settings.
*/
function bodhi_svgs_minify() {
global $bodhi_svgs_options;
global $sanitizer;
if ( !empty($bodhi_svgs_options['minify_svg']) && $bodhi_svgs_options['minify_svg'] === 'on' ) {
$sanitizer->minify(true);
}
}
/**
* Check if a string is gzipped.
*
* @param string $contents The contents to check.
*
* @return bool True if the contents are gzipped, false otherwise.
*/
function bodhi_svgs_is_gzipped( $contents ) {
if ($contents === null) {
return false;
}
if ( function_exists( 'mb_strpos' ) ) {
return 0 === mb_strpos( $contents, "\x1f" . "\x8b" . "\x08" );
} else {
return 0 === strpos( $contents, "\x1f" . "\x8b" . "\x08" );
}
}
/**
* Pre-filter for handling SVG uploads.
*
* This function checks if the uploaded file is an SVG and applies sanitization if required.
*
* @param array $file The uploaded file data.
*
* @return array The modified file data.
*/
function bodhi_svgs_sanitize_svg($file) {
global $bodhi_svgs_options;
$file_path = $file['tmp_name'];
$file_name = $file['name'];
// First quick check - if it's clearly not an SVG, return early
if (!empty($file_name) && strtolower(pathinfo($file_name, PATHINFO_EXTENSION)) !== 'svg') {
return $file;
}
// Multiple validation checks for SVG
if ( $file_path && file_exists( $file_path ) ) {
// 1. Check MIME type using fileinfo
$finfo = finfo_open( FILEINFO_MIME_TYPE );
$real_mime = finfo_file( $finfo, $file_path );
finfo_close( $finfo );
// 2. Read first bytes of the file to check for SVG header
$file_content = file_get_contents( $file_path );
// Check for XML declaration and SVG tag
$pattern1 = '/^[\s\n]*(?:<\?xml[^>]*>[\s\n]*)?(?:<!--.*?-->[\s\n]*)*(?:<!DOCTYPE[^>]*>[\s\n]*)?(?:<!--.*?-->[\s\n]*)*<svg[^>]*>/is';
$pattern2 = '/^[\s\n]*(?:<!--.*?-->[\s\n]*)*<svg[^>]*>/is';
$match1 = preg_match( $pattern1, $file_content );
$match2 = preg_match( $pattern2, $file_content );
$has_closing = strpos( $file_content, '</svg>' ) !== false;
$is_svg_content = ( $match1 || $match2 ) && $has_closing;
// If content validation fails OR (mime type isn't SVG AND isn't a plain text file containing SVG)
if ( !$is_svg_content ||
( $real_mime !== 'image/svg+xml' &&
$real_mime !== 'image/svg' &&
!( $real_mime === 'text/plain' && $is_svg_content ) ) ) {
$file['error'] = __( 'File is not a valid SVG.', 'svg-support' );
return $file;
}
}
// Now we know it's an SVG, continue with security checks
if (!defined('REST_REQUEST') && !wp_verify_nonce(
sanitize_text_field(wp_unslash($_REQUEST['_wpnonce'] ?? '')),
'media-form'
)) {
$file['error'] = __('Security check failed.', 'svg-support');
return $file;
}
// Get the roles that do not require SVG sanitization
$sanitize_on_upload_roles_array = (array) $bodhi_svgs_options['sanitize_on_upload_roles'];
$user = wp_get_current_user();
$current_user_roles = (array) $user->roles;
// Check if the current user's roles intersect with the roles that do not need sanitization
$no_sanitize_needed = array_intersect($sanitize_on_upload_roles_array, $current_user_roles);
// Check if the user has the capability to upload SVGs
$can_upload_files = current_user_can('upload_files');
// Force sanitize unless user is in roles that bypass sanitization
if ($can_upload_files && empty($no_sanitize_needed)) {
global $sanitizer;
// Read file contents
$file_content = file_get_contents($file_path);
if ($file_content === false) {
$file['error'] = __("Unable to read SVG file for sanitization.", 'svg-support');
return $file;
}
// Sanitize the content
$clean_svg = $sanitizer->sanitize($file_content);
if ($clean_svg === false) {
$file['error'] = __("Sorry, this file couldn't be sanitized for security reasons and wasn't uploaded.", 'svg-support');
return $file;
}
// Write sanitized content back
$write_result = file_put_contents($file_path, $clean_svg);
if ($write_result === false) {
$file['error'] = __("Unable to save sanitized SVG file.", 'svg-support');
return $file;
}
}
return $file;
}
// Add filter to handle upload pre-filtering for sanitization
add_filter('wp_handle_upload_prefilter', 'bodhi_svgs_sanitize_svg');
/**
* Fix for image widget PHP warnings related to metadata.
*
* @param array $data The attachment metadata.
*
* @return array|false The modified metadata or false if invalid.
*/
function bodhi_svgs_get_attachment_metadata( $data ) {
$res = $data;
if ( !isset( $data['width'] ) || !isset( $data['height'] ) ) {
$res = false;
}
return $res;
}
// add_filter( 'wp_get_attachment_metadata' , 'bodhi_svgs_get_attachment_metadata' );
// Commented this out 20200307 because it was stripping metadata from other attachments as well. Need to make this target only SVG attachments.
/**
* Remove srcset attribute for SVG images.
*
* @param array $sources The sources array for the image.
*
* @return array The modified sources array.
*/
function bodhi_svgs_disable_srcset( $sources ) {
$first_element = reset($sources);
if ( isset($first_element) && !empty($first_element['url']) ) {
$ext = pathinfo(reset($sources)['url'], PATHINFO_EXTENSION);
if ( $ext == 'svg' ) {
// return empty array
$sources = array();
return $sources;
} else {
return $sources;
}
} else {
return $sources;
}
}
add_filter( 'wp_calculate_image_srcset', 'bodhi_svgs_disable_srcset' );
/**
* Fix for division by zero error for SVGs. (Proposed by @starsis)
*
* This function ensures that SVGs do not cause division by zero errors by providing default
* dimensions if they are missing.
*
* @param array $image The image data.
* @param int $attachment_id The attachment ID.
* @param string $size The requested image size.
* @param bool $icon Whether the image is an icon.
*
* @return array The modified image data.
*/
function bodhi_svgs_dimension_fallback( $image, $attachment_id, $size, $icon ) {
// only manipulate for svgs
if ( get_post_mime_type($attachment_id) == 'image/svg+xml' ) {
if ( isset($image[1]) && $image[1] === 0 ) {
$image[1] = 1;
}
if ( isset($image[2]) && $image[2] === 0 ) {
$image[2] = 1;
}
}
return $image;
}
add_filter( 'wp_get_attachment_image_src', 'bodhi_svgs_dimension_fallback', 10, 4 );
/**
* Pre-process SVG files uploaded via REST API
*
* @param array $file File data before processing
* @param array $request The full request payload
* @return array|WP_Error Modified file data or error
*/
function bodhi_svgs_rest_pre_upload($file, $request) {
if ($file['type'] === 'image/svg+xml') {
// Randomize filename for REST API uploads
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
$random_name = wp_generate_password(12, false) . '.' . $ext;
$file['name'] = sanitize_file_name($random_name);
// Force sanitization
if (!bodhi_svgs_sanitize($file['tmp_name'])) {
return new WP_Error(
'svg_sanitization_failed',
__('SVG sanitization failed for security reasons.', 'svg-support'),
array('status' => 400)
);
}
}
return $file;
}
add_filter('rest_pre_upload_file', 'bodhi_svgs_rest_pre_upload', 10, 2);
function bodhi_svgs_handle_upload_check($fileinfo) {
if ($fileinfo['type'] === 'image/svg+xml') {
global $bodhi_last_upload_info;
$bodhi_last_upload_info = $fileinfo;
}
return $fileinfo;
}
add_filter('wp_handle_upload', 'bodhi_svgs_handle_upload_check');
function bodhi_svgs_rest_insert_attachment($prepared_attachment, $request) {
if ($request->get_header('content-type') !== 'image/svg+xml') {
return $prepared_attachment;
}
global $bodhi_svgs_options;
$user = wp_get_current_user();
$current_user_roles = (array) $user->roles;
$sanitize_on_upload_roles_array = (array) $bodhi_svgs_options['sanitize_on_upload_roles'];
$should_sanitize = empty(array_intersect($sanitize_on_upload_roles_array, $current_user_roles));
if ($should_sanitize) {
$file_path = get_attached_file($prepared_attachment->ID);
if (!$file_path) {
global $bodhi_last_upload_info;
if (isset($bodhi_last_upload_info['file'])) {
$file_path = $bodhi_last_upload_info['file'];
}
}
if ($file_path && file_exists($file_path)) {
global $sanitizer;
$file_content = file_get_contents($file_path);
if ($file_content !== false) {
$clean_svg = $sanitizer->sanitize($file_content);
if ($clean_svg !== false) {
file_put_contents($file_path, $clean_svg);
}
}
}
}
return $prepared_attachment;
}
add_filter('rest_insert_attachment', 'bodhi_svgs_rest_insert_attachment', 10, 2);

View File

@@ -0,0 +1,58 @@
<?php
/**
* Attribute Control
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* If in Advanced Mode
*/
if ( bodhi_svgs_advanced_mode() ) {
/**
* Strip HTML of all attributes and add custom class if the file is .svg
*/
function bodhi_svgs_auto_insert_class( $html, $alt='' ) {
global $bodhi_svgs_options;
if ( ! empty( $bodhi_svgs_options['css_target'] ) ) {
// if custom class is set, use it
$class = $bodhi_svgs_options['css_target'];
} else {
// if no custom class set, use default
$class = 'style-svg';
}
// check if the src file has .svg extension
if ( strpos( $html, '.svg' ) !== FALSE ) {
// strip html for svg files
$html = preg_replace( '/(width|height|title|alt|class)=".*"\s/', 'class="' . esc_attr($class) . '"', $html );
} else {
// leave html intact for non-svg
$html = $html;
}
return $html;
}
/**
* Fire auto insert class
*/
if ( ! empty( $bodhi_svgs_options['auto_insert_class'] ) ) {
add_filter( 'image_send_to_editor', 'bodhi_svgs_auto_insert_class', 10 );
// add_filter( 'post_thumbnail_html', 'bodhi_svgs_auto_insert_class', 10 );
}
}

View File

@@ -0,0 +1,145 @@
<?php
/**
* Enqueue scripts and styles
* This file is to enqueue the scripts and styles both admin and front end
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Enqueue the admin CSS using screen check functions
*/
function bodhi_svgs_admin_css() {
global $svgs_plugin_version;
// Check if user is on SVG Support settings page or media library page
if ( bodhi_svgs_specific_pages_settings() || bodhi_svgs_specific_pages_media_library() ) {
wp_enqueue_style( 'bodhi-svgs-admin', BODHI_SVGS_PLUGIN_URL . 'css/svgs-admin.css', array(), $svgs_plugin_version );
}
// Check if user is on SVG Support settings page and not in "Advanced Mode"
if ( bodhi_svgs_specific_pages_settings() && ! bodhi_svgs_advanced_mode() ) {
wp_enqueue_style( 'bodhi-svgs-admin-simple-mode', BODHI_SVGS_PLUGIN_URL . 'css/svgs-admin-simple-mode.css', array(), $svgs_plugin_version );
}
// Check if user is on an edit post page
if ( bodhi_svgs_is_edit_page() ) {
wp_enqueue_style( 'bodhi-svgs-admin-edit-post', BODHI_SVGS_PLUGIN_URL . 'css/svgs-admin-edit-post.css', array(), $svgs_plugin_version );
}
}
add_action( 'admin_enqueue_scripts', 'bodhi_svgs_admin_css' );
/*
* Enqueue multiselect for settings page only
*/
function bodhi_svgs_admin_multiselect() {
global $svgs_plugin_version;
// Ensure multiselect is only loaded on the settings page
if ( bodhi_svgs_specific_pages_settings() ) {
wp_enqueue_style( 'CSS-for-multiselect', BODHI_SVGS_PLUGIN_URL . 'css/jquery.dropdown-min.css', array(), $svgs_plugin_version );
wp_enqueue_script( 'js-for-multiselect', BODHI_SVGS_PLUGIN_URL . 'js/min/jquery.dropdown-min.js', array( 'jquery' ), $svgs_plugin_version, true );
wp_add_inline_script( 'js-for-multiselect', 'jQuery(document).ready(function(){jQuery(".upload_allowed_roles").dropdown({multipleMode: "label",input: \'<input type="text" maxLength="20" placeholder="Search">\',searchNoData: \'<li style="color:#ddd">No Results</li>\'});});', 'after' );
wp_add_inline_script( 'js-for-multiselect', 'jQuery(document).ready(function(){jQuery(".sanitize_on_upload_roles").dropdown({multipleMode: "label",input: \'<input type="text" maxLength="20" placeholder="Search">\',searchNoData: \'<li style="color:#ddd">No Results</li>\'});});', 'after' );
}
}
add_action( 'admin_enqueue_scripts', 'bodhi_svgs_admin_multiselect' );
/**
* Enqueue Block editor JS
*/
function bodhi_svgs_block_editor() {
global $svgs_plugin_version;
if ( bodhi_svgs_advanced_mode() ) {
wp_enqueue_script( 'bodhi-svgs-gutenberg-filters', BODHI_SVGS_PLUGIN_URL . '/js/min/gutenberg-filters-min.js', ['wp-edit-post'], $svgs_plugin_version, true );
}
}
add_action( 'enqueue_block_editor_assets', 'bodhi_svgs_block_editor' );
/**
* Enqueue frontend CSS
*/
function bodhi_svgs_frontend_css() {
global $bodhi_svgs_options;
global $svgs_plugin_version;
if ( ! empty( $bodhi_svgs_options['frontend_css'] ) ) {
wp_enqueue_style( 'bodhi-svgs-attachment', BODHI_SVGS_PLUGIN_URL . 'css/svgs-attachment.css', array(), $svgs_plugin_version );
}
}
add_action( 'wp_enqueue_scripts', 'bodhi_svgs_frontend_css' );
/**
* Enqueue frontend JS
*/
function bodhi_svgs_frontend_js() {
global $bodhi_svgs_options;
global $svgs_plugin_version;
if ( ! empty( $bodhi_svgs_options['sanitize_svg_front_end'] ) && $bodhi_svgs_options['sanitize_svg_front_end'] === 'on' && bodhi_svgs_advanced_mode() === true ) {
$bodhi_svgs_js_footer = ! empty( $bodhi_svgs_options['js_foot_choice'] );
wp_enqueue_script( 'bodhi-dompurify-library', BODHI_SVGS_PLUGIN_URL . 'vendor/DOMPurify/DOMPurify.min.js', array(), '2.5.8', $bodhi_svgs_js_footer );
}
}
add_action( 'wp_enqueue_scripts', 'bodhi_svgs_frontend_js', 9 );
/**
* Enqueue and localize JS for IMG tag replacement
*/
function bodhi_svgs_inline() {
global $bodhi_svgs_options;
global $svgs_plugin_version;
if ( bodhi_svgs_advanced_mode() ) {
$force_inline_svg_active = ! empty( $bodhi_svgs_options['force_inline_svg'] ) ? 'true' : 'false';
if ( ! empty( $bodhi_svgs_options['css_target'] ) ) {
$css_target_array = array(
'Bodhi' => 'img.' . esc_attr( $bodhi_svgs_options['css_target'] ),
'ForceInlineSVG' => esc_attr( $bodhi_svgs_options['css_target'] )
);
} else {
$css_target_array = array(
'Bodhi' => 'img.style-svg',
'ForceInlineSVG' => 'style-svg'
);
}
if ( ! empty( $bodhi_svgs_options['use_expanded_js'] ) ) {
$bodhi_svgs_js_folder = '';
$bodhi_svgs_js_file = '';
} else {
$bodhi_svgs_js_folder = 'min/';
$bodhi_svgs_js_file = '-min';
}
$bodhi_svgs_js_footer = ! empty( $bodhi_svgs_options['js_foot_choice'] );
$bodhi_svgs_js_vanilla = ! empty( $bodhi_svgs_options['use_vanilla_js'] ) ? '-vanilla' : '';
$bodhi_svgs_js_path = 'js/' . $bodhi_svgs_js_folder . 'svgs-inline' . $bodhi_svgs_js_vanilla . $bodhi_svgs_js_file . '.js';
// Only change: Make jQuery dependency conditional on vanilla JS setting
$bodhi_svgs_dependencies = ! empty( $bodhi_svgs_options['use_vanilla_js'] ) ? array() : array( 'jquery' );
wp_register_script( 'bodhi_svg_inline', BODHI_SVGS_PLUGIN_URL . $bodhi_svgs_js_path, $bodhi_svgs_dependencies, $svgs_plugin_version, $bodhi_svgs_js_footer );
wp_enqueue_script( 'bodhi_svg_inline' );
wp_localize_script('bodhi_svg_inline', 'svgSettings', array(
'skipNested' => !empty($bodhi_svgs_options['skip_nested_svg'])
));
wp_add_inline_script(
'bodhi_svg_inline',
sprintf(
'cssTarget=%s;ForceInlineSVGActive=%s;frontSanitizationEnabled=%s;',
wp_json_encode( $css_target_array ),
wp_json_encode( $force_inline_svg_active ),
wp_json_encode( $bodhi_svgs_options['sanitize_svg_front_end'] )
)
);
}
}
add_action( 'wp_enqueue_scripts', 'bodhi_svgs_inline' );

View File

@@ -0,0 +1,160 @@
<?php
/**
* Featured image meta checkbox to inline SVG
*
* Allow users to select whether featured images should contain the SVG Support class.
* Check if the featured image is SVG first, then display meta box for SVG only.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Add checkbox to the featured image metabox.
*/
function bodhi_svgs_featured_image_meta( $content ) {
global $post;
$thumbnail = get_the_post_thumbnail();
// Check if featured image is set and has extension of .svg or .svgz.
if ( $thumbnail && strpos( $thumbnail, '.svg' ) !== false ) {
$text = __( 'Render this SVG inline (advanced)', 'svg-support' );
$id = 'inline_featured_image';
$value = esc_attr( get_post_meta( $post->ID, $id, true ) );
$label = '<label for="' . $id . '" class="selectit"><input name="' . $id . '" type="checkbox" id="' . $id . '" value="1" '. checked( $value, 1, false ) .'> ' . $text .'</label>';
$nonce = wp_nonce_field( 'bodhi_svgs_save_featured_image_meta', 'bodhi_svgs_featured_image_nonce', true, false );
return $content .= $label . $nonce;
} else {
return $content;
}
}
if ( bodhi_svgs_advanced_mode() ) {
add_filter( 'admin_post_thumbnail_html', 'bodhi_svgs_featured_image_meta' );
}
/**
* Save featured image meta data when saved.
*/
function bodhi_svgs_save_featured_image_meta( $post_id, $post, $update ) {
// Verify nonce
if ( ! isset( $_POST['bodhi_svgs_featured_image_nonce'] ) ||
! wp_verify_nonce(
sanitize_text_field( wp_unslash( $_POST['bodhi_svgs_featured_image_nonce'] ) ),
'bodhi_svgs_save_featured_image_meta'
)
) {
return $post_id;
}
// If this is an autosave, our form has not been submitted, so we don't want to do anything.
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return $post_id;
}
// If the user does not have permission to edit posts, do nothing.
if ( ! current_user_can( 'edit_post', $post_id ) ) {
return $post_id;
}
// If checkbox is checked, add/update meta
if ( isset( $_POST['inline_featured_image'] ) ) {
update_post_meta( $post_id, 'inline_featured_image', 1 );
} else {
// If unchecked, delete the meta entirely
delete_post_meta( $post_id, 'inline_featured_image' );
}
}
add_action( 'save_post', 'bodhi_svgs_save_featured_image_meta', 10, 3 );
/*
* Save featured image meta for Gutenberg Editor
*/
function bodhi_svgs_register_meta() {
register_meta( 'post', 'inline_featured_image', array(
'show_in_rest' => true,
'single' => true,
'type' => 'boolean',
'auth_callback' => '__return_true'
) );
}
add_action( 'init', 'bodhi_svgs_register_meta' );
/**
* Add class to the featured image output on front end.
*/
function bodhi_svgs_add_class_to_thumbnail( $thumb ) {
$inline_featured_image = get_post_meta( get_the_ID(), 'inline_featured_image' );
if ( is_array( $inline_featured_image ) && in_array( 1, $inline_featured_image ) ) {
global $bodhi_svgs_options;
$target_class = ! empty( $bodhi_svgs_options['css_target'] ) ? $bodhi_svgs_options['css_target'] : 'style-svg';
if ( is_singular() ) {
$thumb = str_replace( 'attachment-', $target_class . ' attachment-', $thumb );
}
}
return $thumb;
}
if ( bodhi_svgs_advanced_mode() ) {
add_filter( 'post_thumbnail_html', 'bodhi_svgs_add_class_to_thumbnail' );
}
/**
* Safe update of inline featured image meta
*/
function bodhi_svgs_update_featured_image_meta($post_id, $value) {
// Delete any existing meta first
delete_post_meta($post_id, 'inline_featured_image');
// Add the new value
add_post_meta($post_id, 'inline_featured_image', $value, true);
}
/**
* Handle the AJAX request for updating featured image inline status
*/
function bodhi_svgs_featured_image_inline_toggle() {
// Verify nonce and permissions
if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'svg-support-featured')) {
wp_send_json_error('Invalid nonce');
}
if (!current_user_can('edit_posts')) {
wp_send_json_error('Insufficient permissions');
}
// Validate and sanitize input
if (!isset($_POST['post_id']) || !isset($_POST['checked'])) {
wp_send_json_error('Missing parameters');
}
$post_id = intval($_POST['post_id']);
$checked = ($_POST['checked'] === 'true');
// Update the meta safely
bodhi_svgs_update_featured_image_meta($post_id, $checked);
wp_send_json_success();
}
// Hook the AJAX actions for both logged-in and non-logged-in users
add_action('wp_ajax_bodhi_svgs_featured_image_inline_toggle', 'bodhi_svgs_featured_image_inline_toggle');
add_action('wp_ajax_nopriv_bodhi_svgs_featured_image_inline_toggle', 'bodhi_svgs_featured_image_inline_toggle');

View File

@@ -0,0 +1,14 @@
<?php
/**
* INTERNATIONALIZATION / LOCALIZATION
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
add_action( 'init', 'bodhi_svgs_localization' );
function bodhi_svgs_localization() {
load_plugin_textdomain( 'svg-support', false, basename( dirname( __FILE__ ) ) . '/languages' );
}

View File

@@ -0,0 +1,29 @@
<?php
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
function bodhi_svgs_cleanup_duplicate_meta() {
global $wpdb;
// Delete all but the latest inline_featured_image meta per post
$wpdb->query("
DELETE pm FROM {$wpdb->postmeta} pm
JOIN (
SELECT post_id, meta_id FROM (
SELECT post_id, meta_id,
ROW_NUMBER() OVER (PARTITION BY post_id ORDER BY meta_id DESC) AS row_num
FROM {$wpdb->postmeta}
WHERE meta_key = 'inline_featured_image'
) as duplicates
WHERE row_num > 1
) to_delete ON pm.meta_id = to_delete.meta_id
");
// Delete all inline_featured_image meta entries that aren't explicitly set to 1
$wpdb->query("
DELETE FROM {$wpdb->postmeta}
WHERE meta_key = 'inline_featured_image'
AND (meta_value = '' OR meta_value = '0' OR meta_value IS NULL)
");
}

View File

@@ -0,0 +1,117 @@
<?php
/**
* Add SVG mime types to WordPress
*
* Allows you to upload SVG files to the media library like any other image.
* Additionally provides a fix for WP 4.7.1 - 4.7.2 upload issues and for Avada theme.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Add Mime Types
*/
function bodhi_svgs_upload_mimes( $mimes = array() ) {
global $bodhi_svgs_options;
// Ensure the option is set
if ( !isset($bodhi_svgs_options['restrict']) ) {
return $mimes;
}
// Get the allowed roles from settings
$allowed_roles_array = (array) $bodhi_svgs_options['restrict'];
// Get the current user and their roles
$user = wp_get_current_user();
$current_user_roles = (array) $user->roles;
// For multisite, add network admin to allowed roles
if (is_multisite() && is_super_admin()) {
$current_user_roles[] = 'administrator';
}
// Check if the user has the capability or the role
$is_role_allowed = array_intersect($allowed_roles_array, $current_user_roles);
if ( empty($is_role_allowed) || !current_user_can('upload_files') ) {
return $mimes;
}
// Allow SVG file upload
$mimes['svg'] = 'image/svg+xml';
$mimes['svgz'] = 'image/svg+xml';
return $mimes;
}
add_filter( 'upload_mimes', 'bodhi_svgs_upload_mimes', 99 );
/**
* Check Mime Types
*/
function bodhi_svgs_upload_check( $checked, $file, $filename, $mimes ) {
if ( ! $checked['type'] ) {
$check_filetype = wp_check_filetype( $filename, $mimes );
$ext = $check_filetype['ext'];
$type = $check_filetype['type'];
$proper_filename = $filename;
// Check if the file is an SVG or SVGZ
if ( ( $ext === 'svg' || $ext === 'svgz' ) && $type === 'image/svg+xml' ) {
$checked = compact( 'ext', 'type', 'proper_filename' );
}
}
return $checked;
}
add_filter( 'wp_check_filetype_and_ext', 'bodhi_svgs_upload_check', 10, 4 );
/**
* Mime Check fix for WP 4.7.1 / 4.7.2
*
* Fixes uploads for these 2 versions of WordPress.
* Issue was fixed in 4.7.3 core.
*/
function bodhi_svgs_allow_svg_upload( $data, $file, $filename, $mimes ) {
global $wp_version;
// Corrected the version check condition
if ( version_compare($wp_version, '4.7.1', '>=') && version_compare($wp_version, '4.7.3', '<') ) {
$filetype = wp_check_filetype( $filename, $mimes );
// Check if the file is an SVG or SVGZ
if ( ( $filetype['ext'] === 'svg' || $filetype['ext'] === 'svgz' ) && $filetype['type'] === 'image/svg+xml' ) {
return [
'ext' => $filetype['ext'],
'type' => $filetype['type'],
'proper_filename' => $data['proper_filename']
];
}
}
return $data;
}
add_filter( 'wp_check_filetype_and_ext', 'bodhi_svgs_allow_svg_upload', 10, 4 );
function bodhi_svgs_multisite_settings($mimes) {
// Check if this is a multisite installation
if (is_multisite()) {
// Get the site ID
$blog_id = get_current_blog_id();
// Allow SVG on main site
if (is_main_site()) {
return $mimes;
}
// For subsites, check if upload_files capability is allowed
if (get_site_option('upload_space_check_disabled')) {
return $mimes;
}
}
return $mimes;
}
add_filter('upload_mimes', 'bodhi_svgs_multisite_settings', 98);

View File

@@ -0,0 +1,51 @@
<?php
/**
* ADD ABILITY TO VIEW THUMBNAILS IN WP 4.0+
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
add_action( 'admin_init', 'bodhi_svgs_display_thumbs' );
function bodhi_svgs_display_thumbs() {
if ( bodhi_svgs_specific_pages_media_library() ) {
function bodhi_svgs_thumbs_filter( $content ) {
return apply_filters( 'final_output', $content );
}
ob_start( 'bodhi_svgs_thumbs_filter' );
add_filter( 'final_output', 'bodhi_svgs_final_output' );
function bodhi_svgs_final_output( $content ) {
if ($content === null) {
return '';
}
$content = str_replace(
'<# } else if ( \'image\' === data.type && data.sizes && data.sizes.full ) { #>',
'<# } else if ( \'svg+xml\' === data.subtype ) { #>
<img class="details-image" src="{{ data.url }}" draggable="false" />
<# } else if ( \'image\' === data.type && data.sizes && data.sizes.full ) { #>',
$content
);
$content = str_replace(
'<# } else if ( \'image\' === data.type && data.sizes ) { #>',
'<# } else if ( \'svg+xml\' === data.subtype ) { #>
<div class="centered">
<img src="{{ data.url }}" class="thumbnail" draggable="false" />
</div>
<# } else if ( \'image\' === data.type && data.sizes ) { #>',
$content
);
return $content;
}
}
}

View File

@@ -0,0 +1,20 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
class bodhi_svg_attributes extends \enshrined\svgSanitize\data\AllowedAttributes {
/**
* Returns an array of attributes
*
* @return array
*/
public static function getAttributes() {
/**
* var array Attributes that are allowed.
*/
return apply_filters( 'svg_allowed_attributes', parent::getAttributes() );
}
}

View File

@@ -0,0 +1,58 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
// Check if the sanitizer class exists
if ( ! class_exists( '\enshrined\svgSanitize\data\AllowedTags' ) ) {
// Load the composer autoloader if it exists
$autoloader = dirname( __FILE__ ) . '/../vendor/autoload.php';
if ( file_exists( $autoloader ) ) {
require_once $autoloader;
}
}
// Only define the class if the parent class exists
if ( class_exists( '\enshrined\svgSanitize\data\AllowedTags' ) ) {
class bodhi_svg_tags extends \enshrined\svgSanitize\data\AllowedTags {
/**
* Returns an array of tags
*
* @return array
*/
public static function getTags() {
return apply_filters( 'svg_allowed_tags', parent::getTags() );
}
}
} else {
// Add an admin notice if the sanitizer isn't available
add_action('admin_notices', function() {
if (current_user_can('manage_options')) {
echo '<div class="notice notice-warning is-dismissible"><p>' .
esc_html__('SVG Support: SVG Sanitizer library not found. Some features may be limited.', 'svg-support') .
'</p></div>';
}
});
// Fallback class if the sanitizer isn't available
class bodhi_svg_tags {
/**
* Returns an array of tags
*
* @return array
*/
public static function getTags() {
$tags = array(
'svg',
'g',
'path',
'circle',
'rect',
'line',
'polyline',
'polygon',
);
return apply_filters( 'svg_allowed_tags', $tags );
}
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Integration with WP All Import for processing SVG files.
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
/**
* Hook into WP All Import to process SVG files correctly.
*
* @param int $attachment_id The ID of the uploaded attachment.
*/
function bodhi_svgs_wpallimport_handle_svg( $attachment_id ) {
// Get the file path of the uploaded attachment.
$file_path = get_attached_file( $attachment_id );
$file_mime = get_post_mime_type( $attachment_id );
// Check if the file is an SVG.
if ( $file_mime === 'image/svg+xml' ) {
// Sanitize the SVG file.
if ( ! bodhi_svgs_sanitize_svg_on_import( $file_path ) ) {
// Log the error without deleting the attachment.
// error_log( sprintf( 'SVG Sanitization failed for attachment ID %d during WP All Import.', $attachment_id ) );
}
// Generate attachment metadata for the SVG.
$metadata = wp_generate_attachment_metadata( $attachment_id, $file_path );
if ( ! empty( $metadata ) ) {
if ( ! wp_update_attachment_metadata( $attachment_id, $metadata ) ) {
// error_log( sprintf( 'Failed to update metadata for SVG attachment ID %d during WP All Import.', $attachment_id ) );
}
} else {
// error_log( sprintf( 'Failed to generate metadata for SVG attachment ID %d during WP All Import.', $attachment_id ) );
}
}
}
/**
* This function handles sanitization and any other processing needed for SVG files.
*
* @param string $file_path The file path of the SVG to be processed.
* @return bool True if sanitization was successful, false otherwise.
*/
function bodhi_svgs_sanitize_svg_on_import( $file_path ) {
// Check if the SVG file exists and is valid.
if ( file_exists( $file_path ) && is_readable( $file_path ) ) {
// Use the existing sanitize function.
if ( bodhi_svgs_sanitize( $file_path ) ) {
// Recalculate dimensions and regenerate metadata.
$dimensions = bodhi_svgs_get_dimensions( $file_path );
$metadata = array(
'width' => intval( $dimensions->width ),
'height' => intval( $dimensions->height ),
'file' => basename( $file_path ),
);
return true;
} else {
// error_log( sprintf( 'Sanitization failed for SVG file at path %s.', $file_path ) );
return false;
}
}
// error_log( sprintf( 'SVG file at path %s is either missing or not readable.', $file_path ) );
return false;
}
// Hook the function into WP All Import's `pmxi_attachment_uploaded`.
add_action( 'pmxi_attachment_uploaded', 'bodhi_svgs_wpallimport_handle_svg' );

View File

@@ -0,0 +1,68 @@
"use strict"
const { createElement, Fragment, useState } = wp.element;
const { withSelect, withDispatch } = wp.data;
const { compose } = wp.compose;
function CheckBoxCustom(props) {
const [isChecked, setIsChecked] = useState(props.meta.inline_featured_image);
const {
meta,
updateInlineFeaturedSvg,
} = props;
return createElement(
wp.components.CheckboxControl,
{
label: "Render this SVG inline (Advanced)",
checked: isChecked,
onChange: (value) => {
setIsChecked(value);
updateInlineFeaturedSvg(value, meta);
},
__nextHasNoMarginBottom: true
}
);
}
const composedCheckBox = compose([
withSelect((select) => {
const currentMeta = select('core/editor').getCurrentPostAttribute('meta');
const editedMeta = select('core/editor').getEditedPostAttribute('meta');
return {
meta: { ...currentMeta, ...editedMeta },
};
}),
withDispatch((dispatch) => ({
updateInlineFeaturedSvg(value, meta) {
meta = {
...meta,
inline_featured_image: value,
};
dispatch('core/editor').editPost({ meta });
},
})),
])(CheckBoxCustom);
function wrapPostFeaturedImage(OriginalComponent) {
return function(props) {
return createElement(
Fragment,
{},
'',
createElement(
OriginalComponent,
props
),
createElement(
composedCheckBox
)
);
}
}
wp.hooks.addFilter(
'editor.PostFeaturedImage',
'bodhi-svgs-featured-image/render-inline-image-checkbox',
wrapPostFeaturedImage
);

View File

@@ -0,0 +1,643 @@
;
(function ($) {
'use strict';
function noop() { }
function throttle(func, wait, options) {
var context, args, result;
var timeout = null;
// 上次执行时间点
var previous = 0;
if (!options) options = {};
// 延迟执行函数
var later = function () {
// 若设定了开始边界不执行选项上次执行时间始终为0
previous = options.leading === false ? 0 : new Date().getTime();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function () {
var now = new Date().getTime();
// 首次执行时,如果设定了开始边界不执行选项,将上次执行时间设定为当前时间。
if (!previous && options.leading === false) previous = now;
// 延迟执行时间间隔
var remaining = wait - (now - previous);
context = this;
args = arguments;
// 延迟时间间隔remaining小于等于0表示上次执行至此所间隔时间已经超过一个时间窗口
// remaining大于时间窗口wait表示客户端系统时间被调整过
if (remaining <= 0 || remaining > wait) {
clearTimeout(timeout);
timeout = null;
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
//如果延迟执行不存在,且没有设定结尾边界不执行选项
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
}
var isSafari = function () {
var ua = navigator.userAgent.toLowerCase();
if (ua.indexOf('safari') !== -1) {
return ua.indexOf('chrome') > -1 ? false : true;
}
}();
var settings = {
readonly: false,
minCount: 0,
minCountErrorMessage: '',
limitCount: Infinity,
limitCountErrorMessage: '',
input: '<input type="text" maxLength="20" placeholder="Search...">',
data: [],
searchable: true,
searchNoData: '<li style="color:#ddd">No Results.</li>',
init: noop,
choice: noop,
extendProps: []
};
var KEY_CODE = {
up: 38,
down: 40,
enter: 13
};
var EVENT_SPACE = {
click: 'click.iui-dropdown',
focus: 'focus.iui-dropdown',
keydown: 'keydown.iui-dropdown',
keyup: 'keyup.iui-dropdown'
};
var ALERT_TIMEOUT_PERIOD = 1000;
// 创建模板
function createTemplate() {
var isLabelMode = this.isLabelMode;
var searchable = this.config.searchable;
var templateSearch = searchable ? '<span class="dropdown-search">' + this.config.input + '</span>' : '';
return isLabelMode ? '<div class="dropdown-display-label"><div class="dropdown-chose-list">' + templateSearch + '</div></div><div class="dropdown-main">{{ul}}</div>' : '<a href="javascript:;" class="dropdown-display" tabindex="0"><span class="dropdown-chose-list"></span><a href="javascript:;" class="dropdown-clear-all" tabindex="0">\xD7</a></a><div class="dropdown-main">' + templateSearch + '{{ul}}</div>';
}
// 小于minCount提示的元素
function minItemsAlert() {
var _dropdown = this;
var _config = _dropdown.config;
var $el = _dropdown.$el;
var $alert = $el.find('.dropdown-minItem-alert');
var alertMessage = _config.minCountErrorMessage;
clearTimeout(_dropdown.itemCountAlertTimer);
if ($alert.length === 0) {
if (!alertMessage) {
alertMessage = '\u6700\u4f4e\u9009\u62e9' + _config.minCount + '\u4E2A';
}
$alert = $('<div class="dropdown-minItem-alert">' + alertMessage + '</div>');
}
$el.append($alert);
_dropdown.itemCountAlertTimer = setTimeout(function () {
$el.find('.dropdown-minItem-alert').remove();
}, ALERT_TIMEOUT_PERIOD);
}
// 超出限制提示
function maxItemAlert() {
var _dropdown = this;
var _config = _dropdown.config;
var $el = _dropdown.$el;
var $alert = $el.find('.dropdown-maxItem-alert');
var alertMessage = _config.limitCountErrorMessage;
clearTimeout(_dropdown.itemLimitAlertTimer);
if ($alert.length === 0) {
if (!alertMessage) {
alertMessage = '\u6700\u591A\u53EF\u9009\u62E9' + _config.limitCount + '\u4E2A';
}
$alert = $('<div class="dropdown-maxItem-alert">' + alertMessage + '</div>');
}
$el.append($alert);
_dropdown.itemLimitAlertTimer = setTimeout(function () {
$el.find('.dropdown-maxItem-alert').remove();
}, ALERT_TIMEOUT_PERIOD);
}
// select-option 转 ul-li
function selectToDiv(str) {
var result = str || '';
// 移除select标签
result = result.replace(/<select[^>]*>/gi, '').replace('</select>', '');
// 移除 optgroup 结束标签
result = result.replace(/<\/optgroup>/gi, '');
result = result.replace(/<optgroup[^>]*>/gi, function (matcher) {
var groupName = /label="(.[^"]*)"(\s|>)/.exec(matcher);
var groupId = /data\-group\-id="(.[^"]*)"(\s|>)/.exec(matcher);
return '<li class="dropdown-group" data-group-id="' + (groupId ? groupId[1] : '') + '">' + (groupName ? groupName[1] : '') + '</li>';
});
result = result.replace(/<option(.*?)<\/option>/gi, function (matcher) {
// var value = /value="?([\w\u4E00-\u9FA5\uF900-\uFA2D]+)"?/.exec(matcher);
var value = $(matcher).val();
var name = />(.*)<\//.exec(matcher);
// 强制要求html中使用selected/disabled而不是selected="selected","disabled="disabled"
var isSelected = matcher.indexOf('selected') > -1 ? true : false;
var isDisabled = matcher.indexOf('disabled') > -1 ? true : false;
var extendAttr = ''
var extendProps = matcher.replace(/data-(\w+)="?(.[^"]+)"?/g, function ($1) {
extendAttr += $1 + ' '
});
return '<li ' + (isDisabled ? ' disabled' : ' tabindex="0"') + ' data-value="' + (value || '') + '" class="dropdown-option ' + (isSelected ? 'dropdown-chose' : '') + '" ' + extendAttr + '>' + (name ? name[1] : '') + '</li>';
});
return result;
}
// object-data 转 select-option
function objectToSelect(data) {
var dropdown = this;
var map = {};
var result = '';
var name = [];
var selectAmount = 0;
var extendProps = dropdown.config.extendProps;
if (!data || !data.length) {
return false;
}
$.each(data, function (index, val) {
// disable 权重高于 selected
var hasGroup = val.groupId;
var isDisabled = val.disabled ? ' disabled' : '';
var isSelected = val.selected && !isDisabled ? ' selected' : '';
var extendAttr = ''
$.each(extendProps, function (index, value) {
if (val[value]) {
extendAttr += 'data-' + value + '="' + val[value] + '" '
}
})
var temp = '<option' + isDisabled + isSelected + ' value="' + val.id + '" ' + extendAttr + '>' + val.name + '</option>';
if (isSelected) {
name.push('<span class="dropdown-selected">' + val.name + '<i class="del" data-id="' + val.id + '"></i></span>');
selectAmount++;
}
// 判断是否有分组
if (hasGroup) {
if (map[val.groupId]) {
map[val.groupId] += temp;
} else {
// &janking& just a separator
map[val.groupId] = val.groupName + '&janking&' + temp;
}
} else {
map[index] = temp;
}
});
$.each(map, function (index, val) {
var option = val.split('&janking&');
// 判断是否有分组
if (option.length === 2) {
var groupName = option[0];
var items = option[1];
result += '<optgroup label="' + groupName + '" data-group-id="' + index + '">' + items + '</optgroup>';
} else {
result += val;
}
});
return [result, name, selectAmount];
}
// select-option 转 object-data
//
function selectToObject(el) {
var $select = el;
var result = [];
function readOption(key, el) {
var $option = $(el);
this.id = $option.prop('value');
this.name = $option.text();
this.disabled = $option.prop('disabled');
this.selected = $option.prop('selected');
}
$.each($select.children(), function (key, el) {
var tmp = {};
var tmpGroup = {};
var $el = $(el);
if (el.nodeName === 'OPTGROUP') {
tmpGroup.groupId = $el.data('groupId');
tmpGroup.groupName = $el.attr('label');
$.each($el.children(), $.proxy(readOption, tmp));
$.extend(tmp, tmpGroup);
} else {
$.each($el, $.proxy(readOption, tmp));
}
result.push(tmp);
});
return result;
}
var action = {
show: function (event) {
event.stopPropagation();
var _dropdown = this;
$(document).trigger('click.dropdown');
_dropdown.$el.addClass('active');
},
search: throttle(function (event) {
var _dropdown = this;
var _config = _dropdown.config;
var $el = _dropdown.$el;
var $input = $(event.target);
var intputValue = $input.val();
var data = _dropdown.config.data;
var result = [];
if (event.keyCode > 36 && event.keyCode < 41) {
return;
}
$.each(data, function (key, value) {
if ((value.groupName && value.groupName.toLowerCase().indexOf(intputValue.toLowerCase()) > -1) || value.name.toLowerCase().indexOf(intputValue.toLowerCase()) > -1 || '' + value.id === '' + intputValue) {
result.push(value);
}
});
$el.find('ul').html(selectToDiv(objectToSelect.call(_dropdown, result)[0]) || _config.searchNoData);
}, 300),
control: function (event) {
var keyCode = event.keyCode;
var KC = KEY_CODE;
var index = 0;
var direct;
var itemIndex;
var $items;
if (keyCode === KC.down || keyCode === KC.up) {
// 方向
direct = keyCode === KC.up ? -1 : 1;
$items = this.$el.find('[tabindex]');
itemIndex = $items.index($(document.activeElement));
// 初始
if (itemIndex === -1) {
index = direct + 1 ? -1 : 0;
} else {
index = itemIndex;
}
// 确认位序
index = index + direct;
// 最后位循环
if (index === $items.length) {
index = 0;
}
$items.eq(index).focus();
event.preventDefault();
}
},
multiChoose: function (event, status) {
var _dropdown = this;
var _config = _dropdown.config;
var $select = _dropdown.$select;
var $target = $(event.target);
var value = $target.attr('data-value');
var hasSelected = $target.hasClass('dropdown-chose');
var selectedName = [];
var selectedProp;
if ($target.hasClass('dropdown-display')) {
return false;
}
if (hasSelected) {
$target.removeClass('dropdown-chose');
_dropdown.selectAmount--;
} else {
if (_dropdown.selectAmount < _config.limitCount) {
$target.addClass('dropdown-chose');
_dropdown.selectAmount++;
} else {
maxItemAlert.call(_dropdown);
return false;
}
}
_dropdown.name = [];
$.each(_config.data, function (key, item) {
if ('' + item.id === '' + value) {
selectedProp = item;
item.selected = hasSelected ? false : true;
}
if (item.selected) {
selectedName.push(item.name);
_dropdown.name.push('<span class="dropdown-selected">' + item.name + '<i class="del" data-id="' + item.id + '"></i></span>');
}
});
$select.find('option[value="' + value + '"]').prop('selected', hasSelected ? false : true);
if (hasSelected && _dropdown.selectAmount < _config.minCount) {
minItemsAlert.call(_dropdown);
}
_dropdown.$choseList.find('.dropdown-selected').remove();
_dropdown.$choseList.prepend(_dropdown.name.join(''));
_dropdown.$el.find('.dropdown-display').attr('title', selectedName.join(','));
_config.choice.call(_dropdown, event, selectedProp);
},
singleChoose: function (event) {
var _dropdown = this;
var _config = _dropdown.config;
var $el = _dropdown.$el;
var $select = _dropdown.$select;
var $target = $(event.target);
var value = $target.attr('data-value');
var hasSelected = $target.hasClass('dropdown-chose');
if ($target.hasClass('dropdown-chose') || $target.hasClass('dropdown-display')) {
return false;
}
_dropdown.name = [];
$el.removeClass('active').find('li').not($target).removeClass('dropdown-chose');
$target.toggleClass('dropdown-chose');
$.each(_config.data, function (key, item) {
// id 有可能是数字也有可能是字符串,强制全等有弊端 2017-03-20 22:19:21
item.selected = false;
if ('' + item.id === '' + value) {
item.selected = hasSelected ? 0 : 1;
if (item.selected) {
_dropdown.name.push('<span class="dropdown-selected">' + item.name + '<i class="del" data-id="' + item.id + '"></i></span>');
}
}
});
$select.find('option[value="' + value + '"]').prop('selected', true);
_dropdown.name.push('<span class="placeholder">' + _dropdown.placeholder + '</span>');
_dropdown.$choseList.html(_dropdown.name.join(''));
_config.choice.call(_dropdown, event);
},
del: function (event) {
var _dropdown = this;
var _config = _dropdown.config;
var $target = $(event.target);
var id = $target.data('id');
// 2017-03-23 15:58:50 测试
// 10000条数据测试删除耗时 ~3ms
$.each(_dropdown.name, function (key, value) {
if (value.indexOf('data-id="' + id + '"') !== -1) {
_dropdown.name.splice(key, 1);
return false;
}
});
$.each(_dropdown.config.data, function (key, item) {
if ('' + item.id == '' + id) {
item.selected = false;
return false;
}
});
_dropdown.selectAmount--;
_dropdown.$el.find('[data-value="' + id + '"]').removeClass('dropdown-chose');
_dropdown.$el.find('[value="' + id + '"]').prop('selected', false).removeAttr('selected');
$target.closest('.dropdown-selected').remove();
_config.choice.call(_dropdown, event);
return false;
},
clearAll: function (event) {
var _dropdown = this;
var _config = _dropdown.config;
event && event.preventDefault();
console.log(this)
this.$choseList.find('.del').each(function (index, el) {
$(el).trigger('click');
});
if (_config.minCount > 0) {
minItemsAlert.call(_dropdown);
}
this.$el.find('.dropdown-display').removeAttr('title');
return false;
}
};
function Dropdown(options, el) {
this.$el = $(el);
this.$select = this.$el.find('select');
this.placeholder = this.$select.attr('placeholder');
this.config = options;
this.name = [];
this.isSingleSelect = !this.$select.prop('multiple');
this.selectAmount = 0;
this.itemLimitAlertTimer = null;
this.isLabelMode = this.config.multipleMode === 'label';
this.init();
}
Dropdown.prototype = {
init: function () {
var _this = this;
var _config = _this.config;
var $el = _this.$el;
_this.$select.hide();
// 判断dropdown是否单选是否token模式
$el.addClass(_this.isSingleSelect ? 'dropdown-single' : _this.isLabelMode ? 'dropdown-multiple-label' : 'dropdown-multiple');
if (_config.data.length === 0) {
_config.data = selectToObject(_this.$select);
}
var processResult = objectToSelect.call(_this, _config.data);
_this.name = processResult[1];
_this.selectAmount = processResult[2];
_this.$select.html(processResult[0]);
_this.renderSelect();
// disabled权重高于readonly
_this.changeStatus(_config.disabled ? 'disabled' : _config.readonly ? 'readonly' : false);
_this.config.init();
},
// 渲染 select 为 dropdown
renderSelect: function (isUpdate, isCover) {
var _this = this;
var $el = _this.$el;
var $select = _this.$select;
var elemLi = selectToDiv($select.prop('outerHTML'));
var template;
if (isUpdate) {
$el.find('ul')[isCover ? 'html' : 'append'](elemLi);
} else {
template = createTemplate.call(_this).replace('{{ul}}', '<ul>' + elemLi + '</ul>');
$el.append(template).find('ul').removeAttr('style class');
}
if (isCover) {
_this.name = [];
_this.$el.find('.dropdown-selected').remove();
_this.$select.val('');
}
_this.$choseList = $el.find('.dropdown-chose-list');
if (!_this.isLabelMode) {
_this.$choseList.html($('<span class="placeholder"></span>').text(_this.placeholder));
}
_this.$choseList.prepend(_this.name ? _this.name.join('') : []);
},
bindEvent: function () {
var _this = this;
var $el = _this.$el;
var openHandle = isSafari ? EVENT_SPACE.click : EVENT_SPACE.focus;
$el.on(EVENT_SPACE.click, function (event) {
event.stopPropagation();
});
$el.on(EVENT_SPACE.click, '.del', $.proxy(action.del, _this));
// show
if (_this.isLabelMode) {
$el.on(EVENT_SPACE.click, '.dropdown-display-label', function () {
$el.find('input').focus();
});
if (_this.config.searchable) {
$el.on(EVENT_SPACE.focus, 'input', $.proxy(action.show, _this));
} else {
$el.on(EVENT_SPACE.click, $.proxy(action.show, _this));
}
$el.on(EVENT_SPACE.keydown, 'input', function (event) {
if (event.keyCode === 8 && this.value === '' && _this.name.length) {
$el.find('.del').eq(-1).trigger('click');
}
});
} else {
$el.on(openHandle, '.dropdown-display', $.proxy(action.show, _this));
$el.on(openHandle, '.dropdown-clear-all', $.proxy(action.clearAll, _this));
}
// 搜索
$el.on(EVENT_SPACE.keyup, 'input', $.proxy(action.search, _this));
// 按下enter键设置token
$el.on(EVENT_SPACE.keyup, function (event) {
var keyCode = event.keyCode;
var KC = KEY_CODE;
if (keyCode === KC.enter) {
$.proxy(_this.isSingleSelect ? action.singleChoose : action.multiChoose, _this, event)();
}
});
// 按下上下键切换token
$el.on(EVENT_SPACE.keydown, $.proxy(action.control, _this));
$el.on(EVENT_SPACE.click, 'li[tabindex]', $.proxy(_this.isSingleSelect ? action.singleChoose : action.multiChoose, _this));
},
unbindEvent: function () {
var _this = this;
var $el = _this.$el;
var openHandle = isSafari ? EVENT_SPACE.click : EVENT_SPACE.focus;
$el.off(EVENT_SPACE.click);
$el.off(EVENT_SPACE.click, '.del');
// show
if (_this.isLabelMode) {
$el.off(EVENT_SPACE.click, '.dropdown-display-label');
$el.off(EVENT_SPACE.focus, 'input');
$el.off(EVENT_SPACE.keydown, 'input');
} else {
$el.off(openHandle, '.dropdown-display');
$el.off(openHandle, '.dropdown-clear-all');
}
// 搜索
$el.off(EVENT_SPACE.keyup, 'input');
// 按下enter键设置token
$el.off(EVENT_SPACE.keyup);
// 按下上下键切换token
$el.off(EVENT_SPACE.keydown);
$el.off(EVENT_SPACE.click, '[tabindex]');
},
changeStatus: function (status) {
var _this = this;
if (status === 'readonly') {
_this.unbindEvent();
} else if (status === 'disabled') {
_this.$select.prop('disabled', true);
_this.unbindEvent();
} else {
_this.$select.prop('disabled', false);
_this.bindEvent();
}
},
update: function (data, isCover) {
var _this = this;
var _config = _this.config;
var $el = _this.$el;
var _isCover = isCover || false;
if (Object.prototype.toString.call(data) !== '[object Array]') {
return;
}
_config.data = _isCover ? data.slice(0) : _config.data.concat(data);
var processResult = objectToSelect.call(_this, _config.data);
_this.name = processResult[1];
_this.selectAmount = processResult[2];
_this.$select.html(processResult[0]);
_this.renderSelect(true, _isCover);
},
destroy: function () {
this.unbindEvent();
this.$el.children().not('select').remove();
this.$el.removeClass('dropdown-single dropdown-multiple-label dropdown-multiple');
this.$select.show();
},
choose: function (values, status) {
var valArr = Object.prototype.toString.call(values) === '[object Array]' ? values : [values];
var _this = this;
var _status = status !== void 0 ? !!status : true
$.each(valArr, function (index, value) {
var $target = _this.$el.find('[data-value="' + value + '"]');
var targetStatus = $target.hasClass('dropdown-chose');
if (targetStatus !== _status) {
$target.trigger(EVENT_SPACE.click, status || true)
}
});
},
reset: function () {
action.clearAll.call(this)
}
};
$(document).on('click.dropdown', function () {
$('.dropdown-single,.dropdown-multiple,.dropdown-multiple-label').removeClass('active');
});
$.fn.dropdown = function (options) {
this.each(function (index, el) {
$(el).data('dropdown', new Dropdown($.extend(true, {}, settings, options), el));
});
return this;
}
})(jQuery);

View File

@@ -0,0 +1 @@
"use strict";function CheckBoxCustom(e){const[t,n]=useState(e.meta.inline_featured_image),{meta:o,updateInlineFeaturedSvg:a}=e;return createElement(wp.components.CheckboxControl,{label:"Render this SVG inline (Advanced)",checked:t,onChange:e=>{n(e),a(e,o)},__nextHasNoMarginBottom:!0})}function wrapPostFeaturedImage(e){return function(t){return createElement(Fragment,{},"",createElement(e,t),createElement(composedCheckBox))}}const{createElement:createElement,Fragment:Fragment,useState:useState}=wp.element,{withSelect:withSelect,withDispatch:withDispatch}=wp.data,{compose:compose}=wp.compose,composedCheckBox=compose([withSelect((e=>{const t=undefined,n=undefined;return{meta:{...e("core/editor").getCurrentPostAttribute("meta"),...e("core/editor").getEditedPostAttribute("meta")}}})),withDispatch((e=>({updateInlineFeaturedSvg(t,n){n={...n,inline_featured_image:t},e("core/editor").editPost({meta:n})}})))])(CheckBoxCustom);wp.hooks.addFilter("editor.PostFeaturedImage","bodhi-svgs-featured-image/render-inline-image-checkbox",wrapPostFeaturedImage);

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
jQuery(document).ready((function($){function t(t){const s=t.hasClass(i),r=t.parent().hasClass(i),n=t.closest("."+i).length>0;if(("true"===ForceInlineSVGActive||s||n)&&(!svgSettings.skipNested||s||r||!n)){var a=t.attr("id"),o=t.attr("class"),c=t.attr("src");c.endsWith("svg")&&$.get(c,(function(i){var s=$(i).find("svg"),r=s.attr("id");void 0===a?void 0===r?(a="svg-replaced-"+e,s=s.attr("id",a)):a=r:s=s.attr("id",a),void 0!==o&&(s=s.attr("class",o+" replaced-svg svg-replaced-"+e)),s=s.removeAttr("xmlns:a"),"on"===frontSanitizationEnabled&&""!=s[0].outerHTML&&(s=DOMPurify.sanitize(s[0].outerHTML)),t.replaceWith(s),e++,$(document).trigger("svg.loaded",[a])}),"xml").fail((function(){}))}}let e=0,i;(bodhisvgsInlineSupport=function(){"true"===ForceInlineSVGActive&&jQuery("img").each((function(){void 0!==jQuery(this).attr("src")&&!1!==jQuery(this).attr("src")&&jQuery(this).attr("src").match(/\.(svg)/)&&(jQuery(this).hasClass(cssTarget.ForceInlineSVG)||jQuery(this).addClass(cssTarget.ForceInlineSVG))})),String.prototype.endsWith||(String.prototype.endsWith=function(t,e){var i=this.toString();("number"!=typeof e||!isFinite(e)||Math.floor(e)!==e||e>i.length)&&(e=i.length),e-=t.length;var s=i.lastIndexOf(t,e);return-1!==s&&s===e}),String.prototype.endsWith=function(t){var e=this.length-t.length;return e>=0&&this.lastIndexOf(t)===e},i="true"===ForceInlineSVGActive?"img."!==cssTarget.Bodhi?cssTarget.ForceInlineSVG:"style-svg":"img."!==cssTarget.Bodhi?cssTarget.Bodhi:"style-svg","string"==typeof i&&(i=i.replace("img.",""),$("."+i).each((function(e){void 0!==$(this).attr("src")&&!1!==$(this).attr("src")?t($(this)):$(this).find("img").each((function(e){void 0!==$(this).attr("src")&&!1!==$(this).attr("src")&&t($(this))}))})))})()}));

View File

@@ -0,0 +1 @@
document.addEventListener("DOMContentLoaded",(function(e){function t(e){if("IMG"!==e.nodeName)return;const t=e.classList.contains(i),n=e.parentElement.classList.contains(i),r=null!==e.closest("."+i);if(("true"===ForceInlineSVGActive||t||r)&&(!svgSettings.skipNested||t||n||!r)){var o=e.id,a=e.className,c=e.src;if(c.endsWith("svg")){var l=new XMLHttpRequest;l.onreadystatechange=function(){if(4===l.readyState&&200===l.status){var t=l.responseText;let c;const d=undefined;var n=(new DOMParser).parseFromString(t,"text/html").getElementsByTagName("svg")[0],i=n.id;if(void 0===o||""===o?void 0===i||""===i?(o="svg-replaced-"+s,n.setAttribute("id",o)):o=i:n.setAttribute("id",o),void 0!==a&&""!==a&&n.setAttribute("class",a+" replaced-svg svg-replaced-"+s),n.removeAttribute("xmlns:a"),"on"===frontSanitizationEnabled&&""!==n.outerHTML){var r=DOMPurify.sanitize(n.outerHTML);e.outerHTML=r}else e.replaceWith(n);s++}else 4===l.readyState&&l.status},l.open("GET",c,!0),l.send(null)}}}function n(e){if(e.childNodes.length>0)for(var s=0;s<e.childNodes.length;s++){var i;if("IMG"===e.childNodes[s].nodeName)t(e.childNodes[s]);else n(e.childNodes[s])}}let s=0,i;(bodhisvgsInlineSupport=function(){if("true"===ForceInlineSVGActive)for(var e=document.getElementsByTagName("img"),s=0;s<e.length;s++)void 0!==e[s].src&&e[s].src.match(/\.(svg)/)&&(e[s].classList.contains(cssTarget.ForceInlineSVG)||e[s].classList.add(cssTarget.ForceInlineSVG));String.prototype.endsWith||(String.prototype.endsWith=function(e,t){var n=this.toString();("number"!=typeof t||!isFinite(t)||Math.floor(t)!==t||t>n.length)&&(t=n.length),t-=e.length;var s=n.lastIndexOf(e,t);return-1!==s&&s===t}),String.prototype.endsWith=function(e){var t=this.length-e.length;return t>=0&&this.lastIndexOf(e)===t},i="true"===ForceInlineSVGActive?"img."!==cssTarget.Bodhi?cssTarget.ForceInlineSVG:"style-svg":"img."!==cssTarget.Bodhi?cssTarget.Bodhi:"style-svg","string"==typeof i&&(i=i.replace("img.",""),document.querySelectorAll("."+i).forEach((function(e){"IMG"===e.nodeName?t(e):n(e)})))})()}));

View File

@@ -0,0 +1,168 @@
/* eslint-env browser */
/* global svgSettings, ForceInlineSVGActive, cssTarget, frontSanitizationEnabled, DOMPurify */
document.addEventListener("DOMContentLoaded", function(event) {
let bodhisvgsReplacements = 0;
let target;
// Function to replace the img tag with the SVG
function bodhisvgsReplace(img) {
// Ensure it's an image
if (img.nodeName !== 'IMG') {
return;
}
const hasTargetClass = img.classList.contains(target);
const parentHasTargetClass = img.parentElement.classList.contains(target);
const insideTargetContainer = img.closest('.' + target) !== null;
// First check if we should process at all
if (ForceInlineSVGActive !== 'true' && !hasTargetClass && !insideTargetContainer) {
return;
}
// If skip nested is enabled, only skip if:
// 1. Image doesn't have target class AND
// 2. Image's parent is not the target container but is inside one
if (svgSettings.skipNested && !hasTargetClass && !parentHasTargetClass && insideTargetContainer) {
return;
}
var imgID = img.id;
var imgClass = img.className;
var imgURL = img.src;
// Ensure the URL ends with .svg before proceeding
if (!imgURL.endsWith('svg')) {
return;
}
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
var data = xmlHttp.responseText;
// Parse the returned data to extract the SVG
let parser = new DOMParser();
const doc = parser.parseFromString(data, 'text/html');
// Get the SVG tag from the parsed data
var svg = doc.getElementsByTagName('svg')[0];
var svgID = svg.id;
// Add replaced image's ID to the new SVG if necessary
if (typeof imgID === 'undefined' || imgID === '') {
if (typeof svgID === 'undefined' || svgID === '') {
imgID = 'svg-replaced-' + bodhisvgsReplacements;
svg.setAttribute('id', imgID);
} else {
imgID = svgID;
}
} else {
svg.setAttribute('id', imgID);
}
// Add replaced image's classes to the new SVG
if (typeof imgClass !== 'undefined' && imgClass !== '') {
svg.setAttribute('class', imgClass + ' replaced-svg svg-replaced-' + bodhisvgsReplacements);
}
// Remove any invalid XML tags as per http://validator.w3.org
svg.removeAttribute('xmlns:a');
// If sanitization is enabled, sanitize the SVG code
if (frontSanitizationEnabled === 'on' && svg.outerHTML !== "") {
var sanitizedSVG = DOMPurify.sanitize(svg.outerHTML);
img.outerHTML = sanitizedSVG;
} else {
img.replaceWith(svg);
}
bodhisvgsReplacements++;
} else if (xmlHttp.readyState === 4 && xmlHttp.status !== 200) {
// Silently fail
}
};
xmlHttp.open("GET", imgURL, true);
xmlHttp.send(null);
}
// Function to iterate over nodes and replace images
function bodhisvgsIterator(node) {
if (node.childNodes.length > 0) {
for (var i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i].nodeName === 'IMG') {
var img = node.childNodes[i];
bodhisvgsReplace(img);
} else {
bodhisvgsIterator(node.childNodes[i]);
}
}
}
}
// Wrap in IIFE so that it can be called again later as bodhisvgsInlineSupport();
(bodhisvgsInlineSupport = function() {
// If force inline SVG option is active then add class
if (ForceInlineSVGActive === 'true') {
var allImages = document.getElementsByTagName('img');
for (var i = 0; i < allImages.length; i++) {
if (typeof allImages[i].src !== 'undefined') {
if (allImages[i].src.match(/\.(svg)/)) {
if (!allImages[i].classList.contains(cssTarget.ForceInlineSVG)) {
allImages[i].classList.add(cssTarget.ForceInlineSVG);
}
}
}
}
}
// Polyfill to support all older browsers
if (!String.prototype.endsWith) {
String.prototype.endsWith = function(searchString, position) {
var subjectString = this.toString();
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
position = subjectString.length;
}
position -= searchString.length;
var lastIndex = subjectString.lastIndexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
};
}
// Another snippet to support IE11
String.prototype.endsWith = function(pattern) {
var d = this.length - pattern.length;
return d >= 0 && this.lastIndexOf(pattern) === d;
};
// Set target before we use it
if (ForceInlineSVGActive === 'true') {
target = cssTarget.Bodhi !== 'img.' ? cssTarget.ForceInlineSVG : 'style-svg';
} else {
target = cssTarget.Bodhi !== 'img.' ? cssTarget.Bodhi : 'style-svg';
}
// Ensure target is a string before applying replace method
if (typeof target === 'string') {
target = target.replace("img.", "");
} else {
return;
}
// Replace images with SVGs based on the target class
document.querySelectorAll('.' + target).forEach(function(element) {
if (element.nodeName === 'IMG') {
bodhisvgsReplace(element);
} else {
bodhisvgsIterator(element);
}
});
})(); // Execute immediately
});

View File

@@ -0,0 +1,166 @@
/* eslint-env jquery */
/* global svgSettings, ForceInlineSVGActive, cssTarget, frontSanitizationEnabled, DOMPurify, jQuery */
jQuery(document).ready(function ($) {
let bodhisvgsReplacements = 0;
let target;
// Function to replace the img tag with the SVG
function bodhisvgsReplace(img) {
const hasTargetClass = img.hasClass(target);
const parentHasTargetClass = img.parent().hasClass(target);
const insideTargetContainer = img.closest('.' + target).length > 0;
// First check if we should process at all
if (ForceInlineSVGActive !== 'true' && !hasTargetClass && !insideTargetContainer) {
return;
}
// If skip nested is enabled, only skip if:
// 1. Image doesn't have target class AND
// 2. Image's parent is not the target container but is inside one
if (svgSettings.skipNested && !hasTargetClass && !parentHasTargetClass && insideTargetContainer) {
return;
}
var imgID = img.attr('id');
var imgClass = img.attr('class');
var imgURL = img.attr('src');
// Ensure the URL ends with .svg before proceeding
if (!imgURL.endsWith('svg')) {
return;
}
// Use jQuery's get method to fetch the SVG
$.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = $(data).find('svg');
var svgID = $svg.attr('id');
// Add replaced image's ID to the new SVG if necessary
if (typeof imgID === 'undefined') {
if (typeof svgID === 'undefined') {
imgID = 'svg-replaced-' + bodhisvgsReplacements;
$svg = $svg.attr('id', imgID);
} else {
imgID = svgID;
}
} else {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if (typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass + ' replaced-svg svg-replaced-' + bodhisvgsReplacements);
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// If sanitization is enabled, sanitize the SVG code
if (frontSanitizationEnabled === 'on' && $svg[0]['outerHTML'] != "") {
$svg = DOMPurify.sanitize($svg[0]['outerHTML']);
}
// Replace image with new SVG
img.replaceWith($svg);
// Increment the replacements counter
bodhisvgsReplacements++;
// Trigger custom event after SVG is loaded
$(document).trigger('svg.loaded', [imgID]);
}, 'xml').fail(function() {
// Silently fail
});
}
// Wrap in IIFE so that it can be called again later as bodhisvgsInlineSupport();
(bodhisvgsInlineSupport = function () {
// If force inline SVG option is active then add class
if (ForceInlineSVGActive === 'true') {
// Find all SVG inside img and add class if it hasn't got it
jQuery('img').each(function () {
// Check if the SRC attribute is present at all
if (typeof jQuery(this).attr('src') !== typeof undefined && jQuery(this).attr('src') !== false) {
// Pick only those with the extension we want
if (jQuery(this).attr('src').match(/\.(svg)/)) {
// Add our class name
if (!jQuery(this).hasClass(cssTarget.ForceInlineSVG)) {
jQuery(this).addClass(cssTarget.ForceInlineSVG);
}
}
}
});
}
// Polyfill to support all older browsers
// delete when not needed in the future
if (!String.prototype.endsWith) {
String.prototype.endsWith = function (searchString, position) {
var subjectString = this.toString();
if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {
position = subjectString.length;
}
position -= searchString.length;
var lastIndex = subjectString.lastIndexOf(searchString, position);
return lastIndex !== -1 && lastIndex === position;
};
} // end polyfill
// Another snippet to support IE11
String.prototype.endsWith = function (pattern) {
var d = this.length - pattern.length;
return d >= 0 && this.lastIndexOf(pattern) === d;
};
// End snippet to support IE11
// Set target before we use it
if (ForceInlineSVGActive === 'true') {
target = cssTarget.Bodhi !== 'img.' ? cssTarget.ForceInlineSVG : 'style-svg';
} else {
target = cssTarget.Bodhi !== 'img.' ? cssTarget.Bodhi : 'style-svg';
}
// Ensure target is a string before applying replace method
if (typeof target === 'string') {
target = target.replace("img.", "");
} else {
return;
}
// Replace images with SVGs based on the target class
$('.' + target).each(function (index) {
// If image then send for replacement
if (typeof $(this).attr('src') !== typeof undefined && $(this).attr('src') !== false) {
bodhisvgsReplace($(this));
} else {
// Look for SVG children and send for replacement
$(this).find("img").each(function (i) {
if (typeof $(this).attr('src') !== typeof undefined && $(this).attr('src') !== false) {
bodhisvgsReplace($(this));
}
});
}
});
})(); // Execute immediately
});

View File

@@ -0,0 +1,281 @@
msgid ""
msgstr ""
"Project-Id-Version: SVG Support 2.2.3.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-16 20:19:06+00:00\n"
"PO-Revision-Date: Mon May 16 2016 13:54:01 GMT-0700 (PDT)\n"
"Last-Translator: root <benbodhi@gmail.com>\n"
"Language-Team: Benbodhi <wp@benbodhi.com>\n"
"Language: Spanish (Spain)\n"
"Plural-Forms: nplurals=2; plural=n != 1\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Generator: Loco - https://localise.biz/\n"
"X-Poedit-KeywordsList: _:1;gettext:1;dgettext:2;ngettext:1,2;dngettext:2,3;"
"__:1;_e:1;_c:1;_n:1,2;_n_noop:1,2;_nc:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
"_x:1,2c;_ex:1,2c;_nx:1,2,4c;_nx_noop:1,2,3c;_n_js:1,2;_nx_js:1,2,3c;"
"esc_attr__:1;esc_html__:1;esc_attr_e:1;esc_html_e:1;esc_attr_x:1,2c;"
"esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
"X-Poedit-Basepath: ..\n"
"X-Textdomain-Support: yes\n"
"X-Loco-Target-Locale: es_ES\n"
"X-Poedit-SearchPath-0: ."
#. URI of the plugin
msgid "http://wordpress.org/plugins/svg-support"
msgstr ""
#: ../admin/plugin-action-meta-links.php:32
msgid "$25 Free Credit from GoWebben"
msgstr ""
#: ../admin/svgs-settings-page.php:57
msgid "Output JS in Footer?"
msgstr ""
#: ../admin/svgs-settings-page.php:62
msgid ""
" Normally, scripts are placed in <code>head</code> of the HTML document. If "
"this parameter is true, the script is placed before the closing "
"<code>body</code> tag. This requires the theme to have the "
"<code>wp_footer()</code> template tag in the appropriate place."
msgstr ""
#: ../admin/svgs-settings-page.php:68
msgid "Automatically insert class?"
msgstr ""
#: ../admin/svgs-settings-page.php:73
msgid ""
" Checking this will make sure that either the default class or the custom "
"one you set below is inserted into the style attributes of <code>img</code> "
"tags when you insert images. Additionally, it will remove all of the default "
"WordPress classes."
msgstr ""
#: ../admin/svgs-settings-page.php:112
msgid "Please Note:"
msgstr ""
#: ../admin/svgs-settings-page.php:113
msgid ""
"- You will need to set your own height and width in your CSS for SVG files "
"to display correctly."
msgstr ""
#: ../admin/svgs-settings-page.php:114
msgid ""
"- Your uploaded image needs to be an SVG file for this plugin to replace the "
"img tag with the inline SVG code. It will not create SVG files for you."
msgstr ""
#: ../admin/svgs-settings-page.php:131
msgid "Plugin Features"
msgstr ""
#: ../admin/svgs-settings-page.php:145
msgid "About The Plugin"
msgstr ""
#: ../admin/svgs-settings-page.php:157
msgid "GoWebben Hosting"
msgstr ""
#: ../admin/svgs-settings-page.php:159
msgid "Claim your FREE $25 credit from"
msgstr ""
#: ../admin/svgs-settings-page.php:159
msgid ""
"No catch, just free credit for using this plugin! It will be applied "
"automatically using the link provided, but in any case you can simply use "
"code: SVGSUPPORT during checkout."
msgstr ""
msgid "SVG Support"
msgstr "SVG Support"
msgid ""
"Allow SVG file uploads using the WordPress Media Library uploader plus "
"direct styling of SVG elements using CSS."
msgstr ""
"Permitir la subida de archivos SVG a través de la librería de medios además "
"de dar formato a los elementos SVG usando CSS."
msgid "Benbodhi"
msgstr "Benbodhi"
msgid "http://benbodhi.com"
msgstr "http://benbodhi.com"
#: ../admin/admin-init.php:15
msgid "SVG Support Options and Instructions"
msgstr "SVG Support Opciones e Instrucciones"
#: ../admin/admin-init.php:29
msgid "You can't play with this."
msgstr "No puedes jugar con esto."
#: ../admin/plugin-action-meta-links.php:30
msgid "Get Support"
msgstr "Obtener soporte"
#: ../admin/plugin-action-meta-links.php:31
msgid "Donate to author"
msgstr "Donar al autor"
#: ../admin/svgs-settings-page.php:4
msgid "SVG Support Settings and Usage"
msgstr "SVG Support Configuración y Uso"
#: ../admin/svgs-settings-page.php:12
msgid "Introduction"
msgstr "Introducción"
#: ../admin/svgs-settings-page.php:15
msgid ""
"When using SVG images on your WordPress site, it can be hard to style "
"elements within the SVG using CSS. <strong>Now you can, easily!</strong>"
msgstr ""
"Al usar imágenes SVG en un sitio de WordPress es complicado darle formato a "
"los elementos SVG usando CSS. <strong>¡Ahora esto es sencillo!</strong>"
#: ../admin/svgs-settings-page.php:16
msgid ""
"This plugin not only provides SVG Support like the name says, it also allows "
"you to easily embed your full SVG file's code using a simple IMG tag. By "
"adding the class <code>style-svg</code> to your IMG elements, this plugin "
"dynamically replaces any IMG elements containing the <code>style-svg</code> "
"class with your complete SVG."
msgstr ""
"Este plugin no solo da soporte SVG como su nombre indica, sino que además "
"permite insertar el código completo SVG utilizando una simple etiqueta IMG. "
"Añadiendo la clase <code>style-svg</code> a los elementos IMG este plugin "
"los reemplaza de forma dinámica con los SVG completos."
#: ../admin/svgs-settings-page.php:17
msgid ""
"The main purpose of this is to allow styling of SVG elements. Usually your "
"styling options are restricted when using <code>embed</code>, "
"<code>object</code> or <code>img</code> tags alone."
msgstr ""
"El objetivo principal es permitir darle formato a los elementos SVG. "
"Normalmente las opciones de formato están restringidas al usar solo las "
"etiquetas <code>embed</code>, <code>object</code> o <code>img</code>."
#: ../admin/svgs-settings-page.php:34
msgid "Settings"
msgstr "Configuración"
#: ../admin/svgs-settings-page.php:46
msgid "Restrict to Administrators"
msgstr "Restringir a los administradores"
#: ../admin/svgs-settings-page.php:51 ../admin/svgs-settings-page.php:62 ..
#: admin/svgs-settings-page.php:73
msgid "Yes"
msgstr "Si"
#: ../admin/svgs-settings-page.php:51
msgid " Restricts SVG upload priveledges to Administrators."
msgstr " Restringe la subida de archivos SVG a los administradores."
#: ../admin/svgs-settings-page.php:78
msgid "CSS Class to target"
msgstr "Clase CSS objetivo"
#: ../admin/svgs-settings-page.php:81
msgid ""
"The default target class is <code>style-svg</code>. You can change it to "
"your own class such as <code>my-class</code> by typing it here.<br />Leave "
"blank to use the default class."
msgstr ""
"La clase por defecto es <code>style-svg</code>. Puedes cambiarla por una "
"clase propia como <code>my-class</code> tecleándola aquí.<br />Déjalo en "
"blanco para usar la clase por defecto."
#: ../admin/svgs-settings-page.php:87
msgid "Save Changes"
msgstr "Guardar cambios"
#: ../admin/svgs-settings-page.php:98
msgid "Usage"
msgstr "Uso"
#: ../admin/svgs-settings-page.php:101
msgid "You can simply upload SVG images to your media library like any other file."
msgstr ""
"Puedes subir fácilmente imágenes SVG a tu librería de medios como otros "
"formatos de archivo."
#: ../admin/svgs-settings-page.php:102
msgid ""
"Now, embed your SVG image like a standard image with the addition of adding "
"the class <code>style-svg</code> (or your custom class from above) to any "
"IMG tags that you want this plugin to swap out with your actual SVG code."
msgstr ""
"Ahora, incluye tu imagen SVG como una imágen estándar añadiendo la clase "
"<code>style-svg</code> (o tu clase propia definida arriba) a cualquier "
"etiqueta IMG que quieres que se cambie por el código SVG."
#: ../admin/svgs-settings-page.php:103
msgid "For example:"
msgstr "por ejemplo:"
#: ../admin/svgs-settings-page.php:106
msgid "or"
msgstr "o"
#: ../admin/svgs-settings-page.php:109
msgid ""
"The whole IMG tag element will now be dynamically replaced by the actual "
"code of your SVG, making the inner content targetable."
msgstr ""
"Toda la etiqueta IMG ahora se reemplaza de forma dinámica con el código del "
"SVG haciendo su contenido accesible."
#: ../admin/svgs-settings-page.php:110
msgid "This allows you to target elements within your SVG using CSS."
msgstr "Esto permite acceder a los elementos SVG usando CSS."
#: ../admin/svgs-settings-page.php:134
msgid "SVG Support for your media library"
msgstr "Soporte SVG para la librería de medios"
#: ../admin/svgs-settings-page.php:135
msgid "Style SVG elements directly using CSS"
msgstr "Dar formato a los elementos SVG usando CSS"
#: ../admin/svgs-settings-page.php:136
msgid "Restrict to Administrators only"
msgstr "Restringido para administradores"
#: ../admin/svgs-settings-page.php:137
msgid "Extremely Simple To Use"
msgstr "Muy fácil de usar"
#: ../admin/svgs-settings-page.php:147
msgid "You can read about this plugin in detail on"
msgstr "Puedes leer todo sobre el plugin en"
#: ../admin/svgs-settings-page.php:147
msgid "The WordPress Plugin Repository"
msgstr "El repositorio de plugins de WordPress"
#: ../admin/svgs-settings-page.php:148
msgid "Need help?"
msgstr "¿Necesitas ayuda?"
#: ../admin/svgs-settings-page.php:148
msgid "Visit Support"
msgstr "Visitar soporte"
#: ../admin/svgs-settings-page.php:149
msgid "Buy Benbodhi a Beer &rarr;"
msgstr "Comprar una cerveza para Benbodhi &rarr;"
#: ../admin/svgs-settings-page.php:150
msgid "from"
msgstr "de"

View File

@@ -0,0 +1,284 @@
msgid ""
msgstr ""
"Project-Id-Version: SVG Support 2.2.3.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-16 20:19:06+00:00\n"
"PO-Revision-Date: Mon May 16 2016 13:54:09 GMT-0700 (PDT)\n"
"Last-Translator: root <benbodhi@gmail.com>\n"
"Language-Team: Benbodhi <wp@benbodhi.com>\n"
"Language: Serbian\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10 >= 2 && "
"n%10<=4 &&(n%100<10||n%100 >= 20)? 1 : 2)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-SourceCharset: utf-8\n"
"X-Generator: Loco - https://localise.biz/\n"
"X-Poedit-KeywordsList: _:1;gettext:1;dgettext:2;ngettext:1,2;dngettext:2,3;"
"__:1;_e:1;_c:1;_n:1,2;_n_noop:1,2;_nc:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
"_x:1,2c;_ex:1,2c;_nx:1,2,4c;_nx_noop:1,2,3c;_n_js:1,2;_nx_js:1,2,3c;"
"esc_attr__:1;esc_html__:1;esc_attr_e:1;esc_html_e:1;esc_attr_x:1,2c;"
"esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
"X-Poedit-Basepath: ../\n"
"X-Textdomain-Support: yes\n"
"X-Poedit-SearchPath-0: .\n"
"X-Loco-Target-Locale: sr_RS"
#. URI of the plugin
msgid "http://wordpress.org/plugins/svg-support"
msgstr ""
#: ../admin/plugin-action-meta-links.php:32
msgid "$25 Free Credit from GoWebben"
msgstr ""
#: ../admin/svgs-settings-page.php:57
msgid "Output JS in Footer?"
msgstr ""
#: ../admin/svgs-settings-page.php:62
msgid ""
" Normally, scripts are placed in <code>head</code> of the HTML document. If "
"this parameter is true, the script is placed before the closing "
"<code>body</code> tag. This requires the theme to have the "
"<code>wp_footer()</code> template tag in the appropriate place."
msgstr ""
#: ../admin/svgs-settings-page.php:68
msgid "Automatically insert class?"
msgstr ""
#: ../admin/svgs-settings-page.php:73
msgid ""
" Checking this will make sure that either the default class or the custom "
"one you set below is inserted into the style attributes of <code>img</code> "
"tags when you insert images. Additionally, it will remove all of the default "
"WordPress classes."
msgstr ""
#: ../admin/svgs-settings-page.php:112
msgid "Please Note:"
msgstr ""
#: ../admin/svgs-settings-page.php:113
msgid ""
"- You will need to set your own height and width in your CSS for SVG files "
"to display correctly."
msgstr ""
#: ../admin/svgs-settings-page.php:114
msgid ""
"- Your uploaded image needs to be an SVG file for this plugin to replace the "
"img tag with the inline SVG code. It will not create SVG files for you."
msgstr ""
#: ../admin/svgs-settings-page.php:131
msgid "Plugin Features"
msgstr ""
#: ../admin/svgs-settings-page.php:145
msgid "About The Plugin"
msgstr ""
#: ../admin/svgs-settings-page.php:157
msgid "GoWebben Hosting"
msgstr ""
#: ../admin/svgs-settings-page.php:159
msgid "Claim your FREE $25 credit from"
msgstr ""
#: ../admin/svgs-settings-page.php:159
msgid ""
"No catch, just free credit for using this plugin! It will be applied "
"automatically using the link provided, but in any case you can simply use "
"code: SVGSUPPORT during checkout."
msgstr ""
msgid "SVG Support"
msgstr "SVG Podrška"
msgid ""
"Allow SVG file uploads using the WordPress Media Library uploader plus "
"direct styling of SVG elements using CSS."
msgstr ""
"Aktivirajte učitavanje SVG datoteka uz pomoć WordPress Media Library "
"uploader-a i direktno stilizovanje SVG elemenata uz pomoć CSS-a."
msgid "Benbodhi"
msgstr "Benbodhi"
msgid "http://benbodhi.com"
msgstr "http://benbodhi.com"
#: ../admin/admin-init.php:15
msgid "SVG Support Options and Instructions"
msgstr "SVG opcije podrške i uputstva"
#: ../admin/admin-init.php:29
msgid "You can't play with this."
msgstr "Ne možete se igrati ovim."
#: ../admin/plugin-action-meta-links.php:30
msgid "Get Support"
msgstr "Obezbedite podršku"
#: ../admin/plugin-action-meta-links.php:31
msgid "Donate to author"
msgstr "Donirajte autoru"
#: ../admin/svgs-settings-page.php:4
msgid "SVG Support Settings and Usage"
msgstr "SVG postavke podrške i upotreba"
#: ../admin/svgs-settings-page.php:12
msgid "Introduction"
msgstr "Uvod"
#: ../admin/svgs-settings-page.php:15
msgid ""
"When using SVG images on your WordPress site, it can be hard to style "
"elements within the SVG using CSS. <strong>Now you can, easily!</strong>"
msgstr ""
"Kad koristite SVG slike na svom WordPress sajtu, može vam biti teško da "
"stilizujete elemente u SVG-u uz pomoć CSS-a. <strong>Sad to možete uraditi s "
"lakoćom!</strong>"
#: ../admin/svgs-settings-page.php:16
msgid ""
"This plugin not only provides SVG Support like the name says, it also allows "
"you to easily embed your full SVG file's code using a simple IMG tag. By "
"adding the class <code>style-svg</code> to your IMG elements, this plugin "
"dynamically replaces any IMG elements containing the <code>style-svg</code> "
"class with your complete SVG."
msgstr ""
"Ovaj plugin ne obezbeđuje samo SVG podršku, kao što mu ime kaže, već vam "
"omogućava i da s lakoćom ugradite svoj puni kod SVG datoteke uz pomoć "
"jednostavne IMG oznake. Dodavanjem klase <code>style-svg</code> svojim IMG "
"elementima, ovaj plugin dinamički zamenjuje bilo koje IMG elemente koji "
"sadrže <code>style-svg</code klasu vašim kompletnim SVG-om."
#: ../admin/svgs-settings-page.php:17
msgid ""
"The main purpose of this is to allow styling of SVG elements. Usually your "
"styling options are restricted when using <code>embed</code>, "
"<code>object</code> or <code>img</code> tags alone."
msgstr ""
"Osnovna svrha ovoga je da omogući stilizovanje SVG elemenata. Obično su "
"opcije stilizovanja ograničene ako koristite samo oznake: <code>embed</code>,"
" <code>object</code> or <code>img</code>."
#: ../admin/svgs-settings-page.php:34
msgid "Settings"
msgstr "Postavke"
#: ../admin/svgs-settings-page.php:46
msgid "Restrict to Administrators"
msgstr "Ograniči administratorima"
#: ../admin/svgs-settings-page.php:51 ../admin/svgs-settings-page.php:62 ..
#: admin/svgs-settings-page.php:73
msgid "Yes"
msgstr "Da"
#: ../admin/svgs-settings-page.php:51
msgid " Restricts SVG upload priveledges to Administrators."
msgstr "Ograničava privilegije SVG učitavanja administratorima."
#: ../admin/svgs-settings-page.php:78
msgid "CSS Class to target"
msgstr "CSS meta za ciljanje"
#: ../admin/svgs-settings-page.php:81
msgid ""
"The default target class is <code>style-svg</code>. You can change it to "
"your own class such as <code>my-class</code> by typing it here.<br />Leave "
"blank to use the default class."
msgstr ""
"Podrazumevana ciljna klasa je <code>style-svg</code>. Možete je promeniti u "
"svoju klasu, kao što je <code>my-class</code> tako što ćete je ukucati ovde."
"<br /> Ostavite prazno polje da biste koristili podrazumevanu klasu."
#: ../admin/svgs-settings-page.php:87
msgid "Save Changes"
msgstr "Sačuvaj izmene"
#: ../admin/svgs-settings-page.php:98
msgid "Usage"
msgstr "Upotreba"
#: ../admin/svgs-settings-page.php:101
msgid "You can simply upload SVG images to your media library like any other file."
msgstr ""
"Jednostavno, možete učitati SVG slike u svoju biblioteku medija kao i bilo "
"koju drugu datoteku."
#: ../admin/svgs-settings-page.php:102
msgid ""
"Now, embed your SVG image like a standard image with the addition of adding "
"the class <code>style-svg</code> (or your custom class from above) to any "
"IMG tags that you want this plugin to swap out with your actual SVG code."
msgstr ""
"Sada ugradite svoju SVG sliku kao standardnu sliku uz dodatak klase "
"<code>style-svg</code> (ili svoje prilagođene navedene klase) u bilo koju od "
"IMG oznaka koju želite da ovaj plugin zameni vašim pravim SVG kodom."
#: ../admin/svgs-settings-page.php:103
msgid "For example:"
msgstr "Na primer:"
#: ../admin/svgs-settings-page.php:106
msgid "or"
msgstr "ili"
#: ../admin/svgs-settings-page.php:109
msgid ""
"The whole IMG tag element will now be dynamically replaced by the actual "
"code of your SVG, making the inner content targetable."
msgstr ""
"Sada će ceo IMG element oznake biti dinamički zamenjen pravim kodom ili "
"vašim SVG-om, što znači da će unutrašnji sadržaj biti raspoloživ za ciljanje."
#: ../admin/svgs-settings-page.php:110
msgid "This allows you to target elements within your SVG using CSS."
msgstr "Omogućava vam da ciljate elemente u svom SVG-u koristeći CSS."
#: ../admin/svgs-settings-page.php:134
msgid "SVG Support for your media library"
msgstr "SVG podrška za vaše biblioteke medija"
#: ../admin/svgs-settings-page.php:135
msgid "Style SVG elements directly using CSS"
msgstr "Stilizuj SVG elemente direktno koristeći CSS"
#: ../admin/svgs-settings-page.php:136
msgid "Restrict to Administrators only"
msgstr "Ograniči samo za administratore"
#: ../admin/svgs-settings-page.php:137
msgid "Extremely Simple To Use"
msgstr "Izuzetno jednostavan za upotrebu"
#: ../admin/svgs-settings-page.php:147
msgid "You can read about this plugin in detail on"
msgstr "O ovom plugin-u detaljnije možete pročitati na:"
#: ../admin/svgs-settings-page.php:147
msgid "The WordPress Plugin Repository"
msgstr "WordPress Plugin Repository"
#: ../admin/svgs-settings-page.php:148
msgid "Need help?"
msgstr "Potrebna vam je pomoć?"
#: ../admin/svgs-settings-page.php:148
msgid "Visit Support"
msgstr "Posetite podršku"
#: ../admin/svgs-settings-page.php:149
msgid "Buy Benbodhi a Beer &rarr;"
msgstr "Kupite Benbodhi-ju pivo &rarr;"
#: ../admin/svgs-settings-page.php:150
msgid "from"
msgstr "od"

View File

@@ -0,0 +1,266 @@
# Loco Gettext template
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: SVG Support 2.2.3.1\n"
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/svg-support\n"
"POT-Creation-Date: 2016-05-16 20:19:06+00:00\n"
"POT-Revision-Date: Mon May 16 2016 13:53:21 GMT-0700 (PDT)\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Benbodhi <wp@benbodhi.com>\n"
"Language-Team: Benbodhi <wp@benbodhi.com>\n"
"Language: \n"
"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Poedit-SourceCharset: UTF-8\n"
"X-Poedit-Basepath: .\n"
"X-Poedit-SearchPath-0: ..\n"
"X-Poedit-KeywordsList: _:1;gettext:1;dgettext:2;ngettext:1,2;dngettext:2,3;"
"__:1;_e:1;_c:1;_n:1,2;_n_noop:1,2;_nc:1,2;__ngettext:1,2;__ngettext_noop:1,2;"
"_x:1,2c;_ex:1,2c;_nx:1,2,4c;_nx_noop:1,2,3c;_n_js:1,2;_nx_js:1,2,3c;"
"esc_attr__:1;esc_html__:1;esc_attr_e:1;esc_html_e:1;esc_attr_x:1,2c;"
"esc_html_x:1,2c;comments_number_link:2,3;t:1;st:1;trans:1;transChoice:1,2\n"
"X-Generator: Loco - https://localise.biz/"
#. #-#-#-#-# plugin.pot (SVG Support 2.2.3.1) #-#-#-#-#
#. Plugin Name of the plugin/theme
msgid "SVG Support"
msgstr ""
#. URI of the plugin
msgid "http://wordpress.org/plugins/svg-support"
msgstr ""
#. Description of the plugin/theme
msgid ""
"Allow SVG file uploads using the WordPress Media Library uploader plus "
"direct styling of SVG elements using CSS."
msgstr ""
#. Author of the plugin/theme
msgid "Benbodhi"
msgstr ""
#. Author URI of the plugin/theme
msgid "http://benbodhi.com"
msgstr ""
#: ../admin/admin-init.php:15
msgid "SVG Support Options and Instructions"
msgstr ""
#: ../admin/admin-init.php:29
msgid "You can't play with this."
msgstr ""
#: ../admin/plugin-action-meta-links.php:30
msgid "Get Support"
msgstr ""
#: ../admin/plugin-action-meta-links.php:31
msgid "Donate to author"
msgstr ""
#: ../admin/plugin-action-meta-links.php:32
msgid "$25 Free Credit from GoWebben"
msgstr ""
#: ../admin/svgs-settings-page.php:4
msgid "SVG Support Settings and Usage"
msgstr ""
#: ../admin/svgs-settings-page.php:12
msgid "Introduction"
msgstr ""
#: ../admin/svgs-settings-page.php:15
msgid ""
"When using SVG images on your WordPress site, it can be hard to style "
"elements within the SVG using CSS. <strong>Now you can, easily!</strong>"
msgstr ""
#: ../admin/svgs-settings-page.php:16
msgid ""
"This plugin not only provides SVG Support like the name says, it also allows "
"you to easily embed your full SVG file's code using a simple IMG tag. By "
"adding the class <code>style-svg</code> to your IMG elements, this plugin "
"dynamically replaces any IMG elements containing the <code>style-svg</code> "
"class with your complete SVG."
msgstr ""
#: ../admin/svgs-settings-page.php:17
msgid ""
"The main purpose of this is to allow styling of SVG elements. Usually your "
"styling options are restricted when using <code>embed</code>, "
"<code>object</code> or <code>img</code> tags alone."
msgstr ""
#: ../admin/svgs-settings-page.php:34
msgid "Settings"
msgstr ""
#: ../admin/svgs-settings-page.php:46
msgid "Restrict to Administrators"
msgstr ""
#: ../admin/svgs-settings-page.php:51 ../admin/svgs-settings-page.php:62 ..
#: /admin/svgs-settings-page.php:73
msgid "Yes"
msgstr ""
#: ../admin/svgs-settings-page.php:51
msgid " Restricts SVG upload priveledges to Administrators."
msgstr ""
#: ../admin/svgs-settings-page.php:57
msgid "Output JS in Footer?"
msgstr ""
#: ../admin/svgs-settings-page.php:62
msgid ""
" Normally, scripts are placed in <code>head</code> of the HTML document. If "
"this parameter is true, the script is placed before the closing "
"<code>body</code> tag. This requires the theme to have the "
"<code>wp_footer()</code> template tag in the appropriate place."
msgstr ""
#: ../admin/svgs-settings-page.php:68
msgid "Automatically insert class?"
msgstr ""
#: ../admin/svgs-settings-page.php:73
msgid ""
" Checking this will make sure that either the default class or the custom "
"one you set below is inserted into the style attributes of <code>img</code> "
"tags when you insert images. Additionally, it will remove all of the default "
"WordPress classes."
msgstr ""
#: ../admin/svgs-settings-page.php:78
msgid "CSS Class to target"
msgstr ""
#: ../admin/svgs-settings-page.php:81
msgid ""
"The default target class is <code>style-svg</code>. You can change it to "
"your own class such as <code>my-class</code> by typing it here.<br />Leave "
"blank to use the default class."
msgstr ""
#: ../admin/svgs-settings-page.php:87
msgid "Save Changes"
msgstr ""
#: ../admin/svgs-settings-page.php:98
msgid "Usage"
msgstr ""
#: ../admin/svgs-settings-page.php:101
msgid "You can simply upload SVG images to your media library like any other file."
msgstr ""
#: ../admin/svgs-settings-page.php:102
msgid ""
"Now, embed your SVG image like a standard image with the addition of adding "
"the class <code>style-svg</code> (or your custom class from above) to any "
"IMG tags that you want this plugin to swap out with your actual SVG code."
msgstr ""
#: ../admin/svgs-settings-page.php:103
msgid "For example:"
msgstr ""
#: ../admin/svgs-settings-page.php:106
msgid "or"
msgstr ""
#: ../admin/svgs-settings-page.php:109
msgid ""
"The whole IMG tag element will now be dynamically replaced by the actual "
"code of your SVG, making the inner content targetable."
msgstr ""
#: ../admin/svgs-settings-page.php:110
msgid "This allows you to target elements within your SVG using CSS."
msgstr ""
#: ../admin/svgs-settings-page.php:112
msgid "Please Note:"
msgstr ""
#: ../admin/svgs-settings-page.php:113
msgid ""
"- You will need to set your own height and width in your CSS for SVG files "
"to display correctly."
msgstr ""
#: ../admin/svgs-settings-page.php:114
msgid ""
"- Your uploaded image needs to be an SVG file for this plugin to replace the "
"img tag with the inline SVG code. It will not create SVG files for you."
msgstr ""
#: ../admin/svgs-settings-page.php:131
msgid "Plugin Features"
msgstr ""
#: ../admin/svgs-settings-page.php:134
msgid "SVG Support for your media library"
msgstr ""
#: ../admin/svgs-settings-page.php:135
msgid "Style SVG elements directly using CSS"
msgstr ""
#: ../admin/svgs-settings-page.php:136
msgid "Restrict to Administrators only"
msgstr ""
#: ../admin/svgs-settings-page.php:137
msgid "Extremely Simple To Use"
msgstr ""
#: ../admin/svgs-settings-page.php:145
msgid "About The Plugin"
msgstr ""
#: ../admin/svgs-settings-page.php:147
msgid "You can read about this plugin in detail on"
msgstr ""
#: ../admin/svgs-settings-page.php:147
msgid "The WordPress Plugin Repository"
msgstr ""
#: ../admin/svgs-settings-page.php:148
msgid "Need help?"
msgstr ""
#: ../admin/svgs-settings-page.php:148
msgid "Visit Support"
msgstr ""
#: ../admin/svgs-settings-page.php:149
msgid "Buy Benbodhi a Beer &rarr;"
msgstr ""
#: ../admin/svgs-settings-page.php:150
msgid "from"
msgstr ""
#: ../admin/svgs-settings-page.php:157
msgid "GoWebben Hosting"
msgstr ""
#: ../admin/svgs-settings-page.php:159
msgid "Claim your FREE $25 credit from"
msgstr ""
#: ../admin/svgs-settings-page.php:159
msgid ""
"No catch, just free credit for using this plugin! It will be applied "
"automatically using the link provided, but in any case you can simply use "
"code: SVGSUPPORT during checkout."
msgstr ""

View File

@@ -0,0 +1,675 @@
=== SVG Support ===
Contributors: Benbodhi
Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=Z9R7JERS82EQQ
Tags: svg, vector, safe svg, sanitization, mime type
Requires at least: 5.8
Tested up to: 6.7.3
Requires PHP: 7.4
Stable tag: 2.5.14
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Securely upload SVG files to your media library, with built-in sanitization and advanced features for styling and animation.
== Description ==
**The complete SVG solution for WordPress - secure, flexible, and easy to use.**
SVG Support enables secure SVG uploads with powerful features for both basic users and developers:
✨ **Key Features**:
- Secure SVG uploads with automatic sanitization
- Inline rendering for direct CSS/JS manipulation
- File size optimization through minification
- Role-based access control
- Advanced developer options
- Multisite compatible
- Full Block Editor (Gutenberg) compatibility
🔒 **Security First**:
- Built-in sanitization removes potentially harmful code
- Role-based upload restrictions
- Comprehensive MIME type validation
🎨 **Designer Friendly**:
- Direct styling of SVG elements
- Animation support
- Custom class targeting
- Automatic dimension handling
💻 **Developer Ready**:
- Advanced mode for additional features
- REST API support
- Gutenberg compatible
- Extensive hooks and filters
== Usage ==
**Basic Usage**:
- First, install and activate SVG Support via your WordPress dashboard
- Upload SVG files to your media library like any other image
- Works seamlessly with Image blocks, Cover blocks and featured images
**Advanced Usage**:
- Enable "Advanced Mode" for minification and inline rendering
- Customize with hooks and filters for tailored functionality
**Block Editor Usage**:
- Use Advanced Mode to enable inline rendering:
- Add the `"style-svg"` class to Image blocks
- Add the `"style-svg"` class to Cover blocks to render SVG backgrounds inline
- Use "Skip Nested SVGs" setting to control inline rendering of SVGs within Cover blocks
**Classic Editor Usage**:
- Use Advanced Mode to add the `"style-svg"` class to `<img>` tags for inline rendering
- Enable "Auto Insert Class" option for automatic class insertion in Classic Editor
**Common Issues & Solutions**:
- SVG not displaying? Ensure dimensions are set in CSS.
- Need help? Use the support tab and I will do my best to assist you.
== Spin up a test site ==
With a single click, you can spin up a completely free test site to test SVG Support using TasteWP! No sign up, no cards, nothing! How cool is that? Give it a go:
[Click Here to spin up a test site in seconds](https://tastewp.com/new?pre-installed-plugin-slug=svg-support&redirect=options-general.php%3Fpage%3Dsvg-support&ni=true)
== Security ==
SVG Support prioritizes security with automatic sanitization and role-based restrictions. Only trusted users should have upload permissions. Configure settings to balance functionality and security.
== Feedback ==
I'm open to your [suggestions and feedback](mailto:wp@benbodhi.com) - Thanks for using SVG Support!
Follow [@SVGSupport](https://twitter.com/svgsupport) on Twitter
Follow [@benbodhi](https://twitter.com/benbodhi) on Twitter
Follow [@benbodhi](https://warpcast.com/benbodhi) on Warpcast
*Note:* I hope you like this plugin! Please take a moment to [rate it](https://wordpress.org/support/view/plugin-reviews/svg-support?filter=5#postform).
== Development & Contributing ==
The development version of SVG Support is maintained on GitHub. Feel free to contribute:
* Submit bug reports or feature suggestions: [GitHub Issues](https://github.com/benbodhi/svg-support/issues)
* Contribute code via [Pull Requests](https://github.com/benbodhi/svg-support/pulls)
* Development repository: [GitHub](https://github.com/benbodhi/svg-support)
== Translations ==
Contribute translations [here](https://translate.wordpress.org/projects/wp-plugins/svg-support). New to translating? Check the [Translator Handbook](https://make.wordpress.org/polyglots/handbook/tools/glotpress-translate-wordpress-org/).
== Frequently Asked Questions ==
= SVG not rendering inline since 2.3 update =
Ensure "Advanced Mode" is enabled in Settings > SVG Support.
= How do I disable the Javascript on the front end if I am not using inline SVG? =
Disable "Advanced Mode" in the settings.
= I'm trying to use SVG in the customizer but it's not working. =
To allow SVG to work in the customizer, you will need to modify/add some code in your child theme's function file. [Here is a great tutorial](https://thebrandid.com/using-svg-logos-wordpress-customizer/) on how to do that. The important part is:
`
'flex-width' => true
'flex-height' => true
`
= How do I add animation to my SVG? =
You will need to edit your SVG file in a code editor so you can add CSS classes to each element you need to target within the SVG. Make sure that your IMG tag is being swapped out for your inline SVG and then you can use CSS or JS to apply animations to elements within your SVG file.
= Why is SVG Support not working in multisite? =
If you installed multisite prior to WordPress 3.5, then you will need to remove your ms-files. Here is a couple of resources to help you: [Dumping ms-files](http://halfelf.org/2012/dumping-ms-files/) [Removing ms-files after 3.5](https://www.yunomie.com/2298/removing-ms-files-php-after-upgrading-an-existing-multisite-installation-to-3-5/).
= Why is my SVG not working in Visual Composer? =
If you are using SVG Support with Visual Composer or any other page builders, you will need to make sure that you can add your own class to the image. The easiest way to do this is by using a simple text or code block in the builder to put your image code in to. Additionally, there is now a setting to force all SVG files to be rendered inline.
= How do I get this to work with the Media Library Assistant plugin? =
You need to add the mime type for svg and svgz to: "MLA Settings > Media Library Assistant > Uploads (tab)" and then it works.
== Screenshots ==
1. Basic Settings
2. Advanced Settings
3. Featured Image checkbox to render SVG inline
4. SVG used in WP native Image Widget
5. Inline SVG in the front end markup
6. Help tab - Overview
7. Help tab - The Settings
8. Help tab - Standard Usage
9. Help tab - Render SVG Inline (advanced usage)
91. Help tab - Featured Images
92. Help tab - Animation
== Changelog ==
= 2.5.14 =
* **Security Enhancements**:
- Remove default roles from the sanitizer bypass settings
* **Fixes**:
- More comprehensive upload checks, allowing generator tags and comment patterns
* **Performance Improvements**:
- Cleanup duplicate inline_featured_image meta entries more efficiently
- Remove inline_featured_image meta entries that aren't explicitly set to 1 (enabled)
- Don't store inline_featured_image meta for posts that previously had it enabled but don't anymore
* **General Updates**:
- Restructured settings layout
- Better cleanup on uninstall when delete plugin data is selected
= 2.5.13 =
* **Code Improvements**:
- Better PHP 8.3 compatibility - added null checks to prevent deprecated warnings in PHP 8.3
= 2.5.12 =
* **General Updates**:
- Added blueprint.json for the live preview feature on wordpress.org
* **Fixes**:
- Fixed mime type check that was restricting SVG uploads without the XML tag in PHP 7.4
= 2.5.11 =
* **Security Enhancement**
- Added more effective handling of sanitization for REST API uploads
= 2.5.10 =
* **Fixes**:
- Fixed issue with upload checks preventing plugin uploads
= 2.5.9 =
* **New Features**:
- Added new Advanced Mode setting "Skip Nested SVGs" to control inlining of SVGs within containers (for example: nested SVGs in Gutenberg Cover blocks)
- Added proper multisite support for SVG uploads across subsites
- Added network administrator support for SVG uploads on all subsites
* **Security Enhancements**:
- Updated DOMPurify library to version 2.5.8
- Updated enshrined/svg-sanitize to version 0.21.0
- Added nonce verification for non-REST uploads to prevent CSRF attacks
- Improved MIME type validation for SVG files
- Enhanced file content validation to ensure only valid SVG files are processed
- Moved security checks earlier in the upload process for better efficiency
- Updated and improved sanitization options for both frontend and admin
* **Code Improvements**:
- Changed synchronous XMLHttpRequest to asynchronous in vanilla JS version to improve performance and remove Chrome deprecation warnings
- Removed console logging statements from JavaScript files for cleaner browser console
- Reorganized upload validation flow for better performance
- Added proper error messages for failed security checks
- Improved handling of REST API uploads
- Enhanced code documentation and inline comments
- Added proper plugin asset handling and alt text for admin images
- Enhanced multisite compatibility with proper role and capability checks
- Added network-level upload permission validation
- Added AJAX hooks for featured image inline toggle
- Enqueue minified Gutenberg filters script instead of expanded version
- Added better version update handling
* **Fixes**:
- PHP Warning about undefined array key "css_target" in admin init.php
- Fixed "not allowed to upload this file type" error on multisite installations
- Fixed duplicate meta entries for inline featured images preventing post saves
- Added automatic cleanup of duplicate meta entries during plugin update
- Improved handling of featured image meta to prevent duplicate entries
- Updated and refactored Gutenberg featured image checkbox to use modern React hooks instead of deprecated withState
- Fixed missing file path in SVG attachment metadata causing issues with WPML Media Translation
- Fixed jQuery dependency only being required when not using vanilla JS option
* **General Updates**:
- Updated security documentation
- Refined error messaging for better user experience
= 2.5.8 =
* **Security Enhancements**:
- Improved sanitization of SVG uploads and attachments for enhanced security.
- Ensured all output in the admin settings page is properly escaped.
- Replaced direct file handling functions with WordPress APIs for better security and compatibility.
- Improved translation support with added translators' comments and ordered placeholders.
* **Admin Interface Improvements**:
- Updated admin-init.php with better escaping practices and enhanced security for the settings page.
- Added error logging to SVG processing to assist with debugging without disrupting the user experience.
* **Performance and Compatibility**:
- Updated enqueue functions to ensure scripts and styles are loaded efficiently with proper dependencies.
- Improved metadata handling for SVGs to prevent issues in the Media Library and with ACF integration.
- Optimized nonce verification and meta updates in the featured image functions to prevent unnecessary database writes.
* **General Code Improvements**:
- Refactored code to reduce redundancy and improve maintainability.
- Added detailed inline documentation for better code clarity and future development.
* **Experimental Integration with WP All Import**:
- Introduced integration with WP All Import for experimental SVG handling during imports.
- SVG files imported via WP All Import are sanitized, and their metadata is generated and updated correctly.
- Added error logging to track issues during SVG import processing.
- **Note**: This feature is experimental and commented out in the main plugin file for now. Feel free to uncomment the include lines to test it out, but please ensure you back up your data first.
= 2.5.7 =
* Compatibility with newer versions of php.
= 2.5.6 =
* Addressed some security concerns.
= 2.5.5 =
* More error fixes and general clean up.
= 2.5.4 =
* Fixed errors.
= 2.5.3 =
* Fixed fatal php error.
= 2.5.2 =
* Added some defaults for better security by default.
= 2.5.1 =
* Added missing quotes in uninstall.php.
= 2.5 =
* Cleaned up spelling mistakes and general formatting.
* Addressed security concern.
* Added more sanitization options - frontend and admin both supported.
* Added support for SVG minification.
* Added ability to choose jQuery or vanilla JS.
* Added DB cleanup on uninstall.
* Fixed dimensions fallback.
= 2.4.2 =
* Fixed srcset warning for some premium themes.
* Fixed original IMG IDs not getting preserved on replacement.
* Removed some rogue text from featured image box.
= 2.4.1 =
* Fixed issue causing WP-CLI to break.
= 2.4 =
* NEW FEATURE: Added optional SVG sanitization.
* NEW FEATURE: Added optional SVG minification.
* Added inline SVG checkbox to Gutenberg featured image.
* Better Gutenberg support in general.
* Modified class targeting to allow inline rendering of nested SVGs (any level deep) when you can't set the IMG class directly.
* Modified JS to use vanilla JS instead of jQuery.
* Fixed accessibility issues on settings page.
* Fixed dimensions metadata issue.
* Fixed division by 0 issue when SVG had no width or height set.
* Fixed featured image spacing issue in both classic and block editor.
* Bumped required PHP version.
* Removed obsolete admin notice.
* Removed srcset for SVG files.
* Removed directory name from filepath metadata.
= 2.3.21 =
* Fixed featured image SVG overlapping container.
= 2.3.20 =
* Fixed admin setting not being escaped when output.
= 2.3.19 =
* Fixed PHP Warning from localize_script in functions/enqueue.php.
* Added a check for SRC attribute in js/svgs-inline.js.
= 2.3.18 =
* Updated author URL in main plugin file.
* Updated donate links.
* Cleaned up plugin action meta links and settings page.
* Rolled back a fix in functions/attachment.php due to it removing meta from other attachments.
= 2.3.17 =
* Added setting to choose whether to load frontend CSS or not.
= 2.3.16 =
* Fix for files that have the XML declaration.
* Fix for PHP warnings from image widget.
* Some small CSS changes to the frontend when displaying SVG media attachments.
= 2.3.15 =
* Had to roll back a recent PHP warnings fix due to it breaking some theme compatibility.
= 2.3.14 =
* Fixed: Fatal error in some cases when removing old option from the database.
= 2.3.13 =
* Fixed: PHP warnings and notices from the image widget when using SVG files and wp_debug was on.
* Modified: Better front end CSS for displaying SVG attachments, both as images and inline.
* Removed: DB entry for deprecated admin notice.
= 2.3.12 =
* New: Native "Help" tab on the SVG Support settings page.
* New: Wrapped the inline JS in a function so you can call it at will using `bodhisvgsInlineSupport();`.
* Modified: Admin CSS to target SVG src only.
* Modified: SVG Support settings page - cleaned it up a little.
* Removed: Version update admin notice.
= 2.3.11 =
* New: Feature to use expanded JS file rather than the minified/compressed version (useful for bundling and minifying using external caching plugins).
* New: Force Inline SVG option. This feature allows you to force all of your SVG files to be rendered inline regardless of classes applied. Addresses issues where you can't add your own class to an image for some reason. For example, some page builder image elements. Also addresses changing your target class in the settings and needing to change all of your already embedded media, allowing you to simply force render rather than update all of the classes.
* Modified the readme file and descriptions a bit.
* Refined some code in functions/featured-image.php line 69 to address a warning.
* Updated "Requires at least" tag to 4.8 (though it should still work in older versions, there was issues with core during the 4.7 phase and it's time for you to update anyway).
= 2.3.10 =
* Fixed missing links in settings page.
= 2.3.9 =
* Modified plugin action meta link for settings page.
* Changed some language throughout the plugin.
* Added recommendation for ShortPixel Image Optimization.
* Added conditional to check post type supports thumbnail before setting meta data.
= 2.3.8 =
* Added some CSS to make sure featured images show on WooCommerce products, Sensei Courses and Lessons.
* Fix: Auto insert class setting was stripping featured image HTML in some cases.
= 2.3.7 =
* Added WP version check to wrap mime fix function needed for WP v4.7.1 - v4.7.2.
* Moved mime fix into mime type file.
* Modified admin notice code to make it neater.
* Fix: attachment-modal.php issues with some servers and external SVG files (props to @abstractourist & @malthejorgensen for providing fixes, as I could not consistently reproduce the issue).
* Compatibility: Changed a line to provide wider compatibility, specifically for WordPress Bedrock on a LEMP stack.
* Compatibility: Added another snippet to the JS to support IE11 (apparently people still use IE).
* Added more FAQ's.
= 2.3.6 =
* New: Added polyfill to make svgs-inline.js work with older browsers.
* New: Section to leave reviews on settings page.
* Removed: Redundant one time upgrade activate code.
* Fix: Errors reported on activation and on the settings page - [Related Support Thread](https://wordpress.org/support/topic/error-on-plugin-settings-page/).
= 2.3.5 =
* Revision and modification of the thumbnail display code.
= 2.3.4 =
* Fix: Fatal error for some because a function wasn't prefixed.
= 2.3.3 =
* Fix: Missing arguments PHP warnings from new attribute control file.
* Update settings page text.
= 2.3.2 =
* Modified the attribute control code that auto inserts our class to only apply to SVG files.
= 2.3.1 =
* Fix: Fatal error in some cases due to admin notice.
= 2.3 =
* New Feature - Advanced Mode: allows you to turn off the advanced features and simply upload SVG files like normal images. This addition also enables users to turn off the script added on front end by leaving Advanced Mode unchecked.
* New Feature - Featured Image Support: If your featured image is SVG, once the post is saved you will see a checkbox to render the SVG inline (advanced mode only).
* Performance - Stop inlining JS from running if image source is not SVG.
* Added new stylesheet for settings page.
* Moved SCSS files to their own folder.
* Changed donate link so I can track it and properly thank you for your generous donations.
* Added a rating link to the settings and media pages.
* Cleaned up code formatting, added more comments.
* Added a plugin version check.
* Added notice so people are aware they may need to turn on the advanced mode.
= 2.2.5 =
* FIX: Display SVG thumbnails in attachment modals.
= 2.2.4 =
* FIX: Added function to temporarily fix an issue with uploading in WP 4.7.1
= 2.2.32 =
* Changed text domain to match plugin slug for localization.
= 2.2.31 =
* Attempt to fix ability to translate
= 2.2.3 =
* Modified code in svg-support/js/svg-inline.js and svg-support/js/min/svg-inline-min.js to allow JS control of the SVG elements and detect if they have been loaded (IMG tag swapped out). Thanks to [laurosello](https://wordpress.org/support/profile/laurosollero) for this suggestion and code contribution.
* Fixed SVG thumbnails not displaying correctly in list view of the media library.
* Cleaned up the code and comments a bit.
* Added translation for Spanish. Thanks to [Apasionados del Marketing](http://apasionados.es) for the translation.
= 2.2.2 =
* Changed another anonymous function in svg-support/functions/thumbnail-display.php that was causing errors for some.
= 2.2.1 =
* Changed anonymous function in svg-support/functions/thumbnail-display.php line 15 to prevent fatal error in older PHP versions.
= 2.2 =
* Added support to make SVG thumbnails visible in all media library screens.
* Added SVGZ to the mime types.
* Automatically removes the width and height attributes when inserting SVG files.
* Added ability to choose whether the target class is automatically inserted into img tags or not, stripping the default WordPress classes.
* Added ability to choose whether script is output in footer - true or false.
* Blocked direct access to PHP files.
* Added SCSS support using CodeKit - minified CSS + JS files.
* Updated spelling for incorrect function name.
* Changed comment formatting across all files for consistency.
* Added link to $25 Free credit at GoWebben on the settings page.
* Tested in WordPress 4.3.
* Updated Readme file.
= 2.1.7 =
* Tested in WordPress 4.0 and added plugin icons for the new interface.
= 2.1.6 =
* Added missing jQuery dependency in /functions/enqueue.php (pointed out by [walbach](http://wordpress.org/support/profile/waldbach)) - was loading SVG Support JS before jQuery.
= 2.1.5 =
* Added Serbian translation, submitted by Ogi Djuraskovic.
= 2.1.4 =
* Fixed plugin settings link (on plugins page)
* Added more links - Support & Donate
* Modified the settings page a little
* Cleaned up settings page with CSS
* Satisfied my OCD tendencies a little
= 2.1.3 =
* Added plugin_action_links file for custom menus on plugin page.
= 2.1.2 =
* Cleaned up trunk, tags and readme.txt to show correct changelog and update notice.
= 2.1.1 =
* Fixed JS file conditional - worked in local testing but not live.
= 2.1 =
* Updates to language files for localization.
= 2.0 =
* Added an admin settings page with instructions plus options for restricting to admin use only and setting a custom CSS target class.
* Whole plugin completely re-written and re-structured.
* Added option to restrict SVG uploads to administrators only.
* Added field for custom CSS target class.
* Added stylesheet to admin settings page.
= 1.0 =
* Initial Release.
== Upgrade Notice ==
= 2.5.14 =
Better DB handling, better upload checks
= 2.5.13 =
Better PHP 8.3 compatibility (added null checks to prevent deprecated warnings in PHP 8.3)
= 2.5.12 =
Fixes mime type check that was restricting SVG uploads without the XML tag in PHP 7.4
= 2.5.11 =
Security update: added more effective handling of sanitization for REST API uploads
= 2.5.10 =
Fixed issue with upload checks preventing plugin uploads
= 2.5.9 =
Important security update that adds enhanced upload validation, MIME type checking, and CSRF protection. Please backup before updating. No configuration changes required - all security improvements work automatically.
= 2.5.8 =
Improved security, enhanced SVG processing, and updated admin interface. Includes better sanitization and escaping practices. Please take a backup before updating!
= 2.5.7 =
This update addresses issues with newer PHP versions.
= 2.5.6 =
This update addresses some security concerns.
= 2.5.5 =
Updating to 2.5+ Adds new features and addresses a number of earlier issues raised. Please take a backup before updating!
2.5.5 fixes more reported errors in the 2.5 series of updates.
= 2.5.4 =
Updating to 2.5+ Adds new features and addresses a number of earlier issues raised. Please take a backup before updating!
2.5.4 fixes errors in the 2.5 series of updates.
= 2.5.3 =
Updating to 2.5+ Adds new features and addresses a number of earlier issues raised. Please take a backup before updating!
2.5.3 fixes fatal error in 2.5.2.
= 2.5.2 =
Updating to 2.5+ Adds new features and addresses a number of earlier issues raised. Please take a backup before updating!
2.5.2 introduces some defaults for better security.
= 2.5.1 =
2.5 Adds new features and addresses a number of recent issues raised. Please take a backup before updating!
2.5.1 fixes the uninstall file.
= 2.5 =
Adds new features and addresses a number of recent issues raised. Please take a backup before updating!
= 2.4.2 =
2.4.2 fixes srcset issue firing PHP warnings for some themes and original image IDs missing on replacement to inline SVG.
= 2.4.1 =
2.4.1 fixes broken WP-CLI. Now featuring optional SVG sanitization and ability to target nested SVGs! This update contains a lot, please BACKUP YOUR DATABASE AND FILES BEFORE UPDATING!
= 2.4 =
Now featuring optional SVG sanitization and ability to target nested SVGs! This update contains a lot, please BACKUP YOUR DATABASE AND FILES BEFORE UPDATING!
= 2.3.21 =
Fixes featured image display on edit post screen.
= 2.3.20 =
Added more security.
= 2.3.19 =
Quick update to address PHP warnings from localize_script and to add a SRC check.
= 2.3.18 =
General clean up of plugin, testing on latest nightly build plus fixed issue with metadata being removed from non SVG attachments.
= 2.3.17 =
Added a setting to choose whether to load the frontend CSS file or not. It was previously enabled by default, so you may want to flick that on after the update. This allows you to leave it out so your site has one less file to load :)
= 2.3.16 =
This update addresses upload issues, PHP warnings and some frontend CSS changes with attachment display.
= 2.3.15 =
Had to roll back a recent PHP warnings fix due to it breaking some theme compatibility.
= 2.3.14 =
Fixes fatal error in some cases when removing old option from the database.
= 2.3.13 =
Update to address PHP warnings and notices on the image widget when wp_debug is enabled.
= 2.3.12 =
* Inline JS can now be called using `bodhisvgsInlineSupport();`. Added a native help tab and removed the admin update notice. General cleanup of code and settings page. Remember to back up your site before updating.
= 2.3.11 =
* New Features and Fixes: Added "Force Inline SVG" to render all SVG files inline with one click. Option to use an expanded JS version for separate minification with a caching plugin.
= 2.3.10 =
* Fixed missing links in settings page.
= 2.3.9 =
* Cleaned up some code and language, now stores less meta when not needed and added a plugin recommendation for Image Optimization.
= 2.3.8 =
* Adds better support for WooCommerce and Sensei. Fixes issue with featured images not showing up when auto insert class setting is on.
= 2.3.7 =
* Fixes issues with media library not loading for some, attachment-modal errors and adds some wider compatibility.
= 2.3.6 =
* Adds support for older browsers, fixes a couple of seemingly isolated errors reported, removes some redundant code.
= 2.3.5 =
* Modifications to thumbnail display code to prevent output buffer clash with another plugin.
= 2.3.4 =
* Fixes fatal error for some because a function wasn't prefixed.
= 2.3.3 =
* This update fixes some PHP warnings introduced in 2.3.2 and also has updated settings page text.
= 2.3.2 =
* Changes to the way the auto class insert works.
= 2.3.1 =
* Fixes fatal error in some cases due to admin notice in V2.3.
= 2.3 =
IMPORTANT, MAJOR CHANGES, BACKUP BEFORE UPDATING: Users that are inlining SVG will need to make sure "Advanced Mode" is active under "Settings > SVG Support". Your settings should all still be there. Make sure you run a backup before updating just in case!!!
= 2.2.5 =
* Fix to display SVG thumbnails in attachment modals. (NOTE: You can not edit SVG files like other images in WordPress)
= 2.2.4 =
* IMPORTANT: Fixes upload ability in WP 4.7.1
= 2.2.32 =
* Changed text domain to match plugin slug for localization.
= 2.2.31 =
* This release attempts to fix translation issues.
= 2.2.3 =
* Feature - Changed code to allow JS detection if SVG has loaded and ability to control SVG using JS.
* Fix - Thumbnail display in media library list view.
* Added Spanish translation and cleaned up code/comments a bit.
= 2.2.2 =
* Fix - Another change from anonymous function that was triggering errors for some.
= 2.2.1 =
* Minor change to remove anonymous function that triggered a fatal error in older PHP versions.
= 2.2 =
* Significant changes, added functionality, please BACKUP BEFORE UPDATING just in case.
= 2.1.7 =
* Tested in WordPress 4.0 and added plugin icons for the new interface.
= 2.1.6 =
* Important update! Added missing jQuery dependency in /functions/enqueue.php - was loading SVG Support JS before jQuery.
= 2.1.5 =
* Added Serbian translation, submitted by Ogi Djuraskovic.
= 2.1.4 =
* Some more re-arranging, added a few helpful links, updated language files, tended to my OCD a bit.
= 2.1.3 =
* Added a link on the plugins page to the plugin settings page for easy access after install.
= 2.1.2 =
* A little bit of house cleaning, updates to changelog and readme.txt for correct output with current version.
= 2.1.1 =
* Update to conditional in JS file.
= 2.1 =
* Updated language files for localization that were missed in version 2.0.
= 2.0 =
* SVG Support has been completely re-written and re-structured. It now includes an admin settings page with instructions, plus options for restricting to admin use only and setting a custom CSS target class.
= 1.0 =
* Initial Release.

View File

@@ -0,0 +1,398 @@
@-webkit-keyframes iui-fadeIn {
0% {
opacity: 0
}
100% {
opacity: 1
}
}
@-moz-keyframes iui-fadeIn {
0% {
opacity: 0
}
100% {
opacity: 1
}
}
@-ms-keyframes iui-fadeIn {
0% {
opacity: 0
}
100% {
opacity: 1
}
}
@-o-keyframes iui-fadeIn {
0% {
opacity: 0
}
100% {
opacity: 1
}
}
@keyframes iui-fadeIn {
0% {
opacity: 0
}
100% {
opacity: 1
}
}
@-webkit-keyframes iui-fadeOut {
0% {
opacity: 1
}
100% {
opacity: 0
}
}
@-moz-keyframes iui-fadeOut {
0% {
opacity: 1
}
100% {
opacity: 0
}
}
@-ms-keyframes iui-fadeOut {
0% {
opacity: 1
}
100% {
opacity: 0
}
}
@-o-keyframes iui-fadeOut {
0% {
opacity: 1
}
100% {
opacity: 0
}
}
@keyframes iui-fadeOut {
0% {
opacity: 1
}
100% {
opacity: 0
}
}
.dropdown-multiple,
.dropdown-multiple-label,
.dropdown-single {
position: relative
}
.dropdown-multiple-label.active .dropdown-main,
.dropdown-multiple.active .dropdown-main,
.dropdown-single.active .dropdown-main {
display: block;
-webkit-animation: iui-fadeIn .2s ease-in forwards;
-moz-animation: iui-fadeIn .2s ease-in forwards;
-ms-animation: iui-fadeIn .2s ease-in forwards;
-o-animation: iui-fadeIn .2s ease-in forwards;
animation: iui-fadeIn .2s ease-in forwards
}
.dropdown-multiple-label.active .dropdown-display-label:after,
.dropdown-multiple-label.active .dropdown-display:after,
.dropdown-multiple.active .dropdown-display-label:after,
.dropdown-multiple.active .dropdown-display:after,
.dropdown-single.active .dropdown-display-label:after,
.dropdown-single.active .dropdown-display:after {
border-top: none;
border-bottom: 10px solid #999;
border-left: 5px solid transparent;
border-right: 5px solid transparent
}
.dropdown-multiple-label.active .dropdown-display,
.dropdown-multiple-label.active .dropdown-display-label,
.dropdown-multiple.active .dropdown-display,
.dropdown-multiple.active .dropdown-display-label,
.dropdown-single.active .dropdown-display,
.dropdown-single.active .dropdown-display-label {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0
}
.dropdown-display,
.dropdown-display-label {
position: relative;
display: block;
margin-bottom: 0;
font-size: 14px;
line-height: 1.42857143;
vertical-align: middle;
touch-action: manipulation;
cursor: pointer;
user-select: none;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
color: #333;
background-color: #fff
}
.dropdown-display-label:after,
.dropdown-display:after {
content: '';
position: absolute;
border-top: 10px solid #999;
border-left: 5px solid transparent;
border-right: 5px solid transparent;
top: 15px;
right: 8px
}
.dropdown-clear-all {
background-color: #fff;
border: none;
font-size: 22px;
z-index: 999;
color: #999;
position: absolute;
right: 2px;
top: 2px;
display: none;
width: 25px;
height: 30px;
text-align: center;
line-height: 30px;
}
.dropdown-clear-all:focus {
outline: 0
}
.dropdown-clear-all:hover {
color: #ccc;
text-decoration: none;
}
.dropdown-display {
white-space: nowrap;
padding: 6px 20px 6px 12px
}
.dropdown-multiple:hover .dropdown-clear-all,
.dropdown-single:hover .dropdown-clear-all {
display: block
}
.dropdown-display .dropdown-chose-list {
display: inline-block;
vertical-align: middle;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap
}
.dropdown-display .dropdown-chose-list span:before {
content: ','
}
.dropdown-display .dropdown-chose-list span:first-child:before {
content: ''
}
.dropdown-display .placeholder {
display: none
}
.dropdown-display .placeholder:first-child {
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
color: #999;
display: block;
text-indent: 10px;
font-size: 13px;
line-height: 32px
}
.dropdown-display input {
border: 0;
outline: 0
}
.dropdown-display-label {
cursor: text;
padding: 6px 25px 5px 0
}
.dropdown-display-label .dropdown-search {
display: block;
width: 100%;
border: 1px solid #eee;
}
.dropdown-display-label .dropdown-search input {
width: 100%;
}
.dropdown-option.dropdown-chose {
font-weight: bold;
}
.dropdown-display-label input,
.dropdown-display-label input:focus {
border: none;
outline: 0
}
.dropdown-display-label .dropdown-chose-list {
width: 100%;
display: inline-block;
padding: 0 5px
}
.dropdown-display-label .dropdown-chose-list .placeholder {
display: none
}
.dropdown-display-label .dropdown-selected {
position: relative;
margin: 0 5px 5px 0;
padding: 0 20px 0 5px;
border: 1px solid #aaa;
max-width: 100%;
border-radius: 3px;
background-repeat: repeat-x;
color: #333;
cursor: default;
display: inline-block
}
.dropdown-display-label .dropdown-selected .del {
-webkit-appearance: none;
padding: 0;
cursor: pointer;
background: 0 0;
border: 0;
float: right;
line-height: 1;
color: #999;
position: absolute;
right: 3px;
top: 0
}
.dropdown-display-label .dropdown-selected .del:after {
content: '\D7';
font-size: 16px
}
.dropdown-main {
position: absolute;
top: 100%;
left: 0;
z-index: 1010;
width: 100%;
color: #444;
box-sizing: border-box;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 0 0 4px 4px;
box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
margin-top: -1px;
border-top: 0;
padding: 4px 7px;
display: none
}
.dropdown-main ul {
overflow-x: hidden;
overflow-y: auto;
max-height: 240px;
margin: 0;
padding: 0
}
.dropdown-main input {
margin-top: 0;
display: block;
box-sizing: border-box;
height: 30px;
border: 1px solid #ccc;
width: 100%;
text-indent: 5px;
border-radius: 3px
}
.dropdown-main .dropdown-search {
display: block;
padding: 5px 0
}
.dropdown-group {
font-weight: 700
}
.dropdown-group,
.dropdown-option {
margin: 0;
padding-left: 12px;
list-style: none;
line-height: 26px;
word-wrap: break-word
}
.dropdown-option {
cursor: pointer
}
.dropdown-option:focus,
.dropdown-option:hover {
background-color: #efefef;
outline: 0
}
.dropdown-option[disabled] {
color: #ddd;
background-color: #fff;
cursor: not-allowed;
text-decoration: line-through
}
.dropdown-option.dropdown-chose:after {
content: '';
float: right;
width: 10px;
height: 10px;
background: #4AB1E9;
border-radius: 100%;
margin: 8px 5px 0 0
}
.dropdown-maxItem-alert, .dropdown-minItem-alert {
position: absolute;
top: 0;
left: 0;
background-color: #e4e3e2;
width: 100%;
height: 39px;
line-height: 39px;
padding: 0 5px;
border-radius: 5px;
color: #999;
-webkit-animation: iui-fadeIn .2s ease-in forwards;
-moz-animation: iui-fadeIn .2s ease-in forwards;
-ms-animation: iui-fadeIn .2s ease-in forwards;
-o-animation: iui-fadeIn .2s ease-in forwards;
animation: iui-fadeIn .2s ease-in forwards
}

View File

@@ -0,0 +1,21 @@
/**
* Featured Image Display
*
* Fixes the 0px featured image on edit screen
* WooCommerce Product, Sensei Course
*/
body #set-post-thumbnail,
body #postimagediv .inside img[src$=".svg"] {
width: 100%;
}
// Block display of featured image SVG
body .block-editor__container {
.components-panel .editor-post-featured-image__container img[src$='.svg'] {
position: relative;
}
.edit-post-sidebar .components-panel .components-checkbox-control {
margin-top: 10px;
}
}

View File

@@ -0,0 +1,6 @@
/**
* Hide advanced features
*/
.svgs-advanced {
display: none;
}

View File

@@ -0,0 +1,45 @@
/**
* Settings Page
*/
.svgs-version {
font-size: 10px;
margin-left: 7px;
}
.postbox .inside a {
text-decoration: none;
}
h3 {
padding: 0 12px;
}
.help-tab-content h3 {
padding: 0;
}
h3.inner-title {
padding: 0;
font-size: 1.2em;
}
.metabox-holder {
.postbox>h3,
.stuffbox>h3,
h2.hndle,
h3.hndle {
font-size: 1.3em;
font-weight: 600;
}
}
.shortpixel-logo img {
position: absolute;
right: 10px;
bottom: 0;
width: 140px;
}
/**
* Media Library
*/
table.media .column-title .media-icon img {
width: 60px;
// height: 60px;
}

View File

@@ -0,0 +1,17 @@
// .attachment img[src$=".svg"],
// .widget_media_image img[src$=".svg"] {
// width: 100%;
// }
.attachment,
.widget_media_image {
// img[src$=".svg"] {
// width: 100%;
// }
svg {
max-width: 100%;
height: auto;
}
}

View File

@@ -0,0 +1,152 @@
<?php
/*
Plugin Name: SVG Support
Plugin URI: http://wordpress.org/plugins/svg-support/
Description: Upload SVG files to the Media Library and render SVG files inline for direct styling/animation of an SVG's internal elements using CSS/JS.
Version: 2.5.14
Author URI: https://benbodhi.com
Text Domain: svg-support
Domain Path: /languages
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Requires at least: 5.8
Requires PHP: 7.4
Block: true
Copyright 2013 and beyond | Benbodhi (email : wp@benbodhi.com)
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Global variables and constants
*/
global $bodhi_svgs_options;
$bodhi_svgs_options = array(); // Defining global array
define('BODHI_SVGS_VERSION', get_file_data(__FILE__, array('Version' => 'Version'))['Version']);
define('BODHI_SVGS_PLUGIN_FILE', __FILE__); // define the absolute plugin file path
define('BODHI_SVGS_PLUGIN_PATH', plugin_dir_path(__FILE__)); // define the absolute plugin path for includes
define('BODHI_SVGS_PLUGIN_URL', plugin_dir_url(__FILE__)); // define the plugin url for use in enqueue
$bodhi_svgs_options = get_option('bodhi_svgs_settings', array()); // Retrieve our plugin settings
// ensure $bodhi_svgs_options is always an array
if (!is_array($bodhi_svgs_options)) {
$bodhi_svgs_options = [];
update_option('bodhi_svgs_settings', $bodhi_svgs_options);
}
/**
* SVG Sanitizer class
*/
// init svg sanitizer for usage
use enshrined\svgSanitize\Sanitizer;
// svg sanitizer
include( BODHI_SVGS_PLUGIN_PATH . 'vendor/autoload.php' );
// interfaces to enable custom whitelisting of svg tags and attributes
include( BODHI_SVGS_PLUGIN_PATH . 'includes/svg-tags.php' );
include( BODHI_SVGS_PLUGIN_PATH . 'includes/svg-attributes.php' );
// initialize sanitizer
$sanitizer = new Sanitizer();
/**
* Includes - keeping it modular
*/
include( BODHI_SVGS_PLUGIN_PATH . 'admin/admin-init.php' ); // initialize admin menu & settings page
include( BODHI_SVGS_PLUGIN_PATH . 'admin/plugin-action-meta-links.php' ); // add links to the plugin on the plugins page
include( BODHI_SVGS_PLUGIN_PATH . 'functions/mime-types.php' ); // setup mime types support for SVG (with fix for WP 4.7.1 - 4.7.2)
include( BODHI_SVGS_PLUGIN_PATH . 'functions/thumbnail-display.php' ); // make SVG thumbnails display correctly in media library
include( BODHI_SVGS_PLUGIN_PATH . 'functions/attachment.php' ); // make SVG thumbnails display correctly in attachment modals and generate attachment sizes
include( BODHI_SVGS_PLUGIN_PATH . 'functions/enqueue.php' ); // enqueue js & css for inline replacement & admin
include( BODHI_SVGS_PLUGIN_PATH . 'functions/localization.php' ); // setup localization & languages
include( BODHI_SVGS_PLUGIN_PATH . 'functions/attribute-control.php' ); // auto set SVG class & remove dimensions during insertion
include( BODHI_SVGS_PLUGIN_PATH . 'functions/featured-image.php' ); // allow inline SVG for featured images
include( BODHI_SVGS_PLUGIN_PATH . 'functions/meta-cleanup.php' ); // cleanup duplicate meta entries
// Include WP All Import integration only if WP All Import is active
// if ( defined( 'PMXI_VERSION' ) ) {
// include( BODHI_SVGS_PLUGIN_PATH . 'integrations/wp-all-import.php' );
// }
/**
* Handle version updates and migrations
*
* Handles version comparisons for all format types:
* - Single digit versions (1, 2)
* - Zero versions (0, 0.1, 0.5.26)
* - Two-digit versions (1.0, 2.1, 2.5)
* - Three-digit versions (1.5.17, 2.5.9)
* - Fresh installs ('0.0.0')
* - Legacy versions (null, empty, invalid)
*/
function bodhi_svgs_version_updates() {
$stored_version = get_option('bodhi_svgs_plugin_version', '0.0.0');
if (!is_string($stored_version) || empty($stored_version)) {
$stored_version = '0.0.0';
}
// Skip if already at current version
if ($stored_version === BODHI_SVGS_VERSION) {
return;
}
// Store the old version for comparison
$old_version = $stored_version;
// Update to current version
update_option('bodhi_svgs_plugin_version', BODHI_SVGS_VERSION);
// If coming from before 2.5.14, run cleanup
if (version_compare($old_version, '2.5.14', '<')) {
require_once BODHI_SVGS_PLUGIN_PATH . 'functions/meta-cleanup.php';
bodhi_svgs_cleanup_duplicate_meta();
}
}
add_action('admin_init', 'bodhi_svgs_version_updates');
/**
* Defaults for better security in versions >= 2.5
*/
// Enable 'sanitize_svg_front_end' by default
if ( !isset($bodhi_svgs_options['sanitize_svg_front_end']) ) {
$bodhi_svgs_options['sanitize_svg_front_end'] = 'on';
update_option( 'bodhi_svgs_settings', $bodhi_svgs_options );
}
// Allow only admins to upload SVGs by default
if ( !isset($bodhi_svgs_options['restrict']) || $bodhi_svgs_options['restrict'] == "on" ) {
$bodhi_svgs_options['restrict'] = array('administrator');
update_option( 'bodhi_svgs_settings', $bodhi_svgs_options );
}
elseif (isset($bodhi_svgs_options['restrict']) && $bodhi_svgs_options['restrict'] == "none" ) {
$bodhi_svgs_options['restrict'] = array("none");
update_option( 'bodhi_svgs_settings', $bodhi_svgs_options );
}
// By default sanitize on upload for everyone (no bypass roles)
if ( !isset($bodhi_svgs_options['sanitize_on_upload_roles']) ) {
$bodhi_svgs_options['sanitize_on_upload_roles'] = array();
update_option( 'bodhi_svgs_settings', $bodhi_svgs_options );
}
elseif ( isset($bodhi_svgs_options['sanitize_on_upload_roles']) && $bodhi_svgs_options['sanitize_on_upload_roles'] == "none") {
$bodhi_svgs_options['sanitize_on_upload_roles'] = array("none");
update_option( 'bodhi_svgs_settings', $bodhi_svgs_options );
}
/**
* Register activation and deactivation hooks
*/
// Activation Hook
function bodhi_svgs_plugin_activation() {
bodhi_svgs_remove_old_sanitize_setting();
}
register_activation_hook(__FILE__, 'bodhi_svgs_plugin_activation');
// Deactivation Hook
function bodhi_svgs_plugin_deactivation() {
bodhi_svgs_remove_old_sanitize_setting();
}
register_deactivation_hook(__FILE__, 'bodhi_svgs_plugin_deactivation');

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,15 @@
<?php if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
exit;
}
$bodhi_options_on_deletion = get_option( 'bodhi_svgs_settings' );
if ( isset($bodhi_options_on_deletion[ 'del_plugin_data' ]) && $bodhi_options_on_deletion[ 'del_plugin_data' ] === 'on' ) {
// Delete plugin options
delete_option( 'bodhi_svgs_plugin_version' );
delete_option( 'bodhi_svgs_settings' );
// Delete all post meta related to SVG Support
global $wpdb;
$wpdb->delete($wpdb->postmeta, array('meta_key' => 'inline_featured_image'));
}