)(<)(\\/*)#'; /** * @see https://regex101.com/r/hSG1JT/1 * @var string */ private const IS_OPENING_TAG_REGEX = '#^<[^\\/]*>$#'; /** * @see https://regex101.com/r/ywS62K/1 * @var string */ private const IS_CLOSING_TAG_REGEX = '#^\\s*<\\/#'; /** * @var int|null */ private $depth; /** * @var int */ private $indent = 4; /** * @var string */ private $padChar = ' '; /** * @var bool */ private $preserveWhitespace = \false; /** * @param \Rector\Core\ValueObject\Application\File $file */ public function supports($file) : bool { $smartFileInfo = $file->getSmartFileInfo(); return $smartFileInfo->getExtension() === 'xml'; } /** * @param \Rector\Core\ValueObject\Application\File $file * @param \Rector\FileFormatter\ValueObject\EditorConfigConfiguration $editorConfigConfiguration */ public function format($file, $editorConfigConfiguration) : void { $this->padChar = $editorConfigConfiguration->getIndentStyleCharacter(); $this->indent = $editorConfigConfiguration->getIndentSize(); $newFileContent = $this->formatXml($file->getFileContent(), $editorConfigConfiguration); $newFileContent .= $editorConfigConfiguration->getFinalNewline(); $file->changeFileContent($newFileContent); } public function createDefaultEditorConfigConfigurationBuilder() : \Rector\FileFormatter\ValueObjectFactory\EditorConfigConfigurationBuilder { $editorConfigConfigurationBuilder = new \Rector\FileFormatter\ValueObjectFactory\EditorConfigConfigurationBuilder(); $editorConfigConfigurationBuilder->withIndent(\Rector\FileFormatter\ValueObject\Indent::createTab()); return $editorConfigConfigurationBuilder; } private function formatXml(string $xml, \Rector\FileFormatter\ValueObject\EditorConfigConfiguration $editorConfigConfiguration) : string { $output = ''; $this->depth = 0; $parts = $this->getXmlParts($xml); if (\strncmp($parts[0], 'getNewline(); } foreach ($parts as $part) { $output .= $this->getOutputForPart($part, $editorConfigConfiguration); } return \trim($output); } /** * @return string[] */ private function getXmlParts(string $xml) : array { $withNewLines = \RectorPrefix20210808\Nette\Utils\Strings::replace(\trim($xml), self::XML_PARTS_REGEX, "\$1\n\$2\$3"); return \explode("\n", $withNewLines); } private function getOutputForPart(string $part, \Rector\FileFormatter\ValueObject\EditorConfigConfiguration $editorConfigConfiguration) : string { $output = ''; $this->runPre($part); if ($this->preserveWhitespace) { $output .= $part . $editorConfigConfiguration->getNewline(); } else { $part = \trim($part); $output .= $this->getPaddedString($part) . $editorConfigConfiguration->getNewline(); } $this->runPost($part); return $output; } private function runPre(string $part) : void { if ($this->isClosingTag($part)) { --$this->depth; } } private function runPost(string $part) : void { if ($this->isOpeningTag($part)) { ++$this->depth; } if ($this->isClosingCdataTag($part)) { $this->preserveWhitespace = \false; } if ($this->isOpeningCdataTag($part)) { $this->preserveWhitespace = \true; } } private function getPaddedString(string $part) : string { return \str_pad($part, \strlen($part) + $this->depth * $this->indent, $this->padChar, \STR_PAD_LEFT); } private function isOpeningTag(string $part) : bool { return (bool) \RectorPrefix20210808\Nette\Utils\Strings::match($part, self::IS_OPENING_TAG_REGEX); } private function isClosingTag(string $part) : bool { return (bool) \RectorPrefix20210808\Nette\Utils\Strings::match($part, self::IS_CLOSING_TAG_REGEX); } private function isOpeningCdataTag(string $part) : bool { return \strpos($part, '') !== \false; } }