perl L10N and Perl Templates
FossilOrigin-Name: 06ed73d30ae11c7651dcb87e4b78f9ef7b297b386f8ff0bbd087e22628bc9a68
This commit is contained in:
parent
004b47ad07
commit
772db3ce28
8 changed files with 313 additions and 83 deletions
17
Makefile
17
Makefile
|
@ -8,25 +8,23 @@ SRC = $(wildcard src/*.c)
|
|||
OBJ = $(patsubst %.c,%.o,$(SRC))
|
||||
HEADERS = $(wildcard src/*.h) config.h
|
||||
PAGES_DIR = static
|
||||
PERL_DIR = perl
|
||||
TMPL_DIR = templates
|
||||
PAGES = $(wildcard $(PAGES_DIR)/*.tmpl)
|
||||
PERLS = $(wildcard $(PERL_DIR)/*.pl)
|
||||
TMPLS = $(wildcard $(TMPL_DIR)/*.tt)
|
||||
PAGES_CMP = $(patsubst %.tmpl,%.ctmpl,$(PAGES))
|
||||
PAGES_C = $(patsubst %.tmpl, %.c,$(PAGES))
|
||||
PAGES_C_OBJ = $(patsubst %.c,%.o,$(PAGES_C))
|
||||
PERLS_C = $(patsubst %.pl,%.cpl,$(PERLS))
|
||||
TMPLS_C = $(patsubst %.tt,%.ctt,$(TMPLS))
|
||||
DIST = dist/
|
||||
PREFIX ?= /usr/local
|
||||
TARGET = treebird
|
||||
|
||||
$(info $(PERLS) and $(PERLS_C))
|
||||
|
||||
MASTODONT_URL = https://fossil.nekobit.net/mastodont-c
|
||||
|
||||
all: $(MASTODONT_DIR) dep_build $(TARGET)
|
||||
apache: all apache_start
|
||||
|
||||
$(TARGET): filec template $(PERLS_C) $(PAGES_CMP) $(PAGES_C) $(PAGES_C_OBJ) $(OBJ) $(HEADERS)
|
||||
$(TARGET): filec template $(TMPLS_C) $(TMPLS) $(PAGES_CMP) $(PAGES_C) $(PAGES_C_OBJ) $(OBJ) $(HEADERS)
|
||||
$(CC) -o $(TARGET) $(OBJ) $(PAGES_C_OBJ) $(LDFLAGS)
|
||||
|
||||
template: src/template/main.o
|
||||
|
@ -41,11 +39,11 @@ emojitoc: scripts/emoji-to.o
|
|||
|
||||
# Redirect stdout and stderr into separate contents as a hack
|
||||
# Let bash do the work :)
|
||||
$(PAGES_DIR)/%.ctmpl: $(PAGES_DIR)/%.tmpl
|
||||
$(PAGES_DIR)/%.ctmpl: $(PAGES_DIR)/%.tmpl $(TMPLS)
|
||||
./template $< $(notdir $*) 2> $(PAGES_DIR)/$(notdir $*).c 1> $@
|
||||
|
||||
$(PERL_DIR)/%.cpl: $(PERL_DIR)/%.pl
|
||||
./filec $< data_$(notdir $*)_pl > $@
|
||||
$(TMPL_DIR)/%.ctt: $(TMPL_DIR)/%.tt
|
||||
./filec $< data_$(notdir $*)_tt > $@
|
||||
|
||||
$(MASTODONT_DIR):
|
||||
cd ..; fossil clone $(MASTODONT_URL) || true
|
||||
|
@ -71,6 +69,7 @@ dep_build:
|
|||
clean:
|
||||
rm -f $(OBJ) src/file-to-c/main.o
|
||||
rm -f $(PAGES_CMP)
|
||||
rm -f $(TMPLS_C)
|
||||
rm -f filec
|
||||
make -C $(MASTODONT_DIR) clean
|
||||
|
||||
|
|
89
perl/l10n.pm
Normal file
89
perl/l10n.pm
Normal file
|
@ -0,0 +1,89 @@
|
|||
package l10n;
|
||||
|
||||
our @EXPORT = qw( %L10N );
|
||||
|
||||
our %L10N = (
|
||||
EN_US => {
|
||||
APP_NAME => 'Treebird',
|
||||
HOME => 'Home',
|
||||
LOCAL => 'Local',
|
||||
FEDERATED => 'Federated',
|
||||
NOTIFICATIONS => 'Notifications',
|
||||
LISTS => 'Lists',
|
||||
FAVOURITES => 'Favorites',
|
||||
BOOKMARKS => 'Bookmarks',
|
||||
DIRECT => 'Direct',
|
||||
CONFIG => 'Config',
|
||||
SEARCH_PLACEHOLDER => 'Search',
|
||||
SEARCH_BUTTON => 'Search',
|
||||
GENERAL => 'General',
|
||||
ACCOUNT => 'Account',
|
||||
JAVASCRIPT => 'JavaScript',
|
||||
CFG_QUICK_ACTIONS => 'Quick actions - Likes, Boosts, etc done in the background',
|
||||
CFG_QUICK_REPLY => 'Quick reply - Replies don\'t require redirects',
|
||||
LIVE_STATUSES => 'Live statuses - Statuses fetch on the fly',
|
||||
APPEARANCE => 'Appearance',
|
||||
VARIANT => 'Variant',
|
||||
THEME_TREEBIRD20 => 'Treebird - Default, simple theme',
|
||||
THEME_TREEBIRD30 => 'Treebird 3.0 - Flat, modern theme',
|
||||
COLOR_SCHEME => 'Color Scheme',
|
||||
LIGHT => 'Light',
|
||||
DARK => 'Dark',
|
||||
SAVE => 'Save',
|
||||
ACCT_MENU => 'Menu',
|
||||
SUBSCRIBE => 'Subscribe',
|
||||
UNSUBSCRIBE => 'Unsubscribe',
|
||||
BLOCK => 'Block',
|
||||
UNBLOCK => 'Unblock',
|
||||
MUTE => 'Mute',
|
||||
UNMUTE => 'Unmute',
|
||||
TAB_STATUSES => 'Statuses',
|
||||
TAB_FOLLOWING => 'Following',
|
||||
TAB_FOLLOWERS => 'Followers',
|
||||
TAB_SCROBBLES => 'Scrobbles',
|
||||
TAB_MEDIA => 'Media',
|
||||
TAB_PINNED => 'Pinned',
|
||||
FOLLOWS_YOU => 'Follows you!',
|
||||
FOLLOW => 'Follow',
|
||||
FOLLOW_PENDING => 'Follow pending',
|
||||
FOLLOWING => 'Following!',
|
||||
BLOCKED => 'You are blocked by this user.',
|
||||
REPLY => 'Reply',
|
||||
REPEAT => 'Repeat',
|
||||
LIKE => 'Like',
|
||||
QUICK => 'Quick',
|
||||
VIEW => 'View',
|
||||
IN_REPLY_TO => 'In reply to',
|
||||
PAGE_NOT_FOUND => 'Content not found',
|
||||
STATUS_NOT_FOUND => 'Status not found',
|
||||
ACCOUNT_NOT_FOUND => 'Account not found',
|
||||
VIS_PUBLIC => 'Public',
|
||||
VIS_UNLISTED => 'Unlisted',
|
||||
VIS_PRIVATE => 'Private',
|
||||
VIS_DIRECT => 'Direct',
|
||||
VIS_LOCAL => 'Local',
|
||||
VIS_LIST => 'List',
|
||||
LOGIN => 'Login',
|
||||
REGISTER => 'Register',
|
||||
USERNAME => 'Username',
|
||||
PASSWORD => 'Password',
|
||||
LOGIN_BTN => 'Login',
|
||||
LOGIN_HEADER => 'Login / Register',
|
||||
LOGIN_FAIL => 'Couldn\'t login',
|
||||
NOTIF_LIKED => 'liked your status',
|
||||
NOTIF_REACTED_WITH => 'reacted with %s',
|
||||
NOTIF_REPEATED => 'repeated your status',
|
||||
NOTIF_FOLLOW => 'followed you',
|
||||
NOTIF_FOLLOW_REQUEST => 'wants to follow you',
|
||||
NOTIF_POLL => 'poll results',
|
||||
NOTIF_COMPACT_LIKED => 'liked',
|
||||
NOTIF_COMPACT_REACTED_WITH => 'reacted',
|
||||
NOTIF_COMPACT_REPEATED => 'repeated',
|
||||
NOTIF_COMPACT_FOLLOW => 'followed',
|
||||
COMPACT_FOLLOW_REQUEST => 'wants to follow',
|
||||
NOTIF_COMPACT_POLL => 'poll',
|
||||
},
|
||||
# TODO bring over Spanish and Chinese
|
||||
);
|
||||
|
||||
return 1;
|
25
perl/main.pl
25
perl/main.pl
|
@ -1,10 +1,31 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
# Modules
|
||||
use Template;
|
||||
use l10n;
|
||||
|
||||
my $template = Template->new(
|
||||
{
|
||||
INTERPOLATE => 1,
|
||||
POST_CHOMP => 1,
|
||||
EVAL_PERL => 1,
|
||||
TRIM => 1
|
||||
});
|
||||
|
||||
sub base_page
|
||||
{
|
||||
my ($ssn, $data) = @_;
|
||||
my $result;
|
||||
|
||||
my $vars = {
|
||||
# L10N => L10N,
|
||||
prefix => '',
|
||||
lang => sub { $l10n::L10N{'EN_US'}{shift(@_)} },
|
||||
};
|
||||
|
||||
$template->process(\$data, $vars, \$result) ||
|
||||
return $template->error();
|
||||
|
||||
2 * 2;
|
||||
$result;
|
||||
}
|
||||
|
||||
print "Hello from Perl\n";
|
||||
|
|
155
src/base_page.c
155
src/base_page.c
|
@ -33,14 +33,23 @@
|
|||
// Files
|
||||
#include "../static/index.ctmpl"
|
||||
#include "../static/quick_login.ctmpl"
|
||||
#include "../templates/main.ctt"
|
||||
|
||||
#define BODY_STYLE "style=\"background:url('%s');\""
|
||||
|
||||
void render_base_page(struct base_page* page, FCGX_Request* req, struct session* ssn, mastodont_t* api)
|
||||
{
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
|
||||
HV* session_hv = perlify_session(ssn);
|
||||
XPUSHs(sv_2mortal(newRV_inc((SV*)session_hv)));
|
||||
XPUSHs(sv_2mortal(newSVpv(data_main_tt, 0)));
|
||||
|
||||
struct mstdnt_args m_args;
|
||||
set_mstdnt_args(&m_args, ssn);
|
||||
char* cookie = GET_ENV("HTTP_COOKIE", req);
|
||||
enum l10n_locale locale = l10n_normalize(ssn->config.lang);
|
||||
char* theme_str = NULL;
|
||||
const char* login_string = "<a href=\"login\" id=\"login-header\">Login / Register</a>";
|
||||
|
@ -58,62 +67,62 @@ void render_base_page(struct base_page* page, FCGX_Request* req, struct session*
|
|||
#define SIDEBAR_CSS_LEN 128
|
||||
char sidebar_css[SIDEBAR_CSS_LEN];
|
||||
|
||||
if (keyint(ssn->cookies.logged_in))
|
||||
login_string = "";
|
||||
/* if (keyint(ssn->cookies.logged_in)) */
|
||||
/* login_string = ""; */
|
||||
|
||||
if (ssn->config.background_url)
|
||||
{
|
||||
easprintf(&background_url_css, BODY_STYLE, ssn->config.background_url);
|
||||
}
|
||||
/* if (ssn->config.background_url) */
|
||||
/* { */
|
||||
/* easprintf(&background_url_css, BODY_STYLE, ssn->config.background_url); */
|
||||
/* } */
|
||||
|
||||
// If user is logged in
|
||||
if (keystr(ssn->cookies.logged_in) && keystr(ssn->cookies.access_token))
|
||||
{
|
||||
account_sidebar_str = construct_account_sidebar(&(ssn->acct), NULL);
|
||||
/* // If user is logged in */
|
||||
/* if (keystr(ssn->cookies.logged_in) && keystr(ssn->cookies.access_token)) */
|
||||
/* { */
|
||||
/* account_sidebar_str = construct_account_sidebar(&(ssn->acct), NULL); */
|
||||
|
||||
// Get / Show notifications on sidebar
|
||||
if (ssn->config.notif_embed)
|
||||
{
|
||||
main_sidebar_str = (char*)sidebar_embed;
|
||||
}
|
||||
else {
|
||||
struct mstdnt_get_notifications_args args = {
|
||||
.exclude_types = 0,
|
||||
.account_id = NULL,
|
||||
.exclude_visibilities = 0,
|
||||
.include_types = 0,
|
||||
.with_muted = 1,
|
||||
.max_id = NULL,
|
||||
.min_id = NULL,
|
||||
.since_id = NULL,
|
||||
.offset = 0,
|
||||
.limit = 8,
|
||||
};
|
||||
/* // Get / Show notifications on sidebar */
|
||||
/* if (ssn->config.notif_embed) */
|
||||
/* { */
|
||||
/* main_sidebar_str = (char*)sidebar_embed; */
|
||||
/* } */
|
||||
/* else { */
|
||||
/* struct mstdnt_get_notifications_args args = { */
|
||||
/* .exclude_types = 0, */
|
||||
/* .account_id = NULL, */
|
||||
/* .exclude_visibilities = 0, */
|
||||
/* .include_types = 0, */
|
||||
/* .with_muted = 1, */
|
||||
/* .max_id = NULL, */
|
||||
/* .min_id = NULL, */
|
||||
/* .since_id = NULL, */
|
||||
/* .offset = 0, */
|
||||
/* .limit = 8, */
|
||||
/* }; */
|
||||
|
||||
if (mastodont_get_notifications(api,
|
||||
&m_args,
|
||||
&args,
|
||||
&storage,
|
||||
¬ifs,
|
||||
¬ifs_len) == 0)
|
||||
{
|
||||
main_sidebar_str = construct_notifications_compact(ssn, api, notifs, notifs_len, NULL);
|
||||
}
|
||||
/* if (mastodont_get_notifications(api, */
|
||||
/* &m_args, */
|
||||
/* &args, */
|
||||
/* &storage, */
|
||||
/* ¬ifs, */
|
||||
/* ¬ifs_len) == 0) */
|
||||
/* { */
|
||||
/* main_sidebar_str = construct_notifications_compact(ssn, api, notifs, notifs_len, NULL); */
|
||||
/* } */
|
||||
|
||||
mstdnt_cleanup_notifications(notifs, notifs_len);
|
||||
mastodont_storage_cleanup(&storage);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Construct small login page
|
||||
struct quick_login_template tdata = {
|
||||
.prefix = config_url_prefix,
|
||||
.username = L10N[locale][L10N_USERNAME],
|
||||
.password = L10N[locale][L10N_PASSWORD],
|
||||
.login = L10N[locale][L10N_LOGIN_BTN],
|
||||
};
|
||||
main_sidebar_str = tmpl_gen_quick_login(&tdata, NULL);
|
||||
}
|
||||
/* mstdnt_cleanup_notifications(notifs, notifs_len); */
|
||||
/* mastodont_storage_cleanup(&storage); */
|
||||
/* } */
|
||||
/* } */
|
||||
/* else { */
|
||||
/* // Construct small login page */
|
||||
/* struct quick_login_template tdata = { */
|
||||
/* .prefix = config_url_prefix, */
|
||||
/* .username = L10N[locale][L10N_USERNAME], */
|
||||
/* .password = L10N[locale][L10N_PASSWORD], */
|
||||
/* .login = L10N[locale][L10N_LOGIN_BTN], */
|
||||
/* }; */
|
||||
/* main_sidebar_str = tmpl_gen_quick_login(&tdata, NULL); */
|
||||
/* } */
|
||||
|
||||
// Combine into sidebar
|
||||
easprintf(&sidebar_str, "%s%s",
|
||||
|
@ -180,27 +189,37 @@ void render_base_page(struct base_page* page, FCGX_Request* req, struct session*
|
|||
.source_link_str = "Source code",
|
||||
};
|
||||
|
||||
size_t len;
|
||||
char* data = tmpl_gen_index(&index_tmpl, &len);
|
||||
// char* data = tmpl_gen_index(&index_tmpl, &len);
|
||||
|
||||
if (!data)
|
||||
{
|
||||
perror("malloc");
|
||||
goto cleanup;
|
||||
}
|
||||
/* if (!data) */
|
||||
/* { */
|
||||
/* perror("malloc"); */
|
||||
/* goto cleanup; */
|
||||
/* } */
|
||||
|
||||
// Run function
|
||||
PUTBACK;
|
||||
call_pv("base_page", G_SCALAR);
|
||||
SPAGAIN;
|
||||
|
||||
char* data = POPp;
|
||||
|
||||
send_result(req, NULL, "text/html", data, len);
|
||||
send_result(req, NULL, "text/html", data, 0);
|
||||
|
||||
// Cleanup
|
||||
/* cleanup_all: */
|
||||
free(data);
|
||||
// free(data);
|
||||
cleanup:
|
||||
free(sidebar_str);
|
||||
if (main_sidebar_str != sidebar_embed) free(main_sidebar_str);
|
||||
free(account_sidebar_str);
|
||||
free(background_url_css);
|
||||
free(instance_str);
|
||||
free(theme_str);
|
||||
/* free(sidebar_str); */
|
||||
/* if (main_sidebar_str != sidebar_embed) free(main_sidebar_str); */
|
||||
/* free(account_sidebar_str); */
|
||||
/* free(background_url_css); */
|
||||
/* free(instance_str); */
|
||||
/* free(theme_str); */
|
||||
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
}
|
||||
|
||||
void send_result(FCGX_Request* req, char* status, char* content_type, char* data, size_t data_len)
|
||||
|
@ -216,7 +235,7 @@ void send_result(FCGX_Request* req, char* status, char* content_type, char* data
|
|||
"Content-Length: %d\r\n\r\n",
|
||||
status ? status : "200 OK",
|
||||
content_type ? content_type : "text/html",
|
||||
data_len + 1);
|
||||
data_len);
|
||||
#ifdef SINGLE_THREADED
|
||||
puts(data);
|
||||
#else
|
||||
|
|
|
@ -18,13 +18,13 @@
|
|||
|
||||
#ifndef BASE_PAGE_H
|
||||
#define BASE_PAGE_H
|
||||
#include "session.h"
|
||||
#include <fcgi_stdio.h>
|
||||
#include <fcgiapp.h>
|
||||
#include <mastodont.h>
|
||||
#include "l10n.h"
|
||||
#include "local_config.h"
|
||||
#include "path.h"
|
||||
#include "session.h"
|
||||
|
||||
enum base_category
|
||||
{
|
||||
|
|
16
src/main.c
16
src/main.c
|
@ -47,10 +47,14 @@
|
|||
#include "local_config_set.h"
|
||||
#include "global_cache.h"
|
||||
#include "conversations.h"
|
||||
#include "../perl/main.cpl"
|
||||
|
||||
#define THREAD_COUNT 20
|
||||
|
||||
// Allow dynamic loading for Perl
|
||||
static void xs_init (pTHX);
|
||||
|
||||
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
|
||||
|
||||
/*******************
|
||||
* Path handling *
|
||||
******************/
|
||||
|
@ -194,6 +198,12 @@ static void* cgi_start(void* arg)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
EXTERN_C void xs_init(pTHX)
|
||||
{
|
||||
char *file = __FILE__;
|
||||
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **env)
|
||||
{
|
||||
// Global init
|
||||
|
@ -205,9 +215,9 @@ int main(int argc, char **argv, char **env)
|
|||
perl = perl_alloc();
|
||||
perl_construct(perl);
|
||||
//char* perl_argv[] = { "", "-e", data_main_pl, NULL };
|
||||
char* perl_argv[] = { "", "perl/main.pl", NULL };
|
||||
char* perl_argv[] = { "", "-I", "perl/", "perl/main.pl", NULL };
|
||||
|
||||
perl_parse(perl, NULL, (sizeof(perl_argv) / sizeof(perl_argv[0])) - 1, perl_argv, (char**)NULL);
|
||||
perl_parse(perl, xs_init, (sizeof(perl_argv) / sizeof(perl_argv[0])) - 1, perl_argv, (char**)NULL);
|
||||
PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
|
||||
perl_run(perl);
|
||||
|
||||
|
|
5
templates/main.ctt
Normal file
5
templates/main.ctt
Normal file
File diff suppressed because one or more lines are too long
87
templates/main.tt
Normal file
87
templates/main.tt
Normal file
|
@ -0,0 +1,87 @@
|
|||
<!DOCTYPE html>
|
||||
<html {{ %s : background_url }}>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>{{ %s : title }}</title>
|
||||
<link rel="icon" type="image/png" href="/favicon.png">
|
||||
<link rel="stylesheet" type="text/css" href="/treebird.css">
|
||||
{{ %s : theme_str }}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="{{ %s : title }} is a decentralized social media platform">
|
||||
<style>
|
||||
{{ %s : sidebar_css }}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="main-page">
|
||||
<header id="navbar">
|
||||
<label for="leftbar-show">
|
||||
<svg class="leftbar-btn navbar-btn" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
|
||||
</label>
|
||||
<a href="{{ %s : prefix }}/"><img src="/treebird_logo.png" height="42"></a>
|
||||
<span class="info">{{ %s : name }}</span>
|
||||
<label for="rightbar-show">
|
||||
<svg class="rightbar-btn navbar-btn" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 17H2a3 3 0 0 0 3-3V9a7 7 0 0 1 14 0v5a3 3 0 0 0 3 3zm-8.27 4a2 2 0 0 1-3.46 0"></path></svg>
|
||||
</label>
|
||||
<label for="searchbar-show">
|
||||
<svg class="search-btn-show" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
</label>
|
||||
<input type="checkbox" class="hidden" id="searchbar-show">
|
||||
<div id="navbar-right-container">
|
||||
<div id="navbar-right">
|
||||
{{ %s : sidebar_cnt }}
|
||||
<!-- Searchbox -->
|
||||
<form action="{{ %s : prefix }}/search" method="get">
|
||||
<input type="text" class="group group-left group-inputbox" placeholder="[% lang('SEARCH_PLACEHOLDER') %]" id="searchbox" name="q"><!-- i hate HTML
|
||||
--><input type="submit" class="btn group group-right" value="[% lang('SEARCH_BUTTON') %]">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<input type="checkbox" id="leftbar-show" class="hidden">
|
||||
<input type="checkbox" id="rightbar-show" class="hidden">
|
||||
<table id="content" class="ui-table">
|
||||
<!-- Navigation -->
|
||||
<tr>
|
||||
<td id="leftbar" class="sidebar">
|
||||
<ul>
|
||||
<li><a class="sidebarbtn {{ %s : active_home }}" href="$prefix/">[% lang('HOME') %]</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_local }}" href="$prefix/local/">[% lang('LOCAL') %]</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_federated }}" href="$prefix/federated/">[% lang('FEDERATED') %]</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_notifications }}" href="$prefix/notifications">[% lang('NOTIFICATIONS') %]</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_lists }}" href="$prefix/lists">[% lang('LISTS') %]</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_favourites }}" href="$prefix/favourites">[% lang('FAVOURITES') %]</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_bookmarks }}" href="$prefix/bookmarks">[% lang('BOOKMARKS') %]</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_direct }}" href="$prefix/direct">[% lang('DIRECT') %]</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_chats }}" href="$prefix/chats">Chats</a></li>
|
||||
<li><a class="sidebarbtn {{ %s : active_config }}" href="$prefix/config">[% lang('CONFIG') %]</a></li>
|
||||
</ul>
|
||||
{{ %s : sidebar_leftbar }}
|
||||
{{ %s : instance_panel }}
|
||||
<div class="mini-links">
|
||||
<a href="{{%s:prefix}}/about">{{ %s : about_link_str }}</a>
|
||||
<span class="bullet-separate">•</span>
|
||||
<a href="{{%s:prefix}}/about/license">{{ %s : license_link_str }}</a>
|
||||
<span class="bullet-separate">•</span>
|
||||
<a href="https://fossil.nekobit.net/treebird">{{ %s : source_link_str }}</a>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<!-- Display for posts -->
|
||||
<td id="main">
|
||||
{{ %s : main }}
|
||||
</td>
|
||||
|
||||
<!-- Notifications and such -->
|
||||
<td id="rightbar" class="sidebar">
|
||||
{{ %s : sidebar_rightbar }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Source -->
|
||||
<script src="/js/main.js"></script>
|
||||
<script src="/js/emoji.js"></script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in a new issue