Fallstudie * Electron

Wie Notion kopiert
text und HTML.

Verfolgen Sie einen Aufruf der Zwischenablage von der Seiten-API von Notion über den Preload- und den Hauptprozess zum Clipboard Writer von Electron.

Notion Arbeitsfläche 7.6.1 * JavaScript · REA

Die Brücke im Desktop-Paket des Notion

  1. 01 * Seitenseitige API clipboard.write(data) Das Preload macht eine aufrufbare Methode verfügbar.
  2. 02 * Wickler vorladen ipcRenderer.invoke Der Wrapper sendet den Kanal und die Argumente.
  3. 03 * Haupt-Prozess-Handler ipcMain.handle Der Empfänger überprüft, welche Seite es gesendet hat.
  4. 04 * System-Zwischenablage clipboard.write(data) Electron schreibt den mitgelieferten Text und HTML.

Ein Kanal verbindet die beiden Seiten: notion:clipboard:write

Der gepackte Code verwendet denselben Kanal im Preload- und im Hauptprozess. Beim Auflösen der Wrapper werden die Electron-Aufrufe hinter diesen Namen angezeigt.

Wohin geht der Kopiervorgang?

Die Seite sieht eine Methode namens clipboard.write. Seine Implementierung im Preload ist ein Wrapper. Die nützliche Frage ist, was dieser Wrapper sendet und welcher Code ihn empfängt.

Ihr Codierungsagent

Verwenden Sie REA, um zu verfolgen, wie Notion Text und HTML in die Systemzwischenablage kopiert. Zeigen Sie den Code bei jedem Schritt an.

Eine Beispiel-Eingabeaufforderung mit dem lokalen Anwendungspaket von Notion, das Ihrem Codierungsagenten zur Verfügung steht.

REA findet, wo mit dem Lesen begonnen werden soll

Die Analyse des Tab-Preloads mit REA lokalisiert die API, die für die Seite verfügbar ist, und den Aufruf, der eine IPC-Anforderung sendet. Beide Befunde werden mit Quellbereichen im minimierten Bündel geliefert:

REA Erkenntnisse → zwei Orte zum Öffnen

API für exponierte Seiten
api_key: "__electronApi"
api_status: "dynamic"
source: preload.js:1:22764–22828
Renderer-IPC-Aufruf
operation: "invoke"
channel_expression: "e"
source: preload.js:1:6486–6522
Ausgewählte Felder aus einer frischen analyze_javascript_application ergebnis auf der Registerkarte Vorspannung von Notion, aufgezeichnet mit REA 4.1.0. Positionen verwenden die Linie und die nullbasierte Spalte des ursprünglichen Bündels.

Der Agent öffnet diese Speicherorte, sucht das Mitglied der Zwischenablage in der zusammengestellten API und liest invokerInMain. Seine Call-Site liefert notion:clipboard:write. Dieser Name gibt dem Agenten etwas Genaues, nach dem er im Hauptpaket suchen kann. Die vier folgenden Auszüge zeigen die Route, die es verbindet.

Vier kurze Code-Stücke

Vereinfacht aus dem verpackten JavaScript mit lesbaren Variablennamen. Nicht verwandte Mitglieder werden weggelassen.

  1. Beginnen Sie bei der API, die der Seite angezeigt wird

    tab_browser_ansicht/preload.js * API-Mitglied
    const clipboardApi = {
      write: invokerInMain("notion:clipboard:write")
    };
    
    // Included in the API exposed through contextBridge:
    // window.__electronApi.clipboard

    Dieses Mitglied liefert den Kanalnamen. Die Umsetzung von invokerInMain sagt uns, wie die Anfrage den Prozess der Seite verlässt.

  2. Lösen Sie den Wrapper des Preloads auf

    tab_browser_ansicht/preload.js * IPC-Helfer
    function invokerInMain(channel) {
      return (...args) => invokeInMainAndReturnResult(channel, ...args);
    }
    
    function invokeInMainAndReturnResult(channel, ...args) {
      return ipcRenderer.invoke(channel, ...args);
    }

    Die zurückgegebene Funktion leitet die Argumente über den Anfrage- und Antwort-IPC von Electron weiter. Wir können jetzt suchen nach notion:clipboard:write auf der Hauptprozesseite.

  3. Überprüfen Sie, wie der Empfänger registriert ist

    Hauptindex.js * Handler-Helfer
    const handleRequestFromRenderer = {
      addListener(channel, handler) {
        ipcMain.handle(channel, handler);
      }
    };

    Der Hauptprozess verwendet einen anderen Wrapper. Seiner addListener methode registriert eine ipcMain.handle empfänger für diesen Kanal.

  4. Finden Sie den Schreib- und Absendercheck

    Hauptindex.js * Zwischenablage-Empfänger
    handleRequestFromRenderer.addListener(
      "notion:clipboard:write",
      (event, data) =>
        isNotionWebContents(event.sender)
          ? clipboard.write(data)
          : undefined
    );

    Dies ist das Ziel. Nach Überprüfung des Absenders übergibt der Handler die gelieferten Daten an die Zwischenablage-API von Electron. Der Kanal und die beiden aufgelösten Wrapper verbinden die exponierte Methode mit diesem Aufruf.

