// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. // import "preact/debug"; // Include this line only when debugging rendering import "./kataViewer.css"; import { render } from "preact"; import { useEffect } from "preact/hooks"; // This viewer uses the html version of the katas bundle and MathJax, as quantum.microsoft.com does import { Exercise, ExplainedSolutionItem, Kata, Lesson, getAllKatas, } from "qsharp-lang/katas"; import { ensureTheme, detectThemeChange, updateStyleSheetTheme, } from "qsharp-lang/ux"; declare global { // The below are added by the MathJax and Highlight.js scripts interface Window { MathJax: any; hljs: any; } } window.MathJax = { loader: { load: ["[tex]/color", "[tex]/braket"], }, tex: { packages: { "[+]": ["color", "braket"] }, inlineMath: [ ["$", "$"], ["\\(", "\\)"], ], formatError: (jax: any, err: any) => { console.log("LaTeX processing error occurred. ", err, jax); const errorNode = document.createElement("div"); errorNode.innerText = `LaTeX processing error: ${err.message}.\nLaTeX: ${jax.latex}\n\n`; errorNode.style.fontSize = "20px"; errorNode.style.color = "red"; document.querySelector("#errors")?.appendChild(errorNode); window.scroll(0, 0); jax.formatError(err); }, }, startup: { pageReady: async () => { await onload(); return window.MathJax.startup.defaultPageReady(); }, }, }; function Nav(props: { katas: Kata[]; onnav: (index: number) => void; selected: number; }) { return ( ); } function KataEl(props: { kata: Kata }) { useEffect(() => { window.hljs.highlightAll(); window.MathJax.texReset(); window.MathJax.typesetClear(); window.MathJax.typesetPromise([".content"]); }, [props.kata.id]); window.scrollTo(0, 0); return (

{props.kata.title}

{props.kata.sections.map((section) => section.type === "lesson" ? ( ) : ( ), )}
); } function LessonEl(props: { lesson: Lesson }) { const item = props.lesson; return ( <>

{item.title}

{item.items.map((item) => { switch (item.type) { case "text-content": return (
); case "question": return ( <>

Question

Answer

{item.answer.items.map((answer) => ( ))} ); case "example": return (
                {item.code}
              
); } })} ); } function ExerciseEl(props: { exercise: Exercise }) { const item = props.exercise; return ( <>

{"Exercise: " + item.title}

        {item.placeholderCode}
      

Solution

{item.explainedSolution.items.map((item) => ( ))} ); } function ExplainedSolution(props: { item: ExplainedSolutionItem }) { const item = props.item; return (
{item.type === "text-content" ? (
) : (
          {item.code}
        
)}
); } async function onload() { // Helper to react to theme changes by updating the GitHub and Highlightjs stylesheets const onThemeChange = (isDark: boolean) => { updateStyleSheetTheme( isDark, "gh/highlightjs", /(default\.min\.css)|(dark\.min\.css)/, "default.min.css", "dark.min.css", ); updateStyleSheetTheme( isDark, "github-markdown-css", /(light\.css)|(dark\.css)/, "light.css", "dark.css", ); }; // Ensure a theme is set on load, set the stylesheet accordingly, and react to future changes onThemeChange(ensureTheme() || false); detectThemeChange(document.body, onThemeChange); const katas = await getAllKatas({ includeUnpublished: true }); const app = document.querySelector("#app") as HTMLDivElement; function onRender(index: number) { render( <>