/** * Render formatting options onto text */ public function render() { $offset = 0; foreach ($this->formats as $format) { $attrs = $this->attributes($format->type, !empty($format->attrs) ? $format->attrs : null); $opening = '<' . $format->type . "{$attrs}>"; $closing = '</' . $format->type . '>'; $this->text = UTF8::substr_replace($this->text, $opening, $format->from + $offset, 0); $offset += strlen($opening); $this->text = UTF8::substr_replace($this->text, $closing, $format->to + $offset, 0); $offset += strlen($closing); } // create a temporary document and load the plain html $tmpDoc = new DOMDocument(); // purify HTML to convert HTML chars in text nodes etc. $config = HTMLPurifier_Config::createDefault(); $config->set('HTML.Trusted', true); $this->text = (new HTMLPurifier($config))->purify($this->text); $tmpDoc->loadHTML('<?xml encoding="UTF-8"><html><body>' . $this->text . '</body></html>'); $tmpDoc->encoding = 'UTF-8'; // import and attach the created nodes to the paragraph foreach ($tmpDoc->getElementsByTagName('body')->item(0)->childNodes as $node) { $node = $this->dom->importNode($node, true); $this->paragraph->appendChild($node); } return $this->paragraph; }