mirror of
https://github.com/j0k3r/php-readability.git
synced 2026-09-27 14:36:23 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e5d31b93d1 | ||
|
|
6e24a5d731 | ||
|
|
ff754b80bd | ||
|
|
ade850534c | ||
|
|
d97bece7c5 | ||
|
|
47ce4fb7f9 | ||
|
|
3de4e918b4 | ||
|
|
5182d6cb11 | ||
|
|
fb9810a827 | ||
|
|
22aa4c3b31 | ||
|
|
2ef400bf73 | ||
|
|
dec4514c00 | ||
|
|
00f622e9b7 |
@@ -3,6 +3,7 @@
|
||||
/.gitignore export-ignore
|
||||
/.scrutinizer.yml export-ignore
|
||||
/.travis.yml export-ignore
|
||||
/.php_cs export-ignore
|
||||
/README.md export-ignore
|
||||
/phpunit.xml.dist export-ignore
|
||||
/tests export-ignore
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
vendor/
|
||||
coverage/
|
||||
composer.lock
|
||||
.php_cs.cache
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
return Symfony\CS\Config\Config::create()
|
||||
->setUsingCache(true)
|
||||
->level(Symfony\CS\FixerInterface::SYMFONY_LEVEL)
|
||||
// use default SYMFONY_LEVEL and extra fixers:
|
||||
->fixers(array(
|
||||
'concat_with_spaces',
|
||||
'ordered_use',
|
||||
'phpdoc_order',
|
||||
'strict',
|
||||
'strict_param',
|
||||
'long_array_syntax',
|
||||
))
|
||||
->finder(
|
||||
Symfony\CS\Finder\DefaultFinder::create()
|
||||
->in(__DIR__)
|
||||
->exclude(array('vendor'))
|
||||
)
|
||||
;
|
||||
+15
-4
@@ -7,12 +7,18 @@ php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- nightly
|
||||
- hhvm
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- php: 7.0
|
||||
env: CS_FIXER=run
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- php: hhvm
|
||||
- php: nightly
|
||||
|
||||
# faster builds on new travis setup not using sudo
|
||||
sudo: false
|
||||
@@ -23,20 +29,25 @@ cache:
|
||||
- vendor
|
||||
- $HOME/.composer/cache
|
||||
|
||||
install:
|
||||
- composer self-update
|
||||
|
||||
before_script:
|
||||
before_install:
|
||||
- if [ -n "$GH_TOKEN" ]; then composer config github-oauth.github.com ${GH_TOKEN}; fi;
|
||||
# disable TLS for composer because openssl is disabled for PHP 5.3.3 on travis
|
||||
# see: https://blog.travis-ci.com/upcoming_ubuntu_11_10_migration/
|
||||
- if [[ $TRAVIS_PHP_VERSION = 5.3.3 ]]; then composer config -g -- disable-tls true; fi;
|
||||
- if [[ $TRAVIS_PHP_VERSION = 5.3.3 ]]; then composer config -g -- secure-http false; fi;
|
||||
# no version compatible with PHP > 7.1
|
||||
- if [[ $TRAVIS_PHP_VERSION = 7.2.* ]]; then composer remove friendsofphp/php-cs-fixer; fi;
|
||||
|
||||
install:
|
||||
- composer self-update
|
||||
|
||||
before_script:
|
||||
- composer install --prefer-dist --no-interaction
|
||||
|
||||
script:
|
||||
- mkdir -p build/logs
|
||||
- phpunit -v --coverage-clover build/logs/clover.xml
|
||||
- if [ "$CS_FIXER" = "run" ]; then php vendor/bin/php-cs-fixer fix --verbose --dry-run ; fi;
|
||||
|
||||
after_script:
|
||||
- php vendor/bin/coveralls -v
|
||||
|
||||
+3
-2
@@ -25,10 +25,11 @@
|
||||
}],
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"monolog/monolog": "^1.13.1"
|
||||
"monolog/monolog": "^1.13"
|
||||
},
|
||||
"require-dev": {
|
||||
"satooshi/php-coveralls": "~0.6"
|
||||
"satooshi/php-coveralls": "~0.6",
|
||||
"friendsofphp/php-cs-fixer": "<2"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Readability\\": "src/" }
|
||||
|
||||
@@ -45,14 +45,14 @@ class JSLikeHTMLElement extends \DOMElement
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
if ($name == 'innerHTML') {
|
||||
if ($name === 'innerHTML') {
|
||||
// first, empty the element
|
||||
for ($x = $this->childNodes->length - 1; $x >= 0; --$x) {
|
||||
$this->removeChild($this->childNodes->item($x));
|
||||
}
|
||||
|
||||
// $value holds our new inner HTML
|
||||
if ($value != '') {
|
||||
if ($value !== '') {
|
||||
$f = $this->ownerDocument->createDocumentFragment();
|
||||
|
||||
// appendXML() expects well-formed markup (XHTML)
|
||||
@@ -102,7 +102,7 @@ class JSLikeHTMLElement extends \DOMElement
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if ($name == 'innerHTML') {
|
||||
if ($name === 'innerHTML') {
|
||||
$inner = '';
|
||||
|
||||
foreach ($this->childNodes as $child) {
|
||||
|
||||
+62
-36
@@ -66,7 +66,7 @@ class Readability implements LoggerAwareInterface
|
||||
public $tidied = false;
|
||||
// article domain regexp for calibration
|
||||
protected $domainRegExp = null;
|
||||
protected $body = null; //
|
||||
protected $body = null;
|
||||
// Cache the body HTML in case we need to re-use it later
|
||||
protected $bodyCache = null;
|
||||
// 1 | 2 | 4; // Start with all processing flags set.
|
||||
@@ -83,11 +83,11 @@ class Readability implements LoggerAwareInterface
|
||||
* Defined up here so we don't instantiate them repeatedly in loops.
|
||||
*/
|
||||
public $regexps = array(
|
||||
'unlikelyCandidates' => '/display\s*:\s*none|ignore|\binfo|annoy|clock|date|time|author|intro|links|hidd?e|about|archive|\bprint|bookmark|tags|tag-list|share|search|social|robot|published|combx|comment|mast(?:head)|subscri|community|category|disqus|extra|head|head(?:er|note)|floor|foot(?:er|note)|menu|tool|function|nav|remark|rss|shoutbox|tool|widget|meta|banner|sponsor|adsense|inner-?ad|ad-|sponsor|\badv\b|\bads\b|agr?egate?|pager|sidebar|popup|tweet|twitter/i',
|
||||
'unlikelyCandidates' => '/display\s*:\s*none|ignore|\binfos?\b|annoy|clock|date|time|author|intro|links|hidd?e|about|archive|\bprint|bookmark|tags|tag-list|share|search|social|robot|published|combx|comment|mast(?:head)|subscri|community|category|disqus|extra|head|head(?:er|note)|floor|foot(?:er|note)|menu|tool\b|function|nav|remark|rss|shoutbox|widget|meta|banner|sponsor|adsense|inner-?ad|ad-|sponsor|\badv\b|\bads\b|agr?egate?|pager|sidebar|popup|tweet|twitter/i',
|
||||
'okMaybeItsACandidate' => '/article\b|contain|\bcontent|column|general|detail|shadow|lightbox|blog|body|entry|main|page/i',
|
||||
'positive' => '/read|full|article|body|\bcontent|contain|entry|main|markdown|page|attach|pagination|post|text|blog|story/i',
|
||||
'negative' => '/bottom|stat|info|discuss|e[\-]?mail|comment|reply|log.{2}(n|ed)|sign|single|combx|com-|contact|_nav|link|media|\bout|promo|\bad-|related|scroll|shoutbox|sidebar|sponsor|shopping|teaser|recommend/i',
|
||||
'divToPElements' => '/<(?:blockquote|code|div|article|footer|aside|img|p|pre|dl|ol|ul)/mi',
|
||||
'divToPElements' => '/<(?:blockquote|header|section|code|div|article|footer|aside|img|p|pre|dl|ol|ul)/mi',
|
||||
'killBreaks' => '/(<br\s*\/?>([ \r\n\s]| ?)*)+/',
|
||||
'media' => '!//(?:[^\.\?/]+\.)?(?:youtu(?:be)?|soundcloud|dailymotion|vimeo|pornhub|xvideos|twitvid|rutube|viddler)\.(?:com|be|org|net)/!i',
|
||||
'skipFootnoteLink' => '/^\s*(\[?[a-z0-9]{1,2}\]?|^|edit|citation needed)\s*$/i',
|
||||
@@ -174,14 +174,15 @@ class Readability implements LoggerAwareInterface
|
||||
* @param string (optional) Which parser to use for turning raw HTML into a DOMDocument
|
||||
* @param bool (optional) Use tidy
|
||||
*/
|
||||
public function __construct($html, $url = null, $parser = 'libxml', $useTidy = true)
|
||||
public function __construct($html, $url = null, $parser = 'libxml', $use_tidy = true)
|
||||
{
|
||||
$this->url = $url;
|
||||
$this->html = $html;
|
||||
$this->parser = $parser;
|
||||
$this->useTidy = $useTidy && function_exists('tidy_parse_string');
|
||||
$this->useTidy = $use_tidy && function_exists('tidy_parse_string');
|
||||
|
||||
$this->logger = new NullLogger();
|
||||
$this->loadHtml();
|
||||
}
|
||||
|
||||
public function setLogger(LoggerInterface $logger)
|
||||
@@ -235,6 +236,8 @@ class Readability implements LoggerAwareInterface
|
||||
* Load HTML in a DOMDocument.
|
||||
* Apply Pre filters
|
||||
* Cleanup HTML using Tidy (or not).
|
||||
*
|
||||
* @todo This should be called in init() instead of from __construct
|
||||
*/
|
||||
private function loadHtml()
|
||||
{
|
||||
@@ -266,7 +269,6 @@ class Readability implements LoggerAwareInterface
|
||||
* Use tidy (if it exists).
|
||||
* This fixes problems with some sites which would otherwise trouble DOMDocument's HTML parsing.
|
||||
* Although sometimes it makes matters worse, which is why there is an option to disable it.
|
||||
*
|
||||
*/
|
||||
if ($this->useTidy) {
|
||||
$this->logger->debug('Tidying document');
|
||||
@@ -282,7 +284,7 @@ class Readability implements LoggerAwareInterface
|
||||
|
||||
$this->html = mb_convert_encoding($this->html, 'HTML-ENTITIES', 'UTF-8');
|
||||
|
||||
if (!($this->parser == 'html5lib' && ($this->dom = \HTML5_Parser::parse($this->html)))) {
|
||||
if (!($this->parser === 'html5lib' && ($this->dom = \HTML5_Parser::parse($this->html)))) {
|
||||
libxml_use_internal_errors(true);
|
||||
|
||||
$this->dom = new \DOMDocument();
|
||||
@@ -314,8 +316,6 @@ class Readability implements LoggerAwareInterface
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->loadHtml();
|
||||
|
||||
if (!isset($this->dom->documentElement)) {
|
||||
return false;
|
||||
}
|
||||
@@ -325,7 +325,7 @@ class Readability implements LoggerAwareInterface
|
||||
$bodyElems = $this->dom->getElementsByTagName('body');
|
||||
|
||||
// WTF multiple body nodes?
|
||||
if ($this->bodyCache == null) {
|
||||
if ($this->bodyCache === null) {
|
||||
$this->bodyCache = '';
|
||||
foreach ($bodyElems as $bodyNode) {
|
||||
$this->bodyCache .= trim($bodyNode->innerHTML);
|
||||
@@ -372,12 +372,33 @@ class Readability implements LoggerAwareInterface
|
||||
return $this->success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug.
|
||||
*
|
||||
* @deprecated use $this->logger->debug() instead
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function dbg($msg)
|
||||
{
|
||||
$this->logger->debug($msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump debug info.
|
||||
*
|
||||
* @deprecated since Monolog gather log, we don't need it
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
protected function dump_dbg()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Run any post-process modifications to article content as necessary.
|
||||
*
|
||||
* @param \DOMElement $articleContent
|
||||
*/
|
||||
public function postProcessContent(\DOMElement $articleContent)
|
||||
public function postProcessContent($articleContent)
|
||||
{
|
||||
if ($this->convertLinksToFootnotes && !preg_match('/\bwiki/', $this->url)) {
|
||||
$this->addFootnotes($articleContent);
|
||||
@@ -410,7 +431,7 @@ class Readability implements LoggerAwareInterface
|
||||
}
|
||||
} elseif (mb_strlen($curTitle) > 150 || mb_strlen($curTitle) < 15) {
|
||||
$hOnes = $this->dom->getElementsByTagName('h1');
|
||||
if ($hOnes->length == 1) {
|
||||
if ($hOnes->length === 1) {
|
||||
$curTitle = $this->getInnerText($hOnes->item(0));
|
||||
}
|
||||
}
|
||||
@@ -462,7 +483,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @param \DOMElement $articleContent
|
||||
*/
|
||||
public function addFootnotes(\DOMElement $articleContent)
|
||||
public function addFootnotes($articleContent)
|
||||
{
|
||||
$footnotesWrapper = $this->dom->createElement('footer');
|
||||
$footnotesWrapper->setAttribute('class', 'readability-footnotes');
|
||||
@@ -505,7 +526,7 @@ class Readability implements LoggerAwareInterface
|
||||
$articleLink->setAttribute('style', 'color: inherit; text-decoration: none;');
|
||||
$articleLink->setAttribute('name', 'readabilityLink-' . $linkCount);
|
||||
$footnote->innerHTML = '<small><sup><a href="#readabilityLink-' . $linkCount . '" title="Jump to Link in Article">^</a></sup></small> ';
|
||||
$footnoteLink->innerHTML = ($footnoteLink->getAttribute('title') != '' ? $footnoteLink->getAttribute('title') : $linkText);
|
||||
$footnoteLink->innerHTML = ($footnoteLink->getAttribute('title') !== '' ? $footnoteLink->getAttribute('title') : $linkText);
|
||||
$footnoteLink->setAttribute('name', 'readabilityFootnoteLink-' . $linkCount);
|
||||
$footnote->appendChild($footnoteLink);
|
||||
|
||||
@@ -526,7 +547,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @param \DOMElement $articleContent
|
||||
*/
|
||||
public function prepArticle(\DOMElement $articleContent)
|
||||
public function prepArticle($articleContent)
|
||||
{
|
||||
$this->logger->debug($this->lightClean ? 'Light clean enabled.' : 'Standard clean enabled.');
|
||||
|
||||
@@ -567,7 +588,7 @@ class Readability implements LoggerAwareInterface
|
||||
* already have a header.
|
||||
*/
|
||||
$h2s = $articleContent->getElementsByTagName('h2');
|
||||
if ($h2s->length == 1 && mb_strlen($this->getInnerText($h2s->item(0), true, true)) < 100) {
|
||||
if ($h2s->length === 1 && mb_strlen($this->getInnerText($h2s->item(0), true, true)) < 100) {
|
||||
$this->clean($articleContent, 'h2');
|
||||
}
|
||||
|
||||
@@ -623,7 +644,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @param \DOMElement $node
|
||||
*/
|
||||
protected function initializeNode(\DOMElement $node)
|
||||
protected function initializeNode($node)
|
||||
{
|
||||
if (!isset($node->tagName)) {
|
||||
return;
|
||||
@@ -694,7 +715,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @return \DOMElement|bool
|
||||
*/
|
||||
protected function grabArticle(\DOMElement $page = null)
|
||||
protected function grabArticle($page = null)
|
||||
{
|
||||
if (!$page) {
|
||||
$page = $this->dom;
|
||||
@@ -711,8 +732,9 @@ class Readability implements LoggerAwareInterface
|
||||
|
||||
for ($nodeIndex = 0; ($node = $allElements->item($nodeIndex)); ++$nodeIndex) {
|
||||
$tagName = $node->tagName;
|
||||
|
||||
// Some well known site uses sections as paragraphs.
|
||||
if (strcasecmp($tagName, 'p') === 0 || strcasecmp($tagName, 'td') === 0 || strcasecmp($tagName, 'section') === 0) {
|
||||
if (strcasecmp($tagName, 'p') === 0 || strcasecmp($tagName, 'td') === 0 || strcasecmp($tagName, 'pre') === 0 || strcasecmp($tagName, 'section') === 0) {
|
||||
$nodesToScore[] = $node;
|
||||
}
|
||||
|
||||
@@ -736,6 +758,11 @@ class Readability implements LoggerAwareInterface
|
||||
for ($i = 0, $il = $node->childNodes->length; $i < $il; ++$i) {
|
||||
$childNode = $node->childNodes->item($i);
|
||||
|
||||
// it looks like sometimes the loop is going too far and we are retrieving a non-existant child
|
||||
if (null === $childNode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// executable tags (<?php or <?xml) warning
|
||||
if (is_object($childNode) && get_class($childNode) === 'DOMProcessingInstruction') {
|
||||
$childNode->parentNode->removeChild($childNode);
|
||||
@@ -743,8 +770,7 @@ class Readability implements LoggerAwareInterface
|
||||
continue;
|
||||
}
|
||||
|
||||
// XML_TEXT_NODE
|
||||
if ($childNode->nodeType == 3) {
|
||||
if ($childNode->nodeType === XML_TEXT_NODE) {
|
||||
$p = $this->dom->createElement('p');
|
||||
$p->innerHTML = $childNode->nodeValue;
|
||||
$p->setAttribute('data-readability-styled', 'true');
|
||||
@@ -770,7 +796,7 @@ class Readability implements LoggerAwareInterface
|
||||
continue;
|
||||
}
|
||||
|
||||
$grandParentNode = ($parentNode->parentNode instanceof \DOMElement) ? $parentNode->parentNode : null;
|
||||
$grandParentNode = $parentNode->parentNode instanceof \DOMElement ? $parentNode->parentNode : null;
|
||||
$innerText = $this->getInnerText($nodesToScore[$pt]);
|
||||
|
||||
// If this paragraph is less than MIN_PARAGRAPH_LENGTH (default:20) characters, don't even count it.
|
||||
@@ -953,7 +979,7 @@ class Readability implements LoggerAwareInterface
|
||||
$contentBonus = 0;
|
||||
|
||||
// Give a bonus if sibling nodes and top candidates have the same classname.
|
||||
if ($siblingNode->nodeType === XML_ELEMENT_NODE && $siblingNode->getAttribute('class') == $topCandidate->getAttribute('class') && $topCandidate->getAttribute('class') != '') {
|
||||
if ($siblingNode->nodeType === XML_ELEMENT_NODE && $siblingNode->getAttribute('class') === $topCandidate->getAttribute('class') && $topCandidate->getAttribute('class') !== '') {
|
||||
$contentBonus += ((int) $topCandidate->getAttribute('readability')) * 0.2;
|
||||
}
|
||||
|
||||
@@ -1051,7 +1077,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInnerText(\DOMElement $e = null, $normalizeSpaces = true, $flattenLines = false)
|
||||
public function getInnerText($e, $normalizeSpaces = true, $flattenLines = false)
|
||||
{
|
||||
if (null === $e || !isset($e->textContent) || $e->textContent === '') {
|
||||
return '';
|
||||
@@ -1073,7 +1099,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @param \DOMElement $e
|
||||
*/
|
||||
public function cleanStyles(\DOMElement $e)
|
||||
public function cleanStyles($e)
|
||||
{
|
||||
if (!is_object($e)) {
|
||||
return;
|
||||
@@ -1121,7 +1147,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getLinkDensity(\DOMElement $e, $excludeExternal = false)
|
||||
public function getLinkDensity($e, $excludeExternal = false)
|
||||
{
|
||||
$links = $e->getElementsByTagName('a');
|
||||
$textLength = mb_strlen($this->getInnerText($e, true, true));
|
||||
@@ -1150,7 +1176,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function weightAttribute(\DOMElement $element, $attribute)
|
||||
protected function weightAttribute($element, $attribute)
|
||||
{
|
||||
if (!$element->hasAttribute($attribute)) {
|
||||
return 0;
|
||||
@@ -1160,7 +1186,7 @@ class Readability implements LoggerAwareInterface
|
||||
// $attributeValue = trim($element->getAttribute('class')." ".$element->getAttribute('id'));
|
||||
$attributeValue = trim($element->getAttribute($attribute));
|
||||
|
||||
if ($attributeValue != '') {
|
||||
if ($attributeValue !== '') {
|
||||
if (preg_match($this->regexps['negative'], $attributeValue)) {
|
||||
$weight -= 25;
|
||||
}
|
||||
@@ -1185,7 +1211,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getWeight(\DOMElement $e)
|
||||
public function getWeight($e)
|
||||
{
|
||||
if (!$this->flagIsActive(self::FLAG_WEIGHT_ATTRIBUTES)) {
|
||||
return 0;
|
||||
@@ -1205,7 +1231,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @param \DOMElement $node
|
||||
*/
|
||||
public function killBreaks(\DOMElement $node)
|
||||
public function killBreaks($node)
|
||||
{
|
||||
$html = $node->innerHTML;
|
||||
$html = preg_replace($this->regexps['killBreaks'], '<br />', $html);
|
||||
@@ -1221,7 +1247,7 @@ class Readability implements LoggerAwareInterface
|
||||
* @param \DOMElement $e
|
||||
* @param string $tag
|
||||
*/
|
||||
public function clean(\DOMElement $e, $tag)
|
||||
public function clean($e, $tag)
|
||||
{
|
||||
$currentItem = null;
|
||||
$targetList = $e->getElementsByTagName($tag);
|
||||
@@ -1257,7 +1283,7 @@ class Readability implements LoggerAwareInterface
|
||||
* @param \DOMElement $e
|
||||
* @param string $tag
|
||||
*/
|
||||
public function cleanConditionally(\DOMElement $e, $tag)
|
||||
public function cleanConditionally($e, $tag)
|
||||
{
|
||||
if (!$this->flagIsActive(self::FLAG_CLEAN_CONDITIONALLY)) {
|
||||
return;
|
||||
@@ -1313,7 +1339,7 @@ class Readability implements LoggerAwareInterface
|
||||
$toRemove = false;
|
||||
|
||||
if ($this->lightClean) {
|
||||
if ($li > $p && $tag != 'ul' && $tag != 'ol') {
|
||||
if ($li > $p && $tag !== 'ul' && $tag !== 'ol') {
|
||||
$this->logger->debug(' too many <li> elements, and parent is not <ul> or <ol>');
|
||||
$toRemove = true;
|
||||
} elseif ($input > floor($p / 3)) {
|
||||
@@ -1336,7 +1362,7 @@ class Readability implements LoggerAwareInterface
|
||||
if ($img > $p) {
|
||||
$this->logger->debug(' more image elements than paragraph elements');
|
||||
$toRemove = true;
|
||||
} elseif ($li > $p && $tag != 'ul' && $tag != 'ol') {
|
||||
} elseif ($li > $p && $tag !== 'ul' && $tag !== 'ol') {
|
||||
$this->logger->debug(' too many <li> elements, and parent is not <ul> or <ol>');
|
||||
$toRemove = true;
|
||||
} elseif ($input > floor($p / 3)) {
|
||||
@@ -1351,7 +1377,7 @@ class Readability implements LoggerAwareInterface
|
||||
} elseif ($weight >= 25 && $linkDensity > 0.5) {
|
||||
$this->logger->debug(' weight above 25 but link density is ' . sprintf('%.2f', $linkDensity) . ' > 0.5');
|
||||
$toRemove = true;
|
||||
} elseif (($embedCount == 1 && $contentLength < 75) || $embedCount > 1) {
|
||||
} elseif (($embedCount === 1 && $contentLength < 75) || $embedCount > 1) {
|
||||
$this->logger->debug(' 1 embed and content length smaller than 75 chars, or more than one embed');
|
||||
$toRemove = true;
|
||||
}
|
||||
@@ -1370,7 +1396,7 @@ class Readability implements LoggerAwareInterface
|
||||
*
|
||||
* @param \DOMElement $e
|
||||
*/
|
||||
public function cleanHeaders(\DOMElement $e)
|
||||
public function cleanHeaders($e)
|
||||
{
|
||||
for ($headerIndex = 1; $headerIndex < 3; ++$headerIndex) {
|
||||
$headers = $e->getElementsByTagName('h' . $headerIndex);
|
||||
|
||||
+35
-13
@@ -2,9 +2,9 @@
|
||||
|
||||
namespace Tests\Readability;
|
||||
|
||||
use Readability\Readability;
|
||||
use Monolog\Logger;
|
||||
use Monolog\Handler\TestHandler;
|
||||
use Monolog\Logger;
|
||||
use Readability\Readability;
|
||||
|
||||
class ReadabilityTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
@@ -22,40 +22,47 @@ class ReadabilityTest extends \PHPUnit_Framework_TestCase
|
||||
return $readability;
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension tidy
|
||||
*/
|
||||
public function testConstructDefault()
|
||||
{
|
||||
$readability = $this->getReadability('');
|
||||
|
||||
$this->assertNull($readability->url);
|
||||
$this->assertInstanceOf('DomDocument', $readability->dom);
|
||||
}
|
||||
|
||||
/**
|
||||
* @requires extension tidy
|
||||
*/
|
||||
public function testConstructSimple()
|
||||
{
|
||||
$readability = $this->getReadability('<html/>', 'http://0.0.0.0');
|
||||
$readability->init();
|
||||
|
||||
$this->assertEquals('http://0.0.0.0', $readability->url);
|
||||
$this->assertInstanceOf('DomDocument', $readability->dom);
|
||||
$this->assertEquals('<html/>', $readability->original_html);
|
||||
$this->assertTrue($readability->tidied);
|
||||
|
||||
$this->assertTrue($this->logHandler->hasDebugThatContains('Parsing URL: http://0.0.0.0'));
|
||||
$this->assertTrue($this->logHandler->hasDebugThatContains('Tidying document'));
|
||||
$this->assertTrue($this->logHandler->hasDebugThatContains('Light clean enabled.'));
|
||||
}
|
||||
|
||||
public function testConstructDefaultWithoutTidy()
|
||||
{
|
||||
$readability = $this->getReadability('', null, 'libxml', false);
|
||||
$readability->init();
|
||||
|
||||
$this->assertNull($readability->url);
|
||||
$this->assertEquals('', $readability->original_html);
|
||||
$this->assertFalse($readability->tidied);
|
||||
|
||||
$this->assertTrue($this->logHandler->hasDebugThatContains('Parsing URL: '));
|
||||
$this->assertFalse($this->logHandler->hasDebugThatContains('Tidying document'));
|
||||
$this->assertTrue($this->logHandler->hasDebugThatContains('Light clean enabled.'));
|
||||
$this->assertInstanceOf('DomDocument', $readability->dom);
|
||||
}
|
||||
|
||||
public function testConstructSimpleWithoutTidy()
|
||||
{
|
||||
$readability = $this->getReadability('<html/>', 'http://0.0.0.0', 'libxml', false);
|
||||
$readability->init();
|
||||
|
||||
$this->assertEquals('http://0.0.0.0', $readability->url);
|
||||
$this->assertInstanceOf('DomDocument', $readability->dom);
|
||||
$this->assertEquals('<html/>', $readability->original_html);
|
||||
$this->assertFalse($readability->tidied);
|
||||
}
|
||||
@@ -376,7 +383,7 @@ class ReadabilityTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* This should generate an Exception "DOMElement::setAttribute(): ID post-60 already defined"
|
||||
* This should generate an Exception "DOMElement::setAttribute(): ID post-60 already defined".
|
||||
*/
|
||||
public function testAppendIdAlreadyHere()
|
||||
{
|
||||
@@ -447,6 +454,8 @@ class ReadabilityTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
public function testPreFilters()
|
||||
{
|
||||
$this->markTestSkipped('Won\'t work until loadHtml() is moved in init() instead of __construct()');
|
||||
|
||||
$readability = $this->getReadability('<div>' . str_repeat('<p>This <b>is</b> the awesome and WONDERFUL content :)</p>', 7) . '</div>', 'http://0.0.0.0');
|
||||
$readability->addPreFilter('!<b[^>]*>(.*?)</b>!is', '');
|
||||
|
||||
@@ -455,4 +464,17 @@ class ReadabilityTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertTrue($res);
|
||||
$this->assertContains('This the awesome and WONDERFUL content :)', $readability->getContent()->innerHTML);
|
||||
}
|
||||
|
||||
public function testChildNodeGoneNull()
|
||||
{
|
||||
// from http://www.ayyaantuu.net/ethiopia-targets-opposition-lawmakers/
|
||||
$html = file_get_contents('tests/fixtures/childNodeGoesNull.html');
|
||||
|
||||
$readability = $this->getReadability($html, 'http://0.0.0.0');
|
||||
$readability->debug = true;
|
||||
$readability->convertLinksToFootnotes = true;
|
||||
$res = $readability->init();
|
||||
|
||||
$this->assertTrue($res);
|
||||
}
|
||||
}
|
||||
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
<div id="main-sidebar-container">
|
||||
|
||||
<!-- #main Starts -->
|
||||
<section id="main">
|
||||
<?php if (function_exists ('adinserter')) echo adinserter (1); ?><article class="post-23842 post type-post status-publish format-standard hentry category-ethiopia">
|
||||
<header>
|
||||
<h1 class="title entry-title">Ethiopia targets opposition who met with European lawmakers</h1> </header>
|
||||
<div class="post-meta"><span class="Small"><abbr class="date time published updated" title="2017-01-09T15:25:17-0500">January 9, 2017</abbr> <span class="Small">in</span> <span class="categories"><a href="http://www.ayyaantuu.net/category/horn-of-africa/ethiopia/" title="View all items in Ethiopia">Ethiopia</a></span> </div>
|
||||
<section class="entry">
|
||||
<div id="fb-root"></div>
|
||||
<p><strong>Ethiopia targets opposition who met with European lawmakers</strong></p>
|
||||
<p><span class="dateline"><img class="alignleft wp-image-22789 size-full" src="http://www.ayyaantuu.net/wp-content/uploads/2016/12/Ana-Gomes-Merera-Gudina.jpg" alt="Ethiopia targets opposition who met with European lawmakers" width="300" height="160" srcset="http://www.ayyaantuu.net/wp-content/uploads/2016/12/Ana-Gomes-Merera-Gudina.jpg 300w, http://www.ayyaantuu.net/wp-content/uploads/2016/12/Ana-Gomes-Merera-Gudina-200x107.jpg 200w" sizes="(max-width: 300px) 100vw, 300px" />ADDIS ABABA (<a href="http://www.foxnews.com/world/2017/01/09/ethiopia-targets-opposition-who-met-with-european-lawmakers.html">Fox News</a>) – </span>Ethiopia says it will not release a leading opposition figure detained under the country’s state of emergency after meeting with European lawmakers in Belgium.</p>
|
||||
<!-- WP QUADS Content Ad Plugin v. 1.3.9 -->
|
||||
<div class="quads-location quads-ad2" id="quads-ad2" style="float:left;margin:2px 2px 2px 0;">
|
||||
<script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
|
||||
<!-- Ad2016_12_14_3 -->
|
||||
<ins class="adsbygoogle"
|
||||
style="display:inline-block;width:336px;height:280px"
|
||||
data-ad-client="ca-pub-6953193962442323"
|
||||
data-ad-slot="4950645476"></ins>
|
||||
<script>
|
||||
(adsbygoogle = window.adsbygoogle || []).push({});
|
||||
</script>
|
||||
</div>
|
||||
|
||||
<p>Prime Minister Hailemariam Desalegn told reporters on Monday that Merara Gudina of the Oromo Federalist Congress party instead will face justice.</p>
|
||||
<p>The prime minister says “individuals in the European Parliament who are harboring anti-peace elements cannot save those who trespass the law of the country.”</p>
|
||||
<p>Merara is one of 22,000 people the prime minister says were detained under the state of emergency declared in October after widespread anti-government protests.</p>
|
||||
<p>Merara was arrested immediately after he returned from Belgium. He was accused of meeting with members of an armed Ethiopian opposition group in Brussels, an act banned under the emergency law.</p>
|
||||
|
||||
<div style="font-size:0px;height:0px;line-height:0px;margin:0;padding:0;clear:both"></div><aside class="mashsb-container mashsb-main "><div class="mashsb-box"><div class="mashsb-count mash-small" style="float:left;"><div class="counts mashsbcount">0</div><span class="mashsb-sharetext">SHARES</span></div><div class="mashsb-buttons"><a class="mashicon-facebook mash-small" href="http://www.facebook.com/sharer.php?u=http%3A%2F%2Fwww.ayyaantuu.net%2Fethiopia-targets-opposition-lawmakers%2F" target="_blank" rel="nofollow"><span class="icon"></span><span class="text">Share</span></a><a class="mashicon-twitter mash-small" href="https://twitter.com/intent/tweet?text=Ethiopia%20targets%20opposition%20who%20met%20with%20European%20lawmakers&url=http://www.ayyaantuu.net/?p=23842&via= ayyaantuu" target="_blank" rel="nofollow"><span class="icon"></span><span class="text">Tweet</span></a><div class="onoffswitch mash-small"></div><div class="secondary-shares" style="display:none;"><a class="mashicon-subscribe mash-small" href="#" target="_blank" rel="nofollow"><span class="icon"></span><span class="text">Subscribe</span></a><div class="onoffswitch2 mash-small" style="display:none;"></div></div></div>
|
||||
</div>
|
||||
<div style="clear:both;"></div><div class="mashsb-toggle-container"></div></aside>
|
||||
<!-- Share buttons by mashshare.net - Version: 3.3.6--> </section><!-- /.entry -->
|
||||
<div class="fix"></div>
|
||||
<aside id="connect">
|
||||
<h3>Subscribe</h3>
|
||||
|
||||
<div class="col-left">
|
||||
<p>Subscribe to our e-mail newsletter to receive updates.</p>
|
||||
|
||||
|
||||
|
||||
<div class="social">
|
||||
<a href="http://www.ayyaantuu.net/feed/" class="subscribe" title="RSS"></a>
|
||||
|
||||
<a target="_blank" href="https://twitter.com/ayyaantuu" class="twitter" title="Twitter"></a>
|
||||
|
||||
<a target="_blank" href="https://www.facebook.com/ayyaantuu.oromiyaa" class="facebook" title="Facebook"></a>
|
||||
|
||||
</div>
|
||||
|
||||
</div><!-- col-left -->
|
||||
|
||||
<div class="related-posts col-right">
|
||||
<h4>Related Posts:</h4>
|
||||
<div class="woo-sc-related-posts">
|
||||
<ul>
|
||||
<li class="post-id-23812">
|
||||
|
||||
<a href="http://www.ayyaantuu.net/country-new-african-millionaire/" title="Africa Business: The life of TPLF millionaire in Oromia/Ethiopia?" class="related-title"><span>Africa Business: The life of TPLF millionaire in Oromia/Ethiopia?</span></a>
|
||||
</li>
|
||||
<li class="post-id-23794">
|
||||
|
||||
<a href="http://www.ayyaantuu.net/ethiopian-girl-band-funding-axed-uk/" title="Ethiopian girl band Yegna’s funding axed by UK – BBC News" class="related-title"><span>Ethiopian girl band Yegna’s funding axed by UK – BBC News</span></a>
|
||||
</li>
|
||||
<li class="post-id-23783">
|
||||
|
||||
<a href="http://www.ayyaantuu.net/infrastructure-led-chinese-approach/" title="Ethiopia’s political ripple a big test for infrastructure-led Chinese approach" class="related-title"><span>Ethiopia’s political ripple a big test for infrastructure-led Chinese approach</span></a>
|
||||
</li>
|
||||
<li class="post-id-23766">
|
||||
|
||||
<a href="http://www.ayyaantuu.net/defense-witness-testimonials/" title="Defense Witness Testimonials on Yonatan Tesfaye’s Terrorism Charges" class="related-title"><span>Defense Witness Testimonials on Yonatan Tesfaye’s Terrorism Charges</span></a>
|
||||
</li>
|
||||
<li class="post-id-23745">
|
||||
|
||||
<a href="http://www.ayyaantuu.net/foreign-government-internet-shutdowns-soared-2016/" title="Foreign government internet shutdowns soared in 2016" class="related-title"><span>Foreign government internet shutdowns soared in 2016</span></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="fix"></div><!--/.fix-->
|
||||
</div><!--/.woo-sc-related-posts--> </div><!-- col-right -->
|
||||
|
||||
<div class="fix"></div>
|
||||
</aside>
|
||||
<div class="post-utility"></div>
|
||||
</article><!-- /.post -->
|
||||
<div class="post-entries">
|
||||
<div class="nav-prev fl"><a href="http://www.ayyaantuu.net/many-bombs-united-states-dropped-2016/" rel="prev"><i class="fa fa-angle-left"></i> How Many Bombs the United States Dropped in 2016?</a></div>
|
||||
<div class="nav-next fr"><a href="http://www.ayyaantuu.net/rockefeller-conspiracy-one-world-order/" rel="next">David Rockefeller Says Conspiracy About ‘One World Order’ Is True <i class="fa fa-angle-right"></i></a></div>
|
||||
<div class="fix"></div>
|
||||
</div>
|
||||
|
||||
<?php if (function_exists ('adinserter')) echo adinserter (1); ?><div id="comments"> <h3 id="comments-title">One Response to <em>Ethiopia targets opposition who met with European lawmakers</em></h3>
|
||||
<ol class="commentlist">
|
||||
|
||||
<li id="comment-30772" class="comment even thread-even depth-1">
|
||||
|
||||
<div id="li-comment-30772" class="comment-container">
|
||||
|
||||
<div class="avatar"></div>
|
||||
|
||||
<div class="comment-head">
|
||||
|
||||
<span class="name">Addis Zemen</span>
|
||||
<span class="date">January 9, 2017 at 5:57 pm</span>
|
||||
<span class="perma"><a href="http://www.ayyaantuu.net/ethiopia-targets-opposition-lawmakers/#comment-30772" title="Direct link to this comment">#</a></span>
|
||||
<span class="edit"></span>
|
||||
|
||||
</div><!-- /.comment-head -->
|
||||
|
||||
<div class="comment-entry">
|
||||
|
||||
<p>10,000 people that were areested in Oromia got released. When the people were arrested it was under the assumption “Violence broke out during an Oromo religious festival, and in some instances foreigners seem to have been targeted. ”</p>
|
||||
<p>But now many prosecutors agree Violence was not the case. The people at the Erecha celebration thought aliens invaded their country. They thought the foreigners were aliens from another planet.<br />
|
||||
Close to a thousand threw themselves of a cliff just because they saw a helicopter flying near them. Many are paralized hundreds died. Now the injured are trying to blame the helicopter pilot for their injuries by saying the pilot caused their injuries by scaring them, flying like an alien abductor UFO would . After the prosecutor agreed it was an accident or suicide that caused the deaths of hundreds of people at the Erecha celebration, the suspected 10,000 prisoners got released. The prosecutors are blaming those that spoke with the European parliament for spreading false information about what really happened at the Erecha celebration.</p>
|
||||
|
||||
|
||||
<div class="reply">
|
||||
<a rel='nofollow' class='comment-reply-link' href='http://www.ayyaantuu.net/ethiopia-targets-opposition-lawmakers/?replytocom=30772#respond' onclick='return addComment.moveForm( "comment-30772", "30772", "respond", "23842" )' aria-label='Reply to Addis Zemen'>Reply</a> </div><!-- /.reply -->
|
||||
|
||||
</div><!-- /comment-entry -->
|
||||
|
||||
</div><!-- /.comment-container -->
|
||||
|
||||
</li><!-- #comment-## -->
|
||||
</ol>
|
||||
</div> <div id="respond" class="comment-respond">
|
||||
<h3 id="reply-title" class="comment-reply-title">Leave a Reply <small><a rel="nofollow" id="cancel-comment-reply-link" href="/ethiopia-targets-opposition-lawmakers/#respond" style="display:none;">Click here to cancel reply.</a></small></h3> <form action="http://www.ayyaantuu.net/wp-comments-post.php" method="post" id="commentform" class="comment-form">
|
||||
<p class="comment-form-comment"><label class="hide" for="comment">Comment</label> <textarea tabindex="4" id="comment" name="comment" cols="50" rows="10" maxlength="65525" aria-required="true" required="required"></textarea></p><p class="comment-form-author"><input id="author" name="author" type="text" class="txt" tabindex="1" value="" size="30" aria-required='true' /><label for="author">Name <span class="required">(required)</span></label> </p>
|
||||
<p class="comment-form-email"><input id="email" name="email" type="text" class="txt" tabindex="2" value="" size="30" aria-required='true' /><label for="email">Email (will not be published) <span class="required">(required)</span></label> </p>
|
||||
<p class="comment-form-url"><input id="url" name="url" type="text" class="txt" tabindex="3" value="" size="30" /><label for="url">Website</label></p>
|
||||
<p class="form-submit"><input name="submit" type="submit" id="submit" class="submit" value="Submit Comment" /> <input type='hidden' name='comment_post_ID' value='23842' id='comment_post_ID' />
|
||||
<input type='hidden' name='comment_parent' id='comment_parent' value='0' />
|
||||
</p><p style="display: none;"><input type="hidden" id="akismet_comment_nonce" name="akismet_comment_nonce" value="39bacbf69e" /></p><p style="display: none;"><input type="hidden" id="ak_js" name="ak_js" value="66"/></p> </form>
|
||||
</div><!-- #respond -->
|
||||
|
||||
</section><!-- /#main -->
|
||||
Reference in New Issue
Block a user