Étude de cas · Electron

Comment se copie Notion
texte et HTML.

Tracez un appel de presse-papiers depuis l'API de page de Notion, via le préchargement et le processus principal, vers le rédacteur de presse-papiers de Electron.

Notion Bureau 7.6.1 · JavaScript · REA

Le pont à l'intérieur du package de bureau de Notion

  1. 01 * API orientée page clipboard.write(data) Le préchargement expose une méthode appelable.
  2. 02 * Emballage de précharge ipcRenderer.invoke Le wrapper envoie le canal et les arguments.
  3. 03 * Gestionnaire de processus principal ipcMain.handle Le destinataire vérifie quelle page l'a envoyé.
  4. 04 * Presse-papiers du système clipboard.write(data) Electron écrit le texte et le code HTML fournis.

Un canal relie les deux côtés: notion:clipboard:write

Le code empaqueté utilise le même canal dans le préchargement et le processus principal. La résolution des wrappers révèle les appels Electron derrière ces noms.

Où va l'opération de copie?

La page voit une méthode appelée clipboard.write. Son implémentation dans la précharge est un wrapper. La question utile est de savoir ce que ce wrapper envoie et quel code le reçoit.

Votre agent de codage

Utilisez REA pour déterminer comment Notion copie du texte et du code HTML dans le presse-papiers du système. Affichez le code à chaque étape.

Un exemple d'invite avec le package d'application local de Notion disponible pour votre agent de codage.

REA trouve par où commencer la lecture

L'analyse du préchargement de l'onglet avec REA localise l'API exposée à la page et l'appel qui envoie une requête IPC. Les deux résultats sont fournis avec des plages de sources dans le bundle minifié:

Résultats REA → deux endroits pour ouvrir

API de page exposée
api_key: "__electronApi"
api_status: "dynamic"
source: preload.js:1:22764–22828
Appel IPC du moteur de rendu
operation: "invoke"
channel_expression: "e"
source: preload.js:1:6486–6522
Champs sélectionnés à partir d'un nouveau analyze_javascript_application résultat sur la précharge de l'onglet de Notion, enregistré avec REA 4.1.0. Les positions utilisent la ligne et la colonne de base zéro du bundle d'origine.

L'agent ouvre ces emplacements, trouve le membre du presse-papiers dans l'API assemblée et lit invokerInMain. Son site d'appel approvisionne notion:clipboard:write. Ce nom donne à l'agent quelque chose de précis à rechercher dans le paquet principal. Les quatre extraits ci-dessous montrent l'itinéraire qu'il relie.

Quatre courts morceaux de code

Simplifié à partir du JavaScript emballé, avec des noms de variables lisibles. Les membres non apparentés sont omis.

  1. Commencez par l'API exposée à la page

    affichage des onglets/preload.js * Membre de l'API
    const clipboardApi = {
      write: invokerInMain("notion:clipboard:write")
    };
    
    // Included in the API exposed through contextBridge:
    // window.__electronApi.clipboard

    Ce membre fournit le nom du canal. La mise en œuvre de invokerInMain nous indique comment la demande quitte le processus de la page.

  2. Résoudre le wrapper de la précharge

    affichage des onglets/preload.js * Assistant IPC
    function invokerInMain(channel) {
      return (...args) => invokeInMainAndReturnResult(channel, ...args);
    }
    
    function invokeInMainAndReturnResult(channel, ...args) {
      return ipcRenderer.invoke(channel, ...args);
    }

    La fonction renvoyée transmet les arguments via l'IPC de requête et de réponse de Electron. Nous pouvons maintenant chercher notion:clipboard:write du côté du processus principal.

  3. Vérifiez comment le destinataire est enregistré

    principale/index.js * aide-manutentionnaire
    const handleRequestFromRenderer = {
      addListener(channel, handler) {
        ipcMain.handle(channel, handler);
      }
    };

    Le processus principal utilise un autre wrapper. Ses addListener la méthode enregistre un ipcMain.handle récepteur pour ce canal.

  4. Trouver l'écriture et sa vérification de l'expéditeur

    principale/index.js * récepteur de presse-papiers
    handleRequestFromRenderer.addListener(
      "notion:clipboard:write",
      (event, data) =>
        isNotionWebContents(event.sender)
          ? clipboard.write(data)
          : undefined
    );

    C'est la destination. Après avoir vérifié l'expéditeur, le gestionnaire transmet les données fournies à l'API du presse-papiers de Electron. Le canal et les deux wrappers résolus connectent la méthode exposée à cet appel.

