Sync Canvas LMS export feature + refreshed Settings screenshot
Brings the share build up to date with the main project: QTI .zip export and optional direct Canvas API push, plus the Canvas settings card. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
// lib/canvas/manifest.js — the two wrapper files that make a folder of QTI XML into a
|
||||
// Canvas-importable package: imsmanifest.xml (IMS Content Packaging) and the Canvas
|
||||
// proprietary assessment_meta.xml (quiz-level settings).
|
||||
import { xmlEsc } from "./qti";
|
||||
|
||||
// Canvas quiz-level settings. `title` is the only thing Canvas truly needs; everything
|
||||
// else has a sensible Canvas default if omitted. We emit the fields the user can set.
|
||||
export function renderAssessmentMeta(ir, assessmentIdent) {
|
||||
const q = ir.quiz;
|
||||
const lines = [];
|
||||
const tag = (name, val) => lines.push(`<${name}>${xmlEsc(String(val))}</${name}>`);
|
||||
const bool = (name, val) => tag(name, val ? "true" : "false");
|
||||
const opt = (name, val) => { if (val !== "" && val != null) tag(name, val); };
|
||||
|
||||
tag("title", q.title);
|
||||
tag("description", q.description || "");
|
||||
tag("quiz_type", q.quizType);
|
||||
tag("points_possible", q.pointsPossible);
|
||||
opt("time_limit", q.timeLimit);
|
||||
tag("allowed_attempts", q.allowedAttempts);
|
||||
tag("scoring_policy", q.scoringPolicy);
|
||||
bool("shuffle_answers", q.shuffleAnswers);
|
||||
bool("show_correct_answers", q.showCorrectAnswers);
|
||||
bool("one_question_at_a_time", q.oneQuestionAtATime);
|
||||
bool("cant_go_back", q.cantGoBack);
|
||||
opt("access_code", q.accessCode);
|
||||
opt("due_at", q.dueAt);
|
||||
opt("unlock_at", q.unlockAt);
|
||||
opt("lock_at", q.lockAt);
|
||||
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<quiz identifier="${xmlEsc(assessmentIdent)}" xmlns="http://canvas.instructure.com/xsd/cccv1p0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://canvas.instructure.com/xsd/cccv1p0 https://canvas.instructure.com/xsd/cccv1p0.xsd">
|
||||
${lines.join("\n")}
|
||||
</quiz>`;
|
||||
}
|
||||
|
||||
export function renderManifest(assessmentIdent, manifestIdent) {
|
||||
const assessmentHref = `${assessmentIdent}/${assessmentIdent}.xml`;
|
||||
const metaHref = `${assessmentIdent}/assessment_meta.xml`;
|
||||
const depIdent = `${assessmentIdent}_dependency`;
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<manifest identifier="${xmlEsc(manifestIdent)}" xmlns="http://www.imsglobal.org/xsd/imsccv1p1/imscp_v1p1" xmlns:lom="http://ltsc.ieee.org/xsd/imsccv1p1/LOM/resource" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.imsglobal.org/xsd/imsccv1p1/imscp_v1p1 http://www.imsglobal.org/profile/cc/ccv1p1/ccv1p1_imscp_v1p2_v1p0.xsd">
|
||||
<metadata><schema>IMS Content</schema><schemaversion>1.1.3</schemaversion></metadata>
|
||||
<organizations/>
|
||||
<resources>
|
||||
<resource identifier="${xmlEsc(assessmentIdent)}" type="imsqti_xmlv1p2/imscc_xmlv1p1/assessment" href="${xmlEsc(assessmentHref)}">
|
||||
<file href="${xmlEsc(assessmentHref)}"/>
|
||||
<dependency identifierref="${xmlEsc(depIdent)}"/>
|
||||
</resource>
|
||||
<resource identifier="${xmlEsc(depIdent)}" type="associatedcontent/imscc_xmlv1p1/learning-application-resource" href="${xmlEsc(metaHref)}">
|
||||
<file href="${xmlEsc(metaHref)}"/>
|
||||
</resource>
|
||||
</resources>
|
||||
</manifest>`;
|
||||
}
|
||||
Reference in New Issue
Block a user