*/
public array $items = [];
/**
* Constructor.
*
* @param string $style List style token.
*/
public function __construct( string $style ) {
$this->style = $style;
}
/**
* Append a nested block.
*
* @param WpHtmlApiBlock $block Nested block.
*
* @return void
*/
public function append( WpHtmlApiBlock $block ): void {
$this->items[] = $block;
}
/**
* Flush the list into markdown.
*
* @param WpHtmlApiRendererOptions $options Renderer options.
*
* @return string
*/
public function flush( WpHtmlApiRendererOptions $options ): string {
return '.' === ( $this->style[1] ?? '' )
? $this->flush_ordered( $options )
: $this->flush_unordered( $options );
}
/**
* Flush an ordered list.
*
* @param WpHtmlApiRendererOptions $options Renderer options.
*
* @return string
*/
private function flush_ordered( WpHtmlApiRendererOptions $options ): string {
list( $bullet, $count ) = explode( '.', $this->style );
$count = (int) $count;
$markdown = [];
$item_count = count( $this->items );
$longest_prefix = strlen( (string) ( $count + $item_count ) );
$indent = implode( '', $options->indent );
$prefix_width = mb_strwidth( $indent ) + $longest_prefix;
$spacer = str_repeat( ' ', $longest_prefix );
$soft_limit = $options->soft_line_wrap;
$options->soft_line_wrap -= $prefix_width;
foreach ( $this->items as $item ) {
$buffer = '';
foreach ( explode( "\n", $item->flush( $options ) ) as $index => $line ) {
if ( 0 === $index ) {
if ( '1' === $bullet ) {
$item_number = (string) $count;
} else {
$alpha_index = $count - 1;
$item_number = 'abcdefghijklmnopqrstuvwxyz'[ $alpha_index % 26 ];
}
++$count;
$spacing = str_repeat( ' ', $longest_prefix - strlen( $item_number ) );
$buffer .= "{$indent}{$item_number}.{$spacing} {$line}\n";
} else {
$buffer .= "{$indent}{$spacer} {$line}\n";
}
}
$markdown[] = rtrim( $buffer, "\n" );
}
$options->soft_line_wrap = $soft_limit;
return implode( "\n", $markdown );
}
/**
* Flush an unordered list.
*
* @param WpHtmlApiRendererOptions $options Renderer options.
*
* @return string
*/
private function flush_unordered( WpHtmlApiRendererOptions $options ): string {
$markdown = [];
$indent = implode( '', $options->indent );
$prefix_first = "{$indent}- ";
$prefix_next = "{$indent} ";
$prefix_width = mb_strwidth( $prefix_first );
$soft_limit = $options->soft_line_wrap;
$was_sublist = false;
$options->soft_line_wrap -= $prefix_width;
foreach ( $this->items as $item ) {
$buffer = '';
$is_sublist = $item instanceof WpHtmlApiBlockList;
foreach ( explode( "\n", $item->flush( $options ) ) as $index => $line ) {
if ( 0 === $index && $is_sublist && ! $was_sublist ) {
$buffer .= "{$prefix_next}{$line}\n";
} else {
$buffer .= 0 === $index ? "{$prefix_first}{$line}\n" : "{$prefix_next}{$line}\n";
}
}
$was_sublist = $is_sublist;
$markdown[] = rtrim( $buffer, "\n" );
}
$options->soft_line_wrap = $soft_limit;
return implode( "\n", $markdown );
}
/**
* Determine whether the list is empty.
*
* @return bool
*/
public function is_empty(): bool {
foreach ( $this->items as $item ) {
if ( ! $item->is_empty() ) {
return false;
}
}
return true;
}
}