Skip to content

Commit

Permalink
cci: fix section element detection
Browse files Browse the repository at this point in the history
Prior to this, the "Start working on this
section" overlay would appear far after
the next available section, instead only
appearing after the next contribution
survey row (which does not account for H1
headings, other sections, etc.)

This changes the detection to also break
the detection as soon as it finds a
section heading that isn't a CSR heading.
  • Loading branch information
ChlodAlejandro committed Apr 24, 2024
1 parent 31a9dd5 commit df82208
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 4 deletions.
9 changes: 7 additions & 2 deletions src/util/last.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// These don't recognize TypeScript multiple definitions.
/* eslint-disable jsdoc/require-returns-check */
/**
* Returns the last item of a NodeList array.
*
Expand All @@ -14,6 +12,13 @@ function last<T extends Node>( array: NodeListOf<T> ): T;
* @return The last element of the array
*/
function last<T>( array: T[] ): T;
/**
* Returns the last character of a string.
*
* @param string The string to get the last character from
* @return The last character of the string
*/
function last( string: string ): string;
/**
* Returns the last item of an array.
*
Expand Down
19 changes: 17 additions & 2 deletions src/wiki/DeputyCasePage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import sectionHeadingName from './util/sectionHeadingName';
import getPageTitle from './util/getPageTitle';
import DeputyCase from './DeputyCase';
import sectionHeadingId from './util/sectionHeadingId';
import isWikiHeading from './util/isWikiHeading';
import getWikiHeadingLevel from './util/getWikiHeadingLevel';

export type ContributionSurveyHeading = HTMLHeadingElement;

Expand Down Expand Up @@ -147,7 +149,7 @@ export default class DeputyCasePage extends DeputyCase {
el :
el.querySelector<HTMLElement>( '.mw-headline' );
// Handle DiscussionTools case (.mw-heading)
return ( el.classList.contains( 'mw-heading' ) || /^H\d$/.test( el.tagName ) ) &&
return isWikiHeading( el ) &&
headlineElement != null &&
/(Page|Article|Local file|File)s? \d+ (to|through) \d+$/.test( headlineElement.innerText );
}
Expand Down Expand Up @@ -248,11 +250,24 @@ export default class DeputyCasePage extends DeputyCase {
getContributionSurveySection( sectionHeading: HTMLElement ): Node[] {
// Normalize "sectionHeading" to use the h* element and not the .mw-heading span.
sectionHeading = this.normalizeSectionHeading( sectionHeading );
const sectionHeadingLevel = getWikiHeadingLevel( sectionHeading );

const sectionMembers: Node[] = [];

let nextSibling = sectionHeading.nextSibling;
while ( nextSibling != null && !this.isContributionSurveyHeading( nextSibling ) ) {
while (
// Not the end of rendered page content and
nextSibling != null &&
// Next node is not...
!(
// An element
nextSibling instanceof Element &&
// A heading (of any level)
isWikiHeading( nextSibling ) &&
// Higher than the current heading level
sectionHeadingLevel >= getWikiHeadingLevel( nextSibling )
)
) {
sectionMembers.push( nextSibling );
nextSibling = nextSibling.nextSibling as HTMLElement;
}
Expand Down
23 changes: 23 additions & 0 deletions src/wiki/util/getWikiHeadingLevel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import last from '../../util/last';

/**
* Get the level (1 to 6) of any parsed wikitext heading.
*
* This is its own function to account for different parse outputs (Legacy, Parsoid,
* DiscussionTools, etc.)
*
* @param el The element to check. This MUST be a wikitext heading.
* @return The level of the heading (1 to 6)
*/
export default function getWikiHeadingLevel( el: Element ) {
const h = el.classList.contains( 'mw-heading' ) ?
el.querySelector( 'h1, h2, h3, h4, h5, h6' ) :
el;

// Check if this is a valid header
if ( !/^H\d+$/.test( h.tagName ) ) {
throw new Error( 'Heading element does not contain a valid <h*> element' );
}

return +last( h.tagName ) as 1 | 2 | 3 | 4 | 5 | 6;
}
12 changes: 12 additions & 0 deletions src/wiki/util/isWikiHeading.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Check if a given parameter is a wikitext heading parsed into HTML.
*
* This is its own function to account for different parse outputs (Legacy, Parsoid,
* DiscussionTools, etc.)
*
* @param el The element to check
* @return `true` if the element is a heading, `false` otherwise
*/
export default function isWikiHeading( el: Element ): boolean {
return ( el.classList.contains( 'mw-heading' ) || /^H\d$/.test( el.tagName ) );
}

0 comments on commit df82208

Please sign in to comment.