Skip to content

Repository files navigation

One-Shot Table Parser

One-Shot Table Parser: industrial table image to reusable HTML structure

Live demo: Open One-Shot Table Parser

One-Shot Table Parser is a web application for extracting repeated industrial table documents with a reusable, human-verified HTML structure. Define the table topology once, then give the application another document with the same layout. A multimodal model fills the cells while the application rejects outputs that change the approved rows, columns, or merged-cell structure.

The template is deliberately content-free: it contains only <table>, <tr>, and empty <td> elements, plus rowspan and colspan where needed. This keeps structure definition separate from OCR content and makes templates easy to inspect, edit, and reuse.

Why this project

General-purpose vision models often recognize text correctly but reconstruct complex tables inconsistently. They may add or remove cells, flatten merged regions, or return a different layout between documents. This project turns a verified table structure into an explicit constraint:

  1. Create or extract a blank HTML structure.
  2. Review and correct it once.
  3. Reuse it with images that follow the same layout.
  4. Accept model output only when its topology matches the template.

Features

  • Three template creation modes
    • Edit blank table HTML directly.
    • Initialize a row-by-column grid and merge rectangular selections visually.
    • Extract an initial blank structure from a table image, then correct it in the same visual editor.
  • Structure-only templates with no labels, values, or placeholders.
  • Merged-cell support through validated rowspan and colspan values.
  • OpenAI-compatible vision APIs configured from the web interface or environment variables.
  • Real vision connectivity test using an image request, not a text-only health check.
  • Model safeguards including deterministic generation, a 4,096-token output limit, a 110-second timeout, and automatic disabling of Qwen thinking mode.
  • Client-side image resizing for large inputs before multimodal inference.
  • Strict output validation that rejects changed table topology and unsafe HTML.
  • Persistent templates, model settings, parse history, and uploaded images using Cloudflare D1 and R2.
  • Mock mode for exploring the workflow without a model API.
  • English interface across templates, parsing, history, settings, prompts, and errors.

How it works

1. Build a blank structure template

Choose one of three paths on the Templates page:

Mode Best for Result
Edit HTML Users who already know the exact topology Validated blank table HTML
Visual Builder Manual construction without editing source Grid with visual merge and split operations
Start from Image Fast initialization from a representative document Model-generated blank structure for manual correction

An accepted template looks like this:

<table>
  <tr>
    <td></td>
    <td colspan="2"></td>
  </tr>
  <tr>
    <td rowspan="2"></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td colspan="2"></td>
  </tr>
</table>

All cells must be empty. Attributes other than rowspan and colspan are rejected.

2. Parse another document

On the Parse page, select a saved template and upload a document image with the same layout. The application sends the blank HTML and image to the configured vision model. The model fills each cell by spatial position without being allowed to alter the structure.

3. Verify and reuse the result

The returned HTML is checked against the template's topology. Successful and failed runs are recorded on the History page with the input image, result, raw model output, and error details where available.

Model API setup

Open Model Settings and enter:

  • API Base URL — include the version path but omit /chat/completions, for example https://api.openai.com/v1.
  • Model Name — a multimodal model that accepts image input.
  • API Key — sent only to the server; the browser receives a masked value after saving.

Click Test Vision Connection before saving. The endpoint must support:

  • POST /chat/completions
  • Bearer-token authorization
  • OpenAI-compatible image_url message content

You may instead provide the same configuration through environment variables:

MODEL_API_BASE_URL=https://api.openai.com/v1
MODEL_NAME=your-vision-model
MODEL_API_KEY=your-api-key

Saved database settings take precedence over environment variables. With neither configured, the application runs in Mock mode.

Quick start

Prerequisites

  • Node.js 22.13 or newer
  • npm
  • Linux or WSL for the included build scripts (flock and GNU timeout are used)

Install and run

git clone https://github.com/lyc61c/OneShotTable.git
cd OneShotTable
npm ci
npm run db:migrate:local
npm run dev

Open the local URL printed by Vite. Copy .env.example to .env.local only if you want environment-based model configuration.

The local migration command applies both checked-in D1 migrations to the same project-local state used by the development server. Local R2 storage is provided by the Cloudflare Vite plugin.

Available commands

Command Purpose
npm run dev Start the Vinext/Vite development server
npm run db:migrate:local Apply checked-in migrations to local D1 state
npm run lint Run ESLint
npm run build Build and validate the deployable worker artifact
npm test Build, validate, and run the rendered-page smoke test
npm run validate:artifact Recheck an existing build artifact
npm run db:generate Generate a new Drizzle migration after schema changes

Deployment

The application is designed for a Cloudflare Worker-compatible runtime with:

  • a D1 binding named DB
  • an R2 binding named BUCKET
  • Node.js compatibility enabled

The repository includes .openai/hosting.json for ChatGPT Sites-compatible deployment and vite.config.ts for local D1/R2 simulation. For another Cloudflare deployment workflow, provision D1 and R2, map the bindings above, apply the SQL files in drizzle/, then build with npm run build.

Do not commit real API keys. Set secrets in the deployment environment or configure the model from the protected settings page after deployment.

Architecture

Layer Implementation
UI React 19, Next.js 16, Tailwind CSS 4, Lucide icons
Runtime/build Vinext, Vite, Cloudflare Workers
Database Cloudflare D1, Drizzle ORM
Object storage Cloudflare R2
Model integration OpenAI-compatible multimodal Chat Completions API

Key directories:

app/                  Pages and API routes
components/           Template editor, parser workspace, history, and settings UI
db/                   Drizzle schema and D1 access
drizzle/              Database migrations
lib/                  Model client, prompts, image handling, and HTML validation
public/               Static assets
tests/                Rendered-worker smoke test
worker/               Cloudflare worker entry point

Validation and safety boundaries

The server normalizes structure templates and permits only:

  • <table>, <tr>, and <td>
  • integer rowspan and colspan values from 1 to 100
  • a rectangular, non-overlapping effective grid

Scripts, styles, event handlers, arbitrary attributes, text inside templates, inconsistent row widths, overlapping spans, and spans that extend past the final row are rejected. Parsed output must have the same ordered cell-span signature as the selected template.

The built-in model configuration page is intended for a trusted or access-controlled deployment. The API key is not returned to the browser after saving, but it is stored in D1 and the settings endpoints do not implement application-level user authorization. Do not expose an unrestricted deployment with a shared model key. Add authentication and per-user ownership before using this as a public multi-user service.

Core prompts

Image initialization is intentionally narrow:

You are a table structure extractor.
Generate a blank HTML table template from the uploaded image.
Accurately reconstruct rows, columns, and merged cells; remove all text;
use only table, tr, td, rowspan, and colspan; output only the table HTML.

Parsing uses the confirmed blank HTML as a hard structural reference and asks the model only to fill cell text from corresponding image positions.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages