Example #1
0
 /**
  * Finish invocation.
  * @return Texy\HtmlElement|FALSE
  */
 public function solve(Texy\HandlerInvocation $invocation, $emoticon, $raw)
 {
     $texy = $this->texy;
     $file = $this->icons[$emoticon];
     $el = new Texy\HtmlElement('img');
     $el->attrs['src'] = Texy\Helpers::prependRoot($file, $this->root === NULL ? $texy->imageModule->root : $this->root);
     $el->attrs['alt'] = $raw;
     $el->attrs['class'][] = $this->class;
     // file path
     $file = rtrim($this->fileRoot === NULL ? $texy->imageModule->fileRoot : $this->fileRoot, '/\\') . '/' . $file;
     if (@is_file($file)) {
         // intentionally @
         $size = @getImageSize($file);
         // intentionally @
         if (is_array($size)) {
             $el->attrs['width'] = $size[0];
             $el->attrs['height'] = $size[1];
         }
     }
     $texy->summary['images'][] = $el->attrs['src'];
     return $el;
 }
Example #2
0
 /**
  * Converts cite source to URL.
  * @param  string
  * @return string|NULL
  */
 public function citeLink($link)
 {
     $texy = $this->texy;
     if ($link == NULL) {
         return NULL;
     }
     if ($link[0] === '[') {
         // [ref]
         $link = substr($link, 1, -1);
         $ref = $texy->linkModule->getReference($link);
         if ($ref) {
             return Texy\Helpers::prependRoot($ref->URL, $texy->linkModule->root);
         }
     }
     // special supported case
     if (strncasecmp($link, 'www.', 4) === 0) {
         return 'http://' . $link;
     }
     return Texy\Helpers::prependRoot($link, $texy->linkModule->root);
 }
