/** * XhtmlValidator for validating tag attributes * * @author Bermi Ferrer - http://bermi.org */ WYMeditor.XhtmlValidator = { "_attributes": { "core": { "except":<%= [ "base", "head", "html", "meta", "param", "script", "style", "title" ].reject{|a| Refinery::Wymeditor.whitelist_tags.keys.map(&:to_s).include?(a)}.inspect %>, "attributes":[ "class", "id", "style", "title", "accesskey", "tabindex", "data", "^data-.*", "^aria-.*" ] }, "language": { "except":<%= [ "base", "br", "hr", "iframe", "param", "script" ].reject{|a| Refinery::Wymeditor.whitelist_tags.keys.map(&:to_s).include?(a)}.inspect %>, "attributes": { "dir":[ "ltr", "rtl" ], "0":"lang", "1":"xml:lang" } }, "keyboard": { "attributes": { "accesskey":/^(\w){1}$/, "tabindex":/^(\d)+$/ } } }, "_events": { "window": { "only":[ "body" ], "attributes":[ "onload", "onunload" ] }, "form": { "only":[ "form", "input", "textarea", "select", "a", "label", "button" ], "attributes":[ "onchange", "onsubmit", "onreset", "onselect", "onblur", "onfocus" ] }, "keyboard": { "except":<%= [ "base", "bdo", "br", "frame", "frameset", "head", "html", "iframe", "meta", "param", "script", "style", "title" ].reject{|a| Refinery::Wymeditor.whitelist_tags.keys.map(&:to_s).include?(a)}.inspect %>, "attributes":[ "onkeydown", "onkeypress", "onkeyup" ] }, "mouse": { "except":<%= [ "base", "bdo", "br", "head", "html", "meta", "param", "script", "style", "title" ].reject{|a| Refinery::Wymeditor.whitelist_tags.keys.map(&:to_s).include?(a)}.inspect %>, "attributes":[ "onclick", "ondblclick", "onmousedown", "onmousemove", "onmouseover", "onmouseout", "onmouseup" ] } }, "_tags": { "a": { "attributes": { "0":"charset", "1":"coords", "2":"href", "3":"hreflang", "4":"name", "rel":/^(alternate|designates|stylesheet|start|next|nofollow|prev|contents|index|glossary|copyright|chapter|section|subsection|appendix|help|bookmark| |shortcut|icon|moodalbox)+$/, "rev":/^(alternate|designates|stylesheet|start|next|prev|contents|index|glossary|copyright|chapter|section|subsection|appendix|help|bookmark| |shortcut|icon|moodalbox)+$/, "shape":/^(rect|rectangle|circ|circle|poly|polygon)$/, "5":"type", "target":/^(_blank)+$/ } }, "0":"abbr", "1":"acronym", "2":"address", "area": { "attributes": { "0":"alt", "1":"coords", "2":"href", "nohref":/^(true|false)$/, "shape":/^(rect|rectangle|circ|circle|poly|polygon)$/ }, "required":[ "alt" ] }, "3":"b", "base": { "attributes":[ "href" ], "required":[ "href" ] }, "bdo": { "attributes": { "dir":/^(ltr|rtl)$/ }, "required":[ "dir" ] }, "4":"big", "blockquote": { "attributes":[ "cite" ] }, "5":"body", "6":"br", "button": { "attributes": { "disabled":/^(disabled)$/, "type":/^(button|reset|submit)$/, "0":"value" }, "inside":"form" }, "7":"caption", "8":"cite", "9":"code", "col": { "attributes": { "align":/^(right|left|center|justify)$/, "0":"char", "1":"charoff", "span":/^(\d)+$/, "valign":/^(top|middle|bottom|baseline)$/, "2":"width" }, "inside":"colgroup" }, "colgroup": { "attributes": { "align":/^(right|left|center|justify)$/, "0":"char", "1":"charoff", "span":/^(\d)+$/, "valign":/^(top|middle|bottom|baseline)$/, "2":"width" } }, "10":"dd", "del": { "attributes": { "0":"cite", "datetime":/^([0-9]){8}/ } }, "11":"div", "12":"dfn", "13":"dl", "14":"dt", "15":"em", "fieldset": { "inside":"form" }, "form": { "attributes": { "0":"action", "1":"accept", "2":"accept-charset", "3":"enctype", "method":/^(get|post)$/ }, "required":[ "action" ] }, "head": { "attributes":[ "profile" ] }, "16":"h1", "17":"h2", "18":"h3", "19":"h4", "20":"h5", "21":"h6", "22":"hr", "html": { "attributes":[ "xmlns" ] }, "23":"i", "iframe": { "attributes":[ "src", "width", "height", "frameborder", "allowfullscreen", "rel", "scrolling", "marginheight", "marginwidth" ], "required":[ "src" ] }, "img": { "attributes":{ "align":/^(right|left|center|justify)$/, "0":"alt", "1":"src", "2":"height", "3":"ismap", "4":"longdesc", "5":"usemap", "6":"width", "7":"rel" }, "required":[ "alt", "src" ] }, "input": { "attributes": { "0":"accept", "1":"alt", "checked":/^(checked)$/, "disabled":/^(disabled)$/, "maxlength":/^(\d)+$/, "2":"name", "readonly":/^(readonly)$/, "size":/^(\d)+$/, "3":"src", "type":/^(button|checkbox|file|hidden|image|password|radio|reset|submit|text|tel|search|url|email|datetime|date|month|week|time|datetime-local|number|range|color)$/, "4":"value", "5":"placeholder" }, "inside":"form" }, "ins": { "attributes": { "0":"cite", "datetime":/^([0-9]){8}/ } }, "24":"kbd", "label": { "attributes":[ "for" ], "inside":"form" }, "25":"legend", "26":"li", "link": { "attributes": { "0":"charset", "1":"href", "2":"hreflang", "media":/^(all|braille|print|projection|screen|speech|,|;| )+$/i, //next comment line required by Opera! /*"rel":/^(alternate|appendix|bookmark|chapter|contents|copyright|glossary|help|home|index|next|prev|section|start|stylesheet|subsection| |shortcut|icon)+$/i,*/ "rel":/^(alternate|appendix|bookmark|chapter|contents|copyright|glossary|help|home|index|next|nofollow|prev|section|start|stylesheet|subsection| |shortcut|icon)+$/i, "rev":/^(alternate|appendix|bookmark|chapter|contents|copyright|glossary|help|home|index|next|prev|section|start|stylesheet|subsection| |shortcut|icon)+$/i, "3":"type" }, "inside":"head" }, "map": { "attributes":[ "id", "name" ], "required":[ "id" ] }, "meta": { "attributes": { "0":"content", "http-equiv":/^(content\-type|expires|refresh|set\-cookie)$/i, "1":"name", "2":"scheme" }, "required":[ "content" ] }, "27":"noscript", "28":"ol", "optgroup": { "attributes": { "0":"label", "disabled": /^(disabled)$/ }, "required":[ "label" ] }, "option": { "attributes": { "0":"label", "disabled":/^(disabled)$/, "selected":/^(selected)$/, "1":"value" }, "inside":"select" }, "29":"p", "param": { "attributes": [ "type", "value", "name" ], "required":[ "name" ], "inside":"object" }, "embed": { "attributes": [ "width", "height", "allowfullscreen", "allowscriptaccess", "wmode", "type", "src", "flashvars" ], "inside":"object" }, "object": { "attributes":[ "archive", "classid", "codebase", "codetype", "data", "declare", "height", "name", "standby", "type", "usemap", "width" ] }, "30":"pre", "q": { "attributes":[ "cite" ] }, "31":"samp", "script": { "attributes": { "type":/^(text\/ecmascript|text\/javascript|text\/jscript|text\/vbscript|text\/vbs|text\/xml)$/, "0":"charset", "defer":/^(defer)$/, "1":"src" }, "required":[ "type" ] }, "select": { "attributes": { "disabled":/^(disabled)$/, "multiple":/^(multiple)$/, "0":"name", "1":"size" }, "inside":"form" }, "32":"small", "33":"span", "34":"strong", "style": { "attributes": { "0":"type", "media":/^(screen|tty|tv|projection|handheld|print|braille|aural|all)$/ }, "required":[ "type" ] }, "35":"sub", "36":"sup", "table": { "attributes": { "0":"border", "1":"cellpadding", "2":"cellspacing", "frame":/^(void|above|below|hsides|lhs|rhs|vsides|box|border)$/, "rules":/^(none|groups|rows|cols|all)$/, "3":"summary", "4":"width" } }, "tbody": { "attributes": { "align":/^(right|left|center|justify)$/, "0":"char", "1":"charoff", "valign":/^(top|middle|bottom|baseline)$/ } }, "td": { "attributes": { "0":"abbr", "align":/^(left|right|center|justify|char)$/, "1":"axis", "2":"char", "3":"charoff", "colspan":/^(\d)+$/, "4":"headers", "rowspan":/^(\d)+$/, "scope":/^(col|colgroup|row|rowgroup)$/, "valign":/^(top|middle|bottom|baseline)$/ } }, "textarea": { "attributes":[ "cols", "rows", "disabled", "name", "readonly" ], "required":[ "cols", "rows" ], "inside":"form" }, "tfoot": { "attributes": { "align":/^(right|left|center|justify)$/, "0":"char", "1":"charoff", "valign":/^(top|middle|bottom)$/, "2":"baseline" } }, "th": { "attributes": { "0":"abbr", "align":/^(left|right|center|justify|char)$/, "1":"axis", "2":"char", "3":"charoff", "colspan":/^(\d)+$/, "4":"headers", "rowspan":/^(\d)+$/, "scope":/^(col|colgroup|row|rowgroup)$/, "valign":/^(top|middle|bottom|baseline)$/ } }, "thead": { "attributes": { "align":/^(right|left|center|justify)$/, "0":"char", "1":"charoff", "valign":/^(top|middle|bottom|baseline)$/ } }, "37":"title", "tr": { "attributes": { "align":/^(right|left|center|justify|char)$/, "0":"char", "1":"charoff", "valign":/^(top|middle|bottom|baseline)$/ } }, "38":"tt", "39":"ul", "40":"var", "41":"section", "42":"article", "43":"aside", "44":"details", "45":"header", "46":"footer", "47":"nav", "48":"dialog", "49":"figure", "50":"figcaption", "51":"address", "52":"hgroup", "53":"mark", "54":"time", "55":"canvas", "56":"audio", "57":"video", "58":"source", "59":"output", "60":"progress", "61":"ruby", "62":"rt", "63":"rp", "64":"summary", "65":"command"<% Refinery::Wymeditor.whitelist_tags.each do |key, value| %>, <%= key.inspect %>:<%= value.to_json %><% end %> }, // Temporary skipped attributes skipped_attributes : [], skipped_attribute_values : [], getValidTagAttributes: function(tag, attributes) { var valid_attributes = {}; var possible_attributes = this.getPossibleTagAttributes(tag); var regexp_attributes = []; $.each((possible_attributes || []), function(i, val) { if (val.indexOf("*") > -1) { regexp_attributes.push(new RegExp(val)); } }); var h = WYMeditor.Helper; for(var attribute in attributes) { var value = attributes[attribute]; if(!h.contains(this.skipped_attributes, attribute) && !h.contains(this.skipped_attribute_values, value)){ if (typeof value != 'function') { if (h.contains(possible_attributes, attribute)) { if (this.doesAttributeNeedsValidation(tag, attribute)) { if(this.validateAttribute(tag, attribute, value)){ valid_attributes[attribute] = value; } }else{ valid_attributes[attribute] = value; } } else { $.each(regexp_attributes, function(i, val) { if (attribute.match(val)) { valid_attributes[attribute] = value; } }); } } } } return valid_attributes; }, getUniqueAttributesAndEventsForTag: function(tag) { var result = []; if (this._tags[tag] && this._tags[tag]['attributes']) { for (k in this._tags[tag]['attributes']) { result.push(parseInt(k) == k ? this._tags[tag]['attributes'][k] : k); } } return result; }, getDefaultAttributesAndEventsForTags: function() { var result = []; for (var key in this._events){ result.push(this._events[key]); } for (var key in this._attributes){ result.push(this._attributes[key]); } return result; }, isValidTag: function(tag) { if(this._tags[tag]){ return true; } for(var key in this._tags){ if(this._tags[key] == tag){ return true; } } return false; }, getDefaultAttributesAndEventsForTag: function(tag) { var default_attributes = []; if (this.isValidTag(tag)) { var default_attributes_and_events = this.getDefaultAttributesAndEventsForTags(); for(var key in default_attributes_and_events) { var defaults = default_attributes_and_events[key]; if(typeof defaults == 'object'){ var h = WYMeditor.Helper; if ((defaults['except'] && h.contains(defaults['except'], tag)) || (defaults['only'] && !h.contains(defaults['only'], tag))) { continue; } var tag_defaults = defaults['attributes'] ? defaults['attributes'] : defaults['events']; for(var k in tag_defaults) { default_attributes.push(typeof tag_defaults[k] != 'string' ? k : tag_defaults[k]); } } } } return default_attributes; }, doesAttributeNeedsValidation: function(tag, attribute) { return this._tags[tag] && ((this._tags[tag]['attributes'] && this._tags[tag]['attributes'][attribute]) || (this._tags[tag]['required'] && WYMeditor.Helper.contains(this._tags[tag]['required'], attribute))); }, validateAttribute: function(tag, attribute, value) { if ( this._tags[tag] && (this._tags[tag]['attributes'] && this._tags[tag]['attributes'][attribute] && value.length > 0 && !value.match(this._tags[tag]['attributes'][attribute])) || // invalid format (this._tags[tag] && this._tags[tag]['required'] && WYMeditor.Helper.contains(this._tags[tag]['required'], attribute) && value.length == 0) // required attribute ) { return false; } return typeof this._tags[tag] != 'undefined'; }, getPossibleTagAttributes: function(tag) { if (!this._possible_tag_attributes) { this._possible_tag_attributes = {}; } if (!this._possible_tag_attributes[tag]) { this._possible_tag_attributes[tag] = this.getUniqueAttributesAndEventsForTag(tag).concat(this.getDefaultAttributesAndEventsForTag(tag)); } return this._possible_tag_attributes[tag]; } };