Estudio de caso * Electron

Cómo copia Notion
texto y HTML.

Rastree una llamada al portapapeles desde la API de la página de Notion, a través de la precarga y el proceso principal, hasta el escritor del portapapeles de Electron.

Escritorio Notion 7.6.1 * JavaScript · REA

El puente dentro del paquete de escritorio de Notion

  1. 01 * API orientada a páginas clipboard.write(data) La precarga expone un método invocable.
  2. 02 * Envoltura de precarga ipcRenderer.invoke El contenedor envía el canal y los argumentos.
  3. 03 * Controlador de procesos principales ipcMain.handle El receptor verifica qué página lo envió.
  4. 04 * Portapapeles del sistema clipboard.write(data) Electron escribe el texto y HTML suministrados.

Un canal une los dos lados: notion:clipboard:write

El código empaquetado usa el mismo canal en la precarga y el proceso principal. Al resolver los contenedores, se revelan las llamadas Electron detrás de esos nombres.

¿A dónde va la operación de copia?

La página ve un método llamado clipboard.write. Su implementación en la precarga es un wrapper. La pregunta útil es qué envía ese contenedor y qué código lo recibe.

Su agente de codificación

Use REA para rastrear cómo Notion copia texto y HTML en el portapapeles del sistema. Muestre el código en cada paso.

Un mensaje de ejemplo con el paquete de aplicaciones locales de Notion disponible para su agente de codificación.

REA encuentra dónde comenzar a leer

Al analizar la precarga de pestañas con REA, se localiza la API expuesta a la página y la llamada que envía una solicitud IPC. Ambos hallazgos vienen con rangos de origen en el paquete minimizado:

Hallazgos REA → dos lugares para abrir

API de página expuesta
api_key: "__electronApi"
api_status: "dynamic"
source: preload.js:1:22764–22828
Llamada IPC del renderizador
operation: "invoke"
channel_expression: "e"
source: preload.js:1:6486–6522
Campos seleccionados de un nuevo analyze_javascript_application resultado en la precarga de la pestaña Notion, grabada con REA 4.1.0. Las posiciones usan la línea y la columna de base cero del paquete original.

El agente abre esas ubicaciones, encuentra el miembro del portapapeles en la API ensamblada y lee invokerInMain. Suministros para el sitio Its call notion:clipboard:write. Ese nombre le da al agente algo preciso que buscar en el paquete principal. Los cuatro extractos a continuación muestran la ruta que conecta.

Cuatro piezas cortas de código

Simplificado a partir del JavaScript empaquetado , con nombres de variables legibles. Se omiten los miembros no relacionados.

  1. Comience en la API expuesta en la página

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

    Este miembro proporciona el nombre del canal. La implementación de invokerInMain nos dice cómo la solicitud sale del proceso de la página.

  2. Resolver el contenedor de la precarga

    tab_browser_view/preload.js * Ayudante de IPC
    function invokerInMain(channel) {
      return (...args) => invokeInMainAndReturnResult(channel, ...args);
    }
    
    function invokeInMainAndReturnResult(channel, ...args) {
      return ipcRenderer.invoke(channel, ...args);
    }

    La función devuelta reenvía los argumentos a través del IPC de solicitud y respuesta de Electron. Ahora podemos buscar notion:clipboard:write en el lado del proceso principal.

  3. Compruebe cómo está registrado el destinatario

    principal/index.js * ayudante del manejador
    const handleRequestFromRenderer = {
      addListener(channel, handler) {
        ipcMain.handle(channel, handler);
      }
    };

    El proceso principal usa otro envoltorio. Su addListener el método registra un ipcMain.handle receptor para ese canal.

  4. Encuentre la escritura y su verificación de remitente

    principal/index.js * receptor del portapapeles
    handleRequestFromRenderer.addListener(
      "notion:clipboard:write",
      (event, data) =>
        isNotionWebContents(event.sender)
          ? clipboard.write(data)
          : undefined
    );

    Este es el destino. Después de verificar el remitente, el controlador pasa los datos proporcionados a la API del portapapeles de Electron. El canal y los dos envoltorios resueltos conectan el método expuesto a esta llamada.

¿Cómo mantiene su estructura un bloque copiado?

El editor web de Notion envía texto y HTML a través de electronApi.clipboard.write. Mantiene los datos del bloque localmente y coloca una IDENTIFICACIÓN en el HTML copiado para conectarlos.

Enlaces HTML a los datos de bloque guardados

Enviado al portapapeles del sistema
text: "Project notes"
html: "<p>Project notes</p>"
    + "<!-- notionvc: <copy-id> -->"
Guardado localmente por Notion
id: <copy-id>
mimeTypes:
  text/_notion-blocks-v3-production
    → structured block data
  1. Leer el ID HTML
  2. Encuentre la misma identificación local
  3. Restaurar datos de bloque Notion
Texto ilustrativo e ID. La prueba del módulo grabado restaura los datos del bloque cuando los ID coinciden; una entrada obsoleta devuelve solo texto y HTML.

Al pegar, Notion busca el ID HTML y lo compara con la copia guardada. Los ID coincidentes restauran los datos del bloque.

Formato de portapapeles grabado a partir de activos web almacenados en caché el 13 de julio de 2026.

Más ejemplos y fuentes

Otro ejemplo: Tablas de rebajas

Notion analiza Markdown en datos de bloque. Este ejemplo muestra cómo una tabla se convierte en encabezado y filas de datos.

Una tabla a través del analizador de rebajas de Notion

Entrada de rebajas
| A | B |
| - | - |
| 1 | 2 |
Salida estructurada del analizador · extracto
table · headerRow: true
  table_row
    cells: ["A"], ["B"]
  table_row
    cells: ["1"], ["2"]
Salida grabada de un analizador Markdown extraído. La tabla se convierte en filas y celdas.
Otra ruta: la conexión SQLite sin conexión

Solicitudes de renderizador de Notion getSqliteMeta a través de IPC. El proceso principal crea un canal de mensajes y le da un puerto al renderizador y el otro a un proceso de utilidad SQLite. Los lotes de declaraciones posteriores y los resultados viajan por ese puerto.

A continuación, se explica dónde se ejecuta el trabajo de la base de datos y por qué rastrear solo la solicitud inicial de IPC pierde la conversación posterior.

Fuentes y cómo leer los extractos

El puente del portapapeles proviene de Notion Desktop 7.6.1 app.asar: la pestaña precarga y main/index.js. Los extractos expanden los nombres de variables minimizados y omiten el código no relacionado; el ayudante de verificación del remitente se muestra con su subyacente isNotionWebContents llama.

Los ejemplos del portapapeles virtual y Markdown provienen de activos web almacenados en caché el 13 de julio de 2026, incluidos los módulos 747001, 58169, 736810 y 422457. Esos activos tienen su propia versión. Las sondas guardadas ejecutaron módulos extraídos y arneses pequeños; sus resultados describen esas sondas en lugar de una sesión de IU de escritorio capturada.

El resultado de REA que se muestra aquí es un análisis enfocado de la precarga de pestañas guardada, registrada con el paquete REA 4.1.0 publicado. Localiza la API y la operación de invocación. El miembro del portapapeles y el receptor coincidente se conectan leyendo sus implementaciones de envoltura en el paquete.

El ejemplo de Markdown usa el módulo analizador 422457. Las pruebas de módulo guardadas muestran que tanto los filtros de página como de chat conservan esta tabla. Los analizadores pegar/importar, Markdown estructurado y AI/chat tienen puntos de entrada separados y formatos intermedios.

Arriba