X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/mediawiki.git/blobdiff_plain/19e297c21b10b1b8a3acad5e73fc71dcb35db44a..6932310fd58ebef145fa01eb76edf7150284d8ea:/vendor/wikimedia/remex-html/RemexHtml/TreeBuilder/InForeignContent.php diff --git a/vendor/wikimedia/remex-html/RemexHtml/TreeBuilder/InForeignContent.php b/vendor/wikimedia/remex-html/RemexHtml/TreeBuilder/InForeignContent.php new file mode 100644 index 00000000..d4af5be9 --- /dev/null +++ b/vendor/wikimedia/remex-html/RemexHtml/TreeBuilder/InForeignContent.php @@ -0,0 +1,220 @@ + true, + 'big' => true, + 'blockquote' => true, + 'body' => true, + 'br' => true, + 'center' => true, + 'code' => true, + 'dd' => true, + 'div' => true, + 'dl' => true, + 'dt' => true, + 'em' => true, + 'embed' => true, + 'h1' => true, + 'h2' => true, + 'h3' => true, + 'h4' => true, + 'h5' => true, + 'h6' => true, + 'head' => true, + 'hr' => true, + 'i' => true, + 'img' => true, + 'li' => true, + 'listing' => true, + 'menu' => true, + 'meta' => true, + 'nobr' => true, + 'ol' => true, + 'p' => true, + 'pre' => true, + 'ruby' => true, + 's' => true, + 'small' => true, + 'span' => true, + 'strong' => true, + 'strike' => true, + 'sub' => true, + 'sup' => true, + 'table' => true, + 'tt' => true, + 'u' => true, + 'ul' => true, + 'var' => true, + ]; + + /** + * The table for correcting the tag names of SVG elements, given in the + * "Any other start tag" section of the spec. + */ + private static $svgElementCase = [ + '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', + 'fedropshadow' => 'feDropShadow', + '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', + ]; + + public function characters( $text, $start, $length, $sourceStart, $sourceLength ) { + $builder = $this->builder; + + while ( $length ) { + $normalLength = strcspn( $text, "\0\t\n\f\r ", $start, $length ); + if ( $normalLength ) { + $builder->framesetOK = false; + $builder->insertCharacters( $text, $start, $normalLength, + $sourceStart, $sourceLength ); + } + $start += $normalLength; + $length -= $normalLength; + $sourceStart += $normalLength; + $sourceLength -= $normalLength; + if ( !$length ) { + break; + } + + $char = $text[$start]; + if ( $char === "\0" ) { + $builder->error( "replaced null character", $sourceStart ); + $builder->insertCharacters( "\xef\xbf\xbd", 0, 3, $sourceStart, $sourceLength ); + $start++; + $length--; + $sourceStart++; + $sourceLength--; + } else { + // Whitespace + $wsLength = strspn( $text, "\t\n\f\r ", $start, $length ); + $builder->insertCharacters( $text, $start, $wsLength, $sourceStart, $wsLength ); + $start += $wsLength; + $length -= $wsLength; + $sourceStart += $wsLength; + $sourceLength -= $wsLength; + } + } + } + + private function isIntegrationPoint( Element $element ) { + return $element->namespace === HTMLData::NS_HTML + || $element->isMathmlTextIntegration() + || $element->isHtmlIntegration(); + } + + public function startTag( $name, Attributes $attrs, $selfClose, $sourceStart, $sourceLength ) { + $builder = $this->builder; + $stack = $builder->stack; + $dispatcher = $this->dispatcher; + + if ( isset( self::$notAllowed[$name] ) ) { + $allowed = false; + } elseif ( $name === 'font' && ( + isset( $attrs['color'] ) || isset( $attrs['face'] ) || isset( $attrs['size'] ) ) + ) { + $allowed = false; + } else { + $allowed = true; + } + + if ( !$allowed ) { + $builder->error( "unexpected <$name> tag in foreign content", $sourceStart ); + if ( !$builder->isFragment ) { + do { + $builder->pop( $sourceStart, 0 ); + } while ( $stack->current && !$this->isIntegrationPoint( $stack->current ) ); + $dispatcher->startTag( $name, $attrs, $selfClose, $sourceStart, $sourceLength ); + return; + } + } + + $acnNs = $builder->adjustedCurrentNode()->namespace; + if ( $acnNs === HTMLData::NS_MATHML ) { + $attrs = new ForeignAttributes( $attrs, 'math' ); + } elseif ( $acnNs === HTMLData::NS_SVG ) { + $attrs = new ForeignAttributes( $attrs, 'svg' ); + if ( isset( self::$svgElementCase[$name] ) ) { + $name = self::$svgElementCase[$name]; + } + } else { + $attrs = new ForeignAttributes( $attrs, 'other' ); + } + $dispatcher->ack = true; + $builder->insertForeign( $acnNs, $name, $attrs, $selfClose, $sourceStart, $sourceLength ); + } + + public function endTag( $name, $sourceStart, $sourceLength ) { + $builder = $this->builder; + $stack = $builder->stack; + $dispatcher = $this->dispatcher; + + $node = $stack->current; + if ( strcasecmp( $node->name, $name ) !== 0 ) { + $builder->error( "mismatched end tag in foreign content", $sourceStart ); + } + for ( $idx = $stack->length() - 1; $idx > 0; $idx-- ) { + if ( strcasecmp( $node->name, $name ) === 0 ) { + $builder->popAllUpToElement( $node, $sourceStart, $sourceLength ); + break; + } + $node = $stack->item( $idx - 1 ); + if ( $node->namespace === HTMLData::NS_HTML ) { + $dispatcher->getHandler()->endTag( $name, $sourceStart, $sourceLength ); + break; + } + } + } + + public function endDocument( $pos ) { + throw new TreeBuilderError( "unspecified, presumed unreachable" ); + } +}