Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"baseBranch": "master",
"updateInternalDependencies": "patch",
"ignore": []
}
21 changes: 0 additions & 21 deletions .changeset/initial-release.md

This file was deleted.

35 changes: 35 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Bug report
description: Report a reproducible parser or decoder problem.
body:
- type: markdown
attributes:
value: "For vulnerabilities, follow SECURITY.md instead. Do not upload personal photos or sensitive metadata."
- type: textarea
id: behavior
attributes:
label: Expected and actual behavior
description: Include steps to reproduce and a minimal code example.
validations:
required: true
- type: input
id: version
attributes:
label: Package version
validations:
required: true
- type: input
id: environment
attributes:
label: Browser and operating system versions
validations:
required: true
- type: textarea
id: diagnostics
attributes:
label: Strategy and diagnostics
description: Include probeSupport(), error context/attempts, warnings, and relevant logs.
- type: textarea
id: fixture
attributes:
label: Reproducing input
description: Attach only a non-sensitive file you have permission to redistribute, or a generation script.
15 changes: 15 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Feature request
description: Propose an improvement with a concrete use case.
body:
- type: textarea
id: problem
attributes:
label: What problem would this solve?
validations:
required: true
- type: textarea
id: proposal
attributes:
label: Proposed behavior and alternatives
validations:
required: true
12 changes: 12 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## Problem and behavior

Describe the concrete trigger and the resulting behavior.

## Validation

List checks run and any skipped tests or device coverage gaps.

- [ ] Typecheck, build, package validation, and unit tests pass.
- [ ] Relevant browser tests run for decode changes.
- [ ] Documentation and changeset updated when applicable.
- [ ] New fixtures can be redistributed and contain no sensitive information.
29 changes: 23 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@ name: CI

on:
push:
branches: [main]
branches: [master]
pull_request:

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
check:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
Expand All @@ -18,13 +26,15 @@ jobs:
- run: pnpm install --frozen-lockfile
- run: pnpm typecheck
- run: pnpm build
- run: pnpm test:package

# The parser and the fuzzer need no browser at all, and they are where the
# security-relevant behaviour lives.
- run: pnpm test:unit

browser:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
Expand All @@ -34,18 +44,25 @@ jobs:
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm build
- run: pnpm test:package
- run: pnpm exec playwright install --with-deps chromium firefox webkit
- run: pnpm test:browser

# Headless Linux browsers have no platform HEVC decoder, so the WebCodecs
# strategy does not run here and its tests skip themselves. What this job
# actually covers is the container parser and the wasm fallback, on all
# three engines.
# Headless Linux generally lacks platform HEVC decoding. Some WebKit
# builds accept limited HEVC profiles. Tests check each fixture config;
# software fallback tests run unconditionally on all three engines.
#
# A green badge on this workflow does NOT mean the primary decode path is
# tested. That needs a real device matrix — see the chrome-hevc project in
# playwright.config.ts, run locally with:
# HEIC_CHROME="/path/to/chrome" pnpm test:browser --project=chrome-hevc
- name: Note on coverage
run: |
echo "::notice::WebCodecs HEVC does not run in headless CI. This job covers the parser and the wasm path only."
echo "::notice::Platform HEVC needs device testing. CI covers parser/WASM paths and any fixture-specific WebCodecs configurations accepted by its browsers."

- uses: actions/upload-artifact@v4
if: failure()
with:
name: browser-test-results
path: test-results/
retention-days: 7
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ playwright-report/
# Personal photo corpus used for local development. The committed fixtures under
# test/fixtures/ are the ones CI runs against; see test/fixtures/README.md.
test/fixtures/local/

# Bundled public-API consumer used by browser integration tests.
test/.consumer/
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Changelog

## 0.1.0

Initial public release.

- Browser-first HEIC decoding with native, WebCodecs HEVC, and optional libheif WASM strategies.
- Single-image and tiled-grid planning with container rotation, mirroring, and clean-aperture cropping.
- Typed errors, source metadata, capability probes, and worker-compatible rendering.
- Reproducible build/test setup, public API documentation, and package-entry validation.

See [compatibility limitations](docs/compatibility.md) before deploying.
83 changes: 83 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Contributing

