mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00

* Make eslint sort our imports * fix missing deps in eslint rule (dae) Caught on Linux due to the stricter sandboxing * Remove exports-last eslint rule (for now?) * Adjust browserslist settings - We use ResizeObserver which is not supported in browsers like KaiOS, Baidu or Android UC * Raise minimum iOS version 13.4 - It's the first version that supports ResizeObserver * Apply new eslint rules to sort imports
101 lines
3 KiB
TypeScript
101 lines
3 KiB
TypeScript
// Copyright: Ankitects Pty Ltd and contributors
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
import { ascendWhileSingleInline } from "./ascend";
|
|
import type { ChildNodeRange } from "./child-node-range";
|
|
import {
|
|
areSiblingChildNodeRanges,
|
|
coversWholeParent,
|
|
mergeChildNodeRanges,
|
|
nodeToChildNodeRange,
|
|
} from "./child-node-range";
|
|
|
|
interface MergeMatch {
|
|
mismatch: boolean;
|
|
minimized: ChildNodeRange[];
|
|
}
|
|
|
|
function createInitialMergeMatch(childNodeRange: ChildNodeRange): MergeMatch {
|
|
return {
|
|
mismatch: false,
|
|
minimized: [childNodeRange],
|
|
};
|
|
}
|
|
|
|
/**
|
|
* After an _inner match_, we right-reduce the existing matches
|
|
* to see if any existing inner matches can be matched to one bigger match
|
|
*
|
|
* @example When surround with <b>
|
|
* <b><u>Hello </u></b><b><i>World</i></b> will be merged to
|
|
* <b><u>Hello </u><i>World</i></b>
|
|
*/
|
|
const tryMergingTillMismatch =
|
|
(base: Element) =>
|
|
(
|
|
{ mismatch, minimized /* must be nonempty */ }: MergeMatch,
|
|
childNodeRange: ChildNodeRange,
|
|
): MergeMatch => {
|
|
if (mismatch) {
|
|
return {
|
|
mismatch,
|
|
minimized: [childNodeRange, ...minimized],
|
|
};
|
|
} else {
|
|
const [nextChildNodeRange, ...restChildNodeRanges] = minimized;
|
|
|
|
if (
|
|
areSiblingChildNodeRanges(
|
|
childNodeRange,
|
|
nextChildNodeRange,
|
|
) /* && !childNodeRange.parent === base */
|
|
) {
|
|
const mergedChildNodeRange = mergeChildNodeRanges(
|
|
childNodeRange,
|
|
nextChildNodeRange,
|
|
);
|
|
|
|
const newChildNodeRange =
|
|
coversWholeParent(mergedChildNodeRange) &&
|
|
mergedChildNodeRange.parent !== base
|
|
? nodeToChildNodeRange(
|
|
ascendWhileSingleInline(
|
|
mergedChildNodeRange.parent,
|
|
base,
|
|
),
|
|
)
|
|
: mergedChildNodeRange;
|
|
|
|
return {
|
|
mismatch,
|
|
minimized: [newChildNodeRange, ...restChildNodeRanges],
|
|
};
|
|
} else {
|
|
return {
|
|
mismatch: true,
|
|
minimized: [childNodeRange, ...minimized],
|
|
};
|
|
}
|
|
}
|
|
};
|
|
|
|
function getMergeMatcher(base: Element) {
|
|
function mergeMatchInner(
|
|
accu: ChildNodeRange[],
|
|
childNodeRange: ChildNodeRange,
|
|
): ChildNodeRange[] {
|
|
return [...accu].reduceRight(
|
|
tryMergingTillMismatch(base),
|
|
createInitialMergeMatch(childNodeRange),
|
|
).minimized;
|
|
}
|
|
|
|
return mergeMatchInner;
|
|
}
|
|
|
|
export function mergeMatchChildNodeRanges(
|
|
ranges: ChildNodeRange[],
|
|
base: Element,
|
|
): ChildNodeRange[] {
|
|
return ranges.reduce(getMergeMatcher(base), []);
|
|
}
|