diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index 7e6df6a40..3601a99d2 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -47,17 +47,37 @@ jobs: run: yarn build:lib - name: Build with VitePress run: yarn docs:build # or pnpm docs:build / yarn docs:build / bun run docs:build - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - path: docs/.vitepress/dist - + + # Test Job + test: + name: Test + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: yarn + - name: Install dependencies + run: yarn install + - name: Build skuilder libraries + run: yarn build:lib + - name: Start dev server and run tests + run: | + yarn docs:dev & + SERVER_PID=$! + npx wait-on http://localhost:5173/vue-skuilder + yarn docs:test + kill $SERVER_PID + # Deployment job deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} - needs: build + needs: [build, test] runs-on: ubuntu-latest name: Deploy steps: diff --git a/agent/BACKPORT_CHECKLIST.md b/agent/BACKPORT_CHECKLIST.md deleted file mode 100644 index 11f05fd9e..000000000 --- a/agent/BACKPORT_CHECKLIST.md +++ /dev/null @@ -1,273 +0,0 @@ -# Backport Checklist for Scaffolding Templates - -Changes tested in `/flutor` that need to be propagated to vue-skuilder template packages. - -**Note:** This document is self-contained. All necessary code examples and rationale are included below. - -## How to Use This Document - -1. **Copy this file** to the vue-skuilder monorepo for reference -2. **Apply changes 1-6** to the template packages (standalone-ui, sk-contributor) -3. **Test** using the testing checklist at the bottom -4. **Ignore** the "Infrastructure Changes" section - those are already in the monorepo - -**Files to Update:** -- `/packages/standalone-ui/vite.config.ts` -- `/packages/standalone-ui/src/questions/index.ts` -- `/packages/standalone-ui/src/main.ts` -- `/packages/standalone-ui/src/questions/*QuestionView.vue` (all view components) -- `/packages/sk-contributor/` (same files as above) -- `/packages/standalone-ui/src/questions/README.md` (examples) - -## Context - -These fixes enable custom questions to work in both: -- **Standalone mode** (`yarn dev`) - already worked -- **Studio mode** (`yarn studio`) - now works after these fixes - -The root cause was a combination of: -1. Browser unable to resolve bare imports in dynamically loaded modules -2. Missing view component names for runtime lookup -3. Side-effect import not running (views array staying empty) -4. Incorrect views export format for studio-ui consumption - -## 1. Vite Config - External Dependencies & Terser -**File:** `vite.config.ts` -**Location:** Library build configuration -**Change:** -```typescript -build: buildMode === 'library' - ? { - // ... - terserOptions: { - keep_classnames: true, - keep_fnames: true, // ADD: Preserve function names - mangle: { - properties: false, // ADD: Don't mangle static properties like seedData - }, - }, - rollupOptions: { - // CRITICAL: Do NOT externalize dependencies for studio mode - // Browser cannot resolve bare imports without import maps - external: [ - // Leave empty - bundle everything for browser compatibility - ], - } - } -``` -**Why:** -- Terser options prevent minification from mangling static properties (seedData, views, dataShapes) -- Empty externals array bundles all dependencies so browser can load the module without import maps -- Previously tried externalizing to avoid duplication, but browser can't resolve `import { X } from "@vue-skuilder/courseware"` at runtime -**Affects:** -- `/packages/standalone-ui/vite.config.ts` -- CLI template generation for new projects - ---- - -## 2. Question Index - Views Export Format -**File:** `src/questions/index.ts` -**Location:** `allCustomQuestions()` function -**Change:** -```typescript -// OLD (broken): -const views: ViewComponent[] = []; -questionClasses.forEach((questionClass) => { - if (questionClass.views) { - questionClass.views.forEach((view) => { - views.push(view); - }); - } -}); - -// NEW (working): -const views: Array<{ name: string; component: ViewComponent }> = []; -questionClasses.forEach((questionClass) => { - if (questionClass.views) { - questionClass.views.forEach((view) => { - const viewName = (view as any).name || (view as any).__name; - if (viewName) { - if (!views.find((existing) => existing.name === viewName)) { - views.push({ name: viewName, component: view }); - } - } else { - console.warn('[allCustomQuestions] View component missing name property:', view); - } - }); - } -}); -``` -**Why:** Studio-ui expects `{ name, component }` format (see studio-ui/src/main.ts:183-189) -**Affects:** -- `/packages/standalone-ui/src/questions/index.ts` -- `/packages/sk-contributor/src/questions/index.ts` - ---- - -## 3. Question Index - TypeScript Interface -**File:** `src/questions/index.ts` -**Location:** `CustomQuestionsExport` interface -**Change:** -```typescript -export interface CustomQuestionsExport { - courses: CourseWare[]; - questionClasses: Array; - dataShapes: DataShape[]; - views: Array<{ name: string; component: ViewComponent }>; // CHANGED from ViewComponent[] - inlineComponents: Record; - meta: { /* ... */ }; -} -``` -**Why:** Matches runtime format -**Affects:** -- `/packages/standalone-ui/src/questions/index.ts` -- `/packages/sk-contributor/src/questions/index.ts` - ---- - -## 4. Main.ts - Import Questions Index -**File:** `src/main.ts` -**Location:** Before `allCourseWare.courses.push(exampleCourse)` -**Change:** -```typescript -// Import allCourseWare singleton and exampleCourse -import { allCourseWare } from '@vue-skuilder/courseware'; -// Import from index.ts to ensure view setup code runs -import './questions/index'; // ADD THIS LINE -import { exampleCourse } from './questions/exampleCourse'; -``` -**Why:** Ensures static view setup runs before course registration -**Affects:** -- `/packages/standalone-ui/src/main.ts` -- `/packages/sk-contributor/src/main.ts` - ---- - -## 5. Question Class - Direct Inline Views -**File:** `src/questions/MyQuestion.ts` -**Location:** Question class static properties -**Change:** -```typescript -// Import at top -import { markRaw } from 'vue'; -import MyQuestionView from './MyQuestionView.vue'; - -export class MyQuestion extends Question { - public static dataShapes = [/* ... */]; - - // Direct inline registration - no external setup needed - public static views = [markRaw(MyQuestionView)]; // CHANGED from empty array - - // ... -} -``` -**Why:** Self-contained, works immediately, no fragile side-effects -**Affects:** -- Template examples in `/packages/standalone-ui/src/questions/README.md` -- Template examples in `/packages/sk-contributor/src/questions/README.md` -- Existing template questions (NumberRangeQuestion, etc.) - ---- - -## 6. Vue Component - DefineOptions Name -**File:** `src/questions/MyQuestionView.vue` -**Location:** Script setup -**Change:** -```typescript -