Comment un bloc copié conserve-t-il sa structure?

L'éditeur Web de Notion envoie du texte et du HTML via electronApi.clipboard.write. Il conserve les données de bloc localement et place un identifiant dans le code HTML copié pour les connecter.

Liens HTML vers les données de bloc enregistrées

Envoyé au presse-papiers du système
text: "Project notes"
html: "<p>Project notes</p>"
    + "<!-- notionvc: <copy-id> -->"
Enregistré localement par Notion
id: <copy-id>
mimeTypes:
  text/_notion-blocks-v3-production
    → structured block data
  1. Lire l'identifiant HTML
  2. Trouver le même identifiant local
  3. Restaurer les données de bloc Notion
Texte illustratif et identifiant. Le test de module enregistré restaure les données de bloc lorsque les identifiants correspondent; une entrée périmée ne renvoie que du texte et du HTML.

Lors du collage, Notion recherche l'ID HTML et le compare à la copie enregistrée. Les identifiants correspondants restaurent les données de bloc.

Format du presse-papiers enregistré à partir des ressources Web mises en cache le 13 juillet 2026.

Plus d'exemples et de sources

Un autre exemple: les tables de démarques

Notion analyse la démarque en données de bloc. Cet exemple montre comment une table devient des lignes d'en-tête et de données.

Un tableau via l'analyseur de démarque de Notion

Entrée de démarque
| A | B |
| - | - |
| 1 | 2 |
Sortie de l'analyseur structuré * extrait
table · headerRow: true
  table_row
    cells: ["A"], ["B"]
  table_row
    cells: ["1"], ["2"]
Sortie enregistrée à partir d'un analyseur Markdown extrait. Le tableau devient des lignes et des cellules.
Un autre chemin: la connexion SQLite hors ligne

Requêtes de rendu de Notion getSqliteMeta par l'intermédiaire de l'IPC. Le processus principal crée un canal de message et donne un port au moteur de rendu et l'autre à un processus utilitaire SQLite. Les lots de relevés suivants et les résultats transitent par ce port.

Suite à ce transfert, explique où le travail de base de données s'exécute et pourquoi le suivi uniquement de la demande IPC initiale manque la conversation ultérieure.

Sources et comment lire les extraits

Le pont du presse-papiers provient de Notion Desktop 7.6.1 app.asar: le préchargement de l'onglet et main/index.js. Les extraits développent les noms de variables minifiés et omettent le code non lié; l'assistant de vérification de l'expéditeur est affiché avec son sous-jacent isNotionWebContents appelle.

Les exemples de presse-papiers virtuels et de démarque proviennent d'actifs Web mis en cache le 13 juillet 2026, y compris des modules 747001, 58169, 736810 et 422457. Ces actifs ont leur propre version. Les sondes enregistrées exécutaient des modules extraits et de petits harnais; leurs sorties décrivent ces sondes plutôt qu'une session d'interface utilisateur de bureau capturée.

Le résultat REA présenté ici est une analyse ciblée du préchargement de l'onglet enregistré, enregistré avec le package REA 4.1.0 publié. Il localise l'API et appelle l'opération. L'élément de presse-papiers et le récepteur correspondant sont connectés en lisant leurs implémentations wrapper dans le package.

L'exemple Markdown utilise le module analyseur 422457. Les tests des modules enregistrés montrent que les filtres de page et de discussion conservent cette table. Les analyseurs paste/import, Markdown structuré et AI/chat ont des points d'entrée et des formats intermédiaires distincts.

Haut