q( "//main | //*[@role='main']" ); $root = $main ? $main[0] : null; if ( ! $root ) { $body = $c->q( '//body' ); $root = $body ? $body[0] : null; } if ( ! $root ) { return; } $text_parts = array(); foreach ( $c->q( './/p', $root ) as $p ) { if ( $c->q( "ancestor::nav | ancestor::header | ancestor::footer | ancestor::*[@role='navigation']", $p ) ) { continue; } $t = Html::clean( Html::text_of( $p ) ); $words = str_word_count( $t ); if ( $words > 150 ) { $c->add( 'paragraph-long', $p, array( 'words' => $words ) ); } if ( $words >= 5 ) { $text_parts[] = $t; } } $text = implode( ' ', $text_parts ); if ( $c->on( 'reading-level' ) && str_word_count( $text ) >= 150 ) { $score = self::flesch( $text ); if ( $score < 40 ) { $c->add( 'reading-level', $root, array( 'flesch' => round( $score ) ) ); } } if ( $c->on( 'pdf-heavy' ) ) { $pdfs = $c->q( ".//a[contains(translate(@href,'PDF','pdf'),'.pdf')]", $root ); if ( count( $pdfs ) >= 5 ) { $c->add( 'pdf-heavy', $root, array( 'count' => count( $pdfs ) ) ); } } } /** * Flesch reading ease (English). * * @param string $text Text. * @return float */ public static function flesch( $text ) { $sentences = max( 1, preg_match_all( '/[.!?]+(\s|$)/', $text ) ); preg_match_all( "/[A-Za-z']+/", $text, $m ); $words = max( 1, count( $m[0] ) ); $syl = 0; foreach ( $m[0] as $w ) { $syl += self::syllables( $w ); } return 206.835 - 1.015 * ( $words / $sentences ) - 84.6 * ( $syl / $words ); } /** * Rough syllable count. * * @param string $word Word. * @return int */ public static function syllables( $word ) { $word = strtolower( preg_replace( '/[^a-z]/i', '', $word ) ); if ( strlen( $word ) <= 3 ) { return 1; } $word = preg_replace( '/(?:[^laeiouy]es|ed|[^laeiouy]e)$/', '', $word ); $word = preg_replace( '/^y/', '', $word ); $n = preg_match_all( '/[aeiouy]{1,2}/', $word ); return max( 1, (int) $n ); } }