<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[23120] trunk/wp-includes: Add a sane, inclusive HTML element/attribute schema to TinyMCE.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg > ul, #logmsg > ol { margin-left: 0; margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/23120">23120</a></dd>
<dt>Author</dt> <dd>nacin</dd>
<dt>Date</dt> <dd>2012-12-07 11:26:25 +0000 (Fri, 07 Dec 2012)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add a sane, inclusive HTML element/attribute schema to TinyMCE.

TinyMCE 3.4.x (shipped with WordPress 3.4.x) had an HTML4-based schema definition, with HTML5 elements added to it. TinyMCE 3.5.x (shipping, again coincidentally, with WordPress 3.5) allows for HTML5 schema support, which also provides for full HTML5 attribute support. The problem is its HTML5 schema excludes all HTML4 elements and attributes that were dropped in the HTML5 spec, which is unacceptable behavior.

This &quot;duck punch&quot; of TinyMCE's Schema.js file creates a new, sane schema. It is TinyMCE's HTML4 and HTML5 schema definitions recursively merged.

Objects are not whitelisted in either schema to allow for embed elements as child nodes, so object, param, and embed remain separately whitelisted in the WordPress TinyMCE plugin. Our attempts to add other attributes in said plugin is now superceded.

props koopersmith, azaozz.
fixes <a href="http://core.trac.wordpress.org/ticket/22790">#22790</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpincludesclasswpeditorphp">trunk/wp-includes/class-wp-editor.php</a></li>
<li><a href="#trunkwpincludesjstinymcepluginswordpresseditor_plugin_srcjs">trunk/wp-includes/js/tinymce/plugins/wordpress/editor_plugin_src.js</a></li>
<li><a href="#trunkwpincludesjstinymcewptinymceschemajs">trunk/wp-includes/js/tinymce/wp-tinymce-schema.js</a></li>
<li><a href="#trunkwpincludesjstinymcewptinymcephp">trunk/wp-includes/js/tinymce/wp-tinymce.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpincludesclasswpeditorphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/class-wp-editor.php (23119 => 23120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/class-wp-editor.php        2012-12-07 11:12:51 UTC (rev 23119)
+++ trunk/wp-includes/class-wp-editor.php        2012-12-07 11:26:25 UTC (rev 23120)
</span><span class="lines">@@ -569,10 +569,12 @@
</span><span class="cx">                 $baseurl = self::$baseurl;
</span><span class="cx"> 
</span><span class="cx">                 if ( $tmce_on ) {
</span><del>-                        if ( $compressed )
</del><ins>+                        if ( $compressed ) {
</ins><span class="cx">                                 echo &quot;&lt;script type='text/javascript' src='{$baseurl}/wp-tinymce.php?c=1&amp;amp;$version'&gt;&lt;/script&gt;\n&quot;;
</span><del>-                        else
</del><ins>+                        } else {
</ins><span class="cx">                                 echo &quot;&lt;script type='text/javascript' src='{$baseurl}/tiny_mce.js?$version'&gt;&lt;/script&gt;\n&quot;;
</span><ins>+                                echo &quot;&lt;script type='text/javascript' src='{$baseurl}/wp-tinymce-schema.js?$version'&gt;&lt;/script&gt;\n&quot;;
+                        }
</ins><span class="cx"> 
</span><span class="cx">                         if ( 'en' != self::$mce_locale &amp;&amp; isset($lang) )
</span><span class="cx">                                 echo &quot;&lt;script type='text/javascript'&gt;\n$lang\n&lt;/script&gt;\n&quot;;
</span></span></pre></div>
<a id="trunkwpincludesjstinymcepluginswordpresseditor_plugin_srcjs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/tinymce/plugins/wordpress/editor_plugin_src.js (23119 => 23120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/tinymce/plugins/wordpress/editor_plugin_src.js        2012-12-07 11:12:51 UTC (rev 23119)
+++ trunk/wp-includes/js/tinymce/plugins/wordpress/editor_plugin_src.js        2012-12-07 11:26:25 UTC (rev 23120)
</span><span class="lines">@@ -135,21 +135,8 @@
</span><span class="cx">                                 }
</span><span class="cx">                         });
</span><span class="cx"> 
</span><del>-                        // Add obsolete HTML attributes that are still in use.
</del><ins>+                        // Extend &lt;object&gt; and &lt;embed&gt; (#WP22790)
</ins><span class="cx">                         ed.onPreInit.add(function(ed) {
</span><del>-                                // The commonAttr are from TinyMCE 3.5.7 getHTML5()
-                                // Obsolete attributes are from TinyMCE 3.5.7 getHTML4()
-                                var commonAttr = 'id|accesskey|class|dir|draggable|item|hidden|itemprop|role|spellcheck|style|subject|title|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup',
-                                        tdAttr = commonAttr + '|abbr|axis|headers|scope|rowspan|colspan|char|charoff|align|valign|halign|nowrap|bgcolor|width|height';
-                                // Obsolete table attributes
-                                ed.schema.addValidElements('table['+commonAttr+'|summary|width|border|frame|rules|cellspacing|cellpadding|align|bgcolor]');
-                                // Obsolete tr attributes
-                                ed.schema.addValidElements('tr['+commonAttr+'|align|char|charoff|valign|halign|bgcolor]');
-                                // Obsolete td and th attributes
-                                ed.schema.addValidElements('td['+tdAttr+'],th['+tdAttr+']');
-                                // Adds &quot;name&quot; for &lt;a&gt;
-                                ed.schema.addValidElements('a['+commonAttr+'|href|target|ping|rel|media|type|name]');
-                                // Extend &lt;object&gt; and &lt;embed&gt;
</del><span class="cx">                                 ed.schema.addValidElements('object[*],param[id|name|value|valuetype|type],embed[*]');
</span><span class="cx">                                 ed.schema.addValidChildren('object[*]');
</span><span class="cx">                         });
</span></span></pre></div>
<a id="trunkwpincludesjstinymcewptinymceschemajs"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/tinymce/wp-tinymce-schema.js (23119 => 23120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/tinymce/wp-tinymce-schema.js        2012-12-07 11:12:51 UTC (rev 23119)
+++ trunk/wp-includes/js/tinymce/wp-tinymce-schema.js        2012-12-07 11:26:25 UTC (rev 23120)
</span><span class="lines">@@ -1,6 +1,8 @@
</span><span class="cx"> /**
</span><del>- * Schema.js
</del><ins>+ * TinyMCE Schema.js
</ins><span class="cx">  *
</span><ins>+ * Duck-punched by WordPress core to support a sane schema superset.
+ *
</ins><span class="cx">  * Copyright, Moxiecode Systems AB
</span><span class="cx">  * Released under LGPL License.
</span><span class="cx">  *
</span><span class="lines">@@ -320,6 +322,59 @@
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         /**
</span><ins>+         * WordPress Core
+         *
+         * Returns a schema that is the result of a deep merge between the HTML5
+         * and HTML4 schemas.
+         */
+        function getSaneSchema() {
+                var cachedMapCache = mapCache,
+                        html5, html4;
+
+                if ( mapCache.sane )
+                        return mapCache.sane;
+
+                // Bust the mapCache so we're not dealing with the other schema objects.
+                mapCache = {};
+                html5 = getHTML5();
+                html4 = getHTML4();
+                mapCache = cachedMapCache;
+
+                each( html4, function( html4settings, tag ) {
+                        var html5settings = html5[ tag ],
+                                difference = [];
+
+                        // Merge tags missing in HTML5 mode.
+                        if ( ! html5settings ) {
+                                html5[ tag ] = html4settings;
+                                return;
+                        }
+
+                        // Merge attributes missing from this HTML5 tag.
+                        each( html4settings.attributes, function( attribute, key ) {
+                                if ( ! html5settings.attributes[ key ] )
+                                        html5settings.attributes[ key ] = attribute;
+                        });
+
+                        // Merge any missing attributes into the attributes order.
+                        each( html4settings.attributesOrder, function( key ) {
+                                if ( -1 === tinymce.inArray( html5settings.attributesOrder, key ) )
+                                        difference.push( key );
+                        });
+
+                        html5settings.attributesOrder = html5settings.attributesOrder.concat( difference );
+
+                        // Merge children missing from this HTML5 tag.
+                        each( html4settings.children, function( child, key ) {
+                                if ( ! html5settings.children[ key ] )
+                                        html5settings.children[ key ] = child;
+                        });
+                });
+
+                return mapCache.sane = html5;
+        }
+
+        /**
</ins><span class="cx">          * Schema validator class.
</span><span class="cx">          *
</span><span class="cx">          * @class tinymce.html.Schema
</span><span class="lines">@@ -368,8 +423,12 @@
</span><span class="cx">                 };
</span><span class="cx"> 
</span><span class="cx">                 settings = settings || {};
</span><del>-                schemaItems = settings.schema == &quot;html5&quot; ? getHTML5() : getHTML4();
</del><span class="cx"> 
</span><ins>+                /**
+                 * WordPress core uses a sane schema in place of the default &quot;HTML5&quot; schema.
+                 */
+                schemaItems = settings.schema == &quot;html5&quot; ? getSaneSchema() : getHTML4();
+
</ins><span class="cx">                 // Allow all elements and attributes if verify_html is set to false
</span><span class="cx">                 if (settings.verify_html === false)
</span><span class="cx">                         settings.valid_elements = '*[*]';
</span></span></pre></div>
<a id="trunkwpincludesjstinymcewptinymcephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/js/tinymce/wp-tinymce.php (23119 => 23120)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/js/tinymce/wp-tinymce.php        2012-12-07 11:12:51 UTC (rev 23119)
+++ trunk/wp-includes/js/tinymce/wp-tinymce.php        2012-12-07 11:26:25 UTC (rev 23120)
</span><span class="lines">@@ -33,5 +33,6 @@
</span><span class="cx">         echo $file;
</span><span class="cx"> } else {
</span><span class="cx">         echo get_file($basepath . '/tiny_mce.js');
</span><ins>+        echo get_file($basepath . '/wp-tinymce-schema.js');
</ins><span class="cx"> }
</span><span class="cx"> exit;
</span></span></pre>
</div>
</div>

</body>
</html>