Compare commits

..
10 Commits
Author SHA1 Message Date
Jeremy BenoistandGitHub ade850534c Merge pull request #18 from j0k3r/tool
Don’t be too agressive
2016-10-21 07:24:11 +02:00
Jeremy Benoist d97bece7c5 Don’t be too agressive
Some links got a “tooltip-link” and shouldn’t be removed by php-readability because they are usefull to the content
2016-10-20 23:40:52 +02:00
Jeremy BenoistandGitHub 47ce4fb7f9 Merge pull request #16 from j0k3r/info
“info” is too agressive in unlikelyCandidates
2016-10-03 09:13:35 +02:00
Jeremy Benoist 3de4e918b4 Convert header & section to p
And took `pre` element in score
2016-10-02 14:55:52 +02:00
Jeremy Benoist 5182d6cb11 “info” is too agressive in unlikelyCandidates
Some contents have a `infocontent` node (ot sth different) and they are real content.
Using only `info` as regex is too agressive and remove legitimate content.
Matching the whole word `info` (or `infos`) should be a better choice
2016-10-02 14:49:43 +02:00
Jeremy BenoistandGitHub fb9810a827 Merge pull request #15 from j0k3r/cs
Enable php-cs-fixer
2016-06-24 09:36:50 +02:00
Jeremy Benoist 22aa4c3b31 Fix composer & TLS 2016-06-23 07:44:54 +02:00
Jeremy Benoist 2ef400bf73 Enable php-cs-fixer 2016-06-23 07:28:10 +02:00
Jeremy Benoist dec4514c00 Merge pull request #14 from j0k3r/revert-bc
Revert BC changes
2016-03-01 15:14:36 +01:00
Jeremy Benoist 00f622e9b7 Revert BC changes
- avoid method signature update
- revert moving logic out of the constructor
2016-03-01 15:07:32 +01:00
8 changed files with 167 additions and 108 deletions
+1
View File
@@ -3,6 +3,7 @@
/.gitignore export-ignore /.gitignore export-ignore
/.scrutinizer.yml export-ignore /.scrutinizer.yml export-ignore
/.travis.yml export-ignore /.travis.yml export-ignore
/.php_cs export-ignore
/README.md export-ignore /README.md export-ignore
/phpunit.xml.dist export-ignore /phpunit.xml.dist export-ignore
/tests export-ignore /tests export-ignore
+1
View File
@@ -1,3 +1,4 @@
vendor/ vendor/
coverage/ coverage/
composer.lock composer.lock
.php_cs.cache
+20
View File
@@ -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'))
)
;
+10 -4
View File
@@ -10,6 +10,9 @@ php:
- hhvm - hhvm
matrix: matrix:
include:
- php: 7.0
env: CS_FIXER=run
fast_finish: true fast_finish: true
allow_failures: allow_failures:
- php: hhvm - php: hhvm
@@ -23,20 +26,23 @@ cache:
- vendor - vendor
- $HOME/.composer/cache - $HOME/.composer/cache
install: before_install:
- composer self-update
before_script:
- if [ -n "$GH_TOKEN" ]; then composer config github-oauth.github.com ${GH_TOKEN}; fi; - 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 # 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/ # 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 -- disable-tls true; fi;
- if [[ $TRAVIS_PHP_VERSION = 5.3.3 ]]; then composer config -g -- secure-http false; fi; - if [[ $TRAVIS_PHP_VERSION = 5.3.3 ]]; then composer config -g -- secure-http false; fi;
install:
- composer self-update
before_script:
- composer install --prefer-dist --no-interaction - composer install --prefer-dist --no-interaction
script: script:
- mkdir -p build/logs - mkdir -p build/logs
- phpunit -v --coverage-clover build/logs/clover.xml - 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: after_script:
- php vendor/bin/coveralls -v - php vendor/bin/coveralls -v
+2 -1
View File
@@ -28,7 +28,8 @@
"monolog/monolog": "^1.13.1" "monolog/monolog": "^1.13.1"
}, },
"require-dev": { "require-dev": {
"satooshi/php-coveralls": "~0.6" "satooshi/php-coveralls": "~0.6",
"friendsofphp/php-cs-fixer": "*"
}, },
"autoload": { "autoload": {
"psr-4": { "Readability\\": "src/" } "psr-4": { "Readability\\": "src/" }
+3 -3
View File
@@ -45,14 +45,14 @@ class JSLikeHTMLElement extends \DOMElement
*/ */
public function __set($name, $value) public function __set($name, $value)
{ {
if ($name == 'innerHTML') { if ($name === 'innerHTML') {
// first, empty the element // first, empty the element
for ($x = $this->childNodes->length - 1; $x >= 0; --$x) { for ($x = $this->childNodes->length - 1; $x >= 0; --$x) {
$this->removeChild($this->childNodes->item($x)); $this->removeChild($this->childNodes->item($x));
} }
// $value holds our new inner HTML // $value holds our new inner HTML
if ($value != '') { if ($value !== '') {
$f = $this->ownerDocument->createDocumentFragment(); $f = $this->ownerDocument->createDocumentFragment();
// appendXML() expects well-formed markup (XHTML) // appendXML() expects well-formed markup (XHTML)
@@ -102,7 +102,7 @@ class JSLikeHTMLElement extends \DOMElement
*/ */
public function __get($name) public function __get($name)
{ {
if ($name == 'innerHTML') { if ($name === 'innerHTML') {
$inner = ''; $inner = '';
foreach ($this->childNodes as $child) { foreach ($this->childNodes as $child) {
+57 -36
View File
@@ -66,7 +66,7 @@ class Readability implements LoggerAwareInterface
public $tidied = false; public $tidied = false;
// article domain regexp for calibration // article domain regexp for calibration
protected $domainRegExp = null; protected $domainRegExp = null;
protected $body = null; // protected $body = null;
// Cache the body HTML in case we need to re-use it later // Cache the body HTML in case we need to re-use it later
protected $bodyCache = null; protected $bodyCache = null;
// 1 | 2 | 4; // Start with all processing flags set. // 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. * Defined up here so we don't instantiate them repeatedly in loops.
*/ */
public $regexps = array( 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', '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', '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', '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]|&nbsp;?)*)+/', 'killBreaks' => '/(<br\s*\/?>([ \r\n\s]|&nbsp;?)*)+/',
'media' => '!//(?:[^\.\?/]+\.)?(?:youtu(?:be)?|soundcloud|dailymotion|vimeo|pornhub|xvideos|twitvid|rutube|viddler)\.(?:com|be|org|net)/!i', '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', '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 string (optional) Which parser to use for turning raw HTML into a DOMDocument
* @param bool (optional) Use tidy * @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->url = $url;
$this->html = $html; $this->html = $html;
$this->parser = $parser; $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->logger = new NullLogger();
$this->loadHtml();
} }
public function setLogger(LoggerInterface $logger) public function setLogger(LoggerInterface $logger)
@@ -235,6 +236,8 @@ class Readability implements LoggerAwareInterface
* Load HTML in a DOMDocument. * Load HTML in a DOMDocument.
* Apply Pre filters * Apply Pre filters
* Cleanup HTML using Tidy (or not). * Cleanup HTML using Tidy (or not).
*
* @todo This should be called in init() instead of from __construct
*/ */
private function loadHtml() private function loadHtml()
{ {
@@ -266,7 +269,6 @@ class Readability implements LoggerAwareInterface
* Use tidy (if it exists). * Use tidy (if it exists).
* This fixes problems with some sites which would otherwise trouble DOMDocument's HTML parsing. * 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. * Although sometimes it makes matters worse, which is why there is an option to disable it.
*
*/ */
if ($this->useTidy) { if ($this->useTidy) {
$this->logger->debug('Tidying document'); $this->logger->debug('Tidying document');
@@ -282,7 +284,7 @@ class Readability implements LoggerAwareInterface
$this->html = mb_convert_encoding($this->html, 'HTML-ENTITIES', 'UTF-8'); $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); libxml_use_internal_errors(true);
$this->dom = new \DOMDocument(); $this->dom = new \DOMDocument();
@@ -314,8 +316,6 @@ class Readability implements LoggerAwareInterface
*/ */
public function init() public function init()
{ {
$this->loadHtml();
if (!isset($this->dom->documentElement)) { if (!isset($this->dom->documentElement)) {
return false; return false;
} }
@@ -325,7 +325,7 @@ class Readability implements LoggerAwareInterface
$bodyElems = $this->dom->getElementsByTagName('body'); $bodyElems = $this->dom->getElementsByTagName('body');
// WTF multiple body nodes? // WTF multiple body nodes?
if ($this->bodyCache == null) { if ($this->bodyCache === null) {
$this->bodyCache = ''; $this->bodyCache = '';
foreach ($bodyElems as $bodyNode) { foreach ($bodyElems as $bodyNode) {
$this->bodyCache .= trim($bodyNode->innerHTML); $this->bodyCache .= trim($bodyNode->innerHTML);
@@ -372,12 +372,33 @@ class Readability implements LoggerAwareInterface
return $this->success; 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. * Run any post-process modifications to article content as necessary.
* *
* @param \DOMElement $articleContent * @param \DOMElement $articleContent
*/ */
public function postProcessContent(\DOMElement $articleContent) public function postProcessContent($articleContent)
{ {
if ($this->convertLinksToFootnotes && !preg_match('/\bwiki/', $this->url)) { if ($this->convertLinksToFootnotes && !preg_match('/\bwiki/', $this->url)) {
$this->addFootnotes($articleContent); $this->addFootnotes($articleContent);
@@ -410,7 +431,7 @@ class Readability implements LoggerAwareInterface
} }
} elseif (mb_strlen($curTitle) > 150 || mb_strlen($curTitle) < 15) { } elseif (mb_strlen($curTitle) > 150 || mb_strlen($curTitle) < 15) {
$hOnes = $this->dom->getElementsByTagName('h1'); $hOnes = $this->dom->getElementsByTagName('h1');
if ($hOnes->length == 1) { if ($hOnes->length === 1) {
$curTitle = $this->getInnerText($hOnes->item(0)); $curTitle = $this->getInnerText($hOnes->item(0));
} }
} }
@@ -462,7 +483,7 @@ class Readability implements LoggerAwareInterface
* *
* @param \DOMElement $articleContent * @param \DOMElement $articleContent
*/ */
public function addFootnotes(\DOMElement $articleContent) public function addFootnotes($articleContent)
{ {
$footnotesWrapper = $this->dom->createElement('footer'); $footnotesWrapper = $this->dom->createElement('footer');
$footnotesWrapper->setAttribute('class', 'readability-footnotes'); $footnotesWrapper->setAttribute('class', 'readability-footnotes');
@@ -505,7 +526,7 @@ class Readability implements LoggerAwareInterface
$articleLink->setAttribute('style', 'color: inherit; text-decoration: none;'); $articleLink->setAttribute('style', 'color: inherit; text-decoration: none;');
$articleLink->setAttribute('name', 'readabilityLink-' . $linkCount); $articleLink->setAttribute('name', 'readabilityLink-' . $linkCount);
$footnote->innerHTML = '<small><sup><a href="#readabilityLink-' . $linkCount . '" title="Jump to Link in Article">^</a></sup></small> '; $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); $footnoteLink->setAttribute('name', 'readabilityFootnoteLink-' . $linkCount);
$footnote->appendChild($footnoteLink); $footnote->appendChild($footnoteLink);
@@ -526,7 +547,7 @@ class Readability implements LoggerAwareInterface
* *
* @param \DOMElement $articleContent * @param \DOMElement $articleContent
*/ */
public function prepArticle(\DOMElement $articleContent) public function prepArticle($articleContent)
{ {
$this->logger->debug($this->lightClean ? 'Light clean enabled.' : 'Standard clean enabled.'); $this->logger->debug($this->lightClean ? 'Light clean enabled.' : 'Standard clean enabled.');
@@ -567,7 +588,7 @@ class Readability implements LoggerAwareInterface
* already have a header. * already have a header.
*/ */
$h2s = $articleContent->getElementsByTagName('h2'); $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'); $this->clean($articleContent, 'h2');
} }
@@ -623,7 +644,7 @@ class Readability implements LoggerAwareInterface
* *
* @param \DOMElement $node * @param \DOMElement $node
*/ */
protected function initializeNode(\DOMElement $node) protected function initializeNode($node)
{ {
if (!isset($node->tagName)) { if (!isset($node->tagName)) {
return; return;
@@ -694,7 +715,7 @@ class Readability implements LoggerAwareInterface
* *
* @return \DOMElement|bool * @return \DOMElement|bool
*/ */
protected function grabArticle(\DOMElement $page = null) protected function grabArticle($page = null)
{ {
if (!$page) { if (!$page) {
$page = $this->dom; $page = $this->dom;
@@ -711,8 +732,9 @@ class Readability implements LoggerAwareInterface
for ($nodeIndex = 0; ($node = $allElements->item($nodeIndex)); ++$nodeIndex) { for ($nodeIndex = 0; ($node = $allElements->item($nodeIndex)); ++$nodeIndex) {
$tagName = $node->tagName; $tagName = $node->tagName;
// Some well known site uses sections as paragraphs. // 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; $nodesToScore[] = $node;
} }
@@ -743,8 +765,7 @@ class Readability implements LoggerAwareInterface
continue; continue;
} }
// XML_TEXT_NODE if ($childNode->nodeType === XML_TEXT_NODE) {
if ($childNode->nodeType == 3) {
$p = $this->dom->createElement('p'); $p = $this->dom->createElement('p');
$p->innerHTML = $childNode->nodeValue; $p->innerHTML = $childNode->nodeValue;
$p->setAttribute('data-readability-styled', 'true'); $p->setAttribute('data-readability-styled', 'true');
@@ -770,7 +791,7 @@ class Readability implements LoggerAwareInterface
continue; continue;
} }
$grandParentNode = ($parentNode->parentNode instanceof \DOMElement) ? $parentNode->parentNode : null; $grandParentNode = $parentNode->parentNode instanceof \DOMElement ? $parentNode->parentNode : null;
$innerText = $this->getInnerText($nodesToScore[$pt]); $innerText = $this->getInnerText($nodesToScore[$pt]);
// If this paragraph is less than MIN_PARAGRAPH_LENGTH (default:20) characters, don't even count it. // If this paragraph is less than MIN_PARAGRAPH_LENGTH (default:20) characters, don't even count it.
@@ -953,7 +974,7 @@ class Readability implements LoggerAwareInterface
$contentBonus = 0; $contentBonus = 0;
// Give a bonus if sibling nodes and top candidates have the same classname. // 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; $contentBonus += ((int) $topCandidate->getAttribute('readability')) * 0.2;
} }
@@ -1051,7 +1072,7 @@ class Readability implements LoggerAwareInterface
* *
* @return string * @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 === '') { if (null === $e || !isset($e->textContent) || $e->textContent === '') {
return ''; return '';
@@ -1073,7 +1094,7 @@ class Readability implements LoggerAwareInterface
* *
* @param \DOMElement $e * @param \DOMElement $e
*/ */
public function cleanStyles(\DOMElement $e) public function cleanStyles($e)
{ {
if (!is_object($e)) { if (!is_object($e)) {
return; return;
@@ -1121,7 +1142,7 @@ class Readability implements LoggerAwareInterface
* *
* @return int * @return int
*/ */
public function getLinkDensity(\DOMElement $e, $excludeExternal = false) public function getLinkDensity($e, $excludeExternal = false)
{ {
$links = $e->getElementsByTagName('a'); $links = $e->getElementsByTagName('a');
$textLength = mb_strlen($this->getInnerText($e, true, true)); $textLength = mb_strlen($this->getInnerText($e, true, true));
@@ -1150,7 +1171,7 @@ class Readability implements LoggerAwareInterface
* *
* @return int * @return int
*/ */
protected function weightAttribute(\DOMElement $element, $attribute) protected function weightAttribute($element, $attribute)
{ {
if (!$element->hasAttribute($attribute)) { if (!$element->hasAttribute($attribute)) {
return 0; return 0;
@@ -1160,7 +1181,7 @@ class Readability implements LoggerAwareInterface
// $attributeValue = trim($element->getAttribute('class')." ".$element->getAttribute('id')); // $attributeValue = trim($element->getAttribute('class')." ".$element->getAttribute('id'));
$attributeValue = trim($element->getAttribute($attribute)); $attributeValue = trim($element->getAttribute($attribute));
if ($attributeValue != '') { if ($attributeValue !== '') {
if (preg_match($this->regexps['negative'], $attributeValue)) { if (preg_match($this->regexps['negative'], $attributeValue)) {
$weight -= 25; $weight -= 25;
} }
@@ -1185,7 +1206,7 @@ class Readability implements LoggerAwareInterface
* *
* @return int * @return int
*/ */
public function getWeight(\DOMElement $e) public function getWeight($e)
{ {
if (!$this->flagIsActive(self::FLAG_WEIGHT_ATTRIBUTES)) { if (!$this->flagIsActive(self::FLAG_WEIGHT_ATTRIBUTES)) {
return 0; return 0;
@@ -1205,7 +1226,7 @@ class Readability implements LoggerAwareInterface
* *
* @param \DOMElement $node * @param \DOMElement $node
*/ */
public function killBreaks(\DOMElement $node) public function killBreaks($node)
{ {
$html = $node->innerHTML; $html = $node->innerHTML;
$html = preg_replace($this->regexps['killBreaks'], '<br />', $html); $html = preg_replace($this->regexps['killBreaks'], '<br />', $html);
@@ -1221,7 +1242,7 @@ class Readability implements LoggerAwareInterface
* @param \DOMElement $e * @param \DOMElement $e
* @param string $tag * @param string $tag
*/ */
public function clean(\DOMElement $e, $tag) public function clean($e, $tag)
{ {
$currentItem = null; $currentItem = null;
$targetList = $e->getElementsByTagName($tag); $targetList = $e->getElementsByTagName($tag);
@@ -1257,7 +1278,7 @@ class Readability implements LoggerAwareInterface
* @param \DOMElement $e * @param \DOMElement $e
* @param string $tag * @param string $tag
*/ */
public function cleanConditionally(\DOMElement $e, $tag) public function cleanConditionally($e, $tag)
{ {
if (!$this->flagIsActive(self::FLAG_CLEAN_CONDITIONALLY)) { if (!$this->flagIsActive(self::FLAG_CLEAN_CONDITIONALLY)) {
return; return;
@@ -1313,7 +1334,7 @@ class Readability implements LoggerAwareInterface
$toRemove = false; $toRemove = false;
if ($this->lightClean) { 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>'); $this->logger->debug(' too many <li> elements, and parent is not <ul> or <ol>');
$toRemove = true; $toRemove = true;
} elseif ($input > floor($p / 3)) { } elseif ($input > floor($p / 3)) {
@@ -1336,7 +1357,7 @@ class Readability implements LoggerAwareInterface
if ($img > $p) { if ($img > $p) {
$this->logger->debug(' more image elements than paragraph elements'); $this->logger->debug(' more image elements than paragraph elements');
$toRemove = true; $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>'); $this->logger->debug(' too many <li> elements, and parent is not <ul> or <ol>');
$toRemove = true; $toRemove = true;
} elseif ($input > floor($p / 3)) { } elseif ($input > floor($p / 3)) {
@@ -1351,7 +1372,7 @@ class Readability implements LoggerAwareInterface
} elseif ($weight >= 25 && $linkDensity > 0.5) { } elseif ($weight >= 25 && $linkDensity > 0.5) {
$this->logger->debug(' weight above 25 but link density is ' . sprintf('%.2f', $linkDensity) . ' > 0.5'); $this->logger->debug(' weight above 25 but link density is ' . sprintf('%.2f', $linkDensity) . ' > 0.5');
$toRemove = true; $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'); $this->logger->debug(' 1 embed and content length smaller than 75 chars, or more than one embed');
$toRemove = true; $toRemove = true;
} }
@@ -1370,7 +1391,7 @@ class Readability implements LoggerAwareInterface
* *
* @param \DOMElement $e * @param \DOMElement $e
*/ */
public function cleanHeaders(\DOMElement $e) public function cleanHeaders($e)
{ {
for ($headerIndex = 1; $headerIndex < 3; ++$headerIndex) { for ($headerIndex = 1; $headerIndex < 3; ++$headerIndex) {
$headers = $e->getElementsByTagName('h' . $headerIndex); $headers = $e->getElementsByTagName('h' . $headerIndex);
+22 -13
View File
@@ -2,9 +2,9 @@
namespace Tests\Readability; namespace Tests\Readability;
use Readability\Readability;
use Monolog\Logger;
use Monolog\Handler\TestHandler; use Monolog\Handler\TestHandler;
use Monolog\Logger;
use Readability\Readability;
class ReadabilityTest extends \PHPUnit_Framework_TestCase class ReadabilityTest extends \PHPUnit_Framework_TestCase
{ {
@@ -22,40 +22,47 @@ class ReadabilityTest extends \PHPUnit_Framework_TestCase
return $readability; 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() public function testConstructSimple()
{ {
$readability = $this->getReadability('<html/>', 'http://0.0.0.0'); $readability = $this->getReadability('<html/>', 'http://0.0.0.0');
$readability->init();
$this->assertEquals('http://0.0.0.0', $readability->url); $this->assertEquals('http://0.0.0.0', $readability->url);
$this->assertInstanceOf('DomDocument', $readability->dom);
$this->assertEquals('<html/>', $readability->original_html); $this->assertEquals('<html/>', $readability->original_html);
$this->assertTrue($readability->tidied); $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() public function testConstructDefaultWithoutTidy()
{ {
$readability = $this->getReadability('', null, 'libxml', false); $readability = $this->getReadability('', null, 'libxml', false);
$readability->init();
$this->assertNull($readability->url); $this->assertNull($readability->url);
$this->assertEquals('', $readability->original_html); $this->assertEquals('', $readability->original_html);
$this->assertFalse($readability->tidied); $this->assertFalse($readability->tidied);
$this->assertTrue($this->logHandler->hasDebugThatContains('Parsing URL: ')); $this->assertInstanceOf('DomDocument', $readability->dom);
$this->assertFalse($this->logHandler->hasDebugThatContains('Tidying document'));
$this->assertTrue($this->logHandler->hasDebugThatContains('Light clean enabled.'));
} }
public function testConstructSimpleWithoutTidy() public function testConstructSimpleWithoutTidy()
{ {
$readability = $this->getReadability('<html/>', 'http://0.0.0.0', 'libxml', false); $readability = $this->getReadability('<html/>', 'http://0.0.0.0', 'libxml', false);
$readability->init();
$this->assertEquals('http://0.0.0.0', $readability->url); $this->assertEquals('http://0.0.0.0', $readability->url);
$this->assertInstanceOf('DomDocument', $readability->dom);
$this->assertEquals('<html/>', $readability->original_html); $this->assertEquals('<html/>', $readability->original_html);
$this->assertFalse($readability->tidied); $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() public function testAppendIdAlreadyHere()
{ {
@@ -447,6 +454,8 @@ class ReadabilityTest extends \PHPUnit_Framework_TestCase
public function testPreFilters() 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 = $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', ''); $readability->addPreFilter('!<b[^>]*>(.*?)</b>!is', '');