40 lines
1.5 KiB
HTML
40 lines
1.5 KiB
HTML
{{define "article"}}
|
|
{{template "header" .}}
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
|
|
<section class="max-w-3xl mx-auto px-4 py-12">
|
|
<a href="/" class="inline-flex items-center gap-1 text-sm text-gray-500 hover:text-blue-600 transition-colors mb-6">
|
|
← {{index .Tr "article_back_home"}}
|
|
</a>
|
|
|
|
<article>
|
|
<h1 class="text-4xl font-extrabold text-gray-900 mb-3">{{.Article.Title}}</h1>
|
|
<div class="flex items-center gap-3 text-sm text-gray-500 mb-8">
|
|
{{if .Article.Author.Avatar}}
|
|
<img src="/uploads/avatars/{{.Article.Author.Avatar}}" alt="avatar" class="w-7 h-7 rounded-full object-cover">
|
|
{{end}}
|
|
<span class="font-medium text-gray-700">{{.AuthorName}}</span>
|
|
{{if .PublishedAt}}<span>·</span><span>{{.PublishedAt}}</span>{{end}}
|
|
</div>
|
|
|
|
{{if .Article.Cover}}
|
|
<div class="rounded-xl overflow-hidden mb-8">
|
|
<img src="{{.Article.Cover}}" alt="{{.Article.Title}}" class="w-full max-h-96 object-cover">
|
|
</div>
|
|
{{end}}
|
|
|
|
<div id="articleBody" class="prose max-w-none text-gray-800"></div>
|
|
</article>
|
|
</section>
|
|
|
|
<script>
|
|
// {{.Article.Content}} is emitted by html/template as a JSON-encoded JS
|
|
// string, safely handling quotes, newlines, and HTML special characters.
|
|
var md = {{.Article.Content}};
|
|
document.getElementById('articleBody').innerHTML = marked.parse(md);
|
|
</script>
|
|
|
|
{{template "footer" .}}
|
|
{{end}}
|