Skip to content

Latest commit

 

History

History
154 lines (120 loc) · 5.89 KB

File metadata and controls

154 lines (120 loc) · 5.89 KB

SnapFill

Cross-platform WebView autofill engine.
Detects, classifies, and fills form fields inside WebViews. Also extracts shopping cart data.


Usage

import { snapfillScript, buildFillScript } from '@snap-fill/core';
import type { AutofillMappings, AutofillMessage } from '@snap-fill/core';

// 1. Inject the detection script into any WebView
webview.evaluateJavaScript(snapfillScript);

// 2. Listen for messages
webview.onMessage((msgStr: string) => {
  const msg: AutofillMessage = JSON.parse(msgStr);

  switch (msg.type) {
    case 'formDetected':
      console.log('Detected fields:', msg.fields);
      break;
    case 'cartDetected':
      console.log('Cart total:', msg.cart.total, msg.cart.currency);
      break;
    case 'valuesCaptured':
      console.log('Current values:', msg.mappings);
      break;
    case 'formFillComplete':
      console.log(`Filled ${msg.result.filled}/${msg.result.total}`);
      break;
  }
});

// 3. Fill form fields
const mappings: AutofillMappings = {
  firstName: 'Jane',
  lastName: 'Doe',
  email: 'jane@example.com',
  postalAddressLine1: '123 Main St',
  postalSuburb: 'New York',
  postalState: 'NY',
  postalPostCode: '10001',
};

webview.evaluateJavaScript(buildFillScript(mappings));

How It Works

Form Detection

Fields are classified using four signal types (in priority order):

  1. autocomplete attribute - HTML5 standard (autocomplete="given-name")
  2. name/id/placeholder regex - Heuristic pattern matching
  3. type attribute - type="email", type="tel"
  4. label text - Associated <label> content

A two-pass scan ensures autocomplete matches (high confidence) take priority over regex matches.

Cart Detection

Shopping cart data is extracted from (in priority order):

  1. JSON-LD - <script type="application/ld+json">
  2. Microdata - schema.org/Product itemscope
  3. Open Graph - og:type="product" meta tags
  4. DOM heuristics - Cart container patterns + price regex

Form Filling

Uses native property setters to bypass React/Vue/Angular framework interceptors. Events are dispatched in the correct order: focus -> input -> change -> blur.

Packages

Package Description Platform
@snap-fill/core Core detection + filling engine Any JS runtime
@snap-fill/react-native React Native WebView adapter (hook + component) React Native
@snap-fill/android Kotlin library for Android WebView Android 7.0+
@snap-fill/ios Swift package for WKWebView iOS 15+

Platform Guides

  • React Native — hook, component, and Expo demo setup
  • Android — Kotlin Snapfill helper and SnapfillWebView
  • iOS — Swift Snapfill helper and SnapfillWebView

Documentation

The full documentation site (with a live demo) is available at wangdicoder.github.io/snapfill.

To run it locally:

pnpm --filter @snap-fill/website dev

Development

pnpm install           # Install dependencies
pnpm build             # Build all packages
pnpm test              # Run tests
pnpm lint              # Lint code
pnpm generate:native   # Generate JS assets for Android & iOS

Native Libraries

The Android and iOS libraries load the same injectable scripts from @snap-fill/core. After building core, run pnpm generate:native to copy the JS assets into both native packages. See the platform guides above for build and test instructions.

Architecture

packages/
├── core/src/                  # @snap-fill/core — JS engine
│   ├── detectors/
│   │   ├── formDetector       # Field detection + classification
│   │   ├── cartDetector       # Shopping cart extraction
│   │   └── valueCapture       # Form value monitoring
│   ├── fillers/
│   │   └── formFiller         # Field filling with native setters
│   ├── scripts/               # Entry points for injectable IIFE bundles
│   ├── injectable             # Re-exports generated script strings
│   ├── constants              # Regex patterns, autocomplete maps
│   └── types                  # TypeScript type definitions
│
├── react-native/src/          # @snap-fill/react-native — RN adapter
│   ├── useSnapfill            # Hook for WebView script injection + messaging
│   ├── SnapfillWebView        # Pre-wired WebView component
│   └── parseMessage           # Message type parser
│
├── android/src/               # @snap-fill/android — Kotlin library
│   ├── Snapfill               # Script injection + message bridge
│   ├── SnapfillWebView        # Pre-wired Android WebView
│   ├── SnapfillListener       # Callback interface
│   └── SnapfillModels         # Data classes
│
└── ios/Sources/Snapfill/      # @snap-fill/ios — Swift package
    ├── Snapfill               # Script injection + message bridge
    ├── SnapfillWebView        # Pre-wired WKWebView
    ├── SnapfillDelegate       # Delegate protocol
    └── SnapfillModels         # Data structs

Core exports both functions for direct web use (tree-shakeable) and script strings for WebView injection. The injectable scripts are generated at build time from the same typed source modules (via scripts/ entry points bundled with esbuild), ensuring a single source of truth. Native libraries inject these scripts via platform-specific WebView APIs (evaluateJavascript on Android, WKUserScript on iOS). A bridge shim provides window.ReactNativeWebView.postMessage() so the same scripts work across all platforms.