Od Chrome 120 w schowku asynchronicznym dostępna jest nowa opcja unsanitized
API. Ta opcja może być pomocna w szczególnych sytuacjach związanych z kodem HTML, kiedy trzeba
wklejenie zawartości schowka w taki sam sposób, jak w momencie jej kopiowania.
Oznacza to, że bez żadnego pośredniego etapu dezynfekcji, który jest często używany przez przeglądarki –
z ważnych powodów – zgłoś się. Z tego przewodnika dowiesz się, jak jej używać.
Podczas pracy z Async Clipboard API, w większości przypadków deweloperzy nie muszą martwić się o integralność zawartość schowka i może założyć, że to, co zapisze, schowek (kopia) to ten sam element, z którego otrzymają odczyt danych ze schowka (wklej).
Zdecydowanie dotyczy to także tekstu. Spróbuj wkleić ten kod w Narzędziach deweloperskich
Konsola, a następnie natychmiast zmień ostrość strony. (setTimeout()
jest wymagany
więc masz wystarczająco dużo czasu na skupienie się na stronie, co jest wymagane przez
Clipboard API). Jak widać, dane wejściowe są dokładnie takie same jak dane wyjściowe.
setTimeout(async () => {
const input = 'Hello';
await navigator.clipboard.writeText(input);
const output = await navigator.clipboard.readText();
console.log(input, output, input === output);
// Logs "Hello Hello true".
}, 3000);
Z obrazami wygląda to trochę inaczej. Aby temu zapobiec ataki bombami kompresyjnymi, przeglądarki, ponownie kodować obrazy, takie jak PNG, ale obrazy wejściowe i wyjściowe są wizualne dokładnie tyle samo, ile pikseli na piksel.
setTimeout(async () => {
const dataURL =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=';
const input = await fetch(dataURL).then((response) => response.blob());
await navigator.clipboard.write([
new ClipboardItem({
[input.type]: input,
}),
]);
const [clipboardItem] = await navigator.clipboard.read();
const output = await clipboardItem.getType(input.type);
console.log(input.size, output.size, input.type === output.type);
// Logs "68 161 true".
}, 3000);
Co jednak się stanie z tekstem HTML? Jak można się domyślić, w języku HTML
jest jednak inna. W tym przypadku przeglądarka oczyszcza kod HTML,
na przykład przez usunięcie tagów <script>
z kodu HTML
(i inne, takie jak <meta>
, <head>
i <style>
) oraz przez wstawienie CSS.
Zapoznaj się z podanym niżej przykładem i wypróbuj go w konsoli Narzędzi deweloperskich. Ty
dane wyjściowe znacznie różnią się od danych wejściowych.
setTimeout(async () => {
const input = `<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="ProgId" content="Excel.Sheet" />
<meta name="Generator" content="Microsoft Excel 15" />
<style>
body {
font-family: HK Grotesk;
background-color: var(--color-bg);
}
</style>
</head>
<body>
<div>hello</div>
</body>
</html>`;
const inputBlob = new Blob([input], { type: 'text/html' });
await navigator.clipboard.write([
new ClipboardItem({
'text/html': inputBlob,
}),
]);
const [clipboardItem] = await navigator.clipboard.read();
const outputBlob = await clipboardItem.getType('text/html');
const output = await outputBlob.text();
console.log(input, output);
}, 3000);
Proces oczyszczania kodu HTML jest zwykle bardzo dobry. Nie chcesz się ujawniać na problemy z bezpieczeństwem, zezwalając w większości przypadków na nieoczyszczony kod HTML. OK są scenariuszy, w których programista dokładnie wie, co robi, w których integralność kodu HTML (wejściowego i wyjściowego) jest kluczowa funkcji aplikacji. W takiej sytuacji masz dwie możliwości:
- Jeśli kontrolujesz zarówno koniec kopiowania, jak i wklejania, na przykład jeśli kopiujesz a następnie wklejanie w aplikacji, użyj Niestandardowe formaty internetowe dla interfejsu Async Clipboard API. Przestań go czytać i skorzystaj z linku do artykułu.
- Jeśli masz kontrolę tylko nad końcem wklejania w aplikacji, ale nie na końcu kopiowania,
może to wynikać z faktu, że operacja kopiowania odbywa się w aplikacji natywnej, która nie obsługuje
niestandardowych formatów reklam internetowych, użyj opcji
unsanitized
, która jest co wyjaśniamy w dalszej części tego artykułu.
Proces oczyszczania obejmuje m.in. usunięcie tagów script
, stylów wkładek i
w celu zadbania o prawidłowy format kodu HTML. Ta lista jest niekompletna i zawiera inne informacje
kroki można dodać w przyszłości.
Kopiowanie i wklejanie nieoczyszczonego kodu HTML
Gdy write()
(skopiujesz) kod HTML do schowka za pomocą interfejsu Async Clipboard API,
przeglądarka sprawdza poprawność składni, uruchamiając ją za pomocą parsera DOM.
i serializacji wynikowego ciągu HTML, ale oczyszczanie nie jest przeprowadzane
ten krok. Nie musisz nic robić. Gdy umieścisz kod HTML w sekcji read()
do schowka przez inną aplikację, a aplikacja internetowa włącza pobieranie
czyli dbałości o wysoką jakość treści
i nie musisz przeprowadzać procesu dezynfekcji we własnym kodzie.
możesz przekazać do metody read()
obiekt opcji z właściwością
unsanitized
i wartości ['text/html']
. W izolacji wygląda to tak:
navigator.clipboard.read({ unsanitized: ['text/html'] })
Następujący przykładowy kod
poniżej jest prawie taki sam jak pokazany wcześniej, ale tym razem z unsanitized
. Po wypróbowaniu tej funkcji w konsoli Narzędzi deweloperskich zobaczysz, że dane wejściowe
dane wyjściowe są takie same.
setTimeout(async () => {
const input = `<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="ProgId" content="Excel.Sheet" />
<meta name="Generator" content="Microsoft Excel 15" />
<style>
body {
font-family: HK Grotesk;
background-color: var(--color-bg);
}
</style>
</head>
<body>
<div>hello</div>
</body>
</html>`;
const inputBlob = new Blob([input], { type: 'text/html' });
await navigator.clipboard.write([
new ClipboardItem({
'text/html': inputBlob,
}),
]);
const [clipboardItem] = await navigator.clipboard.read({
unsanitized: ['text/html'],
});
const outputBlob = await clipboardItem.getType('text/html');
const output = await outputBlob.text();
console.log(input, output);
}, 3000);
Obsługa przeglądarek i wykrywanie funkcji
Nie można bezpośrednio sprawdzić, czy dana funkcja jest obsługiwana,
jest oparta na obserwacjach zachowań. W związku z tym w przykładzie poniżej
opiera się na wykrywaniu faktu, czy tag <style>
przetrwa, który
wskazuje wsparcie lub jest w tekście, co oznacza brak obsługi. Pamiętaj, że
aby to zadziałało, strona musi już mieć dostęp do schowka
uprawnienia.
const supportsUnsanitized = async () => {
const input = `<style>p{color:red}</style><p>a`;
const inputBlob = new Blob([input], { type: 'text/html' });
await navigator.clipboard.write([
new ClipboardItem({
'text/html': inputBlob,
}),
]);
const [clipboardItem] = await navigator.clipboard.read({
unsanitized: ['text/html],
});
const outputBlob = await clipboardItem.getType('text/html');
const output = await outputBlob.text();
return /<style>/.test(output);
};
Prezentacja
Aby zobaczyć, jak działa opcja unsanitized
, zapoznaj się z
demonstracja usługi Glitch i zobacz
kodu źródłowego.
Podsumowanie
Zgodnie z wprowadzeniem większość deweloperów nie będzie musiała martwić się o to,
oczyszczania schowka i może działać tylko z domyślnymi opcjami dezynfekcji
przez przeglądarkę. W rzadkich przypadkach, gdy deweloperzy muszą mieć na to uwagę,
Opcja unsanitized
istnieje.
Przydatne linki
Podziękowania
Ten artykuł zweryfikował Anupam Snigdha i Rachel Andrew Określono interfejs API i wdrożony przez zespół Microsoft Edge.