Compare commits
2 Commits
1533f82a6b
...
db677abaa5
| Author | SHA1 | Date | |
|---|---|---|---|
|
db677abaa5
|
|||
|
65abea2093
|
@@ -1,11 +1,109 @@
|
|||||||
from flask import Blueprint, render_template
|
from flask import Blueprint, render_template, render_template_string, current_app, abort
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
|
||||||
bp = Blueprint('guides', __name__, url_prefix='/guides/')
|
bp = Blueprint('guides', __name__, url_prefix='/guides/')
|
||||||
|
|
||||||
|
|
||||||
|
def parse_guide_title(content: str):
|
||||||
|
lines = content.strip().split('\n', 1)
|
||||||
|
fline = lines[0].strip()
|
||||||
|
if fline.startswith('#'):
|
||||||
|
title = fline[2:].strip()
|
||||||
|
content = lines[1] if len(lines) > 1 else ''
|
||||||
|
return title, content.strip()
|
||||||
|
|
||||||
|
return None, content.strip()
|
||||||
|
|
||||||
|
|
||||||
|
def get_guides_by_category():
|
||||||
|
guides_dir = Path(current_app.root_path) / 'templates' / 'guides'
|
||||||
|
categories = {}
|
||||||
|
|
||||||
|
for item in guides_dir.iterdir():
|
||||||
|
if item.is_dir() and not item.name.startswith('_'):
|
||||||
|
category = item.name
|
||||||
|
categories[category] = []
|
||||||
|
for guide_file in sorted(item.glob('*.html')):
|
||||||
|
if guide_file.name.startswith('_'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
m = re.match(r'(\d+)-(.+)\.html', guide_file.name)
|
||||||
|
if not m:
|
||||||
|
continue
|
||||||
|
|
||||||
|
sort_num = int(m.group(1))
|
||||||
|
slug = m.group(2)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(guide_file, 'r') as f:
|
||||||
|
content = f.read()
|
||||||
|
|
||||||
|
title, template = parse_guide_title(content)
|
||||||
|
if not title:
|
||||||
|
title = slug.replace('-', ' ').title()
|
||||||
|
|
||||||
|
categories[category].append(({
|
||||||
|
'sort': sort_num,
|
||||||
|
'slug': slug,
|
||||||
|
'filename': guide_file.name,
|
||||||
|
'title': title,
|
||||||
|
'path': f'{category}/{guide_file.name}',
|
||||||
|
'url': f'/guides/{category}/{slug}',
|
||||||
|
'template': template,
|
||||||
|
}))
|
||||||
|
except Exception as e:
|
||||||
|
current_app.logger.warning(f'failed to read {guide_file}: {e}')
|
||||||
|
continue
|
||||||
|
|
||||||
|
categories[category].sort(key=lambda x: x['sort'])
|
||||||
|
|
||||||
|
return categories
|
||||||
|
|
||||||
|
|
||||||
@bp.get('/babycode')
|
@bp.get('/babycode')
|
||||||
def babycode():
|
def babycode():
|
||||||
return render_template('guides/babycode.html')
|
# print(get_guides_by_category())
|
||||||
|
return '<h1>no</h1>'
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get('/<category>/<slug>')
|
||||||
|
def guide_page(category, slug):
|
||||||
|
categories = get_guides_by_category()
|
||||||
|
if category not in categories:
|
||||||
|
abort(404)
|
||||||
|
return
|
||||||
|
|
||||||
|
for i, guide in enumerate(categories[category]):
|
||||||
|
if guide['slug'] != slug:
|
||||||
|
continue
|
||||||
|
|
||||||
|
next_guide = None
|
||||||
|
prev_guide = None
|
||||||
|
if i != 0:
|
||||||
|
prev_guide = categories[category][i - 1]
|
||||||
|
|
||||||
|
if i + 1 < len(categories[category]):
|
||||||
|
next_guide = categories[category][i + 1]
|
||||||
|
|
||||||
|
return render_template_string(guide['template'], next_guide=next_guide, prev_guide=prev_guide, category=category, guide=guide)
|
||||||
|
|
||||||
|
abort(404)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get('/<category>/')
|
||||||
|
def category_index(category):
|
||||||
|
categories = get_guides_by_category()
|
||||||
|
if category not in categories:
|
||||||
|
abort(404)
|
||||||
|
return
|
||||||
|
|
||||||
|
return render_template('guides/category_index.html', category=category, pages=categories[category])
|
||||||
|
|
||||||
|
|
||||||
|
@bp.get('/')
|
||||||
|
def guides_index():
|
||||||
|
return render_template('guides/guides_index.html', categories=get_guides_by_category())
|
||||||
|
|
||||||
|
|
||||||
@bp.get('/contact')
|
@bp.get('/contact')
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<link rel="stylesheet" href="{{ ("/static/css/%s.css" % get_prefers_theme()) | cachebust }}">
|
<link rel="stylesheet" href="{{ ("/static/css/%s.css" % get_prefers_theme()) | cachebust }}">
|
||||||
<link rel="icon" type="image/png" href="/static/favicon.png">
|
<link rel="icon" type="image/png" href="/static/favicon.png">
|
||||||
<script src="{{ '/static/js/vnd/bitty-6.0.0-rc3.min.js' | cachebust }}" type="module"></script>
|
<script src="{{ '/static/js/vnd/bitty-7.0.0-rc1.min.js' | cachebust }}" type="module"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<bitty-6-0 data-connect="{{ '/static/js/bitties/pyrom-bitty.js' | cachebust }}">
|
<bitty-7-0 data-connect="{{ '/static/js/bitties/pyrom-bitty.js' | cachebust }}">
|
||||||
{% include 'common/topnav.html' %}
|
{% include 'common/topnav.html' %}
|
||||||
{% with messages = get_flashed_messages(with_categories=true) %}
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
@@ -24,6 +24,6 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
{% include 'common/footer.html' %}
|
{% include 'common/footer.html' %}
|
||||||
</bitty-6-0>
|
</bitty-7-0>
|
||||||
<script src="{{ "/static/js/ui.js" | cachebust }}"></script>
|
<script src="{{ "/static/js/ui.js" | cachebust }}"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -2,5 +2,6 @@
|
|||||||
<span>Pyrom commit <a href="{{ "https://git.poto.cafe/yagich/pyrom/commit/" + __commit }}">{{ __commit[:8] }}</a></span>
|
<span>Pyrom commit <a href="{{ "https://git.poto.cafe/yagich/pyrom/commit/" + __commit }}">{{ __commit[:8] }}</a></span>
|
||||||
<ul class="horizontal">
|
<ul class="horizontal">
|
||||||
<li><a href="{{ url_for('guides.contact') }}">Contact</a></li>
|
<li><a href="{{ url_for('guides.contact') }}">Contact</a></li>
|
||||||
|
<li><a href="{{ url_for('guides.guides_index') }}">Guides</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
<button data-send="insertBabycodeTag" data-tag="spoiler=" data-break-line="1" data-prefill="hidden content" class="babycode-button contain-svg" type=button id="post-editor-spoiler" title="Insert spoiler" {{"disabled" if "spoiler" in banned_tags else ""}}>{{ icn_spoiler() }}</button>
|
<button data-send="insertBabycodeTag" data-tag="spoiler=" data-break-line="1" data-prefill="hidden content" class="babycode-button contain-svg" type=button id="post-editor-spoiler" title="Insert spoiler" {{"disabled" if "spoiler" in banned_tags else ""}}>{{ icn_spoiler() }}</button>
|
||||||
</span>
|
</span>
|
||||||
<textarea class="babycode-editor" name="{{ ta_name }}" id="babycode-content" placeholder="{{ ta_placeholder }}" {{ "required" if not optional else "" }} autocomplete="off" data-receive="insertBabycodeTag addQuote">{{ prefill }}</textarea>
|
<textarea class="babycode-editor" name="{{ ta_name }}" id="babycode-content" placeholder="{{ ta_placeholder }}" {{ "required" if not optional else "" }} autocomplete="off" data-receive="insertBabycodeTag addQuote">{{ prefill }}</textarea>
|
||||||
<a href="{{ url_for("guides.babycode") }}" target="_blank">babycode guide</a>
|
<a href="{{ url_for("guides.guide_page", category='user', slug='babycode') }}" target="_blank">babycode guide</a>
|
||||||
{% if banned_tags %}
|
{% if banned_tags %}
|
||||||
<div>Forbidden tags:</div>
|
<div>Forbidden tags:</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -296,6 +296,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="guide-toc">
|
<div class="guide-toc">
|
||||||
<h2>Table of contents</h2>
|
<h2>Table of contents</h2>
|
||||||
|
<a href="#top">(top)</a>
|
||||||
{% set toc = sections | extract_h2 %}
|
{% set toc = sections | extract_h2 %}
|
||||||
<ul>
|
<ul>
|
||||||
{% for heading in toc %}
|
{% for heading in toc %}
|
||||||
|
|||||||
21
app/templates/guides/_layout.html
Normal file
21
app/templates/guides/_layout.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% from 'common/macros.html' import guide_sections with context %}
|
||||||
|
{% block title %}guide - {{ guide.title }}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="darkbg" id="top">
|
||||||
|
<h1 class="thread-title">Guide: {{ guide.title }}</h1>
|
||||||
|
<ul class="horizontal">
|
||||||
|
<li><a href="{{ url_for('guides.category_index', category=category) }}">↑ Back to category</a></li>
|
||||||
|
{% if prev_guide %}
|
||||||
|
<li><a href="{{ prev_guide.url }}">← Previous: {{ prev_guide.title }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{% if next_guide %}
|
||||||
|
<li><a href="{{ next_guide.url }}">→ Next: {{ next_guide.title }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% call() guide_sections() %}
|
||||||
|
{% block guide_content %}
|
||||||
|
{% endblock %}
|
||||||
|
{% endcall %}
|
||||||
|
{% endblock %}
|
||||||
15
app/templates/guides/category_index.html
Normal file
15
app/templates/guides/category_index.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block title %}guides - {{ category | title }}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="darkbg settings-container">
|
||||||
|
<h1 class="thread-title">All guides in category "{{ category | replace('-', ' ') | title }}"</h1>
|
||||||
|
<ul>
|
||||||
|
{% for page in pages %}
|
||||||
|
<li><a href="{{ page.url }}">{{ page.title }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
<div>
|
||||||
|
<a href="{{ url_for('guides.guides_index') }}">← All guide categories</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
19
app/templates/guides/guides_index.html
Normal file
19
app/templates/guides/guides_index.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% block title %}guides{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="darkbg settings-container">
|
||||||
|
<h1 class="thread-title">Guides index</h1>
|
||||||
|
<ul>
|
||||||
|
{% for category in categories %}
|
||||||
|
<li>
|
||||||
|
<h2><a href="{{ url_for('guides.category_index', category=category )}}">{{ category | replace('-', ' ') | title }}</a></h2>
|
||||||
|
<ul>
|
||||||
|
{% for page in categories[category] %}
|
||||||
|
<li><a href="{{ page.url }}">{{ page.title }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
76
app/templates/guides/user-guides/01-introduction.html
Normal file
76
app/templates/guides/user-guides/01-introduction.html
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# Introduction
|
||||||
|
{% extends 'guides/_layout.html' %}
|
||||||
|
{% block guide_content %}
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="pyrom">What is {{config.SITE_NAME}}?</h2>
|
||||||
|
{% if config.GUIDE_DESCRIPTION %}
|
||||||
|
<div>{{ config.GUIDE_DESCRIPTION | babycode_strict | safe }}</div>
|
||||||
|
{% endif %}
|
||||||
|
<p>{{ config.SITE_NAME }} is powered by <a href="https://git.poto.cafe/yagich/pyrom/" target="_blank">Pyrom</a>, a home-grown forum software for the indie web. This guide will help you get started, from creating an account to understanding how discussions are organized.</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="signing-up">Signing up</h2>
|
||||||
|
<p>Most interactive features on {{ config.SITE_NAME }} such as creating threads or posting replies require a user account. While browsing is open to all, you must be signed in to participate.</p>
|
||||||
|
{% if config.DISABLE_SIGNUP %}
|
||||||
|
<p>{{ config.SITE_NAME }} uses an invite-only sign-up system. You cannot sign up directly. Instead, {% if config.USERS_CAN_INVITE %}an existing user{% elif config.MODS_CAN_INVITE %}a moderator{% endif %} can generate an invite link containing an invite key. Using that link will take you to the sign up page.</p>
|
||||||
|
{% else %}
|
||||||
|
<p>You can create an account on the <a href="{{url_for('users.sign_up')}}">sign-up page.</a> After you create your account, a moderator will need to manually approve your account before you can post. This may take some time.</p>
|
||||||
|
{% endif %}
|
||||||
|
<p>To create an account, you will need to provide:</p>
|
||||||
|
<ul>
|
||||||
|
<li>A username:
|
||||||
|
<ul>
|
||||||
|
<li>Your username must be 3-20 characters long and only include lowercase letters (a-z), numbers (0-9), hyphens (-) and underscores (_).</li>
|
||||||
|
<li>If your username includes uppercase characters, the system will automatically convert them to lowercase. Your original capitalization will be preserved as part of your display name.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>A strong password:
|
||||||
|
<ul>
|
||||||
|
<li>Your password must be at least 10 characters long and include at least one uppercase letter, at least one lowercase letter, at least one number, at least one special character, and no spaces.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>Once your account is {% if not config.DISABLE_SIGNUP %}confirmed and{% endif %} active, you will have full access to create threads, post replies, and use other features.</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="topics">Topics</h2>
|
||||||
|
<p>The front page of {{ config.SITE_NAME }} is an overview of topics that you can create threads in. A topic is a broad category created by moderators to organize discussions.</p>
|
||||||
|
<p>Topics usually have a description that is shown under its name. Use it as guidance for where to post a thread. The order topics show up in is chosen by moderators.</p>
|
||||||
|
<p>A topic may be locked by a moderator. This will prevent threads from being created or moved into it by non-moderators. These topics are usually used for forum-wide information, but it is of course up to the moderators.</p>
|
||||||
|
<p>By default, threads in a topic are sorted by activity, but this can be changed in your user settings.</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="threads">Threads</h2>
|
||||||
|
<p>Threads are where discussion happens. A thread is started by a user with a name and an initial post, and other users may add their own posts to it (known as replying to the thread).</p>
|
||||||
|
<p>When drafting a thread, you have to choose which topic to post it under. Be sure to follow the posting rules. If you created a thread under the wrong topic, you may move it when viewing replies. Moderators have the option to move any thread.</p>
|
||||||
|
<p>A thread may be locked by the original poster (OP) or a moderator. When a thread is locked, nobody except moderators can reply to it.</p>
|
||||||
|
<p>A thread may also be stickied by a moderator. Stickied threads show above all other threads in the topic it's under. If a thread is stickied, it is likely important.</p>
|
||||||
|
<p>You can subscribe to any thread. When subscribed, you will receive an overview of posts you missed for that thread in your inbox.</p>
|
||||||
|
<p>You can</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="posts">Posts</h2>
|
||||||
|
<p>Posts are the individual messages that make up a thread. The first post starts the thread, and every subsequent message is a post in reply.</p>
|
||||||
|
<p>A post is split up into five sections:</p>
|
||||||
|
<ol>
|
||||||
|
<li>Usercard
|
||||||
|
<ul><li>The post author's information shows up to the left of the post. This includes their avatar, display name, mention, and status.</li></ul>
|
||||||
|
</li>
|
||||||
|
<li>Post actions
|
||||||
|
<ul><li>This shows the time and date when the post has been made (or edited), and buttons for actions you can perform on the post, such as quoting or editing.</li></ul>
|
||||||
|
</li>
|
||||||
|
<li>Post content
|
||||||
|
<ul><li>The actual message of the post.</li></ul>
|
||||||
|
</li>
|
||||||
|
<li>Signature (sig)
|
||||||
|
<ul><li>If the user has a signature set, it will show under each of their posts.</li></ul>
|
||||||
|
</li>
|
||||||
|
<li>Reactions
|
||||||
|
<ul><li>This shows the emoji reactions users have added to the post, and you can add your own.</li></ul>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<p>You may edit or delete your posts after creating them. Edited posts will show when they were edited instead of when they were posted.</p>
|
||||||
|
<p>You can quote another user's post by pressing the <button>Quote</button> button on that post. This will copy the contents of it into the reply box and mention the user.</p>
|
||||||
|
<p>Posts are written in a markup language called Babycode. <a href="{{ url_for("guides.guide_page", category='user', slug='babycode') }}">More information on it can be found in a separate guide.</a></p>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
24
app/templates/guides/user-guides/02-profiles.html
Normal file
24
app/templates/guides/user-guides/02-profiles.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# User profiles
|
||||||
|
{% extends 'guides/_layout.html' %}
|
||||||
|
{% block guide_content %}
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="profile">User profiles</h2>
|
||||||
|
<p>Each user on {{ config.SITE_NAME }} has a profile.</p>
|
||||||
|
<p>A user's profile shows:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Their avatar;</li>
|
||||||
|
<li>Their username and display name;</li>
|
||||||
|
<li>Their status;</li>
|
||||||
|
<li>Their signature;</li>
|
||||||
|
<li>Their stats:
|
||||||
|
<ul>
|
||||||
|
<li>Their permission level (regular user, moderator, etc);</li>
|
||||||
|
<li>The number of posts they've created;</li>
|
||||||
|
<li>The number of threads they've started;</li>
|
||||||
|
<li>A link to their latest started thread;</li>
|
||||||
|
<li>A few of their latest posts.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
64
app/templates/guides/user-guides/03-settings.html
Normal file
64
app/templates/guides/user-guides/03-settings.html
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# User settings
|
||||||
|
{% extends 'guides/_layout.html' %}
|
||||||
|
{% block guide_content %}
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="settings">Settings</h2>
|
||||||
|
<p>You can access your settings by following the "Settings" link in the top navigation bar or from the <button>Settings</button> button in your profile.</p>
|
||||||
|
<p>The settings page lets you set your avatar, change your personalization options, and change your password.</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="avatar">Avatar</h2>
|
||||||
|
<p>When you upload an avatar, keep in mind that it will be cropped to a square and resized to fit 256 by 256 pixels. It's best to upload an image that is already square. Avatars must be no more than 1 MB in size. You can also clear your avatar, resetting it to the default one.</p>
|
||||||
|
<p>To change your avatar, first press the <button>Browse…</button> button and select a file from your device, then press the <button>Save avatar</button> button to upload it.</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="personalization">Personalization</h2>
|
||||||
|
<p>The personalization section of the settings lets you change the following settings:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Theme
|
||||||
|
<ul>
|
||||||
|
<li>Set the appearance of the forum. This feature is still in beta and themes may change unexpectedly.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Thread sorting
|
||||||
|
<ul>
|
||||||
|
<li>Set the sorting of threads when viewing a single topic. "Latest activity" will put threads which had a response more recently closer to the top. "Thread creation date" will put threads which were created more recently closer to the top.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Display name
|
||||||
|
<ul>
|
||||||
|
<li>If set, your display name will show up instead of your username in most places. In a post's usercard, the display name will show up above your username/mention. In posts that have mentioned you, your display name will be shown instead of your @username.</li>
|
||||||
|
<li>Display names have fewer restrictions than usernames, and most characters are allowed.</li>
|
||||||
|
<li>If you do not wish to use a display name, you can leave the field blank.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Status
|
||||||
|
<ul>
|
||||||
|
<li>If set, your status will show up below your @mention in a post's usercard. 100 characters limit, no <a href="{{ url_for("guides.guide_page", category='user', slug='babycode') }}">Babycodes.</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Subscribe by default
|
||||||
|
<ul>
|
||||||
|
<li>If checked, you will automatically add the thread to your subscriptions when replying to it. You can override this setting by checking or unchecking "Subscribe to thread" before posting your reply in the reply box.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Signature
|
||||||
|
<ul>
|
||||||
|
<li>If set, this signature will appear under all of your posts. <a href="{{ url_for("guides.guide_page", category='user', slug='babycode') }}">Babycode</a> is allowed (except @mentions).</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="password">Changing your password</h2>
|
||||||
|
<p>You can change your password by typing it in the "New password" field and again in the "Confirm new password" field, then pressing the <button class="warn">Change password</button> button. The passwords in the two fields must match.</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="deleting">Deleting your account</h2>
|
||||||
|
<p>If you no longer wish to participate in {{ config.SITE_NAME }}, you may delete your account. To do so, press the <button class="critical">Delete account</button> button in your settings, which will take you to a confirmation page.</p>
|
||||||
|
<p>Deleting your account is an irreversible action. Once you delete your account, <strong>you will not be able to log back in to it.</strong></p>
|
||||||
|
<p>Deleting your account <strong>does not delete your threads and posts.</strong> They will be kept intact to preserve history. They will be altered to show up as if a system user authored them.</p>
|
||||||
|
<p>If you want your posts and threads to be deleted as well, you may either delete them yourself or <a href="{{url_for("guides.contact")}}" target="_blank">contact the administrators</a> for help.</p>
|
||||||
|
<p>If you're sure you want to delete your account, you will need to type your password on the confirmation page before pressing the <button class="critical">Delete account</button> button.</p>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
29
app/templates/guides/user-guides/04-inbox.html
Normal file
29
app/templates/guides/user-guides/04-inbox.html
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Inbox/subscriptions
|
||||||
|
{% extends 'guides/_layout.html' %}
|
||||||
|
{% block guide_content %}
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="overview">Subscriptions</h2>
|
||||||
|
<p>You can subscribe to any thread. When subscribed, you will receive an overview of posts you missed for that thread in your inbox.</p>
|
||||||
|
<p>Additionally, when browsing a topic, threads you've subscribed to will show the number of posts you haven't read in it next to the thread's name.</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="inbox">Inbox</h2>
|
||||||
|
<p>You can access your Inbox by following the "Inbox" link in the top navigation bar.</p>
|
||||||
|
<p>The Inbox is split into two parts:</p>
|
||||||
|
<ol>
|
||||||
|
<li>Subscriptions
|
||||||
|
<ul>
|
||||||
|
<li>A table of all threads that you've subscribed to. You can unsubscribe from each thread by pressing the <button class="warn">Unsubscribe</button> button for that thread's row.</li>
|
||||||
|
<li>This section is collapsible, like a Babycode spoiler - press the "-" button to collapse it.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>Unread posts
|
||||||
|
<ul>
|
||||||
|
<li>These are the posts you missed in each thread, if any. They are sorted in reverse chronological order and are grouped by thread. Each thread is collapsible.</li>
|
||||||
|
<li>You can mark an entire thread as read by pressing the <button>Mark thread as Read</button> button, or unsubscribe from it by pressing the <button class="warn">Unsubscribe</button> button.</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<p>Your inbox is updated automatically when you browse a subscribed thread. Once you've seen the posts you missed, they will disappear from your Inbox.</p>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
39
app/templates/guides/user-guides/05-bookmarks.html
Normal file
39
app/templates/guides/user-guides/05-bookmarks.html
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Bookmarks
|
||||||
|
{% from 'common/icons.html' import icn_bookmark %}
|
||||||
|
{% extends 'guides/_layout.html' %}
|
||||||
|
{% block guide_content %}
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="bookmarks">Bookmarks</h2>
|
||||||
|
<p>You can bookmark whole threads or individual posts to save them for later reading. Bookmarks are split into collections.</p>
|
||||||
|
<p>Each post or thread you bookmark (collectively bookmarks) can only belong to one collection.</p>
|
||||||
|
<p>Each bookmark can have a short memo that you can add to it, for example to help you remember why you saved it.</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="collections">Bookmark collections</h2>
|
||||||
|
<p>Bookmarks are organized into collections. There is always at least one collection you have access to, called "Bookmarks" by default.</p>
|
||||||
|
<p>You can add any number of collections by pressing the <button>Manage collections</button> button on the your bookmarks page.</p>
|
||||||
|
<p>On the "Manage bookmark collections" page, you can add, delete, rename, and reorder your collections.</p>
|
||||||
|
<p>To add a new collection, press the <button>Add new collection</button> button. A new item will be added.</p>
|
||||||
|
<p>You can name any collection by using the input box.</p>
|
||||||
|
<p>You can reorder collections by dragging and dropping it above or below others. The default collection is always at the top and can not be moved.</p>
|
||||||
|
<p>You can delete a collection by pressing the <button class="critical">Delete</button> button on that collection. Deleting a collection will remove all bookmarks from it. If you delete a collection by accident, simply refresh the page. Your changes are not saved until you press the <button>Save</button> button.</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="bookmarking">Bookmarking posts and threads</h2>
|
||||||
|
<ul>
|
||||||
|
<li>To bookmark a thread, press the <button class="contain-svg inline icon">{{ icn_bookmark(20) }}Bookmark…</button> button at the top of the thread.</li>
|
||||||
|
<li>To bookmark a post, press the <button class="contain-svg inline icon">{{ icn_bookmark(20) }}Bookmark…</button> button on that post.</li>
|
||||||
|
</ul>
|
||||||
|
<p>Both will bring up a popup with your bookmark collections. You can select the collection to save the bookmark into by pressing its name and add an optional memo. To save the bookmark, press the <button>Save</button> button. Each bookmark can only belong to one collection.</p>
|
||||||
|
<p>If the post or thread is already bookmarked, the name of the collection will be highlighed and the box to its name will be filled. If you wish to remove the bookmark, press the name of the collection it's in and press the <button>Save</button> button.</p>
|
||||||
|
</section>
|
||||||
|
<section class="guide-section">
|
||||||
|
<h2 id="browsing-bookmarks">Browsing and managing bookmarks</h2>
|
||||||
|
<p>You can access your bookmarks by following the "Bookmarks" link in the top navigation bar.</p>
|
||||||
|
<p>On the Bookmarks page, each collection will show up as a collapsible section. If a collection is empty, it will be collapsed.</p>
|
||||||
|
<p>If a collection has any bookmarks, it will have two collapsibe sections nested inside it: one for threads and one for posts.</p>
|
||||||
|
<p>Bookmarked threads are shown as a table with their title, the memo, and a <button class="contain-svg inline icon">{{ icn_bookmark(20) }}Manage…</button> button. Pressing this button will show the same popup, letting you move or remove the bookmark.</p>
|
||||||
|
<p>Bookmarked posts are shown in the same way they're shown in a thread. The memo will be shown before the post's time stamp. To the right of the post is the same <button class="contain-svg inline icon">{{ icn_bookmark(20) }}Manage…</button> button.</p>
|
||||||
|
<p>If you made changes to bookmarked threads or posts on this page, you will have to refresh to save those changes.</p>
|
||||||
|
</section>
|
||||||
|
{% endblock %}
|
||||||
@@ -1,17 +1,12 @@
|
|||||||
{% extends 'base.html' %}
|
# Babycode
|
||||||
{% from 'common/macros.html' import guide_sections with context %}
|
{% extends 'guides/_layout.html' %}
|
||||||
{% block title %}babycode guide{% endblock %}
|
{% block guide_content %}
|
||||||
{% block content %}
|
|
||||||
<div class=darkbg>
|
|
||||||
<h1 class="thread-title">Babycode guide</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% call() guide_sections() %}
|
|
||||||
<section class="guide-section">
|
<section class="guide-section">
|
||||||
<h2 id="what-is-babycode">What is babycode?</h2>
|
<h2 id="what-is-babycode">What is babycode?</h2>
|
||||||
<p>You may be familiar with BBCode, a loosely related family of markup languages popular on forums. Babycode is another, simplified, dialect of those languages. It is a way of formatting text by enclosing parts of it in special tags.</p>
|
<p>You may be familiar with BBCode, a loosely related family of markup languages popular on forums. Babycode is another, simplified, dialect of those languages. It is a way of formatting text by enclosing parts of it in special tags.</p>
|
||||||
<p>A <b>tag</b> is a short name enclosed in square brackets. Tags can be opening tags, like <code class="inline-code">[b]</code> or closing tags, like <code class="inline-code">[/b]</code>. Anything inserted between matching opening and closing tags is known as the tag's content.</p>
|
<p>A <b>tag</b> is a short name enclosed in square brackets. Tags can be opening tags, like <code class="inline-code">[b]</code> or closing tags, like <code class="inline-code">[/b]</code>. Anything inserted between matching opening and closing tags is known as the tag's content.</p>
|
||||||
<p>Some tags can provide more specific instructions using an <b>attribute</b>. An attribute is added to the opening tag with an equals sign (<code class="inline-code">=</code>). This allows you to specify details like a particular color or a link's address.</p>
|
<p>Some tags can provide more specific instructions using an <b>attribute</b>. An attribute is added to the opening tag with an equals sign (<code class="inline-code">=</code>). This allows you to specify details like a particular color or a link's address.</p>
|
||||||
|
<p>Babycode is used in posts, user signatures, and MOTDs.</p>
|
||||||
</section>
|
</section>
|
||||||
<section class="guide-section">
|
<section class="guide-section">
|
||||||
<h2 id="text-formatting-tags">Text formatting tags</h2>
|
<h2 id="text-formatting-tags">Text formatting tags</h2>
|
||||||
@@ -186,5 +181,4 @@
|
|||||||
<li>The <code class="inline-code">[@]</code> tag allows you to use the @ symbol without it being turned into a mention.</li>
|
<li>The <code class="inline-code">[@]</code> tag allows you to use the @ symbol without it being turned into a mention.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
{% endcall %}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@@ -11,3 +11,8 @@ USERS_CAN_INVITE = false # if true, allows users to create invite links. useless
|
|||||||
# some babycodes allowed
|
# some babycodes allowed
|
||||||
# forbidden tags: [spoiler], [img], @mention, [big], [small], [center], [right], [color]
|
# forbidden tags: [spoiler], [img], @mention, [big], [small], [center], [right], [color]
|
||||||
ADMIN_CONTACT_INFO = ""
|
ADMIN_CONTACT_INFO = ""
|
||||||
|
|
||||||
|
# forum information. shown in the introduction guide at /guides/user/introduction
|
||||||
|
# some babycodes allowed
|
||||||
|
# forbidden tags: [spoiler], [img], @mention, [big], [small], [center], [right], [color]
|
||||||
|
GUIDE_DESCRIPTION = ""
|
||||||
|
|||||||
@@ -1340,7 +1340,7 @@ footer {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.babycode-guide-list {
|
.guide-list {
|
||||||
border-bottom: 1px dashed;
|
border-bottom: 1px dashed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1382,7 +1382,7 @@ footer {
|
|||||||
mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2221%22%20height%3D%2221%22%20rx%3D%223%22%20stroke%3D%22currentColor%22%20stroke-width%3D%223%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center/contain no-repeat;
|
mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2221%22%20height%3D%2221%22%20rx%3D%223%22%20stroke%3D%22currentColor%22%20stroke-width%3D%223%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center/contain no-repeat;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
padding: 0 10px;
|
padding: 0 20px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.bookmark-dropdown-item.selected {
|
.bookmark-dropdown-item.selected {
|
||||||
|
|||||||
@@ -1340,7 +1340,7 @@ footer {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.babycode-guide-list {
|
.guide-list {
|
||||||
border-bottom: 1px dashed;
|
border-bottom: 1px dashed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1382,7 +1382,7 @@ footer {
|
|||||||
mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2221%22%20height%3D%2221%22%20rx%3D%223%22%20stroke%3D%22currentColor%22%20stroke-width%3D%223%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center/contain no-repeat;
|
mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2221%22%20height%3D%2221%22%20rx%3D%223%22%20stroke%3D%22currentColor%22%20stroke-width%3D%223%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center/contain no-repeat;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
padding: 0 10px;
|
padding: 0 20px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.bookmark-dropdown-item.selected {
|
.bookmark-dropdown-item.selected {
|
||||||
|
|||||||
@@ -1340,7 +1340,7 @@ footer {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.babycode-guide-list {
|
.guide-list {
|
||||||
border-bottom: 1px dashed;
|
border-bottom: 1px dashed;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1382,7 +1382,7 @@ footer {
|
|||||||
mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2221%22%20height%3D%2221%22%20rx%3D%223%22%20stroke%3D%22currentColor%22%20stroke-width%3D%223%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center/contain no-repeat;
|
mask: url("data:image/svg+xml,%3Csvg%20width%3D%2224%22%20height%3D%2224%22%20viewBox%3D%220%200%2024%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Crect%20x%3D%221.5%22%20y%3D%221.5%22%20width%3D%2221%22%20height%3D%2221%22%20rx%3D%223%22%20stroke%3D%22currentColor%22%20stroke-width%3D%223%22%20fill%3D%22none%22%2F%3E%3C%2Fsvg%3E") center/contain no-repeat;
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
padding: 0 6px;
|
padding: 0 24px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
.bookmark-dropdown-item.selected {
|
.bookmark-dropdown-item.selected {
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ const delay = ms => {return new Promise(resolve => setTimeout(resolve, ms))}
|
|||||||
|
|
||||||
export default class {
|
export default class {
|
||||||
async showBookmarkMenu(ev, el) {
|
async showBookmarkMenu(ev, el) {
|
||||||
if ((ev.sender.dataset.bookmarkId === el.getString('bookmarkId')) && el.childElementCount === 0) {
|
if ((el.sender.dataset.bookmarkId === el.ds('bookmarkId')) && el.childElementCount === 0) {
|
||||||
const searchParams = new URLSearchParams({
|
const searchParams = new URLSearchParams({
|
||||||
'id': ev.sender.dataset.conceptId,
|
'id': el.sender.dataset.conceptId,
|
||||||
'require_reload': el.dataset.requireReload,
|
'require_reload': el.dataset.requireReload,
|
||||||
});
|
});
|
||||||
const bookmarkMenuHref = `${bookmarkMenuHrefTemplate}/${ev.sender.dataset.bookmarkType}?${searchParams}`;
|
const bookmarkMenuHref = `${bookmarkMenuHrefTemplate}/${el.sender.dataset.bookmarkType}?${searchParams}`;
|
||||||
const res = await this.api.getHTML(bookmarkMenuHref);
|
const res = await this.api.getHTML(bookmarkMenuHref);
|
||||||
if (res.error) {
|
if (res.error) {
|
||||||
return;
|
return;
|
||||||
@@ -49,9 +49,9 @@ export default class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectBookmarkCollection(ev, el) {
|
selectBookmarkCollection(ev, el) {
|
||||||
const clicked = ev.sender;
|
const clicked = el.sender;
|
||||||
|
|
||||||
if (ev.sender === el) {
|
if (el.sender === el) {
|
||||||
if (clicked.classList.contains('selected')) {
|
if (clicked.classList.contains('selected')) {
|
||||||
clicked.classList.remove('selected');
|
clicked.classList.remove('selected');
|
||||||
} else {
|
} else {
|
||||||
@@ -63,7 +63,7 @@ export default class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async saveBookmarks(ev, el) {
|
async saveBookmarks(ev, el) {
|
||||||
const bookmarkHref = el.getString('bookmarkEndpoint');
|
const bookmarkHref = el.ds('bookmarkEndpoint');
|
||||||
const collection = el.querySelector('.bookmark-dropdown-item.selected');
|
const collection = el.querySelector('.bookmark-dropdown-item.selected');
|
||||||
let data = {};
|
let data = {};
|
||||||
if (collection) {
|
if (collection) {
|
||||||
@@ -72,7 +72,7 @@ export default class {
|
|||||||
data['memo'] = el.querySelector('.bookmark-memo-input').value;
|
data['memo'] = el.querySelector('.bookmark-memo-input').value;
|
||||||
} else {
|
} else {
|
||||||
data['operation'] = 'remove';
|
data['operation'] = 'remove';
|
||||||
data['collection_id'] = el.getString('originallyContainedIn');
|
data['collection_id'] = el.ds('originallyContainedIn');
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
@@ -82,7 +82,7 @@ export default class {
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
const requireReload = el.getInt('requireReload') !== 0;
|
const requireReload = el.dsInt('requireReload') !== 0;
|
||||||
el.remove();
|
el.remove();
|
||||||
await fetch(bookmarkHref, options);
|
await fetch(bookmarkHref, options);
|
||||||
if (requireReload) {
|
if (requireReload) {
|
||||||
@@ -103,10 +103,10 @@ export default class {
|
|||||||
toggleAccordion(ev, el) {
|
toggleAccordion(ev, el) {
|
||||||
const accordion = el;
|
const accordion = el;
|
||||||
const header = accordion.querySelector('.accordion-header');
|
const header = accordion.querySelector('.accordion-header');
|
||||||
if (!header.contains(ev.sender)){
|
if (!header.contains(el.sender)){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const btn = ev.sender;
|
const btn = el.sender;
|
||||||
const content = el.querySelector('.accordion-content');
|
const content = el.querySelector('.accordion-content');
|
||||||
// these are all meant to be in sync
|
// these are all meant to be in sync
|
||||||
accordion.classList.toggle('hidden');
|
accordion.classList.toggle('hidden');
|
||||||
@@ -116,15 +116,15 @@ export default class {
|
|||||||
|
|
||||||
toggleTab(ev, el) {
|
toggleTab(ev, el) {
|
||||||
const tabButtonsContainer = el.querySelector('.tab-buttons');
|
const tabButtonsContainer = el.querySelector('.tab-buttons');
|
||||||
if (!el.contains(ev.sender)) {
|
if (!el.contains(el.sender)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ev.sender.classList.contains('active')) {
|
if (el.sender.classList.contains('active')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const targetId = ev.sender.getString('targetId');
|
const targetId = el.senderDs('targetId');
|
||||||
const contents = el.querySelectorAll('.tab-content');
|
const contents = el.querySelectorAll('.tab-content');
|
||||||
for (let content of contents) {
|
for (let content of contents) {
|
||||||
if (content.id === targetId) {
|
if (content.id === targetId) {
|
||||||
@@ -144,7 +144,7 @@ export default class {
|
|||||||
|
|
||||||
#previousMarkup = null;
|
#previousMarkup = null;
|
||||||
async babycodePreview(ev, el) {
|
async babycodePreview(ev, el) {
|
||||||
if (ev.sender.classList.contains('active')) {
|
if (el.sender.classList.contains('active')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,9 +199,9 @@ export default class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
insertBabycodeTag(ev, el) {
|
insertBabycodeTag(ev, el) {
|
||||||
const tagStart = ev.sender.getString('tag');
|
const tagStart = el.senderDs('tag');
|
||||||
const breakLine = 'breakLine' in ev.sender.dataset;
|
const breakLine = 'breakLine' in el.sender.dataset;
|
||||||
const prefill = 'prefill' in ev.sender.dataset ? ev.sender.dataset.prefill : '';
|
const prefill = 'prefill' in el.sender.dataset ? el.sender.dataset.prefill : '';
|
||||||
|
|
||||||
const hasAttr = tagStart[tagStart.length - 1] === '=';
|
const hasAttr = tagStart[tagStart.length - 1] === '=';
|
||||||
let tagEnd = tagStart;
|
let tagEnd = tagStart;
|
||||||
@@ -249,13 +249,13 @@ export default class {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addQuote(ev, el) {
|
addQuote(ev, el) {
|
||||||
el.value += ev.sender.value;
|
el.value += el.sender.value;
|
||||||
el.scrollIntoView();
|
el.scrollIntoView();
|
||||||
el.focus();
|
el.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
convertTimestamps(ev, el) {
|
convertTimestamps(ev, el) {
|
||||||
const timestamp = el.getInt('utc');
|
const timestamp = el.dsInt('utc');
|
||||||
if (!isNaN(timestamp)) {
|
if (!isNaN(timestamp)) {
|
||||||
const date = new Date(timestamp * 1000);
|
const date = new Date(timestamp * 1000);
|
||||||
el.textContent = date.toLocaleString();
|
el.textContent = date.toLocaleString();
|
||||||
@@ -272,7 +272,7 @@ export default class {
|
|||||||
this.#currentUsername = userInfo.value.user.username;
|
this.#currentUsername = userInfo.value.user.username;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (el.getString('username') === this.#currentUsername) {
|
if (el.ds('username') === this.#currentUsername) {
|
||||||
el.classList.add('me');
|
el.classList.add('me');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1
data/static/js/vnd/bitty-6.0.0-rc3.min.js
vendored
1
data/static/js/vnd/bitty-6.0.0-rc3.min.js
vendored
File diff suppressed because one or more lines are too long
1
data/static/js/vnd/bitty-7.0.0-rc1.min.js
vendored
Normal file
1
data/static/js/vnd/bitty-7.0.0-rc1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1269,9 +1269,9 @@ $reaction_popover_padding: $SMALL_PADDING $MEDIUM_PADDING !default;
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
$babycode_guide_list_border: 1px dashed !default;
|
$guide_list_border: 1px dashed !default;
|
||||||
.babycode-guide-list {
|
.guide-list {
|
||||||
border-bottom: $babycode_guide_list_border;
|
border-bottom: $guide_list_border;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bookmark-dropdown-inner {
|
.bookmark-dropdown-inner {
|
||||||
@@ -1306,7 +1306,7 @@ $bookmark_dropdown_item_background_hover: $BUTTON_COLOR_HOVER !default;
|
|||||||
$bookmark_dropdown_item_background_selected: $BUTTON_COLOR_2 !default;
|
$bookmark_dropdown_item_background_selected: $BUTTON_COLOR_2 !default;
|
||||||
$bookmark_dropdown_item_background_selected_hover: $BUTTON_COLOR_2_HOVER !default;
|
$bookmark_dropdown_item_background_selected_hover: $BUTTON_COLOR_2_HOVER !default;
|
||||||
$bookmark_dropdown_item_icon_size: 24px !default;
|
$bookmark_dropdown_item_icon_size: 24px !default;
|
||||||
$bookmark_dropdown_item_icon_padding: 0 $MEDIUM_PADDING !default;
|
$bookmark_dropdown_item_icon_padding: 0 $BIG_PADDING !default;
|
||||||
.bookmark-dropdown-item {
|
.bookmark-dropdown-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ $br: 16px;
|
|||||||
|
|
||||||
$pagebutton_min_width: 36px,
|
$pagebutton_min_width: 36px,
|
||||||
$quote_background_color: #0002,
|
$quote_background_color: #0002,
|
||||||
|
|
||||||
|
$bookmark_dropdown_item_icon_padding: 0 24px,
|
||||||
);
|
);
|
||||||
|
|
||||||
#topnav {
|
#topnav {
|
||||||
|
|||||||
Reference in New Issue
Block a user