Example #3
0
 /**
  * Callback function: <tag> | </tag> | ....
  * @return string
  * @internal
  */
 public function cb($matches)
 {
     // html tag
     list(, $mText, $mComment, $mEnd, $mTag, $mAttr, $mEmpty) = $matches;
     // [1] => text
     // [1] => !-- comment --
     // [2] => /
     // [3] => TAG
     // [4] => ... (attributes)
     // [5] => / (empty)
     $s = '';
     // phase #1 - stuff between tags
     if ($mText !== '') {
         $item = reset($this->tagStack);
         if ($item && !isset($item['dtdContent']['%DATA'])) {
             // text not allowed?
         } elseif (array_intersect(array_keys($this->tagUsed, TRUE), $this->preserveSpaces)) {
             // inside pre & textarea preserve spaces
             $s = Texy\Helpers::freezeSpaces($mText);
         } else {
             $s = Regexp::replace($mText, '#[ \\n]+#', ' ');
             // otherwise shrink multiple spaces
         }
     }
     // phase #2 - HTML comment
     if ($mComment) {
         return $s . '<' . Texy\Helpers::freezeSpaces($mComment) . '>';
     }
     // phase #3 - HTML tag
     $mEmpty = $mEmpty || isset(HtmlElement::$emptyElements[$mTag]);
     if ($mEmpty && $mEnd) {
         return $s;
         // bad tag; /end/
     }
     if ($mEnd) {
         // end tag
         // has start tag?
         if (empty($this->tagUsed[$mTag])) {
             return $s;
         }
         // autoclose tags
         $tmp = [];
         $back = TRUE;
         foreach ($this->tagStack as $i => $item) {
             $tag = $item['tag'];
             $s .= $item['close'];
             $this->space -= $item['indent'];
             $this->tagUsed[$tag]--;
             $back = $back && isset(HtmlElement::$inlineElements[$tag]);
             unset($this->tagStack[$i]);
             if ($tag === $mTag) {
                 break;
             }
             array_unshift($tmp, $item);
         }
         if (!$back || !$tmp) {
             return $s;
         }
         // allowed-check (nejspis neni ani potreba)
         $item = reset($this->tagStack);
         $dtdContent = $item ? $item['dtdContent'] : $this->baseDTD;
         if (!isset($dtdContent[$tmp[0]['tag']])) {
             return $s;
         }
         // autoopen tags
         foreach ($tmp as $item) {
             $s .= $item['open'];
             $this->space += $item['indent'];
             $this->tagUsed[$item['tag']]++;
             array_unshift($this->tagStack, $item);
         }
     } else {
         // start tag
         $dtdContent = $this->baseDTD;
         if (!isset($this->texy->dtd[$mTag])) {
             // unknown (non-html) tag
             $allowed = TRUE;
             $item = reset($this->tagStack);
             if ($item) {
                 $dtdContent = $item['dtdContent'];
             }
         } else {
             // optional end tag closing
             foreach ($this->tagStack as $i => $item) {
                 // is tag allowed here?
                 $dtdContent = $item['dtdContent'];
                 if (isset($dtdContent[$mTag])) {
                     break;
                 }
                 $tag = $item['tag'];
                 // auto-close hidden, optional and inline tags
                 if ($item['close'] && (!isset(HtmlElement::$optionalEnds[$tag]) && !isset(HtmlElement::$inlineElements[$tag]))) {
                     break;
                 }
                 // close it
                 $s .= $item['close'];
                 $this->space -= $item['indent'];
                 $this->tagUsed[$tag]--;
                 unset($this->tagStack[$i]);
                 $dtdContent = $this->baseDTD;
             }
             // is tag allowed in this content?
             $allowed = isset($dtdContent[$mTag]);
             // check deep element prohibitions
             if ($allowed && isset(HtmlElement::$prohibits[$mTag])) {
                 foreach (HtmlElement::$prohibits[$mTag] as $pTag) {
                     if (!empty($this->tagUsed[$pTag])) {
                         $allowed = FALSE;
                         break;
                     }
                 }
             }
         }
         // empty elements se neukladaji do zasobniku
         if ($mEmpty) {
             if (!$allowed) {
                 return $s;
             }
             if ($this->xml) {
                 $mAttr .= ' /';
             }
             $indent = $this->indent && !array_intersect(array_keys($this->tagUsed, TRUE), $this->preserveSpaces);
             if ($indent && $mTag === 'br') {
                 // formatting exception
                 return rtrim($s) . '<' . $mTag . $mAttr . ">\n" . str_repeat("\t", max(0, $this->space - 1)) . "";
             } elseif ($indent && !isset(HtmlElement::$inlineElements[$mTag])) {
                 $space = "\r" . str_repeat("\t", $this->space);
                 return $s . $space . '<' . $mTag . $mAttr . '>' . $space;
             } else {
                 return $s . '<' . $mTag . $mAttr . '>';
             }
         }
         $open = NULL;
         $close = NULL;
         $indent = 0;
         /*
         if (!isset(Texy\HtmlElement::$inlineElements[$mTag])) {
         	// block tags always decorate with \n
         	$s .= "\n";
         	$close = "\n";
         }
         */
         if ($allowed) {
             $open = '<' . $mTag . $mAttr . '>';
             // receive new content (ins & del are special cases)
             if (!empty($this->texy->dtd[$mTag][1])) {
                 $dtdContent = $this->texy->dtd[$mTag][1];
             }
             // format output
             if ($this->indent && !isset(HtmlElement::$inlineElements[$mTag])) {
                 $close = "" . '</' . $mTag . '>' . "\n" . str_repeat("\t", $this->space);
                 $s .= "\n" . str_repeat("\t", $this->space++) . $open . "";
                 $indent = 1;
             } else {
                 $close = '</' . $mTag . '>';
                 $s .= $open;
             }
             // TODO: problematic formatting of select / options, object / params
         }
         // open tag, put to stack, increase counter
         $item = ['tag' => $mTag, 'open' => $open, 'close' => $close, 'dtdContent' => $dtdContent, 'indent' => $indent];
         array_unshift($this->tagStack, $item);
         $tmp =& $this->tagUsed[$mTag];
         $tmp++;
     }
     return $s;
 }
