diff options
| author | Sivaldo <sivaldodavi@disroot.org> | 2026-06-13 19:20:23 -0300 |
|---|---|---|
| committer | Sivaldo <sivaldodavi@disroot.org> | 2026-06-13 19:20:23 -0300 |
| commit | 7316238f16655bd127b04476bbf7864b27f940f9 (patch) | |
| tree | 61f25290b3e5fd14894e52754cfe6dd4e85845ef /layouts/txts | |
Diffstat (limited to 'layouts/txts')
| -rw-r--r-- | layouts/txts/single.html | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/layouts/txts/single.html b/layouts/txts/single.html new file mode 100644 index 0000000..d8f7eb1 --- /dev/null +++ b/layouts/txts/single.html @@ -0,0 +1,224 @@ +{{ define "title" }}{{ .Title }} · {{ .Site.Title }}{{ end }} + +{{ define "header" }} + {{ $discSlug := .RelPermalink | strings.TrimSuffix "/" | path.Dir | path.Base }} + <a class="site-name" href="{{ "/" | relURL }}">direito</a> + {{ range $.Site.Sections }} + {{ if and (eq .Section "txts") (eq (.RelPermalink | strings.TrimSuffix "/" | path.Base) $discSlug) }} + <span class="header-sep">/</span> + <a class="breadcrumb-link" href="{{ .RelPermalink }}">{{ .Title }}</a> + {{ end }} + {{ end }} + <span class="header-sep">/</span> + <span class="breadcrumb">{{ .Title }}</span> +{{ end }} + +{{ define "main" }} +{{ $slug := .File.BaseFileName }} +{{ $discSlug := .RelPermalink | strings.TrimSuffix "/" | path.Dir | path.Base }} + +{{/* Encontra quiz do assunto (exercício, não simulado) */}} +{{ $quizPage := false }} +{{ range $.Site.RegularPages }} + {{ if eq .Section "quizzes" }} + {{ $parent := .File.Dir | strings.TrimSuffix "/" | path.Base }} + {{ if and (eq $parent $discSlug) (eq .File.BaseFileName $slug) }} + {{ if not (or (.Params.simulado) (in (.File.BaseFileName | lower) "simulado")) }} + {{ $quizPage = . }} + {{ end }} + {{ end }} + {{ end }} +{{ end }} + +<div class="page-text fade"> + <div class="text-meta"> + {{ range $.Site.Sections }} + {{ if and (eq .Section "txts") (eq (.RelPermalink | strings.TrimSuffix "/" | path.Base) $discSlug) }} + <span>{{ .Title }}</span><span class="dot"></span> + {{ end }} + {{ end }} + <span>assunto</span> + </div> + <h1 class="text-title">{{ .Title }}</h1> + + {{/* Colapsáveis: guia de estudo e materiais do assunto */}} + {{ $hasExtras := or .Params.guide (or .Params.files (or .Params.videos .Params.audios)) }} + {{ if $hasExtras }} + <div class="disc-extras-wrap"> + {{ partial "disc-extras.html" . }} + </div> + {{ end }} + + <nav class="toc" id="toc-nav" style="display:none;" aria-label="Sumário"> + <div class="toc-label">sumário</div> + <ol id="toc-list"></ol> + </nav> + + <article class="prose" id="prose">{{ .Content }}</article> + + {{/* Notas de rodapé — renderizadas pelo Hugo automaticamente no .Content; + o floater (footnotes.js) intercepta os links #fn: e mostra tooltip */}} + + {{/* Questões do assunto — quiz inline embutido */}} + {{ if $quizPage }} + <div class="inline-quiz-wrap" id="inline-quiz-section"> + <div class="inline-quiz-head"> + <span class="sq-label">exercícios deste assunto</span> + <a class="inline-quiz-link" href="{{ $quizPage.RelPermalink }}">modo completo →</a> + </div> + <div id="inline-quiz-body"> + <button class="btn btn-start-quiz" id="btn-start-inline" onclick="startInlineQuiz()"> + Iniciar exercícios + </button> + </div> + <div id="inline-quiz-player" style="display:none;"> + <div class="progress-wrap" style="margin-bottom:.75rem;"><div class="progress-fill" id="iprog"></div></div> + <div class="q-meta" id="iq-counter"></div> + <div id="iq-body"></div> + <div class="next-row"> + <button class="btn" id="ibtn-next" onclick="inlineNextQuestion()" style="display:none">próxima →</button> + </div> + </div> + <div id="inline-quiz-result" style="display:none;"> + <div class="res-score" id="ires-pct">0%</div> + <div class="res-subtitle"><span id="ires-a">0</span> de <span id="ires-t">0</span> acertos</div> + <div class="res-msg" style="margin-top:1rem;"> + <div class="res-msg-label">diagnóstico</div> + <div id="ires-msg"></div> + </div> + <div class="res-btns" style="margin-top:1.2rem;"> + <button class="btn" onclick="restartInlineQuiz()">refazer</button> + <a class="btn" href="{{ $quizPage.RelPermalink }}">modo completo</a> + </div> + </div> + </div> + <script> + (function() { + const RAW = {{ $quizPage.RawContent | jsonify | safeJS }}; + // Remove frontmatter YAML e notas de rodapé + const body = RAW.replace(/^---[\s\S]*?---\n/, '').replace(/\n\[\^\d+\]:[^\n]*/g, ''); + window._IQ = { raw: body, questions: [], idx: 0, acertos: 0, erros: 0, answered: false, flipped: false }; + })(); + + function startInlineQuiz() { + document.getElementById('btn-start-inline').style.display = 'none'; + const qs = prepareQuizQuestions(parseQuizBody(window._IQ.raw)); + window._IQ.questions = qs; + window._IQ.idx = 0; window._IQ.acertos = 0; window._IQ.erros = 0; + document.getElementById('inline-quiz-player').style.display = ''; + _iqRender(); + } + + function _iqRender() { + const q = window._IQ.questions[window._IQ.idx]; + if (!q) return; + window._IQ.answered = false; window._IQ.flipped = false; + const total = window._IQ.questions.length; + document.getElementById('iq-counter').textContent = (window._IQ.idx + 1) + ' de ' + total; + document.getElementById('iprog').style.width = ((window._IQ.idx + 1) / total * 100) + '%'; + document.getElementById('ibtn-next').style.display = 'none'; + const body = document.getElementById('iq-body'); + if (q.type === 'mc') { + body.innerHTML = '<div class="mc-area fade"><p class="q-text">' + md(q.text) + '</p><div class="options">' + + 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('') + + '</div><div class="feedback-line" id="iq-feedback" aria-live="polite"><span class="feedback-dot"></span><span id="iq-feedback-msg"></span></div>' + + (q.comment ? '<div class="comment-block" id="iq-comment"><div class="comment-label">comentário</div><div>' + md(q.comment) + '</div></div>' : '') + + '</div>'; + } else { + body.innerHTML = '<div class="flashcard-area fade"><p class="q-text">' + md(q.text) + '</p>' + + '<div class="flashcard-simple" id="iq-flashcard"><button class="btn btn-reveal" onclick="iqFlip()">Revelar Resposta</button></div>' + + '<div class="feedback-line" id="iq-feedback" aria-live="polite"><span class="feedback-dot"></span><span id="iq-feedback-msg"></span></div>' + + (q.comment ? '<div class="comment-block" id="iq-comment"><div class="comment-label">comentário</div><div>' + md(q.comment) + '</div></div>' : '') + + '<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>' + + '</div>'; + } + } + + function iqSelectOpt(btn) { + if (window._IQ.answered) return; + window._IQ.answered = true; + const chosen = btn.dataset.opt, correct = btn.dataset.answer; + btn.closest('.options').querySelectorAll('.opt').forEach(b => { + b.disabled = true; + if (b.dataset.opt === correct) b.classList.add('correct'); + else if (b === btn) b.classList.add('wrong'); + else b.classList.add('revealed'); + }); + const ok = chosen === correct; + ok ? window._IQ.acertos++ : window._IQ.erros++; + _iqFeedback(ok, ok ? 'Correto' : 'Incorreto — a correta está destacada'); + document.getElementById('iq-comment')?.classList.add('show'); + document.getElementById('ibtn-next').style.display = ''; + } + + function iqFlip() { + const q = window._IQ.questions[window._IQ.idx]; + const card = document.getElementById('iq-flashcard'); + if (card) card.innerHTML = '<div class="ref-label">resposta de referência</div><div class="ref-content">' + md(q.reference) + '</div>'; + document.getElementById('iq-fc-btns')?.style && (document.getElementById('iq-fc-btns').style.display = ''); + } + + function iqMarkOk() { _iqMark(true); } + function iqMarkBad() { _iqMark(false); } + function _iqMark(ok) { + if (window._IQ.answered) return; + window._IQ.answered = true; + ok ? window._IQ.acertos++ : window._IQ.erros++; + _iqFeedback(ok, ok ? 'Marcado como acertado' : 'Marcado como errado'); + document.getElementById('iq-comment')?.classList.add('show'); + const btns = document.getElementById('iq-fc-btns'); + if (btns) btns.innerHTML = ''; + document.getElementById('ibtn-next').style.display = ''; + } + + function _iqFeedback(ok, msg) { + const fb = document.getElementById('iq-feedback'); + if (fb) { fb.className = 'feedback-line show ' + (ok ? 'ok' : 'bad'); } + const fm = document.getElementById('iq-feedback-msg'); + if (fm) fm.textContent = msg; + } + + function inlineNextQuestion() { + window._IQ.idx++; + if (window._IQ.idx >= window._IQ.questions.length) { + _iqShowResult(); + } else { + _iqRender(); + } + } + + function _iqShowResult() { + document.getElementById('inline-quiz-player').style.display = 'none'; + document.getElementById('inline-quiz-result').style.display = ''; + const { acertos, erros, questions } = window._IQ; + const total = questions.length; + const pct = total ? Math.round(acertos / total * 100) : 0; + document.getElementById('ires-pct').textContent = pct + '%'; + document.getElementById('ires-a').textContent = acertos; + document.getElementById('ires-t').textContent = total; + let nivel = pct >= 90 ? 'Excelente' : pct >= 70 ? 'Bom' : pct >= 50 ? 'Regular' : 'Insuficiente'; + 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.'; + document.getElementById('ires-msg').innerHTML = '<strong>' + nivel + '</strong> — ' + acertos + ' de ' + total + ' (' + pct + '%). ' + det; + } + + function restartInlineQuiz() { + document.getElementById('inline-quiz-result').style.display = 'none'; + window._IQ.idx = 0; window._IQ.acertos = 0; window._IQ.erros = 0; + window._IQ.questions = prepareQuizQuestions(parseQuizBody(window._IQ.raw)); + document.getElementById('inline-quiz-player').style.display = ''; + _iqRender(); + } + </script> + {{ end }} + + {{ if .Params.references }} + <div class="references"> + <div class="ref-head">referências</div> + <div class="ref-list"> + {{ range .Params.references }}<p>{{ . }}</p>{{ end }} + </div> + </div> + {{ end }} +</div> + +{{ end }} |
