mirror of
https://github.com/THU-MAIC/OpenMAIC.git
synced 2026-10-29 00:46:40 +08:00
* refactor(export): share one classroom export snapshot across formats Split buildClassroomExportZip into buildClassroomExportSnapshot, which returns the portable manifest plus the bytes of every payload it names, and a thin ZIP writer on top of it. The upcoming standalone HTML export serializes the same snapshot, so both formats share one serializer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(export): standalone HTML player bundle A small React app that plays a classroom manifest embedded in the page: slides through @openmaic/renderer's SlideCanvas, interactive scenes in sandboxed srcdoc iframes, client-graded quizzes, and static PBL briefings, with prev/next, keyboard, scene list and fullscreen. scripts/build-standalone-player.mjs compiles it at app build time (dev and build) into public/vendor/standalone-player/: one IIFE via esbuild, Tailwind 4 CSS covering the renderer's classes, KaTeX fonts as an optional sheet, and ECharts as an optional script the player reads from a global, so files without charts do not carry it. Shiki is stubbed; code elements render unhighlighted. esbuild is added as a direct devDependency at the version already in the lockfile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * feat(export): export a classroom as a single offline HTML file Add "Export as HTML" to the export menu. The export takes the shared classroom snapshot, embeds slide images, backgrounds and video posters as data URIs (archived payloads first, concrete URLs fetched at export time), patches interactive HTML for the sandboxed iframe, and inlines the prebuilt player into <course-name>.html. The file makes no network requests: a restrictive CSP (default-src 'none', connect-src 'none') is set before any script, the manifest and config are embedded as JSON with <, > and & escaped, and interactive pages run only in iframes sandboxed like the classroom's. PBL scenes link to the online classroom only when it is published at export time. No narration or video bytes yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(sanitize): move the scene-content sanitizer to a client-safe module The policy depends only on sanitize-html, so it moves to lib/sanitize/scene-content.ts unchanged; lib/server/sanitize-scene-content.ts re-exports it for the persistence callers. Client export paths can now apply the same policy to working state before it leaves the app. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(export): sanitize and trim the standalone HTML classroom - Run slide rich text (text, shape text, table cells, LaTeX snapshots) through the persistence sanitizer before embedding: the renderer injects it into the player's own document, and the export reads working state that has not crossed the persistence boundary. - Embed chart point images as data URIs (or drop and report them); rich text images and CSS url() values are removed by the sanitizer. - Leave out what the player does not use: playback actions, multi-agent settings, the agent roster, the video manifest and PBL runtime state. PBL content is resolved the way the classroom resolves it, legacy projects upgraded, and reduced to its briefing. - Skip narration audio, legacy audio fetches and video bytes when building the snapshot for HTML (captured posters are kept); the ZIP path is unchanged. - Resolve each media ref once, count a video poster as unresolved only when no captured frame covers it, and ship KaTeX fonts only when quiz text or slides actually contain math. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(export): keep player scenes scrollable and contain scene failures Navigate with Left/Right only, so Up/Down, PageUp/PageDown and Home/End scroll long quiz and PBL scenes. Wrap each scene in an error boundary that shows it as unavailable instead of blanking the player, and read PBL briefings defensively now that the export resolves legacy projects. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(export): note that dev builds the standalone player once Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(export): keep inline formulas and report dropped rich-text resources The prose sanitizer cannot express the editor's inline formulas (KaTeX spans with SVG and positioned parts carrying data-inline-math), so the standalone export lifts each formula's LaTeX source out before sanitizing (from data-inline-math, else the KaTeX tex annotation) and puts back a fresh KaTeX render afterwards. The embedded markup is generated from the source, never taken from the document. Images and CSS url() values in rich text, which the sanitizer removes, are inventoried first and reported as unresolved media so the partial-export warning counts them instead of losing them silently. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(export): rebuild inline formulas through the DOM, not string markers Rework the standalone export's rich-text pass so authored text is never spliced into strings: - Parse each prose string with the DOM. Inventory resources over the whole tree first, formula subtrees included: image src and srcset, media sources, and CSS url(), image-set() and @import references found by a real CSS parse (comments, quoted URLs and escapes respected). - Replace each inline formula with an empty span whose data-inline-math is set through setAttribute, then run the persistence sanitizer with an export-only option that keeps that one attribute on span. The default persistence policy is unchanged. - Parse the sanitized output and replace each such span with a fresh KaTeX render of the source read back with getAttribute. Generated KaTeX is the only markup added after sanitizing. Tests cover replacement patterns in LaTeX, marker-like and encoded text, resources inside formula wrappers, quoted URLs with parentheses, srcset, escaped url() and commented-out URLs. The export tests now run under jsdom, where the browser DOM the export relies on is available. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(export): make the rich-text resource inventory spec-correct and fail-safe - Decode CSS escapes per CSS Syntax: zero, surrogates and values above U+10FFFF become U+FFFD instead of throwing, and an escaped newline is a line continuation. - Never let the inventory affect the export: each element is scanned under its own guard and the whole pass is guarded, so a failure can only under-report. - Scan and strip formulas inside template contents, nested ones included, which querySelectorAll does not reach. - Document that the inventory is best-effort and only drives the partial-export warning; the sanitizer and the CSP remove and block these resources regardless. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(export): bound the public-classroom lookup in the HTML export Every HTML export awaited the stage-meta request for the optional PBL "continue online" link, so a request that never settled left the export stuck in its busy state with no download. The lookup now gives up after 3000 ms: the request is aborted through the fetch it is given, and a race returns even when the response body never finishes. On timeout or failure the link is omitted and the export continues. Courses without a PBL scene skip the lookup entirely. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(export): always link PBL scenes to the online classroom A classroom is readable by anyone holding its link; the published flag does not gate reading. Gating the PBL "Continue this project online" link on it hid a link that works. The export now always builds the link from the exporting origin and the stage id, with no stage-meta request, so there is nothing to wait on. The explicit classroomUrl option for hosts and the player's http(s)-only guard stay. This replaces the bounded lookup and its timeout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(export): render standalone-player charts without entry animation Line series animate in by growing an SVG clipPath from zero width. WebKit does not repaint the clipped group when the clip path's geometry changes afterwards, so in Safari the exported file showed a line chart's points and labels without the connecting line. Re-setting the clip path (or the clip-path attribute) makes the line appear, which confirms the stale paint. The charts runtime the export ships now wraps ECharts init so every chart renders without its entry animation; the clip path is created at its final size. The shared renderer and the online classroom are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
217 lines
7.9 KiB
JSON
217 lines
7.9 KiB
JSON
{
|
|
"name": "openmaic",
|
|
"version": "1.2.0-rc.1",
|
|
"private": true,
|
|
"license": "MIT",
|
|
"engines": {
|
|
"node": ">=22.19.0"
|
|
},
|
|
"scripts": {
|
|
"postinstall": "pnpm run build:packages",
|
|
"build:packages": "cd packages/mathml2omml && npm run build && cd ../pptxgenjs && npm run build && cd ../@openmaic/dsl && pnpm run build && cd ../generation && pnpm run build && cd ../storage && pnpm run build && cd ../importer && pnpm run build && cd ../renderer && pnpm run build && cd ../editor && pnpm run build && cd ../../.. && node scripts/sync-maic-importer.mjs",
|
|
"sync:maic-importer": "node scripts/sync-maic-importer.mjs",
|
|
"build:standalone-player": "node scripts/build-standalone-player.mjs",
|
|
"gen:video-export-katex": "node scripts/generate-video-export-katex.mjs",
|
|
"gen:video-export-noto-cjk": "node scripts/generate-video-export-noto-cjk.mjs",
|
|
"gen:video-export-noto-script-fonts": "node scripts/generate-video-export-noto-script-fonts.mjs",
|
|
"dev": "node scripts/build-standalone-player.mjs && next dev",
|
|
"build": "node scripts/assert-vendor-maic-importer.mjs && node scripts/build-standalone-player.mjs && next build",
|
|
"start": "next start",
|
|
"db:up": "docker compose -p openmaic-dev-db -f docker-compose.db.yml up -d --wait postgres",
|
|
"db:down": "docker compose -p openmaic-dev-db -f docker-compose.db.yml stop postgres",
|
|
"lint": "eslint",
|
|
"check:i18n-keys": "node scripts/check-i18n-keys.mjs",
|
|
"check:node-engine": "node scripts/check-node-engine-contract.mjs",
|
|
"check:package-versions": "node scripts/check-package-version-bumps.mjs",
|
|
"check": "prettier . --check",
|
|
"format": "prettier . --write",
|
|
"test": "vitest run",
|
|
"test:package-tarballs": "node scripts/smoke-test-package-tarballs.mjs",
|
|
"test:e2e": "playwright test",
|
|
"test:e2e:ui": "playwright test --ui",
|
|
"eval:pbl-v2-planner": "tsx eval/pbl-v2-planner/runner.ts",
|
|
"eval:whiteboard": "tsx eval/whiteboard-layout/runner.ts",
|
|
"eval:outline-language": "tsx eval/outline-language/runner.ts",
|
|
"eval:orchestration": "tsx eval/orchestration/runner.ts",
|
|
"eval:orchestration:answering": "tsx eval/orchestration/answering-runner.ts",
|
|
"eval:orchestration:answer-content": "tsx eval/orchestration/answer-content-runner.ts"
|
|
},
|
|
"dependencies": {
|
|
"@ai-sdk/amazon-bedrock": "^4.0.103",
|
|
"@ai-sdk/anthropic": "^3.0.71",
|
|
"@ai-sdk/azure": "^3.0.88",
|
|
"@ai-sdk/google": "^3.0.64",
|
|
"@ai-sdk/openai": "^3.0.84",
|
|
"@ai-sdk/react": "^3.0.170",
|
|
"@alicloud/credentials": "^2.4.5",
|
|
"@alicloud/docmind-api20220711": "^1.4.15",
|
|
"@alicloud/openapi-client": "^0.4.15",
|
|
"@alicloud/tea-util": "^1.4.11",
|
|
"@aws-sdk/client-s3": "^3.1048.0",
|
|
"@aws-sdk/credential-providers": "^3.1045.0",
|
|
"@aws-sdk/s3-request-presigner": "^3.1048.0",
|
|
"@base-ui/react": "^1.1.0",
|
|
"@copilotkit/backend": "^0.37.0",
|
|
"@copilotkit/runtime": "^1.51.2",
|
|
"@earendil-works/pi-agent-core": "0.78.0",
|
|
"@earendil-works/pi-ai": "0.78.0",
|
|
"@fontsource-variable/inter": "^5.2.8",
|
|
"@fontsource/jetbrains-mono": "^5.2.8",
|
|
"@fontsource/literata": "^5.2.8",
|
|
"@fontsource/lxgw-wenkai": "^5.2.5",
|
|
"@fontsource/merriweather": "^5.2.11",
|
|
"@fontsource/montserrat": "^5.2.8",
|
|
"@fontsource/noto-sans-kr": "^5.2.9",
|
|
"@fontsource/noto-sans-sc": "^5.2.9",
|
|
"@fontsource/noto-serif-sc": "^5.2.8",
|
|
"@fontsource/open-sans": "^5.2.7",
|
|
"@fontsource/roboto": "^5.2.10",
|
|
"@fontsource/source-sans-3": "^5.2.9",
|
|
"@fontsource/source-serif-4": "^5.2.9",
|
|
"@fontsource/zcool-kuaile": "^5.2.8",
|
|
"@joplin/turndown-plugin-gfm": "^1.0.67",
|
|
"@langchain/core": "^1.1.16",
|
|
"@langchain/langgraph": "^1.1.1",
|
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
"@mozilla/readability": "^0.6.0",
|
|
"@napi-rs/canvas": "^0.1.88",
|
|
"@openmaic/dsl": "workspace:*",
|
|
"@openmaic/editor": "workspace:*",
|
|
"@openmaic/generation": "workspace:*",
|
|
"@openmaic/importer": "workspace:*",
|
|
"@openmaic/renderer": "workspace:*",
|
|
"@openmaic/storage": "workspace:*",
|
|
"@radix-ui/react-checkbox": "^1.3.3",
|
|
"@radix-ui/react-popover": "^1.1.15",
|
|
"@radix-ui/react-slider": "^1.3.6",
|
|
"@radix-ui/react-switch": "^1.2.6",
|
|
"@radix-ui/react-use-controllable-state": "^1.2.2",
|
|
"@streamdown/code": "^1.1.1",
|
|
"@streamdown/math": "^1.0.2",
|
|
"@types/js-yaml": "^4.0.9",
|
|
"@xyflow/react": "^12.10.0",
|
|
"ai": "^6.0.168",
|
|
"animate.css": "^4.1.1",
|
|
"class-variance-authority": "^0.7.1",
|
|
"clsx": "^2.1.1",
|
|
"cmdk": "^1.1.1",
|
|
"copilotkit": "^0.0.58",
|
|
"dexie": "^4.2.1",
|
|
"docx": "9.4.1",
|
|
"echarts": "^6.0.0",
|
|
"embla-carousel-react": "^8.6.0",
|
|
"es-module-lexer": "^2.0.0",
|
|
"file-saver": "^2.0.5",
|
|
"geist": "^1.7.0",
|
|
"graphemer": "1.4.0",
|
|
"i18next": "^26.0.1",
|
|
"i18next-resources-to-backend": "^1.2.1",
|
|
"immer": "^11.1.3",
|
|
"ipaddr.js": "^2.5.0",
|
|
"js-yaml": "4.3.0",
|
|
"jsonrepair": "^3.13.2",
|
|
"jszip": "^3.10.1",
|
|
"katex": "^0.16.33",
|
|
"linkedom": "^0.18.13",
|
|
"lodash": "4.18.1",
|
|
"lucide-react": "^0.562.0",
|
|
"mathml2omml": "workspace:*",
|
|
"micromark-extension-math": "^3.1.0",
|
|
"mitt": "^3.0.1",
|
|
"motion": "^12.27.5",
|
|
"nanoid": "5.1.16",
|
|
"next": "16.3.3",
|
|
"next-themes": "^0.4.6",
|
|
"openai": "^4.104.0",
|
|
"parse-srcset": "^1.0.2",
|
|
"parse5": "^8.0.1",
|
|
"partial-json": "^0.1.7",
|
|
"pdf-lib": "^1.17.1",
|
|
"pg": "^8.16.3",
|
|
"postcss": "^8.5.15",
|
|
"postcss-value-parser": "^4.2.0",
|
|
"pptxgenjs": "workspace:*",
|
|
"pptxtojson": "^1.11.0",
|
|
"prosemirror-commands": "^1.7.1",
|
|
"prosemirror-dropcursor": "^1.8.2",
|
|
"prosemirror-gapcursor": "^1.4.0",
|
|
"prosemirror-history": "^1.5.0",
|
|
"prosemirror-inputrules": "^1.5.1",
|
|
"prosemirror-keymap": "^1.2.3",
|
|
"prosemirror-model": "^1.25.4",
|
|
"prosemirror-schema-basic": "^1.2.4",
|
|
"prosemirror-schema-list": "^1.5.1",
|
|
"prosemirror-state": "^1.4.4",
|
|
"prosemirror-view": "^1.41.5",
|
|
"radix-ui": "^1.4.3",
|
|
"react": "19.2.3",
|
|
"react-colorful": "^5.7.0",
|
|
"react-dom": "19.2.3",
|
|
"react-i18next": "^17.0.1",
|
|
"sanitize-html": "2.17.0",
|
|
"shadcn": "^3.6.3",
|
|
"sharp": "0.35.4",
|
|
"shiki": "^3.21.0",
|
|
"sonner": "^2.0.7",
|
|
"streamdown": "^2.5.0",
|
|
"svg-arc-to-cubic-bezier": "^3.2.0",
|
|
"svg-pathdata": "^8.0.0",
|
|
"tailwind-merge": "^3.4.0",
|
|
"temml": "^0.13.1",
|
|
"tinycolor2": "^1.6.0",
|
|
"tokenlens": "^1.3.1",
|
|
"turndown": "^7.2.4",
|
|
"tw-animate-css": "^1.4.0",
|
|
"typebox": "^1.1.39",
|
|
"undici": "7.29.0",
|
|
"unpdf": "^1.4.0",
|
|
"uqr": "^0.1.3",
|
|
"use-stick-to-bottom": "^1.1.1",
|
|
"zod": "^4.3.5",
|
|
"zustand": "^5.0.10",
|
|
"remark-cjk-friendly": "^2.3.1"
|
|
},
|
|
"devDependencies": {
|
|
"@electric-sql/pglite": "^0.3.16",
|
|
"@fontsource/noto-sans": "5.3.0",
|
|
"@fontsource/noto-sans-arabic": "5.3.0",
|
|
"@playwright/test": "^1.58.2",
|
|
"@rollup/plugin-commonjs": "^28.0.1",
|
|
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
"@tailwindcss/postcss": "^4",
|
|
"@types/file-saver": "^2.0.7",
|
|
"@types/katex": "^0.16.8",
|
|
"@types/lodash": "^4.17.23",
|
|
"@types/node": "^20",
|
|
"@types/pg": "^8.15.5",
|
|
"@types/react": "^19",
|
|
"@types/react-dom": "^19",
|
|
"@types/sanitize-html": "^2.16.1",
|
|
"@types/tinycolor2": "^1.4.6",
|
|
"esbuild": "0.27.7",
|
|
"eslint": "^9",
|
|
"eslint-config-next": "16.2.11",
|
|
"fake-indexeddb": "^6.2.5",
|
|
"fontkit": "2.0.4",
|
|
"gsap": "^3.15.0",
|
|
"hyperframes": "0.7.60",
|
|
"prettier": "3.8.1",
|
|
"rollup": "^4.35.0",
|
|
"rollup-plugin-typescript2": "^0.36.0",
|
|
"semver": "7.8.5",
|
|
"tailwindcss": "^4",
|
|
"tslib": "^2.8.0",
|
|
"tsx": "^4.21.0",
|
|
"typescript": "^5",
|
|
"vitest": "^4.1.8",
|
|
"vue-to-react": "^1.0.0"
|
|
},
|
|
"pnpm": {
|
|
"ignoredBuiltDependencies": [
|
|
"sharp",
|
|
"unrs-resolver"
|
|
]
|
|
},
|
|
"packageManager": "pnpm@10.28.0+sha512.05df71d1421f21399e053fde567cea34d446fa02c76571441bfc1c7956e98e363088982d940465fd34480d4d90a0668bc12362f8aa88000a64e83d0b0e47be48"
|
|
}
|