Skip to content

Commit 2e900f1

Browse files
authored
Feature/shortcuts (#53)
* Add shortcuts for Saving and Raw View * Add shortcuts tooltips * Invalidate CSS cache * Update icons and CSS * Fix a breaking bug; Breaking CSS.
1 parent 90ccf83 commit 2e900f1

File tree

9 files changed

+166
-35
lines changed

9 files changed

+166
-35
lines changed

views/htmx.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,12 @@ def highlight_code(self, *, files: list[dict[str, Any]]) -> str:
9292

9393
position += length + 1
9494

95-
content = bleach.clean(original.replace("<!", "&lt;&#33;"), attributes=[], tags=[], strip_comments=False)
95+
content = bleach.clean(
96+
original.replace("<!", "&lt;&#33;").replace("&#xa;", "&amp;#xa;"),
97+
attributes=[],
98+
tags=[],
99+
strip_comments=False,
100+
)
96101

97102
lines: str = f"""<table class="lineNums"><tbody>\n{"".join(numbers)}\n</tbody></table>"""
98103
html += f"""
@@ -214,23 +219,31 @@ async def paste_raw(self, request: starlette_plus.Request) -> starlette_plus.Res
214219
password: str | None = request.headers.get("authorization", None)
215220
identifier: str = request.path_params["id"]
216221

222+
htmx_url: str | None = request.headers.get("HX-Current-URL", None)
223+
if identifier == "0" and htmx_url:
224+
identifier = htmx_url.removeprefix(f'{CONFIG["SERVER"]["domain"]}/')
225+
226+
headers: dict[str, str] = {"HX-Redirect": f"/raw/{identifier}"}
217227
paste = await self.app.database.fetch_paste(identifier, password=password)
228+
218229
if not paste:
219230
return starlette_plus.JSONResponse(
220231
{"error": f'A paste with the id "{identifier}" could not be found or has expired.'},
221232
status_code=404,
233+
headers=headers,
222234
)
223235

224236
if paste.has_password and not paste.password_ok:
225237
return starlette_plus.JSONResponse(
226238
{"error": "Unauthorized. Raw pastes can not be viewed when protected by passwords."},
227239
status_code=401,
240+
headers=headers,
228241
)
229242

230243
to_return: dict[str, Any] = paste.serialize(exclude=["safety", "password", "password_ok"])
231244
text: str = "\n\n\n\n".join([f"# MystBin ! - {f['filename']}\n{f['content']}" for f in to_return["files"]])
232245

233-
return starlette_plus.PlainTextResponse(text)
246+
return starlette_plus.PlainTextResponse(text, headers=headers)
234247

235248
@starlette_plus.route("/raw/{id}/{page:int}", prefix=False)
236249
@starlette_plus.limit(**CONFIG["LIMITS"]["paste_get"])

web/index.html

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@
1919
<script src="/static/scripts/themes.js?v=1" defer></script>
2020
<script src="/static/scripts/files.js?v=4" defer></script>
2121
<script src="/static/scripts/dragDrop.js?v=1"></script>
22+
<script src="/static/scripts/shortcuts.js?v=1" defer></script>
2223

2324
<!-- STYLESHEETS -->
2425
<!-- <link rel="preload" href="static/styles/global.css" as="style" /> -->
2526
<!-- <link rel="preload" href="static/styles/highlights.css" as="style" /> -->
26-
<link rel="stylesheet" type="text/css" href="/static/styles/global.css?v=6" />
27+
<link rel="stylesheet" type="text/css" href="/static/styles/global.css?v=7" />
2728

2829
<!-- FONTS -->
2930
<link rel="preconnect" href="https://fonts.googleapis.com">
@@ -46,7 +47,13 @@
4647
<img src="/static/images/logo.svg" class="logo" />
4748
MystBin
4849
</a>
49-
<div>
50+
<div class="headerRight">
51+
<span class="keyboardTool keyboardLight"
52+
data-text="Ctrl + S&#xa; Save Paste&#xa;&#xa;Ctrl + Shift + R&#xa; View Raw"><img
53+
src="/static/images/keyboard-light.svg" class="keyboard" /></span>
54+
<span class="keyboardTool keyboardDark"
55+
data-text="Ctrl + S&#xa; Save Paste&#xa;&#xa;Ctrl + Shift + R&#xa; View Raw"><img
56+
src="/static/images/keyboard.svg" class="keyboard" /></span>
5057
<input id="themeSwitch" class="themeSwitch" type="checkbox" />
5158
<label for="themeSwitch"></label>
5259
</div>
@@ -55,7 +62,9 @@
5562
<form id="content" class="content" hx-swap-oob="true" hx-swap="outerHTML"
5663
hx-include="[name='fileName'] [name='fileContent'] [name='pastePassword']">
5764
<div id="pastecontainer" class="pasteContainer">
58-
<div class="pasteArea" id="__file0" data-position="0" ondrop="fileDrop(event, this)" ondragover="fileDragOver(event, this)" ondragenter="fileDragStart(event, this)" ondragleave="fileDragEnd(event, this)">
65+
<div class="pasteArea" id="__file0" data-position="0" ondrop="fileDrop(event, this)"
66+
ondragover="fileDragOver(event, this)" ondragenter="fileDragStart(event, this)"
67+
ondragleave="fileDragEnd(event, this)">
5968
<div class="pasteHeader">
6069
<textarea name="fileName" class="filenameArea" rows="1" placeholder="Optional Filename..." maxlength="25"
6170
spellcheck="false"></textarea>
@@ -65,21 +74,24 @@
6574
Filling in all current files will create a new one (Up to 5)" maxlength="300000" onkeyup="addFile(0)"></textarea>
6675
</div>
6776

68-
<div class="pasteArea smallArea" id="__file1" data-position="1" ondrop="fileDrop(event, this)" ondragover="fileDragOver(event, this)" ondragenter="fileDragStart(event, this)" ondragleave="fileDragEnd(event, this)">
77+
<div class="pasteArea smallArea" id="__file1" data-position="1" ondrop="fileDrop(event, this)"
78+
ondragover="fileDragOver(event, this)" ondragenter="fileDragStart(event, this)"
79+
ondragleave="fileDragEnd(event, this)">
6980
<div class="pasteHeader">
7081
<textarea name="fileName" class="filenameArea" rows="1" placeholder="Optional Filename..." maxlength="25"
7182
spellcheck="false"></textarea>
7283
<span class="deleteFile" onclick="deleteFile('__file1')">Delete File</span>
7384
</div>
74-
<textarea class="fileContent" name="fileContent" required autofocus spellcheck="false" placeholder="Paste code or text..."
75-
maxlength="300000" onkeyup="addFile(1)"></textarea>
85+
<textarea class="fileContent" name="fileContent" required autofocus spellcheck="false"
86+
placeholder="Paste code or text..." maxlength="300000" onkeyup="addFile(1)"></textarea>
7687
</div>
7788
</div>
7889

7990
<div class="pasteOptions">
8091
<hr class="hrLight" />
8192
<div class="pasteOptionsSection">
82-
<span class="savePaste" hx-post="/htmx/save" hx-target="#content">Save Paste</span>
93+
<span class="savePaste" hx-post="/htmx/save" hx-target="#content"
94+
hx-trigger="click, keyup[ctrlKey&&key=='s'] from:body">Save Paste</span>
8395
<input name="pastePassword" class="filenameArea" rows="1" placeholder="Optional Password..." maxlength="100"
8496
type="password" autocomplete="off" />
8597
</div>

web/maint.html

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
<meta name="viewport" content="width=device-width,initial-scale=1" />
99
<meta name="description" content="Easily share code and text." />
1010

11-
<!-- PACKAGES -->
12-
<!-- SCRIPTS -->
13-
<script src="static/scripts/initialTheme.js?v=1"></script>
14-
<script src="static/scripts/themes.js?v=1" defer></script>
11+
<!-- PACKAGES -->
12+
<!-- SCRIPTS -->
13+
<script src="static/scripts/initialTheme.js?v=1"></script>
14+
<script src="static/scripts/themes.js?v=1" defer></script>
1515

16-
<!-- STYLESHEETS -->
17-
<!-- <link rel="preload" href="static/styles/global.css" as="style" /> -->
18-
<link rel="stylesheet" type="text/css" href="static/styles/global.css?v=6" />
16+
<!-- STYLESHEETS -->
17+
<!-- <link rel="preload" href="static/styles/global.css" as="style" /> -->
18+
<link rel="stylesheet" type="text/css" href="static/styles/global.css?v=7" />
1919

2020

2121
<!-- FONTS -->
@@ -39,7 +39,13 @@
3939
<img src="/static/images/logo.svg" class="logo" />
4040
MystBin
4141
</a>
42-
<div>
42+
<div class="headerRight">
43+
<span class="keyboardTool keyboardLight"
44+
data-text="Ctrl + S&#xa; Save Paste&#xa;&#xa;Ctrl + Shift + R&#xa; View Raw"><img
45+
src="/static/images/keyboard-light.svg" class="keyboard" /></span>
46+
<span class="keyboardTool keyboardDark"
47+
data-text="Ctrl + S&#xa; Save Paste&#xa;&#xa;Ctrl + Shift + R&#xa; View Raw"><img
48+
src="/static/images/keyboard.svg" class="keyboard" /></span>
4349
<input id="themeSwitch" class="themeSwitch" type="checkbox" />
4450
<label for="themeSwitch"></label>
4551
</div>

web/password.html

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@
2020
<script src="/static/scripts/themes.js?v=1" defer></script>
2121
<script src="/static/scripts/hidecopy.js?v=1" defer></script>
2222
<script src="/static/scripts/highlightsHTMX.js?v=5"></script>
23+
<script src="/static/scripts/shortcuts.js?v=1" defer></script>
2324

2425
<!-- STYLESHEETS -->
2526
<!-- <link rel="preload" href="static/styles/global.css" as="style" /> -->
2627
<!-- <link rel="preload" href="static/styles/highlights.css" as="style" /> -->
27-
<link rel="stylesheet" type="text/css" href="/static/styles/global.css?v=6" />
28+
<link rel="stylesheet" type="text/css" href="/static/styles/global.css?v=7" />
2829
<link rel="stylesheet" type="text/css" href="/static/styles/highlights.css" />
2930

3031
<!-- FONTS -->
@@ -48,15 +49,21 @@
4849
<img src="/static/images/logo.svg" class="logo" />
4950
MystBin
5051
</a>
51-
<div>
52+
<div class="headerRight">
53+
<span class="keyboardTool keyboardLight"
54+
data-text="Ctrl + S&#xa; Save Paste&#xa;&#xa;Ctrl + Shift + R&#xa; View Raw"><img
55+
src="/static/images/keyboard-light.svg" class="keyboard" /></span>
56+
<span class="keyboardTool keyboardDark"
57+
data-text="Ctrl + S&#xa; Save Paste&#xa;&#xa;Ctrl + Shift + R&#xa; View Raw"><img
58+
src="/static/images/keyboard.svg" class="keyboard" /></span>
5259
<input id="themeSwitch" class="themeSwitch" type="checkbox" />
5360
<label for="themeSwitch"></label>
5461
</div>
5562
</div>
5663

5764
<form id="content" class="content" hx-swap-oob="true" hx-get="/pass" hx-target="#pastecontainer"
58-
hx-vals="js:{id: window.location.pathname}" hx-include="[name='pastePassword']" hx-trigger="keyup[keyCode==13] from:[name='pastePassword']"
59-
onSubmit="return false;">
65+
hx-vals="js:{id: window.location.pathname}" hx-include="[name='pastePassword']"
66+
hx-trigger="keyup[keyCode==13] from:[name='pastePassword']" onSubmit="return false;">
6067
<div id="pastecontainer" class="pasteContainer">
6168
<div class="protected">
6269
<h1>Password Protected!</h1>
@@ -85,6 +92,8 @@ <h1>Password Protected!</h1>
8592
<a href="https://github.com/PythonistaGuild">GitHub</a>
8693
</div>
8794
</div>
95+
<!-- META DIV FOR KEYBOARD SHORTCUT -->
96+
<div style="display: none;" hx-get="/raw/0" hx-trigger="keyup[ctrlKey&&shiftKey&&key=='R'] from:body"></div>
8897
</body>
8998

9099
</html>

web/paste.html

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<meta name="description" content="Easily share code and text." />
1010

1111
<!-- PACKAGES -->
12-
<!-- <link rel="preload" href="static/packages/htmx.min.js" as="script"> -->
12+
<script src="static/packages/htmx.min.js"></script>
1313
<!-- <link rel="preload" href="static/packages/highlight.min.js" as="script"> -->
1414
<!-- <link rel="preload" href="static/packages/highlight-ln.min.js" as="script"> -->
1515
<script src="/static/packages/highlight.min.js"></script>
@@ -19,11 +19,12 @@
1919
<script src="/static/scripts/themes.js?v=1" defer></script>
2020
<script src="/static/scripts/hidecopy.js?v=1" defer></script>
2121
<script src="/static/scripts/highlights.js?v=5" defer></script>
22+
<script src="/static/scripts/shortcuts.js?v=1" defer></script>
2223

2324
<!-- STYLESHEETS -->
2425
<!-- <link rel="preload" href="static/styles/global.css" as="style" /> -->
2526
<!-- <link rel="preload" href="static/styles/highlights.css" as="style" /> -->
26-
<link rel="stylesheet" type="text/css" href="/static/styles/global.css?v=6" />
27+
<link rel="stylesheet" type="text/css" href="/static/styles/global.css?v=7" />
2728
<link rel="stylesheet" type="text/css" href="/static/styles/highlights.css" />
2829

2930
<!-- FONTS -->
@@ -47,7 +48,13 @@
4748
<img src="/static/images/logo.svg" class="logo" />
4849
MystBin
4950
</a>
50-
<div>
51+
<div class="headerRight">
52+
<span class="keyboardTool keyboardLight"
53+
data-text="Ctrl + S&#xa; Save Paste&#xa;&#xa;Ctrl + Shift + R&#xa; View Raw"><img
54+
src="/static/images/keyboard-light.svg" class="keyboard" /></span>
55+
<span class="keyboardTool keyboardDark"
56+
data-text="Ctrl + S&#xa; Save Paste&#xa;&#xa;Ctrl + Shift + R&#xa; View Raw"><img
57+
src="/static/images/keyboard.svg" class="keyboard" /></span>
5158
<input id="themeSwitch" class="themeSwitch" type="checkbox" />
5259
<label for="themeSwitch"></label>
5360
</div>
@@ -72,6 +79,8 @@
7279
<a href="https://github.com/PythonistaGuild">GitHub</a>
7380
</div>
7481
</div>
82+
<!-- META DIV FOR KEYBOARD SHORTCUT -->
83+
<div style="display: none;" hx-get="/raw/0" hx-trigger="keyup[ctrlKey&&shiftKey&&key=='R'] from:body"></div>
7584
</body>
7685

7786
</html>

web/static/images/keyboard-light.svg

Lines changed: 6 additions & 0 deletions
Loading

web/static/images/keyboard.svg

Lines changed: 6 additions & 0 deletions
Loading

web/static/scripts/shortcuts.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
window.addEventListener("keydown", (e) => {
2+
3+
// Ctrl + s === Save Paste
4+
if (e.ctrlKey && e.key === "s") {
5+
e.preventDefault();
6+
e.stopPropagation();
7+
return;
8+
}
9+
10+
// Ctrl + Shift + R === Raw Paste
11+
else if (e.ctrlKey && e.shiftKey && e.key === "R") {
12+
e.preventDefault();
13+
e.stopPropagation();
14+
return;
15+
}
16+
});

0 commit comments

Comments
 (0)