Skip to content

lynnswap/WebInspectorKit

Repository files navigation

WebInspectorKit

日本語版 README

WebInspectorKit preview

Web Inspector for WKWebView (iOS / macOS).

Products

  • WebInspectorKit: Container UI, pane descriptors, Observation state
  • WebInspectorKitCore (Core): DOM/Network engines, runtime actors, bundled inspector scripts

WebInspectorKit depends on WebInspectorKitCore.

Features

  • DOM tree browsing (element picking, highlights, deletion, attribute editing)
  • Network request logging (fetch/XHR/WebSocket) with buffering/active mode switching
  • Configurable panes via WIPaneDescriptor
  • Explicit lifecycle via WISessionController (connect(to:), suspend(), disconnect())

Requirements

  • Swift 6.2+
  • iOS 18 / macOS 15+
  • WKWebView with JavaScript enabled

Quick Start

UIKit

import UIKit
import WebKit
import WebInspectorKit

final class BrowserViewController: UIViewController {
    private let pageWebView = WKWebView(frame: .zero)
    private let inspector = WISessionController()

    @objc private func presentInspector() {
        let container = WIContainerViewController(
            inspector,
            webView: pageWebView,
            tabs: [.dom(), .element(), .network()]
        )
        container.modalPresentationStyle = .pageSheet
        if let sheet = container.sheetPresentationController {
            sheet.detents = [.medium(), .large()]
            sheet.selectedDetentIdentifier = .medium
            sheet.prefersGrabberVisible = true
        }
        present(container, animated: true)
    }
}

AppKit

import AppKit
import WebKit
import WebInspectorKit

final class BrowserWindowController: NSWindowController {
    let pageWebView = WKWebView(frame: .zero)
    let inspector = WISessionController()

    @objc func presentInspector() {
        let container = WIContainerViewController(
            inspector,
            webView: pageWebView,
            tabs: [.dom(), .element(), .network()]
        )
        let inspectorWindow = NSWindow(contentViewController: container)
        inspectorWindow.styleMask = [.titled, .closable, .miniaturizable, .resizable]
        inspectorWindow.title = "Web Inspector"
        inspectorWindow.setContentSize(NSSize(width: 960, height: 720))
        inspectorWindow.makeKeyAndOrderFront(nil)
    }
}

Custom Pane

let customPane = WIPaneDescriptor(
    id: "my_custom_pane",
    title: "Custom",
    systemImage: "folder",
    role: .other
) { context in
    #if canImport(UIKit)
    return UIViewController()
    #else
    return NSViewController()
    #endif
}

let container = WIContainerViewController(
    inspector,
    webView: pageWebView,
    tabs: [.dom(), .element(), .network(), customPane]
)

Migration

See MIGRATION.md for details on breaking changes.

Testing

Run tests with xcodebuild from the repository root. Execute both macOS and iOS Simulator test suites.

# macOS: Package tests (Core)
xcodebuild -workspace WebInspectorKit.xcworkspace \
  -scheme WebInspectorKitCoreTests \
  -destination 'platform=macOS' \
  test

# macOS: Package tests (Feature)
xcodebuild -workspace WebInspectorKit.xcworkspace \
  -scheme WebInspectorKitFeatureTests \
  -destination 'platform=macOS' \
  test

# iOS Simulator: Package tests (Core)
xcodebuild -workspace WebInspectorKit.xcworkspace \
  -scheme WebInspectorKitCoreTests \
  -destination 'platform=iOS Simulator,name=iPhone 17,OS=latest' \
  test

# iOS Simulator: Package tests (Feature)
xcodebuild -workspace WebInspectorKit.xcworkspace \
  -scheme WebInspectorKitFeatureTests \
  -destination 'platform=iOS Simulator,name=iPhone 17,OS=latest' \
  test

If the destination does not exist on your machine, check available simulators with:

xcrun simctl list devices available

Run TypeScript tests (Vitest) from the repository root:

pnpm -s run test:ts
pnpm -s run typecheck:ts

License

See LICENSE.

About

Web Inspector for WKWebView on iOS and macOS

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published