From dd5b57d166d45aa72b5174396dab212c7a3e9229 Mon Sep 17 00:00:00 2001 From: OriginalAuthority Date: Sun, 26 Oct 2025 13:57:45 +0000 Subject: [PATCH 1/3] feat: if the exclude-row-indexes arg is set, skip those rows --- includes/ProgressTableProcessor.php | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/includes/ProgressTableProcessor.php b/includes/ProgressTableProcessor.php index 96ee2a0..4efa39e 100644 --- a/includes/ProgressTableProcessor.php +++ b/includes/ProgressTableProcessor.php @@ -4,6 +4,7 @@ use DOMDocument; use DOMElement; +use DOMException; use DOMXPath; use Exception; use MediaWiki\Html\Html; @@ -58,6 +59,12 @@ class ProgressTableProcessor { */ private ?string $errorMessage = null; + /** + * Row indexes that should not contain checkboxes if exclude-row-indexes is set + * @var array + */ + private array $skipRows = []; + /** * Constructor * @@ -84,6 +91,17 @@ public function __construct( string $wikitext, array $args, Parser $parser, PPFr return; } + if ( isset( $this->args['exclude-row-indexes'] ) ) { + $indexes = explode( ";" , $this->args['exclude-row-indexes'] ); + + // DOMDocument and XPath are 0-based, therefore, as above, we need to minus 1 from each of + // the user-provided args to ensure we are targeting the correct row + $this->skipRows = array_map( + fn( $i ) => max( 0, intval( $i ) - 1 ), + $indexes + ); + } + $this->loadAndValidateHtml(); } @@ -291,11 +309,23 @@ private function processDataRows(): void { /** * Creates and adds a progress tracking checkbox cell to a single data row. + * * @param DOMElement $row the row we are currently working on * @param int $rowIndex the index we are applying to the row + * * @return void + * @throws DOMException */ private function addCheckboxCellToRow( DOMElement $row, int $rowIndex ): void { + // user did not want a checkbox for this cell. We still need to add the or else + // the remainder of the content is shifted left 1 place + if ( in_array( $rowIndex, $this->skipRows, true ) ) { + $emptyCell = $this->dom->createElement( 'td' ); + $emptyCell->setAttribute( 'class', self::CHECKBOX_CELL_CLASS ); + $row->insertBefore( $emptyCell, $row->firstChild ); + return; + } + $rowId = $this->getUniqueRowId( $row, $rowIndex ); $row->setAttribute( 'data-row-id', $rowId ); From 39152ece23fcda00dd07e60bdf712bbe0fd3adfe Mon Sep 17 00:00:00 2001 From: OriginalAuthority Date: Thu, 19 Mar 2026 00:26:15 +0000 Subject: [PATCH 2/3] feat: allow skipping by nth term --- includes/ProgressTableProcessor.php | 39 +++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/includes/ProgressTableProcessor.php b/includes/ProgressTableProcessor.php index 4efa39e..4c22b97 100644 --- a/includes/ProgressTableProcessor.php +++ b/includes/ProgressTableProcessor.php @@ -65,6 +65,13 @@ class ProgressTableProcessor { */ private array $skipRows = []; + /** + * Whether we want to skip every Nth row, using % as the delimeter + * for example, %2 would mean skip every even row (every second row) + * @var int|null + */ + private ?int $skipNth = null; + /** * Constructor * @@ -92,14 +99,20 @@ public function __construct( string $wikitext, array $args, Parser $parser, PPFr } if ( isset( $this->args['exclude-row-indexes'] ) ) { - $indexes = explode( ";" , $this->args['exclude-row-indexes'] ); - - // DOMDocument and XPath are 0-based, therefore, as above, we need to minus 1 from each of - // the user-provided args to ensure we are targeting the correct row - $this->skipRows = array_map( - fn( $i ) => max( 0, intval( $i ) - 1 ), - $indexes - ); + $val = trim( $this->args['exclude-row-indexes'] ); + + // lets look if we have %n and want to do an nth row skip + if ( preg_match( '/^%(\d+)$/', $val, $matches ) ) { + $this->skipNth = max( 1, intval( $matches[1] ) ); + } else { + $indexes = explode( ";" , $this->args['exclude-row-indexes'] ); + // DOMDocument and XPath are 0-based, therefore, as above, we need to minus 1 from each of + // the user-provided args to ensure we are targeting the correct row + $this->skipRows = array_map( + fn( $i ) => max( 0, intval( $i ) - 1 ), + $indexes + ); + } } $this->loadAndValidateHtml(); @@ -192,7 +205,7 @@ private function validateDataRowIds(): bool { foreach ( $dataRows as $row ) { $rowId = $this->extractDataRowId( $row ); if ( empty( $rowId ) ) { - $this->errorMessage = 'When unique-column-index is not provided, + $this->errorMessage = 'When unique-column-index is not provided, all data rows must have a data-row-id attribute.'; return false; } @@ -318,8 +331,12 @@ private function processDataRows(): void { */ private function addCheckboxCellToRow( DOMElement $row, int $rowIndex ): void { // user did not want a checkbox for this cell. We still need to add the or else - // the remainder of the content is shifted left 1 place - if ( in_array( $rowIndex, $this->skipRows, true ) ) { + // the remainder of the content is shifted left 1 place (the user either opted not to have a checkbox by + // explicitly passing the row index to be skipped, or used a skipNth rule + $shouldSkipCheckbox = in_array( $rowIndex, $this->skipRows, true ) || + ( $this->skipNth !== null && ( ( $rowIndex + 1) % $this->skipNth === 0 ) ); + + if ( $shouldSkipCheckbox ) { $emptyCell = $this->dom->createElement( 'td' ); $emptyCell->setAttribute( 'class', self::CHECKBOX_CELL_CLASS ); $row->insertBefore( $emptyCell, $row->firstChild ); From 0c376d056a00949b02f7c886cb40e191b292e62d Mon Sep 17 00:00:00 2001 From: OriginalAuthority Date: Sat, 21 Mar 2026 02:40:17 +0000 Subject: [PATCH 3/3] feat: add ability to skip before and after a row --- includes/ProgressTableProcessor.php | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/includes/ProgressTableProcessor.php b/includes/ProgressTableProcessor.php index 4c22b97..23f3570 100644 --- a/includes/ProgressTableProcessor.php +++ b/includes/ProgressTableProcessor.php @@ -72,6 +72,18 @@ class ProgressTableProcessor { */ private ?int $skipNth = null; + /** + * Should we skip all rows after a certain index? + * @var ?int + */ + private ?int $skipAfter = null; + + /** + * Should we skip all rows before a certain index? + * @var ?int + */ + private ?int $skipBefore = null; + /** * Constructor * @@ -104,6 +116,10 @@ public function __construct( string $wikitext, array $args, Parser $parser, PPFr // lets look if we have %n and want to do an nth row skip if ( preg_match( '/^%(\d+)$/', $val, $matches ) ) { $this->skipNth = max( 1, intval( $matches[1] ) ); + } elseif ( preg_match( '/^gt(\d+)$/', $val, $matches ) ) { + $this->skipAfter = max( 1, intval( $matches[1] ) ); + } elseif ( preg_match( '/^lt(\d+)$/', $val, $matches ) ) { + $this->skipBefore = max( 1, intval( $matches[1] ) ); } else { $indexes = explode( ";" , $this->args['exclude-row-indexes'] ); // DOMDocument and XPath are 0-based, therefore, as above, we need to minus 1 from each of @@ -334,7 +350,9 @@ private function addCheckboxCellToRow( DOMElement $row, int $rowIndex ): void { // the remainder of the content is shifted left 1 place (the user either opted not to have a checkbox by // explicitly passing the row index to be skipped, or used a skipNth rule $shouldSkipCheckbox = in_array( $rowIndex, $this->skipRows, true ) || - ( $this->skipNth !== null && ( ( $rowIndex + 1) % $this->skipNth === 0 ) ); + ( $this->skipNth !== null && ( ( $rowIndex + 1) % $this->skipNth === 0 ) ) || + ( $this->skipAfter !== null && ( ( $rowIndex + 1) > $this->skipAfter ) ) || + ( $this->skipBefore !== null && ( ( $rowIndex + 1) < $this->skipBefore ) ); if ( $shouldSkipCheckbox ) { $emptyCell = $this->dom->createElement( 'td' );