• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3var Tokenizer = require('../tokenization/tokenizer'),
4    HTML = require('./html');
5
6//Aliases
7var $ = HTML.TAG_NAMES,
8    NS = HTML.NAMESPACES,
9    ATTRS = HTML.ATTRS;
10
11
12//MIME types
13var MIME_TYPES = {
14    TEXT_HTML: 'text/html',
15    APPLICATION_XML: 'application/xhtml+xml'
16};
17
18//Attributes
19var 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
102var 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
142var EXITS_FOREIGN_CONTENT = {};
143
144EXITS_FOREIGN_CONTENT[$.B] = true;
145EXITS_FOREIGN_CONTENT[$.BIG] = true;
146EXITS_FOREIGN_CONTENT[$.BLOCKQUOTE] = true;
147EXITS_FOREIGN_CONTENT[$.BODY] = true;
148EXITS_FOREIGN_CONTENT[$.BR] = true;
149EXITS_FOREIGN_CONTENT[$.CENTER] = true;
150EXITS_FOREIGN_CONTENT[$.CODE] = true;
151EXITS_FOREIGN_CONTENT[$.DD] = true;
152EXITS_FOREIGN_CONTENT[$.DIV] = true;
153EXITS_FOREIGN_CONTENT[$.DL] = true;
154EXITS_FOREIGN_CONTENT[$.DT] = true;
155EXITS_FOREIGN_CONTENT[$.EM] = true;
156EXITS_FOREIGN_CONTENT[$.EMBED] = true;
157EXITS_FOREIGN_CONTENT[$.H1] = true;
158EXITS_FOREIGN_CONTENT[$.H2] = true;
159EXITS_FOREIGN_CONTENT[$.H3] = true;
160EXITS_FOREIGN_CONTENT[$.H4] = true;
161EXITS_FOREIGN_CONTENT[$.H5] = true;
162EXITS_FOREIGN_CONTENT[$.H6] = true;
163EXITS_FOREIGN_CONTENT[$.HEAD] = true;
164EXITS_FOREIGN_CONTENT[$.HR] = true;
165EXITS_FOREIGN_CONTENT[$.I] = true;
166EXITS_FOREIGN_CONTENT[$.IMG] = true;
167EXITS_FOREIGN_CONTENT[$.LI] = true;
168EXITS_FOREIGN_CONTENT[$.LISTING] = true;
169EXITS_FOREIGN_CONTENT[$.MENU] = true;
170EXITS_FOREIGN_CONTENT[$.META] = true;
171EXITS_FOREIGN_CONTENT[$.NOBR] = true;
172EXITS_FOREIGN_CONTENT[$.OL] = true;
173EXITS_FOREIGN_CONTENT[$.P] = true;
174EXITS_FOREIGN_CONTENT[$.PRE] = true;
175EXITS_FOREIGN_CONTENT[$.RUBY] = true;
176EXITS_FOREIGN_CONTENT[$.S] = true;
177EXITS_FOREIGN_CONTENT[$.SMALL] = true;
178EXITS_FOREIGN_CONTENT[$.SPAN] = true;
179EXITS_FOREIGN_CONTENT[$.STRONG] = true;
180EXITS_FOREIGN_CONTENT[$.STRIKE] = true;
181EXITS_FOREIGN_CONTENT[$.SUB] = true;
182EXITS_FOREIGN_CONTENT[$.SUP] = true;
183EXITS_FOREIGN_CONTENT[$.TABLE] = true;
184EXITS_FOREIGN_CONTENT[$.TT] = true;
185EXITS_FOREIGN_CONTENT[$.U] = true;
186EXITS_FOREIGN_CONTENT[$.UL] = true;
187EXITS_FOREIGN_CONTENT[$.VAR] = true;
188
189//Check exit from foreign content
190exports.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
203exports.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
212exports.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
221exports.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
233exports.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
241exports.isMathMLTextIntegrationPoint = function (tn, ns) {
242    return ns === NS.MATHML && (tn === $.MI || tn === $.MO || tn === $.MN || tn === $.MS || tn === $.MTEXT);
243};
244
245exports.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