openwrite 0.13.0__tar.gz → 0.13.1__tar.gz
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-0.13.0/openwrite.egg-info → openwrite-0.13.1}/PKG-INFO +1 -1
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/routes/admin.py +24 -9
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/routes/dashboard.py +71 -29
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/routes/main.py +1 -1
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/style/style.css +6 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/create.html +7 -1
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/dashboard.html +5 -2
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/discover.html +1 -1
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/edit.html +9 -2
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/footer.html +1 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/header.html +0 -1
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/new_page.html +7 -1
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/new_post.html +46 -11
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/post.html +7 -3
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/settings.html +7 -1
- openwrite-0.13.1/openwrite/utils/i18n.json +1 -0
- {openwrite-0.13.0 → openwrite-0.13.1/openwrite.egg-info}/PKG-INFO +1 -1
- {openwrite-0.13.0 → openwrite-0.13.1}/pyproject.toml +1 -1
- openwrite-0.13.0/openwrite/utils/i18n.json +0 -1
- {openwrite-0.13.0 → openwrite-0.13.1}/LICENSE +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/MANIFEST.in +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/README.md +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/__init__.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/cli.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/db/__init__.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/db/base.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/gemini_multi.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/gemini_single.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/routes/auth.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/routes/blog.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/routes/federation.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/routes/upload.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/IBMPlexSans-Regular.ttf +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/Merriweather.ttf +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/avatar.png +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/emoji.json +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/favicon.ico +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/logo.png +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/script/chart.js +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/script/highlight.min.js +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/script/nativeEmoji.js +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/script/openwrite.js +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/script/papaparse.min.js +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/script/showdown.min.js +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/script/showdown.min.js.map +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/script/site.compat.min.js +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/script/site.min.js +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/style/hl.css +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/style/nativeEmoji.min.css +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/style/themes/cyberpunk.css +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/style/themes/light.css +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/style/themes/obscura.css +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/style/themes/stickynote.css +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/style/themes/terminal.css +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/style/themes/warmnight.css +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/static/style/themes/windows98.css +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/admin.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/blog.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/blog_footer.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/blog_header.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/blog_preview.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/changepw.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/import.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/index.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/instances.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/login.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/page_preview.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/preview.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/register.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/stats.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/templates/translations.html +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/utils/create_db.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/utils/db.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/utils/helpers.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite/utils/models.py +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite.egg-info/SOURCES.txt +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite.egg-info/dependency_links.txt +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite.egg-info/entry_points.txt +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite.egg-info/requires.txt +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/openwrite.egg-info/top_level.txt +0 -0
- {openwrite-0.13.0 → openwrite-0.13.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from flask import Blueprint, render_template, redirect, g, request, make_response
|
|
2
2
|
import json
|
|
3
|
-
from openwrite.utils.models import Blog, User, Settings, Home
|
|
3
|
+
from openwrite.utils.models import Blog, User, Settings, Home, Post
|
|
4
4
|
import re
|
|
5
5
|
import bcrypt
|
|
6
6
|
from werkzeug.utils import secure_filename
|
|
@@ -116,16 +116,16 @@ def admin_add_user():
|
|
|
116
116
|
|
|
117
117
|
form_username = request.form.get('username')
|
|
118
118
|
if not re.match(r"^[a-zA-Z0-9](?:[a-zA-Z0-9_-]{1,28}[a-zA-Z0-9])?$", form_username):
|
|
119
|
-
return render_template('register.html', error=
|
|
119
|
+
return render_template('register.html', error='wrong_username', add="1", captcha="0")
|
|
120
120
|
form_password = request.form.get('password')
|
|
121
121
|
form_password2 = request.form.get('password2')
|
|
122
122
|
|
|
123
123
|
if form_password != form_password2:
|
|
124
|
-
return render_template("register.html", error=
|
|
124
|
+
return render_template("register.html", error='password_dont_match', add="1", captcha="0")
|
|
125
125
|
|
|
126
126
|
user = g.db.query(User).filter_by(username=form_username).first()
|
|
127
127
|
if user:
|
|
128
|
-
return render_template('register.html', error=
|
|
128
|
+
return render_template('register.html', error="user_exists", add="1", captcha="0")
|
|
129
129
|
|
|
130
130
|
try:
|
|
131
131
|
hashed = bcrypt.hashpw(form_password.encode('utf-8'), bcrypt.gensalt())
|
|
@@ -136,7 +136,7 @@ def admin_add_user():
|
|
|
136
136
|
except Exception as e:
|
|
137
137
|
print(e)
|
|
138
138
|
g.db.rollback()
|
|
139
|
-
return render_template('register.html', error=
|
|
139
|
+
return render_template('register.html', error='error', add="1", captcha="0")
|
|
140
140
|
|
|
141
141
|
|
|
142
142
|
@admin_bp.route("/admin/settings", methods=['GET', 'POST'])
|
|
@@ -166,17 +166,17 @@ def admin_settings():
|
|
|
166
166
|
file = request.files['logo']
|
|
167
167
|
filename = secure_filename(file.filename)
|
|
168
168
|
if "." not in filename:
|
|
169
|
-
return render_template("settings.html", settings=settings_dict, hometext=hometext, error=
|
|
169
|
+
return render_template("settings.html", settings=settings_dict, hometext=hometext, error='invalid_filename')
|
|
170
170
|
|
|
171
171
|
extension = filename.rsplit('.', 1)[1].lower()
|
|
172
172
|
if extension not in ALLOWED_EXTENSIONS:
|
|
173
|
-
return render_template("settings.html", settings=settings_dict, hometext=hometext, error=
|
|
173
|
+
return render_template("settings.html", settings=settings_dict, hometext=hometext, error='unsupported_filetype')
|
|
174
174
|
|
|
175
175
|
try:
|
|
176
176
|
img = Image.open(file.stream)
|
|
177
177
|
img.verify()
|
|
178
178
|
except Exception:
|
|
179
|
-
return render_template("settings.html", settings=settings_dict, hometext=hometext, error="
|
|
179
|
+
return render_template("settings.html", settings=settings_dict, hometext=hometext, error="not_image")
|
|
180
180
|
|
|
181
181
|
file.stream.seek(0)
|
|
182
182
|
|
|
@@ -245,4 +245,19 @@ def download_translations():
|
|
|
245
245
|
response = make_response(json.dumps(dict(trans_dict), ensure_ascii=False))
|
|
246
246
|
response.headers["Content-Disposition"] = "attachment; filename=i18n.json"
|
|
247
247
|
response.headers["Content-Type"] = "application/json"
|
|
248
|
-
return response
|
|
248
|
+
return response
|
|
249
|
+
|
|
250
|
+
@admin_bp.route("/admin/remove_from_feed/<int:post_id>")
|
|
251
|
+
def remove_from_feed(post_id):
|
|
252
|
+
"""
|
|
253
|
+
Remove a post from the discover feed.
|
|
254
|
+
"""
|
|
255
|
+
if g.user is None or g.isadmin == 0 or g.mode == "single":
|
|
256
|
+
return redirect("/")
|
|
257
|
+
|
|
258
|
+
post = g.db.query(Post).filter_by(id=post_id).first()
|
|
259
|
+
if post:
|
|
260
|
+
post.feed = "0"
|
|
261
|
+
g.db.commit()
|
|
262
|
+
|
|
263
|
+
return redirect("/discover")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from flask import Blueprint, render_template, redirect, request, g, abort
|
|
1
|
+
from flask import Blueprint, render_template, redirect, request, g, abort, Response
|
|
2
2
|
from openwrite.utils.models import Blog, Post, User, View, Page
|
|
3
3
|
from openwrite.utils.helpers import sanitize_html, gen_link, safe_css, send_activity, is_html, get_themes
|
|
4
4
|
import requests
|
|
@@ -13,6 +13,8 @@ import markdown
|
|
|
13
13
|
from bs4 import BeautifulSoup
|
|
14
14
|
from user_agents import parse
|
|
15
15
|
import re
|
|
16
|
+
import csv
|
|
17
|
+
from io import StringIO
|
|
16
18
|
|
|
17
19
|
dashboard_bp = Blueprint("dashboard", __name__)
|
|
18
20
|
|
|
@@ -36,7 +38,7 @@ def create_blog():
|
|
|
36
38
|
if int(g.blog_limit) > 0:
|
|
37
39
|
count = g.db.query(Blog).filter_by(owner=g.user).count()
|
|
38
40
|
if count >= int(g.blog_limit):
|
|
39
|
-
return render_template("create.html", error="
|
|
41
|
+
return render_template("create.html", error="blog-limit-reached")
|
|
40
42
|
|
|
41
43
|
if request.method == "GET":
|
|
42
44
|
return render_template("create.html")
|
|
@@ -44,17 +46,17 @@ def create_blog():
|
|
|
44
46
|
form_name = request.form.get("name")
|
|
45
47
|
form_url = gen_link(request.form.get("url"))
|
|
46
48
|
if len(form_name) > 30:
|
|
47
|
-
return render_template("create.html", error="
|
|
49
|
+
return render_template("create.html", error="title-too-long")
|
|
48
50
|
if len(form_url) > 30:
|
|
49
|
-
return render_template("create.html", error="
|
|
51
|
+
return render_template("create.html", error="url-too-long")
|
|
50
52
|
blog = g.db.query(Blog).filter_by(name=form_url).first()
|
|
51
53
|
if blog:
|
|
52
|
-
return render_template("create.html", error="
|
|
54
|
+
return render_template("create.html", error="url-exists")
|
|
53
55
|
|
|
54
56
|
form_index = request.form.get("index") or "off"
|
|
55
57
|
form_access = request.form.get("access")
|
|
56
58
|
if form_access not in ("path", "domain"):
|
|
57
|
-
return render_template("create.html", error="
|
|
59
|
+
return render_template("create.html", error="wrong-access")
|
|
58
60
|
|
|
59
61
|
key = rsa.generate_private_key(
|
|
60
62
|
public_exponent=65537,
|
|
@@ -107,7 +109,7 @@ def create_blog():
|
|
|
107
109
|
|
|
108
110
|
return redirect("/dashboard")
|
|
109
111
|
except Exception:
|
|
110
|
-
return render_template("create.html", error=
|
|
112
|
+
return render_template("create.html", error="error")
|
|
111
113
|
|
|
112
114
|
@dashboard_bp.route("/dashboard/delete/<name>")
|
|
113
115
|
def delete_blog(name):
|
|
@@ -118,7 +120,7 @@ def delete_blog(name):
|
|
|
118
120
|
|
|
119
121
|
blog = g.db.query(Blog).filter_by(name=name).first()
|
|
120
122
|
if blog is None or blog.owner != g.user:
|
|
121
|
-
|
|
123
|
+
abort(403)
|
|
122
124
|
|
|
123
125
|
g.db.delete(blog)
|
|
124
126
|
g.db.commit()
|
|
@@ -131,7 +133,7 @@ def edit_blog(name):
|
|
|
131
133
|
|
|
132
134
|
blog = g.db.query(Blog).filter_by(name=name).first()
|
|
133
135
|
if blog is None or blog.owner != g.user:
|
|
134
|
-
|
|
136
|
+
abort(403)
|
|
135
137
|
|
|
136
138
|
posts = g.db.query(Post).filter_by(blog=blog.id).all()
|
|
137
139
|
for p in posts:
|
|
@@ -148,14 +150,14 @@ def edit_blog(name):
|
|
|
148
150
|
|
|
149
151
|
now = datetime.now(timezone.utc).replace(microsecond=0)
|
|
150
152
|
if len(request.form.get("title")) > 30:
|
|
151
|
-
return render_template("edit.html", blog=blog, posts=posts, themes=themes, pages=pages, error="
|
|
153
|
+
return render_template("edit.html", blog=blog, posts=posts, themes=themes, pages=pages, error="title-too-long")
|
|
152
154
|
blog.css = safe_css(request.form.get("css"))
|
|
153
155
|
blog.updated = now
|
|
154
156
|
blog.title = request.form.get("title")
|
|
155
157
|
blog.favicon = request.form.get("icon")[:10]
|
|
156
158
|
selected_theme = request.form.get("theme")
|
|
157
159
|
if selected_theme not in themes:
|
|
158
|
-
return render_template("edit.html", blog=blog, posts=posts, themes=themes, pages=pages, error="
|
|
160
|
+
return render_template("edit.html", blog=blog, posts=posts, themes=themes, pages=pages, error="wrong-theme")
|
|
159
161
|
blog.theme = selected_theme
|
|
160
162
|
g.db.commit()
|
|
161
163
|
|
|
@@ -168,7 +170,7 @@ def new_post(name):
|
|
|
168
170
|
|
|
169
171
|
blog = g.db.query(Blog).filter_by(name=name).first()
|
|
170
172
|
if blog is None or blog.owner != g.user:
|
|
171
|
-
|
|
173
|
+
abort(403)
|
|
172
174
|
|
|
173
175
|
if request.method == "GET":
|
|
174
176
|
return render_template("new_post.html", blog=blog)
|
|
@@ -176,11 +178,11 @@ def new_post(name):
|
|
|
176
178
|
u = g.db.query(User).filter_by(id=g.user).first()
|
|
177
179
|
title = request.form.get('title')
|
|
178
180
|
if len(title) > 120:
|
|
179
|
-
return render_template("new_post.html", blog=blog, error="
|
|
181
|
+
return render_template("new_post.html", blog=blog, error="title-too-long")
|
|
180
182
|
|
|
181
183
|
if len(title) < 1:
|
|
182
|
-
return render_template("new_post.html", blog=blog, error="
|
|
183
|
-
|
|
184
|
+
return render_template("new_post.html", blog=blog, error="title-empty")
|
|
185
|
+
|
|
184
186
|
link = gen_link(title)
|
|
185
187
|
if link == "rss":
|
|
186
188
|
link = "p_rss"
|
|
@@ -272,7 +274,7 @@ def blog_preview():
|
|
|
272
274
|
blog_name = request.referrer.split("/")[-1]
|
|
273
275
|
blog = g.db.query(Blog).filter_by(name=blog_name).first()
|
|
274
276
|
if not blog:
|
|
275
|
-
|
|
277
|
+
abort(404)
|
|
276
278
|
|
|
277
279
|
homepage = g.db.query(Page).filter(Page.blog == blog.id, Page.url == "").first()
|
|
278
280
|
data = {
|
|
@@ -293,7 +295,7 @@ def edit_post(blog, post):
|
|
|
293
295
|
|
|
294
296
|
blog_obj = g.db.query(Blog).filter_by(name=blog).first()
|
|
295
297
|
if blog_obj is None or blog_obj.owner != g.user:
|
|
296
|
-
|
|
298
|
+
abort(403)
|
|
297
299
|
|
|
298
300
|
e_post = g.db.query(Post).filter_by(link=post).first()
|
|
299
301
|
if request.method == "GET":
|
|
@@ -301,11 +303,11 @@ def edit_post(blog, post):
|
|
|
301
303
|
|
|
302
304
|
p = g.db.query(Post).filter_by(link=post, blog=blog_obj.id).first()
|
|
303
305
|
if not p:
|
|
304
|
-
|
|
306
|
+
abort(404)
|
|
305
307
|
|
|
306
308
|
title = request.form.get("title")
|
|
307
309
|
if len(title) > 120:
|
|
308
|
-
return render_template("new_post.html", blog=blog_obj, error="
|
|
310
|
+
return render_template("new_post.html", blog=blog_obj, error="title-too-long")
|
|
309
311
|
link = gen_link(title)
|
|
310
312
|
if link == "rss":
|
|
311
313
|
link = "p_rss"
|
|
@@ -334,7 +336,7 @@ def delete_post(blog, post):
|
|
|
334
336
|
|
|
335
337
|
blog_obj = g.db.query(Blog).filter_by(name=blog).first()
|
|
336
338
|
if blog_obj is None or blog_obj.owner != g.user:
|
|
337
|
-
|
|
339
|
+
abort(403)
|
|
338
340
|
|
|
339
341
|
p = g.db.query(Post).filter_by(link=post, blog=blog_obj.id).first()
|
|
340
342
|
if p:
|
|
@@ -358,14 +360,14 @@ def changepw():
|
|
|
358
360
|
user = g.db.query(User).filter_by(id=g.user).first()
|
|
359
361
|
if user and bcrypt.checkpw(old_pw.encode('utf-8'), user.password_hash.encode('utf-8')):
|
|
360
362
|
if new_pass != new_pass2:
|
|
361
|
-
return render_template("changepw.html", error=
|
|
363
|
+
return render_template("changepw.html", error='passwords_dont_match')
|
|
362
364
|
hashed = bcrypt.hashpw(new_pass.encode('utf-8'), bcrypt.gensalt())
|
|
363
365
|
user.password_hash = hashed
|
|
364
366
|
return redirect("/dashboard")
|
|
365
367
|
|
|
366
368
|
else:
|
|
367
|
-
return render_template("changepw.html", error=
|
|
368
|
-
|
|
369
|
+
return render_template("changepw.html", error='invalid_password')
|
|
370
|
+
|
|
369
371
|
|
|
370
372
|
@dashboard_bp.route("/dashboard/import", methods=['GET', 'POST'])
|
|
371
373
|
def migrate():
|
|
@@ -382,7 +384,7 @@ def migrate():
|
|
|
382
384
|
|
|
383
385
|
blog = g.db.query(Blog).filter_by(name=blog_d).first()
|
|
384
386
|
if blog.owner != g.user:
|
|
385
|
-
|
|
387
|
+
abort(403)
|
|
386
388
|
|
|
387
389
|
for post in posts:
|
|
388
390
|
title = post['title']
|
|
@@ -409,7 +411,7 @@ def stats(blog):
|
|
|
409
411
|
|
|
410
412
|
blog = g.db.query(Blog).filter_by(name=blog).first()
|
|
411
413
|
if blog.owner != g.user:
|
|
412
|
-
|
|
414
|
+
abort(403)
|
|
413
415
|
|
|
414
416
|
posts = g.db.query(Post).filter_by(blog=blog.id).all()
|
|
415
417
|
|
|
@@ -464,9 +466,9 @@ def new_page(blog):
|
|
|
464
466
|
content_html = request.form.get("content")
|
|
465
467
|
show = request.form.get("show")
|
|
466
468
|
if len(name) > 120:
|
|
467
|
-
return render_template("new_page.html", blog=blog, error="
|
|
469
|
+
return render_template("new_page.html", blog=blog, error="name-too-long")
|
|
468
470
|
if not re.match(r"^\/[a-zA-Z0-9\-\_]+$", url):
|
|
469
|
-
return render_template("new_page.html", blog=blog, error="
|
|
471
|
+
return render_template("new_page.html", blog=blog, error="invalid-url")
|
|
470
472
|
|
|
471
473
|
url = url[1:]
|
|
472
474
|
if url == "rss":
|
|
@@ -511,10 +513,10 @@ def edit_page(page):
|
|
|
511
513
|
show = request.form.get("show")
|
|
512
514
|
url = request.form.get("url")
|
|
513
515
|
if len(name) > 120:
|
|
514
|
-
return render_template("new_page.html", blog=blog, page=page, home=home, error="
|
|
516
|
+
return render_template("new_page.html", blog=blog, page=page, home=home, error="name-too-long")
|
|
515
517
|
if home == False:
|
|
516
518
|
if not re.match(r"^\/[a-zA-Z0-9\-\_]+$", url):
|
|
517
|
-
return render_template("new_page.html", blog=blog, error="
|
|
519
|
+
return render_template("new_page.html", blog=blog, error="invalid-url")
|
|
518
520
|
|
|
519
521
|
url = url[1:]
|
|
520
522
|
if url == "rss":
|
|
@@ -569,3 +571,43 @@ def page_delete(page):
|
|
|
569
571
|
g.db.commit()
|
|
570
572
|
|
|
571
573
|
return redirect(f"/dashboard/edit/{blog.name}")
|
|
574
|
+
|
|
575
|
+
@dashboard_bp.route("/dashboard/export/<blog>")
|
|
576
|
+
def export_posts(blog):
|
|
577
|
+
if g.user is None:
|
|
578
|
+
return redirect("/login")
|
|
579
|
+
|
|
580
|
+
blog_obj = g.db.query(Blog).filter_by(name=blog).first()
|
|
581
|
+
if blog_obj is None or blog_obj.owner != g.user:
|
|
582
|
+
return redirect("/dashboard")
|
|
583
|
+
|
|
584
|
+
posts = g.db.query(Post).filter_by(blog=blog_obj.id).all()
|
|
585
|
+
|
|
586
|
+
|
|
587
|
+
output = StringIO()
|
|
588
|
+
writer = csv.writer(output)
|
|
589
|
+
|
|
590
|
+
writer.writerow(['Title', 'Content Raw', 'Content HTML', 'Author', 'Link', 'Date', 'Updated', 'Feed', 'Is Draft'])
|
|
591
|
+
|
|
592
|
+
for post in posts:
|
|
593
|
+
writer.writerow([
|
|
594
|
+
post.title,
|
|
595
|
+
post.content_raw,
|
|
596
|
+
post.content_html,
|
|
597
|
+
post.author,
|
|
598
|
+
post.link,
|
|
599
|
+
post.date.isoformat() if post.date else '',
|
|
600
|
+
post.updated.isoformat() if post.updated else '',
|
|
601
|
+
post.feed,
|
|
602
|
+
post.isdraft
|
|
603
|
+
])
|
|
604
|
+
|
|
605
|
+
output.seek(0)
|
|
606
|
+
|
|
607
|
+
return Response(
|
|
608
|
+
output.getvalue(),
|
|
609
|
+
mimetype='text/csv',
|
|
610
|
+
headers={
|
|
611
|
+
'Content-Disposition': f'attachment; filename={blog}_posts.csv'
|
|
612
|
+
}
|
|
613
|
+
)
|
|
@@ -96,7 +96,7 @@ def show_instance():
|
|
|
96
96
|
blog_count = g.db.query(Blog).count()
|
|
97
97
|
user_count = g.db.query(User).count()
|
|
98
98
|
return {
|
|
99
|
-
"version":
|
|
99
|
+
"version": "0.13.1",
|
|
100
100
|
"blogs": blog_count,
|
|
101
101
|
"users": user_count,
|
|
102
102
|
"uptime": int(time.time() - int(start_time)),
|
|
@@ -389,6 +389,10 @@ i.post-date {
|
|
|
389
389
|
font-size: 15px;
|
|
390
390
|
}
|
|
391
391
|
|
|
392
|
+
i.post-date.updated {
|
|
393
|
+
opacity: 0.5;
|
|
394
|
+
}
|
|
395
|
+
|
|
392
396
|
article.post-content {
|
|
393
397
|
display: flex;
|
|
394
398
|
flex-direction: column;
|
|
@@ -535,6 +539,8 @@ div.postlist_item {
|
|
|
535
539
|
justify-content: left;
|
|
536
540
|
} .to-center {
|
|
537
541
|
justify-content: center;
|
|
542
|
+
} .space-between {
|
|
543
|
+
justify-content: space-between;
|
|
538
544
|
}
|
|
539
545
|
|
|
540
546
|
.post-content#posts {
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
<h1 class="centered">create a new blog</h1>
|
|
3
3
|
<article class="main-content">
|
|
4
4
|
{% if error %}
|
|
5
|
-
<div class="error">{{ error }}</div>
|
|
5
|
+
<div class="error">{{ _(error) }}</div>
|
|
6
|
+
{% endif %}
|
|
7
|
+
{% if request.args.get('error') %}
|
|
8
|
+
<div class="error">{{ _(request.args.get('error')) }}</div>
|
|
9
|
+
{% endif %}
|
|
10
|
+
{% if message %}
|
|
11
|
+
<div class="message">{{ _(message) }}</div>
|
|
6
12
|
{% endif %}
|
|
7
13
|
|
|
8
14
|
<form method="post" action="/dashboard/create">
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
{% include 'header.html' %}
|
|
2
2
|
{% if error %}
|
|
3
|
-
<div class="error">{{ error }}</div>
|
|
3
|
+
<div class="error">{{ _(error) }}</div>
|
|
4
|
+
{% endif %}
|
|
5
|
+
{% if request.args.get('error') %}
|
|
6
|
+
<div class="error">{{ _(request.args.get('error')) }}</div>
|
|
4
7
|
{% endif %}
|
|
5
8
|
{% if message %}
|
|
6
|
-
<div class="message">{{ message }}</div>
|
|
9
|
+
<div class="message">{{ _(message) }}</div>
|
|
7
10
|
{% endif %}
|
|
8
11
|
<h1 class="centered">{% if g.mode == "single" %}{{ _('your_blog') }}{% else %}{{ _('your_blogs') }}{% endif %}</h1>
|
|
9
12
|
{% if g.mode == "multi" %}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<div style="display: flex; flex-direction: column; gap: 1rem">
|
|
5
5
|
{% for p in posts %}
|
|
6
6
|
<div class="discover_post">
|
|
7
|
-
<i class="datetime">{{ p.date }}</i>{{ p.blogname }}: <a class="action" href="{{ p.url }}" target="_blank">{{ p.title }}</a> {{ p.likes }} ♡
|
|
7
|
+
<i class="datetime">{{ p.date }}</i>{{ p.blogname }}: <a class="action" href="{{ p.url }}" target="_blank">{{ p.title }}</a> {{ p.likes }} ♡ {% if g.isadmin == 1 %}<a href="/admin/remove_from_feed/{{ p.id }}" class="action" onclick="return confirm('Remove post {{ p.title }} from discover?')">Remove from discover</a>{% endif %}
|
|
8
8
|
</div>
|
|
9
9
|
{% endfor %}
|
|
10
10
|
</div>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{% include 'header.html' %}
|
|
2
2
|
{% if error %}
|
|
3
|
-
<div class="error">{{ error }}</div>
|
|
3
|
+
<div class="error">{{ _(error) }}</div>
|
|
4
|
+
{% endif %}
|
|
5
|
+
{% if request.args.get('error') %}
|
|
6
|
+
<div class="error">{{ _(request.args.get('error')) }}</div>
|
|
7
|
+
{% endif %}
|
|
8
|
+
{% if message %}
|
|
9
|
+
<div class="message">{{ _(message) }}</div>
|
|
4
10
|
{% endif %}
|
|
5
11
|
<div><a href="/dashboard" class="action">Dashboard</a> > {{ blog.title }}</div>
|
|
6
12
|
<h1 class="centered">
|
|
@@ -55,7 +61,7 @@ blog: {{ blog.name }}
|
|
|
55
61
|
<tbody>
|
|
56
62
|
{% for page in pages %}
|
|
57
63
|
<tr>
|
|
58
|
-
<td style="text-align: center; padding: 0.5rem;">/{{ page.url }}</td><td style="text-align: center">{{ page.name }}</td><td style="text-align: center;">{% if page.show == "1" %}{{ _('yes') }}{% else %}{{ _('no') }}{% endif %}</td><td style="display: flex; gap: 1rem; padding: 0.5rem; justify-content: space-between;">
|
|
64
|
+
<td style="text-align: center; padding: 0.5rem;">/{{ page.url }}</td><td style="text-align: center"><a href="{% if blog.access == "path" %}https://{{ g.main_domain }}/b/{{ blog.name }}/{% else %}https://{{ blog.name }}.{{ g.main_domain }}/{% endif %}{{ page.url }}" class="action" target="_blank">{{ page.name }}</a></td><td style="text-align: center;">{% if page.show == "1" %}{{ _('yes') }}{% else %}{{ _('no') }}{% endif %}</td><td style="display: flex; gap: 1rem; padding: 0.5rem; justify-content: space-between;">
|
|
59
65
|
<a class="action" href="/dashboard/page/{{ page.id }}/edit">{{ _('edit') }}</a>
|
|
60
66
|
{% if page.url != "" %}<a class="action" href="/dashboard/page/{{ page.id }}/delete" onclick="return confirm('{{ _('are-you-sure-page') }} {{ page.name }}?\n{{ _('this_action_cannot_be_reverted') }}.')">{{ _('delete') }}</a>{% endif %}
|
|
61
67
|
</td>
|
|
@@ -80,6 +86,7 @@ blog: {{ blog.name }}
|
|
|
80
86
|
</table>
|
|
81
87
|
<div class="buttons-list">
|
|
82
88
|
<a href="/dashboard/post/{{ blog.name }}" class="btn purple">{{ _('new_post') }}</a>
|
|
89
|
+
<a href="/dashboard/export/{{ blog.name }}" class="btn purple">{{ _('export-posts') }}</a>
|
|
83
90
|
<a href="/dashboard/delete/{{ blog.name }}" class="btn red" onclick="return confirm('{{ _('are_you_sure_blog') }} {{ blog.name }}?\n{{ _('this_action_cannot_be_reverted') }}.')">{{ _('delete_blog') }}</a>
|
|
84
91
|
</div>
|
|
85
92
|
</div>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<a href="https://hub.docker.com/r/openwrite/openwrite">Dockerhub</a>
|
|
5
5
|
<a href="https://ko-fi.com/openwrite">{{ _('buy_coffee') }}</a>
|
|
6
6
|
<a href="https://main.openwrite.io/contact">{{ _('contact') }}</a>
|
|
7
|
+
<a href="https://main.openwrite.io/terms-of-service">{{ _('terms-of-service') }}</a>
|
|
7
8
|
<p>{{ _('language') }}: </p>
|
|
8
9
|
<select name="lang" onchange="location = '/set-lang/' + this.value">
|
|
9
10
|
{% for code in available_languages.keys() %}
|
|
@@ -44,7 +44,6 @@
|
|
|
44
44
|
<a href="/dashboard">Dashboard</a>
|
|
45
45
|
{% endif %}
|
|
46
46
|
<a href="/discover">{{ _('discover') }}</a>
|
|
47
|
-
<a href="/instances">{{ _('instances') }}</a>
|
|
48
47
|
<a href="https://main.openwrite.io/hosting">{{ _('hosting') }}</a>
|
|
49
48
|
{% if g.user %}
|
|
50
49
|
<a href="/logout">{{ _('logout') }}</a>
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{% include 'header.html' %}
|
|
2
2
|
{% if error %}
|
|
3
|
-
<div class="error">{{ error }}</div>
|
|
3
|
+
<div class="error">{{ _(error) }}</div>
|
|
4
|
+
{% endif %}
|
|
5
|
+
{% if request.args.get('error') %}
|
|
6
|
+
<div class="error">{{ _(request.args.get('error')) }}</div>
|
|
7
|
+
{% endif %}
|
|
8
|
+
{% if message %}
|
|
9
|
+
<div class="message">{{ _(message) }}</div>
|
|
4
10
|
{% endif %}
|
|
5
11
|
<div><a href="/dashboard" class="action">Dashboard</a> > <a href="/dashboard/edit/{{ blog.name }}" class="action">{{ blog.title }}</a> > {% if page %}{{ page.name }}{% else %}{{ _('new-page') }}{% endif %}</div>
|
|
6
12
|
<div class="container-row-fluid">
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{% include 'header.html' %}
|
|
2
2
|
{% if error %}
|
|
3
|
-
<div class="error">{{ error }}</div>
|
|
3
|
+
<div class="error">{{ _(error) }}</div>
|
|
4
|
+
{% endif %}
|
|
5
|
+
{% if request.args.get('error') %}
|
|
6
|
+
<div class="error">{{ _(request.args.get('error')) }}</div>
|
|
7
|
+
{% endif %}
|
|
8
|
+
{% if message %}
|
|
9
|
+
<div class="message">{{ _(message) }}</div>
|
|
4
10
|
{% endif %}
|
|
5
11
|
<div><a href="/dashboard" class="action">Dashboard</a> > <a href="/dashboard/edit/{{ blog.name }}" class="action">{{ blog.title }}</a> > {% if post %}{{ post.title }}{% else %}{{ _('new_post') }}{% endif %}</div>
|
|
6
12
|
<div class="container-row-fluid">
|
|
@@ -11,15 +17,16 @@
|
|
|
11
17
|
<form method="post" action="{% if post %}/dashboard/edit/{{ blog.name }}/{{ post.link }}{% else %}/dashboard/post/{{ blog.name }}{% endif %}">
|
|
12
18
|
<input type="text" name="title" placeholder="{{ _('title') }}" style="max-width: 100%; height: 50px; font-size: 25px; margin-bottom: 1rem;" value="{% if post %}{{ post.title }}{% endif %}">
|
|
13
19
|
<div style="display: flex; flex-direction: row; gap: 5px; align-items: center;">
|
|
14
|
-
<a href="#" class="small btn empty" data-action="h1">H1</a>
|
|
15
|
-
<a href="#" class="small btn empty" data-action="h2">H2</a>
|
|
16
|
-
<a href="#" class="small btn empty" data-action="h3">H3</a>
|
|
17
|
-
<a href="#" class="small btn empty" data-action="bold"><b>B</b></a>
|
|
18
|
-
<a href="#" class="small btn empty" data-action="italic"><i>I</i></a>
|
|
19
|
-
<a href="#" class="small btn empty" data-action="underline"><u>U</u></a>
|
|
20
|
-
<a href="#" class="small btn empty" data-action="strikethrough"><del>C</del></a>
|
|
21
|
-
<a href="#" class="small btn empty" data-action="quote">Q</a>
|
|
22
|
-
<a href="
|
|
20
|
+
<a href="#" class="small btn empty" data-action="h1" title="Heading 1">H1</a>
|
|
21
|
+
<a href="#" class="small btn empty" data-action="h2" title="Heading 2">H2</a>
|
|
22
|
+
<a href="#" class="small btn empty" data-action="h3" title="Heading 3">H3</a>
|
|
23
|
+
<a href="#" class="small btn empty" data-action="bold" title="Bold text"><b>B</b></a>
|
|
24
|
+
<a href="#" class="small btn empty" data-action="italic" title="Italic text"><i>I</i></a>
|
|
25
|
+
<a href="#" class="small btn empty" data-action="underline" title="Underlined text"><u>U</u></a>
|
|
26
|
+
<a href="#" class="small btn empty" data-action="strikethrough" title="Strikethrough text"><del>C</del></a>
|
|
27
|
+
<a href="#" class="small btn empty" data-action="quote" title="Quote/Blockquote">Q</a>
|
|
28
|
+
<a href="#" class="small btn empty" data-action="link" title="Insert link">🔗</a>
|
|
29
|
+
<a href="https://main.openwrite.io/markdown-syntax" style="text-decoration: none; color: #eeeeee; margin-left: auto" target="_blank" title="View Markdown syntax guide">Markdown syntax</a>
|
|
23
30
|
</div>
|
|
24
31
|
<textarea autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" name="content" class="post_content" placeholder="{{ _('content') }}">{% if post %}{{ post.content_raw }}{% endif %}</textarea>
|
|
25
32
|
<div style="display: flex; justify-content: space-between">
|
|
@@ -40,6 +47,7 @@
|
|
|
40
47
|
<input type="submit" value="{{ _('save-as-draft') }}" name="draft" id="draft" class="btn empty">
|
|
41
48
|
{% endif %}
|
|
42
49
|
<input type="submit" value="{% if post %}{% if post.isdraft == "0" %}{{ _('save') }}{% else %}{{ _('save-draft') }}{% endif %}{% else %}{{ _('create') }}{% endif %}" class="btn purple" id="{% if post %}{% if post.isdraft == "0" %}submit{% else %}draft{% endif %}{% else %}submit{% endif %}">
|
|
50
|
+
{% if post %}{% if post.isdraft == "0" %}<input type="hidden" id="draft">{% endif %}{% endif %}
|
|
43
51
|
{% if post %}
|
|
44
52
|
{% if post.isdraft == "1" %}
|
|
45
53
|
<input type="submit" value="{{ _('publish') }}" class="btn purple" id="submit">
|
|
@@ -52,10 +60,10 @@
|
|
|
52
60
|
var converter = new showdown.Converter();
|
|
53
61
|
converter.setOption('emoji', true);
|
|
54
62
|
converter.setOption('noHeaderId', true);
|
|
55
|
-
converter.setOption('openLinksInNewWindow', true);
|
|
56
63
|
converter.setOption('tables', true);
|
|
57
64
|
converter.setOption('tasklists', true);
|
|
58
65
|
converter.setOption('strikethrough', true);
|
|
66
|
+
converter.setOption('simplifiedAutoLink', true);
|
|
59
67
|
|
|
60
68
|
document.getElementById('preview').addEventListener('click', function(e) {
|
|
61
69
|
e.preventDefault();
|
|
@@ -219,34 +227,61 @@ document.querySelectorAll('[data-action]').forEach(btn => {
|
|
|
219
227
|
const selected = editor.value.slice(start, end);
|
|
220
228
|
|
|
221
229
|
let modified = selected;
|
|
230
|
+
let cursorOffset = 0;
|
|
231
|
+
|
|
222
232
|
switch (action) {
|
|
223
233
|
case "bold":
|
|
224
234
|
modified = `**${selected}**`;
|
|
235
|
+
cursorOffset = selected ? 0 : 2;
|
|
225
236
|
break;
|
|
226
237
|
case "italic":
|
|
227
238
|
modified = `*${selected}*`;
|
|
239
|
+
cursorOffset = selected ? 0 : 1;
|
|
228
240
|
break;
|
|
229
241
|
case "underline":
|
|
230
242
|
modified = `<u>${selected}</u>`;
|
|
243
|
+
cursorOffset = selected ? 0 : 3;
|
|
231
244
|
break;
|
|
232
245
|
case "strikethrough":
|
|
233
246
|
modified = `~~${selected}~~`;
|
|
247
|
+
cursorOffset = selected ? 0 : 2;
|
|
234
248
|
break;
|
|
235
249
|
case "quote":
|
|
236
250
|
modified = selected.split("\n").map(line => `> ${line}`).join("\n");
|
|
251
|
+
cursorOffset = selected ? 0 : 2;
|
|
237
252
|
break;
|
|
238
253
|
case "h1":
|
|
239
254
|
modified = `# ${selected}`;
|
|
255
|
+
cursorOffset = selected ? 0 : 2;
|
|
240
256
|
break;
|
|
241
257
|
case "h2":
|
|
242
258
|
modified = `## ${selected}`;
|
|
259
|
+
cursorOffset = selected ? 0 : 3;
|
|
243
260
|
break;
|
|
244
261
|
case "h3":
|
|
245
262
|
modified = `### ${selected}`;
|
|
263
|
+
cursorOffset = selected ? 0 : 4;
|
|
264
|
+
break;
|
|
265
|
+
case "link":
|
|
266
|
+
const url = prompt("Enter the URL:");
|
|
267
|
+
if (url) {
|
|
268
|
+
if (selected) {
|
|
269
|
+
modified = `[${selected}](${url})`;
|
|
270
|
+
cursorOffset = 0;
|
|
271
|
+
} else {
|
|
272
|
+
modified = `[link description](${url})`;
|
|
273
|
+
cursorOffset = 1;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
246
276
|
break;
|
|
247
277
|
}
|
|
248
278
|
|
|
249
279
|
editor.setRangeText(modified, start, end, "end");
|
|
280
|
+
|
|
281
|
+
if (!selected && cursorOffset > 0) {
|
|
282
|
+
editor.selectionStart = editor.selectionEnd = start + cursorOffset;
|
|
283
|
+
}
|
|
284
|
+
|
|
250
285
|
editor.focus();
|
|
251
286
|
});
|
|
252
287
|
});
|
|
@@ -4,9 +4,13 @@
|
|
|
4
4
|
<article class="post-content">
|
|
5
5
|
{{ post.content_html | safe }}
|
|
6
6
|
</article>
|
|
7
|
-
<div class="flex row small-gap
|
|
8
|
-
<
|
|
9
|
-
|
|
7
|
+
<div class="flex row small-gap space-between">
|
|
8
|
+
<i class="post-date updated">
|
|
9
|
+
{% if post.updated not in (None, "", "null", "NULL") %}
|
|
10
|
+
{{ _('last-updated') }}: <span class="datetime">{{ post.updated }}</span>
|
|
11
|
+
{% endif %}
|
|
12
|
+
</i>
|
|
13
|
+
<span>{{ post.likes }} <svg id="like" width="20px" height="20px" viewBox="0 0 36 36" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--twemoji" preserveAspectRatio="xMidYMid meet"><path style="{% if post.liked > 0 %}fill: #DD2E44;{% else %}fill: none{% endif %}" stroke="#DD2E44" stroke-width="2" d="M35.885 11.833c0-5.45-4.418-9.868-9.867-9.868c-3.308 0-6.227 1.633-8.018 4.129c-1.791-2.496-4.71-4.129-8.017-4.129c-5.45 0-9.868 4.417-9.868 9.868c0 .772.098 1.52.266 2.241C1.751 22.587 11.216 31.568 18 34.034c6.783-2.466 16.249-11.447 17.617-19.959c.17-.721.268-1.469.268-2.242z"></path></svg></span>
|
|
10
14
|
</div>
|
|
11
15
|
|
|
12
16
|
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{% include 'header.html' %}
|
|
2
2
|
{% if error %}
|
|
3
|
-
<div class="error">{{ error }}</div>
|
|
3
|
+
<div class="error">{{ _(error) }}</div>
|
|
4
|
+
{% endif %}
|
|
5
|
+
{% if request.args.get('error') %}
|
|
6
|
+
<div class="error">{{ _(request.args.get('error')) }}</div>
|
|
7
|
+
{% endif %}
|
|
8
|
+
{% if message %}
|
|
9
|
+
<div class="message">{{ _(message) }}</div>
|
|
4
10
|
{% endif %}
|
|
5
11
|
<h1 class="centered">{{ _('settings') }}</h1>
|
|
6
12
|
<form method="post" action="/admin/settings" enctype="multipart/form-data">
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"pl": {"lang_name": "🇵🇱 Polski", "instances": "Instancje", "hosting": "Hosting", "register": "Rejestracja", "login": "Zaloguj się", "register_here": "Zarejestruj się tutaj", "self_host": "Samodzielny hosting", "username": "Nazwa użytkownika", "password": "Hasło", "email": "E-mail", "not_required": "nie wymagany, ale zalecany do 2FA i odzyskiwania konta", "register_on_this_instance": "zarejestruj się na tej instancji", "or": "lub", "language": "Język", "buy_coffee": "Kup mi kawkę", "user_exists": "Użytkownik o takiej nazwie istnieje. Wybierz inną.", "error": "Wystąpił nieznany błąd. Spróbuj ponownie później.", "registered": "Zarejestrowano pomyslnie! Możesz się zalogować.", "invalid_credentials": "Login lub hasło nieprawidłowe!", "logout": "Wyloguj", "your_blogs": "twoje blogi", "title": "Tytuł", "edit": "Edytuj", "new_post": "Nowy wpis", "delete_blog": "Usuń bloga", "create_new_blog": "Utwórz nowego bloga", "description": "Opis", "save": "Zapisz", "upload_image": "Prześlij obraz", "date": "Data", "actions": "Akcje", "choose_blog_title": "Wybierz tytuł bloga", "choose_blog_url": "Wybierz adres URL bloga", "access_blog_how": "Jaki chcesz link do bloga", "domain_name": "Nazwa domeny", "path": "Ścieżka", "create": "Utwórz", "index_blog": "Indeksuj bloga w wyszukiwarkach", "content": "Treść", "preview": "Podgląd", "post": "Opublikuj", "include_author": "Dołącz informacje o autorze (nazwa użytkownika) we wpisie", "new_post_on": "nowy wpis na blogu", "posts": "Wpisy", "are_you_sure_blog": "Czy na pewno chcesz usunąć bloga", "this_action_cannot_be_reverted": "Tej operacji nie można cofnąć", "are_you_sure_user": "Czy na pewno chcesz usunąć użytkownika", "are_you_sure_post": "Czy na pewno chcesz usunąć wpis", "delete": "Usuń", "editing_post": "edycja wpisu", "views": "Wyświetlenia", "settings": "Ustawienia", "mfa": "Weryfikacja dwuetapowa", "verify": "Zweryfikuj", "delete_account": "Usuń konto", "instances_text": "Tutaj znajdziesz wszystkie znane nam instancje openwrite.io wraz z ich właściwościami", "name": "Nazwa", "blogs_running": "Uruchomione blogi", "users": "Użytkownicy", "media_upload": "Przesyłanie mediów?", "password2": "Powtórz hasło", "passwords_dont_match": "Hasła się nie zgadzają!", "include_in_feed": "Wyświetlać wpis w sekcji \"Odkrywaj\"", "discover": "Odkrywaj", "discover_text": "Tutaj znajdziesz wszystkie najnowsze posty z tej instancji openwrite.", "yes": "Tak", "no": "Nie", "change_password": "Zmień hasło", "migrate_posts": "Importuj posty", "wrong_username": "Nieprawidłowa nazwa!", "invalid_captcha": "Captcha nieprawidłowa!", "uploads_disabled": "Przesyłanie plików wyłączone", "invalid_filename": "Nieprawidłowa nazwa pliku", "unsupported_filetype": "Nieprawidłowy typ pliku", "no_file": "Brak pliku", "not_image": "Przesyłany plik nie jest obrazem", "upload_failed": "Niepowodzenie w przesyłaniu", "current_password": "Aktualne hasło", "new_password": "Nowe hasło", "choose_vendor": "Wybierz dostawcę obecnego bloga", "select_posts": "Wybierz wpisy do migracji", "migrate_info": "Dane są używane wyłącznie do migracji wpisów i nie są zapisywane.", "invalid_password": "Nieprawidłowe hasło!", "choose_format": "Wybierz format danych", "title_column": "Nazwa kolumny z tytułem", "content_column": "Nazwa kolumny z treścią", "date_column": "Nazwa kolumny z datą", "content_format": "Format treści wpisu", "step": "Krok", "upload_file": "Wybierz plik", "send": "Wyślij", "import_info": "W tym miejscu możesz zaimportować wpisy z innej platformy. Przyjmowane są pliki z Wordpress(XML) oraz CSV. <a class=\"link\" href=\"https://main.openwrite.io/posts-migration\">Tutaj</a> dowiesz się jak przygotować dane do importu.", "import_success1": "Import wpisów zakończony sukcesem! Przejdź do", "import_success2": "dashboardu bloga", "import_success3": "żeby zobaczyć swoje posty.", "import_failed": "Wystąpił błąd! Sprawdź przesyłane dane.", "select_blog_to_import": "Wybierz blog, do którego trafią wpisy", "remove_admin": "Zabierz prawa administratora", "add_admin": "Mianuj administratorem", "are_you_sure_make_admin": "Czy na pewno chcesz nadać prawa administratora dla", "are_you_sure_remove_admin": "Czy na pewno zabrać uprawnienia administratora ", "add_user": "Dodaj użytkownika", "select_theme": "Wybierz motyw", "default": "Domyślny", "see_themes": "Zobacz motywy", "custom_css": "Własny CSS", "css_unsafe_info": "Niebezpieczne wartości jak url(), @keyframes, @import, expression, javascript i animation zostaną usunięte.", "your_blog": "twój blog", "statistics": "Statystyki", "contact": "Kontakt", "pages": "Strony", "new-page": "Nowa strona", "show-in-header": "Pokaż w nagłówku bloga", "are-you-sure-page": "Czy na pewno chcesz usunąć stronę", "new-page-on": "Nowa strona na blogu", "hint-posts": "Wpisz {posts} gdziekolwiek chcesz żeby pokazała się twoja lista wpisów!", "and": "i", "icon": "Ikona", "save-as-draft": "Zapisz jako szkic", "draft": "Szkic", "save-draft": "Zapisz szkic", "publish": "Opublikuj", "export-posts": "Eksportuj wpisy", "blog-limit-reached": "Osiągnięto limit blogów!", "title-too-long": "Tytuł za długi!", "url-too-long": "URL za długi! Max 30 znaków.", "url-exists": "Taki URL już istnieje, wybierz inny.", "wrong-access": "Niepoprawny link!", "wrong-theme": "Niepoprawny motyw!", "title-empty": "Tytuł nie może być pusty!", "name-too-long": "Nazwa za długa!", "invalid-url": "Nieprawidłowy URL!", "terms-of-use": "Regulamin", "terms-of-service": "Regulamin", "last-updated": "Ostatnio edytowane"}, "en": {"lang_name": "🇬🇧 English", "instances": "Instances", "hosting": "Hosting", "register": "Register", "login": "Login", "register_here": "Register Here", "self_host": "Self Host", "username": "Username", "password": "Password", "email": "Email", "not_required": "not required by recommended for 2FA and recovery", "register_on_this_instance": "register on this instance", "or": "or", "language": "Language", "buy_coffee": "Buy me a coffee", "user_exists": "User already exists. Choose different name.", "error": "Unknown error occured. Try again later.", "registered": "Register successful! You can login now.", "invalid_credentials": "Invalid credentials!", "logout": "Log out", "your_blogs": "your blogs", "title": "Title", "edit": "Edit", "new_post": "New post", "delete_blog": "Delete blog", "create_new_blog": "Create new blog", "description": "Description", "save": "Save", "upload_image": "Upload image", "date": "Date", "actions": "Actions", "choose_blog_title": "Choose blog title", "choose_blog_url": "Choose blog URL", "access_blog_how": "How would you like to access your blog", "domain_name": "Domain name", "path": "Path", "create": "Create", "index_blog": "Index your blog in search engines", "content": "content", "preview": "Preview", "post": "Post", "include_author": "Include author information(username) in post", "new_post_on": "new post on blog", "posts": "Posts", "are_you_sure_blog": "Are you sure to delete blog", "this_action_cannot_be_reverted": "This action cannot be reverted", "are_you_sure_user": "Are you sure to delete user", "are_you_sure_post": "Are you sure to delete post", "delete": "Delete", "editing_post": "editing post", "views": "Views", "settings": "Settings", "mfa": "Multi-factor authentication", "verify": "Verify", "delete_account": "Delete account", "instances_text": "Here you will find all known openwrite instances along with their properties", "name": "Name", "blogs_running": "Blogs running", "users": "Users", "media_upload": "Upload media?", "password2": "Retype password", "passwords_dont_match": "Passwords don't match!", "include_in_feed": "Include post in \"Discover\" section", "discover": "Discover", "discover_text": "Here you can find most recent posts from this instance.", "yes": "Yes", "no": "No", "change_password": "Change Password", "migrate_posts": "Import posts", "wrong_username": "Wrong username!", "invalid_captcha": "Invalid captcha!", "uploads_disabled": "Uploads disabled", "invalid_filename": "Invalid filename", "unsupported_filetype": "Unsupported file type", "no_file": "No file", "not_image": "Uploaded file is not a valid image", "upload_failed": "Upload failed", "current_password": "Current password", "new_password": "New password", "choose_vendor": "Choose blog vendor", "select_posts": "Select posts to migrate", "migrate_info": "Data is used only for migration and not saved in any place.", "invalid_password": "Invalid password!", "choose_format": "Choose data format", "title_column": "Title column name", "content_column": "Content column name", "date_column": "Date column name", "content_format": "Content format", "step": "Step", "upload_file": "Upload file", "send": "Send", "import_info": "In here you can import posts from another platform. Files can be exported from Wordpress(XML) or in general CSV format. <a class=\"link\" href=\"https://main.openwrite.io/posts-migration\">Here</a> you can find information about how to prepare data to import.", "import_success1": "Import successful! Go to", "import_success2": "blog dashboard", "import_success3": "to see your posts.", "import_failed": "Error occured! Check your data format.", "select_blog_to_import": "Select blog to import data to", "remove_admin": "Remove admin", "add_admin": "Make admin", "are_you_sure_make_admin": "Are you sure to add admin rights to", "are_you_sure_remove_admin": "Are you sure to remove admin rights from", "add_user": "Add user", "select_theme": "Select theme", "default": "Default", "see_themes": "See themes", "custom_css": "Custom CSS", "css_unsafe_info": "Unsafe values like url(), @keyframes, @import, expression, javascript and animation will be removed.", "your_blog": "your blog", "statistics": "Statistics", "contact": "Contact", "pages": "Pages", "new-page": "New page", "show-in-header": "Show in blog header", "are-you-sure-page": "Are you sure to delete page", "new-page-on": "New page on blog", "hint-posts": "Add {posts} wherever you want to print your post list!", "and": "and", "icon": "Icon", "save-as-draft": "Save as draft", "draft": "Draft", "save-draft": "Save draft", "publish": "Publish", "export-posts": "Export posts", "blog-limit-reached": "Blog limit reached!", "title-too-long": "Title too long!", "url-too-long": "URL too long! Max 30 characters.", "url-exists": "This URL already exists. Choose different one.", "wrong-access": "Wrong access!", "wrong-theme": "Wrong theme!", "title-empty": "Title cannot be empty!", "name-too-long": "Name too long!", "invalid-url": "Invalid URL!", "terms-of-use": "Terms of Service", "terms-of-service": "Terms of Service", "last-updated": "Last updated"}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"pl": {"lang_name": "🇵🇱 Polski", "instances": "Instancje", "hosting": "Hosting", "register": "Rejestracja", "login": "Zaloguj się", "register_here": "Zarejestruj się tutaj", "self_host": "Samodzielny hosting", "username": "Nazwa użytkownika", "password": "Hasło", "email": "E-mail", "not_required": "nie wymagany, ale zalecany do 2FA i odzyskiwania konta", "register_on_this_instance": "zarejestruj się na tej instancji", "or": "lub", "language": "Język", "buy_coffee": "Kup mi kawkę", "user_exists": "Użytkownik o takiej nazwie istnieje. Wybierz inną.", "error": "Wystąpił nieznany błąd. Spróbuj ponownie później.", "registered": "Zarejestrowano pomyslnie! Możesz się zalogować.", "invalid_credentials": "Login lub hasło nieprawidłowe!", "logout": "Wyloguj", "your_blogs": "twoje blogi", "title": "Tytuł", "edit": "Edytuj", "new_post": "Nowy wpis", "delete_blog": "Usuń bloga", "create_new_blog": "Utwórz nowego bloga", "description": "Opis", "save": "Zapisz", "upload_image": "Prześlij obraz", "date": "Data", "actions": "Akcje", "choose_blog_title": "Wybierz tytuł bloga", "choose_blog_url": "Wybierz adres URL bloga", "access_blog_how": "Jaki chcesz link do bloga", "domain_name": "Nazwa domeny", "path": "Ścieżka", "create": "Utwórz", "index_blog": "Indeksuj bloga w wyszukiwarkach", "content": "Treść", "preview": "Podgląd", "post": "Opublikuj", "include_author": "Dołącz informacje o autorze (nazwa użytkownika) we wpisie", "new_post_on": "nowy wpis na blogu", "posts": "Wpisy", "are_you_sure_blog": "Czy na pewno chcesz usunąć bloga", "this_action_cannot_be_reverted": "Tej operacji nie można cofnąć", "are_you_sure_user": "Czy na pewno chcesz usunąć użytkownika", "are_you_sure_post": "Czy na pewno chcesz usunąć wpis", "delete": "Usuń", "editing_post": "edycja wpisu", "views": "Wyświetlenia", "settings": "Ustawienia", "mfa": "Weryfikacja dwuetapowa", "verify": "Zweryfikuj", "delete_account": "Usuń konto", "instances_text": "Tutaj znajdziesz wszystkie znane nam instancje openwrite.io wraz z ich właściwościami", "name": "Nazwa", "blogs_running": "Uruchomione blogi", "users": "Użytkownicy", "media_upload": "Przesyłanie mediów?", "password2": "Powtórz hasło", "passwords_dont_match": "Hasła się nie zgadzają!", "include_in_feed": "Wyświetlać wpis w sekcji \"Odkrywaj\"", "discover": "Odkrywaj", "discover_text": "Tutaj znajdziesz wszystkie najnowsze posty z tej instancji openwrite.", "yes": "Tak", "no": "Nie", "change_password": "Zmień hasło", "migrate_posts": "Importuj posty", "wrong_username": "Nieprawidłowa nazwa!", "invalid_captcha": "Captcha nieprawidłowa!", "uploads_disabled": "Przesyłanie plików wyłączone", "invalid_filename": "Nieprawidłowa nazwa pliku", "unsupported_filetype": "Nieprawidłowy typ pliku", "no_file": "Brak pliku", "not_image": "Przesyłany plik nie jest obrazem", "upload_failed": "Niepowodzenie w przesyłaniu", "current_password": "Aktualne hasło", "new_password": "Nowe hasło", "choose_vendor": "Wybierz dostawcę obecnego bloga", "select_posts": "Wybierz wpisy do migracji", "migrate_info": "Dane są używane wyłącznie do migracji wpisów i nie są zapisywane.", "invalid_password": "Nieprawidłowe hasło!", "choose_format": "Wybierz format danych", "title_column": "Nazwa kolumny z tytułem", "content_column": "Nazwa kolumny z treścią", "date_column": "Nazwa kolumny z datą", "content_format": "Format treści wpisu", "step": "Krok", "upload_file": "Wybierz plik", "send": "Wyślij", "import_info": "W tym miejscu możesz zaimportować wpisy z innej platformy. Przyjmowane są pliki z Wordpress(XML) oraz CSV. <a class=\"link\" href=\"https://main.openwrite.io/posts-migration\">Tutaj</a> dowiesz się jak przygotować dane do importu.", "import_success1": "Import wpisów zakończony sukcesem! Przejdź do", "import_success2": "dashboardu bloga", "import_success3": "żeby zobaczyć swoje posty.", "import_failed": "Wystąpił błąd! Sprawdź przesyłane dane.", "select_blog_to_import": "Wybierz blog, do którego trafią wpisy", "remove_admin": "Zabierz prawa administratora", "add_admin": "Mianuj administratorem", "are_you_sure_make_admin": "Czy na pewno chcesz nadać prawa administratora dla", "are_you_sure_remove_admin": "Czy na pewno zabrać uprawnienia administratora ", "add_user": "Dodaj użytkownika", "select_theme": "Wybierz motyw", "default": "Domyślny", "see_themes": "Zobacz motywy", "custom_css": "Własny CSS", "css_unsafe_info": "Niebezpieczne wartości jak url(), @keyframes, @import, expression, javascript i animation zostaną usunięte.", "your_blog": "twój blog", "statistics": "Statystyki", "contact": "Kontakt", "pages": "Strony", "new-page": "Nowa strona", "show-in-header": "Pokaż w nagłówku bloga", "are-you-sure-page": "Czy na pewno chcesz usunąć stronę", "new-page-on": "Nowa strona na blogu", "hint-posts": "Wpisz {posts} gdziekolwiek chcesz żeby pokazała się twoja lista wpisów!", "and": "i", "icon": "Ikona", "save-as-draft": "Zapisz jako szkic", "draft": "Szkic", "save-draft": "Zapisz szkic", "publish": "Opublikuj"}, "en": {"lang_name": "🇬🇧 English", "instances": "Instances", "hosting": "Hosting", "register": "Register", "login": "Login", "register_here": "Register Here", "self_host": "Self Host", "username": "Username", "password": "Password", "email": "Email", "not_required": "not required by recommended for 2FA and recovery", "register_on_this_instance": "register on this instance", "or": "or", "language": "Language", "buy_coffee": "Buy me a coffee", "user_exists": "User already exists. Choose different name.", "error": "Unknown error occured. Try again later.", "registered": "Register successful! You can login now.", "invalid_credentials": "Invalid credentials!", "logout": "Log out", "your_blogs": "your blogs", "title": "Title", "edit": "Edit", "new_post": "New post", "delete_blog": "Delete blog", "create_new_blog": "Create new blog", "description": "Description", "save": "Save", "upload_image": "Upload image", "date": "Date", "actions": "Actions", "choose_blog_title": "Choose blog title", "choose_blog_url": "Choose blog URL", "access_blog_how": "How would you like to access your blog", "domain_name": "Domain name", "path": "Path", "create": "Create", "index_blog": "Index your blog in search engines", "content": "content", "preview": "Preview", "post": "Post", "include_author": "Include author information(username) in post", "new_post_on": "new post on blog", "posts": "Posts", "are_you_sure_blog": "Are you sure to delete blog", "this_action_cannot_be_reverted": "This action cannot be reverted", "are_you_sure_user": "Are you sure to delete user", "are_you_sure_post": "Are you sure to delete post", "delete": "Delete", "editing_post": "editing post", "views": "Views", "settings": "Settings", "mfa": "Multi-factor authentication", "verify": "Verify", "delete_account": "Delete account", "instances_text": "Here you will find all known openwrite instances along with their properties", "name": "Name", "blogs_running": "Blogs running", "users": "Users", "media_upload": "Upload media?", "password2": "Retype password", "passwords_dont_match": "Passwords don't match!", "include_in_feed": "Include post in \"Discover\" section", "discover": "Discover", "discover_text": "Here you can find most recent posts from this instance.", "yes": "Yes", "no": "No", "change_password": "Change Password", "migrate_posts": "Import posts", "wrong_username": "Wrong username!", "invalid_captcha": "Invalid captcha!", "uploads_disabled": "Uploads disabled", "invalid_filename": "Invalid filename", "unsupported_filetype": "Unsupported file type", "no_file": "No file", "not_image": "Uploaded file is not a valid image", "upload_failed": "Upload failed", "current_password": "Current password", "new_password": "New password", "choose_vendor": "Choose blog vendor", "select_posts": "Select posts to migrate", "migrate_info": "Data is used only for migration and not saved in any place.", "invalid_password": "Invalid password!", "choose_format": "Choose data format", "title_column": "Title column name", "content_column": "Content column name", "date_column": "Date column name", "content_format": "Content format", "step": "Step", "upload_file": "Upload file", "send": "Send", "import_info": "In here you can import posts from another platform. Files can be exported from Wordpress(XML) or in general CSV format. <a class=\"link\" href=\"https://main.openwrite.io/posts-migration\">Here</a> you can find information about how to prepare data to import.", "import_success1": "Import successful! Go to", "import_success2": "blog dashboard", "import_success3": "to see your posts.", "import_failed": "Error occured! Check your data format.", "select_blog_to_import": "Select blog to import data to", "remove_admin": "Remove admin", "add_admin": "Make admin", "are_you_sure_make_admin": "Are you sure to add admin rights to", "are_you_sure_remove_admin": "Are you sure to remove admin rights from", "add_user": "Add user", "select_theme": "Select theme", "default": "Default", "see_themes": "See themes", "custom_css": "Custom CSS", "css_unsafe_info": "Unsafe values like url(), @keyframes, @import, expression, javascript and animation will be removed.", "your_blog": "your blog", "statistics": "Statistics", "contact": "Contact", "pages": "Pages", "new-page": "New page", "show-in-header": "Show in blog header", "are-you-sure-page": "Are you sure to delete page", "new-page-on": "New page on blog", "hint-posts": "Add {posts} wherever you want to print your post list!", "and": "and", "icon": "Icon", "save-as-draft": "Save as draft", "draft": "Draft", "save-draft": "Save draft", "publish": "Publish"}}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|