Half-Elf on Tech

Thoughts From a Professional Lesbian

Author: Ipstenu (Mika Epstein)

  • Prefix or Suffix

    Prefix or Suffix

    I’ve been seeing a lot of a new trend in coding, which stems from boilerplate plugin code, and that is the use of suffixes in function names. This has become increasingly popular in WordPress code and I, for one, am not a fan.

    WordPress Function, What’s Your Function?

    Otto likes to say that well named functions don’t need code comments.

    While optimistic in this day and age of complex code, the basic concept remains quite valid. If you name your functions well, the chances are that they will trigger your contextual memory and you’ll remember what they are, what they do, and why they’re there. To this end, the difference between function activate_pluginname() and function pluginname_activate() is miniscule. Both of those are clearly functions that run on ‘activate’ and that makes perfect sense. We can see the purpose of the function by its name, and that is the majority of Otto’s point. They are well named as they indicate their job. The issue then does not like in the name of the function but in the format of the name of the function.

    Function Name Conflicts

    A majority of the time, my argument for having unique function names is that there are over fifty-thousand plugins out there, and the odds of two of them having the same function name is quite high, for cases when the function name is generic. For example, function my_plugin_init() is not unique in the slightest. Yes, people literally use my_plugin_ as a prefix. That’s not a placeholder. That particular error occurs when people use boilerplates and don’t read the directions clearly. Most state “Search and replace my_plugin with your plugin prefix.”

    Preventing conflicts means it’s incumbent of developers to select unique function names. Now this pressure is alleviated by the use of namespaces and classes, but even those have to be unique to their plugin (or theme). After all, class WordPress is not a great classname.

    Again, in this regard there is very little difference between function activate_pluginname() and function pluginname_activate() in the real world. Both are unlikely to cause conflicts.

    Internal Consistency is Good

    Another aspect of names is that good function names are logical and consistent. Few things pain me more than seeing function pluginname_init() and function pn_admin_init() (where pn is an abbreviation for the plugin name). What I see a great deal with the plugin name as suffix is this hodgepodge of names:

    • init_plugin_name()
    • plugin_name_uninstall()
    • pn_wp_class_list()

    My guess at this point is that any time a particular boilerplate doesn’t specify the name of the function needed, people fall back into old habits. Or rather, they fall back into the recommended habits. You know, a prefix. Consistently named functions make it easier for people to recognize what function belongs to what plugin or theme.

    So why Prefix?

    This takes us to an interesting point. Both function activate_pluginname() and function pluginname_activate() meet the requirement of being well named and unique (and can be consistent). So what actually is the problem here?

    The problem is the future.

    Your code does not exist in a vacuum! Code that will only ever be used on your own server still runs with the other plugins and themes you add, and they could cause a conflict. It’s somewhat trivial to change those things, but it’s not fun and usually it means that you broke something in your live environment.

    • Consistently named functions make it easier to know what function relates to what.
    • Uniquely named functions are easier to find.
    • Well named functions remind you what the function is supposed to do.

    But again, why prefix?

    Remember Who Comes Next

    I do a lot of searches on code in myriad plugins. More than most people involved in WordPress I suspect. I have a very peculiar relationship with plugins, after all. When the core developers want to figure out how ‘well used’ a function is before changing it, I help out by running a search on all the code in the plugin directory. This results in me finding a lot of weirdly named functions that require me to track back through the plugin and find out what it’s really doing. When things are prefixed, this search goes a lot faster.

    Besides just my convenience, when you remember that your code is used by thousands of people, they will have an easier time searching for your code when they have an error. If you got an error that a function named halfelf_init was doing something wrong, you could run this to find the file: grep -r "halfelf_init" ./wp-content/

    Some of the more experienced debuggers out there are probably wondering why I grep from wp-content when most errors give the full path of wp-content/plugins/plugin-name/filename.php in the first place. The answer to that is “most” but also because often functionality plugins that are related to a theme (or other plugins) will cross-reference themselves in ways that can cause PHP to give you the wrong file for the problem.

    If you ran my check and found that the function was called in nothing but files in that plugin’s folder, great. But if you found it was called in a theme, you would then want to run this: grep -r "halfelf_" ./wp-content/themes/theme-name/ — That would reveal all the calls for the functions that belonged to a specific other tool.

    And what if you got a warning that the function had already be declared? grep -r "function halfelf_" ./wp-content/plugins/other-plugin/ will list all the functions that start with halfelf_ and save you a headache of solving one warning only to have it be replaced by another. (Of course, if you use namespaces or classes, this gets thrown out the window, oh well).

    Finally there’s the human factor. This is exceptionally subjective, I know, but doesn’t a line of functions all starting with the same term feel cleaner to you? It demonstrates a repeating pattern that a human mind can follow and feel comfortable with.

    Solution: Be Consistent

    There’s only one solution to be had here. While I greatly prefer a prefix, if you chose to use a suffix, be consistent. Make every single function end with _pluginname and don’t skip a single one.

  • Secure Your Shit

    Secure Your Shit

    Ignore the fact that Google’s going to downgrade your sites if they’re not HTTPS soon. That’s not what I’m talking about.

    I’m a strong proponent of Net Neutrality and Freedom of Speech. I certainly intend to speak up and write and protest in the coming weeks and months, just like I have my whole life. I look at the world and I see things that need changing. So while this blog is about technology and computers and the Internet and websites, it has an impact on my political actions.

    Or rather, it’s that my political actions impact this site.

    People try to hack me all the time. All the damn time. Within the last 24 hours, over 400 people have tried to break into my ‘root’ account. It’s not named root. Good luck there. But the point is that people do try to hack me. They attack my WordPress install, my server, my email, my social media accounts, and my home wifi. I suspect the last one is my neighbor being stupid.

    This means I know that speaking up will make me a target and, because of that, I need to secure the hell out of my stuff. And that means using Two Factor Authentication.

    Use Strong Passwords

    I use 1Password to both create strong passwords and securely store them. A popular alternative is LastPass, but having used both, I find 1Password easier to use. Regardless, use them. My passwords are things like 4seqKD)CsbG=iQnVoirwZ77+ which I hate typing in when I have to change them, but thankfully with browser extensions I not only don’t have to, but I don’t know my own passwords.

    Example of the 1password generator

    I can just generate and go.

    Secure your Email

    I know a lot of people use Gmail. I pay them for email right now (long story, tl;dr no one does spam better). That doesn’t mean I fully trust them but, since I pay them, I know I have a different relationship than the free Gmail one. Still I use 2-step verification on gmail.

    If you need super secure and private email, ProtonMail is the way to go. Sadly it’d be $30 a month for my multiple domains. I wish they’d charge per email address, but that’s another issue.

    Secure Your Panels

    Everyone logs into web hosts the same way. We use a panel. It might be Plesk or cPanel or a home-grown system. It doesn’t matter which. Whichever one you use, make secure passwords, don’t share them with anyone, and if at all humanly possible, use Two Factor Authentication. If your webhost doesn’t offer it, leave. I know what I just said. If they don’t offer some method of verification, they’re not safe.

    When you secure your panel, make sure you also secure your billing stuff. For example, I use LiquidWeb. They use cPanel and I activated Two Factor Authentication for that. But they also have a proprietary manage site where I log in for billing and server allocations. That also needs security. Make sure you do it on both.

    Secure Your Blog

    If you use WordPress.com, Turn on Two Step Authentication.

    If you self host WordPress, use a plugin like Two Factor. That’s the feature project’s plugin that hopes to be added to WordPress core, so it’s a little rough around the edges. While I do have fundamental issues with 2FA being enabled by default for all users of a blog, it’s because I understand that most users are not technical.

    It’s a double-edged sword. If we don’t teach people to be a little more technical to be a little safer, they won’t become safer. On the other hand, with things like 2FA and WordPress, there’s no real way for them to contact a person for help. If you turn it on, then everyone who locks themselves out gets to either call their webhost (who isn’t responsible for that) or a young relative (who didn’t sign on for that) or post in the support forums (who did sign on for that, but still).

    Secure Social Media

    Twitter, Facebook, and Tumblr have Two Factor authentication. Use it.

    Twitter’s sucks, by the way. It’s text based, which means you can only use it via text-messages. Facebook requires you to use texts, but allows it to be a backup to a code generator like Google Authenticator.

    Be Secure

    The moral of all this? Be secure.

  • Mailbag: When Do I Use “If Exists”?

    Mailbag: When Do I Use “If Exists”?

    Someone pinged me on slack about this. Bear in mind, I tell people “If you got an email from plugins, please press reply and email back, don’t slack me.” because it allows me to keep track of the whole history of a conversation, but also because if I’m sick, someone else can reply to you and you’ll wait less. While, in this case, the answer should have been very short, it grew to be a lot longer than he’d expected because he didn’t quite understand what I meant.

    Unique Prefixes

    One of the requirements of the Plugin Directory is that all plugins have unique function names, defines, and classnames. This is for a pretty obvious reason: it will prevent your plugin from conflicting with other plugins or themes.

    • For plugins, use a function or classname that matches the plugin name: class ThisPluginName{} or function ThisPluginName_FUNCTION()
    • For specific specific sites, use a function class for the domain: class HalfElfOrg{} or class HELF{} or function helf_FUNCTION

    This extends to all things, including defines, namespaces, enqueue’d handles, and on and on. As I tell people, “A namespace or class of MyPlugin is not actually all that unique…” Defines are extra tricky since sometimes you want to define them and allow them to be replaced. But more on that in a minute. No matter what, this is bad: define( 'PLUGIN_PATH', plugins_url( __FILE__ ) );

    Since it’s 2016, I have to tell people that they shouldn’t use two letter slugs anymore as all the good ones are taken. I also tell them not to use wp_ or __ as a prefix.

    And then I say this:

    If those are intended to be in shared libraries, please detect IF the code is already included and not re-include it, as doing so will cause conflicts if two people call the same defines and functions.

    Yeah. It’s messy.

    If Define Exists…

    This is used a lot. Let’s say you know you need the plugin basename (the folder name) in multiple sub folders of you plugin, and it’s a pain in the ass to do plugins_urls( 'foo.css' , dirname( dirname( __FILE__ )) ); to go up two folders. That’s a case where a global define starts to make sense and it’s a case where rarely would you want to bother checking if it exists.

    The code is just this: define( 'MY_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );

    But what if you want to have a default value for an API Key and allow people to override it? Then you can one of these:

    // Option 1:
    if ( ! defined( 'MY_PLUGIN_APIKEY' ) )
        define( 'MY_PLUGIN_APIKEY', 'default key value' );
    
    // Option 2:
    defined('MY_PLUGIN_APIKEY') or define('MY_PLUGIN_APIKEY', 'default key value' );
    

    What those do is check “Does the define already exist?” for you.

    Now keep in mind, I wouldn’t do that. I’d do this:

    $apikey = ( defined('MY_PLUGIN_APIKEY') ) ? MY_PLUGIN_APIKEY : 'default key value' ;

    The best example of this in core WP is how WP_DEBUG is handled. If you delete that from your wp-config.php file, it doesn’t turn on debugging. The code checks for the existence and if it’s not there, it assumes no. For the most part, if you name your defines properly, there’s no need to allow them to be overwritten because you’re not defining them in advance. But in case you do, this code is a wise idea.

    If Function (or Class) Exists …

    Lately I’ve seen a lot of people do this:

    if ( ! function_exists( 'my_awesome_function' ) ) {
    	function my_awesome_function() {
    		//function stuff
    	}
    }
    

    Okay look. This sounds like a great idea until you realize the fatal flaw. What happens when (not if, when) someone else has a function with the same name and their plugin or theme loads first?

    As Lilu Dallas would say “Big badda boom.”

    This is a terrible idea unless we’re talking about shared libraries.

    Use if-checks With Shared Libraries

    That’s my answer here folks. The only time you should be checking if-exists is WHEN you are using a shared library. If your plugin includes a common PHP library, check for it before you include it.

    It’s a little different with Javascript and CSS though. Let’s say you’ve got Bootstrap. This is a commonly used library. A lot of plugins and themes have it, and you’re a good person. You want to make sure you only load it one time no matter how many people include it in their plugins and themes. In this moment, you have to do something paradoxically brilliant.

    Don’t use a unique name for your enqueues.

    function mypluginname_resources() {
        wp_enqueue_style( 'bootstrap', plugins_url( 'css/bootstrap.min.css', __FILE__ ), array(), VERSION );
        wp_enqueue_script( 'bootstrap', plugins_url( 'css/js', __FILE__ ), array(), VERSION );
    }
    add_action('wp_enqueue_scripts', 'mypluginname_resources');
    

    The magic here is specific to how WordPress handles enqueues. It knows “There’s already something enqueued as bootstrap! I don’t need this!” and you’ve sped up sites. Of course there’s a risk here when someone might have an older version loaded first. As far as I know, the enqueue system isn’t clever enough to detect what version is included, and use the newest one (I wish it was), so you may have to do some convoluted checks. Also making this worse is that people don’t name things properly. I’ve see people using bootstrap-js and bootstrap-css for the enqueue names, which is totally unnecessary. WordPress will handle that for you.

    Remember: When in doubt, if coding for WordPress do it the WordPress way.

  • PHP Ternary Operations

    PHP Ternary Operations

    I mentioned a few days ago that I finally got to use ternary operations in my code and I was excited.

    I have a tendency to write my code out long form, which stems from how I actually sit down and think about my code. For example, when I need to check if specific parameters are set, I write it out like this:

    If variable X is equal to FOO, then do BLAH. Else do DEFAULT!

    When I translate that to PHP code, it becomes this:

    if ( $variable == 'FOO' ) {
        BLAH;
    } else {
        DEFAULT;
    }
    

    There’s nothing particularly wrong with it, but it can get a little long. And then consider code like this:

    if($_POST['variable'] == 'no' || $_POST['variable'] == 'yes'){              
        $variable = $_POST['variable'] ;
    }
    

    That has two issues. The first is that I’m trusting my data a little more than I should and not sanitizing when I save the variable. The second is I’m not validating smartly. If I want to be smarter, I do this:

    if( $_POST['variable'] == 'yes'){              
        $variable = 'yes ;
    } else {
        $variable = 'no';
    }
    

    At this point, I’m no longer allowing my code to be anything but yes or no, and if someone puts in ‘maybe’ as a value for the POST data, that’s nice but I’m forcing no.

    Another alternate way is this:

    $variable = 'no';
    if( $_POST['variable'] == 'yes'){              
        $variable = 'yes ;
    }
    

    There I default to ‘no’ and only pick ‘yes’ if it’s set to yes. This code is somewhat better because it only has one check and it’s obvious what my default is.

    But we can be even smarter! The trick is that I have to rethink how I’m checking for things. If all I care about is if a comparison is true or false, and I want to save a specific value to a variable based on that, then I can do my code all in one line:

    $variable = ( $_POST['variable'] == 'yes' )? 'yes' : 'no';
    

    This is the magic of the ternary operators. With it I get one line that checks for a specific result and defaults when that’s not it. You can make it more complicated, as long as the result is true/false. Like here:

    $schema = ( is_ssl() || get_setting( 'plugin-force-ssl' ) )? 'https' : 'http';
    

    Obviously they won’t work in all situations, and there are some cases where the two possibilities are going to make the code harder to read, but they can be downright nifty if you do them right.

  • Cleaning up SVGs

    Cleaning up SVGs

    If you were here on Friday, I talked about the headache of using SVGs on AMP pages. In that post I mentioned that one of the fixes was to ‘clean’ the SVG file.

    Why would be bother? The simple answer is that smaller files are better. But as we learned with AMP being picky, it’s also because we want our files to be fully compatible with all browsers and servers. SVG standards are important, after all.

    So let’s clean!

    Remove Headers

    If your SVG starts with this, just remove it:

    <!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN">
    

    Remove Less Standard Tags

    I wouldn’t have realized these weren’t super standard if it hadn’t been for AMP alerts. But these aren’t:

    xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
    

    Again, remove them. But also you want to remove tags like <g i:extraneous="self"> and that’s tricky because you’ll usually see it like this:

    <g i:extraneous="self">
        <g>
            [Image stuff]
        </g>
    </g>
    

    If you use a regular expression like I did, be very cautious. I checked every single one of my 700 SVGs after the edits to make sure they still worked. There were cases where the only call to the <g> tag was with the extraneous stuff, so I had to very cautiously replace. I missed about 40.

    Remove Illustrator’s Extra Shit

    Here’s where you’re going to save the most space. First remove the requiredExtensions stuff:

    	<foreignObject requiredExtensions="&ns_ai;" x="0" y="0" width="1" height="1">
    		<i:pgfRef  xlink:href="#adobe_illustrator_pgf">
    		</i:pgfRef>
    	</foreignObject>
    

    And then remove the big hunk of PGF:

    <i:pgf  id="adobe_illustrator_pgf">(.*)</i:pgf>
    

    I can’t show you the actual content. It’s huge. It’s way huge. It’s up to 20k huge.

    Remove Switch

    If you’re not using the switch, you want to remove it.

    <switch>
    	<g i:extraneous="self">
    		<rect fill="#231F20" width="28" height="28"/>
    	</g>
    </switch>
    

    End Result?

    A 29 KB file is 4KB. And that is a faster internet.

  • Can AMP and SVGs Be Friends?

    Can AMP and SVGs Be Friends?

    Spoiler: Not at the moment, no.

    Warning: Fix errors on your AMP pages

    On January first, I got a scary email with that subject:

    Google systems have detected that some of your AMP pages do not meet our guidelines and will therefore not show in Google Search AMP-related features.

    Yikes! I ran over to Google Webmaster Tools and saw I had well over 400 pages with critical issues. Happy New Year to me, right? Looking at them, most of the problems were exactly the same:

    • The tag ‘pgfref’ is disallowed.
    • The tag ‘pgf’ is disallowed.
    • The attribute ‘i:extraneous’ may not appear in tag ‘g’.
    • The attribute ‘xmlns:x’ may not appear in tag ‘svg’.
    • The tag ‘switch’ is disallowed.

    Right away, I knew this was from my SVGs. On this site, I use SVGs instead of PNGs because they look crisper on retina screens and they can be colored on the fly. Basically I really like the power of SVGs. And, as far as I could tell, SVGs worked on AMP pages. I read the details on SVGs in AMP/HTML and it’s listed there, after all.

    But in reading the errors and looking at my SVGs in a text editor, I quickly saw what was wrong.

    Most SVGs have Extra Data

    I use the Block Bundle from Symbolicons for my SVGs. They’re awesome, but once in a while I have to edit them and clean up some extraneous data within. Adobe Illustrator, for example, puts in a lot of junk at the top of my SVGs:

    <?xml version="1.0" encoding="utf-8"?>
    <!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    

    But in the case of the SVG having a problem, it had … well. This:

    <?xml version="1.0" encoding="utf-8"?>
    <!-- Generator: Adobe Illustrator 17.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN">
    <svg version="1.1" id="Layer_1" xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;"
    	 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 28 28"
    	 enable-background="new 0 0 28 28" xml:space="preserve">
    <switch>
    	<foreignObject requiredExtensions="&ns_ai;" x="0" y="0" width="1" height="1">
    		<i:pgfRef  xlink:href="#adobe_illustrator_pgf">
    		</i:pgfRef>
    	</foreignObject>
    	<g i:extraneous="self">
    		<g>
    			<defs>
    				<rect id="SVGID_1_" width="28" height="28"/>
    			</defs>
    			<clipPath id="SVGID_2_">
    				<use xlink:href="#SVGID_1_"  overflow="visible"/>
    			</clipPath>
    			<path clip-path="url(#SVGID_2_)" fill="#231F20" d="M24.286,20h-6.757c-1.229,0-2.259,0.69-2.568,1.615
    				[...]
    				C26,20.651,25.234,20,24.286,20"/>
    			<path clip-path="url(#SVGID_2_)" fill="#231F20" d="M27,16H1c-0.553,0-1,0.447-1,1c0,0.553,0.447,1,1,1h26c0.553,0,1-0.447,1-1
    				C28,16.447,27.553,16,27,16"/>
    			<path clip-path="url(#SVGID_2_)" fill="#231F20" d="M21.699,2.046c-0.384-1.711-1.927-2.513-3.427-1.781l-1.544,0.752
    				c-1.5,0.732-3.956,0.732-5.456,0L9.728,0.265c-1.5-0.732-3.042,0.07-3.427,1.781L4.29,10h19.42L21.699,2.046z"/>
    			<polygon clip-path="url(#SVGID_2_)" fill="#231F20" points="23.935,11 4.066,11 3.167,15 24.833,15 			"/>
    		</g>
    	</g>
    </switch>
    <i:pgf  id="adobe_illustrator_pgf">
    	<![CDATA[
    		eJzVfelCMsuu6H0B3gFUBGTqidGZyQkVxXlCkFb5RMAG1trf+XGf/aaq56G6qxs859y99nJBd5FUpVKpJJVUopFWO73fH/fENJ9hwqFotCqJ3dlYKofx0/DRcDifziT0KH6ZCLOFDAON9o+KHaXhjShNB+NRGb1i8csG+nX8eCz9DV92J59dcZgIxxPw4mowG4rwajr5m5n03xMqNvh5rTuDN3y2mGWFcL4slMKtU/S6O/qnO50O/[...]==	
    	]]>	
    	<![CDATA[	
    		k3D32Uw5IYV5ef6oHOpoLUjz3J9shIS0J71kk7fOSM8qidXrybCJkYaiFrTT1Zd8hYT0cOeiMLpxRiok7pKbb+enTkhD0elK40XQ0VqQMo3KyR4BaX51bSQltglI71+YxvtZGyMFHrOMdeUgsrXOHneuHJEeHHJXRPJyDztXrxgpsH2vriNF62Vzeis9zXeaCG3CPqvxe/5xyCYAqTC2stJzk1HJ24rFLEhzue/OBCMNRS1oEdKO9Pw5uiIg3evmC4011hHpy+7rpRPSUBTP6hof33xyGqskbUWep6uf4qUz0otqYudn7bvphDS5OSzvYKRIWlrHml9d/Zk/[...]==	
    	]]>	
    	<![CDATA[	
    		dcrskeHXSl9Zs0fmmNYjE7Jee2ZNHFkrryzktsCJTQbLwl96jj3t62SdzndBkZ6zVmZj/odmsSu/jxf2yKA0NKvjIcB9Ssf+PTJOGakoDW1RjwzOzrPccReQMDna5Bz1vnFCsMsxMT3HV3KOdspTbs2seai711GPaBoaZRl0udXFcxJPKCIZtFubPKyWycki94aZd+TyRXzxoTmE7OkeRUoOLV9EqEIXTPxpuxMSzTlNMLBnXp0xaNZ6N5SPvDofsesEKwkRhiqFxDMWA9GmQMXJlGHrcYdz1Lb3fX10Z2UU+XA09/[...]++foLQ
    	]]>
    </i:pgf>
    </svg>
    

    I’ve truncated the code because it’s insanely long. In fact, it’s so long that with all of it, the file is 25k larger!

    Let me explain. The SVG there has ‘switch’ code. The switch code is awesome because it can change what’s displayed based on what the file detects. For example if I wanted to make different text show based on the detected system language, I would do this:

    <switch>
        <g systemLanguage="en-UK">
            <text x="10" y="20">I say, bravo!</text>
        </g>
        <g systemLanguage="en">
            <text x="10" y="20">Arright!</text>
        </g>
    </switch>    
    

    The problem is that AMP? Doesn’t like that.

    AMP Doesn’t Trust SVGs

    AMP really doesn’t like fancy things. This makes sense. It’s meant to be faster for mobile browsers, so it’s streamlined and simplified. Fine. It wants simple SVGs. Obviously one fix here is I could clean up all my SVGs. The other one would be to do what AMP suggests and that is to whitelist attributes. Except you can’t do it. Yet.

    There is a reason for this, and it’s similar to the same reason WordPress doesn’t (yet) allow SVGs to be uploaded by default. Unlike images, SVG files contain code. An user who can upload an SVG has the ability to upload code files which can be executed in the victim’s browser. Picture this. An attacker uploads an image to a forum. If the forum links to the image with <img> then the end-user’s browsers load the SVG and run the code. Yaaaaaay.

    SVGs are dangerous. And to help this, AMP says SVGs with special tags are not welcome.

    The Fix?

    Edit your SVGs or, if you’re me, ditch the images all together. I decided to go with the ditching since I wanted the pages to load fast. It’s the point of AMP after all.