securityos/node_modules/parse5/dist/common/foreign-content.js

230 lines
6.3 KiB
JavaScript
Raw Normal View History

2024-09-06 15:32:35 +00:00
import { TAG_ID as $, NS, ATTRS, getTagID } from './html.js';
//MIME types
const MIME_TYPES = {
TEXT_HTML: 'text/html',
APPLICATION_XML: 'application/xhtml+xml',
};
//Attributes
const DEFINITION_URL_ATTR = 'definitionurl';
const ADJUSTED_DEFINITION_URL_ATTR = 'definitionURL';
const SVG_ATTRS_ADJUSTMENT_MAP = new Map([
'attributeName',
'attributeType',
'baseFrequency',
'baseProfile',
'calcMode',
'clipPathUnits',
'diffuseConstant',
'edgeMode',
'filterUnits',
'glyphRef',
'gradientTransform',
'gradientUnits',
'kernelMatrix',
'kernelUnitLength',
'keyPoints',
'keySplines',
'keyTimes',
'lengthAdjust',
'limitingConeAngle',
'markerHeight',
'markerUnits',
'markerWidth',
'maskContentUnits',
'maskUnits',
'numOctaves',
'pathLength',
'patternContentUnits',
'patternTransform',
'patternUnits',
'pointsAtX',
'pointsAtY',
'pointsAtZ',
'preserveAlpha',
'preserveAspectRatio',
'primitiveUnits',
'refX',
'refY',
'repeatCount',
'repeatDur',
'requiredExtensions',
'requiredFeatures',
'specularConstant',
'specularExponent',
'spreadMethod',
'startOffset',
'stdDeviation',
'stitchTiles',
'surfaceScale',
'systemLanguage',
'tableValues',
'targetX',
'targetY',
'textLength',
'viewBox',
'viewTarget',
'xChannelSelector',
'yChannelSelector',
'zoomAndPan',
].map((attr) => [attr.toLowerCase(), attr]));
const XML_ATTRS_ADJUSTMENT_MAP = new 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
export const SVG_TAG_NAMES_ADJUSTMENT_MAP = new Map([
'altGlyph',
'altGlyphDef',
'altGlyphItem',
'animateColor',
'animateMotion',
'animateTransform',
'clipPath',
'feBlend',
'feColorMatrix',
'feComponentTransfer',
'feComposite',
'feConvolveMatrix',
'feDiffuseLighting',
'feDisplacementMap',
'feDistantLight',
'feFlood',
'feFuncA',
'feFuncB',
'feFuncG',
'feFuncR',
'feGaussianBlur',
'feImage',
'feMerge',
'feMergeNode',
'feMorphology',
'feOffset',
'fePointLight',
'feSpecularLighting',
'feSpotLight',
'feTile',
'feTurbulence',
'foreignObject',
'glyphRef',
'linearGradient',
'radialGradient',
'textPath',
].map((tn) => [tn.toLowerCase(), tn]));
//Tags that causes exit from foreign content
const EXITS_FOREIGN_CONTENT = new Set([
$.B,
$.BIG,
$.BLOCKQUOTE,
$.BODY,
$.BR,
$.CENTER,
$.CODE,
$.DD,
$.DIV,
$.DL,
$.DT,
$.EM,
$.EMBED,
$.H1,
$.H2,
$.H3,
$.H4,
$.H5,
$.H6,
$.HEAD,
$.HR,
$.I,
$.IMG,
$.LI,
$.LISTING,
$.MENU,
$.META,
$.NOBR,
$.OL,
$.P,
$.PRE,
$.RUBY,
$.S,
$.SMALL,
$.SPAN,
$.STRONG,
$.STRIKE,
$.SUB,
$.SUP,
$.TABLE,
$.TT,
$.U,
$.UL,
$.VAR,
]);
//Check exit from foreign content
export function causesExit(startTagToken) {
const tn = startTagToken.tagID;
const isFontWithAttrs = tn === $.FONT &&
startTagToken.attrs.some(({ name }) => name === ATTRS.COLOR || name === ATTRS.SIZE || name === ATTRS.FACE);
return isFontWithAttrs || EXITS_FOREIGN_CONTENT.has(tn);
}
//Token adjustments
export function adjustTokenMathMLAttrs(token) {
for (let i = 0; i < token.attrs.length; i++) {
if (token.attrs[i].name === DEFINITION_URL_ATTR) {
token.attrs[i].name = ADJUSTED_DEFINITION_URL_ATTR;
break;
}
}
}
export function adjustTokenSVGAttrs(token) {
for (let i = 0; i < token.attrs.length; i++) {
const adjustedAttrName = SVG_ATTRS_ADJUSTMENT_MAP.get(token.attrs[i].name);
if (adjustedAttrName != null) {
token.attrs[i].name = adjustedAttrName;
}
}
}
export function adjustTokenXMLAttrs(token) {
for (let i = 0; i < token.attrs.length; i++) {
const adjustedAttrEntry = XML_ATTRS_ADJUSTMENT_MAP.get(token.attrs[i].name);
if (adjustedAttrEntry) {
token.attrs[i].prefix = adjustedAttrEntry.prefix;
token.attrs[i].name = adjustedAttrEntry.name;
token.attrs[i].namespace = adjustedAttrEntry.namespace;
}
}
}
export function adjustTokenSVGTagName(token) {
const adjustedTagName = SVG_TAG_NAMES_ADJUSTMENT_MAP.get(token.tagName);
if (adjustedTagName != null) {
token.tagName = adjustedTagName;
token.tagID = getTagID(token.tagName);
}
}
//Integration points
function isMathMLTextIntegrationPoint(tn, ns) {
return ns === NS.MATHML && (tn === $.MI || tn === $.MO || tn === $.MN || tn === $.MS || tn === $.MTEXT);
}
function isHtmlIntegrationPoint(tn, ns, attrs) {
if (ns === NS.MATHML && tn === $.ANNOTATION_XML) {
for (let i = 0; i < attrs.length; i++) {
if (attrs[i].name === ATTRS.ENCODING) {
const 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);
}
export function isIntegrationPoint(tn, ns, attrs, foreignNS) {
return (((!foreignNS || foreignNS === NS.HTML) && isHtmlIntegrationPoint(tn, ns, attrs)) ||
((!foreignNS || foreignNS === NS.MATHML) && isMathMLTextIntegrationPoint(tn, ns)));
}
//# sourceMappingURL=foreign-content.js.map