add a proper babycode help page

This commit is contained in:
Lera Elvoé 2025-06-01 10:53:37 +03:00
parent db8d32113c
commit d227932878
Signed by: yagich
SSH Key Fingerprint: SHA256:6xjGb6uA7lAVcULa7byPEN//rQ0wPoG+UzYVMfZnbvc
9 changed files with 335 additions and 96 deletions

View File

@ -65,4 +65,10 @@ app:get("/", function(self)
return {redirect_to = self:url_for("all_topics")} return {redirect_to = self:url_for("all_topics")}
end) end)
app:get("babycode_guide", "/babycode", function(self)
self.me = util.get_logged_in_user_or_transient(self)
self.page_title = "babycode guide"
return {render = "babycode"}
end)
return app return app

View File

@ -154,6 +154,7 @@ pre code {
border-left: 10px solid rgb(229.84, 231.92, 227.28); border-left: 10px solid rgb(229.84, 231.92, 227.28);
padding: 20px; padding: 20px;
overflow: scroll; overflow: scroll;
tab-size: 4;
} }
.inline-code { .inline-code {
@ -456,6 +457,58 @@ input[type=text]:focus, input[type=password]:focus, textarea:focus, select:focus
margin-right: 25%; margin-right: 25%;
} }
.babycode-guide-section {
background-color: #c1ceb1;
padding: 5px 20px;
border: 1px solid black;
padding-right: 25%;
}
.babycode-guide-container {
display: grid;
grid-template-columns: 1.5fr 300px;
grid-template-rows: 1fr;
gap: 0px 0px;
grid-auto-flow: row;
grid-template-areas: "guide-topics guide-toc";
}
.guide-topics {
grid-area: guide-topics;
overflow: hidden;
}
.guide-toc {
grid-area: guide-toc;
position: sticky;
top: 100px;
align-self: start;
padding: 10px;
border-bottom-right-radius: 8px;
background-color: rgb(177, 206, 204.5);
border-right: 1px solid black;
border-top: 1px solid black;
border-bottom: 1px solid black;
}
.emoji-table tr td {
text-align: center;
}
.emoji-table tr th {
padding-left: 50px;
padding-right: 50px;
}
.emoji-table {
margin: auto;
}
.emoji-table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
.topic { .topic {
display: grid; display: grid;
grid-template-columns: 1.5fr 64px; grid-template-columns: 1.5fr 64px;

View File

@ -1,46 +1,47 @@
local emoji_template = " <img class=emoji src=\"/emoji/$NAME.png\" alt=\"$NAME\" title=\":$NAME:\"> " local emoji_template = " <img class=emoji src=\"/emoji/$NAME.png\" alt=\"$NAME\" title=\":$CODE:\"> "
local emoji_pat = "%$NAME" local emoji_pat = "%$NAME"
local name_pat = "%$CODE"
return { return {
["angry"] = emoji_template:gsub(emoji_pat, "angry"), ["angry"] = emoji_template:gsub(emoji_pat, "angry"):gsub(name_pat, "angry"),
["("] = emoji_template:gsub(emoji_pat, "frown"), ["("] = emoji_template:gsub(emoji_pat, "frown"):gsub(name_pat, "("),
["D"] = emoji_template:gsub(emoji_pat, "grin"), ["D"] = emoji_template:gsub(emoji_pat, "grin"):gsub(name_pat, "D"),
["imp"] = emoji_template:gsub(emoji_pat, "imp"), ["imp"] = emoji_template:gsub(emoji_pat, "imp"):gsub(name_pat, "imp"),
["angryimp"] = emoji_template:gsub(emoji_pat, "impangry"), ["angryimp"] = emoji_template:gsub(emoji_pat, "impangry"):gsub(name_pat, "angryimp"),
["impangry"] = emoji_template:gsub(emoji_pat, "impangry"), ["impangry"] = emoji_template:gsub(emoji_pat, "impangry"):gsub(name_pat, "impangry"),
["lobster"] = emoji_template:gsub(emoji_pat, "lobster"), ["lobster"] = emoji_template:gsub(emoji_pat, "lobster"):gsub(name_pat, "lobster"),
["|"] = emoji_template:gsub(emoji_pat, "neutral"), ["|"] = emoji_template:gsub(emoji_pat, "neutral"):gsub(name_pat, "|"),
["pensive"] = emoji_template:gsub(emoji_pat, "pensive"), ["pensive"] = emoji_template:gsub(emoji_pat, "pensive"):gsub(name_pat, "pensive"),
[")"] = emoji_template:gsub(emoji_pat, "smile"), [")"] = emoji_template:gsub(emoji_pat, "smile"):gsub(name_pat, ")"),
["smiletear"] = emoji_template:gsub(emoji_pat, "smiletear"), ["smiletear"] = emoji_template:gsub(emoji_pat, "smiletear"):gsub(name_pat, "smiletear"),
["crytear"] = emoji_template:gsub(emoji_pat, "smiletear"), ["crytear"] = emoji_template:gsub(emoji_pat, "smiletear"):gsub(name_pat, "crytear"),
[","] = emoji_template:gsub(emoji_pat, "sob"), [","] = emoji_template:gsub(emoji_pat, "sob"):gsub(name_pat, ","),
["T"] = emoji_template:gsub(emoji_pat, "sob"), ["T"] = emoji_template:gsub(emoji_pat, "sob"):gsub(name_pat, "T"),
["cry"] = emoji_template:gsub(emoji_pat, "sob"), ["cry"] = emoji_template:gsub(emoji_pat, "sob"):gsub(name_pat, "cry"),
["sob"] = emoji_template:gsub(emoji_pat, "sob"), ["sob"] = emoji_template:gsub(emoji_pat, "sob"):gsub(name_pat, "sob"),
["o"] = emoji_template:gsub(emoji_pat, "surprised"), ["o"] = emoji_template:gsub(emoji_pat, "surprised"):gsub(name_pat, "o"),
["O"] = emoji_template:gsub(emoji_pat, "surprised"), ["O"] = emoji_template:gsub(emoji_pat, "surprised"):gsub(name_pat, "O"),
["hmm"] = emoji_template:gsub(emoji_pat, "think"), ["hmm"] = emoji_template:gsub(emoji_pat, "think"):gsub(name_pat, "hmm"),
["think"] = emoji_template:gsub(emoji_pat, "think"), ["think"] = emoji_template:gsub(emoji_pat, "think"):gsub(name_pat, "think"),
["thinking"] = emoji_template:gsub(emoji_pat, "think"), ["thinking"] = emoji_template:gsub(emoji_pat, "think"):gsub(name_pat, "thinking"),
["P"] = emoji_template:gsub(emoji_pat, "tongue"), ["P"] = emoji_template:gsub(emoji_pat, "tongue"):gsub(name_pat, "P"),
["p"] = emoji_template:gsub(emoji_pat, "tongue"), ["p"] = emoji_template:gsub(emoji_pat, "tongue"):gsub(name_pat, "p"),
["weary"] = emoji_template:gsub(emoji_pat, "weary"), ["weary"] = emoji_template:gsub(emoji_pat, "weary"):gsub(name_pat, "weary"),
[";"] = emoji_template:gsub(emoji_pat, "wink"), [";"] = emoji_template:gsub(emoji_pat, "wink"):gsub(name_pat, ";"),
["wink"] = emoji_template:gsub(emoji_pat, "wink"), ["wink"] = emoji_template:gsub(emoji_pat, "wink"):gsub(name_pat, "wink"),
} }

View File

@ -197,6 +197,7 @@ pre code {
border-left: 10px solid $lighter; border-left: 10px solid $lighter;
padding: 20px; padding: 20px;
overflow: scroll; overflow: scroll;
tab-size: 4;
} }
.inline-code { .inline-code {
@ -467,6 +468,60 @@ input[type="text"], input[type="password"], textarea, select {
margin-right: 25%; margin-right: 25%;
} }
.babycode-guide-section {
background-color: $accent_color;
padding: 5px 20px;
border: 1px solid black;
padding-right: 25%;
}
.babycode-guide-container {
display: grid;
grid-template-columns: 1.5fr 300px;
grid-template-rows: 1fr;
gap: 0px 0px;
grid-auto-flow: row;
grid-template-areas:
"guide-topics guide-toc";
}
.guide-topics {
grid-area: guide-topics;
overflow: hidden;
}
.guide-toc {
grid-area: guide-toc;
position: sticky;
top: 100px;
align-self: start;
padding: 10px;
// border-top-right-radius: 16px;
border-bottom-right-radius: 8px;
background-color: $button_color;
border-right: 1px solid black;
border-top: 1px solid black;
border-bottom: 1px solid black;
}
.emoji-table tr td {
text-align: center;
}
.emoji-table tr th {
padding-left: 50px;
padding-right: 50px;
}
.emoji-table {
margin: auto;
}
.emoji-table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
.topic { .topic {
display: grid; display: grid;
grid-template-columns: 1.5fr 64px; grid-template-columns: 1.5fr 64px;

192
views/babycode.etlua Normal file
View File

@ -0,0 +1,192 @@
<div class=darkbg>
<h1 class="thread-title">Babycode guide</h1>
</div>
<% local tocs = {} %>
<div class="babycode-guide-container">
<div class="guide-topics">
<section class="babycode-guide-section">
<h2 id="what-is-babycode">What is babycode?</h2>
<% table.insert(tocs, {"What is babycode?", "what-is-babycode"}) %>
<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>
</section>
<section class="babycode-guide-section">
<h2 id="text-formatting-tags">Text formatting tags</h2>
<% table.insert(tocs, {"Text formatting tags", "text-formatting-tags"}) %>
<ul>
<li>To make some text <strong>bold</strong>, enclose it in <code class="inline-code">[b][/b]</code>:<br>
[b]Hello World[/b]<br>
Will become<br>
<strong>Hello World</strong>
</ul>
<ul>
<li>To <em>italicize</em> text, enclose it in <code class="inline-code">[i][/i]</code>:<br>
[i]Hello World[/i]<br>
Will become<br>
<em>Hello World</em>
</ul>
<ul>
<li>To make some text <del>strikethrough</del>, enclose it in <code class="inline-code">[s][/s]</code>:<br>
[s]Hello World[/s]<br>
Will become<br>
<del>Hello World</del>
</ul>
</section>
<section class="babycode-guide-section">
<h2 id="emoji">Emotes</h2>
<% table.insert(tocs, {"Emotes", "emoji"}) %>
<p>There are a few emoji in the style of old forum emotes:</p>
<% --[[ we'll pretend like i will totally refactor emojis and generate this table dynamically in the future. clown emoji ]]%>
<table class="emoji-table">
<tr>
<th>Short code(s)</th>
<th>Emoji result</th>
</tr>
<tr>
<td>:angry:</td>
<td><img class=emoji src="/emoji/angry.png" alt="angry" title=":angry:"></td>
</tr>
<tr>
<td>:(:</td>
<td><img class=emoji src="/emoji/frown.png" alt="frown" title=":(:"></td>
</tr>
<tr>
<td>:D:</td>
<td><img class=emoji src="/emoji/grin.png" alt="grin" title=":D:"></td>
</tr>
<tr>
<td>:imp:</td>
<td><img class=emoji src="/emoji/imp.png" alt="imp" title=":imp:"></td>
</tr>
<tr>
<td>:impangry: :angryimp:</td>
<td><img class=emoji src="/emoji/impangry.png" alt="impangry" title=":impangry:"></td>
</tr>
<tr>
<td>:lobster:</td>
<td><img class=emoji src="/emoji/lobster.png" alt="lobster" title=":lobster:"></td>
</tr>
<tr>
<td>:|:</td>
<td><img class=emoji src="/emoji/neutral.png" alt="neutral" title=":|:"></td>
</tr>
<tr>
<td>:pensive:</td>
<td><img class=emoji src="/emoji/pensive.png" alt="pensive" title=":pensive:"></td>
</tr>
<tr>
<td>:):</td>
<td><img class=emoji src="/emoji/smile.png" alt="smile" title=":):"></td>
</tr>
<tr>
<td>:smiletear: :crytear:</td>
<td><img class=emoji src="/emoji/smiletear.png" alt="smiletear" title=":smiletear:"></td>
</tr>
<tr>
<td>:,: :T: :cry: :sob:</td>
<td><img class=emoji src="/emoji/sob.png" alt="sob" title=":sob:"></td>
</tr>
<tr>
<td>:o: :O:</td>
<td><img class=emoji src="/emoji/surprised.png" alt="surprised" title=":o:"></td>
</tr>
<tr>
<td>:hmm: :think: :thinking:</td>
<td><img class=emoji src="/emoji/think.png" alt="think" title=":think:"></td>
</tr>
<tr>
<td>:P: :p:</td>
<td><img class=emoji src="/emoji/tongue.png" alt="tongue" title=":p:"></td>
</tr>
<tr>
<td>:weary:</td>
<td><img class=emoji src="/emoji/weary.png" alt="weary" title=":weary:"></td>
</tr>
<tr>
<td>:;: :wink:</td>
<td><img class=emoji src="/emoji/wink.png" alt="wink" title=":wink:"></td>
</tr>
</table>
<p>Special thanks to the <a href="https://gh.vercte.net/forumoji/">Forumoji project</a> and its contributors for these graphics.</p>
</section>
<section class="babycode-guide-section">
<h2 id="paragraph-rules">Paragraph rules</h2>
<% table.insert(tocs, {"Paragraph rules", "paragraph-rules"}) %>
<p>Line breaks in babycode work more like Markdown: to start a new paragraph, use two line breaks:</p>
<pre><span class="copy-code-container"><button type=button class="copy-code" value="paragraph 1
paragraph 2">Copy</button></span><code>paragraph 1
paragraph 2</code></pre>
Will produce:<br>
paragraph 1<br><br>paragraph 2
<p>To break a line without starting a new paragraph, end a line with two spaces:</p>
<pre><span class="copy-code-container"><button type=button class="copy-code" value="paragraph 1
still paragraph 1">Copy</button></span><code>paragraph 1
still paragraph 1</code></pre>
That will produce:<br>
paragraph 1<br>still paragraph 1
</section>
<section class="babycode-guide-section">
<h2 id="links">Links</h2>
<% table.insert(tocs, {"Links", "links"}) %>
<p>Loose links (starting with http:// or https://) will automatically get converted to clickable links. To add a label to a link, use<br><code class="inline-code">[url=https://example.com]Link label[/url]</code>:<br>
<a href="https://example.com">Link label</a></p>
</section>
<section class="babycode-guide-section">
<h2 id="attaching-an-image">Attaching an image</h2>
<% table.insert(tocs, {"Attaching an image", "attaching-an-image"}) %>
<p>To add an image to your post, use the <code class="inline-code">[img]</code> tag:<br>
<code class="inline-code">[img=https://forum.poto.cafe/avatars/default.webp]the Lua logo with a cowboy hat[/img]</code>
<div class="post-img-container"><img class="block-img" src="/avatars/default.webp" alt="the Lua logo with a cowboy hat"></div></p>
<p>Images will always break up a paragraph and will get scaled down to a maximum of 400px. The text inside the tag will become the image's alt text.</p>
</section>
<section class="babycode-guide-section">
<h2 id="adding-code-blocks">Adding code blocks</h2>
<% table.insert(tocs, {"Adding code blocks", "adding-code-blocks"}) %>
<p>There are two kinds of code blocks recognized by babycode: inline and block. Inline code blocks do not break a paragraph. They can be added with <code class="inline-code">[code]your code here[/code]</code>. As long as there are no line breaks inside the code block, it is considered inline. If there are any, it will produce this:</p>
<% local code = 'func _ready() -> void:\n\tprint("hello world!")' %>
<pre><span class="copy-code-container"><button type=button class="copy-code" value="<%= code %>">Copy</button></span><code><%= code %></code></pre>
<p>Babycodes are not parsed inside code blocks.</p>
</section>
<section class="babycode-guide-section">
<h2 id="quoting">Quoting</h2>
<% table.insert(tocs, {"Quoting", "quoting"}) %>
<p>Text enclosed within <code class="inline-code">[quote][/quote]</code> will look like a quote:</p>
<blockquote>A man provided with paper, pencil, and rubber, and subject to strict discipline, is in effect a universal machine.</blockquote>
</section>
<section class="babycode-guide-section">
<h2 id="lists">Lists</h2>
<% table.insert(tocs, {"Lists", "lists"}) %>
<p>There are two kinds of lists, ordered (1, 2, 3, ...) and unordered (bullet points). Ordered lists are made with <code class="inline-code">[ol][/ol]</code> tags, and unordered with <code class="inline-code">[ul][/ul]</code>. Every new paragraph according to the <a href="#paragraph-rules">usual paragraph rules</a> will create a new list item. For example:</p>
<pre><span class="copy-code-container"><button type=button class="copy-code" value="[ul]
item 1
item 2
item 3
still item 3 (break line without inserting a new item by using two spaces at the end of a line)
[/ul]">Copy</button></span><code>[ul]
item 1
item 2
item 3
still item 3 (break line without inserting a new item by using two spaces at the end of a line)
[/ul]</code></pre><br>
Will produce the following list:
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3<br>still item 3 (break line without inserting a new item by using two spaces at the end of a line)</li>
</ul>
</section>
</div>
<div class="guide-toc">
<h2>Table of contents</h2>
<ul>
<% for _, t in ipairs(tocs) do %>
<li><a href="#<%= t[2] %>"><%= t[1] %></a></li>
<% end %>
</ul>
</div>
</div>

View File

@ -11,6 +11,7 @@
<button type=button id="post-editor-code" title="Insert Code block">Code</button> <button type=button id="post-editor-code" title="Insert Code block">Code</button>
</span> </span>
<textarea class="babycode-editor" name="<%= ta_name %>" id="babycode-content" placeholder="<%= ta_placeholder or "Post body"%>" <%= not optional and "required" or "" %>><%- prefill or "" %></textarea> <textarea class="babycode-editor" name="<%= ta_name %>" id="babycode-content" placeholder="<%= ta_placeholder or "Post body"%>" <%= not optional and "required" or "" %>><%- prefill or "" %></textarea>
<a href="<%= url_for("babycode_guide") %>" target="_blank">babycode guide</a>
</div> </div>
<div class="tab-content" id="tab-preview"> <div class="tab-content" id="tab-preview">
<div id="babycode-preview-errors-container">Type something!</div> <div id="babycode-preview-errors-container">Type something!</div>

View File

@ -12,5 +12,4 @@
<a class="linkbutton warn" href="<%= cancel_url %>">Cancel</a> <a class="linkbutton warn" href="<%= cancel_url %>">Cancel</a>
<% end %> <% end %>
</span> </span>
<% render("views.common.bbcode_help") %>
</form> </form>

View File

@ -1,67 +0,0 @@
<details>
<summary>babycode guide</summary>
<ul>
<li>To start a new paragraph, separate the paragraphs with an empty line. To break a line without starting a paragraph, end a line with two spaces. (same rules as Markdown)</li>
<li>
<details>
<summary>Forumoji (emoticons)</summary>
<ul>
<li><img class="emoji" src="/emoji/smile.png" alt="smile" title=":smile:"> - <code class=inline-code>:): </code></li>
<li><img class="emoji" src="/emoji/frown.png" alt="frown" title=":frown:"> - <code class=inline-code>:(: </code></li>
<li><img class="emoji" src="/emoji/grin.png" alt="grin" title=":grin:"> - <code class=inline-code>:D: </code></li>
<li><img class="emoji" src="/emoji/neutral.png" alt="neutral" title=":neutral:"> - <code class=inline-code>:|: </code></li>
<li><img class="emoji" src="/emoji/angry.png" alt="angry" title=":angry:"> - <code class=inline-code>:angry: </code></li>
<li><img class="emoji" src="/emoji/sob.png" alt="sob" title=":sob:"> - <code class=inline-code>:,: :cry: :sob: :T: </code></li>
<li><img class="emoji" src="/emoji/surprised.png" alt="surprised" title=":surprised:"> - <code class=inline-code>:o: :O: </code></li>
<li><img class="emoji" src="/emoji/think.png" alt="think" title=":think:"> - <code class=inline-code>:hmm: :think: :thinking: </code></li>
<li><img class="emoji" src="/emoji/tongue.png" alt="tongue" title=":tongue:"> - <code class=inline-code>:p: :P: </code></li>
<li><img class="emoji" src="/emoji/wink.png" alt="wink" title=":wink:"> - <code class=inline-code>:;: :wink: </code></li>
<li><img class="emoji" src="/emoji/imp.png" alt="imp" title=":imp:"> - <code class=inline-code>:imp: </code></li>
<li><img class="emoji" src="/emoji/impangry.png" alt="impangry" title=":impangry:"> - <code class=inline-code>:angryimp: :impangry: </code></li>
<li><img class="emoji" src="/emoji/lobster.png" alt="lobster" title=":lobster:"> - <code class=inline-code>:lobster:</code></li>
<li><img class="emoji" src="/emoji/pensive.png" alt="pensive" title=":pensive:"> - <code class=inline-code>:pensive:</code></li>
<li><img class="emoji" src="/emoji/weary.png" alt="weary" title=":weary:"> - <code class=inline-code>:weary:</code></li>
<li><img class="emoji" src="/emoji/smiletear.png" alt="smiletear" title=":smiletear:"> - <code class=inline-code>:smiletear: :crytear:</code></li>
</ul>
</details>
</li>
<li>Loose links will be converted to clickable links automatically</li>
<li>[b]<b>bold</b>[/b]</li>
<li>[i]<i>italic</i>[/i]</li>
<li>[s]<del>strikethrough</del>[/s]</li>
<li>[img=https://example.com/some-image]alt text[/img] creates an image</li>
<li>[url=https://example.com]<a href="https://example.com">labeled URL</a>[/url]</li>
<li>
[ul] and [ol] are unordered and ordered lists:
<details>
<summary>Show list example</summary>
<pre><span class="copy-code-container"><button type=button class="copy-code" value="[ul]
item 1
item 2
item 3
still item 3 (break line without inserting a new item by using two spaces at the end of a line)
[/ul]">Copy</button></span><code>[ul]
item 1
item 2
item 3
still item 3 (break line without inserting a new item by using two spaces at the end of a line)
[/ul]</code></pre>
</details>
</li>
<li>
[code]with<br>line breaks[/code] will produce a code block:
<details>
<summary>Show code block example</summary>
<pre><span class="copy-code-container"><button type=button class="copy-code" value="with
line breaks">Copy</button></span><code>with
line breaks</code></pre>
</details>
</li>
<li>[code]<code class="inline-code">with no line breaks</code>[/code]</li>
<li><code class="inline-code">---</code> will create a horizontal rule for separating content</li>
</ul>
</details>

View File

@ -11,7 +11,6 @@
<input type="text" id="title" name="title" placeholder="Required" required> <input type="text" id="title" name="title" placeholder="Required" required>
<label for="initial_post">Post body</label><br> <label for="initial_post">Post body</label><br>
<% render("views.common.babycode-editor-component", {ta_name = "initial_post"}) %> <% render("views.common.babycode-editor-component", {ta_name = "initial_post"}) %>
<% render "views.common.bbcode_help" %>
<input type="submit" value="Create thread"> <input type="submit" value="Create thread">
</form> </form>
</div> </div>