Example #4
0
 /**
  * Finish invocation.
  *
  * @param  Texy\HtmlElement|string $content
  * @return Texy\HtmlElement|string
  */
 public function solve(HandlerInvocation $invocation = NULL, Link $link, $content = NULL)
 {
     if ($link->URL == NULL) {
         return $content;
     }
     $texy = $this->texy;
     $el = new Texy\HtmlElement('a');
     if (empty($link->modifier)) {
         $nofollow = $popup = FALSE;
     } else {
         $nofollow = isset($link->modifier->classes['nofollow']);
         $popup = isset($link->modifier->classes['popup']);
         unset($link->modifier->classes['nofollow'], $link->modifier->classes['popup']);
         $el->attrs['href'] = NULL;
         // trick - move to front
         $link->modifier->decorate($texy, $el);
     }
     if ($link->type === Link::IMAGE) {
         // image
         $el->attrs['href'] = Texy\Helpers::prependRoot($link->URL, $texy->imageModule->linkedRoot);
         if ($this->imageClass) {
             $el->attrs['class'][] = $this->imageClass;
         } else {
             $el->attrs['onclick'] = $this->imageOnClick;
         }
     } else {
         $el->attrs['href'] = Texy\Helpers::prependRoot($link->URL, $this->root);
         // rel="nofollow"
         if ($nofollow || $this->forceNoFollow && strpos($el->attrs['href'], '//') !== FALSE) {
             $el->attrs['rel'] = 'nofollow';
         }
     }
     // popup on click
     if ($popup) {
         $el->attrs['onclick'] = $this->popupOnClick;
     }
     if ($content !== NULL) {
         $el->add($content);
     }
     $texy->summary['links'][] = $el->attrs['href'];
     return $el;
 }
Example #5
0
 /**
  * Finish invocation.
  * @return Texy\HtmlElement|FALSE
  */
 public function solve(Texy\HandlerInvocation $invocation = NULL, Image $image, Texy\Link $link = NULL)
 {
     if ($image->URL == NULL) {
         return FALSE;
     }
     $texy = $this->texy;
     $mod = $image->modifier;
     $alt = $mod->title;
     $mod->title = NULL;
     $hAlign = $mod->hAlign;
     $mod->hAlign = NULL;
     $el = new Texy\HtmlElement('img');
     $el->attrs['src'] = NULL;
     // trick - move to front
     $mod->decorate($texy, $el);
     $el->attrs['src'] = Helpers::prependRoot($image->URL, $this->root);
     if (!isset($el->attrs['alt'])) {
         $el->attrs['alt'] = $alt === NULL ? $this->defaultAlt : $texy->typographyModule->postLine($alt);
     }
     if ($hAlign) {
         $var = $hAlign . 'Class';
         // leftClass, rightClass
         if (!empty($this->{$var})) {
             $el->attrs['class'][] = $this->{$var};
         } elseif (empty($texy->alignClasses[$hAlign])) {
             $el->attrs['style']['float'] = $hAlign;
         } else {
             $el->attrs['class'][] = $texy->alignClasses[$hAlign];
         }
     }
     if (!is_int($image->width) || !is_int($image->height) || $image->asMax) {
         // autodetect fileRoot
         if ($this->fileRoot === NULL && isset($_SERVER['SCRIPT_FILENAME'])) {
             $this->fileRoot = dirname($_SERVER['SCRIPT_FILENAME']) . '/' . $this->root;
         }
         // detect dimensions
         // absolute URL & security check for double dot
         if (Helpers::isRelative($image->URL) && strpos($image->URL, '..') === FALSE) {
             $file = rtrim($this->fileRoot, '/\\') . '/' . $image->URL;
             if (@is_file($file)) {
                 // intentionally @
                 $size = @getImageSize($file);
                 // intentionally @
                 if (is_array($size)) {
                     if ($image->asMax) {
                         $ratio = 1;
                         if (is_int($image->width)) {
                             $ratio = min($ratio, $image->width / $size[0]);
                         }
                         if (is_int($image->height)) {
                             $ratio = min($ratio, $image->height / $size[1]);
                         }
                         $image->width = round($ratio * $size[0]);
                         $image->height = round($ratio * $size[1]);
                     } elseif (is_int($image->width)) {
                         $image->height = round($size[1] / $size[0] * $image->width);
                     } elseif (is_int($image->height)) {
                         $image->width = round($size[0] / $size[1] * $image->height);
                     } else {
                         $image->width = $size[0];
                         $image->height = $size[1];
                     }
                 }
             }
         }
     }
     $el->attrs['width'] = $image->width;
     $el->attrs['height'] = $image->height;
     // onmouseover actions generate
     if (!empty($texy->allowed['image/hover']) && $image->overURL !== NULL) {
         $overSrc = Helpers::prependRoot($image->overURL, $this->root);
         $el->attrs['onmouseover'] = 'this.src=\'' . addSlashes($overSrc) . '\'';
         $el->attrs['onmouseout'] = 'this.src=\'' . addSlashes($el->attrs['src']) . '\'';
         $el->attrs['onload'] = str_replace('%i', addSlashes($overSrc), $this->onLoad);
         $texy->summary['preload'][] = $overSrc;
     }
     $texy->summary['images'][] = $el->attrs['src'];
     if ($link) {
         return $texy->linkModule->solve(NULL, $link, $el);
     }
     return $el;
 }
