Skip to content

Commit dc411b5

Browse files
committed
Fix processing of new Gist HTML. See #55
1 parent a7b53db commit dc411b5

File tree

1 file changed

+75
-84
lines changed

1 file changed

+75
-84
lines changed

includes/class-gistpress.php

Lines changed: 75 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,12 @@ public function shortcode( array $rawattr ) {
199199

200200
if ( is_feed() ) {
201201
$html = sprintf( '<a href="%s" target="_blank"><em>%s</em></a>', esc_url( $url ), __( 'View this code snippet on GitHub.', 'gistpress' ) );
202-
202+
203203
/**
204204
* Filter what is shown in feeds.
205-
*
205+
*
206206
* @since 2.0.0
207-
*
207+
*
208208
* @param string $html Markup to show in feeds.
209209
*/
210210
return apply_filters( 'gistpress_feed_html', $html );
@@ -224,9 +224,9 @@ public function shortcode( array $rawattr ) {
224224

225225
/**
226226
* Filter the output HTML.
227-
*
227+
*
228228
* @since 2.0.0
229-
*
229+
*
230230
* @param string $html The output HTML.
231231
* @param string $url The URL to the Gist.
232232
* @param array $attr Shortcode attributes, standardized.
@@ -465,60 +465,75 @@ public function process_gist_html( $html, array $args ) {
465465
$html = preg_replace( '#<div class="gist-meta">.*?</div>#s', '', $html );
466466
}
467467

468-
$lines_pattern = '#(<pre class="line-pre"[^>]*>)(.+?)</pre>#s';
469-
preg_match( $lines_pattern, $html, $lines_matches );
468+
if ( ! class_exists( 'DOMDocument' ) ) {
469+
return $html;
470+
}
470471

471-
if ( ! empty( $lines_matches[2] ) ) {
472-
// Restrict the line number display if a range has been specified.
473-
if ( $args['show_line_numbers'] && ( ( $args['lines']['min'] && $args['lines']['max'] ) || ! empty( $args['lines_start'] ) ) ) {
474-
$html = $this->process_gist_line_numbers( $html, $args['lines'], $args['lines_start'] );
475-
}
472+
$dom = DOMDocument::loadHTML( $html );
476473

477-
if ( ! empty( $args['highlight'] ) ) {
478-
// Flip to use isset() when looping through the lines.
479-
$highlight = array_flip( $args['highlight'] );
480-
}
474+
// @todo Make this more unique?
475+
$lines = $dom->getElementsByTagName( 'tr' );
481476

482-
// Extract and cleanup the individual lines from the Gist HTML into an array for processing.
483-
$lines = preg_replace( '#<div[^>]+>#', '', trim( $lines_matches[2] ), 1 );
484-
$lines = preg_split( '#</div>[\s]*<div[^>]+>#', substr( $lines, 0, strlen( $lines ) - 6 ) );
477+
if ( ! empty( $args['highlight'] ) ) {
478+
// Flip to use isset() when looping through the lines.
479+
$highlight = array_flip( $args['highlight'] );
480+
}
485481

486-
foreach ( $lines as $key => $line ) {
487-
// Remove lines if they're not in the specified range and continue.
488-
if ( ( $args['lines']['min'] && $key < $args['lines']['min'] - 1 ) || ( $args['lines']['max'] && $key > $args['lines']['max'] - 1 ) ) {
489-
unset( $lines[ $key ] );
490-
continue;
491-
}
482+
$lines_to_remove = array();
483+
foreach ( $lines as $key => $line ) {
484+
// Remove lines if they're not in the specified range and continue.
485+
if (
486+
( $args['lines']['min'] && $key < $args['lines']['min'] - 1 ) ||
487+
( $args['lines']['max'] && $key > $args['lines']['max'] - 1 )
488+
) {
489+
$lines_to_remove[] = $line;
490+
continue;
491+
}
492492

493-
// Add classes for styling.
494-
$classes = array( 'line' );
495-
//$classes[] = ( $key % 2 ) ? 'line-odd' : 'line-even';
496-
$style = '';
493+
// Add classes for styling.
494+
$classes = array( 'line' );
497495

498-
if ( isset( $highlight[ $key + 1 ] ) ) {
499-
$classes[] = 'line-highlight';
496+
if ( isset( $highlight[ $key + 1 ] ) ) {
497+
$classes[] = 'line-highlight';
500498

501-
if ( ! empty( $args['highlight_color'] ) ) {
502-
$style = ' style="background-color: ' . $args['highlight_color'] . ' !important"';
499+
if ( ! empty( $args['highlight_color'] ) ) {
500+
$style = 'background-color: ' . $args['highlight_color'] . ' !important';
501+
502+
foreach ( $line->getElementsByTagName( 'td' ) as $cell ) {
503+
$value = $cell->getAttribute( 'style' );
504+
$value = empty( $value ) ? $style : $value . ';' . $style;
505+
$cell->setAttribute( 'style', $value );
503506
}
504507
}
508+
}
505509

506-
/**
507-
* Filter the classes applied to a line of the Gist.
508-
*
509-
* @since 2.0.0
510-
*
511-
* @param array $classes List of HTML class values.
512-
*/
513-
$classes = apply_filters( 'gistpress_line_classes', $classes );
514-
$class = ( ! empty( $classes ) && is_array( $classes ) ) ? ' class="' . implode ( ' ', $classes ) . '"' : '';
510+
/**
511+
* Filter the classes applied to a line of the Gist.
512+
*
513+
* @since 2.0.0
514+
*
515+
* @param array $classes List of HTML class values.
516+
*/
517+
$classes = apply_filters( 'gistpress_line_classes', $classes );
518+
$class = ( ! empty( $classes ) && is_array( $classes ) ) ? implode ( ' ', $classes ) : '';
515519

516-
$lines[ $key ] = '<div' . $class . $style . '>' . $line . '</div>';
517-
}
520+
$value = $line->getAttribute( 'class' );
521+
$value = empty( $value ) ? $class : $value . ' ' . $class;
522+
$line->setAttribute( 'class', $value );
523+
}
518524

519-
$replacement = $lines_matches[1] . join( '', $lines ) . '</pre>';
520-
$replacement = $this->preg_replace_quote( $replacement );
521-
$html = preg_replace( $lines_pattern, $replacement, $html, 1 );
525+
foreach ( $lines_to_remove as $line ) {
526+
$line->parentNode->removeChild( $line );
527+
}
528+
529+
$html = $dom->saveHTML();
530+
531+
// Restrict the line number display if a range has been specified.
532+
if (
533+
$args['show_line_numbers'] &&
534+
( ( $args['lines']['min'] && $args['lines']['max'] ) || ! empty( $args['lines_start'] ) )
535+
) {
536+
$html = $this->process_gist_line_numbers( $html, $args['lines'], $args['lines_start'] );
522537
}
523538

524539
return $html;
@@ -537,43 +552,19 @@ public function process_gist_html( $html, array $args ) {
537552
* @return string Modified HTML.
538553
*/
539554
public function process_gist_line_numbers( $html, array $range, $start = null ) {
540-
$line_num_pattern = '#(<td class="line-numbers">)(.*?)</td>#s';
541-
preg_match( $line_num_pattern, $html, $line_num_matches );
542-
543-
if ( ! empty( $line_num_matches[2] ) ) {
544-
$start = absint( $start );
545-
$lines = array_map( 'trim', explode( "\n", trim( $line_num_matches[2] ) ) );
555+
$start = empty( $start ) ? absint( $range['min'] ) : absint( $start );
546556

547-
if( ! $start && $range['min'] && $range['max'] ) {
548-
$line_numbers = array_slice( $lines, $range['min'] - 1, $range['max'] - $range['min'] + 1 );
549-
} else {
550-
// Determine how many lines should be shown.
551-
$range_length = count( $lines );
552-
if ( $range['min'] && $range['max'] ) {
553-
$range_length = $range['max'] - $range['min'] + 1;
554-
$start = ( $start ) ? $start : $range['min'];
555-
}
556-
557-
// Create a template with a placeholder for the line number.
558-
preg_match( '#<span rel="([^"]+)[0-9]+?"#', $lines[0], $attr_matches );
559-
if ( ! empty( $attr_matches[1] ) ) {
560-
$template = sprintf( '<span rel="%1$s%2$s" id="%1$s%2$s">%2$s</span>', esc_attr( $attr_matches[1] ), '{{num}}' );
561-
} else {
562-
$template = '<span>{{num}}</span>';
563-
}
557+
$dom = DOMDocument::loadHTML( $html );
558+
$lines = $dom->getElementsByTagName( 'tr' );
564559

565-
// Generate HTML for the line numbers.
566-
$line_numbers = array();
567-
for ( $i = $start; $i <= $start + $range_length - 1; $i ++ ) {
568-
$line_numbers[] = str_replace( '{{num}}', $i, $template );
569-
}
570-
}
571-
572-
$replacement = $line_num_matches[1] . join( "\n", $line_numbers ) . '</td>';
573-
$html = preg_replace( $line_num_pattern, $replacement, $html, 1 );
560+
foreach ( $lines as $i => $line ) {
561+
$line
562+
->getElementsByTagName( 'td' )
563+
->item( 0 )
564+
->setAttribute( 'data-line-number', $start + $i );
574565
}
575566

576-
return $html;
567+
return $dom->saveHTML();
577568
}
578569

579570
/**
@@ -638,14 +629,14 @@ protected function rebuild_shortcode( array $rawattr ) {
638629
protected function standardize_attributes( array $rawattr ) {
639630
/**
640631
* Filter the shortcode attributes defaults.
641-
*
632+
*
642633
* @since 2.0.0
643-
*
634+
*
644635
* @see standardize_attributes()
645-
*
636+
*
646637
* @param array $gistpress_shortcode_defaults {
647638
* Shortcode attributes defaults.
648-
*
639+
*
649640
* @type bool $embed_stylesheet Filterable value to include style sheet or not. Default is true
650641
* to include it.
651642
* @type string $file File name within gist. Default is an empty string, indicating

0 commit comments

Comments
 (0)