Ir al contenido

Visión general del scripting

Guida incluye un entorno completo de scripting para automatización del navegador. Los scripts interactúan con páginas, gestionan datos y orquestan flujos mediante la API g.*.

Hay tres motores disponibles:

  • JavaScript (ClearScript V8) — compatibilidad completa ES2024+, top-level await, Promises nativas e imports de módulos ES. Usa el mismo motor V8 que Chrome y Node.js.
  • Lua (LuaCSharp) — API limpia basada en tablas con sintaxis Lua estándar. Integrado con bibliotecas del espacio de trabajo mediante require().
  • Janet (JanetSharp) — dialecto Lisp funcional y expresivo con estructuras de datos inmutables y un motor PEG integrado potente.

Los tres motores comparten la misma superficie de API g.*.

Como los scripts de automatización son fundamentalmente asíncronos, Guida admite top-level await para scripts que no necesitan una sentencia return temprana:

// Top-level await works out of the box
const tabs = g.tabs.getTabs();
g.log("Open tabs: " + tabs.length);

Para scripts que necesitan devolver antes, envuelva el código en async function main() y añada await main(); al final.

Pulse F5 en el editor de scripts para ejecutar.

El manejo de errores en Guida depende del motor usado.

En JavaScript y Janet, todos los métodos g.* devuelven valores directamente y lanzan excepciones en caso de error. En JavaScript, use try/catch:

try {
await g.dom.click("#submit");
} catch (e) {
g.log("Click failed: " + e.message);
return;
}

En Lua, la API g.* usa retornos múltiples idiomáticos (nil, error) en lugar de lanzar excepciones. Esto evita que el depurador de Visual Studio se detenga ante excepciones “no controladas” durante el desarrollo.

Compruebe siempre el primer valor de retorno:

local success, err = g.nav.navigateToUrl("https://example.com")
if not success then
g.log("Error: Navigation failed: " .. err)
else
g.log("Page loaded successfully")
end

Muchas operaciones del navegador son asíncronas. En JavaScript, use await. En Lua y Janet, las llamadas son esperadas automáticamente por el motor.

JavaScript:

async function main() {
await g.nav.navigateToUrl("https://example.com");
await g.dom.waitForDomStable();
const html = await g.page.getDom();
g.log("Page loaded, DOM length: " + html.length);
}

Lua:

