mirror of
https://github.com/j0k3r/php-readability.git
synced 2026-09-27 14:36:23 +00:00
Compare commits
10
Commits
2.0.8
...
a8b08d8cb2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8b08d8cb2 | ||
|
|
7db754debe | ||
|
|
18bfe842f8 | ||
|
|
63a0db9109 | ||
|
|
63d6ef1a47 | ||
|
|
116b6c839a | ||
|
|
a35f00ebb3 | ||
|
|
0f9f971556 | ||
|
|
fd1eaf61a7 | ||
|
|
3e40d78a67 |
@@ -0,0 +1,6 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "composer"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
@@ -30,6 +30,8 @@ return (new PhpCsFixer\Config())
|
|||||||
'modernize_strpos' => false,
|
'modernize_strpos' => false,
|
||||||
// Pulled in by @Symfony, we cannot add property types until we bump PHP to ≥ 7.4
|
// Pulled in by @Symfony, we cannot add property types until we bump PHP to ≥ 7.4
|
||||||
'no_null_property_initialization' => false,
|
'no_null_property_initialization' => false,
|
||||||
|
// @Symfony:risky started removing them but we will probably want to go the opposite direction.
|
||||||
|
'declare_strict_types' => false,
|
||||||
])
|
])
|
||||||
->setFinder($finder)
|
->setFinder($finder)
|
||||||
;
|
;
|
||||||
|
|||||||
+7
-4
@@ -30,12 +30,12 @@
|
|||||||
"masterminds/html5": "^2.7"
|
"masterminds/html5": "^2.7"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"friendsofphp/php-cs-fixer": "^3.0",
|
"friendsofphp/php-cs-fixer": "3.95.8",
|
||||||
"monolog/monolog": "^1.24|^2.1",
|
"monolog/monolog": "^1.24|^2.1",
|
||||||
"symfony/phpunit-bridge": "^4.4|^5.3|^6.0|^7.0",
|
"symfony/phpunit-bridge": "^4.4|^5.3|^6.0|^7.0",
|
||||||
"phpstan/phpstan": "^2.0",
|
"phpstan/phpstan": "2.2.2",
|
||||||
"phpstan/phpstan-phpunit": "^2.0",
|
"phpstan/phpstan-phpunit": "2.0.16",
|
||||||
"rector/rector": "^2.0.0"
|
"rector/rector": "2.4.6"
|
||||||
},
|
},
|
||||||
"suggest": {
|
"suggest": {
|
||||||
"ext-tidy": "Used to clean up given HTML and to avoid problems with bad HTML structure."
|
"ext-tidy": "Used to clean up given HTML and to avoid problems with bad HTML structure."
|
||||||
@@ -46,6 +46,9 @@
|
|||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": { "Tests\\Readability\\": "tests/" }
|
"psr-4": { "Tests\\Readability\\": "tests/" }
|
||||||
},
|
},
|
||||||
|
"config": {
|
||||||
|
"lock": false
|
||||||
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"fix": "php-cs-fixer fix --verbose --diff",
|
"fix": "php-cs-fixer fix --verbose --diff",
|
||||||
"phpstan": "phpstan analyze --memory-limit 512M",
|
"phpstan": "phpstan analyze --memory-limit 512M",
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class JSLikeHTMLElement extends \DOMElement
|
|||||||
* $div->innerHTML = '<h2>Chapter 2</h2><p>The story begins...</p>';
|
* $div->innerHTML = '<h2>Chapter 2</h2><p>The story begins...</p>';
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
public function __set($name, $value)
|
public function __set(string $name, string $value): void
|
||||||
{
|
{
|
||||||
if ('innerHTML' !== $name) {
|
if ('innerHTML' !== $name) {
|
||||||
$trace = debug_backtrace();
|
$trace = debug_backtrace();
|
||||||
@@ -108,7 +108,7 @@ class JSLikeHTMLElement extends \DOMElement
|
|||||||
* $string = $div->innerHTML;
|
* $string = $div->innerHTML;
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
public function __get($name)
|
public function __get(string $name): string
|
||||||
{
|
{
|
||||||
if ('innerHTML' === $name) {
|
if ('innerHTML' === $name) {
|
||||||
$inner = '';
|
$inner = '';
|
||||||
@@ -124,20 +124,22 @@ class JSLikeHTMLElement extends \DOMElement
|
|||||||
|
|
||||||
$trace = debug_backtrace();
|
$trace = debug_backtrace();
|
||||||
trigger_error('Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], \E_USER_NOTICE);
|
trigger_error('Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], \E_USER_NOTICE);
|
||||||
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __toString()
|
public function __toString(): string
|
||||||
{
|
{
|
||||||
return '[' . $this->tagName . ']';
|
return '[' . $this->tagName . ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInnerHtml()
|
public function getInnerHtml(): string
|
||||||
{
|
{
|
||||||
return $this->__get('innerHTML');
|
return $this->__get('innerHTML');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setInnerHtml($value)
|
public function setInnerHtml(string $value): void
|
||||||
{
|
{
|
||||||
return $this->__set('innerHTML', $value);
|
$this->__set('innerHTML', $value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-1
@@ -1483,8 +1483,15 @@ class Readability implements LoggerAwareInterface
|
|||||||
$childNodes = iterator_to_array($node->childNodes);
|
$childNodes = iterator_to_array($node->childNodes);
|
||||||
$children = array_filter($childNodes, static fn ($childNode) => $childNode instanceof \DOMElement);
|
$children = array_filter($childNodes, static fn ($childNode) => $childNode instanceof \DOMElement);
|
||||||
|
|
||||||
|
// array_first() has been added in PHP 8.5, failing back for older versions
|
||||||
|
if (!\function_exists('array_first')) {
|
||||||
|
$firstChild = $children ? $children[array_key_first($children)] : null;
|
||||||
|
} else {
|
||||||
|
$firstChild = array_first($children);
|
||||||
|
}
|
||||||
|
|
||||||
// There should be exactly 1 element child with given tag
|
// There should be exactly 1 element child with given tag
|
||||||
if (1 !== \count($children) || $children[0]->nodeName !== $tag) {
|
if (1 !== \count($children) || $firstChild->nodeName !== $tag) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -464,6 +464,49 @@ class ReadabilityTest extends \PHPUnit\Framework\TestCase
|
|||||||
$this->assertTrue($res);
|
$this->assertTrue($res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function dataForHasSingleTagInsideElement(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'single matching tag, no other content' => [
|
||||||
|
'<div><p>Some text</p></div>', 'p', true,
|
||||||
|
],
|
||||||
|
'single matching tag with comment' => [
|
||||||
|
'<div><!-- comment --><p>Some text</p></div>', 'p', true,
|
||||||
|
],
|
||||||
|
'whitespace-only text around single matching tag' => [
|
||||||
|
'<div> <p>Some text</p> </div>', 'p', true,
|
||||||
|
],
|
||||||
|
'two matching tags' => [
|
||||||
|
'<div><p>One</p><p>Two</p></div>', 'p', false,
|
||||||
|
],
|
||||||
|
'non-whitespace text alongside the single tag' => [
|
||||||
|
'<div>Some text<p>One</p></div>', 'p', false,
|
||||||
|
],
|
||||||
|
'single tag with a different name' => [
|
||||||
|
'<div><span>One</span></div>', 'p', false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider dataForHasSingleTagInsideElement
|
||||||
|
*/
|
||||||
|
public function testHasSingleTagInsideElement(string $html, string $tag, bool $expected): void
|
||||||
|
{
|
||||||
|
$dom = new \DOMDocument();
|
||||||
|
$dom->loadHTML('<html><body>' . $html . '</body></html>');
|
||||||
|
$node = $dom->getElementsByTagName('div')->item(0);
|
||||||
|
|
||||||
|
$readability = $this->getReadability('', '', 'libxml', false);
|
||||||
|
|
||||||
|
$method = new \ReflectionMethod($readability, 'hasSingleTagInsideElement');
|
||||||
|
if (\PHP_VERSION_ID < 80100) {
|
||||||
|
$method->setAccessible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertSame($expected, $method->invoke($readability, $node, $tag));
|
||||||
|
}
|
||||||
|
|
||||||
public function testKeepFootnotes(): void
|
public function testKeepFootnotes(): void
|
||||||
{
|
{
|
||||||
// from https://www.schreibdichte.de/blog/feed-aggregator-und-spaeter-lesen-dienst-im-team
|
// from https://www.schreibdichte.de/blog/feed-aggregator-und-spaeter-lesen-dienst-im-team
|
||||||
@@ -538,8 +581,8 @@ class ReadabilityTest extends \PHPUnit\Framework\TestCase
|
|||||||
$res = $readability->init();
|
$res = $readability->init();
|
||||||
|
|
||||||
$this->assertTrue($res);
|
$this->assertTrue($res);
|
||||||
$this->assertInstanceOf('Readability\JSLikeHTMLElement', $readability->getContent());
|
$this->assertInstanceOf(JSLikeHTMLElement::class, $readability->getContent());
|
||||||
$this->assertInstanceOf('Readability\JSLikeHTMLElement', $readability->getTitle());
|
$this->assertInstanceOf(JSLikeHTMLElement::class, $readability->getTitle());
|
||||||
$this->assertSame('Tõde ja õigus I', $readability->getTitle()->getInnerHtml());
|
$this->assertSame('Tõde ja õigus I', $readability->getTitle()->getInnerHtml());
|
||||||
$this->assertStringContainsString('Päike lähenes', $readability->getContent()->getInnerHtml());
|
$this->assertStringContainsString('Päike lähenes', $readability->getContent()->getInnerHtml());
|
||||||
}
|
}
|
||||||
@@ -584,7 +627,7 @@ class ReadabilityTest extends \PHPUnit\Framework\TestCase
|
|||||||
$this->assertTrue($res);
|
$this->assertTrue($res);
|
||||||
$this->assertInstanceOf(\DOMDocument::class, $readability->dom);
|
$this->assertInstanceOf(\DOMDocument::class, $readability->dom);
|
||||||
$this->assertSame($lang, $readability->dom->documentElement->getAttribute('lang'));
|
$this->assertSame($lang, $readability->dom->documentElement->getAttribute('lang'));
|
||||||
$this->assertInstanceOf('Readability\JSLikeHTMLElement', $readability->getContent());
|
$this->assertInstanceOf(JSLikeHTMLElement::class, $readability->getContent());
|
||||||
$this->assertStringContainsString('êtres', $readability->getContent()->getInnerHtml());
|
$this->assertStringContainsString('êtres', $readability->getContent()->getInnerHtml());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user