A partire da Chrome 120, è disponibile una nuova opzione unsanitized
negli appunti asincroni
tramite Google Cloud CLI
o tramite l'API Compute Engine. Questa opzione può essere utile in situazioni speciali con HTML, dove è necessario
incollare i contenuti degli appunti identici a come erano quando sono stati copiati.
Vale a dire, senza alcun passaggio intermedio di sanificazione comunemente utilizzato dai browser,
per validi motivi, fai domanda. Scopri come utilizzarlo in questa guida.
Quando utilizzi API Async Clipboard, nella maggior parte dei casi, gli sviluppatori non devono preoccuparsi dell'integrità i contenuti negli appunti e possiamo presumere che ciò che scrivono nella Appunti (copia) è lo stesso di quello che riceveranno quando legge i dati da negli appunti (da incollare).
Questo è decisamente vero per i testi. Prova a incollare il seguente codice in DevTools
e rimettere a fuoco la pagina immediatamente. (setTimeout()
è necessario
in modo da avere tempo sufficiente per impostare lo stato attivo sulla pagina, come richiesto dal modello
API Clipboard). Come puoi vedere, l'input è esattamente uguale all'output.
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);
Con le immagini, è un po' diverso. Per evitare le cosiddette attacchi di bomba di compressione, browser ricodificare immagini come i file PNG, ma le immagini di input e di output sono visivamente esattamente la stessa, pixel per pixel.
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);
Cosa succede con il testo HTML? Come avrai intuito, con l'HTML,
la situazione è diversa. In questo caso, il browser ripulisce il codice HTML per evitare
cose da accadere, ad esempio eliminando i tag <script>
dal codice HTML
(e altri come <meta>
, <head>
e <style>
) e incorporare il codice CSS.
Considera l'esempio seguente e provalo nella console DevTools. Potrai
puoi notare che l'output differisce molto notevolmente dall'input.
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);
La sanificazione HTML in genere è un aspetto positivo. Non vuoi esporti ai problemi di sicurezza, consentendo nella maggior parte dei casi HTML non sottoposto a sanitizzazione. Là sono scenari in cui lo sviluppatore sa esattamente cosa sta facendo e in cui l'integrità dell'HTML in-stream e di output è fondamentale per la il funzionamento dell'app. In queste circostanze, hai due opzioni:
- Se hai il controllo sia di copiare che di incollare, ad esempio, dall'interno dell'app per incollarla all'interno dell'app, devi usare Formati personalizzati web per l'API Async Clipboard. Smetti di leggere qui e controlla l'articolo collegato.
- Se sei tu a controllare solo l'estremità di incollare nell'app, ma non quella di copia,
ad esempio perché l'operazione di copia viene eseguita in un'app nativa che non supporta
formati personalizzati per il web, devi utilizzare l'opzione
unsanitized
, che spiegati nel resto di questo articolo.
La sanificazione include, ad esempio, la rimozione di tag script
, l'allineamento degli stili e
verificando che l'HTML sia formattato correttamente. Questo elenco non è esaustivo e altro ancora
potrebbero essere aggiunti in futuro.
Copia e incolla HTML non convalidato
Quando write()
(copi) il codice HTML negli appunti con l'API Async Clipboard,
il browser si assicura che sia nel formato corretto eseguendolo attraverso un parser DOM
e serializzare la stringa HTML risultante, ma non viene eseguita alcuna sanificazione
questo passaggio. Non devi fare nulla. Quando read()
inserisci il codice HTML nella
appunti da un'altra applicazione e la tua app web sta accettando il
ad alta fedeltà e la necessità di eseguire la sanificazione nel tuo codice,
puoi passare un oggetto opzioni al metodo read()
con una proprietà
unsanitized
e il valore ['text/html']
. In sostanza, ha il seguente aspetto:
navigator.clipboard.read({ unsanitized: ['text/html'] })
. Il seguente esempio di codice
di seguito è quasi uguale a quella mostrata in precedenza, ma questa volta con l'unsanitized
. Quando lo provi nella console DevTools, vedrai che l'input e
l'output è lo stesso.
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);
Supporto dei browser e rilevamento delle funzionalità
Non esiste un modo diretto per verificare se la funzionalità è supportata, quindi la funzionalità
il rilevamento si basa sull'osservazione del comportamento. Di conseguenza, il seguente esempio
si basa sul rilevamento della persistenza di un tag <style>
, che
indica supporto, o è in linea, indica che non è supportato. Tieni presente che
perché funzioni, la pagina deve avere già ottenuto gli appunti
autorizzazione.
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);
};
Demo
Per vedere l'opzione unsanitized
in azione, consulta le
di Google su Glitch e dai un'occhiata
codice sorgente.
Conclusioni
Come descritto nell'introduzione, la maggior parte degli sviluppatori non dovrà mai preoccuparsi
la sanificazione degli appunti e può funzionare solo con le opzioni di sanificazione predefinite
dal browser. Nei rari casi in cui gli sviluppatori devono prestare attenzione,
L'opzione unsanitized
esiste.
Link utili
Ringraziamenti
Questo articolo è stato esaminato da Anupam Snigdha e Rachel Andrew. L'API è stata specificata e implementato dal team di Microsoft Edge.