'use strict'; | |
var Tokenizer = require('../tokenization/tokenizer'), | |
HTML = require('./html'); | |
//Aliases | |
var $ = HTML.TAG_NAMES, | |
NS = HTML.NAMESPACES, | |
ATTRS = HTML.ATTRS; | |
//MIME types | |
var MIME_TYPES = { | |
TEXT_HTML: 'text/html', | |
APPLICATION_XML: 'application/xhtml+xml' | |
}; | |
//Attributes | |
var DEFINITION_URL_ATTR = 'definitionurl', | |
ADJUSTED_DEFINITION_URL_ATTR = 'definitionURL', | |
SVG_ATTRS_ADJUSTMENT_MAP = { | |
'attributename': 'attributeName', | |
'attributetype': 'attributeType', | |
'basefrequency': 'baseFrequency', | |
'baseprofile': 'baseProfile', | |
'calcmode': 'calcMode', | |
'clippathunits': 'clipPathUnits', | |
'contentscripttype': 'contentScriptType', | |
'contentstyletype': 'contentStyleType', | |
'diffuseconstant': 'diffuseConstant', | |
'edgemode': 'edgeMode', | |
'externalresourcesrequired': 'externalResourcesRequired', | |
'filterres': 'filterRes', | |
'filterunits': 'filterUnits', | |
'glyphref': 'glyphRef', | |
'gradienttransform': 'gradientTransform', | |
'gradientunits': 'gradientUnits', | |
'kernelmatrix': 'kernelMatrix', | |
'kernelunitlength': 'kernelUnitLength', | |
'keypoints': 'keyPoints', | |
'keysplines': 'keySplines', | |
'keytimes': 'keyTimes', | |
'lengthadjust': 'lengthAdjust', | |
'limitingconeangle': 'limitingConeAngle', | |
'markerheight': 'markerHeight', | |
'markerunits': 'markerUnits', | |
'markerwidth': 'markerWidth', | |
'maskcontentunits': 'maskContentUnits', | |
'maskunits': 'maskUnits', | |
'numoctaves': 'numOctaves', | |
'pathlength': 'pathLength', | |
'patterncontentunits': 'patternContentUnits', | |
'patterntransform': 'patternTransform', | |
'patternunits': 'patternUnits', | |
'pointsatx': 'pointsAtX', | |
'pointsaty': 'pointsAtY', | |
'pointsatz': 'pointsAtZ', | |
'preservealpha': 'preserveAlpha', | |
'preserveaspectratio': 'preserveAspectRatio', | |
'primitiveunits': 'primitiveUnits', | |
'refx': 'refX', | |
'refy': 'refY', | |
'repeatcount': 'repeatCount', | |
'repeatdur': 'repeatDur', | |
'requiredextensions': 'requiredExtensions', | |
'requiredfeatures': 'requiredFeatures', | |
'specularconstant': 'specularConstant', | |
'specularexponent': 'specularExponent', | |
'spreadmethod': 'spreadMethod', | |
'startoffset': 'startOffset', | |
'stddeviation': 'stdDeviation', | |
'stitchtiles': 'stitchTiles', | |
'surfacescale': 'surfaceScale', | |
'systemlanguage': 'systemLanguage', | |
'tablevalues': 'tableValues', | |
'targetx': 'targetX', | |
'targety': 'targetY', | |
'textlength': 'textLength', | |
'viewbox': 'viewBox', | |
'viewtarget': 'viewTarget', | |
'xchannelselector': 'xChannelSelector', | |
'ychannelselector': 'yChannelSelector', | |
'zoomandpan': 'zoomAndPan' | |
}, | |
XML_ATTRS_ADJUSTMENT_MAP = { | |
'xlink:actuate': {prefix: 'xlink', name: 'actuate', namespace: NS.XLINK}, | |
'xlink:arcrole': {prefix: 'xlink', name: 'arcrole', namespace: NS.XLINK}, | |
'xlink:href': {prefix: 'xlink', name: 'href', namespace: NS.XLINK}, | |
'xlink:role': {prefix: 'xlink', name: 'role', namespace: NS.XLINK}, | |
'xlink:show': {prefix: 'xlink', name: 'show', namespace: NS.XLINK}, | |
'xlink:title': {prefix: 'xlink', name: 'title', namespace: NS.XLINK}, | |
'xlink:type': {prefix: 'xlink', name: 'type', namespace: NS.XLINK}, | |
'xml:base': {prefix: 'xml', name: 'base', namespace: NS.XML}, | |
'xml:lang': {prefix: 'xml', name: 'lang', namespace: NS.XML}, | |
'xml:space': {prefix: 'xml', name: 'space', namespace: NS.XML}, | |
'xmlns': {prefix: '', name: 'xmlns', namespace: NS.XMLNS}, | |
'xmlns:xlink': {prefix: 'xmlns', name: 'xlink', namespace: NS.XMLNS} | |
}; | |
//SVG tag names adjustment map | |
var SVG_TAG_NAMES_ADJUSTMENT_MAP = { | |
'altglyph': 'altGlyph', | |
'altglyphdef': 'altGlyphDef', | |
'altglyphitem': 'altGlyphItem', | |
'animatecolor': 'animateColor', | |
'animatemotion': 'animateMotion', | |
'animatetransform': 'animateTransform', | |
'clippath': 'clipPath', | |
'feblend': 'feBlend', | |
'fecolormatrix': 'feColorMatrix', | |
'fecomponenttransfer': 'feComponentTransfer', | |
'fecomposite': 'feComposite', | |
'feconvolvematrix': 'feConvolveMatrix', | |
'fediffuselighting': 'feDiffuseLighting', | |
'fedisplacementmap': 'feDisplacementMap', | |
'fedistantlight': 'feDistantLight', | |
'feflood': 'feFlood', | |
'fefunca': 'feFuncA', | |
'fefuncb': 'feFuncB', | |
'fefuncg': 'feFuncG', | |
'fefuncr': 'feFuncR', | |
'fegaussianblur': 'feGaussianBlur', | |
'feimage': 'feImage', | |
'femerge': 'feMerge', | |
'femergenode': 'feMergeNode', | |
'femorphology': 'feMorphology', | |
'feoffset': 'feOffset', | |
'fepointlight': 'fePointLight', | |
'fespecularlighting': 'feSpecularLighting', | |
'fespotlight': 'feSpotLight', | |
'fetile': 'feTile', | |
'feturbulence': 'feTurbulence', | |
'foreignobject': 'foreignObject', | |
'glyphref': 'glyphRef', | |
'lineargradient': 'linearGradient', | |
'radialgradient': 'radialGradient', | |
'textpath': 'textPath' | |
}; | |
//Tags that causes exit from foreign content | |
var EXITS_FOREIGN_CONTENT = {}; | |
EXITS_FOREIGN_CONTENT[$.B] = true; | |
EXITS_FOREIGN_CONTENT[$.BIG] = true; | |
EXITS_FOREIGN_CONTENT[$.BLOCKQUOTE] = true; | |
EXITS_FOREIGN_CONTENT[$.BODY] = true; | |
EXITS_FOREIGN_CONTENT[$.BR] = true; | |
EXITS_FOREIGN_CONTENT[$.CENTER] = true; | |
EXITS_FOREIGN_CONTENT[$.CODE] = true; | |
EXITS_FOREIGN_CONTENT[$.DD] = true; | |
EXITS_FOREIGN_CONTENT[$.DIV] = true; | |
EXITS_FOREIGN_CONTENT[$.DL] = true; | |
EXITS_FOREIGN_CONTENT[$.DT] = true; | |
EXITS_FOREIGN_CONTENT[$.EM] = true; | |
EXITS_FOREIGN_CONTENT[$.EMBED] = true; | |
EXITS_FOREIGN_CONTENT[$.H1] = true; | |
EXITS_FOREIGN_CONTENT[$.H2] = true; | |
EXITS_FOREIGN_CONTENT[$.H3] = true; | |
EXITS_FOREIGN_CONTENT[$.H4] = true; | |
EXITS_FOREIGN_CONTENT[$.H5] = true; | |
EXITS_FOREIGN_CONTENT[$.H6] = true; | |
EXITS_FOREIGN_CONTENT[$.HEAD] = true; | |
EXITS_FOREIGN_CONTENT[$.HR] = true; | |
EXITS_FOREIGN_CONTENT[$.I] = true; | |
EXITS_FOREIGN_CONTENT[$.IMG] = true; | |
EXITS_FOREIGN_CONTENT[$.LI] = true; | |
EXITS_FOREIGN_CONTENT[$.LISTING] = true; | |
EXITS_FOREIGN_CONTENT[$.MENU] = true; | |
EXITS_FOREIGN_CONTENT[$.META] = true; | |
EXITS_FOREIGN_CONTENT[$.NOBR] = true; | |
EXITS_FOREIGN_CONTENT[$.OL] = true; | |
EXITS_FOREIGN_CONTENT[$.P] = true; | |
EXITS_FOREIGN_CONTENT[$.PRE] = true; | |
EXITS_FOREIGN_CONTENT[$.RUBY] = true; | |
EXITS_FOREIGN_CONTENT[$.S] = true; | |
EXITS_FOREIGN_CONTENT[$.SMALL] = true; | |
EXITS_FOREIGN_CONTENT[$.SPAN] = true; | |
EXITS_FOREIGN_CONTENT[$.STRONG] = true; | |
EXITS_FOREIGN_CONTENT[$.STRIKE] = true; | |
EXITS_FOREIGN_CONTENT[$.SUB] = true; | |
EXITS_FOREIGN_CONTENT[$.SUP] = true; | |
EXITS_FOREIGN_CONTENT[$.TABLE] = true; | |
EXITS_FOREIGN_CONTENT[$.TT] = true; | |
EXITS_FOREIGN_CONTENT[$.U] = true; | |
EXITS_FOREIGN_CONTENT[$.UL] = true; | |
EXITS_FOREIGN_CONTENT[$.VAR] = true; | |
//Check exit from foreign content | |
exports.causesExit = function (startTagToken) { | |
var tn = startTagToken.tagName; | |
if (tn === $.FONT && (Tokenizer.getTokenAttr(startTagToken, ATTRS.COLOR) !== null || | |
Tokenizer.getTokenAttr(startTagToken, ATTRS.SIZE) !== null || | |
Tokenizer.getTokenAttr(startTagToken, ATTRS.FACE) !== null)) { | |
return true; | |
} | |
return EXITS_FOREIGN_CONTENT[tn]; | |
}; | |
//Token adjustments | |
exports.adjustTokenMathMLAttrs = function (token) { | |
for (var i = 0; i < token.attrs.length; i++) { | |
if (token.attrs[i].name === DEFINITION_URL_ATTR) { | |
token.attrs[i].name = ADJUSTED_DEFINITION_URL_ATTR; | |
break; | |
} | |
} | |
}; | |
exports.adjustTokenSVGAttrs = function (token) { | |
for (var i = 0; i < token.attrs.length; i++) { | |
var adjustedAttrName = SVG_ATTRS_ADJUSTMENT_MAP[token.attrs[i].name]; | |
if (adjustedAttrName) | |
token.attrs[i].name = adjustedAttrName; | |
} | |
}; | |
exports.adjustTokenXMLAttrs = function (token) { | |
for (var i = 0; i < token.attrs.length; i++) { | |
var adjustedAttrEntry = XML_ATTRS_ADJUSTMENT_MAP[token.attrs[i].name]; | |
if (adjustedAttrEntry) { | |
token.attrs[i].prefix = adjustedAttrEntry.prefix; | |
token.attrs[i].name = adjustedAttrEntry.name; | |
token.attrs[i].namespace = adjustedAttrEntry.namespace; | |
} | |
} | |
}; | |
exports.adjustTokenSVGTagName = function (token) { | |
var adjustedTagName = SVG_TAG_NAMES_ADJUSTMENT_MAP[token.tagName]; | |
if (adjustedTagName) | |
token.tagName = adjustedTagName; | |
}; | |
//Integration points | |
exports.isMathMLTextIntegrationPoint = function (tn, ns) { | |
return ns === NS.MATHML && (tn === $.MI || tn === $.MO || tn === $.MN || tn === $.MS || tn === $.MTEXT); | |
}; | |
exports.isHtmlIntegrationPoint = function (tn, ns, attrs) { | |
if (ns === NS.MATHML && tn === $.ANNOTATION_XML) { | |
for (var i = 0; i < attrs.length; i++) { | |
if (attrs[i].name === ATTRS.ENCODING) { | |
var value = attrs[i].value.toLowerCase(); | |
return value === MIME_TYPES.TEXT_HTML || value === MIME_TYPES.APPLICATION_XML; | |
} | |
} | |
} | |
return ns === NS.SVG && (tn === $.FOREIGN_OBJECT || tn === $.DESC || tn === $.TITLE); | |
}; |