Home | History | Annotate | Download | only in common
      1 'use strict';
      2 
      3 var Tokenizer = require('../tokenization/tokenizer'),
      4     HTML = require('./html');
      5 
      6 //Aliases
      7 var $ = HTML.TAG_NAMES,
      8     NS = HTML.NAMESPACES,
      9     ATTRS = HTML.ATTRS;
     10 
     11 
     12 //MIME types
     13 var MIME_TYPES = {
     14     TEXT_HTML: 'text/html',
     15     APPLICATION_XML: 'application/xhtml+xml'
     16 };
     17 
     18 //Attributes
     19 var DEFINITION_URL_ATTR = 'definitionurl',
     20     ADJUSTED_DEFINITION_URL_ATTR = 'definitionURL',
     21     SVG_ATTRS_ADJUSTMENT_MAP = {
     22         'attributename': 'attributeName',
     23         'attributetype': 'attributeType',
     24         'basefrequency': 'baseFrequency',
     25         'baseprofile': 'baseProfile',
     26         'calcmode': 'calcMode',
     27         'clippathunits': 'clipPathUnits',
     28         'contentscripttype': 'contentScriptType',
     29         'contentstyletype': 'contentStyleType',
     30         'diffuseconstant': 'diffuseConstant',
     31         'edgemode': 'edgeMode',
     32         'externalresourcesrequired': 'externalResourcesRequired',
     33         'filterres': 'filterRes',
     34         'filterunits': 'filterUnits',
     35         'glyphref': 'glyphRef',
     36         'gradienttransform': 'gradientTransform',
     37         'gradientunits': 'gradientUnits',
     38         'kernelmatrix': 'kernelMatrix',
     39         'kernelunitlength': 'kernelUnitLength',
     40         'keypoints': 'keyPoints',
     41         'keysplines': 'keySplines',
     42         'keytimes': 'keyTimes',
     43         'lengthadjust': 'lengthAdjust',
     44         'limitingconeangle': 'limitingConeAngle',
     45         'markerheight': 'markerHeight',
     46         'markerunits': 'markerUnits',
     47         'markerwidth': 'markerWidth',
     48         'maskcontentunits': 'maskContentUnits',
     49         'maskunits': 'maskUnits',
     50         'numoctaves': 'numOctaves',
     51         'pathlength': 'pathLength',
     52         'patterncontentunits': 'patternContentUnits',
     53         'patterntransform': 'patternTransform',
     54         'patternunits': 'patternUnits',
     55         'pointsatx': 'pointsAtX',
     56         'pointsaty': 'pointsAtY',
     57         'pointsatz': 'pointsAtZ',
     58         'preservealpha': 'preserveAlpha',
     59         'preserveaspectratio': 'preserveAspectRatio',
     60         'primitiveunits': 'primitiveUnits',
     61         'refx': 'refX',
     62         'refy': 'refY',
     63         'repeatcount': 'repeatCount',
     64         'repeatdur': 'repeatDur',
     65         'requiredextensions': 'requiredExtensions',
     66         'requiredfeatures': 'requiredFeatures',
     67         'specularconstant': 'specularConstant',
     68         'specularexponent': 'specularExponent',
     69         'spreadmethod': 'spreadMethod',
     70         'startoffset': 'startOffset',
     71         'stddeviation': 'stdDeviation',
     72         'stitchtiles': 'stitchTiles',
     73         'surfacescale': 'surfaceScale',
     74         'systemlanguage': 'systemLanguage',
     75         'tablevalues': 'tableValues',
     76         'targetx': 'targetX',
     77         'targety': 'targetY',
     78         'textlength': 'textLength',
     79         'viewbox': 'viewBox',
     80         'viewtarget': 'viewTarget',
     81         'xchannelselector': 'xChannelSelector',
     82         'ychannelselector': 'yChannelSelector',
     83         'zoomandpan': 'zoomAndPan'
     84     },
     85     XML_ATTRS_ADJUSTMENT_MAP = {
     86         'xlink:actuate': {prefix: 'xlink', name: 'actuate', namespace: NS.XLINK},
     87         'xlink:arcrole': {prefix: 'xlink', name: 'arcrole', namespace: NS.XLINK},
     88         'xlink:href': {prefix: 'xlink', name: 'href', namespace: NS.XLINK},
     89         'xlink:role': {prefix: 'xlink', name: 'role', namespace: NS.XLINK},
     90         'xlink:show': {prefix: 'xlink', name: 'show', namespace: NS.XLINK},
     91         'xlink:title': {prefix: 'xlink', name: 'title', namespace: NS.XLINK},
     92         'xlink:type': {prefix: 'xlink', name: 'type', namespace: NS.XLINK},
     93         'xml:base': {prefix: 'xml', name: 'base', namespace: NS.XML},
     94         'xml:lang': {prefix: 'xml', name: 'lang', namespace: NS.XML},
     95         'xml:space': {prefix: 'xml', name: 'space', namespace: NS.XML},
     96         'xmlns': {prefix: '', name: 'xmlns', namespace: NS.XMLNS},
     97         'xmlns:xlink': {prefix: 'xmlns', name: 'xlink', namespace: NS.XMLNS}
     98 
     99     };
    100 
    101 //SVG tag names adjustment map
    102 var SVG_TAG_NAMES_ADJUSTMENT_MAP = {
    103     'altglyph': 'altGlyph',
    104     'altglyphdef': 'altGlyphDef',
    105     'altglyphitem': 'altGlyphItem',
    106     'animatecolor': 'animateColor',
    107     'animatemotion': 'animateMotion',
    108     'animatetransform': 'animateTransform',
    109     'clippath': 'clipPath',
    110     'feblend': 'feBlend',
    111     'fecolormatrix': 'feColorMatrix',
    112     'fecomponenttransfer': 'feComponentTransfer',
    113     'fecomposite': 'feComposite',
    114     'feconvolvematrix': 'feConvolveMatrix',
    115     'fediffuselighting': 'feDiffuseLighting',
    116     'fedisplacementmap': 'feDisplacementMap',
    117     'fedistantlight': 'feDistantLight',
    118     'feflood': 'feFlood',
    119     'fefunca': 'feFuncA',
    120     'fefuncb': 'feFuncB',
    121     'fefuncg': 'feFuncG',
    122     'fefuncr': 'feFuncR',
    123     'fegaussianblur': 'feGaussianBlur',
    124     'feimage': 'feImage',
    125     'femerge': 'feMerge',
    126     'femergenode': 'feMergeNode',
    127     'femorphology': 'feMorphology',
    128     'feoffset': 'feOffset',
    129     'fepointlight': 'fePointLight',
    130     'fespecularlighting': 'feSpecularLighting',
    131     'fespotlight': 'feSpotLight',
    132     'fetile': 'feTile',
    133     'feturbulence': 'feTurbulence',
    134     'foreignobject': 'foreignObject',
    135     'glyphref': 'glyphRef',
    136     'lineargradient': 'linearGradient',
    137     'radialgradient': 'radialGradient',
    138     'textpath': 'textPath'
    139 };
    140 
    141 //Tags that causes exit from foreign content
    142 var EXITS_FOREIGN_CONTENT = {};
    143 
    144 EXITS_FOREIGN_CONTENT[$.B] = true;
    145 EXITS_FOREIGN_CONTENT[$.BIG] = true;
    146 EXITS_FOREIGN_CONTENT[$.BLOCKQUOTE] = true;
    147 EXITS_FOREIGN_CONTENT[$.BODY] = true;
    148 EXITS_FOREIGN_CONTENT[$.BR] = true;
    149 EXITS_FOREIGN_CONTENT[$.CENTER] = true;
    150 EXITS_FOREIGN_CONTENT[$.CODE] = true;
    151 EXITS_FOREIGN_CONTENT[$.DD] = true;
    152 EXITS_FOREIGN_CONTENT[$.DIV] = true;
    153 EXITS_FOREIGN_CONTENT[$.DL] = true;
    154 EXITS_FOREIGN_CONTENT[$.DT] = true;
    155 EXITS_FOREIGN_CONTENT[$.EM] = true;
    156 EXITS_FOREIGN_CONTENT[$.EMBED] = true;
    157 EXITS_FOREIGN_CONTENT[$.H1] = true;
    158 EXITS_FOREIGN_CONTENT[$.H2] = true;
    159 EXITS_FOREIGN_CONTENT[$.H3] = true;
    160 EXITS_FOREIGN_CONTENT[$.H4] = true;
    161 EXITS_FOREIGN_CONTENT[$.H5] = true;
    162 EXITS_FOREIGN_CONTENT[$.H6] = true;
    163 EXITS_FOREIGN_CONTENT[$.HEAD] = true;
    164 EXITS_FOREIGN_CONTENT[$.HR] = true;
    165 EXITS_FOREIGN_CONTENT[$.I] = true;
    166 EXITS_FOREIGN_CONTENT[$.IMG] = true;
    167 EXITS_FOREIGN_CONTENT[$.LI] = true;
    168 EXITS_FOREIGN_CONTENT[$.LISTING] = true;
    169 EXITS_FOREIGN_CONTENT[$.MENU] = true;
    170 EXITS_FOREIGN_CONTENT[$.META] = true;
    171 EXITS_FOREIGN_CONTENT[$.NOBR] = true;
    172 EXITS_FOREIGN_CONTENT[$.OL] = true;
    173 EXITS_FOREIGN_CONTENT[$.P] = true;
    174 EXITS_FOREIGN_CONTENT[$.PRE] = true;
    175 EXITS_FOREIGN_CONTENT[$.RUBY] = true;
    176 EXITS_FOREIGN_CONTENT[$.S] = true;
    177 EXITS_FOREIGN_CONTENT[$.SMALL] = true;
    178 EXITS_FOREIGN_CONTENT[$.SPAN] = true;
    179 EXITS_FOREIGN_CONTENT[$.STRONG] = true;
    180 EXITS_FOREIGN_CONTENT[$.STRIKE] = true;
    181 EXITS_FOREIGN_CONTENT[$.SUB] = true;
    182 EXITS_FOREIGN_CONTENT[$.SUP] = true;
    183 EXITS_FOREIGN_CONTENT[$.TABLE] = true;
    184 EXITS_FOREIGN_CONTENT[$.TT] = true;
    185 EXITS_FOREIGN_CONTENT[$.U] = true;
    186 EXITS_FOREIGN_CONTENT[$.UL] = true;
    187 EXITS_FOREIGN_CONTENT[$.VAR] = true;
    188 
    189 //Check exit from foreign content
    190 exports.causesExit = function (startTagToken) {
    191     var tn = startTagToken.tagName;
    192 
    193     if (tn === $.FONT && (Tokenizer.getTokenAttr(startTagToken, ATTRS.COLOR) !== null ||
    194         Tokenizer.getTokenAttr(startTagToken, ATTRS.SIZE) !== null ||
    195         Tokenizer.getTokenAttr(startTagToken, ATTRS.FACE) !== null)) {
    196         return true;
    197     }
    198 
    199     return EXITS_FOREIGN_CONTENT[tn];
    200 };
    201 
    202 //Token adjustments
    203 exports.adjustTokenMathMLAttrs = function (token) {
    204     for (var i = 0; i < token.attrs.length; i++) {
    205         if (token.attrs[i].name === DEFINITION_URL_ATTR) {
    206             token.attrs[i].name = ADJUSTED_DEFINITION_URL_ATTR;
    207             break;
    208         }
    209     }
    210 };
    211 
    212 exports.adjustTokenSVGAttrs = function (token) {
    213     for (var i = 0; i < token.attrs.length; i++) {
    214         var adjustedAttrName = SVG_ATTRS_ADJUSTMENT_MAP[token.attrs[i].name];
    215 
    216         if (adjustedAttrName)
    217             token.attrs[i].name = adjustedAttrName;
    218     }
    219 };
    220 
    221 exports.adjustTokenXMLAttrs = function (token) {
    222     for (var i = 0; i < token.attrs.length; i++) {
    223         var adjustedAttrEntry = XML_ATTRS_ADJUSTMENT_MAP[token.attrs[i].name];
    224 
    225         if (adjustedAttrEntry) {
    226             token.attrs[i].prefix = adjustedAttrEntry.prefix;
    227             token.attrs[i].name = adjustedAttrEntry.name;
    228             token.attrs[i].namespace = adjustedAttrEntry.namespace;
    229         }
    230     }
    231 };
    232 
    233 exports.adjustTokenSVGTagName = function (token) {
    234     var adjustedTagName = SVG_TAG_NAMES_ADJUSTMENT_MAP[token.tagName];
    235 
    236     if (adjustedTagName)
    237         token.tagName = adjustedTagName;
    238 };
    239 
    240 //Integration points
    241 exports.isMathMLTextIntegrationPoint = function (tn, ns) {
    242     return ns === NS.MATHML && (tn === $.MI || tn === $.MO || tn === $.MN || tn === $.MS || tn === $.MTEXT);
    243 };
    244 
    245 exports.isHtmlIntegrationPoint = function (tn, ns, attrs) {
    246     if (ns === NS.MATHML && tn === $.ANNOTATION_XML) {
    247         for (var i = 0; i < attrs.length; i++) {
    248             if (attrs[i].name === ATTRS.ENCODING) {
    249                 var value = attrs[i].value.toLowerCase();
    250 
    251                 return value === MIME_TYPES.TEXT_HTML || value === MIME_TYPES.APPLICATION_XML;
    252             }
    253         }
    254     }
    255 
    256     return ns === NS.SVG && (tn === $.FOREIGN_OBJECT || tn === $.DESC || tn === $.TITLE);
    257 };
    258