Re-enable formatting for .ts files

There are some style differences compared to prettier, and not all are
necessarily an improvement, but it's much faster now.
This commit is contained in:
Damien Elmes 2022-11-28 09:33:04 +10:00
parent ea5153e7a4
commit b2049209ff
47 changed files with 174 additions and 258 deletions

View file

@ -18,7 +18,6 @@
"**/node_modules", "**/node_modules",
"out/**", "out/**",
"**/*-lock.json", "**/*-lock.json",
"**/*.{ts}",
"qt/aqt/data/web/js/vendor/*.js", "qt/aqt/data/web/js/vendor/*.js",
"ftl/qt-repo", "ftl/qt-repo",
"ftl/core-repo", "ftl/core-repo",

View file

@ -8,7 +8,7 @@ function init() {
scroll: false, scroll: false,
// can't use "helper: 'clone'" because of a bug in jQuery 1.5 // can't use "helper: 'clone'" because of a bug in jQuery 1.5
helper: function (_event) { helper: function(_event) {
return $(this).clone(false); return $(this).clone(false);
}, },
delay: 200, delay: 200,

View file

@ -10,7 +10,7 @@ let time: number; // set in python code
let maxTime = 0; let maxTime = 0;
document.addEventListener("DOMContentLoaded", () => { document.addEventListener("DOMContentLoaded", () => {
updateTime(); updateTime();
setInterval(function () { setInterval(function() {
time += 1; time += 1;
updateTime(); updateTime();
}, 1000); }, 1000);

View file

@ -2,7 +2,7 @@
* License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */ * License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html */
// prevent backspace key from going back a page // prevent backspace key from going back a page
document.addEventListener("keydown", function (evt: KeyboardEvent) { document.addEventListener("keydown", function(evt: KeyboardEvent) {
if (evt.keyCode !== 8) { if (evt.keyCode !== 8) {
return; return;
} }

View file

@ -4,7 +4,7 @@
import * as tr from "@tslib/ftl"; import * as tr from "@tslib/ftl";
import { Notetypes, notetypes } from "@tslib/proto"; import { Notetypes, notetypes } from "@tslib/proto";
import { isEqual } from "lodash-es"; import { isEqual } from "lodash-es";
import type { Readable} from "svelte/store"; import type { Readable } from "svelte/store";
import { readable } from "svelte/store"; import { readable } from "svelte/store";
function nullToNegativeOne(list: (number | null)[]): number[] { function nullToNegativeOne(list: (number | null)[]): number[] {

View file

@ -15,14 +15,10 @@ export function mergeTooltipAndShortcut(
return buf; return buf;
} }
export const withButton = export const withButton = (f: (button: HTMLButtonElement) => void) => ({ detail }: CustomEvent): void => {
(f: (button: HTMLButtonElement) => void) =>
({ detail }: CustomEvent): void => {
f(detail.button); f(detail.button);
}; };
export const withSpan = export const withSpan = (f: (span: HTMLSpanElement) => void) => ({ detail }: CustomEvent): void => {
(f: (span: HTMLSpanElement) => void) =>
({ detail }: CustomEvent): void => {
f(detail.span); f(detail.span);
}; };

View file

@ -5,7 +5,6 @@
@typescript-eslint/no-explicit-any: "off", @typescript-eslint/no-explicit-any: "off",
*/ */
import { DeckConfig } from "@tslib/proto"; import { DeckConfig } from "@tslib/proto";
import { get } from "svelte/store"; import { get } from "svelte/store";

View file

@ -4,7 +4,7 @@
import { localeCompare } from "@tslib/i18n"; import { localeCompare } from "@tslib/i18n";
import { DeckConfig, deckConfig } from "@tslib/proto"; import { DeckConfig, deckConfig } from "@tslib/proto";
import { cloneDeep, isEqual } from "lodash-es"; import { cloneDeep, isEqual } from "lodash-es";
import type { Readable, Writable} from "svelte/store"; import type { Readable, Writable } from "svelte/store";
import { get, readable, writable } from "svelte/store"; import { get, readable, writable } from "svelte/store";
import type { DynamicSvelteComponent } from "../sveltelib/dynamicComponent"; import type { DynamicSvelteComponent } from "../sveltelib/dynamicComponent";

View file

@ -13,13 +13,6 @@ registerPackage("anki/location", {
saveSelection, saveSelection,
}); });
export { export { findNodeFromCoordinates, getNodeCoordinates, getRangeCoordinates, Position, restoreSelection, saveSelection };
findNodeFromCoordinates,
getNodeCoordinates,
getRangeCoordinates,
Position,
restoreSelection,
saveSelection,
};
export type { RangeCoordinates } from "./range"; export type { RangeCoordinates } from "./range";
export type { SelectionLocation } from "./selection"; export type { SelectionLocation } from "./selection";

View file

@ -62,9 +62,9 @@ function buildFromElement<T>(
if ( if (
// blocking // blocking
only instanceof BlockNode || only instanceof BlockNode
// ascension // ascension
(only instanceof FormattingNode && format.tryAscend(only, matchNode)) || (only instanceof FormattingNode && format.tryAscend(only, matchNode))
) { ) {
return [only]; return [only];
} }

View file

@ -6,7 +6,7 @@ import { Position } from "../../location";
import { Match } from "../match-type"; import { Match } from "../match-type";
import type { SplitRange } from "../split-text"; import type { SplitRange } from "../split-text";
import type { SurroundFormat } from "../surround-format"; import type { SurroundFormat } from "../surround-format";
import type { ElementNode} from "../tree"; import type { ElementNode } from "../tree";
import { FormattingNode } from "../tree"; import { FormattingNode } from "../tree";
function nodeWithinRange(node: Node, range: Range): boolean { function nodeWithinRange(node: Node, range: Range): boolean {
@ -14,9 +14,9 @@ function nodeWithinRange(node: Node, range: Range): boolean {
nodeRange.selectNodeContents(node); nodeRange.selectNodeContents(node);
return ( return (
range.compareBoundaryPoints(Range.START_TO_START, nodeRange) !== range.compareBoundaryPoints(Range.START_TO_START, nodeRange)
Position.After && !== Position.After
range.compareBoundaryPoints(Range.END_TO_END, nodeRange) !== Position.Before && range.compareBoundaryPoints(Range.END_TO_END, nodeRange) !== Position.Before
); );
} }

View file

@ -69,8 +69,7 @@ export class FlatRange {
if (range.collapsed) { if (range.collapsed) {
// If the range is collapsed to a single element, move the range inside the element. // If the range is collapsed to a single element, move the range inside the element.
// This prevents putting the surround above the base element. // This prevents putting the surround above the base element.
const selected = const selected = range.commonAncestorContainer.childNodes[range.startOffset];
range.commonAncestorContainer.childNodes[range.startOffset];
if (nodeIsElement(selected)) { if (nodeIsElement(selected)) {
range.selectNode(selected); range.selectNode(selected);

View file

@ -83,7 +83,7 @@ class FakeMatch implements MatchType<never> {
export function boolMatcher<T>( export function boolMatcher<T>(
format: SurroundFormat<T>, format: SurroundFormat<T>,
): (element: Element) => boolean { ): (element: Element) => boolean {
return function (element: Element): boolean { return function(element: Element): boolean {
const fake = new FakeMatch(); const fake = new FakeMatch();
format.matcher(element as HTMLElement | SVGElement, fake); format.matcher(element as HTMLElement | SVGElement, fake);
return fake.value; return fake.value;

View file

@ -10,8 +10,8 @@ function length(node: Node): number {
if (node instanceof CharacterData) { if (node instanceof CharacterData) {
return node.length; return node.length;
} else if ( } else if (
node.nodeType === Node.DOCUMENT_TYPE_NODE || node.nodeType === Node.DOCUMENT_TYPE_NODE
node.nodeType === Node.ATTRIBUTE_NODE || node.nodeType === Node.ATTRIBUTE_NODE
) { ) {
return 0; return 0;
} }

View file

@ -3,18 +3,8 @@
import type { Matcher } from "../find-above"; import type { Matcher } from "../find-above";
import { findFarthest } from "../find-above"; import { findFarthest } from "../find-above";
import { import { apply, ApplyFormat, ReformatApplyFormat, UnsurroundApplyFormat } from "./apply";
apply, import { build, BuildFormat, ReformatBuildFormat, UnsurroundBuildFormat } from "./build";
ApplyFormat,
ReformatApplyFormat,
UnsurroundApplyFormat,
} from "./apply";
import {
build,
BuildFormat,
ReformatBuildFormat,
UnsurroundBuildFormat,
} from "./build";
import { boolMatcher } from "./match-type"; import { boolMatcher } from "./match-type";
import { splitPartiallySelected } from "./split-text"; import { splitPartiallySelected } from "./split-text";
import type { SurroundFormat } from "./surround-format"; import type { SurroundFormat } from "./surround-format";
@ -53,7 +43,7 @@ function reformatInner<T>(
* Assumes that there are no matching ancestor elements above * Assumes that there are no matching ancestor elements above
* `range.commonAncestorContainer`. Make sure that the range is not placed * `range.commonAncestorContainer`. Make sure that the range is not placed
* inside the format before using this. * inside the format before using this.
**/ */
export function surround<T>( export function surround<T>(
range: Range, range: Range,
base: Element, base: Element,

View file

@ -3,13 +3,11 @@
import type { MatchType } from "./match-type"; import type { MatchType } from "./match-type";
export const matchTagName = export const matchTagName = (tagName: string) => <T>(element: Element, match: MatchType<T>): void => {
(tagName: string) =>
<T>(element: Element, match: MatchType<T>): void => {
if (element.matches(tagName)) { if (element.matches(tagName)) {
match.remove(); match.remove();
} }
}; };
export const easyBold = { export const easyBold = {
surroundElement: document.createElement("b"), surroundElement: document.createElement("b"),
@ -38,7 +36,7 @@ export function t(data: string): Text {
} }
function element(tagName: string): (...childNodes: Node[]) => HTMLElement { function element(tagName: string): (...childNodes: Node[]) => HTMLElement {
return function (...childNodes: Node[]): HTMLElement { return function(...childNodes: Node[]): HTMLElement {
const element = document.createElement(tagName); const element = document.createElement(tagName);
element.append(...childNodes); element.append(...childNodes);
return element; return element;

View file

@ -24,9 +24,7 @@ interface WithTagName {
tagName: string; tagName: string;
} }
export interface DecoratedElementConstructor export interface DecoratedElementConstructor extends CustomElementConstructor, WithTagName {
extends CustomElementConstructor,
WithTagName {
prototype: DecoratedElement; prototype: DecoratedElement;
/** /**
* Transforms elements in input HTML from undecorated to stored state. * Transforms elements in input HTML from undecorated to stored state.

View file

@ -9,7 +9,7 @@ export function clearableArray<T>(): (T & Destroyable)[] {
const list: (T & Destroyable)[] = []; const list: (T & Destroyable)[] = [];
return new Proxy(list, { return new Proxy(list, {
get: function (target: (T & Destroyable)[], prop: string | symbol) { get: function(target: (T & Destroyable)[], prop: string | symbol) {
if (!(typeof prop === "symbol") && !isNaN(Number(prop)) && !target[prop]) { if (!(typeof prop === "symbol") && !isNaN(Number(prop)) && !target[prop]) {
const item = {} as T & Destroyable; const item = {} as T & Destroyable;
@ -19,7 +19,7 @@ export function clearableArray<T>(): (T & Destroyable)[] {
}; };
target[prop] = new Proxy(item, { target[prop] = new Proxy(item, {
get: function (target: T & Destroyable, prop: string | symbol) { get: function(target: T & Destroyable, prop: string | symbol) {
if (prop === "destroy") { if (prop === "destroy") {
return destroy; return destroy;
} }

View file

@ -3,7 +3,6 @@
/// <reference types="../lib/image-import" /> /// <reference types="../lib/image-import" />
export { default as incrementClozeIcon } from "../icons/contain-plus.svg";
export { default as alertIcon } from "@mdi/svg/svg/alert.svg"; export { default as alertIcon } from "@mdi/svg/svg/alert.svg";
export { default as chevronDown } from "@mdi/svg/svg/chevron-down.svg"; export { default as chevronDown } from "@mdi/svg/svg/chevron-down.svg";
export { default as chevronUp } from "@mdi/svg/svg/chevron-up.svg"; export { default as chevronUp } from "@mdi/svg/svg/chevron-up.svg";
@ -11,3 +10,7 @@ export { default as plainTextIcon } from "@mdi/svg/svg/code-tags.svg";
export { default as clozeIcon } from "@mdi/svg/svg/contain.svg"; export { default as clozeIcon } from "@mdi/svg/svg/contain.svg";
export { default as richTextIcon } from "@mdi/svg/svg/format-font.svg"; export { default as richTextIcon } from "@mdi/svg/svg/format-font.svg";
export { default as stickyIcon } from "@mdi/svg/svg/pin-outline.svg"; export { default as stickyIcon } from "@mdi/svg/svg/pin-outline.svg";
// This comment prevents disagreement between eslint-plugin-simple-sort and
// dprint about whether .. or @ should come first.
export { default as incrementClozeIcon } from "../icons/contain-plus.svg";

View file

@ -10,9 +10,11 @@ function normalizeFragment(fragment: DocumentFragment): void {
fragment.normalize(); fragment.normalize();
for (const decorated of decoratedElements) { for (const decorated of decoratedElements) {
for (const element of fragment.querySelectorAll( for (
const element of fragment.querySelectorAll(
decorated.tagName, decorated.tagName,
) as NodeListOf<DecoratedElement>) { ) as NodeListOf<DecoratedElement>
) {
element.undecorate(); element.undecorate();
} }
} }

View file

@ -1,11 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { import { fragmentToString, nodeContainsInlineContent, nodeIsElement } from "../../lib/dom";
fragmentToString,
nodeContainsInlineContent,
nodeIsElement,
} from "../../lib/dom";
import { createDummyDoc } from "../../lib/parsing"; import { createDummyDoc } from "../../lib/parsing";
import { decoratedElements } from "../decorated-elements"; import { decoratedElements } from "../decorated-elements";
@ -35,10 +31,10 @@ export function storedToFragment(storedHTML: string): DocumentFragment {
function adjustOutputFragment(fragment: DocumentFragment): void { function adjustOutputFragment(fragment: DocumentFragment): void {
if ( if (
fragment.hasChildNodes() && fragment.hasChildNodes()
nodeIsElement(fragment.lastChild!) && && nodeIsElement(fragment.lastChild!)
nodeContainsInlineContent(fragment) && && nodeContainsInlineContent(fragment)
fragment.lastChild!.tagName === "BR" && fragment.lastChild!.tagName === "BR"
) { ) {
fragment.lastChild!.remove(); fragment.lastChild!.remove();
} }

View file

@ -20,7 +20,7 @@ import {
sum, sum,
} from "d3"; } from "d3";
import type { GraphBounds, GraphRange} from "./graph-helpers"; import type { GraphBounds, GraphRange } from "./graph-helpers";
import { millisecondCutoffForRange, setDataAvailable } from "./graph-helpers"; import { millisecondCutoffForRange, setDataAvailable } from "./graph-helpers";
import { hideTooltip, showTooltip } from "./tooltip"; import { hideTooltip, showTooltip } from "./tooltip";

View file

@ -19,7 +19,7 @@ import {
timeYear, timeYear,
} from "d3"; } from "d3";
import type { GraphBounds, SearchDispatch} from "./graph-helpers"; import type { GraphBounds, SearchDispatch } from "./graph-helpers";
import { RevlogRange, setDataAvailable } from "./graph-helpers"; import { RevlogRange, setDataAvailable } from "./graph-helpers";
import { clickableClass } from "./graph-styles"; import { clickableClass } from "./graph-styles";
import { hideTooltip, showTooltip } from "./tooltip"; import { hideTooltip, showTooltip } from "./tooltip";

View file

@ -9,7 +9,7 @@ import { localizedNumber } from "@tslib/i18n";
import type { Bin, ScaleLinear, ScaleSequential } from "d3"; import type { Bin, ScaleLinear, ScaleSequential } from "d3";
import { area, axisBottom, axisLeft, axisRight, cumsum, curveBasis, max, pointer, scaleLinear, select } from "d3"; import { area, axisBottom, axisLeft, axisRight, cumsum, curveBasis, max, pointer, scaleLinear, select } from "d3";
import type { GraphBounds} from "./graph-helpers"; import type { GraphBounds } from "./graph-helpers";
import { setDataAvailable } from "./graph-helpers"; import { setDataAvailable } from "./graph-helpers";
import { clickableClass } from "./graph-styles"; import { clickableClass } from "./graph-styles";
import { hideTooltip, showTooltip } from "./tooltip"; import { hideTooltip, showTooltip } from "./tooltip";

View file

@ -22,7 +22,7 @@ import {
select, select,
} from "d3"; } from "d3";
import type { GraphBounds, GraphRange} from "./graph-helpers"; import type { GraphBounds, GraphRange } from "./graph-helpers";
import { millisecondCutoffForRange, setDataAvailable } from "./graph-helpers"; import { millisecondCutoffForRange, setDataAvailable } from "./graph-helpers";
import { oddTickClass } from "./graph-styles"; import { oddTickClass } from "./graph-styles";
import { hideTooltip, showTooltip } from "./tooltip"; import { hideTooltip, showTooltip } from "./tooltip";

View file

@ -9,8 +9,7 @@ import * as tr from "@tslib/ftl";
import { localizedNumber } from "@tslib/i18n"; import { localizedNumber } from "@tslib/i18n";
import { Stats } from "@tslib/proto"; import { Stats } from "@tslib/proto";
import { dayLabel, timeSpan } from "@tslib/time"; import { dayLabel, timeSpan } from "@tslib/time";
import type { Bin , import type { Bin, ScaleSequential } from "d3";
ScaleSequential} from "d3";
import { import {
area, area,
axisBottom, axisBottom,
@ -32,7 +31,7 @@ import {
sum, sum,
} from "d3"; } from "d3";
import type { GraphBounds,TableDatum } from "./graph-helpers"; import type { GraphBounds, TableDatum } from "./graph-helpers";
import { GraphRange, setDataAvailable } from "./graph-helpers"; import { GraphRange, setDataAvailable } from "./graph-helpers";
import { hideTooltip, showTooltip } from "./tooltip"; import { hideTooltip, showTooltip } from "./tooltip";

View file

@ -1,7 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { DebouncedFunc} from "lodash-es"; import type { DebouncedFunc } from "lodash-es";
import { throttle } from "lodash-es"; import { throttle } from "lodash-es";
import Tooltip from "./Tooltip.svelte"; import Tooltip from "./Tooltip.svelte";
@ -26,8 +26,7 @@ function showTooltipInner(msg: string, x: number, y: number): void {
tooltip.$set({ html: msg, x, y, show: true }); tooltip.$set({ html: msg, x, y, show: true });
} }
export const showTooltip: DebouncedFunc<(msg: string, x: number, y: number) => void> = export const showTooltip: DebouncedFunc<(msg: string, x: number, y: number) => void> = throttle(showTooltipInner, 16);
throttle(showTooltipInner, 16);
export function hideTooltip(): void { export function hideTooltip(): void {
const tooltip = getOrCreateTooltip(); const tooltip = getOrCreateTooltip();

View file

@ -3,11 +3,7 @@
import { isHTMLElement, isNightMode } from "./helpers"; import { isHTMLElement, isNightMode } from "./helpers";
import { removeNode as removeElement } from "./node"; import { removeNode as removeElement } from "./node";
import { import { filterStylingInternal, filterStylingLightMode, filterStylingNightMode } from "./styling";
filterStylingInternal,
filterStylingLightMode,
filterStylingNightMode,
} from "./styling";
interface TagsAllowed { interface TagsAllowed {
[tagName: string]: FilterMethod; [tagName: string]: FilterMethod;
@ -32,9 +28,7 @@ function allowNone(element: Element): void {
filterAttributes(() => false, element); filterAttributes(() => false, element);
} }
const allow = const allow = (attrs: string[]): FilterMethod => (element: Element): void =>
(attrs: string[]): FilterMethod =>
(element: Element): void =>
filterAttributes( filterAttributes(
(attributeName: string) => attrs.includes(attributeName), (attributeName: string) => attrs.includes(attributeName),
element, element,
@ -93,9 +87,7 @@ const tagsAllowedExtended: TagsAllowed = {
UL: allowNone, UL: allowNone,
}; };
const filterElementTagsAllowed = const filterElementTagsAllowed = (tagsAllowed: TagsAllowed) => (element: Element): void => {
(tagsAllowed: TagsAllowed) =>
(element: Element): void => {
const tagName = element.tagName; const tagName = element.tagName;
if (Object.prototype.hasOwnProperty.call(tagsAllowed, tagName)) { if (Object.prototype.hasOwnProperty.call(tagsAllowed, tagName)) {
@ -105,7 +97,7 @@ const filterElementTagsAllowed =
} else { } else {
removeElement(element); removeElement(element);
} }
}; };
export const filterElementBasic = filterElementTagsAllowed(tagsAllowedBasic); export const filterElementBasic = filterElementTagsAllowed(tagsAllowedBasic);
export const filterElementExtended = filterElementTagsAllowed(tagsAllowedExtended); export const filterElementExtended = filterElementTagsAllowed(tagsAllowedExtended);

View file

@ -13,35 +13,35 @@ describe("filterHTML", () => {
// font-size is filtered, weight is not // font-size is filtered, weight is not
expect( expect(
filterHTML( filterHTML(
'<div style="font-weight: bold; font-size: 10px;"></div>', "<div style=\"font-weight: bold; font-size: 10px;\"></div>",
true, true,
true, true,
), ),
).toBe('<div style="font-weight: bold;"></div>'); ).toBe("<div style=\"font-weight: bold;\"></div>");
}); });
test("background color", () => { test("background color", () => {
// transparent is stripped, other colors are not // transparent is stripped, other colors are not
expect( expect(
filterHTML( filterHTML(
'<span style="background-color: transparent;"></span>', "<span style=\"background-color: transparent;\"></span>",
false, false,
true, true,
), ),
).toBe('<span style=""></span>'); ).toBe("<span style=\"\"></span>");
expect( expect(
filterHTML('<span style="background-color: blue;"></span>', false, true), filterHTML("<span style=\"background-color: blue;\"></span>", false, true),
).toBe('<span style="background-color: blue;"></span>'); ).toBe("<span style=\"background-color: blue;\"></span>");
// except if extended mode is off // except if extended mode is off
expect( expect(
filterHTML('<span style="background-color: blue;">x</span>', false, false), filterHTML("<span style=\"background-color: blue;\">x</span>", false, false),
).toBe("x"); ).toBe("x");
// no filtering on internal paste // no filtering on internal paste
expect( expect(
filterHTML( filterHTML(
'<span style="background-color: transparent;"></span>', "<span style=\"background-color: transparent;\"></span>",
true, true,
true, true,
), ),
).toBe('<span style="background-color: transparent;"></span>'); ).toBe("<span style=\"background-color: transparent;\"></span>");
}); });
}); });

View file

@ -1,11 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import { import { filterElementBasic, filterElementExtended, filterElementInternal } from "./element";
filterElementBasic,
filterElementExtended,
filterElementInternal,
} from "./element";
import { filterNode } from "./node"; import { filterNode } from "./node";
enum FilterMode { enum FilterMode {
@ -31,8 +27,7 @@ function trim(value: string): string {
} }
const outputHTMLProcessors: Record<FilterMode, (outputHTML: string) => string> = { const outputHTMLProcessors: Record<FilterMode, (outputHTML: string) => string> = {
[FilterMode.Basic]: (outputHTML: string): string => [FilterMode.Basic]: (outputHTML: string): string => trim(collapseWhitespace(outputHTML)),
trim(collapseWhitespace(outputHTML)),
[FilterMode.Extended]: trim, [FilterMode.Extended]: trim,
[FilterMode.Internal]: trim, [FilterMode.Internal]: trim,
}; };

View file

@ -14,9 +14,7 @@ function iterateElement(
} }
} }
export const filterNode = export const filterNode = (elementFilter: (element: Element) => void) => (node: Node): void => {
(elementFilter: (element: Element) => void) =>
(node: Node): void => {
switch (node.nodeType) { switch (node.nodeType) {
case Node.COMMENT_NODE: case Node.COMMENT_NODE:
removeNode(node); removeNode(node);
@ -34,4 +32,4 @@ export const filterNode =
default: default:
// do nothing // do nothing
} }
}; };

View file

@ -99,8 +99,8 @@ export function elementIsEmpty(element: Element): boolean {
export function nodeContainsInlineContent(node: Node): boolean { export function nodeContainsInlineContent(node: Node): boolean {
for (const child of node.childNodes) { for (const child of node.childNodes) {
if ( if (
(nodeIsElement(child) && elementIsBlock(child)) || (nodeIsElement(child) && elementIsBlock(child))
!nodeContainsInlineContent(child) || !nodeContainsInlineContent(child)
) { ) {
return false; return false;
} }
@ -122,8 +122,7 @@ export function fragmentToString(fragment: DocumentFragment): string {
} }
const getAnchorParent = const getAnchorParent =
<T extends Element>(predicate: (element: Element) => element is T) => <T extends Element>(predicate: (element: Element) => element is T) => (root: Node): T | null => {
(root: Node): T | null => {
const anchor = getSelection(root)?.anchorNode; const anchor = getSelection(root)?.anchorNode;
if (!anchor) { if (!anchor) {
@ -143,12 +142,10 @@ const getAnchorParent =
const isListItem = (element: Element): element is HTMLLIElement => const isListItem = (element: Element): element is HTMLLIElement =>
window.getComputedStyle(element).display === "list-item"; window.getComputedStyle(element).display === "list-item";
const isParagraph = (element: Element): element is HTMLParamElement => const isParagraph = (element: Element): element is HTMLParamElement => element.tagName === "P";
element.tagName === "P";
const isBlockElement = ( const isBlockElement = (
element: Element, element: Element,
): element is HTMLLIElement & HTMLParamElement => ): element is HTMLLIElement & HTMLParamElement => isListItem(element) || isParagraph(element);
isListItem(element) || isParagraph(element);
export const getListItem = getAnchorParent(isListItem); export const getListItem = getAnchorParent(isListItem);
export const getParagraph = getAnchorParent(isParagraph); export const getParagraph = getAnchorParent(isParagraph);

View file

@ -1,24 +1,15 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export type EventTargetToMap<A extends EventTarget> = A extends HTMLElement export type EventTargetToMap<A extends EventTarget> = A extends HTMLElement ? HTMLElementEventMap
? HTMLElementEventMap : A extends Document ? DocumentEventMap
: A extends Document : A extends Window ? WindowEventMap
? DocumentEventMap : A extends FileReader ? FileReaderEventMap
: A extends Window : A extends Element ? ElementEventMap
? WindowEventMap : A extends Animation ? AnimationEventMap
: A extends FileReader : A extends EventSource ? EventSourceEventMap
? FileReaderEventMap : A extends AbortSignal ? AbortSignalEventMap
: A extends Element : A extends AbstractWorker ? AbstractWorkerEventMap
? ElementEventMap
: A extends Animation
? AnimationEventMap
: A extends EventSource
? EventSourceEventMap
: A extends AbortSignal
? AbortSignalEventMap
: A extends AbstractWorker
? AbstractWorkerEventMap
: never; : never;
export function on<T extends EventTarget, K extends keyof EventTargetToMap<T>>( export function on<T extends EventTarget, K extends keyof EventTargetToMap<T>>(
@ -28,8 +19,7 @@ export function on<T extends EventTarget, K extends keyof EventTargetToMap<T>>(
options?: AddEventListenerOptions, options?: AddEventListenerOptions,
): () => void { ): () => void {
target.addEventListener(eventType, handler as EventListener, options); target.addEventListener(eventType, handler as EventListener, options);
return () => return () => target.removeEventListener(eventType, handler as EventListener, options);
target.removeEventListener(eventType, handler as EventListener, options);
} }
export function preventDefault(event: Event): void { export function preventDefault(event: Event): void {

View file

@ -12,18 +12,18 @@ import type { ModuleName } from "./modules";
export function supportsVerticalText(): boolean { export function supportsVerticalText(): boolean {
const firstLang = firstLanguage(); const firstLang = firstLanguage();
return ( return (
firstLang.startsWith("ja") || firstLang.startsWith("ja")
firstLang.startsWith("zh") || || firstLang.startsWith("zh")
firstLang.startsWith("ko") || firstLang.startsWith("ko")
); );
} }
export function direction(): string { export function direction(): string {
const firstLang = firstLanguage(); const firstLang = firstLanguage();
if ( if (
firstLang.startsWith("ar") || firstLang.startsWith("ar")
firstLang.startsWith("he") || || firstLang.startsWith("he")
firstLang.startsWith("fa") || firstLang.startsWith("fa")
) { ) {
return "rtl"; return "rtl";
} else { } else {

View file

@ -3,9 +3,9 @@
export function isApplePlatform(): boolean { export function isApplePlatform(): boolean {
// avoid deprecation warning // avoid deprecation warning
const platform = window.navigator["platform" + ""] const platform = window.navigator["platform" + ""];
return ( return (
platform.startsWith("Mac") || platform.startsWith("Mac")
platform.startsWith("iP") || platform.startsWith("iP")
); );
} }

View file

@ -3,12 +3,7 @@
import { on } from "./events"; import { on } from "./events";
import type { Modifier } from "./keys"; import type { Modifier } from "./keys";
import { import { checkIfModifierKey, checkModifiers, keyToPlatformString, modifiersToPlatformString } from "./keys";
checkIfModifierKey,
checkModifiers,
keyToPlatformString,
modifiersToPlatformString,
} from "./keys";
import { registerPackage } from "./runtime-require"; import { registerPackage } from "./runtime-require";
const keyCodeLookup = { const keyCodeLookup = {
@ -65,7 +60,7 @@ export function getPlatformString(keyCombinationString: string): string {
function checkKey(event: KeyboardEvent, key: number): boolean { function checkKey(event: KeyboardEvent, key: number): boolean {
// avoid deprecation warning // avoid deprecation warning
const which = event["which" + ""] const which = event["which" + ""];
return which === key; return which === key;
} }
@ -101,8 +96,8 @@ const check =
(keyCode: number, requiredModifiers: Modifier[], optionalModifiers: Modifier[]) => (keyCode: number, requiredModifiers: Modifier[], optionalModifiers: Modifier[]) =>
(event: KeyboardEvent): boolean => { (event: KeyboardEvent): boolean => {
return ( return (
checkKey(event, keyCode) && checkKey(event, keyCode)
checkModifiers(requiredModifiers, optionalModifiers)(event) && checkModifiers(requiredModifiers, optionalModifiers)(event)
); );
}; };
@ -166,8 +161,7 @@ export function registerShortcut(
event = defaultRegisterShortcutRestParams.event, event = defaultRegisterShortcutRestParams.event,
} = restParams; } = restParams;
const [check, ...restChecks] = const [check, ...restChecks] = splitKeyCombinationString(keyCombinationString).map(keyCombinationToCheck);
splitKeyCombinationString(keyCombinationString).map(keyCombinationToCheck);
function handler(event: KeyboardEvent): void { function handler(event: KeyboardEvent): void {
if (check(event)) { if (check(event)) {

View file

@ -9,9 +9,8 @@ export function randomUUID(): string {
return value.replace(/[018]/g, (character: string): string => return value.replace(/[018]/g, (character: string): string =>
( (
Number(character) ^ Number(character)
(crypto.getRandomValues(new Uint8Array(1))[0] & ^ (crypto.getRandomValues(new Uint8Array(1))[0]
(15 >> (Number(character) / 4))) & (15 >> (Number(character) / 4)))
).toString(16), ).toString(16));
);
} }

View file

@ -45,8 +45,8 @@ export function wrapInternal(
} }
if ( if (
wasCollapsed && wasCollapsed
/* ugly solution: treat <anki-mathjax> differently than other wraps */ !front.includes( /* ugly solution: treat <anki-mathjax> differently than other wraps */ && !front.includes(
"<anki-mathjax", "<anki-mathjax",
) )
) { ) {

View file

@ -19,18 +19,16 @@ export async function maybePreloadExternalCss(html: string): Promise<void> {
} }
function clearPreloadedCss(): void { function clearPreloadedCss(): void {
[...document.head.getElementsByClassName(preloadCssClassName)].forEach((css) => [...document.head.getElementsByClassName(preloadCssClassName)].forEach((css) => css.remove());
css.remove(),
);
} }
function extractExternalCssElements(fragment: DocumentFragment): CssElementType[] { function extractExternalCssElements(fragment: DocumentFragment): CssElementType[] {
return <CssElementType[]>( return <CssElementType[]> (
[...fragment.querySelectorAll("style, link")].filter( [...fragment.querySelectorAll("style, link")].filter(
(css) => (css) =>
(css instanceof HTMLStyleElement && (css instanceof HTMLStyleElement
css.innerHTML.includes("@import")) || && css.innerHTML.includes("@import"))
(css instanceof HTMLLinkElement && css.rel === "stylesheet"), || (css instanceof HTMLLinkElement && css.rel === "stylesheet"),
) )
); );
} }

View file

@ -1,7 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { Readable} from "svelte/store"; import type { Readable } from "svelte/store";
import { readable } from "svelte/store"; import { readable } from "svelte/store";
interface AsyncData<T, E> { interface AsyncData<T, E> {

View file

@ -31,7 +31,7 @@ function useAsyncReactive<T, E>(
const error = derived( const error = derived(
promise, promise,
($promise, set: (error: E | null) => void): (() => void) => { ($promise, set: (error: E | null) => void): () => void => {
$promise?.catch((error: E) => set(error)); $promise?.catch((error: E) => set(error));
return (): void => set(null); return (): void => set(null);
}, },
@ -40,7 +40,7 @@ function useAsyncReactive<T, E>(
const loading = derived( const loading = derived(
promise, promise,
($promise, set: (value: boolean) => void): (() => void) => { ($promise, set: (value: boolean) => void): () => void => {
$promise?.finally(() => set(false)); $promise?.finally(() => set(false));
return (): void => set(true); return (): void => set(true);
}, },

View file

@ -9,13 +9,12 @@ export interface DynamicSvelteComponent<
[k: string]: unknown; [k: string]: unknown;
} }
export const dynamicComponent = export const dynamicComponent = <
<
Comp extends typeof SvelteComponentDev, Comp extends typeof SvelteComponentDev,
DefaultProps = NonNullable<ConstructorParameters<Comp>[0]["props"]>, DefaultProps = NonNullable<ConstructorParameters<Comp>[0]["props"]>,
>( >(
component: Comp, component: Comp,
) => ) =>
<Props = DefaultProps>(props: Props): DynamicSvelteComponent<Comp> & Props => { <Props = DefaultProps>(props: Props): DynamicSvelteComponent<Comp> & Props => {
return { component, ...props }; return { component, ...props };
}; };

View file

@ -1,22 +1,8 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { import type { ComputePositionConfig, FloatingElement, Middleware, Placement, ReferenceElement } from "@floating-ui/dom";
ComputePositionConfig, import { arrow, computePosition, flip, hide, inline, offset, shift } from "@floating-ui/dom";
FloatingElement,
Middleware,
Placement,
ReferenceElement,
} from "@floating-ui/dom";
import {
arrow,
computePosition,
flip,
hide,
inline,
offset,
shift,
} from "@floating-ui/dom";
import type { PositionAlgorithm } from "./position-algorithm"; import type { PositionAlgorithm } from "./position-algorithm";
@ -41,7 +27,7 @@ function positionFloating({
hideIfReferenceHidden, hideIfReferenceHidden,
hideCallback, hideCallback,
}: PositionFloatingArgs): PositionAlgorithm { }: PositionFloatingArgs): PositionAlgorithm {
return async function ( return async function(
reference: ReferenceElement, reference: ReferenceElement,
floating: FloatingElement, floating: FloatingElement,
): Promise<void> { ): Promise<void> {

View file

@ -1,12 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { import type { ComputePositionConfig, FloatingElement, Middleware, ReferenceElement } from "@floating-ui/dom";
ComputePositionConfig,
FloatingElement,
Middleware,
ReferenceElement,
} from "@floating-ui/dom";
import { computePosition, inline, offset } from "@floating-ui/dom"; import { computePosition, inline, offset } from "@floating-ui/dom";
import type { PositionAlgorithm } from "./position-algorithm"; import type { PositionAlgorithm } from "./position-algorithm";
@ -22,7 +17,7 @@ function positionOverlay({
inline: inlineArg, inline: inlineArg,
hideCallback, hideCallback,
}: PositionOverlayArgs): PositionAlgorithm { }: PositionOverlayArgs): PositionAlgorithm {
return async function ( return async function(
reference: ReferenceElement, reference: ReferenceElement,
floating: FloatingElement, floating: FloatingElement,
): Promise<void> { ): Promise<void> {

View file

@ -1,7 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
import type { Writable} from "svelte/store"; import type { Writable } from "svelte/store";
import { get, writable } from "svelte/store"; import { get, writable } from "svelte/store";
export interface CustomStore<T> extends Writable<T> { export interface CustomStore<T> extends Writable<T> {
@ -61,9 +61,11 @@ function preparePreferences<T>(
setter(constructPreferences()); setter(constructPreferences());
} }
for (const [key, value] of Object.entries( for (
const [key, value] of Object.entries(
toObject(Preferences, { defaults: true }), toObject(Preferences, { defaults: true }),
)) { )
) {
preferences[key] = createPreference(value, savePreferences); preferences[key] = createPreference(value, savePreferences);
} }