Thanks for helping improve HEIC decoding on the web. We welcome bug fixes, documentation improvements, and regression tests for files the parser or decoder mishandles.

## Local development

Use Node.js 22.12+ and pnpm 9.15.9 (declared in `package.json`). If your Node installation does not include Corepack, install pnpm 9.15.9 using your preferred package manager.

```sh
git clone https://github.com/su-engineering/heic-web.git
cd heic-web
corepack enable
pnpm install --frozen-lockfile
pnpm typecheck
pnpm build
pnpm test:package
pnpm test:unit
```

The package can be used before registry publication by building it and importing `dist/index.js`, or by installing a tarball created with `pnpm pack --pack-destination /tmp/heic-pack`. The WASM entry point is `dist/wasm.js`; its optional peer dependency must be available in the consuming project.

## Repository map

| Directory | Responsibility |
| --- | --- |
| `src/parser/` | Bounds-checked ISOBMFF/HEIF parsing, item extraction, grid descriptors, and HEVC configuration. |
| `src/plan.ts` | Primary-image planning, dimensions, tile groups, transforms, and feature warnings. |
| `src/decoders/` | Native image decoding and WebCodecs HEVC decoding. |
| `src/render/` | Canvas compositing helpers and container transforms. |
| `wasm/` | Optional libheif adapter and its module declarations. |
| `test/unit/` | Parser tests and deterministic mutation fuzzing. |
| `test/browser/` | Public-API browser tests and worker harnesses. |
| `test/fixtures/` | Committed fixtures; private local corpus is ignored by Git. |
| `tools/` | Test server, package validation, fixture generation, and inspection tools. |

## Browser tests

Build and run `pnpm test:package` first; the harness imports `dist/` and the bundled consumer created by that check.

```sh
pnpm exec playwright install chromium firefox webkit
pnpm test:browser
```

On a supported Linux distribution, add `--with-deps` to install required system libraries. If a browser fails to launch on an unsupported distribution, run the suite in the same Ubuntu environment as CI rather than changing host libraries blindly.

The default projects are `chromium`, `firefox`, and `webkit`. To test a real Chromium installation with platform HEVC:

```sh
HEIC_CHROME="/path/to/chrome" pnpm test:browser --project=chrome-hevc
```

The environment variable adds that project to the matrix. Setting it does not create HEVC support; capability-dependent tests still skip if the installed browser cannot decode HEVC. Playwright WebKit is not a substitute for testing released Safari on an Apple device.

Run `pnpm test:all` after installing browsers for the combined checks. Record skipped tests as well as failures when reporting coverage.

## Reproducing a bug

Include the input's provenance, browser and OS versions, package version, strategy, and error name/message/context. For `HeicUnsupportedError`, include `attempts`. Explain the expected orientation, dimensions, or colors. A minimal redistributable fixture is preferable to a personal photograph.

For container inspection (Node.js 22.6+ with type stripping):

```sh
pnpm dump path/to/photo.heic --boxes
pnpm validate-corpus path/to/corpus
```

See [fixture documentation](https://github.com/su-engineering/heic-web/blob/master/test/fixtures/README.md) for reference-image generation and manifest provenance. Fixture regeneration requires libheif command-line tools, ImageMagick, and ExifTool; normal builds and tests use committed fixtures and do not need those tools.

## Submitting a change

1. Create a focused branch from `master`.
2. Explain the observable problem and add a regression test for behavior changes.
3. Preserve typed parser errors and bounds/count checks. Avoid DOM dependencies in decode paths.
4. Run typecheck, build, package validation, and unit tests; run relevant browser tests for decoding changes.
5. Update documentation when API behavior or requirements change. For package changes, run `pnpm exec changeset` and add a concise release note.
6. Open a pull request explaining the change, validation, and any coverage gaps.

Do not commit `dist/`, browser reports, `node_modules/`, or the private photo corpus. Only contribute fixtures you have permission to redistribute, without sensitive metadata. Contributions are licensed under the repository's MIT license.

## Community expectations

Be respectful, explain disagreements with evidence, and focus reviews on the work. Do not harass contributors or disclose private information. Report conduct concerns privately to hello@su.engineering. Use the [security policy](SECURITY.md) for vulnerabilities.
Loading
Loading