mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 00:36:38 -04:00
Preserve background-color when pasting external content in light mode
Closes #1964
This commit is contained in:
parent
92171e25e6
commit
0809812c1d
2 changed files with 71 additions and 53 deletions
|
@ -9,4 +9,35 @@ describe("filterHTML", () => {
|
||||||
expect(filterHTML("", true, false)).toBe("");
|
expect(filterHTML("", true, false)).toBe("");
|
||||||
expect(filterHTML("", false, false)).toBe("");
|
expect(filterHTML("", false, false)).toBe("");
|
||||||
});
|
});
|
||||||
|
test("internal filtering", () => {
|
||||||
|
// font-size is filtered, weight is not
|
||||||
|
expect(
|
||||||
|
filterHTML(
|
||||||
|
'<div style="font-weight: bold; font-size: 10px;"></div>',
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
).toBe('<div style="font-weight: bold;"></div>');
|
||||||
|
});
|
||||||
|
test("background color", () => {
|
||||||
|
// transparent is stripped, other colors are not
|
||||||
|
expect(
|
||||||
|
filterHTML(
|
||||||
|
'<span style="background-color: transparent;"></span>',
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
),
|
||||||
|
).toBe('<span style=""></span>');
|
||||||
|
expect(
|
||||||
|
filterHTML('<span style="background-color: blue;"></span>', false, true),
|
||||||
|
).toBe('<span style="background-color: blue;"></span>');
|
||||||
|
// except if extended mode is off
|
||||||
|
expect(
|
||||||
|
filterHTML('<span style="background-color: blue;">x</span>', false, false),
|
||||||
|
).toBe("x");
|
||||||
|
// or if it's an internal paste
|
||||||
|
expect(
|
||||||
|
filterHTML('<span style="background-color: blue;"></span>', true, true),
|
||||||
|
).toBe('<span style=""></span>');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,63 +1,50 @@
|
||||||
// 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
|
||||||
|
|
||||||
interface AllowPropertiesBlockValues {
|
/// Keep property if true.
|
||||||
[property: string]: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
type BlockProperties = string[];
|
|
||||||
|
|
||||||
type StylingPredicate = (property: string, value: string) => boolean;
|
type StylingPredicate = (property: string, value: string) => boolean;
|
||||||
|
|
||||||
const stylingNightMode: AllowPropertiesBlockValues = {
|
const keep = (_key: string, _value: string) => true;
|
||||||
"font-weight": [],
|
const discard = (_key: string, _value: string) => false;
|
||||||
"font-style": [],
|
|
||||||
"text-decoration-line": [],
|
|
||||||
};
|
|
||||||
|
|
||||||
const stylingLightMode: AllowPropertiesBlockValues = {
|
/// Return a function that filters out certain styles.
|
||||||
color: [],
|
/// - If the style is listed in `exceptions`, the provided predicate is used.
|
||||||
"background-color": ["transparent"],
|
/// - If the style is not listed, the default predicate is used instead.
|
||||||
...stylingNightMode,
|
function filterStyling(
|
||||||
};
|
defaultPredicate: StylingPredicate,
|
||||||
|
exceptions: Record<string, StylingPredicate>,
|
||||||
const stylingInternal: BlockProperties = [
|
): (element: HTMLElement) => void {
|
||||||
"background-color",
|
return (element: HTMLElement): void => {
|
||||||
"font-size",
|
// jsdom does not support @@iterator, so manually iterate
|
||||||
"font-family",
|
for (let i = 0; i < element.style.length; i++) {
|
||||||
"width",
|
const key = element.style.item(i);
|
||||||
"height",
|
const value = element.style.getPropertyValue(key);
|
||||||
"max-width",
|
const predicate = exceptions[key] ?? defaultPredicate;
|
||||||
"max-height",
|
if (!predicate(key, value)) {
|
||||||
];
|
element.style.removeProperty(key);
|
||||||
|
|
||||||
const allowPropertiesBlockValues =
|
|
||||||
(allowBlock: AllowPropertiesBlockValues): StylingPredicate =>
|
|
||||||
(property: string, value: string): boolean =>
|
|
||||||
Object.prototype.hasOwnProperty.call(allowBlock, property) &&
|
|
||||||
!allowBlock[property].includes(value);
|
|
||||||
|
|
||||||
const blockProperties =
|
|
||||||
(block: BlockProperties): StylingPredicate =>
|
|
||||||
(property: string): boolean =>
|
|
||||||
!block.includes(property);
|
|
||||||
|
|
||||||
const filterStyling =
|
|
||||||
(predicate: (property: string, value: string) => boolean) =>
|
|
||||||
(element: HTMLElement): void => {
|
|
||||||
for (const property of [...element.style]) {
|
|
||||||
const value = element.style.getPropertyValue(property);
|
|
||||||
|
|
||||||
if (!predicate(property, value)) {
|
|
||||||
element.style.removeProperty(property);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export const filterStylingNightMode = filterStyling(
|
const nightModeExceptions = {
|
||||||
allowPropertiesBlockValues(stylingNightMode),
|
"font-weight": keep,
|
||||||
);
|
"font-style": keep,
|
||||||
export const filterStylingLightMode = filterStyling(
|
"text-decoration-line": keep,
|
||||||
allowPropertiesBlockValues(stylingLightMode),
|
};
|
||||||
);
|
|
||||||
export const filterStylingInternal = filterStyling(blockProperties(stylingInternal));
|
export const filterStylingNightMode = filterStyling(discard, nightModeExceptions);
|
||||||
|
export const filterStylingLightMode = filterStyling(discard, {
|
||||||
|
color: keep,
|
||||||
|
"background-color": (_key: string, value: string) => value != "transparent",
|
||||||
|
...nightModeExceptions,
|
||||||
|
});
|
||||||
|
export const filterStylingInternal = filterStyling(keep, {
|
||||||
|
"background-color": discard,
|
||||||
|
"font-size": discard,
|
||||||
|
"font-family": discard,
|
||||||
|
width: discard,
|
||||||
|
height: discard,
|
||||||
|
"max-width": discard,
|
||||||
|
"max-height": discard,
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue