Nicht bereinigter HTML-Code in der Async Clipboard API

Ab Chrome 120 ist in der asynchronen Zwischenablage eine neue unsanitized-Option verfügbar der API erstellen. Diese Option kann in besonderen Situationen mit HTML hilfreich sein, in denen Sie fügen Sie den Inhalt der Zwischenablage genauso ein, wie er beim Kopieren war. Das heißt, ohne einen zwischengeschalteten Bereinigungsschritt, den Browser üblicherweise – und – bewerben Sie sich. In diesem Leitfaden erfahren Sie, wie Sie das Tool verwenden.

Wenn Sie mit dem Async Clipboard API In den meisten Fällen müssen sich Entwickler nicht um die Integrität der Inhalt in der Zwischenablage und kann davon ausgehen, dass das, was in die Zwischenablage geschrieben wird, Die Zwischenablage (kopieren) ist dieselbe wie die, die sie erhalten, wenn sie die Daten auslesen. in die Zwischenablage einfügen.

Das gilt definitiv für Text. Versuche, den folgenden Code in die Entwicklertools einzufügen Konsole und dann sofort den Fokus auf der Seite neu. (Der setTimeout() ist erforderlich, damit Sie genug Zeit haben, sich auf die Seite zu konzentrieren. Dies ist eine Voraussetzung für Clipboard API.) Die Eingabe ist also genau die gleiche wie die Ausgabe.

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);

Bei Bildern ist das etwas anders. Um sogenannte Compression Bomb-Angriffe, Browser Bilder wie PNGs neu codieren, aber die Eingabe- und Ausgabebilder sind visuell genau gleich, also Pixel pro 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);

Was passiert jedoch mit HTML-Text? Wie Sie vielleicht schon vermutet haben, ist eine andere Situation. Hier wird der HTML-Code vom Browser bereinigt, um ungültige z. B. durch Entfernen von <script>-Tags aus dem HTML-Code (und andere wie <meta>, <head> und <style>) sowie durch Inline-CSS-Code. Betrachten Sie das folgende Beispiel und probieren Sie es in der Entwicklertools-Konsole aus. Sie werden sehen Sie, dass sich die Ausgabe erheblich von der Eingabe unterscheidet.

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);

HTML-Bereinigung ist im Allgemeinen eine gute Sache. Sie möchten nicht, dass Sie indem wir unbereinigtes HTML in den meisten Fällen zulassen. Es aber es sind Szenarien, in denen der Entwickler genau weiß, was er tut bei denen die Integrität des Ein- und Ausgabe-HTML-Codes für die korrekte der App funktioniert. Unter diesen Umständen haben Sie zwei Möglichkeiten:

  1. Wenn Sie sowohl das Kopieren als auch das Einfügen steuern und beispielsweise aus Ihrer App heraus, um diese dann ebenfalls einzufügen, verwenden Sie Benutzerdefinierte Webformate für die Async Clipboard API Lies hier nichts weiter und sieh dir den verlinkten Artikel an.
  2. Wenn Sie nur das Ende des Einfügens in Ihrer App festlegen, nicht aber das Ende des Kopiervorgangs, weil der Kopiervorgang in einer nativen App stattfindet, benutzerdefinierten Webformaten verwenden, sollten Sie die Option unsanitized verwenden. Weitere Informationen zu diesem Thema erhalten Sie weiter unten in diesem Artikel.

Die Bereinigung umfasst unter anderem das Entfernen von script-Tags, Inline-Stile und Sie überprüfen, ob der HTML-Code korrekt formatiert ist. Diese Liste ist nicht umfassend weitere Schritte hinzugefügt werden.

Unbereinigten HTML-Code kopieren und einfügen

Wenn Sie HTML mit der Async Clipboard API mit write() in die Zwischenablage kopieren (kopieren), stellt der Browser sicher, dass er korrekt formatiert ist, indem er ihn über einen DOM-Parser ausführt. und serialisiert den resultierenden HTML-String, aber es findet keine Bereinigung statt. für diesen Schritt. Sie müssen nichts weiter tun. Wenn Sie read() HTML-Code auf der in die Zwischenablage kopiert und Ihre Webanwendung aktiviert hat, und die Bereinigung in Ihrem eigenen Code vornehmen müssen, können Sie ein Optionsobjekt mit einem Attribut an die Methode read() übergeben. unsanitized und den Wert ['text/html']. Isoliert sieht das so aus: navigator.clipboard.read({ unsanitized: ['text/html'] }) Im folgenden Codebeispiel wird unten ist fast identisch mit dem zuvor gezeigten, dieses Mal jedoch mit unsanitized Option. Wenn Sie es in der Entwicklertools-Konsole testen, sehen Sie, dass die Eingabe und die Ausgabe ist gleich.

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);

Browserunterstützung und Funktionserkennung

Es gibt keine direkte Möglichkeit, zu prüfen, ob die Funktion unterstützt wird. auf der Beobachtung des Verhaltens basiert. Daher entspricht das folgende Beispiel hängt davon ab, ob ein <style>-Tag weiterhin besteht, was steht für Support oder wird inline eingefügt, d. h., es wird kein Support angeboten. Beachten Sie, dass Damit das funktioniert, muss die Seite bereits die Zwischenablage abrufen Berechtigung.

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

Informationen zur Option unsanitized in Aktion finden Sie in der Demo zu Glitch ansehen und die Quellcode.

Ergebnisse

Wie in der Einführung erwähnt, müssen sich die meisten Entwickler Bereinigung der Zwischenablage. Kann einfach mit den Standardoptionen zur Bereinigung verwendet werden. durch den Browser. In den seltenen Fällen, in denen Entwickler etwas tun müssen, unsanitized Option ist vorhanden.

Danksagungen

Dieser Artikel wurde von Anupam Snigdha geprüft und Rachel Andrew: Die API wurde angegeben und Microsoft Edge-Team implementiert.