forked from retoor/devplacepy
Add `_alt_from_url` helper in Python rendering and `altFromUrl` in JS ContentRenderer to generate descriptive alt attributes from image filenames, replacing empty alt strings. Update image embed templates and Avatar component to use derived alt text. Migrate inline `style.width` assignments to CSS custom properties (`--poll-pct`, `--hud-xp`, `--quest-pct`, `--bar-pct`, `--quota-pct`) across PollManager, GameFarm, and profile/quest CSS for better maintainability. Introduce new admin, docs, projects, services, and base CSS utility classes. Add "Code Farm" docs page entry.
136 lines
8.0 KiB
HTML
136 lines
8.0 KiB
HTML
{% extends "base.html" %}
|
|
{% from "_macros.html" import modal %}
|
|
{% block extra_head %}
|
|
<link rel="stylesheet" href="{{ static_url('/static/css/gists.css') }}">
|
|
<link rel="stylesheet" href="{{ static_url('/static/css/post.css') }}">
|
|
<link rel="stylesheet" href="{{ static_url('/static/vendor/codemirror/codemirror.min.css') }}">
|
|
<link rel="stylesheet" href="{{ static_url('/static/vendor/codemirror/theme/monokai.min.css') }}">
|
|
{% endblock %}
|
|
{% block content %}
|
|
<div class="gist-detail-page">
|
|
<a href="/gists" class="back-link">← Back to Gists</a>
|
|
|
|
<article class="gist-detail">
|
|
<div class="gist-detail-header">
|
|
<h1 class="gist-detail-title">{{ render_title(gist['title']) }}</h1>
|
|
<span class="gist-language-badge">📝 {{ language_name(gist['language']) }}</span>
|
|
</div>
|
|
|
|
<div class="gist-detail-author">
|
|
{% set _size = 32 %}{% set _size_class = "sm" %}{% set _user = author %}{% include "_avatar_link.html" %}
|
|
<div>
|
|
{% set _user = author %}{% set _class = none %}{% include "_user_link.html" %}
|
|
<span class="meta-muted">· Level {{ author.get('level', 1) if author else 1 }}</span>
|
|
<span class="meta-muted meta-muted-spaced">· {{ dt_ago(gist.created_at) if gist.get('created_at') else time_ago }}</span>
|
|
</div>
|
|
</div>
|
|
|
|
{% if gist.get('description') %}
|
|
<div class="gist-detail-desc rendered-content">{{ render_content(gist['description']) }}</div>
|
|
{% endif %}
|
|
|
|
{% if attachments %}
|
|
{% include "_attachment_display.html" %}
|
|
{% endif %}
|
|
|
|
<div class="gist-code-block">
|
|
<div class="gist-code-header">
|
|
<span class="gist-language-name">{{ language_name(gist['language']) }}</span>
|
|
<button type="button" class="gist-copy-btn" data-copy="gist-code-content">Copy</button>
|
|
</div>
|
|
<pre><code id="gist-code-content" class="language-{{ gist['language'] }}">{{ gist['source_code'] }}</code></pre>
|
|
</div>
|
|
|
|
<div class="gist-detail-actions">
|
|
<button type="button" class="gist-star-btn" data-share="/gists/{{ gist['slug'] or gist['uid'] }}"><span class="icon">🔗</span><span class="label"> Share</span></button>
|
|
{% if user %}
|
|
{% set _type = "gist" %}{% set _uid = gist['uid'] %}{% set _my_vote = my_vote %}{% set _count = star_count %}{% set _btn_class = "gist-star-btn" %}{% include "_star_vote.html" %}
|
|
{% endif %}
|
|
{% set _type = "gist" %}{% set _uid = gist['uid'] %}{% set _bookmarked = bookmarked %}{% include "_bookmark_button.html" %}
|
|
{% if is_owner %}
|
|
<button type="button" class="gist-star-btn" data-modal="edit-gist-modal"><span class="icon">✏️</span><span class="label">Edit</span></button>
|
|
{% endif %}
|
|
{% if is_owner or is_admin(user) %}
|
|
<form method="POST" action="/gists/delete/{{ gist['slug'] or gist['uid'] }}" class="inline-form">
|
|
<button type="submit" class="gist-star-btn" data-confirm="Delete this gist?"><span class="icon">🗑️</span><span class="label">Delete</span></button>
|
|
</form>
|
|
{% endif %}
|
|
{% set _type = "gist" %}{% set _uid = gist['uid'] %}{% set _reactions = reactions %}{% include "_reaction_bar.html" %}
|
|
</div>
|
|
</article>
|
|
|
|
{% if is_owner %}
|
|
{% call modal('edit-gist-modal', 'Edit Gist', wide=true) %}
|
|
<form method="POST" action="/gists/edit/{{ gist['slug'] or gist['uid'] }}">
|
|
<div class="auth-field auth-field-gap">
|
|
<label for="edit-gist-title">Title</label>
|
|
<input type="text" id="edit-gist-title" name="title" required maxlength="200" value="{{ gist['title'] }}">
|
|
</div>
|
|
<div class="auth-field auth-field-gap">
|
|
<label for="edit-gist-description">Description (optional)</label>
|
|
<textarea id="edit-gist-description" name="description" maxlength="5000" class="min-h-80" data-mention>{{ gist.get('description', '') }}</textarea>
|
|
</div>
|
|
<div class="auth-field auth-field-gap">
|
|
<label for="edit-gist-language">Language</label>
|
|
<select id="edit-gist-language" name="language">
|
|
{% for code, name in languages %}
|
|
<option value="{{ code }}" {% if code == gist['language'] %}selected{% endif %}>{{ name }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
<div class="auth-field auth-field-gap-last">
|
|
<label for="edit-gist-source-editor">Source Code</label>
|
|
<textarea id="edit-gist-source-editor" name="source_code" class="hidden-textarea" data-language="{{ gist['language'] }}">{{ gist['source_code'] }}</textarea>
|
|
</div>
|
|
{% include "_attachment_form.html" %}
|
|
<div class="modal-footer">
|
|
<button type="button" class="modal-close btn btn-secondary">Cancel</button>
|
|
<button type="submit" class="btn btn-primary"><span class="icon">💾</span>Save Changes</button>
|
|
</div>
|
|
</form>
|
|
{% endcall %}
|
|
{% endif %}
|
|
|
|
{% with target_uid=gist['uid'], target_type="gist" %}
|
|
{% include "_comment_section.html" %}
|
|
{% endwith %}
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/codemirror.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/python/python.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/javascript/javascript.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/clike/clike.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/htmlmixed/htmlmixed.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/xml/xml.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/css/css.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/go/go.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/rust/rust.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/sql/sql.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/shell/shell.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/yaml/yaml.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/markdown/markdown.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/swift/swift.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/php/php.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/ruby/ruby.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/haskell/haskell.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/lua/lua.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/perl/perl.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/r/r.min.js') }}"></script>
|
|
<script defer src="{{ static_url('/static/vendor/codemirror/mode/dart/dart.min.js') }}"></script>
|
|
<script type="module" src="{{ static_url('/static/js/GistEditor.js') }}"></script>
|
|
<script type="module">
|
|
const editModal = document.getElementById("edit-gist-modal");
|
|
if (editModal) {
|
|
const editGistEditor = new window.GistEditor("edit-gist-source-editor", "edit-gist-language");
|
|
const observer = new MutationObserver(() => {
|
|
if (editModal.classList.contains("visible")) {
|
|
editGistEditor.refresh();
|
|
}
|
|
});
|
|
observer.observe(editModal, { attributes: true, attributeFilter: ["class"] });
|
|
}
|
|
</script>
|
|
{% endblock %}
|