Catalog npm
PACKAGE EXPLORERView in registry

@008h/oxs

npm

Read, write and validate Open Cross Stitch (.OXS) files

cross-stitchembroideryoxs
Versions collected3
Direct dependencies5From release 0.1.1
Last observed20 Oct, 21:54 UTC

README

Current package documentation

oxs

Read, write and validate Open Cross Stitch (.oxs) files. Pure TypeScript, ESM, no DOM or Node-specific APIs.

Install

npm install @008h/oxs

Usage

Read, validate, write

import { parseOxs, serializeOxs, validateOxs } from '@008h/oxs';

const doc = parseOxs(xmlString);
console.log(doc.properties.chartWidth, doc.properties.chartHeight);

for (const d of validateOxs(doc)) {
  console.warn(d.severity, d.code, d.message);
}

const xml = serializeOxs(doc);

serializeOxs(doc, { sort: true }) orders stitches by x, y and palette index, which gives stable output for diffs and golden files.

Create a chart

Documents are immutable: build a new one instead of changing it in place.

import { createDocument, serializeOxs } from '@008h/oxs';

const empty = createDocument({ width: 8, height: 8, title: 'Heart', author: 'me' });

const doc = {
  ...empty,
  palette: [
    ...empty.palette,
    { index: 1, number: '321', name: 'Red', color: 'C93756', blends: [], extra: [] },
  ],
  fullStitches: [
    { x: 3, y: 2, palindex: 1, extra: [] },
    { x: 4, y: 2, palindex: 1, extra: [] },
  ],
};

const xml = serializeOxs(doc);

palette[0] (index 0) is the cloth colour. createDocument adds it for you.

Inspect

import { chartBounds, paletteUsage, paletteCount } from '@008h/oxs';

chartBounds(doc);   // { minX, maxX, minY, maxY } of the stitches, or null if empty
paletteUsage(doc);  // Set of palette indexes that are actually used
paletteCount(doc);  // number of palette entries, not counting the cloth

Edit as a grid

toDense turns a document into maps keyed by cell, which is convenient for editors. fromDense converts back against the original document, reusing unchanged elements so that unknown attributes survive.

import { toDense, fromDense, cellKey } from '@008h/oxs';

const dense = toDense(doc);

const edited = {
  ...dense,
  fullStitches: new Map(dense.fullStitches).set(cellKey(5, 5), 1),
};

const next = fromDense(edited, doc);

Validation

validateOxs does not throw on odd input. It returns diagnostics, each with a severity (error, warn or info), a stable code, a message and usually a path. It currently reports:

CodeSeverityMeaning
OXS003_OUT_OF_BOUNDSinfoa stitch or ornament lies outside the chart size
OXS004_UNKNOWN_PALINDEXwarna stitch references a palette index that does not exist
OXS007_FOREIGN_ELEMENTinfoan unknown element was kept verbatim
OXS009_CLOTH_INDEX_MISSINGinfothe palette has no entry at index 0 (cloth)

Out-of-bounds coordinates are legal in OXS, so they are reported as info, never error. The DiagnosticCode type lists a few more codes that are reserved for later and not reported yet.

Errors

Malformed XML makes parseOxs (and readXml) throw XmlParseError:

import { parseOxs, XmlParseError } from '@008h/oxs';

try {
  parseOxs(text);
} catch (e) {
  if (e instanceof XmlParseError) console.error('not valid XML:', e.message);
  else throw e;
}

Preservation

Unknown attributes are kept in extra and unknown elements in foreign, so a parse → serialize round trip does not drop data written by other software.

Coordinates

The OXS specification does not define the coordinate origin. Based on measurements of real-world files, this library treats coordinates as 0-based and keeps them exactly as written in the file: parsing and serializing never shift values. Out-of-bounds coordinates are therefore legal in the IR and reported by validateOxs instead. Use detectOrigin, toZeroBased and fromZeroBased to interpret a file's origin.

Details and evidence: docs/OXS-DIALECT.md.

Disclaimer

OXS is a file format published by Ursa Software. This project is an independent implementation and is not affiliated with or endorsed by Ursa Software.

License

MIT

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 3

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.1Registry latest10 Oct 20265
0.1.010 Oct 20265
0.0.0-stage10 Oct 20260

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
008h/oxs

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 21:54 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:67bcd4fcc8090f8e89829bde1f2203e57f86e9208aa0e4ac96582f3ada5fdd17