Example #6
0
 /**
  * Finish invocation.
  * @return HtmlElement|string|FALSE
  */
 public function solve(Texy\HandlerInvocation $invocation, $blocktype, $s, $param, Texy\Modifier $mod)
 {
     $texy = $this->texy;
     $parser = $invocation->getParser();
     if ($blocktype === 'block/texy') {
         $el = new HtmlElement();
         $el->parseBlock($texy, $s, $parser->isIndented());
         return $el;
     }
     if (empty($texy->allowed[$blocktype])) {
         return FALSE;
     }
     if ($blocktype === 'block/texysource') {
         $s = Helpers::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = new HtmlElement();
         if ($param === 'line') {
             $el->parseLine($texy, $s);
         } else {
             $el->parseBlock($texy, $s);
         }
         $s = $el->toHtml($texy);
         $blocktype = 'block/code';
         $param = 'html';
         // to be continue (as block/code)
     }
     if ($blocktype === 'block/code') {
         $s = Helpers::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $s = htmlspecialchars($s, ENT_NOQUOTES, 'UTF-8');
         $s = $texy->protect($s, $texy::CONTENT_BLOCK);
         $el = new HtmlElement('pre');
         $mod->decorate($texy, $el);
         $el->attrs['class'][] = $param;
         // lang
         $el->create('code', $s);
         return $el;
     }
     if ($blocktype === 'block/default') {
         $s = Helpers::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = new HtmlElement('pre');
         $mod->decorate($texy, $el);
         $el->attrs['class'][] = $param;
         // lang
         $s = htmlspecialchars($s, ENT_NOQUOTES, 'UTF-8');
         $s = $texy->protect($s, $texy::CONTENT_BLOCK);
         $el->setText($s);
         return $el;
     }
     if ($blocktype === 'block/pre') {
         $s = Helpers::outdent($s);
         if ($s === '') {
             return "\n";
         }
         $el = new HtmlElement('pre');
         $mod->decorate($texy, $el);
         $lineParser = new Texy\LineParser($texy, $el);
         // special mode - parse only html tags
         $tmp = $lineParser->patterns;
         $lineParser->patterns = [];
         if (isset($tmp['html/tag'])) {
             $lineParser->patterns['html/tag'] = $tmp['html/tag'];
         }
         if (isset($tmp['html/comment'])) {
             $lineParser->patterns['html/comment'] = $tmp['html/comment'];
         }
         unset($tmp);
         $lineParser->parse($s);
         $s = $el->getText();
         $s = html_entity_decode($s, ENT_QUOTES, 'UTF-8');
         $s = htmlspecialchars($s, ENT_NOQUOTES, 'UTF-8');
         $s = $texy->unprotect($s);
         $s = $texy->protect($s, $texy::CONTENT_BLOCK);
         $el->setText($s);
         return $el;
     }
     if ($blocktype === 'block/html') {
         $s = trim($s, "\n");
         if ($s === '') {
             return "\n";
         }
         $el = new HtmlElement();
         $lineParser = new Texy\LineParser($texy, $el);
         // special mode - parse only html tags
         $tmp = $lineParser->patterns;
         $lineParser->patterns = [];
         if (isset($tmp['html/tag'])) {
             $lineParser->patterns['html/tag'] = $tmp['html/tag'];
         }
         if (isset($tmp['html/comment'])) {
             $lineParser->patterns['html/comment'] = $tmp['html/comment'];
         }
         unset($tmp);
         $lineParser->parse($s);
         $s = $el->getText();
         $s = html_entity_decode($s, ENT_QUOTES, 'UTF-8');
         $s = htmlspecialchars($s, ENT_NOQUOTES, 'UTF-8');
         $s = $texy->unprotect($s);
         return $texy->protect($s, $texy::CONTENT_BLOCK) . "\n";
     }
     if ($blocktype === 'block/text') {
         $s = trim($s, "\n");
         if ($s === '') {
             return "\n";
         }
         $s = htmlspecialchars($s, ENT_NOQUOTES, 'UTF-8');
         $s = str_replace("\n", (new HtmlElement('br'))->startTag(), $s);
         // nl2br
         return $texy->protect($s, $texy::CONTENT_BLOCK) . "\n";
     }
     if ($blocktype === 'block/comment') {
         return "\n";
     }
     if ($blocktype === 'block/div') {
         $s = Helpers::outdent($s, TRUE);
         if ($s === '') {
             return "\n";
         }
         $el = new HtmlElement('div');
         $mod->decorate($texy, $el);
         $el->parseBlock($texy, $s, $parser->isIndented());
         // TODO: INDENT or NORMAL ?
         return $el;
     }
     return FALSE;
 }
