2017-11-30
This commit is contained in:
parent
d1dbeb272a
commit
a4a81c04e0
24 changed files with 310 additions and 1151 deletions
66
app/Core/Parser.php
Normal file
66
app/Core/Parser.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace ForkBB\Core;
|
||||
|
||||
use Parserus;
|
||||
|
||||
class Parser extends Parserus
|
||||
{
|
||||
/**
|
||||
* Контейнер
|
||||
* @var Container
|
||||
*/
|
||||
protected $c;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param int $flag
|
||||
* @param Container $container
|
||||
*/
|
||||
public function __construct($flag, Container $container)
|
||||
{
|
||||
$this->c = $container;
|
||||
parent::__construct($flag);
|
||||
$this->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициализация данных
|
||||
*/
|
||||
protected function init()
|
||||
{
|
||||
$bbcodes = include $this->c->DIR_CONFIG . '/defaultBBCode.php';
|
||||
$this->setBBCodes($bbcodes);
|
||||
|
||||
if ($this->c->user->show_smilies == '1'
|
||||
&& ($this->c->config->o_smilies_sig == '1' || $this->c->config->o_smilies == '1')
|
||||
) {
|
||||
$smilies = $this->c->smilies->list; //????
|
||||
|
||||
foreach ($smilies as &$cur) {
|
||||
$cur = $this->c->PUBLIC_URL . '/img/sm/' . $cur;
|
||||
}
|
||||
unset($cur);
|
||||
|
||||
$info = $this->c->BBCODE_INFO;
|
||||
|
||||
$this->setSmilies($smilies)->setSmTpl($info['smTpl'], $info['smTplTag'], $info['smTplBl']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод добавляет один bb-код
|
||||
*
|
||||
* @param array $bb
|
||||
*
|
||||
* @return Parser
|
||||
*/
|
||||
public function addBBCode(array $bb)
|
||||
{
|
||||
if ($bb['tag'] == 'quote') {
|
||||
$bb['self nesting'] = (int) $this->c->config->o_quote_depth;
|
||||
}
|
||||
return parent::addBBCode($bb);
|
||||
}
|
||||
}
|
|
@ -100,7 +100,7 @@ class LoadTree extends MethodModel
|
|||
foreach ($list as $forum) {
|
||||
$t = max($max, (int) $forum->mf_mark_all_read);
|
||||
if ($forum->last_post > $t) {
|
||||
$time[$id] = $t;
|
||||
$time[$forum->id] = $t;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -391,7 +391,6 @@ class Topic extends Page
|
|||
$this->topic = $topic;
|
||||
$this->posts = $posts;
|
||||
$this->crumbs = $this->crumbs($topic);
|
||||
$this->pagination = $topic->pagination;
|
||||
$this->online = $this->c->Online->calc($this)->info();
|
||||
$this->stats = null;
|
||||
$this->form = $form;
|
||||
|
@ -399,6 +398,7 @@ class Topic extends Page
|
|||
if ($topic->showViews) {
|
||||
$topic->incViews();
|
||||
}
|
||||
$topic->updateVisits();
|
||||
/*
|
||||
if (! $user->isGuest) {
|
||||
$vars = [
|
||||
|
|
|
@ -112,4 +112,26 @@ class Post extends DataModel
|
|||
}
|
||||
return $controls;
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML код сообщения
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function html()
|
||||
{
|
||||
$bbWList = $this->c->config->p_message_bbcode == '1' ? null : [];
|
||||
$bbBList = $this->c->config->p_message_img_tag == '1' ? [] : ['img'];
|
||||
|
||||
$parser = $this->c->Parser->setAttr('isSign', false)
|
||||
->setWhiteList($bbWList)
|
||||
->setBlackList($bbBList)
|
||||
->parse($this->cens()->message);
|
||||
|
||||
if ($this->hide_smilies != '1' && $this->c->config->o_smilies == '1') {
|
||||
$parser->detectSmilies();
|
||||
}
|
||||
|
||||
return $parser->getHtml();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -330,6 +330,7 @@ class Topic extends DataModel
|
|||
$cur = $this->c->ModelPost->setAttrs($cur);
|
||||
}
|
||||
unset($cur);
|
||||
$this->timeMax = $timeMax;
|
||||
return $posts;
|
||||
}
|
||||
|
||||
|
@ -355,4 +356,48 @@ class Topic extends DataModel
|
|||
|
||||
$this->c->DB->query($sql, $vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Обновление меток последнего визита и последнего прочитанного сообщения
|
||||
*/
|
||||
public function updateVisits()
|
||||
{
|
||||
if ($this->c->user->isGuest) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vars = [
|
||||
':uid' => $this->c->user->id,
|
||||
':tid' => $this->id,
|
||||
':read' => $this->mt_last_read,
|
||||
':visit' => $this->mt_last_visit,
|
||||
];
|
||||
$flag = false;
|
||||
|
||||
if (false !== $this->hasNew) {
|
||||
$flag = true;
|
||||
$vars[':visit'] = $this->last_post;
|
||||
}
|
||||
if (false !== $this->hasUnread && $this->timeMax > $this->hasUnread) {
|
||||
$flag = true;
|
||||
$vars[':read'] = $this->timeMax;
|
||||
}
|
||||
|
||||
if ($flag) {
|
||||
if (empty($this->mt_last_read) && empty($this->mt_last_visit)) {
|
||||
$sql = 'INSERT INTO ::mark_of_topic (uid, tid, mt_last_visit, mt_last_read)
|
||||
SELECT ?i:uid, ?i:tid, ?i:visit, ?i:read
|
||||
FROM ::groups
|
||||
WHERE NOT EXISTS (SELECT 1
|
||||
FROM ::mark_of_topic
|
||||
WHERE uid=?i:uid AND tid=?i:tid)
|
||||
LIMIT 1';
|
||||
} else {
|
||||
$sql = 'UPDATE ::mark_of_topic
|
||||
SET mt_last_visit=?i:visit, mt_last_read=?i:read
|
||||
WHERE uid=?i:uid AND tid=?i:tid';
|
||||
}
|
||||
$this->c->DB->exec($sql, $vars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -186,4 +186,26 @@ class User extends DataModel
|
|||
{
|
||||
return isset($this->c->Online->online[$this->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* HTML код подписи
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function gethtmlSign()
|
||||
{
|
||||
$bbWList = $this->c->config->p_sig_bbcode == '1' ? $this->c->BBCODE_INFO['forSign'] : [];
|
||||
$bbBList = $this->c->config->p_sig_img_tag == '1' ? [] : ['img'];
|
||||
|
||||
$parser = $this->c->Parser->setAttr('isSign', true)
|
||||
->setWhiteList($bbWList)
|
||||
->setBlackList($bbBList)
|
||||
->parse($this->cens()->signature);
|
||||
|
||||
if ($this->c->config->o_smilies_sig == '1') {
|
||||
$parser->detectSmilies();
|
||||
}
|
||||
|
||||
return $parser->getHtml();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,10 +4,8 @@ return [
|
|||
['tag' => 'ROOT',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
$body = '<p>' . $body . '</p>';
|
||||
|
||||
// Replace any breaks next to paragraphs so our replace below catches them
|
||||
$body = preg_replace('%(</?p>)(?:\s*?<br>){1,2}%', '$1', $body);
|
||||
$body = preg_replace('%(</?p>)(?:\s*?<br>){1,2}%', '$1', '<p>' . $body . '</p>');
|
||||
$body = preg_replace('%(?:<br>\s*?){1,2}(</?p>)%', '$1', $body);
|
||||
|
||||
// Remove any empty paragraph tags (inserted via quotes/lists/code/etc) which should be stripped
|
||||
|
@ -32,9 +30,7 @@ return [
|
|||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$body = trim($body, "\n\r");
|
||||
$class = substr_count($body, "\n") > 28 ? ' class="vscroll"' : '';
|
||||
return '</p><div class="codebox"><pre' . $class . '><code>' . $body . '</code></pre></div><p>';
|
||||
return '</p><div class="codebox"><pre><code>' . trim($body, "\n\r") . '</code></pre></div><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'b',
|
||||
|
@ -86,7 +82,7 @@ return [
|
|||
},
|
||||
],
|
||||
['tag' => 'color',
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
|
@ -97,7 +93,7 @@ return [
|
|||
},
|
||||
],
|
||||
['tag' => 'colour',
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
|
@ -108,7 +104,7 @@ return [
|
|||
},
|
||||
],
|
||||
['tag' => 'background',
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
|
@ -119,7 +115,7 @@ return [
|
|||
},
|
||||
],
|
||||
['tag' => 'size',
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[1-9]\d*(?:em|ex|pt|px|\%)?$%',
|
||||
|
@ -156,7 +152,7 @@ return [
|
|||
},
|
||||
],
|
||||
['tag' => 'font',
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[a-z\d, -]+$%i',
|
||||
|
@ -187,7 +183,7 @@ return [
|
|||
],
|
||||
['tag' => '*',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'parents' => ['list'],
|
||||
'auto' => true,
|
||||
'handler' => function($body) {
|
||||
|
@ -196,7 +192,7 @@ return [
|
|||
],
|
||||
['tag' => 'list',
|
||||
'type' => 'list',
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'tags only' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
|
@ -251,7 +247,7 @@ return [
|
|||
],
|
||||
['tag' => 'quote',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
|
@ -268,7 +264,7 @@ return [
|
|||
],
|
||||
['tag' => 'spoiler',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
|
@ -354,7 +350,7 @@ return [
|
|||
}
|
||||
|
||||
if ($url === $body) {
|
||||
$url = htmlspecialchars_decode($url, ENT_QUOTES);
|
||||
$url = htmlspecialchars_decode($url, ENT_QUOTES | ENT_HTML5);
|
||||
$url = mb_strlen($url, 'UTF-8') > 55 ? mb_substr($url, 0, 39, 'UTF-8') . ' … ' . mb_substr($url, -10, null, 'UTF-8') : $url;
|
||||
$body = $parser->e($url);
|
||||
}
|
||||
|
@ -365,7 +361,7 @@ return [
|
|||
['tag' => 'table',
|
||||
'type' => 'table',
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
|
@ -390,7 +386,7 @@ return [
|
|||
['tag' => 'caption',
|
||||
'type' => 'block',
|
||||
'parents' => ['table'],
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
|
@ -407,7 +403,7 @@ return [
|
|||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
|
@ -424,7 +420,7 @@ return [
|
|||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
|
@ -441,7 +437,7 @@ return [
|
|||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
|
@ -458,7 +454,7 @@ return [
|
|||
'type' => 'tr',
|
||||
'parents' => ['table', 't'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
|
@ -474,7 +470,7 @@ return [
|
|||
['tag' => 'th',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
|
@ -492,7 +488,7 @@ return [
|
|||
['tag' => 'td',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'self nesting' => 5,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
@endsection
|
||||
@section('pagination')
|
||||
<nav class="f-pages">
|
||||
@foreach($p->pagination as $cur)
|
||||
@foreach($p->topic->pagination as $cur)
|
||||
@if($cur[2])
|
||||
<span class="f-page active">{{ $cur[1] }}</span>
|
||||
@elseif($cur[1] === 'space')
|
||||
|
@ -40,7 +40,7 @@
|
|||
@extends('layouts/main')
|
||||
<div class="f-nav-links">
|
||||
@yield('crumbs')
|
||||
@if($p->topic->canReply || $p->topic->closed || $p->pagination)
|
||||
@if($p->topic->canReply || $p->topic->closed || $p->topic->pagination)
|
||||
<div class="f-links-b clearfix">
|
||||
@yield('pagination')
|
||||
@yield('linkpost')
|
||||
|
@ -70,7 +70,7 @@
|
|||
@else
|
||||
<li class="f-username">{{ $post->user->username }}</li>
|
||||
@endif
|
||||
@if($post->showUserAvatar)
|
||||
@if($post->showUserAvatar && $post->user->avatar)
|
||||
<li class="f-avatar">
|
||||
<img alt="{{ $post->user->username }}" src="{!! $post->user->avatar !!}">
|
||||
</li>
|
||||
|
@ -91,12 +91,12 @@
|
|||
@endif
|
||||
</address>
|
||||
<div class="f-post-right f-post-main">
|
||||
{!! $post->message !!}
|
||||
{!! $post->html() !!}
|
||||
</div>
|
||||
@if($post->showSignature && $post->user->signature)
|
||||
<div class="f-post-right f-post-signature">
|
||||
<hr>
|
||||
{!! $post->user->signature !!}
|
||||
{!! $post->user->htmlSign !!}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
@ -118,7 +118,7 @@
|
|||
@endforeach
|
||||
</section>
|
||||
<div class="f-nav-links">
|
||||
@if($p->topic->canReply || $p->topic->closed || $p->pagination)
|
||||
@if($p->topic->canReply || $p->topic->closed || $p->topic->pagination)
|
||||
<div class="f-links-a clearfix">
|
||||
@yield('linkpost')
|
||||
@yield('pagination')
|
||||
|
|
17
composer.lock
generated
17
composer.lock
generated
|
@ -4,8 +4,8 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "f222f403c8d48f00cb5e3e37f680ebcb",
|
||||
"content-hash": "b8c1ffae094a89502ad8a3c60385d4b8",
|
||||
"hash": "683b977706502db4bb7fc7ba3cd8ca71",
|
||||
"content-hash": "2299621b481bdbc8ce629eee53b1b82e",
|
||||
"packages": [
|
||||
{
|
||||
"name": "artoodetoo/dirk",
|
||||
|
@ -55,16 +55,16 @@
|
|||
},
|
||||
{
|
||||
"name": "miovisman/parserus",
|
||||
"version": "0.9.1",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MioVisman/Parserus.git",
|
||||
"reference": "d039178d46c989ebb8eb89970b52eb6ce927c817"
|
||||
"reference": "bbdade91cfc4927ebb8b5b984f90a52075f75ece"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MioVisman/Parserus/zipball/d039178d46c989ebb8eb89970b52eb6ce927c817",
|
||||
"reference": "d039178d46c989ebb8eb89970b52eb6ce927c817",
|
||||
"url": "https://api.github.com/repos/MioVisman/Parserus/zipball/bbdade91cfc4927ebb8b5b984f90a52075f75ece",
|
||||
"reference": "bbdade91cfc4927ebb8b5b984f90a52075f75ece",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -93,14 +93,15 @@
|
|||
"bbcode",
|
||||
"parser"
|
||||
],
|
||||
"time": "2016-11-26 06:56:51"
|
||||
"time": "2017-11-21 06:34:31"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"artoodetoo/dirk": 20
|
||||
"artoodetoo/dirk": 20,
|
||||
"miovisman/parserus": 20
|
||||
},
|
||||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
|
|
12
vendor/composer/installed.json
vendored
12
vendor/composer/installed.json
vendored
|
@ -49,23 +49,23 @@
|
|||
},
|
||||
{
|
||||
"name": "miovisman/parserus",
|
||||
"version": "0.9.1",
|
||||
"version_normalized": "0.9.1.0",
|
||||
"version": "dev-master",
|
||||
"version_normalized": "9999999-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MioVisman/Parserus.git",
|
||||
"reference": "d039178d46c989ebb8eb89970b52eb6ce927c817"
|
||||
"reference": "bbdade91cfc4927ebb8b5b984f90a52075f75ece"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MioVisman/Parserus/zipball/d039178d46c989ebb8eb89970b52eb6ce927c817",
|
||||
"reference": "d039178d46c989ebb8eb89970b52eb6ce927c817",
|
||||
"url": "https://api.github.com/repos/MioVisman/Parserus/zipball/bbdade91cfc4927ebb8b5b984f90a52075f75ece",
|
||||
"reference": "bbdade91cfc4927ebb8b5b984f90a52075f75ece",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"time": "2016-11-26 06:56:51",
|
||||
"time": "2017-11-21 06:34:31",
|
||||
"type": "library",
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
|
|
2
vendor/miovisman/parserus/LICENSE
vendored
2
vendor/miovisman/parserus/LICENSE
vendored
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2016 Visman
|
||||
Copyright (c) 2016-2017 Visman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
|
156
vendor/miovisman/parserus/Parserus.php
vendored
156
vendor/miovisman/parserus/Parserus.php
vendored
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2016 Visman. All rights reserved.
|
||||
* @copyright Copyright (c) 2016-2017 Visman. All rights reserved.
|
||||
* @author Visman <mio.visman@yandex.ru>
|
||||
* @link https://github.com/MioVisman/Parserus
|
||||
* @license https://opensource.org/licenses/MIT The MIT License (MIT)
|
||||
|
@ -119,6 +119,12 @@ class Parserus
|
|||
*/
|
||||
protected $strict = false;
|
||||
|
||||
/**
|
||||
* Максимальная глубина дерева тегов при строгом режиме поиска ошибок
|
||||
* @var int
|
||||
*/
|
||||
protected $maxDepth;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
|
@ -131,14 +137,15 @@ class Parserus
|
|||
}
|
||||
$this->eFlags = $flag | ENT_QUOTES | ENT_SUBSTITUTE;
|
||||
$this->tRepl = in_array($flag, [ENT_HTML5, ENT_HTML401])
|
||||
? ['<br>', ' ', ' ', ' ']
|
||||
: ['<br />', '    ', '  ', '  '];
|
||||
? ['<br>', ' ', ' ', ' ']
|
||||
: ['<br />', '    ', '  ', '  '];
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод добавляет один bb-код
|
||||
*
|
||||
* @param array $bb Массив описания bb-кода
|
||||
*
|
||||
* @return Parserus $this
|
||||
*/
|
||||
public function addBBCode(array $bb)
|
||||
|
@ -174,7 +181,7 @@ class Parserus
|
|||
}
|
||||
|
||||
if (isset($bb['self nesting'])) {
|
||||
$res['self nesting'] = (bool) $bb['self nesting'];
|
||||
$res['self nesting'] = (int) $bb['self nesting'] > 0 ? (int) $bb['self nesting'] : false;
|
||||
}
|
||||
|
||||
if (isset($bb['recursive'])) {
|
||||
|
@ -248,6 +255,7 @@ class Parserus
|
|||
* Метод задает массив bb-кодов
|
||||
*
|
||||
* @param array $bbcodes Массив описаний bb-кодов
|
||||
*
|
||||
* @return Parserus $this
|
||||
*/
|
||||
public function setBBCodes(array $bbcodes)
|
||||
|
@ -276,6 +284,7 @@ class Parserus
|
|||
* Метод задает массив смайлов
|
||||
*
|
||||
* @param array $smilies Ассоциативный массив смайлов
|
||||
*
|
||||
* @return Parserus $this
|
||||
*/
|
||||
public function setSmilies(array $smilies)
|
||||
|
@ -331,6 +340,7 @@ class Parserus
|
|||
* @param string $tpl Строка шаблона, например: <img src="{url}" alt="{alt}">
|
||||
* @param string $tag Имя тега под которым идет отображение смайлов
|
||||
* @param array $bl Список тегов в которых не нужно отображать смайлы
|
||||
*
|
||||
* @return Parserus $this
|
||||
*/
|
||||
public function setSmTpl($tpl, $tag = 'img', array $bl = ['url'])
|
||||
|
@ -356,6 +366,7 @@ class Parserus
|
|||
* Метод устанавливает список разрешенных bb-кодов
|
||||
*
|
||||
* @param mixed $list Массив bb-кодов, null и т.д.
|
||||
*
|
||||
* @return Parserus $this
|
||||
*/
|
||||
public function setWhiteList($list = null)
|
||||
|
@ -368,6 +379,7 @@ class Parserus
|
|||
* Метод устанавливает список запрещенных bb-кодов
|
||||
*
|
||||
* @param mixed $list Массив bb-кодов, null и т.д.
|
||||
*
|
||||
* @return Parserus $this
|
||||
*/
|
||||
public function setBlackList($list = null)
|
||||
|
@ -381,6 +393,7 @@ class Parserus
|
|||
*
|
||||
* @param string $name Имя переменной
|
||||
* @param mixed $val Значение переменной
|
||||
*
|
||||
* @return Parserus $this
|
||||
*/
|
||||
public function setAttr($name, $val)
|
||||
|
@ -392,8 +405,9 @@ class Parserus
|
|||
/**
|
||||
* Метод для получения значения переменной
|
||||
*
|
||||
* @param string $name Имя переменной
|
||||
* @return mixed|null Значение переменной или null, если переменная не была задана ранее
|
||||
* @param string $name Имя переменной
|
||||
*
|
||||
* @return mixed Значение переменной или null, если переменная не была задана ранее
|
||||
*/
|
||||
public function attr($name)
|
||||
{
|
||||
|
@ -407,15 +421,16 @@ class Parserus
|
|||
* @param int $parentId Указатель на родителя
|
||||
* @param array $attrs Массив атрибутов тега
|
||||
* @param bool $textOnly Флаг. Если true, то в теле только текст
|
||||
*
|
||||
* @return int Указатель на данный тег
|
||||
*/
|
||||
protected function addTagNode($tag, $parentId = null, $attrs = [], $textOnly = false)
|
||||
protected function addTagNode($tag, $parentId = null, array $attrs = [], $textOnly = false)
|
||||
{
|
||||
$this->data[++$this->dataId] = [
|
||||
'tag' => $tag,
|
||||
'parent' => $parentId,
|
||||
'tag' => $tag,
|
||||
'parent' => $parentId,
|
||||
'children' => [],
|
||||
'attrs' => $attrs,
|
||||
'attrs' => $attrs,
|
||||
];
|
||||
|
||||
if ($textOnly) {
|
||||
|
@ -434,14 +449,14 @@ class Parserus
|
|||
*
|
||||
* @param string $text Текст
|
||||
* @param int $parentId Указатель на родителя
|
||||
*
|
||||
* @return string Пустая строка
|
||||
*/
|
||||
protected function addTextNode($text, $parentId)
|
||||
{
|
||||
if (isset($text[0])) {
|
||||
|
||||
$this->data[++$this->dataId] = [
|
||||
'text' => $text,
|
||||
'text' => $text,
|
||||
'parent' => $parentId,
|
||||
];
|
||||
|
||||
|
@ -455,6 +470,7 @@ class Parserus
|
|||
* Метод нормализует содержимое атрибута
|
||||
*
|
||||
* @param string $attr Содержимое атрибута полученное из регулярного выражения
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getNormAttr($attr)
|
||||
|
@ -476,6 +492,7 @@ class Parserus
|
|||
* @param string $tag Имя обрабатываемого тега
|
||||
* @param string $type "Тип атрибутов" = ' ', '=' или ']'
|
||||
* @param string $text Текст из которого выделяются атрибуты
|
||||
*
|
||||
* @return null|array
|
||||
*/
|
||||
protected function parseAttrs($tag, $type, $text)
|
||||
|
@ -575,8 +592,8 @@ class Parserus
|
|||
|
||||
return [
|
||||
'attrs' => $attrs,
|
||||
'tag' => $tagText,
|
||||
'text' => $text,
|
||||
'tag' => $tagText,
|
||||
'text' => $text,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -584,6 +601,7 @@ class Parserus
|
|||
* Метод определяет указатель на родительский тег для текущего
|
||||
*
|
||||
* @param string $tag Имя тега
|
||||
*
|
||||
* @return int|false false, если невозможно подобрать родителя
|
||||
*/
|
||||
protected function findParent($tag)
|
||||
|
@ -629,9 +647,10 @@ class Parserus
|
|||
* @param string $tag Имя тега
|
||||
* @param array $attrs Массив атрибутов
|
||||
* @param string $text Текст из которого выделяется тело тега
|
||||
*
|
||||
* @return array|false false в случае ошибки
|
||||
*/
|
||||
protected function validationTag($tag, $attrs, $text)
|
||||
protected function validationTag($tag, array $attrs, $text)
|
||||
{
|
||||
if (empty($attrs)) {
|
||||
$attrs['no attr'] = null;
|
||||
|
@ -691,8 +710,8 @@ class Parserus
|
|||
|
||||
return [
|
||||
'attrs' => $attrs,
|
||||
'body' => $flag ? $body : null,
|
||||
'end' => $end,
|
||||
'body' => $flag ? $body : null,
|
||||
'end' => $end,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -702,6 +721,7 @@ class Parserus
|
|||
* @param string $tag Имя обрабатываемого тега
|
||||
* @param string $curText Текст до тега, который еще не был учтен
|
||||
* @param string $tagText Текст самого тега - [/tag]
|
||||
*
|
||||
* @return string Пустая строка, если тег удалось закрыть
|
||||
*/
|
||||
protected function closeTag($tag, $curText, $tagText) {
|
||||
|
@ -715,7 +735,9 @@ class Parserus
|
|||
$curTag = $this->data[$curId]['tag'];
|
||||
|
||||
while ($curTag !== $tag && $curId > 0) {
|
||||
if (false === $this->bbcodes[$curTag]['auto']) {
|
||||
if ($this->bbcodes[$tag]['type'] === 'inline'
|
||||
|| false === $this->bbcodes[$curTag]['auto']
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -753,6 +775,7 @@ class Parserus
|
|||
$this->smOn = false;
|
||||
$this->errors = [];
|
||||
$this->strict = isset($opts['strict']) ? (bool) $opts['strict'] : false;
|
||||
$this->maxDepth = isset($opts['depth']) ? (int) $opts['depth'] : 10;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -760,9 +783,10 @@ class Parserus
|
|||
*
|
||||
* @param string $text Обрабатываемый текст
|
||||
* @param array $opts Ассоциативный массив опций
|
||||
*
|
||||
* @return Parserus $this
|
||||
*/
|
||||
public function parse($text, $opts = [])
|
||||
public function parse($text, array $opts = [])
|
||||
{
|
||||
$this->reset($opts);
|
||||
$curText = '';
|
||||
|
@ -774,13 +798,13 @@ class Parserus
|
|||
while (($match = preg_split('%(\[(/)?(' . ($recCount ? $recTag : '[a-z\*][a-z\d-]{0,10}') . ')((?(1)\]|[=\]\x20])))%i', $text, 2, PREG_SPLIT_DELIM_CAPTURE))
|
||||
&& isset($match[1])
|
||||
) {
|
||||
/* $match[0] - текст до тега
|
||||
* $match[1] - [ + (|/) + имя тега + (]| |=)
|
||||
* $match[2] - (|/)
|
||||
* $match[3] - имя тега
|
||||
* $match[4] - тип атрибутов --> (]| |=)
|
||||
* $match[5] - остаток текста до конца
|
||||
*/
|
||||
/* $match[0] - текст до тега
|
||||
* $match[1] - [ + (|/) + имя тега + (]| |=)
|
||||
* $match[2] - (|/)
|
||||
* $match[3] - имя тега
|
||||
* $match[4] - тип атрибутов --> (]| |=)
|
||||
* $match[5] - остаток текста до конца
|
||||
*/
|
||||
$tagText = $match[1];
|
||||
$curText .= $match[0];
|
||||
$text = $match[5];
|
||||
|
@ -869,13 +893,62 @@ class Parserus
|
|||
}
|
||||
|
||||
$this->addTextNode($curText . $text, $this->curId);
|
||||
|
||||
if ($this->strict) {
|
||||
$this->searchError();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод проверяет глубину дерева тегов
|
||||
* Метод проверяет лимит вложенности тегов в самих себя
|
||||
*
|
||||
* @param int $id Указатель на текущий тег
|
||||
* @param int $depth Глубина дерева на текущий момент
|
||||
* @param array $tags Массив количества вложений тегов с включенным 'self nesting'
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function searchError($id = 0, $depth = -1, array $tags = [])
|
||||
{
|
||||
if (isset($this->data[$id]['text'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
++$depth;
|
||||
|
||||
if ($depth > $this->maxDepth) {
|
||||
$this->errors[] = [15, $this->maxDepth];
|
||||
return true;
|
||||
}
|
||||
|
||||
$tag = $this->data[$id]['tag'];
|
||||
if (false !== $this->bbcodes[$tag]['self nesting']) {
|
||||
if (isset($tags[$tag])) {
|
||||
++$tags[$tag];
|
||||
} else {
|
||||
$tags[$tag] = 0;
|
||||
}
|
||||
if ($tags[$tag] > $this->bbcodes[$tag]['self nesting']) {
|
||||
$this->errors[] = [16, $tag, $this->bbcodes[$tag]['self nesting']];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
foreach ($this->data[$id]['children'] as $child) {
|
||||
if ($this->searchError($child, $depth, $tags)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод возвращает HTML построенный на основании дерева тегов
|
||||
*
|
||||
* @param int $id Указатель на текущий тег
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHtml($id = 0)
|
||||
|
@ -952,6 +1025,7 @@ class Parserus
|
|||
* Метод возвращает текст с bb-кодами построенный на основании дерева тегов
|
||||
*
|
||||
* @param int $id Указатель на текущий тег
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCode($id = 0)
|
||||
|
@ -1021,6 +1095,7 @@ class Parserus
|
|||
* @param string $tag Имя для создания bb-кода
|
||||
* @param string $pattern Регулярное выражение для поиска
|
||||
* @param bool $textOnly Флаг. true, если содержимое созданного тега текстовое
|
||||
*
|
||||
* @return Parserus $this
|
||||
*/
|
||||
protected function detect($tag, $pattern, $textOnly)
|
||||
|
@ -1073,7 +1148,7 @@ class Parserus
|
|||
$pos = $match[1] + strlen($match[0]);
|
||||
}
|
||||
|
||||
$this->addTextNode($this->endStr($this->data[$id]['text'], $pos), $pid);
|
||||
$this->addTextNode((string) substr($this->data[$id]['text'], $pos), $pid);
|
||||
unset($this->data[$id]);
|
||||
|
||||
$this->data[$pid]['children'] = array_merge($this->data[$pid]['children'], $arrEnd);
|
||||
|
@ -1112,6 +1187,7 @@ class Parserus
|
|||
*
|
||||
* @param string $mask Маска символов, которые не учитываются при определении пустоты текстовых узлов
|
||||
* @param int $id Указатель на текущий тег
|
||||
*
|
||||
* @return bool Если true, то тег/узел пустой
|
||||
*/
|
||||
protected function stripEmptyTags_($mask, $id)
|
||||
|
@ -1155,10 +1231,12 @@ class Parserus
|
|||
/**
|
||||
* Метод возвращает массив ошибок
|
||||
*
|
||||
* @param array $lang Массив строк шаблонов описания ошибок
|
||||
* @param array $lang Массив строк шаблонов описания ошибок
|
||||
* @param array $errors Массив, который дополняется ошибками
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getErrors(array $lang = [])
|
||||
public function getErrors(array $lang = [], array $errors = [])
|
||||
{
|
||||
$defLang = [
|
||||
1 => 'Тег [%1$s] находится в черном списке',
|
||||
|
@ -1174,11 +1252,11 @@ class Parserus
|
|||
11 => 'Тело тега [%1$s] не соответствует шаблону',
|
||||
12 => 'Тег [%1$s] нельзя открыть внутри аналогичного тега',
|
||||
13 => 'В теге [%1$s] отсутствует обязательный атрибут \'%2$s\'',
|
||||
14 => 'Все теги пустые'
|
||||
14 => 'Все теги пустые',
|
||||
15 => 'Глубина дерева тегов больше %1$s',
|
||||
16 => 'Тег [%1$s] вложен в себя больше %2$s раз',
|
||||
];
|
||||
|
||||
$errors = [];
|
||||
|
||||
foreach ($this->errors as $args) {
|
||||
$err = array_shift($args);
|
||||
|
||||
|
@ -1200,23 +1278,11 @@ class Parserus
|
|||
* Метод преобразует специальные символы в HTML-сущности
|
||||
*
|
||||
* @param string $text
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function e($text)
|
||||
{
|
||||
return htmlspecialchars($text, $this->eFlags, 'UTF-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод возвращает окончание строки
|
||||
*
|
||||
* @param string $str Текст
|
||||
* @param int $pos Начальная позиция в байтах с которой идет возврат текста
|
||||
* @return string
|
||||
*/
|
||||
protected function endStr($str, $pos)
|
||||
{
|
||||
$s = substr($str, $pos);
|
||||
return false === $s ? '' : $s;
|
||||
}
|
||||
}
|
||||
|
|
20
vendor/miovisman/parserus/examples/_first.php
vendored
20
vendor/miovisman/parserus/examples/_first.php
vendored
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
])->parse("[i]Hello\n[b]World[/b]![/i]")
|
||||
->getHTML();
|
||||
|
||||
#output: <i>Hello<br><b>World</b>!</i>
|
20
vendor/miovisman/parserus/examples/_second.php
vendored
20
vendor/miovisman/parserus/examples/_second.php
vendored
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus(ENT_XHTML);
|
||||
|
||||
echo $parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
])->parse("[i]Hello\n[b]World[/b]![/i]")
|
||||
->getHTML();
|
||||
|
||||
#output: <i>Hello<br /><b>World</b>!</i>
|
20
vendor/miovisman/parserus/examples/_third.php
vendored
20
vendor/miovisman/parserus/examples/_third.php
vendored
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
])->parse("[i]\nHello\n[b]\nWorld!")
|
||||
->getHTML();
|
||||
|
||||
#output: <i>Hello<br><b>World!</b></i>
|
50
vendor/miovisman/parserus/examples/attr.php
vendored
50
vendor/miovisman/parserus/examples/attr.php
vendored
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->addBBCode([
|
||||
'tag' => 'after',
|
||||
'type' => 'block',
|
||||
'single' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^\d+$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
$lang = $parser->attr('lang');
|
||||
$arr = array();
|
||||
$sec = $attrs['Def'] % 60;
|
||||
$min = ($attrs['Def'] / 60) % 60;
|
||||
$hours = ($attrs['Def'] / 3600) % 24;
|
||||
$days = (int) ($attrs['Def'] / 86400);
|
||||
if ($days > 0) {
|
||||
$arr[] = $days . $lang['After time d'];
|
||||
}
|
||||
if ($hours > 0) {
|
||||
$arr[] = $hours . $lang['After time H'];
|
||||
}
|
||||
if ($min > 0) {
|
||||
$arr[] = (($min < 10) ? '0' . $min : $min) . $lang['After time i'];
|
||||
}
|
||||
if ($sec > 0) {
|
||||
$arr[] = (($sec < 10) ? '0' . $sec : $sec) . $lang['After time s'];
|
||||
}
|
||||
|
||||
$attr = $lang['After time'] . ' ' . implode(' ', $arr);
|
||||
|
||||
return '<span style="color: #808080"><em>' . $attr . ':</em></span><br>';
|
||||
},
|
||||
])->setAttr('lang', [
|
||||
'After time' => 'Added later',
|
||||
'After time s' => ' s',
|
||||
'After time i' => ' min',
|
||||
'After time H' => ' h',
|
||||
'After time d' => ' d',
|
||||
])->parse('[after=10123]')
|
||||
->getHTML();
|
||||
|
||||
|
||||
#output: <span style="color: #808080"><em>Added later 2 h 48 min 43 s:</em></span><br>
|
588
vendor/miovisman/parserus/examples/bbcodes_test.php
vendored
588
vendor/miovisman/parserus/examples/bbcodes_test.php
vendored
|
@ -1,588 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
# example on the basis of (partially) bb-codes from FluxBB/PunBB parsers
|
||||
# пример на основании (частично) bb-кодов из парсеров FluxBB/PunBB
|
||||
|
||||
$bbcodes = [
|
||||
['tag' => 'ROOT',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
$body = '<p>' . $body . '</p>';
|
||||
|
||||
// Replace any breaks next to paragraphs so our replace below catches them
|
||||
$body = preg_replace('%(</?p>)(?:\s*?<br />){1,2}%', '$1', $body);
|
||||
$body = preg_replace('%(?:<br />\s*?){1,2}(</?p>)%', '$1', $body);
|
||||
|
||||
// Remove any empty paragraph tags (inserted via quotes/lists/code/etc) which should be stripped
|
||||
$body = str_replace('<p></p>', '', $body);
|
||||
|
||||
$body = preg_replace('%<br />\s*?<br />%', '</p><p>', $body);
|
||||
|
||||
$body = str_replace('<p><br />', '<br /><p>', $body);
|
||||
$body = str_replace('<br /></p>', '</p><br />', $body);
|
||||
$body = str_replace('<p></p>', '<br /><br />', $body);
|
||||
|
||||
return $body;
|
||||
},
|
||||
],
|
||||
['tag' => 'code',
|
||||
'type' => 'block',
|
||||
'recursive' => true,
|
||||
'text only' => true,
|
||||
'pre' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$body = trim($body, "\n\r");
|
||||
$class = substr_count($body, "\n") > 28 ? ' class="vscroll"' : '';
|
||||
return '</p><div class="codebox"><pre' . $class . '><code>' . $body . '</code></pre></div><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<strong>' . $body . '</strong>';
|
||||
},
|
||||
],
|
||||
['tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<em>' . $body . '</em>';
|
||||
},
|
||||
],
|
||||
['tag' => 'em',
|
||||
'handler' => function($body) {
|
||||
return '<em>' . $body . '</em>';
|
||||
},
|
||||
],
|
||||
['tag' => 'u',
|
||||
'handler' => function($body) {
|
||||
return '<span class="bbu">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 's',
|
||||
'handler' => function($body) {
|
||||
return '<span class="bbs">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'del',
|
||||
'handler' => function($body) {
|
||||
return '<del>' . $body . '</del>';
|
||||
},
|
||||
],
|
||||
['tag' => 'ins',
|
||||
'handler' => function($body) {
|
||||
return '<ins>' . $body . '</ins>';
|
||||
},
|
||||
],
|
||||
['tag' => 'h',
|
||||
'type' => 'h',
|
||||
'handler' => function($body) {
|
||||
return '</p><h5>' . $body . '</h5><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'hr',
|
||||
'type' => 'block',
|
||||
'single' => true,
|
||||
'handler' => function() {
|
||||
return '</p><hr /><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'color',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="color:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'colour',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="color:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'background',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^(?:\#(?:[\dA-Fa-f]{3}){1,2}|(?:aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|yellow|white))$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="background-color:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'size',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[1-9]\d*(?:em|ex|pt|px|\%)?$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (is_numeric($attrs['Def'])) {
|
||||
$attrs['Def'] .= 'px';
|
||||
}
|
||||
return '<span style="font-size:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'right',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
return '</p><p style="text-align: right;">' . $body . '</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'center',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
return '</p><p style="text-align: center;">' . $body . '</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'justify',
|
||||
'type' => 'block',
|
||||
'handler' => function($body) {
|
||||
return '</p><p style="text-align: justify;">' . $body . '</p><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'mono',
|
||||
'handler' => function($body) {
|
||||
return '<code>' . $body . '</code>';
|
||||
},
|
||||
],
|
||||
['tag' => 'font',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[a-z\d, -]+$%i',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
return '<span style="font-family:' . $attrs['Def'] . ';">' . $body . '</span>';
|
||||
},
|
||||
],
|
||||
['tag' => 'email',
|
||||
'type' => 'email',
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[^\x00-\x1f\s]+?@[^\x00-\x1f\s]+$%',
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^[^\x00-\x1f\s]+?@[^\x00-\x1f\s]+$%D',
|
||||
'text only' => true,
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (empty($attrs['Def'])) {
|
||||
return '<a href="mailto:' . $body . '">' . $body . '</a>';
|
||||
} else {
|
||||
return '<a href="mailto:' . $attrs['Def'] . '">' . $body . '</a>';
|
||||
}
|
||||
},
|
||||
],
|
||||
['tag' => '*',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'parents' => ['list'],
|
||||
'auto' => true,
|
||||
'handler' => function($body) {
|
||||
return '<li><p>' . $body . '</p></li>';
|
||||
},
|
||||
],
|
||||
['tag' => 'list',
|
||||
'type' => 'list',
|
||||
'self nesting' => true,
|
||||
'tags only' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
if (!isset($attrs['Def'])) {
|
||||
$attrs['Def'] = '*';
|
||||
}
|
||||
|
||||
switch ($attrs['Def'][0]) {
|
||||
case 'a':
|
||||
return '</p><ol class="alpha">' . $body . '</ol><p>';
|
||||
case '1':
|
||||
return '</p><ol class="decimal">' . $body . '</ol><p>';
|
||||
default:
|
||||
return '</p><ul>' . $body . '</ul><p>';
|
||||
}
|
||||
},
|
||||
],
|
||||
['tag' => 'after',
|
||||
'type' => 'block',
|
||||
'single' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^\d+$%',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
$lang = $parser->attr('lang');
|
||||
$arr = array();
|
||||
$sec = $attrs['Def'] % 60;
|
||||
$min = ($attrs['Def'] / 60) % 60;
|
||||
$hours = ($attrs['Def'] / 3600) % 24;
|
||||
$days = (int) ($attrs['Def'] / 86400);
|
||||
if ($days > 0) {
|
||||
$arr[] = $days . $lang['After time d'];
|
||||
}
|
||||
if ($hours > 0) {
|
||||
$arr[] = $hours . $lang['After time H'];
|
||||
}
|
||||
if ($min > 0) {
|
||||
$arr[] = (($min < 10) ? '0' . $min : $min) . $lang['After time i'];
|
||||
}
|
||||
if ($sec > 0) {
|
||||
$arr[] = (($sec < 10) ? '0' . $sec : $sec) . $lang['After time s'];
|
||||
}
|
||||
|
||||
$attr = $lang['After time'] . ' ' . implode(' ', $arr);
|
||||
|
||||
return '<span style="color: #808080"><em>' . $attr . ':</em></span><br />';
|
||||
},
|
||||
],
|
||||
['tag' => 'quote',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (isset($attrs['Def'])) {
|
||||
$lang = $parser->attr('lang');
|
||||
$st = '</p><div class="quotebox"><cite>' . $attrs['Def'] . ' ' . $lang['wrote'] . '</cite><blockquote><div><p>';
|
||||
} else {
|
||||
$st = '</p><div class="quotebox"><blockquote><div><p>';
|
||||
}
|
||||
|
||||
return $st . $body . '</p></div></blockquote></div><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'spoiler',
|
||||
'type' => 'block',
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'Def' => true,
|
||||
'no attr' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (isset($attrs['Def'])) {
|
||||
$st = '</p><div class="quotebox" style="padding: 0px;"><div onclick="var e,d,c=this.parentNode,a=c.getElementsByTagName(\'div\')[1],b=this.getElementsByTagName(\'span\')[0];if(a.style.display!=\'\'){while(c.parentNode&&(!d||!e||d==e)){e=d;d=(window.getComputedStyle?getComputedStyle(c, null):c.currentStyle)[\'backgroundColor\'];if(d==\'transparent\'||d==\'rgba(0, 0, 0, 0)\')d=e;c=c.parentNode;}a.style.display=\'\';a.style.backgroundColor=d;b.innerHTML=\'▲\';}else{a.style.display=\'none\';b.innerHTML=\'▼\';}" style="font-weight: bold; cursor: pointer; font-size: 0.9em;"><span style="padding: 0 5px;">▼</span>' . $attrs['Def'] . '</div><div style="padding: 6px; margin: 0; display: none;"><p>';
|
||||
} else {
|
||||
$lang = $parser->attr('lang');
|
||||
$st = '</p><div class="quotebox" style="padding: 0px;"><div onclick="var e,d,c=this.parentNode,a=c.getElementsByTagName(\'div\')[1],b=this.getElementsByTagName(\'span\')[0];if(a.style.display!=\'\'){while(c.parentNode&&(!d||!e||d==e)){e=d;d=(window.getComputedStyle?getComputedStyle(c, null):c.currentStyle)[\'backgroundColor\'];if(d==\'transparent\'||d==\'rgba(0, 0, 0, 0)\')d=e;c=c.parentNode;}a.style.display=\'\';a.style.backgroundColor=d;b.innerHTML=\'▲\';}else{a.style.display=\'none\';b.innerHTML=\'▼\';}" style="font-weight: bold; cursor: pointer; font-size: 0.9em;"><span style="padding: 0 5px;">▼</span>' . $lang['Hidden text'] . '</div><div style="padding: 6px; margin: 0; display: none;"><p>';
|
||||
}
|
||||
|
||||
return $st . $body . '</p></div></div><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'img',
|
||||
'type' => 'img',
|
||||
'parents' => ['inline', 'block', 'url'],
|
||||
'text only' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'body format' => '%^(?:(?:ht|f)tps?://[^\x00-\x1f\s<"]+|data:image/[a-z]+;base64,(?:[a-zA-Z\d/\+\=]+))$%D'
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^(?:(?:ht|f)tps?://[^\x00-\x1f\s<"]+|data:image/[a-z]+;base64,(?:[a-zA-Z\d/\+\=]+))$%D'
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (! isset($attrs['Def'])) {
|
||||
$attrs['Def'] = (substr($body, 0, 11) === 'data:image/') ? 'base64' : basename($body);
|
||||
}
|
||||
|
||||
// тег в подписи
|
||||
if ($parser->attr('isSign')) {
|
||||
if ($parser->attr('showImgSign')) {
|
||||
return '<img src="' . $body . '" alt="' . $attrs['Def'] . '" class="sigimage" />';
|
||||
}
|
||||
} else {
|
||||
// тег в теле сообщения
|
||||
if ($parser->attr('showImg')) {
|
||||
return '<span class="postimg"><img src="' . $body . '" alt="' . $attrs['Def'] . '" /></span>';
|
||||
}
|
||||
}
|
||||
|
||||
$lang = $parser->attr('lang');
|
||||
|
||||
return '<a href="' . $body . '" rel="nofollow"><' . $lang['Image link']. ' - ' . $attrs['Def'] . '></a>';
|
||||
},
|
||||
],
|
||||
['tag' => 'url',
|
||||
'type' => 'url',
|
||||
'parents' => ['inline', 'block'],
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[^\x00-\x1f]+$%',
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^[^\x00-\x1f]+$%D',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (isset($attrs['Def'])) {
|
||||
$url = $attrs['Def'];
|
||||
} else {
|
||||
$url = $body;
|
||||
// возможно внутри была картинка, которая отображается как ссылка
|
||||
if (preg_match('%^<a href=".++(?<=</a>)$%D', $url)) {
|
||||
return $url;
|
||||
}
|
||||
// возможно внутри картинка
|
||||
if (preg_match('%<img src="([^"]+)"%', $url, $match)) {
|
||||
$url = $match[1];
|
||||
}
|
||||
}
|
||||
|
||||
$fUrl = str_replace(array(' ', '\'', '`', '"'), array('%20', '', '', ''), $url);
|
||||
|
||||
if (strpos($url, 'www.') === 0) {
|
||||
$fUrl = 'http://'.$fUrl;
|
||||
} else if (strpos($url, 'ftp.') === 0) {
|
||||
$fUrl = 'ftp://'.$fUrl;
|
||||
} else if (strpos($url, '/') === 0) {
|
||||
$fUrl = $parser->attr('baseUrl') . $fUrl;
|
||||
} else if (!preg_match('%^([a-z0-9]{3,6})://%', $url)) {
|
||||
$fUrl = 'http://'.$fUrl;
|
||||
}
|
||||
|
||||
if ($url === $body) {
|
||||
$url = htmlspecialchars_decode($url, ENT_QUOTES);
|
||||
$url = mb_strlen($url, 'UTF-8') > 55 ? mb_substr($url, 0, 39, 'UTF-8') . ' … ' . mb_substr($url, -10, null, 'UTF-8') : $url;
|
||||
$body = $parser->e($url);
|
||||
}
|
||||
|
||||
return '<a href="' . $fUrl . '" rel="nofollow">' . $body . '</a>';
|
||||
},
|
||||
],
|
||||
['tag' => 'table',
|
||||
'type' => 'table',
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'align' => true,
|
||||
'background' => true,
|
||||
'bgcolor' => true,
|
||||
'border' => true,
|
||||
'bordercolor' => true,
|
||||
'cellpadding' => true,
|
||||
'cellspacing' => true,
|
||||
'frame' => true,
|
||||
'rules' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '</p><table' . $attr . '>' . $body . '</table><p>';
|
||||
},
|
||||
],
|
||||
['tag' => 'caption',
|
||||
'type' => 'block',
|
||||
'parents' => ['table'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<caption' . $attr . '><p>' . $body . '</p></caption>';
|
||||
},
|
||||
],
|
||||
['tag' => 'thead',
|
||||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<thead' . $attr . '>' . $body . '</thead>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tbody',
|
||||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tbody' . $attr . '>' . $body . '</tbody>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tfoot',
|
||||
'type' => 't',
|
||||
'parents' => ['table'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tfoot' . $attr . '>' . $body . '</tfoot>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tr',
|
||||
'type' => 'tr',
|
||||
'parents' => ['table', 't'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tr' . $attr . '>' . $body . '</tr>';
|
||||
},
|
||||
],
|
||||
['tag' => 'th',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'colspan' => true,
|
||||
'rowspan' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<th' . $attr . '><p>' . $body . '</p></th>';
|
||||
},
|
||||
],
|
||||
['tag' => 'td',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'colspan' => true,
|
||||
'rowspan' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<td' . $attr . '><p>' . $body . '</p></td>';
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
$lang = [
|
||||
'Hidden text' => 'Hidden text',
|
||||
'wrote' => 'wrote:', // For [quote]'s
|
||||
'After time' => 'Added later',
|
||||
'After time s' => ' s',
|
||||
'After time i' => ' min',
|
||||
'After time H' => ' h',
|
||||
'After time d' => ' d',
|
||||
'Image link' => 'image', // This is displayed (i.e. <image>) instead of images when "Show images" is disabled in the profile
|
||||
];
|
||||
|
||||
$text = '[table align="center" border="1" bordercolor="#ccc" cellpadding="5" cellspacing="0" style="border-collapse:collapse; width:500px"]
|
||||
[caption][b]Table[/b][/caption]
|
||||
[thead]
|
||||
[tr]
|
||||
[th style=width:50%]Column 1[/th]
|
||||
[th style=width:50%]Column 2[/th]
|
||||
[/tr]
|
||||
[/thead]
|
||||
[tbody]
|
||||
[tr]
|
||||
[td]1.1[/td]
|
||||
[td]
|
||||
[list]
|
||||
[*]1.2
|
||||
[*]1.3
|
||||
[*]1.4
|
||||
[/list]
|
||||
[/td]
|
||||
[/tr]
|
||||
[/tbody]
|
||||
[/table]
|
||||
[size=36]Hello World![/size]
|
||||
[img]data:image/gif;base64,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[/img]
|
||||
[code]
|
||||
$parser->setBBCodes($bbcodes)
|
||||
->setAttr(\'baseUrl\', \'http://localhost\')
|
||||
->setAttr(\'lang\', $lang)
|
||||
->setAttr(\'showImg\', true)
|
||||
->setAttr(\'showImgSign\', true)
|
||||
->setAttr(\'isSign\', false)
|
||||
->parse($text);
|
||||
[/code]
|
||||
|
||||
[center][background=#00CCCC][url=https://github.com/MioVisman/Parserus]Parserus[/url] BBCode parser[/background][/center]
|
||||
|
||||
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
';
|
||||
|
||||
$parser = new Parserus(ENT_XHTML);
|
||||
$parser->setBBCodes($bbcodes)
|
||||
->setAttr('baseUrl', 'http://localhost')
|
||||
->setAttr('lang', $lang)
|
||||
->setAttr('showImg', true)
|
||||
->setAttr('showImgSign', true)
|
||||
->setAttr('isSign', false)
|
||||
->parse($text);
|
||||
|
||||
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru" dir="ltr">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
</head>
|
||||
<body>' .
|
||||
$parser->getHtml() .
|
||||
'</body>
|
||||
</html>';
|
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->setBBCodes([
|
||||
['tag' => 'url',
|
||||
'type' => 'url',
|
||||
'parents' => ['inline', 'block'],
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[^\x00-\x1f]+$%',
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^[^\x00-\x1f]+$%D',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
#...
|
||||
},
|
||||
],
|
||||
])->parse('Hello www.example.com World!')
|
||||
->detectUrls()
|
||||
->getCode();
|
||||
|
||||
#output: Hello [url]www.example.com[/url] World!
|
|
@ -1,63 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->setBBCodes([
|
||||
['tag' => 'url',
|
||||
'type' => 'url',
|
||||
'parents' => ['inline', 'block'],
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'format' => '%^[^\x00-\x1f]+$%',
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^[^\x00-\x1f]+$%D',
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
#...
|
||||
},
|
||||
],
|
||||
['tag' => 'h',
|
||||
'type' => 'h',
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
#...
|
||||
},
|
||||
],
|
||||
])->parse('www.example.com/link1[h]Hello www.example.com/link2 World![/h]www.example.com/link3')
|
||||
->detectUrls()
|
||||
->getCode();
|
||||
|
||||
#output: [url]www.example.com/link1[/url][h]Hello www.example.com/link2 World![/h][url]www.example.com/link3[/url]
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
echo $parser->setBlackList(['url'])
|
||||
->setWhiteList()
|
||||
->parse('www.example.com/link1[h]Hello www.example.com/link2 World![/h]www.example.com/link3')
|
||||
->detectUrls()
|
||||
->getCode();
|
||||
|
||||
#output: www.example.com/link1[h]Hello www.example.com/link2 World![/h]www.example.com/link3
|
||||
|
||||
var_dump($parser->getErrors());
|
||||
|
||||
#output: array (size=1)
|
||||
#output: 0 => string 'Тег [url] находится в черном списке' (length=60)
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
echo $parser->setBlackList()
|
||||
->setWhiteList(['h'])
|
||||
->parse('www.example.com/link1[h]Hello www.example.com/link2 World![/h]www.example.com/link3')
|
||||
->detectUrls()
|
||||
->getCode();
|
||||
|
||||
#output: www.example.com/link1[h]Hello www.example.com/link2 World![/h]www.example.com/link3
|
||||
|
||||
var_dump($parser->getErrors());
|
||||
|
||||
#output: array (size=1)
|
||||
#output: 0 => string 'Тег [url] отсутствует в белом списке' (length=62)
|
9
vendor/miovisman/parserus/examples/e.php
vendored
9
vendor/miovisman/parserus/examples/e.php
vendored
|
@ -1,9 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->e("<'abcde'>");
|
||||
|
||||
#output: <'abcde'>
|
126
vendor/miovisman/parserus/examples/getCode.php
vendored
126
vendor/miovisman/parserus/examples/getCode.php
vendored
|
@ -1,126 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->setBBCodes([
|
||||
['tag' => 'table',
|
||||
'type' => 'table',
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'align' => true,
|
||||
'background' => true,
|
||||
'bgcolor' => true,
|
||||
'border' => true,
|
||||
'bordercolor' => true,
|
||||
'cellpadding' => true,
|
||||
'cellspacing' => true,
|
||||
'frame' => true,
|
||||
'rules' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<table' . $attr . '>' . $body . '</table>';
|
||||
},
|
||||
],
|
||||
['tag' => 'tr',
|
||||
'type' => 'tr',
|
||||
'parents' => ['table', 't'],
|
||||
'tags only' => true,
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<tr' . $attr . '>' . $body . '</tr>';
|
||||
},
|
||||
],
|
||||
['tag' => 'th',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'colspan' => true,
|
||||
'rowspan' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<th' . $attr . '>' . $body . '</th>';
|
||||
},
|
||||
],
|
||||
['tag' => 'td',
|
||||
'type' => 'block',
|
||||
'parents' => ['tr'],
|
||||
'self nesting' => true,
|
||||
'attrs' => [
|
||||
'no attr' => true,
|
||||
'style' => true,
|
||||
'colspan' => true,
|
||||
'rowspan' => true,
|
||||
],
|
||||
'handler' => function($body, $attrs) {
|
||||
$attr = '';
|
||||
foreach ($attrs as $key => $val) {
|
||||
$attr .= ' ' . $key . '="' . $val . '"';
|
||||
}
|
||||
return '<td' . $attr . '>' . $body . '</td>';
|
||||
},
|
||||
],
|
||||
])->parse('
|
||||
[table align=right border=1 bordercolor=#ccc cellpadding=5 cellspacing=0 style="border-collapse:collapse; width:500px"]
|
||||
[tr]
|
||||
[th style="width:50%"]Position[/th]
|
||||
[th style=width:50%]Astronaut[/th]
|
||||
[/tr]
|
||||
[tr]
|
||||
[td]Commander[/td]
|
||||
[td]Neil A. Armstrong[/td]
|
||||
[/tr]
|
||||
[tr]
|
||||
[td]Command Module Pilot[/td]
|
||||
[td]Michael Collins[/td]
|
||||
[/tr]
|
||||
[tr]
|
||||
[td]Lunar Module Pilot[/td]
|
||||
[td]Edwin "Buzz" E. Aldrin, Jr.[/td]
|
||||
[/tr]
|
||||
[/table]
|
||||
')->getCode();
|
||||
|
||||
#output:
|
||||
#[table align="right" border="1" bordercolor="#ccc" cellpadding="5" cellspacing="0" style="border-collapse:collapse; width:500px"]
|
||||
# [tr]
|
||||
# [th style=width:50%]Position[/th]
|
||||
# [th style=width:50%]Astronaut[/th]
|
||||
# [/tr]
|
||||
# [tr]
|
||||
# [td]Commander[/td]
|
||||
# [td]Neil A. Armstrong[/td]
|
||||
# [/tr]
|
||||
# [tr]
|
||||
# [td]Command Module Pilot[/td]
|
||||
# [td]Michael Collins[/td]
|
||||
# [/tr]
|
||||
# [tr]
|
||||
# [td]Lunar Module Pilot[/td]
|
||||
# [td]Edwin "Buzz" E. Aldrin, Jr.[/td]
|
||||
# [/tr]
|
||||
#[/table]
|
||||
#
|
41
vendor/miovisman/parserus/examples/getErrors.php
vendored
41
vendor/miovisman/parserus/examples/getErrors.php
vendored
|
@ -1,41 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
$parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
]);
|
||||
|
||||
$parser->parse("[i][b] [/b][/i]")->stripEmptyTags(" \n", true);
|
||||
|
||||
$err = [
|
||||
1 => '[%1$s] is in the black list',
|
||||
2 => '[%1$s] is absent in the white list',
|
||||
3 => '[%1$s] can\'t be opened in the [%2$s]',
|
||||
4 => '[/%1$s] was found without a matching [%1$s]',
|
||||
5 => '[/%1$s] is found for single [%1$s]',
|
||||
6 => 'There are no attributes in [%1$s]',
|
||||
7 => 'Primary attribute is forbidden in [%1$s=...]',
|
||||
8 => 'Secondary attributes are forbidden in [%1$s ...]',
|
||||
9 => 'The attribute \'%2$s\' doesn\'t correspond to a template in the [%1$s]',
|
||||
10 => '[%1$s ...] contains unknown secondary attribute \'%2$s\'',
|
||||
11 => 'The body of [%1$s] doesn\'t correspond to a template',
|
||||
12 => '[%1$s] was opened within itself, this is not allowed',
|
||||
13 => 'In the [%1$s] is absent mandatory attribute \'%2$s\'',
|
||||
14 => 'All tags are empty'
|
||||
];
|
||||
|
||||
var_dump($parser->getErrors($err));
|
||||
|
||||
#output: array (size=1)
|
||||
# 0 => string 'All tags are empty' (length=18)
|
34
vendor/miovisman/parserus/examples/smilies.php
vendored
34
vendor/miovisman/parserus/examples/smilies.php
vendored
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
echo $parser->setSmilies([
|
||||
':)' => 'http://example.com/smilies/smile.png',
|
||||
';)' => 'http://example.com/smilies/wink.png',
|
||||
])->addBBCode([
|
||||
'tag' => 'img',
|
||||
'type' => 'img',
|
||||
'parents' => ['inline', 'block', 'url'],
|
||||
'text only' => true,
|
||||
'attrs' => [
|
||||
'Def' => [
|
||||
'body format' => '%^(?:(?:ht|f)tps?://[^\x00-\x1f\s<"]+|data:image/[a-z]+;base64,(?:[a-zA-Z\d/\+\=]+))$%D'
|
||||
],
|
||||
'no attr' => [
|
||||
'body format' => '%^(?:(?:ht|f)tps?://[^\x00-\x1f\s<"]+|data:image/[a-z]+;base64,(?:[a-zA-Z\d/\+\=]+))$%D'
|
||||
],
|
||||
],
|
||||
'handler' => function($body, $attrs, $parser) {
|
||||
if (! isset($attrs['Def'])) {
|
||||
$attrs['Def'] = (substr($body, 0, 11) === 'data:image/') ? 'base64' : basename($body);
|
||||
}
|
||||
return '<img src="' . $body . '" alt="' . $attrs['Def'] . '">';
|
||||
},
|
||||
])->setSmTpl('<img src="{url}" alt="{alt}">')
|
||||
->parse(":)\n;)")
|
||||
->detectSmilies()
|
||||
->getHTML();
|
||||
|
||||
#output: <img src="http://example.com/smilies/smile.png" alt=":)"><br><img src="http://example.com/smilies/wink.png" alt=";)">
|
|
@ -1,61 +0,0 @@
|
|||
<?php
|
||||
|
||||
include '../Parserus.php';
|
||||
|
||||
$parser = new Parserus();
|
||||
|
||||
$parser->addBBCode([
|
||||
'tag' => 'b',
|
||||
'handler' => function($body) {
|
||||
return '<b>' . $body . '</b>';
|
||||
}
|
||||
])->addBBcode([
|
||||
'tag' => 'i',
|
||||
'handler' => function($body) {
|
||||
return '<i>' . $body . '</i>';
|
||||
},
|
||||
]);
|
||||
|
||||
# №1
|
||||
|
||||
var_dump($parser->parse("[i][b] [/b][/i]")->stripEmptyTags());
|
||||
|
||||
#output: boolean false
|
||||
|
||||
echo $parser->getCode();
|
||||
|
||||
#output: [i][b] [/b][/i]
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
# №2
|
||||
|
||||
var_dump($parser->parse("[i][b] [/b][/i]")->stripEmptyTags(" \n", true));
|
||||
|
||||
#output: boolean true
|
||||
|
||||
echo $parser->getCode();
|
||||
|
||||
#output: [i][b] [/b][/i]
|
||||
|
||||
var_dump($parser->getErrors());
|
||||
|
||||
#output: array (size=1)
|
||||
# 0 => string 'Все теги пустые' (length=28)
|
||||
|
||||
echo "\n\n";
|
||||
|
||||
# №3
|
||||
|
||||
var_dump($parser->parse("[i][b] [/b][/i]")->stripEmptyTags(" \n"));
|
||||
|
||||
#output: boolean true
|
||||
|
||||
echo $parser->getCode();
|
||||
|
||||
#output:
|
||||
|
||||
var_dump($parser->getErrors());
|
||||
|
||||
#output: array (size=1)
|
||||
# empty
|
Loading…
Reference in a new issue