Wie behält ein kopierter Block seine Struktur bei?

Der Webeditor von Notion sendet Text und HTML durch electronApi.clipboard.write. Es speichert die Blockdaten lokal und fügt eine ID in den kopierten HTML-Code ein, um sie zu verbinden.

HTML-Links zu gespeicherten Blockdaten

An die Zwischenablage des Systems gesendet
text: "Project notes"
html: "<p>Project notes</p>"
    + "<!-- notionvc: <copy-id> -->"
Lokal gespeichert von Notion
id: <copy-id>
mimeTypes:
  text/_notion-blocks-v3-production
    → structured block data
  1. Lesen Sie die HTML-ID
  2. Finden Sie die gleiche lokale ID
  3. Wiederherstellen von Notion-Blockdaten
Illustrativer Text und ID. Der aufgezeichnete Modultest stellt die Blockdaten wieder her, wenn die IDs übereinstimmen. Ein veralteter Eintrag gibt nur Text und HTML zurück.

Beim Einfügen sucht Notion nach der HTML-ID und vergleicht sie mit der gespeicherten Kopie. Übereinstimmende IDs stellen die Blockdaten wieder her.

Format der Zwischenablage, aufgezeichnet aus Web-Assets, die am 13.Juli 2026 zwischengespeichert wurden.

Weitere Beispiele und Quellen

Ein weiteres Beispiel: Markdown-Tabellen

Notion analysiert Markdown in Blockdaten. Dieses Beispiel zeigt, wie aus einer Tabelle Kopf- und Datenzeilen werden.

Eine Tabelle durch den Markdown-Parser von Notion

Markdown-Eingabe
| A | B |
| - | - |
| 1 | 2 |
Strukturierte Parser-Ausgabe * Auszug
table · headerRow: true
  table_row
    cells: ["A"], ["B"]
  table_row
    cells: ["1"], ["2"]
Aufgezeichnete Ausgabe von einem extrahierten Markdown-Parser. Die Tabelle wird zu Zeilen und Zellen.
Ein anderer Pfad: die Offline-SQLite-Verbindung

Renderer-Anfragen von Notion getSqliteMeta durch IPC. Der Hauptprozess erstellt einen Nachrichtenkanal und gibt einen Port an den Renderer und den anderen an einen SQLite-Dienstprogrammprozess weiter. Nachfolgende Anweisungsstapel und Ergebnisse werden über diesen Port übertragen.

Im Anschluss an diese Übergabe wird erläutert, wo die Datenbankarbeit ausgeführt wird und warum bei der Verfolgung nur der anfänglichen IPC-Anforderung die spätere Konversation übersehen wird.

Quellen und wie man die Auszüge liest

Die Zwischenablage-Brücke stammt von Notion Desktop 7.6.1 app.asar: die Registerkarte Vorspannung und main/index.js. Die Auszüge erweitern minimierte Variablennamen und lassen nicht verwandten Code weg; Der Absenderprüfungs-Helfer wird mit seinem zugrunde liegenden angezeigt isNotionWebContents nennen.

Die Beispiele für virtuelle Zwischenablage und Markdown stammen aus Web-Assets, die am 13.Juli 2026 zwischengespeichert wurden, einschließlich Modulen 747001, 58169, 736810 und 422457. Diese Assets haben ihre eigene Version. Gespeicherte Sonden führten extrahierte Module und kleine Kabelbäume aus; Ihre Ausgaben beschreiben diese Sonden und nicht eine erfasste Desktop-UI-Sitzung.

Das hier gezeigte REA-Ergebnis ist eine fokussierte Analyse des gespeicherten Tab-Preloads, die mit dem veröffentlichten REA 4.1.0-Paket aufgezeichnet wurde. Es sucht die API und ruft die Operation auf. Das Clipboard-Mitglied und der passende Empfänger werden durch Lesen ihrer Wrapper-Implementierungen im Paket verbunden.

Das Markdown-Beispiel verwendet das Parser-Modul 422457. Gespeicherte Modultests zeigen, dass sowohl Seiten- als auch Chatfilter diese Tabelle beibehalten. Die Paste / Import-, Structured Markdown- und AI / Chat-Parser haben separate Einstiegspunkte und Zwischenformate.

Oberen