Skip to content

Latest commit

 

History

History
114 lines (86 loc) · 6.19 KB

WIDGET_SPEC.md

File metadata and controls

114 lines (86 loc) · 6.19 KB

互动组件规范(CourseForge Widget Spec)v0.1

目的:让老师用 WorkBuddy / 任意大模型自由生成的 HTML 小部件,都能在 CourseForge 里稳定展示、统一风格、可通信、可复用。 没有这套规范,大模型会自由发挥尺寸/技术栈,导致"在编辑器里显示错位、导出后打不开、和课件风格割裂"——这是你最担心的点。


1. 核心约束(生成时必须遵守)

# 约束 说明
1 自包含、可离线 禁止外链任何 CDN / 网络字体 / 远程图片 / 远程 JS 库。所有 CSS、JS 内联;图片转 base64。离线环境(断网、U盘)必须能跑。
2 填满容器 根元素 width:100%;height:100%;内部用相对单位(%/clamp/vw/vh/em),不要写死大像素尺寸。设计基准建议 320×200,实际由容器自适应缩放。
3 主题色用变量 配色使用 CSS 变量 var(--cf-brand) / var(--cf-bg) / var(--cf-text),不要写死主色。编辑器会自动把当前课件主题注入 iframe 文档根,组件自动跟随课件风格。
4 生命周期 监听来自课件的消息:{type:'cf:activate'} 开始/重置,{type:'cf:deactivate'} 暂停/清理。用于"翻到本页才加载/运行"。
5 上报(推荐) 完成/得分用 parent.postMessage({source:'cf-widget',type:'cf:event',event:'complete',score:100},'*') 上报,课件可据此记录学习行为。
6 权限(按需) 摄像头/麦克风仅在用户手势内调用 getUserMedia,不要自动弹权限。编辑器侧提供组件级开关(perms.camera / perms.microphone / perms.sameOrigin):开启音视频会自动追加 allow-same-origin 与 allow="camera; microphone"。注意 getUserMedia 在 opaque origin 下被浏览器拦截,故开启摄像头/麦克风时务必同时开启「允许同源」。
7 单一根节点 一个根 <div>,不要 document.write、不要跳转 parent、不要全局键盘监听(除非必要)。

2. 主题变量(编辑器注入到 iframe 文档根)

组件直接引用即可,无需自己定义:

:root{
  --cf-brand: #2563eb;   /* 主题色 */
  --cf-bg:    #f8fafc;   /* 背景色 */
  --cf-text:  #0f172a;   /* 文字色 */
}

组件内建议同时写一份 :root{--cf-brand:#2563eb;...} 兜底,保证单独打开也好看。


3. 通信协议(postMessage)

课件 → 组件(编辑器实际实现)

  • 主题:编辑器在渲染互动 iframe 时,自动向组件文档根的 :root 注入 --cf-brand / --cf-bg / --cf-surface / --cf-text / --cf-muted / --cf-border / --cf-ok / --cf-warn / --cf-danger / --cf-radius / --cf-font(取自全局统一样式)。组件直接 var(--cf-*) 即用,无需额外消息。
  • 生命周期:翻到含该组件的页面时,编辑器向 iframe 发送(信封字段 __cf:true):
parent ← iframe : { __cf:true, type:'cf:activate', name:'组件标题' }   // 本页激活/开始/重置
parent ← iframe : { __cf:true, type:'cf:deactivate' }                 // 离开本页

组件侧只需 window.addEventListener('message', e => { if(e.data?.type==='cf:activate') ... }) 即可,与规范 v0.1 的语义一致。编辑器另在组件文档内注入一段桥接脚本,把该消息同时派发为同名 CustomEvent,两种监听方式都可用。

组件 → 课件

parent.postMessage({ source:'cf-widget', type:'cf:event', event:'complete', score:100 }, '*');
// event: 'complete' | 'score' | 'interact'

4. 组件清单(manifest,用于平台检索/插入)

每个组件可选配一个 manifest.json:

{
  "name": "浮力选择题",
  "category": "答题",
  "author": "王老师",
  "version": "1.0.0",
  "sizeHint": { "w": 340, "h": 200 },
  "thumbnail": "thumb.png",
  "tags": ["物理", "初中"],
  "allow": { "camera": false, "mic": false },
  "entry": "index.html"
}

5. 组件平台(后期)

  • 一个清单注册表(JSON 列表),每个条目含上面的 manifest + 文件地址。
  • 编辑器「从平台插入」按分类/标签检索,一键插入到当前页容器。
  • 老师可上传共享自己开发的组件;所有组件必须符合本规范才能上架,保证展示与兼容。
  • 平台侧做自动校验:检测是否外链、是否填满容器、是否声明尺寸,不合规打回。

6. 给老师的「提示词框架」

让老师把下面这段固定前缀粘到 WorkBuddy(或任意大模型),再写自己的需求,就能产出合规组件。完整版见 widgets/PROMPT_FRAMEWORK.md,也可内置到编辑器"生成组件"按钮里。

你是一个网页互动课件小组件生成器,输出必须严格遵守《CourseForge 组件规范》:
1. 自包含可离线:禁止外链任何 CDN/字体/图片/JS 库,全部内联,图片用 base64。
2. 填满容器:根元素 width/height:100%,内部用相对单位,不要写死大像素尺寸;设计基准 320×200。
3. 主题色用 CSS 变量 var(--cf-brand)/var(--cf-bg)/var(--cf-text),不要写死主色。
4. 监听 window 消息 {type:'cf:activate'} 开始、{type:'cf:deactivate'} 暂停。
5. 可选:完成用 parent.postMessage({source:'cf-widget',type:'cf:event',event:'complete',score:..},'*') 上报。
6. 摄像头/麦克风仅在用户手势内请求,不要自动弹权限。
7. 只输出一个完整 <!doctype html> 页面,不要任何解释文字。
需求:

7. 编辑器侧责任(实现清单)

  • 支持手动导入合规 HTML
  • 加载组件后,向 iframe 文档根注入 --cf-* 主题变量(跟随全局统一样式)
  • 翻页/预览时向激活页组件发 cf:activate(信封 __cf:true)
  • 接收 cf:event / cf:ready / cf:error 并输出到控制台(可扩展为学习行为记录)
  • 内置"提示词框架"(widgets/PROMPT_FRAMEWORK.md)+ 若干 starter 模板(quiz/vote/drag)
  • 组件级权限开关(摄像头/麦克风/同源),映射到 sandbox + allow 属性
  • 内置"组件平台"面板(后期)
  • 导入外部 HTML 时做规范校验提示(外链/尺寸)