openwrite 0.10.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openwrite/__init__.py +134 -0
- openwrite/cli.py +340 -0
- openwrite/db/__init__.py +0 -0
- openwrite/db/base.py +3 -0
- openwrite/launch_gemini.py +8 -0
- openwrite/routes/admin.py +170 -0
- openwrite/routes/auth.py +77 -0
- openwrite/routes/blog.py +205 -0
- openwrite/routes/dashboard.py +408 -0
- openwrite/routes/federation.py +284 -0
- openwrite/routes/main.py +96 -0
- openwrite/routes/upload.py +81 -0
- openwrite/static/IBMPlexSans-Regular.ttf +0 -0
- openwrite/static/Merriweather.ttf +0 -0
- openwrite/static/avatar.png +0 -0
- openwrite/static/favicon.ico +0 -0
- openwrite/static/logo.png +0 -0
- openwrite/static/script/chart.js +14 -0
- openwrite/static/script/highlight.min.js +1244 -0
- openwrite/static/script/openwrite.js +88 -0
- openwrite/static/script/papaparse.min.js +7 -0
- openwrite/static/script/showdown.min.js +3 -0
- openwrite/static/script/showdown.min.js.map +1 -0
- openwrite/static/script/site.compat.min.js +7 -0
- openwrite/static/script/site.min.js +7 -0
- openwrite/static/style/hl.css +1 -0
- openwrite/static/style/style.css +611 -0
- openwrite/static/style/themes/light.css +28 -0
- openwrite/static/style/themes/obscura.css +27 -0
- openwrite/static/style/themes/stickynote.css +50 -0
- openwrite/static/style/themes/terminal.css +37 -0
- openwrite/static/style/themes/warmnight.css +73 -0
- openwrite/static/style/themes/windows98.css +132 -0
- openwrite/templates/admin.html +47 -0
- openwrite/templates/blog.html +16 -0
- openwrite/templates/blog_footer.html +6 -0
- openwrite/templates/blog_header.html +45 -0
- openwrite/templates/blog_preview.html +44 -0
- openwrite/templates/changepw.html +19 -0
- openwrite/templates/create.html +46 -0
- openwrite/templates/dashboard.html +45 -0
- openwrite/templates/discover.html +11 -0
- openwrite/templates/edit.html +190 -0
- openwrite/templates/footer.html +16 -0
- openwrite/templates/header.html +61 -0
- openwrite/templates/import.html +142 -0
- openwrite/templates/index.html +9 -0
- openwrite/templates/instances.html +14 -0
- openwrite/templates/login.html +18 -0
- openwrite/templates/new_post.html +207 -0
- openwrite/templates/post.html +53 -0
- openwrite/templates/preview.html +37 -0
- openwrite/templates/register.html +42 -0
- openwrite/templates/settings.html +63 -0
- openwrite/templates/stats.html +242 -0
- openwrite/utils/create_db.py +15 -0
- openwrite/utils/db.py +30 -0
- openwrite/utils/helpers.py +216 -0
- openwrite/utils/i18n.json +229 -0
- openwrite/utils/models.py +87 -0
- openwrite/utils/translations.py +6 -0
- openwrite-0.10.1.dist-info/METADATA +684 -0
- openwrite-0.10.1.dist-info/RECORD +67 -0
- openwrite-0.10.1.dist-info/WHEEL +5 -0
- openwrite-0.10.1.dist-info/entry_points.txt +2 -0
- openwrite-0.10.1.dist-info/licenses/LICENSE +661 -0
- openwrite-0.10.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
body {
|
|
2
|
+
background: #000;
|
|
3
|
+
color: #FFF;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
article.blog-content {
|
|
7
|
+
font-family: "Courier New";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
h1.blog-name a {
|
|
11
|
+
font-family: "Courier New";
|
|
12
|
+
color: #00FF00;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
h1.post-title {
|
|
16
|
+
font-family: "Courier New";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.header #menu a svg {
|
|
20
|
+
fill: #00FF00;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
h1.blog-name a::before {
|
|
24
|
+
content: '> ';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.blog-content .post-title {
|
|
28
|
+
color: #545454;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
i.post-date {
|
|
32
|
+
color: #545454;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
article.post-content a {
|
|
36
|
+
color: #00FF00;
|
|
37
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
body {
|
|
2
|
+
background: #201917;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
header.header {
|
|
6
|
+
border-bottom: unset;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.container {
|
|
10
|
+
max-width: 700px;
|
|
11
|
+
padding: 1rem 0.5rem;
|
|
12
|
+
font-family: 'Georgia', serif;
|
|
13
|
+
line-height: 1.6;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
h1.blog-name a {
|
|
17
|
+
color: #202020;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#menu a svg {
|
|
21
|
+
fill: #F59D84;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
article.post-content {
|
|
25
|
+
color: #F59D84;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
article.blog-content {
|
|
29
|
+
border: 1px solid #F59D84;
|
|
30
|
+
padding: 2rem;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
article.blog-content h3 {
|
|
34
|
+
color: #F59D84;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
article.post-content a {
|
|
38
|
+
color: #ffa489;
|
|
39
|
+
text-decoration: underline;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
article.post-content h1, article.post-content h2, article.post-content h3, article.post-content h4, article.post-content h5 {
|
|
43
|
+
color: #ffd2c5;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
article.post-content blockquote {
|
|
47
|
+
color: #8d7068;
|
|
48
|
+
border-left: 4px solid #8d7068;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
h1.post-title {
|
|
52
|
+
color: #fff;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
h1.blog-name {
|
|
56
|
+
font-family: "Courier New", "Courier";
|
|
57
|
+
font-size: 18px;
|
|
58
|
+
background: #F59D84;
|
|
59
|
+
padding-left: 1rem;
|
|
60
|
+
padding-right: 1rem;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
i.post-date {
|
|
64
|
+
color: #7c7c7c;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
pre code.hljs {
|
|
68
|
+
background: #1A0E0B;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
p code {
|
|
72
|
+
background: #ffffea;
|
|
73
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
@media only screen and (max-width: 850px) {
|
|
2
|
+
.header {
|
|
3
|
+
flex-direction: row;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.header #menu {
|
|
7
|
+
margin-top: unset;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
body {
|
|
12
|
+
background: #ff00f7;
|
|
13
|
+
background: linear-gradient(180deg, rgba(255, 0, 247, 1) 0%, rgba(148, 230, 255, 1) 100%);
|
|
14
|
+
font-family: "Georgia", "Times New Roman";
|
|
15
|
+
background-attachment: fixed;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.container {
|
|
19
|
+
margin-top: 1rem;
|
|
20
|
+
background: #b7b7b7;
|
|
21
|
+
border: 2px solid #FFFFFF;
|
|
22
|
+
box-shadow:
|
|
23
|
+
2px 2px 0 #000000,
|
|
24
|
+
1px 1px 0 #FFFFFF,
|
|
25
|
+
inset 1px 1px 0 #FFFFFF,
|
|
26
|
+
inset -1px -1px 0 #A0A0A0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
h1.blog-name {
|
|
30
|
+
font-size: 12px;
|
|
31
|
+
margin-left: 10px;
|
|
32
|
+
margin-top: 4px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
h1.blog-name a {
|
|
36
|
+
color: #fff;
|
|
37
|
+
font-family: "Microsoft Sans Serif", "MS Sans Serif", sans-serif;
|
|
38
|
+
display: inline-flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
gap: 0.5rem;
|
|
41
|
+
text-decoration: none;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
h1.blog-name a::before {
|
|
45
|
+
content: '';
|
|
46
|
+
display: inline-block;
|
|
47
|
+
width: 20px;
|
|
48
|
+
height: 20px;
|
|
49
|
+
background-image: url(https://openwrite.b-cdn.net/world-2.png);
|
|
50
|
+
background-size: contain;
|
|
51
|
+
background-repeat: no-repeat;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
header.header {
|
|
55
|
+
height: 1rem;
|
|
56
|
+
background: #0000a3;
|
|
57
|
+
background: linear-gradient(90deg,rgba(0, 0, 163, 1) 0%, rgba(0, 195, 255, 1) 100%);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
article.blog-content {
|
|
61
|
+
font-family: "Georgia", "Times New Roman";
|
|
62
|
+
color: #222;
|
|
63
|
+
padding: 1rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
article.post-content {
|
|
67
|
+
color: #222;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
article.post-content a {
|
|
71
|
+
color: #0000FF;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.header #menu a {
|
|
75
|
+
margin-right: 4px;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
h1.post-title {
|
|
79
|
+
font-family: "Georgia", "Times New Roman";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
h1.post-title::before {
|
|
83
|
+
content: '';
|
|
84
|
+
display: inline-block;
|
|
85
|
+
width: 32px;
|
|
86
|
+
height: 32px;
|
|
87
|
+
background-image: url(https://openwrite.b-cdn.net/write_file-1.png);
|
|
88
|
+
background-size: contain;
|
|
89
|
+
background-repeat: no-repeat;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
p code {
|
|
93
|
+
background: #fff;
|
|
94
|
+
color: #000;
|
|
95
|
+
font-family: "Courier New", "Courier";
|
|
96
|
+
box-shadow: -2px -2px 0px 0px rgba(59,59,59,0.75) inset;
|
|
97
|
+
-webkit-box-shadow: -2px -2px 0px 0px rgba(59,59,59,0.75) inset;
|
|
98
|
+
-moz-box-shadow: -2px -2px 0px 0px rgba(59,59,59,0.75) inset;
|
|
99
|
+
display: inline-block;
|
|
100
|
+
padding: 2px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
i.post-date::before {
|
|
104
|
+
content: '';
|
|
105
|
+
display: inline-block;
|
|
106
|
+
width: 13px;
|
|
107
|
+
height: 13px;
|
|
108
|
+
background-image: url(https://openwrite.b-cdn.net/calendar-0.png);
|
|
109
|
+
background-size: contain;
|
|
110
|
+
background-repeat: no-repeat;
|
|
111
|
+
margin-right: 5px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
footer.footer {
|
|
115
|
+
border: none;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
pre code.hljs {
|
|
119
|
+
background: #fff;
|
|
120
|
+
color: #000;
|
|
121
|
+
font-family: "Courier New", "Courier";
|
|
122
|
+
box-shadow: -2px -2px 0px 0px rgba(59,59,59,0.75) inset;
|
|
123
|
+
-webkit-box-shadow: -2px -2px 0px 0px rgba(59,59,59,0.75) inset;
|
|
124
|
+
-moz-box-shadow: -2px -2px 0px 0px rgba(59,59,59,0.75) inset;
|
|
125
|
+
display: block;
|
|
126
|
+
padding: 2px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
article.post-content blockquote {
|
|
130
|
+
color: #46608e;
|
|
131
|
+
border-left: 4px solid #46608e;
|
|
132
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{% include 'header.html' %}
|
|
2
|
+
{% if error %}
|
|
3
|
+
<div class="error">{{ error }}</div>
|
|
4
|
+
{% endif %}
|
|
5
|
+
<h1 class="centered">Actions</h1>
|
|
6
|
+
<div style="display: flex; justify-content: center; gap: 1rem;">
|
|
7
|
+
<a style="width: 5rem;" class="btn purple" href="/admin/add_user">{{ g.trans['add_user'] }}</a>
|
|
8
|
+
<a style="width: 5rem;" class="btn purple" href="/admin/settings">Settings</a>
|
|
9
|
+
</div>
|
|
10
|
+
<h1 class="centered">Blogs</h1>
|
|
11
|
+
<table class="table">
|
|
12
|
+
<thead>
|
|
13
|
+
<th>Title</th><th>Name</th><th>Author</th><th>Actions</th>
|
|
14
|
+
</thead>
|
|
15
|
+
<tbody>
|
|
16
|
+
{% for blog in blogs %}
|
|
17
|
+
<tr><td>{{ blog.title }}</td><td>{{ blog.name }}</td><td>{{ blog.ownername }}</td><td><a class="action" href="/admin/delete_blog/{{ blog.name }}" onclick="return confirm('{{ g.trans['are_you_sure_blog'] }} {{ blog.name }}?\n{{ g.trans['this_action_cannot_be_reverted'] }}.')">Delete</a></td></tr>
|
|
18
|
+
{% endfor %}
|
|
19
|
+
</tbody>
|
|
20
|
+
</table>
|
|
21
|
+
|
|
22
|
+
<h1 class="centered">Users</h1>
|
|
23
|
+
<table class="table">
|
|
24
|
+
<thead>
|
|
25
|
+
<th>Username</th><th>Admin?</th><th>Actions</th>
|
|
26
|
+
</thead>
|
|
27
|
+
<tbody>
|
|
28
|
+
{% for user in users %}
|
|
29
|
+
<tr><td>{{ user.username }}</td>
|
|
30
|
+
<td>{% if user.admin > 0 %}{{ g.trans['yes'] }}{% else %}{{ g.trans['no'] }}{% endif %}</td>
|
|
31
|
+
<td>
|
|
32
|
+
<a class="action" href="/admin/delete_user/{{ user.username }}" onclick="return confirm('{{ g.trans['are_you_sure_user'] }} {{ user.username }}?\n{{ g.trans['this_action_cannot_be_reverted'] }}.')">Delete</a>
|
|
33
|
+
{% if user.admin > 0 %}
|
|
34
|
+
{% if user.username != "admin" %}
|
|
35
|
+
<a class="action" onclick="return confirm('{{ g.trans['are_you_sure_remove_admin'] }} {{ user.username }}?')" href="/admin/remove_admin/{{ user.username }}">{{ g.trans['remove_admin'] }}</a>
|
|
36
|
+
{% endif %}
|
|
37
|
+
{% else %}
|
|
38
|
+
<a class="action" onclick="return confirm('{{ g.trans['are_you_sure_make_admin'] }} {{ user.username }}?')" href="/admin/make_admin/{{ user.username }}">{{ g.trans['add_admin'] }}</a>
|
|
39
|
+
{% endif %}
|
|
40
|
+
</td>
|
|
41
|
+
</tr>
|
|
42
|
+
{% endfor %}
|
|
43
|
+
</tbody>
|
|
44
|
+
</table>
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
{% include 'footer.html' %}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{% include 'blog_header.html' %}
|
|
2
|
+
<article class="post-content">
|
|
3
|
+
{{ blog.description_html | safe }}
|
|
4
|
+
</article>
|
|
5
|
+
{% if posts | count > 0 %}
|
|
6
|
+
<hr>
|
|
7
|
+
<h3><b>{{ g.trans['posts'] }}</b></h3>
|
|
8
|
+
<article class="post-content" id="posts">
|
|
9
|
+
{% for post in posts %}
|
|
10
|
+
<div class="postlist_item">
|
|
11
|
+
<i class="datetime">{{ post.date }}</i> - {% if g.mode == "multi" %}<a href="{{ blog.url }}/{{ post.link }}">{{ post.title }}</a>{% else %}<a href="http://{{ g.main_domain }}/p/{{ post.link }}">{{ post.title }}</a>{% endif %}
|
|
12
|
+
</div>
|
|
13
|
+
{% endfor%}
|
|
14
|
+
</article>
|
|
15
|
+
{% endif %}
|
|
16
|
+
{% include 'blog_footer.html' %}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
{% if blog.index == "off" %}<meta name="robots" content="noindex, nofollow"> {% endif %}
|
|
7
|
+
<title>{% if post %}{{ post.title }} | {% endif %}{{ blog.title }}</title>
|
|
8
|
+
<meta name="description" content="Minimalist, opensource blog. Write, freely.">
|
|
9
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='style/style.css') }}">
|
|
10
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='style/hl.css') }}">
|
|
11
|
+
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
|
12
|
+
<script src="{{ url_for('static', filename='script/highlight.min.js') }}"></script>
|
|
13
|
+
<script nonce="{{ g.nonce }}">hljs.highlightAll();</script>
|
|
14
|
+
<script src="{{ url_for('static', filename='script/openwrite.js') }}"></script>
|
|
15
|
+
{% if blog.theme != "default" %}
|
|
16
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='style/themes/'+blog.theme) }}.css">
|
|
17
|
+
{% endif %}
|
|
18
|
+
{% if blog.name == "themes-test" %}
|
|
19
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='style/test.css') }}">
|
|
20
|
+
{% endif %}
|
|
21
|
+
{% if blog.css %}
|
|
22
|
+
<style>
|
|
23
|
+
{{ blog.css }}
|
|
24
|
+
</style>
|
|
25
|
+
{% endif%}
|
|
26
|
+
</head>
|
|
27
|
+
<body>
|
|
28
|
+
<div class="container">
|
|
29
|
+
<header class="header">
|
|
30
|
+
{% if g.mode == "multi" %}
|
|
31
|
+
<h1 class="blog-name"><a href="{{ blog.url }}"><span>{{ blog.title }}</span></a></h1>
|
|
32
|
+
{% else %}
|
|
33
|
+
<h1 class="blog-name"><a href="http://{{ g.main_domain }}"><span>{{ blog.title }}</span></a></h1>
|
|
34
|
+
{% endif %}
|
|
35
|
+
<div id="menu">
|
|
36
|
+
<a href="{{ blog.url }}/rss">
|
|
37
|
+
<svg fill="#FFFFFF" width="20px" height="20px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
|
38
|
+
<path d="M20.885 30.996h-5.83c-0.037-7.745-6.306-14.014-14.047-14.052h-0.004v-5.83c10.958 0.055 19.826 8.924 19.881 19.877l0 0.005zM5.117 22.767c0.001 0 0.001 0 0.002 0 2.272 0 4.114 1.842 4.114 4.114s-1.842 4.114-4.114 4.114c-2.271 0-4.113-1.84-4.114-4.111v-0c0.003-2.271 1.842-4.112 4.112-4.118h0.001zM24.996 30.996c-0.064-13.225-10.767-23.928-23.986-23.993l-0.006-0v-5.998c16.531 0.082 29.91 13.461 29.991 29.984l0 0.008z"></path>
|
|
39
|
+
|
|
40
|
+
</svg>
|
|
41
|
+
|
|
42
|
+
</a>
|
|
43
|
+
</div>
|
|
44
|
+
</header>
|
|
45
|
+
<article class="blog-content">
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>[preview] {{ data.title }}</title>
|
|
7
|
+
<meta name="description" content="Minimalist, opensource blog. Write, freely.">
|
|
8
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='style/style.css') }}">
|
|
9
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='style/hl.css') }}">
|
|
10
|
+
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
|
11
|
+
<script src="{{ url_for('static', filename='highlight.min.js') }}"></script>
|
|
12
|
+
<script nonce="{{ g.nonce }}">hljs.highlightAll();</script>
|
|
13
|
+
<script src="{{ url_for('static', filename='openwrite.js') }}"></script>
|
|
14
|
+
{% if data.theme != "default" %}
|
|
15
|
+
<link rel="stylesheet" href="{{ url_for('static', filename='style/themes/'+data.theme) }}.css">
|
|
16
|
+
{% endif %}
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<div class="container">
|
|
20
|
+
<header class="header">
|
|
21
|
+
<h1 class="blog-name"><a href="#"><span>{{ data.title }}</span></a></h1>
|
|
22
|
+
<div id="menu">
|
|
23
|
+
</div>
|
|
24
|
+
</header>
|
|
25
|
+
<article class="blog-content">
|
|
26
|
+
<article class="post-content">
|
|
27
|
+
{{ data.content | safe }}
|
|
28
|
+
</article>
|
|
29
|
+
<hr>
|
|
30
|
+
<h3><b>{{ g.trans['posts'] }}</b></h3>
|
|
31
|
+
<article class="post-content">
|
|
32
|
+
<div class="postlist_item">
|
|
33
|
+
<i class="datetime">01.01.1970, 00:01</i>
|
|
34
|
+
-
|
|
35
|
+
<a href="#">{{ g.trans['post'] }} 1</a>
|
|
36
|
+
</div>
|
|
37
|
+
</article>
|
|
38
|
+
</article>
|
|
39
|
+
</div>
|
|
40
|
+
<footer class="footer">
|
|
41
|
+
Written with ♡ on <a target="_blank" href="https://{{ g.main_domain }}/">{{ g.main_domain }}</a>
|
|
42
|
+
</footer>
|
|
43
|
+
</body>
|
|
44
|
+
</html>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{% include 'header.html' %}
|
|
2
|
+
|
|
3
|
+
<h1 class="centered">{{ g.trans["change_password"] }}</h1>
|
|
4
|
+
|
|
5
|
+
<article class="main-content">
|
|
6
|
+
{% if error %}
|
|
7
|
+
<div class="error">{{ error }}</div>
|
|
8
|
+
{% endif %}
|
|
9
|
+
<form method="post" action="/dashboard/changepw">
|
|
10
|
+
<span class="form-field">{{ g.trans["current_password"] }}:</span>
|
|
11
|
+
<input type="password" name="current_pass">
|
|
12
|
+
<span class="form-field">{{ g.trans["new_password"] }}:</span>
|
|
13
|
+
<input type="password" name="new_pass">
|
|
14
|
+
<span class="form-field">{{ g.trans["password2"] }}:</span>
|
|
15
|
+
<input type="password" name="new_pass2">
|
|
16
|
+
<input type="submit" name="sub" value="{{ g.trans["change_password"] }}" class="btn purple" style="margin-top: 1rem;">
|
|
17
|
+
</form>
|
|
18
|
+
</article>
|
|
19
|
+
{% include 'footer.html' %}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{% include 'header.html' %}
|
|
2
|
+
<h1 class="centered">create a new blog</h1>
|
|
3
|
+
<article class="main-content">
|
|
4
|
+
{% if error %}
|
|
5
|
+
<div class="error">{{ error }}</div>
|
|
6
|
+
{% endif %}
|
|
7
|
+
|
|
8
|
+
<form method="post" action="/dashboard/create">
|
|
9
|
+
<span class="form-field">{{ g.trans['choose_blog_title'] }}:</span>
|
|
10
|
+
<input type="text" name="name" class="medium" placeholder="my awesome blog" required>
|
|
11
|
+
<span class="form-field">{{ g.trans['choose_blog_url'] }}:</span>
|
|
12
|
+
<input id="url" oninput="change_url();" type="text" name="url" class="medium" placeholder="my-awesome-blog" required>
|
|
13
|
+
|
|
14
|
+
<span class="form-field" style="margin-top: 2rem;">{{ g.trans['access_blog_how'] }}?</span>
|
|
15
|
+
<div class="horizontal-fields">
|
|
16
|
+
<input type="radio" id="domain" name="access" value="domain">
|
|
17
|
+
<label for="domain">{{ g.trans['domain_name'] }}: <i><span id="bname">my-awesome-blog</span>.{{ g.main_domain }}</i></label>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="horizontal-fields">
|
|
20
|
+
<input type="radio" id="path" name="access" value="path" checked>
|
|
21
|
+
<label for="path">{{ g.trans['path'] }}: <i>{{ g.main_domain }}/b/<span id="bname2">my-awesome-blog</span></i></label>
|
|
22
|
+
</div>
|
|
23
|
+
<div class="horizontal-fields" style="margin-top: 2rem;">
|
|
24
|
+
<input type="checkbox" name="index" id="index">
|
|
25
|
+
<label for="index">{{ g.trans['index_blog'] }}?</label>
|
|
26
|
+
</div>
|
|
27
|
+
<input type="submit" value="{{ g.trans['create'] }}" class="btn purple">
|
|
28
|
+
</form>
|
|
29
|
+
</article>
|
|
30
|
+
|
|
31
|
+
<script nonce="{{ g.nonce }}">
|
|
32
|
+
function change_url() {
|
|
33
|
+
var url = document.querySelector("#url").value.trim().replaceAll(/[^a-zA-Z0-9]+/g, "-").replaceAll(".", "-").toLowerCase();
|
|
34
|
+
var bname = document.querySelector("#bname");
|
|
35
|
+
var bname2 = document.querySelector("#bname2");
|
|
36
|
+
|
|
37
|
+
if(url.length > 0) {
|
|
38
|
+
bname.innerText = url;
|
|
39
|
+
bname2.innerText = url;
|
|
40
|
+
} else {
|
|
41
|
+
bname.innerText = "my-awesome-blog";
|
|
42
|
+
bname2.innerText = "my-awesome-blog";
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
</script>
|
|
46
|
+
{% include 'footer.html' %}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{% include 'header.html' %}
|
|
2
|
+
{% if error %}
|
|
3
|
+
<div class="error">{{ error }}</div>
|
|
4
|
+
{% endif %}
|
|
5
|
+
{% if message %}
|
|
6
|
+
<div class="message">{{ message }}</div>
|
|
7
|
+
{% endif %}
|
|
8
|
+
<h1 class="centered">{% if g.mode == "single" %}{{ g.trans['your_blog'] }}{% else %}{{ g.trans['your_blogs'] }}{% endif %}</h1>
|
|
9
|
+
{% if g.mode == "multi" %}
|
|
10
|
+
<h2>{{ blogs | count }}/{{ g.blog_limit }}</h2>
|
|
11
|
+
{% endif %}
|
|
12
|
+
{% for blog in blogs %}
|
|
13
|
+
<div class="bloginfo">
|
|
14
|
+
{% if g.mode == "multi" %}
|
|
15
|
+
<h2><b>{{ blog.name }}</b></h2>
|
|
16
|
+
{% endif %}
|
|
17
|
+
<span class="bloginfo">{{ g.trans['title'] }}: {{ blog.title }}</span>
|
|
18
|
+
<span class="bloginfo">URL:
|
|
19
|
+
{% if g.mode == "multi" %}
|
|
20
|
+
<a href="{% if blog.access == "path" %}https://{{ g.main_domain }}/b/{{ blog.name }} {% else %}https://{{ blog.name }}.{{ g.main_domain }}/{% endif %}" target="_blank" style="text-decoration: none; color: #fff;">{% if blog.access == "path" %}https://{{ g.main_domain }}/b/{{ blog.name }} {% else %}https://{{ blog.name }}.{{ g.main_domain }}/{% endif %}</a>
|
|
21
|
+
{% else %}
|
|
22
|
+
<a style="text-decoration: none; color: #fff" href="http://{{ g.main_domain }}">{{ g.main_domain }}</a>
|
|
23
|
+
{% endif %}
|
|
24
|
+
</span>
|
|
25
|
+
<div class="buttons-list">
|
|
26
|
+
<a href="/dashboard/edit/{{ blog.name }}" class="btn empty">{{ g.trans['edit'] }}</a>
|
|
27
|
+
<a href="/dashboard/post/{{ blog.name }}" class="btn purple">{{ g.trans['new_post'] }}</a>
|
|
28
|
+
<a href="/dashboard/stats/{{ blog.name }}" class="btn purple">{{ g.trans['statistics'] }}</a>
|
|
29
|
+
{% if g.mode == "multi" %}
|
|
30
|
+
<a href="/dashboard/delete/{{ blog.name }}" class="btn red" onclick="return confirm('{{ g.trans['are_you_sure_blog'] }} {{ blog.name }}?\n{{ g.trans['this_action_cannot_be_reverted'] }}.')">{{g.trans['delete_blog'] }}</a>
|
|
31
|
+
{% endif %}
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
{% endfor %}
|
|
35
|
+
<h1 style="padding: 2rem;" class="centered">{{ g.trans['settings'] }}</h1>
|
|
36
|
+
<div class="buttons-list">
|
|
37
|
+
{% if g.mode == "multi" %}
|
|
38
|
+
{% if blogs | count < g.blog_limit | int %}
|
|
39
|
+
<a href="/dashboard/create" class="btn purple">{{ g.trans['create_new_blog'] }}</a>
|
|
40
|
+
{% endif %}
|
|
41
|
+
{% endif %}
|
|
42
|
+
<a class="btn purple" href="/dashboard/changepw">{{ g.trans['change_password'] }}</a>
|
|
43
|
+
<a class="btn purple" href="/dashboard/import">{{ g.trans['migrate_posts'] }}</a>
|
|
44
|
+
</div>
|
|
45
|
+
{% include 'footer.html' %}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{% include 'header.html' %}
|
|
2
|
+
<h1 class="centered">{{ g.trans['discover'] }}</h1>
|
|
3
|
+
<p style="margin-bottom: 2rem;">{{ g.trans['discover_text'] }}</p>
|
|
4
|
+
<div style="display: flex; flex-direction: column">
|
|
5
|
+
{% for p in posts %}
|
|
6
|
+
<div style="display: flex; flex-direction: row; gap: 1rem">
|
|
7
|
+
<i class="datetime">{{ p.date }}</i> - {{ p.blogname }} - <a class="action" href="{{ p.url }}" target="_blank">{{ p.title }}</a>
|
|
8
|
+
</div>
|
|
9
|
+
{% endfor %}
|
|
10
|
+
</div>
|
|
11
|
+
{% include 'footer.html' %}
|