Skip to content

Repository files navigation

plainforge

Plainforge is a local-first fixture workbench for HTML-to-plain-text extraction. It helps developers and agents compare conversion behavior against small, reviewable fixtures before trusting extracted text in docs, crawlers, or automation.

Why

HTML-to-text conversion often looks simple until links, tables, hidden script blocks, entities, and spacing collide. Plainforge gives those edge cases a tiny home:

  • keep representative HTML snippets in fixtures/
  • record expected plain text beside each snippet
  • run deterministic conversions locally
  • export JSON and Markdown reports for review

Plainforge was inspired by the existence of adjacent html2text projects, including vincentkoc/html2text, but it is a fresh JavaScript implementation focused on fixture-driven testing rather than copying another project's implementation.

Install

Plainforge 0.1.0 is not currently available from the npm registry. Install the published GitHub release tarball instead:

npm install https://github.com/rogerchappel/plainforge/releases/download/v0.1.0/plainforge-0.1.0.tgz

For local development you can run the CLI directly:

node bin/plainforge.js --help

The installed package exposes a plainforge binary and the public API shown below. For repository development, use npm ci instead of the release-tarball install command and run the CLI directly with node bin/plainforge.js --help.

Quickstart

Inspect the bundled sample fixtures and write reports:

node bin/plainforge.js inspect fixtures/sample --output out/plainforge

Convert one local HTML file:

node bin/plainforge.js convert fixtures/sample/basic-link/input.html

Use JSON output in automation:

node bin/plainforge.js inspect fixtures/sample --json

The CLI accepts these command forms:

plainforge convert <html-file> [--strategy readable|compact] [--json]
plainforge inspect <fixture-dir> [--output <dir>] [--strategy readable|compact] [--json]

--output (or -o) is available only for inspect. Options that require a value, unknown options, and extra file or directory arguments are rejected with a nonzero exit status and an actionable error message.

Fixture format

Each fixture is a directory with:

my-case/
  input.html      # source HTML
  expected.txt    # expected plain-text output
  meta.json       # optional id/title/tags/notes

See fixtures/sample for working examples.

Conversion decodes semicolon-terminated named references used by the bundled fixtures, including common currency (&pound;, &cent;, &yen;) and mathematical (&notin;, &le;, &ge;) references. It also supports the HTML 4 Greek-letter set, common mathematical operators and relations, and directional arrows (for example, &alpha;, &sum;, &ne;, and &rarr;). The complete HTML Latin-1 set is supported, so &frac12;, &times;, and &divide; become ½, ×, and ÷. Named references are case-sensitive: defined aliases such as &Aacute; decode, while undefined spellings such as &AACUTE; remain unchanged. Historical text references amp, lt, gt, quot, nbsp, copy, and reg may omit the semicolon when the following character is not alphanumeric. Unknown or ambiguous references remain unchanged so fixture comparisons do not silently discard source text.

When present, meta.json must contain a JSON object. id, title, and notes must be strings, while tags must be an array containing only strings. All fields may be omitted: the fixture directory name supplies id and title, with [] and an empty string used for tags and notes. Invalid metadata stops inspection with an error that names the fixture's meta.json file and the field that needs correction. Malformed JSON likewise reports the exact meta.json path together with the parser's syntax context, so a broken fixture can be identified when inspecting a directory of fixtures. Pipes and line breaks in these fields are escaped or normalized when Markdown reports are rendered.

API

import { convertHtmlToText, inspectFixtures } from 'plainforge';

const conversion = convertHtmlToText('<h1>Hello</h1><p>World</p>');
console.log(conversion.text);

const report = await inspectFixtures('fixtures/sample');
console.log(report.summary);

HTML numeric character references follow browser-style recovery: decimal and hexadecimal forms may omit the trailing semicolon, null, surrogate, and out-of-range values become �, and the HTML C1 replacement table is applied. Common named references, including HTML Latin-1 names such as &ccedil; and &eacute;, &frac12;, &times;, and &divide; and symbols such as &trade;, &euro;, and &ldquo;, are supported alongside Greek letters, mathematical operators and relations, and arrows. Named references normally require a trailing semicolon and an exact case match; the legacy text references listed above may omit their semicolon at an unambiguous boundary. Unknown, ambiguous, or differently cased named references are preserved.

Safety boundaries

Plainforge is intentionally boring and local:

  • reads local files you point it at
  • writes reports only when --output is provided
  • makes no network calls
  • sends no telemetry
  • does not read credentials
  • does not publish packages, releases, or reports

Treat fixture content as untrusted text. Plainforge does not execute HTML, JavaScript, CSS, or remote resources. Hidden script, style, noscript, svg, template, and head blocks are omitted; if one is truncated without a closing tag, its content is omitted through the end of the input. Tag and anchor boundaries respect single- and double-quoted attribute values, including > characters inside those values. HTML comments are omitted through their closing marker or the end of truncated input. Ordinary text comparisons containing < and > are retained rather than treated as tags.

Development

npm test
npm run check
npm run build
npm run smoke
npm run package:smoke
bash scripts/validate.sh

A real CLI smoke is also available:

node bin/plainforge.js inspect fixtures/sample --output out/smoke --json

Project status

This is a usable MVP: fixture discovery, deterministic conversion, comparison diffs, JSON/Markdown reports, tests, and CLI smokes are implemented. The roadmap is intentionally conservative until real users identify the next painful extraction cases.

License

MIT

Release Readiness

Use the checked-in scripts before opening or publishing a release:

npm run check
npm test
npm run build
npm run smoke
npm run package:smoke
npm run release:check

The package smoke uses npm pack --dry-run so the published file list can be reviewed without publishing. It also installs the generated tarball in a temporary project and checks the public import, CLI help, conversion, and fixture inspection paths.

Tagged releases require the tag to exactly match the package version (for example, v0.2.0 for plainforge@0.2.0). The release workflow is intended to run the full gate, pack and validate one tarball, publish that artifact to npm with trusted publishing, and then attach it to the GitHub release. Verify npm registry availability independently: an existing GitHub release and attached tarball do not prove that npm publication succeeded or remains available.

For a failed or partial release, inspect the workflow run and both distribution targets before retrying. Correct validation, trusted-publisher, or registry configuration first. Never republish a version that already exists on npm; recover only the missing distribution step with the already validated artifact, or issue a new version when the original npm publication did not complete.

About

Local-first fixture testbed for comparing HTML-to-plain-text extraction quality.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages