{"id":35833029,"url":"https://github.com/pie-framework/pie-qti","last_synced_at":"2026-01-26T07:13:48.505Z","repository":{"id":331554997,"uuid":"1128837315","full_name":"pie-framework/pie-qti","owner":"pie-framework","description":"QTI Player and QTI \u003c-\u003e PIE transforms framework","archived":false,"fork":false,"pushed_at":"2026-01-18T05:28:51.000Z","size":3678,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-01-18T17:28:22.175Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pie-framework.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-06T08:14:25.000Z","updated_at":"2026-01-18T05:27:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pie-framework/pie-qti","commit_stats":null,"previous_names":["pie-framework/pie-qti"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/pie-framework/pie-qti","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pie-framework%2Fpie-qti","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pie-framework%2Fpie-qti/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pie-framework%2Fpie-qti/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pie-framework%2Fpie-qti/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pie-framework","download_url":"https://codeload.github.com/pie-framework/pie-qti/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pie-framework%2Fpie-qti/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28769507,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T06:37:25.426Z","status":"ssl_error","status_checked_at":"2026-01-26T06:37:23.039Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-07T23:21:29.345Z","updated_at":"2026-01-26T07:13:48.498Z","avatar_url":"https://github.com/pie-framework.png","language":"TypeScript","readme":"# PIE-QTI\n\n![QTI 2.x \u0026 3.0 Support](https://img.shields.io/badge/QTI%202.x%20%26%203.0-Supported-success)\n![Interactions](https://img.shields.io/badge/Interactions-21%2F21-success)\n![Tests](https://img.shields.io/badge/Tests-1112%2B-success)\n![Accessibility](https://img.shields.io/badge/Accessibility-Tested-blue)\n![TypeScript](https://img.shields.io/badge/TypeScript-Strict-blue)\n\nThis project provides two major capabilities:\n\n1. **QTI 2.x \u0026 3.0 Players** — Production-ready item and assessment players with unified version-agnostic architecture\n2. **PIE ↔ QTI Transformation Framework** — Bidirectional transforms between QTI and PIE, with CLI, web app, and IMS Content Package support\n\n📚 **[Live Examples](https://pie-framework.github.io/pie-qti/examples/)**\n\n![QTI Player Examples](docs/images/examples-screenshot-1.png)\n\n\u003e **Project Status**: QTI 2.x players are production-ready. Transform framework is under active development. See [STATUS.md](STATUS.md) for details.\n\n---\n\n\u003e [!WARNING]\n\u003e While I believe the QTI player is production ready, we're still sticking to 0.1.x for a while, and we may make API changes between versions. I don't foresee a lot of that, but nevertheless, until this project has been used in the wild for a while, we may need some tweaks here and there to make the API good and meanwhile it's best to keep the code clean and unbothered with shims and other backwards compatibility constructs. Once we're at 1.0.0, we'll make stronger commitments for the API. But, let us know if you plan to use this for a non-trivial/ production system, and we can move such commitments forward.\n\n---\n\n## Why This Project Exists\n\n[PIE](https://pie-framework.org/) (Portable Interactions and Elements) is a complete framework for playing and authoring assessment items, maintained by [Renaissance Learning](https://www.renaissance.com/) with implementation partner [MCRO](https://mcro.tech/).\n\nMany Renaissance partners exchange content in **QTI format**, so bidirectional QTI ↔ PIE transformation is essential. This project **open sources that transformation framework** for partners and the broader community.\n\nWe also built a **spec-complete QTI 2.x player** because a modern, open-source option was missing—and we needed one for previewing, analysis, and \"convert then render\" workflows.\n\n---\n\n## Part 1: QTI Players (2.x \u0026 3.0)\n\n\u003e **Status**: Production-ready (QTI 2.x); QTI 3.0 infrastructure complete, player enhancements in progress\n\nFull-featured players for rendering QTI 2.x and 3.0 assessment content in the browser.\n\n### Version-Agnostic Architecture\n\nThe players use a unified architecture that supports both QTI 2.x and 3.0 through automatic version detection:\n\n- **QTI 2.x** — camelCase elements (`choiceInteraction`, `itemBody`)\n- **QTI 3.0** — kebab-case with `qti-` prefix (`qti-choice-interaction`, `qti-item-body`)\n- **Common Internal Model** — Both versions convert to the same canonical representation\n- **Zero Breaking Changes** — Existing QTI 2.x code continues to work unchanged\n\nSee [`@pie-qti/qti-common`](packages/qti-common/README.md) for the version abstraction layer.\n\n### Item Player (`@pie-qti/item-player`)\n\nRenders and scores individual QTI items:\n\n- **21 interaction types** — All QTI 2.2 interactions supported\n- **45 response processing operators** — Complete client-side scoring\n- **Role-based rendering** — Candidate, scorer, author, tutor, proctor, testConstructor\n- **Adaptive items** — Multi-attempt workflows with progressive feedback\n- **Accessible** — Full keyboard navigation and screen reader support (follows WCAG 2.2 Level AA guidelines)\n- **Iframe isolation mode** — Optional secure rendering for untrusted content\n\n### Assessment Player (`@pie-qti/assessment-player`)\n\nOrchestrates multi-item assessments:\n\n- **Navigation modes** — Linear (sequential) and nonlinear (free navigation)\n- **Sections \u0026 hierarchy** — Nested sections with rubric blocks\n- **Selection \u0026 ordering** — Random item selection and shuffling per QTI spec\n- **Time limits** — Countdown timers with warnings and auto-submission\n- **Item session control** — Max attempts, review/skip, response validation\n- **State persistence** — Auto-save with resume capability\n- **Outcome processing** — Scoring templates (total, weighted, percentage, pass/fail)\n- **Backend adapter** — Optional server-side scoring and secure data handling\n\n### Extensibility (Docs)\n\nThe player architecture separates QTI logic from UI rendering:\n\n- **Plugin system** (`QTIPlugin`) — Register custom extractors, components, and lifecycle hooks\n- **Registries** — Priority-based `ExtractionRegistry` and `ComponentRegistry`\n- **Typesetting hook** — Host-provided math rendering (KaTeX adapter included)\n- **Custom operators** — Support for `\u003ccustomOperator\u003e` elements\n\nSee the [ACME Likert plugin](packages/acme-likert-plugin/) for a complete extensibility example.\n\n### Theming\n\nComponents render via web components (Shadow DOM) with a CSS variable contract:\n\n- **Theme tokens** — DaisyUI-compatible variables (`--p`, `--a`, `--b1`, `--bc`, etc.)\n- **`::part()` hooks** — Stable part names for host-side style refinement\n- **Zero-CSS fallback** — Components render correctly with no host styles\n\nSee [STYLING.md](packages/default-components/STYLING.md) for the full styling contract.\n\n### Internationalization (i18n)\n\nThe player UI supports multiple languages with runtime locale switching:\n\n- **Type-safe translations** — TypeScript autocomplete for all message keys\n- **Runtime switching** — Change language without page reload\n- **Custom translations** — Clients provide complete locale bundles or override specific strings\n- **Small bundle** — \u003c10 KB gzipped (core + default locale)\n\nSee [`@pie-qti/i18n`](packages/i18n/) for the complete i18n API and [custom translation examples](packages/i18n/docs/custom-translations-example.md).\n\n---\n\n## Part 2: PIE ↔ QTI Transformation Framework\n\n\u003e **Status**: Under active development\n\nBidirectional transformation between QTI 2.2 XML and PIE JSON.\n\n### Architecture Overview\n\nThe transformation framework provides a plugin-based architecture for converting between assessment formats:\n\n![QTI Transform Engine Architecture](docs/images/qti-transform-engine.png)\n\nThe engine orchestrates transformations through:\n\n- **Plugin Registry** — Priority-based plugin selection (vendor plugins override defaults)\n- **Transform Engine** — Format detection, plugin matching, and execution\n- **Extensibility System** — Custom transformers, asset resolvers, and vendor-specific handlers\n\nSee [Transformation Engine Documentation](docs/TRANSFORMATION-ENGINE.md) for complete architecture details.\n\n### Transform Capabilities\n\n**QTI → PIE** (`@pie-qti/to-pie`)\n\n- Supports QTI 2.x and 3.0 (auto-detected)\n- Lossless round-trip when QTI originated from PIE\n- Best-effort semantic transformation otherwise\n- Vendor extension system for custom QTI variants\n\n**PIE → QTI** (`@pie-qti/pie-to-qti`)\n\n- Lossless reconstruction when PIE contains embedded QTI\n- Generator registry for custom PIE model handling\n- IMS Content Package generation (`imsmanifest.xml`)\n\n### Transform App (`@pie-qti/transform-web`)\n\n![QTI Player Examples](docs/images/transform-app-screenshot-1.png)\n\nInteractive web UI for transformations:\n\n- **Upload** — Single files or ZIP packages (including nested ZIPs)\n- **Analyze** — Discover items, count interactions, report issues\n- **Transform** — Batch convert with progress reporting\n- **Preview** — Side-by-side QTI and PIE rendering\n\nStorage is pluggable with filesystem (default), S3, or database backends via configuration.\n\n### CLI (`@pie-qti/transform-cli`)\n\nCommand-line tool for batch operations:\n\n```bash\n# Transform a single item\nbun run pie-qti -- transform input.xml --format qti22:pie --output output.json\n\n# Analyze QTI content\nbun run pie-qti -- analyze ./content-package/\n\n# See all commands\nbun run pie-qti -- --help\n```\n\n---\n\n## Development\n\n```bash\n# Install dependencies\nbun install\n\n# Build all packages\nbun run build\n\n# Run tests\nbun run test\n\n# Lint and typecheck\nbun run lint\nbun run typecheck\n\n# E2E tests (Playwright)\nbun run test:e2e\n```\n\n### Local PIE Players\n\nTo test with [pie-players](https://github.com/pie-framework/pie-players) locally, clone both repos side-by-side. The postinstall script auto-links them.\n\n### GitHub Pages Preview\n\n```bash\nbun run build:pages\nbun run preview:pages\n# Open http://localhost:4173/pie-qti/\n```\n\n---\n\n## Documentation\n\n### Architecture \u0026 Project Layout\n\n- **[Architecture Guide](docs/ARCHITECTURE.md)** — System design, package map, extensibility, theming, and security\n\n### Players\n\n- **[Item Player](packages/item-player/README.md)** — API, interactions, accessibility\n- **[Assessment Player](packages/assessment-player/README.md)** — Navigation, scoring, backend integration\n- **[QTI Common](packages/qti-common/README.md)** — Version abstraction layer (QTI 2.x \u0026 3.0)\n- **[Styling Contract](packages/default-components/STYLING.md)** — Theming with CSS variables and ::part\n- **[Example App](packages/example/README.md)** — Demo application with all interactions\n\n### Transforms\n\n- **[Transformation Engine](docs/TRANSFORMATION-ENGINE.md)** — Architecture, plugin system, and extensibility\n- **[Transformation Guide](docs/PIE-QTI-TRANSFORMATION-GUIDE.md)** — Bidirectional transform overview\n- **[Vendor Plugin Guide](docs/VENDOR-TRANSFORM-PLUGIN-GUIDE.md)** — Building custom vendor plugins\n- **[Configuration Guide](docs/CONFIGURATION.md)** — Storage backends, plugins, and environment setup\n- **[Migration Guide](docs/MIGRATION_GUIDE.md)** — Upgrading from legacy storage to new architecture\n- **[Transform App](packages/transform-app/README.md)** — Web UI for transformations\n- **[CLI](tools/cli/README.md)** — Command-line batch operations\n- **[QTI → PIE](packages/to-pie/README.md)** — QTI to PIE transformer\n- **[PIE → QTI](packages/pie-to-qti/README.md)** — PIE to QTI transformer\n- **[IMS Content Packages](packages/pie-to-qti/docs/MANIFEST-GENERATION.md)** — Manifest generation\n\n### Extensibility\n\n- **[Custom Generators](packages/pie-to-qti/CUSTOM-GENERATORS.md)** — Adding PIE model support\n- **[ACME Likert Plugin](packages/acme-likert-plugin/README.md)** — Player extensibility example\n\n---\n\n## License\n\nISC License — see [LICENSE](LICENSE)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpie-framework%2Fpie-qti","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpie-framework%2Fpie-qti","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpie-framework%2Fpie-qti/lists"}