app.webview - WebView API

Displays web pages or HTML content in a standalone window with JavaScript interaction support.

Permission: Requires webview declared in the manifest (L2 sensitive)

Methods

app.webview.open(config)

Opens a WebView window.

Parameters:

  • config (table):
    • url (string, optional) - URL to load (mutually exclusive with html)
    • html (string, optional) - HTML content to display (mutually exclusive with url)
    • title (string, optional) - Window title
    • width (number, optional) - Window width (default 800)
    • height (number, optional) - Window height (default 600)
    • x (number, optional) - Window X position
    • y (number, optional) - Window Y position
    • resizable (boolean, optional) - Whether the window is resizable (default true)
    • closable (boolean, optional) - Whether the window is closable (default true)
    • onClose (function, optional) - Window close callback function(id)

Returns: string, error - WebView ID

-- Load a URL
local id, err = app.webview.open({
    url = "https://example.com",
    title = "Preview",
    width = 1024,
    height = 768
})

-- Load HTML
local id, err = app.webview.open({
    html = "<h1>Hello</h1><p>This is a webview.</p>",
    title = "Custom Page",
    width = 400,
    height = 300
})

-- With close callback
local id, err = app.webview.open({
    url = "https://example.com",
    onClose = function(id)
        app.log.info("WebView closed: " .. id)
    end
})

app.webview.close(id)

Closes the specified WebView window.

Parameters:

  • id (string) - WebView ID

Returns: boolean, error

local ok, err = app.webview.close(webviewId)

app.webview.closeAll()

Closes all WebView windows.

Returns: boolean

app.webview.closeAll()

app.webview.eval(id, js)

Executes JavaScript code in the WebView.

Parameters:

  • id (string) - WebView ID
  • js (string) - JavaScript code

Returns: string|nil, error - JavaScript execution result (as a JSON string)

-- Get the page title
local title, err = app.webview.eval(id, "document.title")

-- Get form data
local data, err = app.webview.eval(id, [[
    JSON.stringify({
        name: document.getElementById('name').value,
        email: document.getElementById('email').value
    })
]])
if data then
    local result = app.json.parse(data)
end

-- Modify page content
app.webview.eval(id, "document.body.style.backgroundColor = '#f0f0f0'")

app.webview.loadURL(id, url)

Loads a new URL in an existing WebView.

Parameters:

  • id (string) - WebView ID
  • url (string) - URL to load

Returns: boolean, error

local ok, err = app.webview.loadURL(id, "https://other-page.com")

app.webview.loadHTML(id, html)

Loads new HTML content in an existing WebView.

Parameters:

  • id (string) - WebView ID
  • html (string) - HTML content

Returns: boolean, error

local ok, err = app.webview.loadHTML(id, "<h1>Updated Content</h1>")

Examples

Markdown preview

function MyPlugin:handlePreview(context)
    local file = context.selectedFiles[1]
    if not file then return end

    local content = app.file.read(file)
    if not content then return end

    local html = string.format([[
        <!DOCTYPE html>
        <html>
        <head>
            <style>
                body { font-family: -apple-system; padding: 20px; max-width: 800px; margin: 0 auto; }
                pre { background: #f5f5f5; padding: 12px; border-radius: 6px; overflow-x: auto; }
                code { font-family: 'SF Mono', monospace; }
            </style>
            <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
        </head>
        <body>
            <div id="content"></div>
            <script>
                document.getElementById('content').innerHTML = marked.parse(%s);
            </script>
        </body>
        </html>
    ]], app.json.stringify(content))

    app.webview.open({
        html = html,
        title = app.path.basename(file),
        width = 900,
        height = 700
    })
end

Custom settings UI

function MyPlugin:handleSettings(context)
    local settings = app.settings.getAll()

    local html = string.format([[
        <!DOCTYPE html>
        <html>
        <head>
            <style>
                body { font-family: -apple-system; padding: 20px; }
                .field { margin: 12px 0; }
                label { display: block; margin-bottom: 4px; font-weight: 600; }
                input, select { width: 100%%; padding: 6px; border: 1px solid #ccc; border-radius: 4px; }
                button { padding: 8px 16px; background: #007AFF; color: white; border: none; border-radius: 6px; cursor: pointer; }
            </style>
        </head>
        <body>
            <h2>Plugin Settings</h2>
            <div class="field">
                <label>API Key</label>
                <input id="apiKey" value="%s">
            </div>
            <div class="field">
                <label>Output Format</label>
                <select id="format">
                    <option value="json">JSON</option>
                    <option value="csv">CSV</option>
                </select>
            </div>
            <button onclick="save()">Save</button>
            <script>
                function save() {
                    window.__result = JSON.stringify({
                        apiKey: document.getElementById('apiKey').value,
                        format: document.getElementById('format').value
                    });
                }
            </script>
        </body>
        </html>
    ]], settings.apiKey or "")

    local id, err = app.webview.open({
        html = html,
        title = "Settings",
        width = 400,
        height = 300,
        resizable = false,
        onClose = function(wvId)
            local result = app.webview.eval(wvId, "window.__result || null")
            if result and result ~= "null" then
                local data = app.json.parse(result)
                if data then
                    app.settings.set("apiKey", data.apiKey)
                    app.settings.set("format", data.format)
                end
            end
        end
    })
end

Data visualization

function MyPlugin:handleVisualize(context)
    local files = context.selectedFiles
    local sizes = {}

    for _, file in ipairs(files) do
        table.insert(sizes, {
            name = app.path.basename(file),
            size = app.file.size(file) or 0
        })
    end

    local html = string.format([[
        <!DOCTYPE html>
        <html>
        <head>
            <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
            <style>body { padding: 20px; }</style>
        </head>
        <body>
            <canvas id="chart"></canvas>
            <script>
                var data = %s;
                new Chart(document.getElementById('chart'), {
                    type: 'bar',
                    data: {
                        labels: data.map(d => d.name),
                        datasets: [{
                            label: 'File Size (bytes)',
                            data: data.map(d => d.size),
                            backgroundColor: '#007AFF'
                        }]
                    }
                });
            </script>
        </body>
        </html>
    ]], app.json.stringify(sizes))

    app.webview.open({
        html = html,
        title = "File Size Analysis",
        width = 800,
        height = 500
    })
end

Notes

  1. Window limit: Each plugin can have up to 5 WebView windows
  2. JavaScript results: eval() returns results as JSON strings
  3. Close callback: onClose is automatically triggered when the window is closed
  4. Resource cleanup: All WebView windows are automatically closed when the plugin is unloaded
  5. Network access: WebView can load external URLs, subject to App Transport Security restrictions
Developer Documentation
User Guide
Getting Started Script Menus FAQ
Script Development
Development Guide
Plugin Development
Quick Start Development Guide Example Plugins
API Reference
Overview API Query Plugin Info Logging Finder Context Plugin Settings Internationalization
UI & Interaction
Dialog Progress Notification Chooser WebView Status Bar Dock
Files & Paths
File Operations Path Utilities Finder Actions Trash Extended Attributes Metadata File Watcher
Data Formats
JSON Plist CSV XML PDF Image
Text & Encoding
String Regex Date & Time Color Crypto
System
Shell Commands Process Application System Info AppleScript Shortcuts
System Info
Network Power/Battery Screen/Appearance Audio Bluetooth Location
Network
HTTP WebSocket URL
Input & Clipboard
Keyboard Mouse Hotkey Clipboard Window
Storage
SQLite Keychain UserDefaults
Media
OCR QR Code
Utilities
Archive UTI Share Timer Wake Lock Thread