À partir de Chrome 120, une nouvelle option unsanitized
est disponible dans le presse-papiers asynchrone
API. Cette option peut être utile dans certaines situations spéciales avec HTML, où vous devez
collez le contenu du presse-papiers de la même façon qu'au moment de la copie.
C'est-à-dire, sans étape de nettoyage intermédiaire que les navigateurs
pour de bonnes raisons : postulez. Découvrez comment l'utiliser dans ce guide.
Lorsque vous travaillez avec API Async Clipboard dans la majorité des cas, les développeurs n'ont pas à se soucier de l'intégrité le contenu du presse-papiers et peut supposer que ce qu'ils écrivent sur le presse-papiers (copie) est identique à celle obtenue en lire les données depuis le presse-papiers (coller).
C'est sans aucun doute le cas pour le texte. Essayez de coller le code suivant dans les outils de développement
dans la console, puis recentrez immédiatement la page. (Le setTimeout()
est nécessaire
Vous disposez ainsi de suffisamment de temps pour vous concentrer sur la page, ce qui est l'une des exigences
API Clipboard). Comme vous pouvez le voir, l'entrée est exactement la même que la sortie.
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);
Avec les images, c'est un peu différent. Pour empêcher ce que l'on appelle les attaques par bombe de compression, les navigateurs réencodez des images comme au format PNG, mais les images d'entrée et de sortie sont visuellement exactement la même chose, pixel par 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);
Mais qu'en est-il du texte HTML ? Comme vous l'avez peut-être deviné, avec le langage HTML,
la situation est différente. Ici, le navigateur nettoie le code HTML pour éviter
en supprimant les balises <script>
du code HTML, par exemple.
(et d'autres éléments comme <meta>
, <head>
et <style>
) et en intégrant le CSS.
Examinez l'exemple suivant et essayez-le dans la console des outils de développement. Vous :
notez que la sortie diffère
très nettement de l'entrée.
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);
Le nettoyage HTML est généralement une bonne chose. Vous ne devez pas vous exposer aux problèmes de sécurité en autorisant le HTML non rectifié dans la majorité des cas. Il y sont des scénarios dans lesquels le développeur sait exactement ce qu'il fait et où l'intégrité du code HTML de l'entrée et de la sortie est cruciale le fonctionnement de l’application. Dans ce cas, deux possibilités s'offrent à vous:
- Si vous contrôlez à la fois la copie et le collage (par exemple, si vous copiez depuis votre application pour les coller dans celle-ci, vous devez utiliser Formats Web personnalisés pour l'API Async Clipboard Arrêtez la lecture et consultez l'article associé.
- Si vous contrôlez uniquement le collage dans votre application,
peut-être parce que l'opération de copie a lieu dans une application native qui n'est pas
des formats personnalisés pour le Web, vous devez utiliser l'option
unsanitized
, qui est expliqué dans la suite de cet article.
L'assainissement inclut, par exemple, la suppression des balises script
, l'intégration de styles et
de s'assurer que le code HTML
est bien formé. Cette liste n'est pas exhaustive, et bien d'autres
des étapes peuvent être ajoutées ultérieurement.
Copier et coller du code HTML non rectifié
Lorsque vous write()
(copiez) du code HTML dans le presse-papiers avec l'API Async Clipboard,
le navigateur s'assure qu'il est correctement formé en l'exécutant via un analyseur DOM
et de sérialiser la chaîne HTML obtenue, mais aucun nettoyage n'a lieu au niveau
cette étape. Vous n'avez rien à faire. Lorsque vous read()
avez placé du code HTML
presse-papiers par une autre application, et votre application Web active la fonction
contenu ultraprécis et la nécessité de nettoyer votre propre code,
vous pouvez transmettre un objet d'options à la méthode read()
avec une propriété
unsanitized
et la valeur ['text/html']
. Indépendamment, il se présente comme suit:
navigator.clipboard.read({ unsanitized: ['text/html'] })
L'exemple de code suivant
ci-dessous est presque identique à celle présentée précédemment, mais cette fois avec unsanitized
. Lorsque vous l'essayerez dans la console DevTools, vous constaterez que l'entrée et
la sortie est la même.
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);
Prise en charge des navigateurs et détection de fonctionnalités
Il n'existe aucun moyen direct de vérifier si la fonctionnalité est prise en charge.
la détection repose sur l'observation du comportement. Par conséquent, l'exemple suivant
repose sur la détection de la présence ou non d'une balise <style>
, ce qui
indique une compatibilité ou est en cours d'intégration, ce qui indique qu'il n'y a pas de support. Notez que
Pour que cela fonctionne, la page doit déjà avoir obtenu le presse-papiers
l'autorisation.
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);
};
Démo
Pour voir comment l'option unsanitized
fonctionne, consultez la
sur Glitch et regardez sa
code source.
Conclusions
Comme indiqué dans l'introduction, la plupart des développeurs n'auront jamais à se soucier
le nettoyage du presse-papiers et ne peut fonctionner qu'avec les options de nettoyage par défaut.
effectuées par le navigateur. Dans les rares cas où les développeurs doivent se soucier,
L'option unsanitized
existe.
Liens utiles
Remerciements
Cet article a été lu par Anupam Snigdha et Rachel Andrew. L'API a été spécifiée, par l'équipe Microsoft Edge.