single.html (10200B)
1 {{ define "title" }}{{ .Title }} · {{ .Site.Title }}{{ end }} 2 3 {{ define "header" }} 4 {{ $discSlug := .RelPermalink | strings.TrimSuffix "/" | path.Dir | path.Base }} 5 <a class="site-name" href="{{ "/" | relURL }}">direito</a> 6 {{ range $.Site.Sections }} 7 {{ if and (eq .Section "txts") (eq (.RelPermalink | strings.TrimSuffix "/" | path.Base) $discSlug) }} 8 <span class="header-sep">/</span> 9 <a class="breadcrumb-link" href="{{ .RelPermalink }}">{{ .Title }}</a> 10 {{ end }} 11 {{ end }} 12 <span class="header-sep">/</span> 13 <span class="breadcrumb">{{ .Title }}</span> 14 {{ end }} 15 16 {{ define "main" }} 17 {{ $slug := .File.BaseFileName }} 18 {{ $discSlug := .RelPermalink | strings.TrimSuffix "/" | path.Dir | path.Base }} 19 20 {{/* Encontra quiz do assunto (exercício, não simulado) */}} 21 {{ $quizPage := false }} 22 {{ range $.Site.RegularPages }} 23 {{ if eq .Section "quizzes" }} 24 {{ $parent := .File.Dir | strings.TrimSuffix "/" | path.Base }} 25 {{ if and (eq $parent $discSlug) (eq .File.BaseFileName $slug) }} 26 {{ if not (or (.Params.simulado) (in (.File.BaseFileName | lower) "simulado")) }} 27 {{ $quizPage = . }} 28 {{ end }} 29 {{ end }} 30 {{ end }} 31 {{ end }} 32 33 <div class="page-text fade"> 34 <div class="text-meta"> 35 {{ range $.Site.Sections }} 36 {{ if and (eq .Section "txts") (eq (.RelPermalink | strings.TrimSuffix "/" | path.Base) $discSlug) }} 37 <span>{{ .Title }}</span><span class="dot"></span> 38 {{ end }} 39 {{ end }} 40 <span>assunto</span> 41 </div> 42 <h1 class="text-title">{{ .Title }}</h1> 43 44 {{/* Colapsáveis: guia de estudo e materiais do assunto */}} 45 {{ $hasExtras := or .Params.guide (or .Params.files (or .Params.videos .Params.audios)) }} 46 {{ if $hasExtras }} 47 <div class="disc-extras-wrap"> 48 {{ partial "disc-extras.html" . }} 49 </div> 50 {{ end }} 51 52 <nav class="toc" id="toc-nav" style="display:none;" aria-label="Sumário"> 53 <div class="toc-label">sumário</div> 54 <ol id="toc-list"></ol> 55 </nav> 56 57 <article class="prose" id="prose">{{ .Content }}</article> 58 59 {{/* Notas de rodapé — renderizadas pelo Hugo automaticamente no .Content; 60 o floater (footnotes.js) intercepta os links #fn: e mostra tooltip */}} 61 62 {{/* Questões do assunto — quiz inline embutido */}} 63 {{ if $quizPage }} 64 <div class="inline-quiz-wrap" id="inline-quiz-section"> 65 <div class="inline-quiz-head"> 66 <span class="sq-label">exercícios deste assunto</span> 67 <a class="inline-quiz-link" href="{{ $quizPage.RelPermalink }}">modo completo →</a> 68 </div> 69 <div id="inline-quiz-body"> 70 <button class="btn btn-start-quiz" id="btn-start-inline" onclick="startInlineQuiz()"> 71 Iniciar exercícios 72 </button> 73 </div> 74 <div id="inline-quiz-player" style="display:none;"> 75 <div class="progress-wrap" style="margin-bottom:.75rem;"><div class="progress-fill" id="iprog"></div></div> 76 <div class="q-meta" id="iq-counter"></div> 77 <div id="iq-body"></div> 78 <div class="next-row"> 79 <button class="btn" id="ibtn-next" onclick="inlineNextQuestion()" style="display:none">próxima →</button> 80 </div> 81 </div> 82 <div id="inline-quiz-result" style="display:none;"> 83 <div class="res-score" id="ires-pct">0%</div> 84 <div class="res-subtitle"><span id="ires-a">0</span> de <span id="ires-t">0</span> acertos</div> 85 <div class="res-msg" style="margin-top:1rem;"> 86 <div class="res-msg-label">diagnóstico</div> 87 <div id="ires-msg"></div> 88 </div> 89 <div class="res-btns" style="margin-top:1.2rem;"> 90 <button class="btn" onclick="restartInlineQuiz()">refazer</button> 91 <a class="btn" href="{{ $quizPage.RelPermalink }}">modo completo</a> 92 </div> 93 </div> 94 </div> 95 <script> 96 (function() { 97 const RAW = {{ $quizPage.RawContent | jsonify | safeJS }}; 98 // Remove frontmatter YAML e notas de rodapé 99 const body = RAW.replace(/^---[\s\S]*?---\n/, '').replace(/\n\[\^\d+\]:[^\n]*/g, ''); 100 window._IQ = { raw: body, questions: [], idx: 0, acertos: 0, erros: 0, answered: false, flipped: false }; 101 })(); 102 103 function startInlineQuiz() { 104 document.getElementById('btn-start-inline').style.display = 'none'; 105 const qs = prepareQuizQuestions(parseQuizBody(window._IQ.raw)); 106 window._IQ.questions = qs; 107 window._IQ.idx = 0; window._IQ.acertos = 0; window._IQ.erros = 0; 108 document.getElementById('inline-quiz-player').style.display = ''; 109 _iqRender(); 110 } 111 112 function _iqRender() { 113 const q = window._IQ.questions[window._IQ.idx]; 114 if (!q) return; 115 window._IQ.answered = false; window._IQ.flipped = false; 116 const total = window._IQ.questions.length; 117 document.getElementById('iq-counter').textContent = (window._IQ.idx + 1) + ' de ' + total; 118 document.getElementById('iprog').style.width = ((window._IQ.idx + 1) / total * 100) + '%'; 119 document.getElementById('ibtn-next').style.display = 'none'; 120 const body = document.getElementById('iq-body'); 121 if (q.type === 'mc') { 122 body.innerHTML = '<div class="mc-area fade"><p class="q-text">' + md(q.text) + '</p><div class="options">' 123 + q.options.map((o, i) => '<button class="opt" data-opt="' + esc(o) + '" data-answer="' + esc(q.answer) + '" onclick="iqSelectOpt(this)" aria-label="Opção ' + LETRAS[i] + ': ' + o + '"><span class="opt-letter">' + LETRAS[i] + '</span><span>' + md(o) + '</span></button>').join('') 124 + '</div><div class="feedback-line" id="iq-feedback" aria-live="polite"><span class="feedback-dot"></span><span id="iq-feedback-msg"></span></div>' 125 + (q.comment ? '<div class="comment-block" id="iq-comment"><div class="comment-label">comentário</div><div>' + md(q.comment) + '</div></div>' : '') 126 + '</div>'; 127 } else { 128 body.innerHTML = '<div class="flashcard-area fade"><p class="q-text">' + md(q.text) + '</p>' 129 + '<div class="flashcard-simple" id="iq-flashcard"><button class="btn btn-reveal" onclick="iqFlip()">Revelar Resposta</button></div>' 130 + '<div class="feedback-line" id="iq-feedback" aria-live="polite"><span class="feedback-dot"></span><span id="iq-feedback-msg"></span></div>' 131 + (q.comment ? '<div class="comment-block" id="iq-comment"><div class="comment-label">comentário</div><div>' + md(q.comment) + '</div></div>' : '') 132 + '<div class="flashcard-btns" id="iq-fc-btns"><button class="btn btn-ok" onclick="iqMarkOk()">✓ Acertei</button><button class="btn btn-bad" onclick="iqMarkBad()">✗ Errei</button></div>' 133 + '</div>'; 134 } 135 } 136 137 function iqSelectOpt(btn) { 138 if (window._IQ.answered) return; 139 window._IQ.answered = true; 140 const chosen = btn.dataset.opt, correct = btn.dataset.answer; 141 btn.closest('.options').querySelectorAll('.opt').forEach(b => { 142 b.disabled = true; 143 if (b.dataset.opt === correct) b.classList.add('correct'); 144 else if (b === btn) b.classList.add('wrong'); 145 else b.classList.add('revealed'); 146 }); 147 const ok = chosen === correct; 148 ok ? window._IQ.acertos++ : window._IQ.erros++; 149 _iqFeedback(ok, ok ? 'Correto' : 'Incorreto — a correta está destacada'); 150 document.getElementById('iq-comment')?.classList.add('show'); 151 document.getElementById('ibtn-next').style.display = ''; 152 } 153 154 function iqFlip() { 155 const q = window._IQ.questions[window._IQ.idx]; 156 const card = document.getElementById('iq-flashcard'); 157 if (card) card.innerHTML = '<div class="ref-label">resposta de referência</div><div class="ref-content">' + md(q.reference) + '</div>'; 158 document.getElementById('iq-fc-btns')?.style && (document.getElementById('iq-fc-btns').style.display = ''); 159 } 160 161 function iqMarkOk() { _iqMark(true); } 162 function iqMarkBad() { _iqMark(false); } 163 function _iqMark(ok) { 164 if (window._IQ.answered) return; 165 window._IQ.answered = true; 166 ok ? window._IQ.acertos++ : window._IQ.erros++; 167 _iqFeedback(ok, ok ? 'Marcado como acertado' : 'Marcado como errado'); 168 document.getElementById('iq-comment')?.classList.add('show'); 169 const btns = document.getElementById('iq-fc-btns'); 170 if (btns) btns.innerHTML = ''; 171 document.getElementById('ibtn-next').style.display = ''; 172 } 173 174 function _iqFeedback(ok, msg) { 175 const fb = document.getElementById('iq-feedback'); 176 if (fb) { fb.className = 'feedback-line show ' + (ok ? 'ok' : 'bad'); } 177 const fm = document.getElementById('iq-feedback-msg'); 178 if (fm) fm.textContent = msg; 179 } 180 181 function inlineNextQuestion() { 182 window._IQ.idx++; 183 if (window._IQ.idx >= window._IQ.questions.length) { 184 _iqShowResult(); 185 } else { 186 _iqRender(); 187 } 188 } 189 190 function _iqShowResult() { 191 document.getElementById('inline-quiz-player').style.display = 'none'; 192 document.getElementById('inline-quiz-result').style.display = ''; 193 const { acertos, erros, questions } = window._IQ; 194 const total = questions.length; 195 const pct = total ? Math.round(acertos / total * 100) : 0; 196 document.getElementById('ires-pct').textContent = pct + '%'; 197 document.getElementById('ires-a').textContent = acertos; 198 document.getElementById('ires-t').textContent = total; 199 let nivel = pct >= 90 ? 'Excelente' : pct >= 70 ? 'Bom' : pct >= 50 ? 'Regular' : 'Insuficiente'; 200 let det = pct >= 90 ? 'Domínio sólido deste assunto.' : pct >= 70 ? 'Boa base, revise os erros.' : pct >= 50 ? 'Lacunas importantes, releia o texto.' : 'Retome o conteúdo antes de prosseguir.'; 201 document.getElementById('ires-msg').innerHTML = '<strong>' + nivel + '</strong> — ' + acertos + ' de ' + total + ' (' + pct + '%). ' + det; 202 } 203 204 function restartInlineQuiz() { 205 document.getElementById('inline-quiz-result').style.display = 'none'; 206 window._IQ.idx = 0; window._IQ.acertos = 0; window._IQ.erros = 0; 207 window._IQ.questions = prepareQuizQuestions(parseQuizBody(window._IQ.raw)); 208 document.getElementById('inline-quiz-player').style.display = ''; 209 _iqRender(); 210 } 211 </script> 212 {{ end }} 213 214 {{ if .Params.references }} 215 <div class="references"> 216 <div class="ref-head">referências</div> 217 <div class="ref-list"> 218 {{ range .Params.references }}<p>{{ . }}</p>{{ end }} 219 </div> 220 </div> 221 {{ end }} 222 </div> 223 224 {{ end }}