feat(client,challenge-parser): support audio and transcript in quiz questions (#65711)

This commit is contained in:
Huyen Nguyen
2026-02-11 23:52:49 -08:00
committed by GitHub
parent 5202f95af4
commit 1108d25883
20 changed files with 769 additions and 7 deletions
+17
View File
@@ -351,10 +351,27 @@ type Quiz {
questions: [QuizQuestion]
}
type QuizAudio {
filename: String
startTimestamp: Float
finishTimestamp: Float
}
type QuizTranscriptLine {
character: String
text: String
}
type QuizAudioData {
audio: QuizAudio
transcript: [QuizTranscriptLine]
}
type QuizQuestion {
text: String
distractors: [String]
answer: String
audioData: QuizAudioData
}
type RequiredResource {
+17
View File
@@ -347,10 +347,27 @@ type Quiz = {
questions: QuizQuestion[];
};
type QuizAudio = {
filename: string;
startTimestamp?: number | null;
finishTimestamp?: number | null;
};
type QuizTranscriptLine = {
character: string;
text: string;
};
type QuizAudioData = {
audio: QuizAudio;
transcript: QuizTranscriptLine[];
};
type QuizQuestion = {
text: string;
distractors: string[];
answer: string;
audioData?: QuizAudioData | null;
};
export type CertificateNode = {
@@ -25,3 +25,9 @@
.quiz-answer-label:has(ruby) {
line-height: 1.7rem;
}
/* Override global button:hover for the play/pause button in the Quiz component */
.quiz-challenge-container button:has(svg.svg-inline--fa):hover {
background-color: unset;
color: unset;
}
+34 -3
View File
@@ -166,16 +166,36 @@ const ShowQuiz = ({
value: 4
};
return {
const allAnswers = shuffleArray([...distractors, answer]);
const audioData = question.audioData?.audio?.filename
? {
audioUrl: `https://cdn.freecodecamp.org/curriculum/english/animation-assets/sounds/${question.audioData.audio.filename}`,
audioStartTime:
question.audioData.audio.startTimestamp ?? undefined,
audioFinishTime:
question.audioData.audio.finishTimestamp ?? undefined,
transcript: question.audioData.transcript.length
? question.audioData.transcript
.map(line => `<p><b>${line.character}</b>: ${line.text}</p>`)
.join('')
: undefined
}
: {};
const questionData = {
question: (
<PrismFormatted
className='quiz-question-label'
text={question.text}
/>
),
answers: shuffleArray([...distractors, answer]),
correctAnswer: answer.value
answers: allAnswers,
correctAnswer: answer.value,
...audioData
};
return questionData;
})
);
@@ -400,6 +420,17 @@ export const query = graphql`
distractors
text
answer
audioData {
audio {
filename
startTimestamp
finishTimestamp
}
transcript {
character
text
}
}
}
}
tests {