Skip to content

Commit

Permalink
chore: refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
WilcoFiers committed Jun 2, 2021
1 parent 08d7adc commit 1d508c8
Showing 1 changed file with 49 additions and 79 deletions.
128 changes: 49 additions & 79 deletions lib/checks/navigation/heading-order-after.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,20 @@ export default function headingOrderAfter(results) {
* Determine check outcome, based on the position of the result in the headingOrder
*/
function getHeadingOrderOutcome(result, headingOrder) {
const index = headingOrder.findIndex(heading => heading.result === result);
const index = findHeadingOrderIndex(headingOrder, result.node.ancestry)
const currLevel = headingOrder[index]?.level ?? -1;
const prevLevel = headingOrder[index - 1]?.level ?? -1;

// First heading always passes
if (index === 0) {
return true
};

// Heading not in the map
if (currLevel === -1) {
return undefined;
// Heading level is skipped
} else if (currLevel - prevLevel > 1) {
return false;
} else {
return true;
return undefined;
}
// Check if a heading is skipped
return (currLevel - prevLevel <= 1)
}

/**
Expand All @@ -40,101 +37,74 @@ function getHeadingOrder(results) {
results.sort(({ node: nodeA }, { node: nodeB }) => {
return nodeA.ancestry.length - nodeB.ancestry.length;
});

// Recursively push or splice result.data into headingOrder
const headingOrder = results.reduce(addResultToHeadingOrder, []);
// push or splice result.data into headingOrder
const headingOrder = results.reduce(mergeHeadingOrder, []);
// Remove all frame placeholders that was fully replaced
return headingOrder.filter(heading => heading && !heading.replaced);
}

/**
* Add the data of a heading-order result to the headingOrder map
*/
function addResultToHeadingOrder(headingOrder, result) {
let frameHeadingOrder = result?.data?.headingOrder;
// Only the first selected element in the window has headingOrder info
function mergeHeadingOrder(mergedHeadingOrder, result) {
const frameHeadingOrder = result.data?.headingOrder;
const frameAncestry = shortenArray(result.node.ancestry, 1);

// Only the first result in each frame has a headingOrder. Ignore the rest
if (!frameHeadingOrder) {
setResultInHeadingOrder(headingOrder, result);
return headingOrder;
return mergedHeadingOrder;
}

// Update the ancestry to include frame information
frameHeadingOrder = frameHeadingOrder.map(heading => {
return normalizeHeading(heading, result);
// Prepend node ancestry to each heading.ancestry
const normalizedHeadingOrder = frameHeadingOrder.map(heading => {
return addFrameToHeadingAncestry(heading, frameAncestry);
});

const index = getFrameIndex(headingOrder, result);
// Find if the result is from a frame previously processed
const index = getFrameIndex(mergedHeadingOrder, frameAncestry);
// heading is not in a frame, stick 'm in at the end.
if (index === -1) {
headingOrder.push(...frameHeadingOrder);
mergedHeadingOrder.push(...normalizedHeadingOrder);
} else {
// Mark the frame for later removal
// Keep it, for nested iframes where a parent has no headings
headingOrder[index].replaced = true;
headingOrder.splice(index, 0, ...frameHeadingOrder);
// Flag the frame placeholder so it can be deleted later
mergedHeadingOrder[index].replaced = true;
mergedHeadingOrder.splice(index, 0, ...normalizedHeadingOrder);
}
return headingOrder;
return mergedHeadingOrder;
}

/**
* Determine where the iframe results fit into the top-level
* heading order
* Determine where the iframe results fit into the top-level heading order
*
* If a frame has no headings, but it does have iframes we might not have a result.
* We can account for this by finding the closest ancestor we do know about.
*/
function getFrameIndex(headingOrder, result) {
let index = -1;
const ancestry = shortenArray(result.node.ancestry, 1);
// If a frame has no headings, but it does have iframes we might
// not have a result. We can account for this by finding the closest
// ancestor we do know about.
while (ancestry.length && index === -1) {
index = headingOrder.findIndex(heading => {
return matchAncestry(heading.ancestry, ancestry);
});
ancestry.pop();
function getFrameIndex(headingOrder, frameAncestry) {
while (frameAncestry.length) {
const index = findHeadingOrderIndex(headingOrder, frameAncestry);
if (index !== -1) {
return index;
}
frameAncestry = shortenArray(frameAncestry, 1)
}
return index;
return -1;
}

/**
* Find the heading based on ancestry, and set the result property
* Find the index of a heading in the headingOrder by matching ancestries
*/
function setResultInHeadingOrder(headingOrder, result) {
const ancestry = result.node.ancestry;
const index = headingOrder.findIndex(heading => {
function findHeadingOrderIndex(headingOrder, ancestry) {
return headingOrder.findIndex(heading => {
return matchAncestry(heading.ancestry, ancestry);
});

if (index === -1) {
// Something went wrong, set it to incomplete
result.result = undefined;
return;
}

headingOrder[index] = {
...headingOrder[index],
result
};
}

/**
* Add all required props to the heading
*/
function normalizeHeading(heading, result) {
const ancestry = combineAncestry(result, heading);
const resultMatches = matchAncestry(result.node.ancestry, ancestry);
return {
...heading,
result: resultMatches ? result : undefined,
ancestry
};
}

/**
* Take the frame ancestry from a result, and add it to the ancestry
* of a heading.
* Prepend the frame ancestry of a node to heading.ancestry
*/
function combineAncestry(result, heading) {
const frameAncestry = shortenArray(result.node.ancestry, 1);
return frameAncestry.concat(heading.ancestry);
function addFrameToHeadingAncestry(heading, frameAncestry) {
const ancestry = frameAncestry.concat(heading.ancestry);
return { ...heading, ancestry };
}

/**
Expand All @@ -146,13 +116,13 @@ function matchAncestry(ancestryA, ancestryB) {
}
return ancestryA.every((selectorA, index) => {
const selectorB = ancestryB[index];
if (Array.isArray(selectorA)) {
if (selectorA.length !== selectorB.length) {
return false;
}
return selectorA.every((str, index) => selectorB[index] === str);
if (!Array.isArray(selectorA)) {
return selectorA === selectorB;
}
if (selectorA.length !== selectorB.length) {
return false;
}
return selectorA === selectorB;
return selectorA.every((str, index) => selectorB[index] === str);
});
}

Expand Down

0 comments on commit 1d508c8

Please sign in to comment.