g.nav.navigateToUrl("https://example.com")
g.dom.waitForDomStable()
local html = g.page.getDom()
g.log("Page loaded, DOM length: " .. #html)

Janet:

(g.nav.navigateToUrl "https://example.com")
(g.dom.waitForDomStable)
(def html (g.page.getDom))
(g.log (string "Page loaded, DOM length: " (length html)))

Guida permite escribir funciones reutilizables en archivos compartidos.

Use sintaxis estándar ES import/export. La ruta se resuelve relativa al directorio del script llamador, con fallback a la raíz del espacio de trabajo.

lib/helpers.js:

export async function loginToApp(username, password) {
await g.nav.navigateToUrl("https://example.com/login");
await g.dom.enterText("#user", username);
await g.dom.enterText("#pass", password);
await g.dom.click("#submit");
}

myscript.js:

import { loginToApp } from "./lib/helpers.js";
await loginToApp("admin", "secure123");
const data = await g.dom.extractContent(".stats");
g.log("Dashboard stats: " + data);

Use la función estándar require(). Guida busca módulos en la carpeta lib/ del espacio de trabajo y en las carpetas lib/ y scripts/ del flujo actual.

lib/utils.lua:

local M = {}
function M.hello() g.log("Hello from library!") end
return M

myscript.lua:

local utils = require("utils")
utils.hello()

Use la macro import para cargar módulos Janet desde las carpetas lib/ y scripts/ del espacio de trabajo.

lib/utils.janet:

(defn hello []
(g.log "Hello from Janet library!"))

myscript.janet:

(import utils)
(utils/hello)

Defina un tiempo máximo de ejecución del script, en milisegundos:

// @timeout 60000
async function main() {
// This script will be cancelled after 60 seconds
}

El timeout predeterminado es 10 segundos. Coloque el pragma antes de cualquier código.

Proteja scripts que dependen de g.worker.getContext() para que no se ejecuten fuera de un contexto de proceso de trabajo:

// @require-context
async function main() {
const ctx = g.worker.getContext();
// This script will only run inside a queue processor or worker pool
}

Si el script se ejecuta de forma independiente (F5, MCP, disparador de evento), falla de inmediato con un error claro en lugar de fallar a mitad de ejecución. Vea Colas y revisión para más detalles.

Use g.log() para escribir en el panel Console:

g.log("Processing item: " + item.name);

El editor integrado ofrece:

  • IntelliSense — autocompletado para todos los métodos g.* y sus parámetros
  • Ayuda de firma — pistas de parámetros al escribir (
  • Documentación al pasar el cursor — información de tipos al pasar el ratón
  • Depuración con Chrome DevTools — haga clic en Debug sobre cualquier archivo .js para lanzar una instancia externa de Chrome DevTools conectada directamente al motor V8. Defina breakpoints, avance paso a paso e inspeccione variables con la interfaz estándar de Chrome.
  • Buscar/reemplazar — con soporte regex
  • Emparejamiento de llaves y guías de indentación

Algunos sitios detectan navegadores automatizados. Use stealth: true para inyectar parches antidedetección antes de que se ejecuten los scripts de la página:

await g.nav.navigateToUrl("https://example.com", { stealth: true });

Esto aplica cinco parches: oculta navigator.webdriver, inyecta window.chrome.runtime, corrige Permissions.prototype.query, simula navigator.plugins y define navigator.languages como ["en-US", "en"].

Para control granular, pase un objeto StealthOptions para habilitar o deshabilitar parches individuales. También puede detectar redirecciones basadas en JavaScript con { detectRedirects: true }. Vea la Referencia de API para más detalles.

Guida incluye texto a voz mediante Windows Speech Synthesis. Configure la voz predeterminada y la velocidad en Settings > TTS.

Pestaña Settings > TTS con desplegable Default Voice, deslizador Default Rate y botón Preview

Los scripts pueden pronunciar texto y sobrescribir valores predeterminados por llamada:

await g.tts.speak("Processing complete", { voice: "Microsoft David", rate: 2 });

Vea la Referencia de API para todos los métodos.

Todos los métodos de automatización de Guida están disponibles mediante el espacio de nombres global g. Aunque JavaScript y Lua comparten la misma superficie de API, hay dos diferencias clave en su uso:

A diferencia de algunas otras integraciones C# Lua, la API de Guida usa el operador punto (.) para todas las llamadas, por ejemplo g.dom.click("#btn"). No use el operador de dos puntos (:), como g.dom:click, porque los métodos de la API están vinculados directamente a servicios C# y no esperan un argumento self.

Lua usa tablas para estructuras de datos. Cuando un método de API devuelve un objeto, como una pestaña de navegador o un documento del almacén, se devuelve como una tabla Lua con indexación estándar desde 1 para arrays.

-- Working with the document store
local doc, err = g.store.get("products", "item-1")
if doc and doc.data then
g.log("Found product: " .. doc.data.name)
end

Janet es un lenguaje funcional similar a Lisp. Su sintaxis se basa fuertemente en s-expressions, paréntesis y notación prefija.

En lugar de usar notación de punto con paréntesis exteriores como g.dom.click("#btn"), se envuelve toda la expresión entre paréntesis: (g.dom.click "#btn").

Cuando un método de API devuelve un objeto, como TabInfo o un documento del almacén, se devuelve como diccionario Janet. Acceda a propiedades con get o get-in:

# Working with the document store
(def doc (g.store.get "products" "item-1"))
(if doc
(g.log (string "Found product: " (get (get doc "data") "name"))))
  • Referencia de API — lista completa de métodos para todos los espacios de nombres g.*
  • Recetas — scripts prácticos basados en ejemplos reales de la aplicación
  • Espacios de trabajo — organizar scripts, datos y configuración en carpetas de espacio de trabajo
  • Inicio rápido — recorrido práctico de 5 minutos