Example #7
0
 /**
  * Parse text in all cells.
  * @return void
  */
 private function finishPart(HtmlElement $elPart)
 {
     foreach ($elPart->getChildren() as $elRow) {
         foreach ($elRow->getChildren() as $elCell) {
             if ($elCell->colSpan > 1) {
                 $elCell->attrs['colspan'] = $elCell->colSpan;
             }
             if ($elCell->rowSpan > 1) {
                 $elCell->attrs['rowspan'] = $elCell->rowSpan;
             }
             $text = rtrim($elCell->text);
             if (strpos($text, "\n") !== FALSE) {
                 // multiline parse as block
                 // HACK: disable tables
                 $this->disableTables = TRUE;
                 $elCell->parseBlock($this->texy, Texy\Helpers::outdent($text));
                 $this->disableTables = FALSE;
             } else {
                 $elCell->parseLine($this->texy, ltrim($text));
             }
             if ($elCell->getText() === '') {
                 $elCell->setText(" ");
                 // &nbsp;
             }
         }
     }
 }
Example #8
0
 /**
  * @return void
  */
 public function afterParse(Texy\Texy $texy, Texy\HtmlElement $DOM, $isSingleLine)
 {
     if ($isSingleLine) {
         return;
     }
     if ($this->balancing === self::DYNAMIC) {
         $top = $this->top;
         $map = [];
         $min = 100;
         foreach ($this->TOC as $item) {
             $level = $item['level'];
             if ($item['type'] === 'surrounded') {
                 $min = min($level, $min);
                 $top = $this->top - $min;
             } elseif ($item['type'] === 'underlined') {
                 $map[$level] = $level;
             }
         }
         asort($map);
         $map = array_flip(array_values($map));
     }
     foreach ($this->TOC as $key => $item) {
         if ($this->balancing === self::DYNAMIC) {
             if ($item['type'] === 'surrounded') {
                 $level = $item['level'] + $top;
             } elseif ($item['type'] === 'underlined') {
                 $level = $map[$item['level']] + $this->top;
             } else {
                 $level = $item['level'];
             }
             $item['el']->setName('h' . min(6, max(1, $level)));
             $this->TOC[$key]['level'] = $level;
         }
         if ($this->generateID) {
             if (!empty($item['el']->style['toc']) && is_array($item['el']->style)) {
                 $title = $item['el']->style['toc'];
                 unset($item['el']->style['toc']);
             } else {
                 $title = trim($item['el']->toText($this->texy));
             }
             $this->TOC[$key]['title'] = $title;
             if (empty($item['el']->attrs['id'])) {
                 $id = $this->idPrefix . Texy\Helpers::webalize($title);
                 $counter = '';
                 if (isset($this->usedID[$id . $counter])) {
                     $counter = 2;
                     while (isset($this->usedID[$id . '-' . $counter])) {
                         $counter++;
                     }
                     $id .= '-' . $counter;
                 }
                 $this->usedID[$id] = TRUE;
                 $item['el']->attrs['id'] = $id;
             }
         }
     }
     // document title
     if ($this->title === NULL && count($this->TOC)) {
         $item = reset($this->TOC);
         $this->title = isset($item['title']) ? $item['title'] : trim($item['el']->toText($this->texy));
     }
 }