Compare commits

...
Sign in to create a new pull request.

539 commits

Author SHA1 Message Date
0babeb9390
First batch of Twig macro reduction, forum ones will probably take as long as these combined. 2025-06-17 01:20:14 +00:00
8ef46fe475
Minor spacing fixes. 2025-06-16 20:59:05 +00:00
c8db915142
Increased base font size and switched to Inter, Victor Mono and Zen Kaku Gothic New.
You'll likely run into some jank with this update, and this is also the first in a series of visual overhauls to come.

I've been wanting to increase the base font size from 12px to 16px for a while now but never actually got around to it until getting really tired of the limits imposed on me by Verdana.
It will require some getting used to, even for me, though!
The only thing that really stands out is that big walls of text like news and forum posts are a bit bigger and actually have a non-claustrophobic amount of spacing inbetween them.

My efforts to avoid shoving too much spacing into things have severely backfired into making me afraid to introduce any in the first place.
Personally, I think this reads a lot nicer!

Verdana won't be gone for good though.
Once enough of the API is ready it will be featured on the Flashii Fundamentals for Legacy PCs subsite!!
2025-06-16 20:52:25 +00:00
a0e719c2d1
Updated libraries. 2025-06-12 20:17:54 +00:00
d8dbfaa7ab
Added leeway to the device code token polling process. 2025-05-18 15:55:06 +00:00
4e66852db1
Fixed tag script, potentially. 2025-05-13 17:28:26 +00:00
40a96029ff
Switched to the railgun/jwt library. 2025-05-13 17:27:04 +00:00
dd8ec7c8dd
Cleaned up forum templates. 2025-04-24 19:17:38 +00:00
5ec7dddd0e
Fixed categories without topics not being browseable. 2025-04-24 18:40:41 +00:00
af476491b2
Made OAuth2 IDs snowflakes and also removed the client_id field. 2025-04-24 00:17:35 +00:00
c91fa69362
Altered default token lifetimes and also made them configurable. 2025-04-23 21:56:33 +00:00
093266eb1e
Allow access and refresh tokens to not be associated with an app. 2025-04-23 21:24:02 +00:00
d9cf9674f3
Check for empty array. 2025-04-22 22:20:13 +00:00
e1155158d9
Should probably also bump the version. 2025-04-22 21:58:24 +00:00
86578c9ff4
Forgot to update the migration, oops. 2025-04-22 21:58:07 +00:00
3bd556fba9
Added chat server selection endpoints. 2025-04-22 21:55:51 +00:00
52632b42eb
Fixed oversights. 2025-04-22 21:10:47 +00:00
ca2c192330
Added new token/login endpoints for chat. 2025-04-22 20:16:55 +00:00
85c71f604a
Use URI instead of URL in the API.
URL equivalent of a field can still be requested using the fields parameter for the existing routes.
2025-04-22 18:33:47 +00:00
1d57fc3b45
Added kaomoji list to the database. 2025-04-21 01:25:02 +00:00
45635ddc5b
Updated libraries. 2025-04-21 00:52:00 +00:00
d675f1410f
Ported removeChild util. 2025-04-13 00:46:51 +00:00
a6b3cef7b4
Fixed incorrect path being used for CORS credentials check. 2025-04-12 21:15:14 +00:00
4b4ae1c820
Added Cache-Control rules for existing APIs. 2025-04-12 20:33:44 +00:00
d15e074674
Use --env-file-if-exists instead. 2025-04-11 19:28:57 +00:00
c7dc5de306
That should've been install, not update. 2025-04-11 19:02:37 +00:00
e8dcd5b878
Removed push. 2025-04-11 18:59:15 +00:00
4da099ca74
Use make for calling various scripts correctly. 2025-04-11 18:57:13 +00:00
0d8283495d
Allow filtering to a specific type of asset task. 2025-04-11 18:15:50 +00:00
99e3e3111a
Share .env file with the NodeJS build script. 2025-04-11 18:02:38 +00:00
35dce01323
Fixed authentication oversights. 2025-04-03 20:35:57 +00:00
277afa5b19
Removed SameSite=Strict. 2025-04-03 20:26:04 +00:00
55dc011df6
Also check folder permissions for the EEPROM scripts. 2025-04-03 20:09:18 +00:00
9d70505ad8
Added utility to nuke the templating cache directory. 2025-04-03 20:01:27 +00:00
155b301405
Fixed this thing being a layer up too high. 2025-04-03 19:42:43 +00:00
83068a4183
Replaced timings in the footer with a visual for the Server-Timing header. 2025-04-03 19:40:10 +00:00
ceb6bece09
Improved templating engine wrapping. 2025-04-03 14:37:19 +00:00
e4c3e4c052
Authn/z rework. 2025-03-31 15:35:24 +00:00
28be4f16c2
Added optional alphaless RGB field. 2025-03-30 19:26:54 +00:00
16a7e20441
Logging cleanup. 2025-03-28 20:19:54 +00:00
d1fad37022
Added new tables to data exports. 2025-03-28 02:05:40 +00:00
a1398fb179
Added field filtering to API endpoints and store colour presets in the database. 2025-03-28 01:47:24 +00:00
12d40e69a5
Tighter client side integrations for uploads. 2025-03-27 21:27:49 +00:00
41e27cdffa
Ensure storage folder exists. 2025-03-27 00:57:53 +00:00
104bf379b0
One day I won't forgot to bump VERSION. 2025-03-27 00:45:46 +00:00
5f6133c007
Shoved EEPROM into Misuzu. 2025-03-27 00:44:42 +00:00
0b7031959b
Removed RPCii dependency. 2025-03-25 14:28:04 +00:00
6c50a582cb
:))) 2025-03-25 14:22:28 +00:00
238bb3f48e
Updated leftovers from rebase. 2025-03-25 13:51:39 +00:00
5ba8b30047 Updated to latest Index as well as some minor bug fixes. 2025-03-25 14:27:48 +01:00
ad89d45cf0
Fixed oversight. 2025-03-25 12:23:40 +00:00
e3707bf2b4
Moved /v1/me over. 2025-03-24 22:15:52 +00:00
649968814a
Forgot the VERSION bump again (its gonna get confusing). 2025-03-24 19:04:16 +00:00
477210411d
Moved /v1/emotes. 2025-03-24 19:03:05 +00:00
b6f5a4e0cc
Styled landing, Bluesky and Fedi redirect pages. 2025-02-27 00:17:00 +00:00
7e75a71bd2
Fixed oversight. 2025-02-26 22:06:00 +00:00
61ab586df8
Bumped VERSION. 2025-02-26 22:03:55 +00:00
17251cf750
PHPStan fixes. 2025-02-26 22:03:13 +00:00
446c675613
JWT out of the OpenID namespace and merged the remainder with the OAuth namespace. 2025-02-26 21:01:32 +00:00
b2f8347526
OAuth metadata endpoints. 2025-02-26 18:06:46 +00:00
e5a947e973
Moved user agent string creation thingy into a method. 2025-02-26 15:14:30 +00:00
676e3fb217
Switched Xrpc client to Guzzle. 2025-02-26 14:57:19 +00:00
d3bdd8f3a2
Removed Awaki from the source code list.
(Excuse to test GPG signing)
2025-02-25 19:34:40 +00:00
b1d9f88549 Don't use X-Accel-Redirect for the maintenance page, it overrides the status code. 2025-02-25 15:14:17 +00:00
aaba24894c Added OpenID Connect. 2025-02-25 02:30:24 +00:00
24d93a5dbf Slight adjustment to style assignment. 2025-02-20 19:17:17 +00:00
55fca7b945 Adjusted fragment creation. 2025-02-20 18:21:36 +00:00
eb72573121 Reverted to the old removeChildren implementation. 2025-02-20 18:09:17 +00:00
604771aac3 Bumped VERSION. 2025-02-20 02:23:25 +00:00
7353553de7 Rewrote the comments system. ()
old one basically bitrotted to death, may it rinse in prosciutto

Reviewed-on: 
Co-authored-by: flashwave <me@flash.moe>
Co-committed-by: flashwave <me@flash.moe>
2025-02-20 02:19:32 +00:00
6b2bfb726f Added ability to filter search by topic. 2025-02-11 02:41:49 +00:00
e1cb500f99 Use .env file instead of local config. 2025-02-09 23:34:28 +00:00
4110cd5190 Moved constants out of misuzu.php. 2025-02-09 20:44:10 +00:00
1d54d41f6b No longer use random anonymous object for asset info. 2025-02-09 19:58:09 +00:00
bac889787a Moved database methods into own context class. 2025-02-09 17:39:48 +00:00
21a730d189 Cleaned up use statements in misuzu context. 2025-02-09 16:52:46 +00:00
7bf9a7eedd Made certain strings less ugly. 2025-02-09 16:41:09 +00:00
cc37b7cad3 Added user name history beginnings. 2025-02-09 01:32:35 +00:00
7f7e644069 Fixed detections. 2025-02-09 00:28:28 +00:00
f39e1230c5 Moved passwords out of the users table. 2025-02-09 00:26:12 +00:00
7f85abba6e Made timestamps be at the end of the users table like every other table. 2025-02-08 23:24:29 +00:00
372797c564 Moved profile about sections into their own table. 2025-02-08 23:20:53 +00:00
8bb2400d3f Moved forum signatures into dedicated table. 2025-02-08 22:52:36 +00:00
d1173c6e0f Fixed collections on the ENUM columns. 2025-02-08 21:27:50 +00:00
31d89a08bf Moved profile background settings out of the users table. 2025-02-08 21:20:44 +00:00
9f5076cc77 Fixed missing closing parenthesis. 2025-02-08 18:00:07 +00:00
d9f35594e7 Changed internal parser selection value from integers to a string enum. 2025-02-08 17:51:18 +00:00
4d53565139 Fixed query oversights. 2025-02-08 15:17:03 +00:00
179b9aaa08 Included new tables in account data exports. 2025-02-08 03:08:08 +00:00
a0f5444292 Added id to the audit logs table. 2025-02-08 02:51:03 +00:00
4a3d63c065 Ran PHPstan checks. 2025-02-08 02:45:41 +00:00
c28e0a90dd Moved birthdate into separate table. 2025-02-08 02:43:54 +00:00
2c4d35e2dd That's not nullable, oops. 2025-02-08 01:50:59 +00:00
b13cc7804d Moved TOTP codes out of the main users table. 2025-02-08 01:36:33 +00:00
3897dc13fe Removed bogus data scripts. 2025-02-08 01:29:25 +00:00
e46a4ffe1d Bumped minimum MariaDB version. 2025-02-08 01:11:53 +00:00
497bc5323d Made database column names more consistent across the board. 2025-02-07 23:10:41 +00:00
22f216a6a9 Removed unused CSS stuff. 2025-02-07 00:12:13 +00:00
b49868e9c7 Removed 'is'. 2025-02-06 21:12:13 +00:00
2d6f9d0f1b Moved common JS and CSS to separate file. 2025-02-02 21:27:31 +00:00
584546a8f7 Removed RPC stuff for Flashii ID. 2025-02-02 20:25:58 +00:00
8f63b57c0c Improved flow for using OAuth2 while logged out. 2025-02-02 19:51:05 +00:00
8be630531a Only serve ID stuff on main domain and just redirect the id.flashii.net URLs. 2025-02-02 19:31:06 +00:00
6e0726fd3f Fixed chat login using Bearer token. 2025-02-02 02:34:51 +00:00
ab1bcaebc0 Added missing housekeeping cronjob. 2025-02-02 02:28:09 +00:00
534e947522 Merged OAuth2 handling into Misuzu. 2025-02-02 02:09:56 +00:00
1994a9892d Updated lockfile. 2025-01-30 21:33:20 +00:00
b3112ce433 Speedrunned Bluesky integration for news posts. 2025-01-30 21:31:38 +00:00
0701298fa1 Explicitly disable templating cache for tools/render-tpl. 2025-01-30 14:59:02 +00:00
269dc78919 Fixed broom closet index being visible while logged out??? 2025-01-30 14:55:20 +00:00
3e14f63bdb Redid HTTP error pages. 2025-01-30 14:52:01 +00:00
312be0e7fe Added Bluesky link where the Twitter link used to be. 2025-01-30 13:04:43 +00:00
eb88cc0999 Updated Font Awesome. 2025-01-30 13:03:25 +00:00
a09bdb5fc3 Added template layer below the master template in preparation for other things. 2025-01-30 12:07:59 +00:00
720d36dd23 Added script for rendering templates in console. 2025-01-30 11:46:04 +00:00
8f532492c4 Bump VERSION. 2025-01-29 23:57:50 +00:00
9e5945cbd4 Initial implementation of the dependency injector thingy. 2025-01-29 23:56:56 +00:00
d462ee0594 Added Data suffix where applicable. 2025-01-29 23:36:35 +00:00
6c7568e261 Updated Index version. 2025-01-29 23:13:17 +00:00
f2233c5390 Built redirector service into Misuzu. 2025-01-29 21:08:13 +00:00
a83cfdc595 Updated libraries. 2025-01-29 19:32:27 +00:00
1176fbce16 Removed old build script leftovers. 2025-01-29 19:31:24 +00:00
5333a3277f Read remote address from the right place. 2025-01-29 18:19:33 +00:00
33344541d6 Added ability to scope RoutingContext. 2025-01-29 00:25:53 +00:00
06d0413976 Replaced all / reads with filter_input in public/index.php. 2025-01-28 21:14:48 +00:00
e43ba4572f Bumped VERSION. 2025-01-04 02:51:07 +00:00
c16c122aef Switched to integrated EEPROM client. 2025-01-04 02:50:21 +00:00
72e821fc24 Updated libraries. 2025-01-04 02:47:54 +00:00
2b3e0aa6f1 Updated LICENCE year. 2025-01-03 19:15:56 +00:00
e8db4feb39 Update VERSION. 2025-01-03 19:15:21 +00:00
32c9a09d4a Alter output of /v1/me if banned. 2025-01-03 19:14:48 +00:00
ba79bb81d1 Bumped VERSION. 2024-12-23 01:49:03 +00:00
5443ea331e Fixed PM actions not doing anything. 2024-12-23 01:48:32 +00:00
7f7b198007 Updated libraries. 2024-12-20 00:40:15 +00:00
3c2adfdbd5 Bumped VERSION. 2024-12-20 00:30:03 +00:00
20ed8cd59f Moved topic listing into the router. 2024-12-20 00:29:14 +00:00
50b2322c8c p= -> page= for forum categories. 2024-12-20 00:10:20 +00:00
471a054030 Moved forum category views into the router. 2024-12-19 23:41:52 +00:00
72361d1e29 Bumped VERSION. 2024-12-19 02:27:51 +00:00
b5f0f6cda6 Shortcut for pagination appending. 2024-12-19 02:27:28 +00:00
7d710e2d02 Use nextParameter instead of addParameter and manually counting where possible. 2024-12-19 02:23:05 +00:00
d3f9c299af Rewrote the Pagination handler. 2024-12-19 01:22:26 +00:00
02adfa1f4f Moved forum index into the router. 2024-12-18 23:58:53 +00:00
10a377f90f Minor design update for roles list in settings. 2024-12-18 03:26:44 +00:00
d10fa29d3c Bumped VERSION. 2024-12-18 03:08:17 +00:00
265e8f2d4b Replaced confirm pages with dynamic requests on the forum. 2024-12-18 03:07:48 +00:00
a8c777d725 Added global <noscript> notice. 2024-12-17 21:44:48 +00:00
928fe4047a Made use significantly less ugly. 2024-12-17 21:37:28 +00:00
312c4d2968 Final set of CSRFP -> CSRF renames, use headers instead of POST fields and build CSRF handling into the XHR wrapper. 2024-12-17 21:23:38 +00:00
45b75a92ee Fixed migrations being impossible to run on a clean database. 2024-12-17 20:32:09 +00:00
8a1bee10a4 Updated .gitignore. 2024-12-15 17:14:43 +00:00
0e64d85393 Raised checking level from 5 to 6. 2024-12-02 21:33:15 +00:00
3c10fb0de0 Fixed PHPstan detections. 2024-12-02 02:28:08 +00:00
96cc58f820 Forgot to remove one of the vs. 2024-12-02 00:37:46 +00:00
37cbb925ad Imported tag creation script with VERSION file. 2024-12-02 00:36:27 +00:00
bb60d91bd5 Fixed oversight on memberlist. 2024-12-02 00:34:00 +00:00
9ec54e9296 Fixed omegadumb oversight. 2024-12-01 01:37:53 +00:00
db427363f7 Fixed oversight... 2024-11-30 15:30:30 +00:00
163e54def1 Forgot half of it. 2024-11-30 04:20:20 +00:00
d103477fe1 Removed getter/setter methods in favour of property hooks and asymmetric visibility. 2024-11-30 04:09:29 +00:00
2cb2918533 Added simpler avatar URL field. 2024-11-22 20:57:02 +00:00
4569911739 Reordered output cus it was bothering me. 2024-11-21 20:05:56 +00:00
29c7766793 Added option to include e-mail address in user rpc call. 2024-11-21 19:37:04 +00:00
6efda5a1a7 Count loads of old emote endpoint in case I forgot to replace anywhere. 2024-11-14 04:13:57 +00:00
06b9d28a47 Added RPC for emotes list. 2024-11-14 02:44:02 +00:00
8fc998621b Updated RPC library. 2024-11-13 23:30:34 +00:00
5e5e45db1e Ensure content passed to the parse_text filter is escaped. 2024-11-07 00:33:42 +00:00
518a9b6bcc Updated libraries. 2024-10-28 18:35:19 +00:00
db9e60a018 Fixed some URLs not getting registered properly. 2024-10-05 15:28:56 +00:00
2f5db64982 Fixed casing oversight. 2024-10-05 14:39:43 +00:00
99a592dcce Removed all references to the IPAddress class. 2024-10-05 14:22:14 +00:00
1d62db8de6 Fixed undropkicked I. 2024-10-05 03:36:53 +00:00
55a2424fee Updated to latest Index version. 2024-10-05 02:40:29 +00:00
83f94debc7 Use attributes for JSON encoding. 2024-09-30 17:38:08 +00:00
3a42f51614 Updated libraries. 2024-09-30 17:37:41 +00:00
aabffb7b30 Added optional string role IDs for the API. 2024-09-16 21:44:37 +00:00
f373690b12 Updated libraries. 2024-09-16 20:51:46 +00:00
2b1691ae26 Added RPC endpoint for fetching user info. 2024-09-05 20:08:31 +00:00
76443a5d1a Added auth RPC routes. 2024-08-25 23:03:46 +00:00
bed2216717 Fixed return type. 2024-08-18 20:54:39 +00:00
ccaca7eaac Replaced internal Flashii ID routes with RPC library. 2024-08-16 19:29:57 +00:00
e708f99fee Updated Index and switched to Carbon for date handling. 2024-08-04 21:37:12 +00:00
e2ee567711 Removed stray Jeff. 2024-07-27 20:11:06 +00:00
e0fea668a1 Added very preliminary support for Bearer tokens to chat authentication. 2024-07-21 01:50:42 +00:00
ab81e1bcf7 Added interop endpoints for Hanyuu. 2024-07-20 19:35:50 +00:00
0a6f30f290 Updated libraries. 2024-07-18 03:42:16 +00:00
aa22815008 Updated build script. 2024-06-11 00:48:44 +00:00
e804e00139 SharpConfig -> FileConfig 2024-06-03 23:04:59 +00:00
c3162f4013 Updated libraries. 2024-06-03 23:04:21 +00:00
07d93e0023 Prevent access to private messages when impersonating a user. 2024-06-02 19:57:58 +00:00
90f3fd1c88 Base64 encode PM titles and bodies in the database.
To prevent personal discomfort with having to do database messages and seeing people's personal conversations.
I haven't run into it yet, but I'd rather avoid it altogether.
2024-06-02 19:54:33 +00:00
f5c8a2cc5e Added broom closet PM stats. 2024-06-02 19:43:57 +00:00
43c2734e74 Updated libraries. 2024-05-30 22:02:09 +00:00
38975e8004 Built Playpen icon updating into Misuzu.
Was previously handled by a stinky script.
2024-05-30 22:00:41 +00:00
6af4e8b1e5 Fixed wrong HTTP verb. 2024-03-30 15:22:11 +00:00
6e1977d4e9 Fixed various oversights. 2024-03-30 03:19:08 +00:00
0da002d6d2 Updated Misuzu to new HTTP router. 2024-03-30 03:14:03 +00:00
af100649d2 Fixed error when trying to access a topic with no posts associated. 2024-02-24 22:03:32 +00:00
73ffd22fe6 hurr 2024-02-21 00:31:25 +00:00
fa093b86b7 Stinky fix for impersonation in chat auth. 2024-02-20 23:56:43 +00:00
db29a33d20 Fixed bans no longer working. 2024-02-15 22:55:24 +00:00
c876bc2710 Fixed Forum Activity section always showing up. 2024-02-13 21:22:56 +00:00
3d56d27227 Fixed profile fields not showing up anymore. 2024-02-11 02:22:22 +00:00
712ed3e0c8 Missed one! 2024-02-09 16:07:43 +00:00
1a678f54c6 Fixed forum/topic breadcrumbs. 2024-02-08 15:20:44 +00:00
2278ecab38 Fixed use of wrong BanInfo constructor. 2024-02-08 15:18:57 +00:00
b0e9f4a167 Fixed oversights on landing page. 2024-02-08 00:06:23 +00:00
ba7fb5e15a Added lazy database object creation. 2024-02-07 00:04:45 +00:00
eb596d0fee Added PMs to data export. 2024-02-05 22:56:51 +00:00
73d5456e9a whoops 2024-02-02 21:53:36 +00:00
e7d97ad9ac Updated to new EEPROM script. 2024-02-02 21:42:40 +00:00
1a7922ba6e Added notice when recipient is banned. 2024-02-02 02:16:37 +00:00
d64eb69e22 Check if recipient is actually able to receive messages. 2024-02-02 02:07:29 +00:00
a649b8b9a6 Prevent banned users from sending messages. 2024-02-02 01:59:21 +00:00
3e7935fb79 Added private messages. 2024-01-30 23:47:02 +00:00
4e38a537ea Use accent-color and color-scheme CSS directives. 2024-01-25 18:17:54 +00:00
a65f8dc8dd Fixed Ctrl+Enter submission not working anymore either. 2024-01-25 00:18:56 +00:00
27b3e49e14 Fixed forum post form throwing up the navigation confirmation when it isn't supposed to. 2024-01-25 00:12:53 +00:00
c9ef6e4112 Include SameSite attribute on cookies. 2024-01-24 22:14:48 +00:00
85f77eb566 Rewrote Javascript code. 2024-01-24 21:53:26 +00:00
a430568925 Fixed error when trying to add a new change. 2024-01-24 18:28:13 +00:00
3f867af99b Imported new asset build script. 2024-01-24 18:24:40 +00:00
f41c24638d Added links to Amimami repositories. 2024-01-18 20:31:08 +00:00
40fe809389 Adjusted CORS handling for emoticon endpoint. 2024-01-17 19:57:46 +00:00
cbd7d070fc Updated browserlists. 2024-01-08 13:43:34 +00:00
b81f934e8f Added server side image map support. 2024-01-08 13:42:22 +00:00
d81ac56076 Ported boolean attribute support. 2024-01-08 13:36:47 +00:00
42d4e1f238 Removed broken CONSTRAINT from perms table creation. 2023-12-16 18:51:17 +00:00
42671db410 Fixed markdown styling issues. 2023-12-15 12:56:08 +00:00
7acfa8b30e Updated highlight.js and created new code theme. 2023-12-15 12:47:01 +00:00
676810e143 Updated Sentry library to 4.0 in Misuzu. 2023-12-15 01:03:57 +00:00
262ba10694 Fixed error when trying to create a new role. 2023-12-02 02:57:46 +00:00
774494ac33 Fixed undefined variable. 2023-11-26 22:23:47 +00:00
a25621802e Libraries have been updated once more. 2023-11-20 19:10:47 +00:00
14f1c4d5e9 git.flash.moe -> patchii.net 2023-11-20 19:04:59 +00:00
d63a7f53a4 Updated source.md. 2023-11-09 20:58:56 +00:00
bbabce0e49 Supply super user status in auth data. 2023-11-07 14:38:53 +00:00
d221a1ce8f Return to purple. 2023-11-01 09:36:49 +00:00
2077099e7e moguu? 2023-10-21 23:54:41 +00:00
b221904866 Use SharpConfig format for the pre-database config. 2023-10-21 23:45:40 +00:00
727d0650ce Updated to use Syokuhou config library. 2023-10-20 22:29:28 +00:00
dc90787214 Fixed oversight on members list. 2023-10-18 10:16:32 +00:00
383af93c9c Fixed overly eager url encoding on the search page. 2023-10-18 10:11:21 +00:00
4e982333a3 Enable Spookii 2023-10-01 18:44:59 +00:00
ac66a3ecea Fixed chat routes being broken. 2023-09-11 20:36:20 +00:00
6bb9572913 Fixed legacy paths being too / tolerant. 2023-09-11 20:15:48 +00:00
c4f0976f2e Fixed router related explosions. 2023-09-11 20:10:37 +00:00
47c76b735e Fixed oversight on memberlist. 2023-09-11 19:19:19 +00:00
c62da933d1 Fixed syntax error in post.php. 2023-09-11 19:18:10 +00:00
56b71ba929 Fixed error when trying to view a non-existent topic when logged out. 2023-09-10 21:04:10 +00:00
28c97ef8ba Added Sentry error logging on the server side. 2023-09-10 20:46:58 +00:00
cbd84b8345 Removed unused pagination helper function. 2023-09-10 20:12:27 +00:00
c7f2cf79e7 Fixed CSRF tokens not being added to URLs that need them. 2023-09-10 20:02:11 +00:00
c6649f1ca8 Attempt at fixing forum issues. 2023-09-10 19:13:36 +00:00
48b767edd4 Added URL registry attributes. 2023-09-10 00:04:53 +00:00
c009c1691f Revert "チルノの日"
This reverts commit 2e270edc10.
2025-01-27 20:44:44 +00:00
2e270edc10 チルノの日 2023-09-08 23:07:37 +00:00
98d36dffff Moved various .php file redirects into the LegacyRouter. 2023-09-08 20:47:54 +00:00
c3827bceff Rewrote URL registry. 2023-09-08 20:40:48 +00:00
a94b905116 Added separate context class for forum stuff and split up handling of each object type. 2023-09-08 13:22:46 +00:00
0971240ab1 Cleaned up some things I missed. 2023-09-08 01:05:17 +00:00
485cbe38c9 Make PHPStan happy. 2023-09-08 00:54:19 +00:00
3309f75592 Split auth stuff off into own context. 2023-09-08 00:43:00 +00:00
0d0bd041a4 Route registration with attributes! 2023-09-08 00:13:30 +00:00
ef74057b5a Fixed incorrect type on latest forum post fetching result. 2023-09-07 20:53:19 +00:00
b2e30f4e49 Merge SharpChat permission set into the Misuzu permission system directly. 2023-09-06 20:44:28 +00:00
df970df252 Moved authentication related macros out of MisuzuContext. 2023-09-06 20:06:07 +00:00
92ff644290 Rewrote Satori recent forum post fetch. 2023-09-06 19:35:50 +00:00
ade2460b92 Moved user related stuff into its own context object. 2023-09-06 13:50:19 +00:00
618a3c31d9 Syntactic sugar for mass route registration. 2023-09-06 11:59:44 +00:00
cb6ef1e151 Fixed edit display threshold. 2023-09-06 11:32:13 +00:00
e81a032d75 Pluralise Views. 2023-09-06 11:19:54 +00:00
82043f14ff Fixed topic read status check. 2023-09-06 11:19:04 +00:00
fdafd9b129 Switch to Sasae. 2023-08-31 21:33:34 +00:00
84eef6dae9 Fixed static analysis detections. 2023-08-31 17:14:41 +00:00
d680b29f16 Moved render_info and render_error into Template class. 2023-08-31 15:59:53 +00:00
c0dbd36cbe Removed html_colour function, moved renamed DateCheck to Tools and moved the country names function into it and use new callable syntax. 2023-08-31 14:55:39 +00:00
4493cc1ab1 No longer rely on Referer header for the comments return URL. 2023-08-31 14:39:50 +00:00
60a5fb6804 Fixed leaderboard name not retaining the leading 0. 2023-08-31 00:54:17 +00:00
60e33edce9 Append total posts count at the end of the leaderboard. 2023-08-31 00:52:14 +00:00
d6ba0953fc Fixed oversight. 2023-08-31 00:40:07 +00:00
45522cedc7 Fixed missing use statement. 2023-08-31 00:38:20 +00:00
aed8c8b126 Added permission for displaying load timings in the footer. 2023-08-31 00:37:09 +00:00
a120cce5a0 Removed old database backend. 2023-08-31 00:31:11 +00:00
9911c51d9b Count profile stats using Index database backend. 2023-08-31 00:24:59 +00:00
2ea1018123 Added shitty search hack to users class. 2023-08-31 00:19:20 +00:00
2603a597df Added targeted permission recalculation.
Reduces reliance on full recalculation and actually makes it viable to do from within the browser.
2023-08-30 23:56:33 +00:00
c724c02c66 Moved validation methods into the new Users class. 2023-08-30 23:41:44 +00:00
349cc237c5 Rewrote permissions system. 2023-08-30 22:37:21 +00:00
0d90b6576b Fixed errors on profiles. 2023-08-28 14:45:32 +00:00
4bdc00fac3 Removed manage.php. 2023-08-28 13:45:36 +00:00
6b7d9b6637 Fixed user colours in comments sections. 2023-08-28 13:33:39 +00:00
99cc05f991 Fixed topic type string usage. 2023-08-28 01:41:13 +00:00
71463fefcc Fixed user colours not showing on forum posts. 2023-08-28 01:32:05 +00:00
265399d343 Rewrote forum backend. 2023-08-28 01:17:34 +00:00
f033e27ab5 Fixed emoticon ordering in chat. 2023-08-07 12:59:08 +00:00
ce8f9c0435 Fixed profile editing failing due to old argument. 2023-08-06 19:09:59 +00:00
4f56427501 Fixed error 500 when trying to log in to a non-existing user. 2023-08-06 18:22:39 +00:00
f7bc703b4a Fixed oversight regarding RNG ordering of user list. 2023-08-05 13:55:34 +00:00
f394f372c1 Made data source argument lists for News, Changelog, Comments and Emotes consistent with the rest. 2023-08-05 13:50:15 +00:00
758a052191 Fixed forum post deletion and editing. 2023-08-04 22:49:09 +00:00
c1bf19bc12 Converted all Misuzu style route handlers to Index style ones. 2023-08-04 20:51:02 +00:00
761fdb7f80 Fixed error 500 when viewing profiles as guest. 2023-08-04 17:44:37 +00:00
0a0e882950 Fixed search and updated collations of various fields to more appropriate ones. 2023-08-03 12:40:37 +00:00
b08de04b07 Fixed issue caused by used of dangling variable on sessions page. 2023-08-03 01:43:43 +00:00
9ae2a6a39b Changed the way msz_auth is handled.
Going forward msz_auth is always assumed to be present, even while the user is not logged in.
If the cookie is not present a default, empty value will be used.
The msz_uid and msz_sid cookies are also still upconverted for some reason but are no longer removed even though there's no active sessions that can possibly have those anymore.
As with the previous change, shit may be broken so report any Anomalies you come across, through flashii-issues@flash.moe if necessary.
2023-08-03 01:35:08 +00:00
e000c21987 Rewrote the user information class.
This one took multiple days and it pretty invasive into the core of Misuzu so issue might (will) arise, there's also some features that have gone temporarily missing in the mean time and some inefficiencies introduced that will be fixed again at a later time.
The old class isn't gone entirely because I still have to figure out what I'm gonna do about validation, but for the most part this knocks out one of the "layers of backwards compatibility", as I've been referring to it, and is moving us closer to a future where Flashii actually gets real updates.
If you run into anything that's broken and you're inhibited from reporting it through the forum, do it through chat or mail me at flashii-issues@flash.moe.
2023-08-02 22:12:47 +00:00
99353c4e70 Added server side stuff for Satori hooks. 2023-07-29 22:18:20 +00:00
d90d734c90 Some TOTP touch-ups. 2023-07-29 20:18:41 +00:00
9449af30ef Removed permissions stuff from the User object. 2023-07-29 18:15:30 +00:00
05d1beb267 Fixed error when news comments category doesn't exist somehow. 2023-07-29 18:01:41 +00:00
8a63906bdb Removed HasRankInterface. 2023-07-29 17:31:43 +00:00
4a59be7d9d Emit audit log upon impersonation. 2023-07-28 23:23:45 +00:00
cb40f1efce Added counters table for storing numbers of things statically. 2023-07-28 23:17:37 +00:00
35598a01a8 Allow non-super users to impersonate select users. 2023-07-28 21:20:19 +00:00
3dd854e383 Don't update last online time and ip address when impersonating. 2023-07-28 20:43:08 +00:00
eb4fc96b29 Added notice when there's no account logs to display. 2023-07-28 20:36:16 +00:00
7a3875d6da Hide roles section from settings if there's only one available. 2023-07-28 20:33:44 +00:00
4fe77f345c Use random alphabetic string instead hex bytes for session tokens. 2023-07-28 20:13:11 +00:00
10ec424a4f Rewrote Sessions backend. 2023-07-28 20:06:12 +00:00
a7b8b905b4 Cleaned up User and UserSession queries. 2023-07-28 15:07:30 +00:00
adf7a40e07 Fixed phpstan detections. 2023-07-27 23:49:55 +00:00
9dbfb0a396 Rewrote user role handling. 2023-07-27 23:26:05 +00:00
d2db06d0e4 Fixed data export. 2023-07-27 13:14:32 +00:00
5022222162 Pluralise user role relations table name. 2023-07-27 13:09:22 +00:00
25c87ada6b Rewrote TFA session code. 2023-07-27 12:44:50 +00:00
1d26871bc6 Fixed the manage index statistics causing a 500 because the old warnings table is Gone. 2023-07-26 22:57:03 +00:00
d71990f30e Fixed warning deletion. 2023-07-26 22:48:47 +00:00
a97955b7e2 Split Sharp Chat kick and ban permissions based on the Misuzu warnings and bans permissions. 2023-07-26 22:46:35 +00:00
d31cc70128 Rewrote user warnings backend. 2023-07-26 22:43:50 +00:00
4318c3fbe1 Expiration -> Expires 2023-07-26 18:24:49 +00:00
60cc6643a0 Added new banning system.
it actually works and isn't confusing this time around!
2023-07-26 18:19:48 +00:00
42560a62e6 Pluralise. 2023-07-26 11:56:06 +00:00
1ff9b11b97 Fixed typo that would cause things to fail. 2023-07-26 11:54:49 +00:00
49b3062dbe Fixed gross misalignment. 2023-07-25 19:03:48 +00:00
92f18bfe9a Redesigned news post preview information section. 2023-07-25 19:02:00 +00:00
eb30b6b718 Fixed error 500 when trying to view a non-existent profile. 2023-07-25 15:03:25 +00:00
26d5abffe5 Allow moderators to view a stripped down version of the user page in the broom closet. 2023-07-25 14:52:51 +00:00
96f9ea7271 Added new moderator notes system. 2023-07-25 14:40:31 +00:00
8c52338751 Removed the concept of silencing.
Nothing really implemented it properly or checked for it and the places that did check just handled it as a slightly softer ban.
It's pretty obvious that the existence of this feature was directly taken from osu! where the differentation between a ban and a silence probably makes more sense, though even there Silences are just non-permanent bans, so like why does this exist lol?
Well, it doesn't anymore! Hopefully chat will upgrade successfully because I let it get 18 commits behind :D
2023-07-23 21:47:15 +00:00
f382e1f210 Attempt 2 at fixing the profile fields issue (this one actually fixes the issue!) 2023-07-22 21:25:51 +00:00
1dffd30136 Rewrote password recovery token storage using new DB backend. 2023-07-22 21:20:03 +00:00
033abfd150 Fixed error 500 on profiles when filling certain fields in specific conditions. 2023-07-22 20:54:52 +00:00
4243d50abd Fixed type on getUserId in LoginAttemptInfo. 2023-07-22 17:27:42 +00:00
a894db2052 Rewrite login attempts log to use new database backend. 2023-07-22 16:37:57 +00:00
20c528a88c Normalised custom exception usage in user classes.
Also updated the Index library to include the MediaType fix.
2023-07-22 15:02:45 +00:00
6414d1290a Use the Index DbStatementCache implementation. 2023-07-22 14:00:51 +00:00
2c02a3594f Use the Index DbTools version for list prepare thing. 2023-07-22 13:54:42 +00:00
d559df61da Updated Index Serialiser usage. 2023-07-21 21:56:09 +00:00
7831da9f70 Added phpstan as a dev dependency. 2023-07-21 19:38:54 +00:00
45900202dc Removed local config plugin and fixed Index info pages. 2023-07-21 19:30:28 +00:00
84dc4ee873 Oops it's all white! 2023-07-21 19:17:57 +00:00
f292e64322 Updated project licence to BSD3CC and import Index through Composer. 2023-07-21 18:58:37 +00:00
f628c8ad76 Just use Composer for DeviceDetector.
It was initially my goal to lessen use of Composer, but given I just switched to using NPM packages for asset compilation, it's a little bit silly to try and keep that going.
2023-07-21 16:12:08 +00:00
52aa43dd94 Determine client info on insert rather than on retrieve for speed improvements.
i suppose device detect only ever expects to analyse a single string at once given its made for matomo so it on the slower side for multiple dingusses
2023-07-21 12:47:59 +00:00
1094f8dc67 Fixed error 500 on logs and sessions pages because of dead library. 2023-07-21 11:33:27 +00:00
d870a386cf Improved profile fields code. 2023-07-20 19:36:43 +00:00
aefc4ddb9c Upgrade to PHP 8.2. 2023-07-19 19:10:20 +00:00
f5d8914991 Removed lockdown feature for now. 2023-07-19 19:04:57 +00:00
a09c8b7ef6 Restructured public folder and initialisation process. 2023-07-19 19:03:53 +00:00
67b41379e5 Display full join and seen dates on hover. 2023-07-19 18:18:27 +00:00
2df94ba0f6 Minor members list redesign. 2023-07-19 18:14:04 +00:00
283044b3b2 Removed overbearing global shadow. 2023-07-19 14:43:49 +00:00
b41df8ffbe Removed leftover abstract class. 2023-07-19 14:34:02 +00:00
6a32119c8a Fixed whatever the date formatter was smoking. 2023-07-18 23:19:19 +00:00
d938ff74c1 Removed server-side relative time. 2023-07-18 23:12:47 +00:00
f1fdf5c792 Removed unnecessary checks from URL formatter. 2023-07-18 22:36:07 +00:00
540b886b18 Removed old formats of and unused SharpChat endpoints. 2023-07-18 22:33:13 +00:00
31cb6ab82d Fixed various errors and oversights caught by phpstan. 2023-07-18 22:24:23 +00:00
8339892559 Config class overhaul. 2023-07-18 21:48:44 +00:00
2b92d00b4b Removed timeago library. 2023-07-17 20:14:21 +00:00
bd9f59f998 Fixed account data export memory usage. 2023-07-17 19:28:13 +00:00
0930fde6dd Rewrote audit log on new database backend. 2023-07-17 17:43:17 +00:00
271fde9939 Fixed Javascript not working because it's written very poorly. 2023-07-17 14:44:09 +00:00
ace24c8eee Use Node for asset building instead of building on the fly every time (feat. minification!) 2023-07-15 23:58:17 +00:00
ec74f74624 Rewrote most of the comments backend.g 2023-07-15 23:58:17 +00:00
bca3286c1a Fixed some routing oversights. 2023-07-15 17:45:39 +00:00
7d0e907fa8 Show Index and PDO query counts separately in the footer. 2023-07-15 17:15:40 +00:00
f5d14fac14 Rewrote the news backend. 2023-07-15 17:02:46 +00:00
02e80cde61 Fixed various other oversights. 2023-07-15 02:14:39 +00:00
ce01602fb0 Fixed error on main page. 2023-07-15 02:08:13 +00:00
b6c9c6c627 Rewrote the Changelog code. 2023-07-15 02:05:49 +00:00
c05ec36e60 Added more elegant method for statement caching. 2023-07-14 20:26:38 +00:00
5868a6c38c Fixed leap year birthdays without a year set. 2023-07-12 23:08:35 +00:00
142ccc3f01 Rewrote backend for emoticons.
Manage actually works this time!!!
2023-07-12 21:52:55 +00:00
849b38cbea Fixed possible NULL in CSRF check. 2023-07-12 19:14:40 +00:00
50fac1e585 Use the Index DSN to create the PDO based DB instance. 2023-07-11 22:45:23 +00:00
163ff95cdf Use Index for CSRF protection tokens. 2023-07-11 22:13:56 +00:00
5d62e6e741 CSRF and URL cleanup. 2023-07-11 20:51:24 +00:00
d69f7c2abf Rely on NGINX GeoIP2 module for country code lookup. 2023-07-11 00:25:43 +00:00
911c12a3b0 Updated info pages. 2023-07-10 23:07:48 +00:00
839fd4e7f1 Switched to a tools directory for commands. 2023-07-10 22:52:30 +00:00
a4059de89a Get rid of unused JSON stuff. 2023-07-10 20:12:20 +00:00
1bd12b9a0b Fixed country name not having a value for XX or any other fallback. 2023-07-05 23:12:44 +00:00
f9edc5b9cf Switched to Index byte formatter and adjusted max file sizes. 2023-07-05 23:09:28 +00:00
46114b3642 Added local country list instead. 2023-07-05 02:23:34 +00:00
070b788038 Cleaned up various utility functions. 2023-07-05 01:33:12 +00:00
b797e95d75 Apply user colour to header rather than username on profiles. 2023-07-03 13:53:58 +00:00
aa8f70db12 Fixed birthdate setting not working (did it ever work???). 2023-05-26 18:41:21 +00:00
24e4ab980c Updated authentication token format. 2023-05-21 18:15:04 +00:00
8bfa2def78 Fixed Insert button for uploads inserting with the wrong markup format if the setting was changed after upload. 2023-05-04 17:20:56 +00:00
c798ce5d61 Added ability to add redirects to deleted topic ids. 2023-04-30 00:18:14 +00:00
01c43e38d8 Fixed oversights that occur because of the empty username. 2023-04-29 21:57:21 +00:00
ac8000f8c8 Removed space inserted before embed tags inserted by EEPROM. 2023-03-15 10:58:55 +00:00
4358f0145b Removed quirky newline. 2023-03-11 22:28:57 +00:00
86c597edae Gave posts a 1 minute cooldown for edits without being marked as edited. 2023-03-11 22:28:10 +00:00
3ea078df34 Removed Twitter integrations. 2023-03-09 21:38:03 +00:00
da1d3184bc Added rudimentary EEPROM file uploading support to the forum post editor. 2023-03-09 21:05:37 +00:00
3d438ea36f Added editor buttons for video and audio in markdown mode. 2023-03-09 16:27:43 +00:00
ede0ce0acc Updated composter packages. 2023-03-09 16:23:42 +00:00
622a9c64ae Allow media linking without https: or http: prefix on forum. 2023-03-09 16:18:52 +00:00
b141070690 Fixed smart event. 2023-02-24 18:36:32 +00:00
a99c8232b1 Added h1 thru h6 bbcodes. 2023-02-12 03:50:08 +00:00
1f6eb44ab6 Added most active forum category and topic to profiles. 2023-02-10 09:04:15 +00:00
d2f9328979 Sharp Chat interop updates. 2023-02-08 00:06:15 +00:00
9c6c7d9786 Made Twitter and Chat link targets in the header configurable. 2023-01-31 16:21:19 +00:00
bc8e7f3f43 Forum post text style fixes. 2023-01-29 21:34:22 +00:00
a4ca778428 Enabled video and audio embeds in markdown. 2023-01-29 21:06:03 +00:00
ffc794886c Audio embed previews (no player yet). 2023-01-29 20:29:20 +00:00
74ac42a9ba constipation moment 2023-01-29 03:35:45 +00:00
52e948aadb Improved video embed handling. 2023-01-29 01:51:54 +00:00
dc43ac47f8 Fixed various video embedding bugs. 2023-01-26 22:51:33 +00:00
b23a87ef04 Removed will-change statements because buggy in Chrome. 2023-01-26 08:49:19 +00:00
381afe28c4 Fixed videos not embedding in the posting preview. 2023-01-25 23:03:38 +00:00
e6496378ea Complete revamp of the forum video bbcode.
Rather than blindly embedding everything, video metadata is first requested through the URL metadata lookup service.
This slightly protects you from automatically connecting to third party servers and also vastly improves page loading performance in tandem with caching on the server.
A similar implementation will eventually make its way to the audio bbcode and will also be worked in the img bbcode somehow.
This will then eventually make it possible to embed audio and video in markdown the same way you'd embed an image.
2023-01-25 22:33:59 +00:00
249294aa0f Fixed 'view full profile' thing showing up on non-existent users while logged out. 2023-01-07 04:47:31 +00:00
7365a882ad Fixed inability to log in with two factor authentication. 2023-01-07 04:46:49 +00:00
67aeb9a70a Updated database migration system to use the Index methods. 2023-01-07 04:15:19 +00:00
59a09cf4ac Use interface constants instead of a dedicate enum class for config types. 2023-01-06 20:50:41 +00:00
5f0e94350f Changed name of context class and global variable. 2023-01-06 20:35:03 +00:00
82129ce9e6 Updated handler classes to use the new IRouter interface. 2023-01-06 20:22:03 +00:00
15506da06b Removed unused tester permission. 2023-01-06 00:03:29 +00:00
ae8361751c Store forum permission types as numbers rather than bit shifts. 2023-01-06 00:02:40 +00:00
86701122d0 Removed error to exception conversion in Misuzu (handled in Index). 2023-01-05 23:54:27 +00:00
587e341c59 Updates to GeoIP lookup stuff. 2023-01-05 20:03:26 +00:00
1905606276 Updated composer libraries. 2023-01-05 18:35:07 +00:00
bc03c0756c Remove IPAddress::remote and all implicit resolving of the request remote address. 2023-01-05 18:33:03 +00:00
ce392055b8 Removed IPAddress methods only used by the blacklist. 2023-01-05 17:15:26 +00:00
c0e5e8c9ed Removed IP blacklist for now. 2023-01-05 15:56:36 +00:00
86e465797d Rewrote Twitter connection (v1.1 -> v2). 2023-01-05 03:20:31 +00:00
e386f2499c Fixed error when trying to use the forum posting form. 2023-01-03 00:31:39 +00:00
a280971e1e Rewrote avatar element contruction as Twig macro. 2023-01-03 00:10:28 +00:00
ccdb6c7c29 Updated copyright year. 2023-01-02 23:52:40 +00:00
901add2ce9 Replaced Misuzu Colour library with the Index ones. 2023-01-02 23:48:04 +00:00
6b64968afe Removed more XHR leftovers. 2023-01-02 23:12:23 +00:00
70a285aa29 Removed XHR stuff from comments handler. 2023-01-02 22:59:24 +00:00
a2a3c6a73c "Fixed" user editor in the broom closet. 2023-01-02 20:09:38 +00:00
08b6358cba Pruned a lot of existing Javascript, comments will receive and overhaul later. 2023-01-02 20:07:55 +00:00
758ca53bba Fixed Mark As Read on forum index not working. 2023-01-02 19:50:33 +00:00
c5201acfec Updated contact info. 2023-01-02 18:41:47 +00:00
b881a9fea9 Fixed error when trying to edit profile. 2023-01-02 03:27:20 +00:00
0a43ffbe36 Fixed oversight from removing the proxy stuff. 2023-01-01 20:37:15 +00:00
22ac2e05c7 Use Git HEAD hash for the template cache folder name. 2023-01-01 20:33:32 +00:00
bec238dc97 Removed unused built-in media proxy. 2023-01-01 20:27:25 +00:00
5631f464d2 Restructured config handler. 2023-01-01 20:23:53 +00:00
46b30d5470 Index updates + floatval, intval -> casts. 2023-01-01 19:06:01 +00:00
d43cb6f794 Removed unfinished leftovers of priority voting and polls. 2023-01-01 05:01:18 +00:00
f62c852143 Forgot to CTRL+S this file, oops! 2023-01-01 03:50:41 +00:00
ca814279f1 Removed support for rolling back database migrations. 2023-01-01 03:42:18 +00:00
8245bc0a7b Added Flappyzor hacks. 2023-01-01 01:53:29 +00:00
e8d07f747d Make two factor code input field trigger a numeric keyboard on phones. 2022-12-12 15:49:23 +00:00
3ffcd79ed3 Updated repository URL in the footer. 2022-09-13 14:08:45 +00:00
5891a748eb Updated contact page repositories. 2022-08-26 00:36:14 +00:00
c02a5a0563 Updated Index repository URL. 2022-08-26 00:30:24 +00:00
88b3acf08e Fixed error in render_info macro. 2022-08-11 23:28:45 +00:00
33bf839689 Updated sources list on the contact page. 2022-07-16 23:26:23 +00:00
64bda9339a Allow hiding values of settings in the overview. 2022-07-05 00:36:36 +00:00
fdb200b36a Added site configuration editor. 2022-07-04 23:25:58 +00:00
3dafc519d8 Allow specifying a hash key in the config rather than a path for Sharp Chat authentication. 2022-07-04 23:21:05 +00:00
f2fd3ff66f Fixed emoticons manage panel. 2022-07-04 20:39:50 +00:00
2f6552aaea Updated .gitignore. 2022-07-04 16:42:22 +00:00
78dd9ae5bc Fixed error in dev box setup script. 2022-07-04 15:25:36 +00:00
34bfb49a38 More cleanup. 2022-06-10 20:48:32 +02:00
7d6b94294f Converted Sharp Chat routes to Index. 2022-06-10 20:26:24 +02:00
6e650923d8 Accounted for stupid behaviour. 2022-06-07 22:47:26 +02:00
c750591782 Fixed user not found error page. 2022-06-06 18:30:02 +02:00
0339bc3ec9 Removed special case from about page length limit. 2022-06-06 17:10:11 +02:00
3c518c48e6 Fixed cookies not being set correctly when running on a non-standard port. 2022-06-06 16:57:45 +02:00
ba4f03cefa Fixed GeoIP lookup causing an exception when no MMDB is available. 2022-06-06 16:42:38 +02:00
01b3f41742 Update Vagrant setup script. 2022-06-04 03:38:49 +02:00
dbb67262e5 Fixed an issue. 2022-04-27 23:24:38 +00:00
95610cb3ef Fixed stupid conversions. 2022-03-19 19:53:44 +00:00
59edead442 Fixed avatar changing issue. 2022-03-02 23:15:36 +00:00
469b4f7859 Replace more things with Index implementations, also bump QR Code library. 2022-03-01 23:14:03 +00:00
ef4921949b Removed old redirect handlers. 2022-02-28 19:52:53 +00:00
56911715fe Added root context class, moved routes into it and removed _sockchat.php redirect. 2022-02-28 19:47:50 +00:00
3bc18f3d2c Removed MisuzuException and use RuntimeException as base. 2022-02-28 01:55:36 +00:00
22bc5f4168 Fixed JSON content type issue. 2022-02-27 17:37:27 +00:00
a18b3244e9 Fixed 'infinity undefineds'. 2022-02-27 17:21:57 +00:00
ac30c42285 Fixed issues with chat authentication. 2022-02-27 17:17:55 +00:00
881426e950 First bits of Indexification. 2022-02-26 01:27:52 +00:00
21526491c6 Added sample data generation based on Markov chaining. 2022-02-24 23:49:37 +00:00
029e996b58 Added robots.txt to gitignore (oops). 2022-02-19 22:44:57 +00:00
efa7e048d8 Removed robots.txt from the repo. 2022-02-19 22:43:21 +00:00
d55585372e Ran PHPStan over everything and attempted some fixes. 2022-02-19 19:03:00 +00:00
3a118fef15 Update TOTP.php 2022-02-18 02:50:41 +01:00
ddadb1d068 More dumbass fixes. 2022-02-15 22:39:29 +00:00
fef958b10b Trim call fix. 2022-02-15 22:37:18 +00:00
0da24c0aaa Fixed compatibility issues with PHP 8.1. 2022-02-15 22:28:49 +00:00
2c57107eb9 Use Symfony Mailer instead of SwiftMailer because they killed the latter for no reason. 2022-02-15 22:14:38 +00:00
f9181fc6f9 Surprisingly painless upgrade to Twig 3.x. 2022-02-15 21:21:19 +00:00
96e266b1fc Moved profile check into Misuzu. 2022-02-14 21:26:30 +00:00
a86500ad7a Yeah, I'm somewhat of an idiot myself. 2022-02-14 21:11:12 +00:00
e5dcd654d3 Some adjustments. 2022-02-14 21:04:34 +00:00
a28b5b275c An attempt at adding the token fetching thing to Misuzu. 2022-02-14 20:52:09 +00:00
647cc0061f 88x31 courtesy of geb 2022-02-13 03:36:15 +01:00
dependabot[bot]
0dcf1095bb Bump twig/twig from 2.14.6 to 2.14.11
Bumps [twig/twig](https://github.com/twigphp/Twig) from 2.14.6 to 2.14.11.
- [Release notes](https://github.com/twigphp/Twig/releases)
- [Changelog](https://github.com/twigphp/Twig/blob/v2.14.11/CHANGELOG)
- [Commits](https://github.com/twigphp/Twig/compare/v2.14.6...v2.14.11)

---
updated-dependencies:
- dependency-name: twig/twig
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-02-11 02:28:32 +00:00
64b4744352 apparently it was a double OOPS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2022-02-10 01:20:41 +01:00
2a79184bdb OOPS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2022-02-10 01:18:06 +01:00
6535f8c787 Updated LICENSE format. 2022-02-10 01:16:06 +01:00
e37ec29123 Make script enable debug mode. 2022-01-17 03:16:27 +01:00
1bca6b4692 Forgot a couple, oops! 2022-01-17 03:06:45 +01:00
c6cc2ecc67 Attempt to fix permissions on Unix-like systems. 2022-01-17 03:05:45 +01:00
3bc4de431c Attempt to fix .sh line endings. 2022-01-17 02:45:38 +01:00
8df4166520 Added Vagrant config and script for quick setting up a virtual development environment. 2022-01-17 02:37:46 +01:00
fb77a936f5 Removed leftovers from chat token system. 2022-01-13 00:59:35 +01:00
4a3a28629b So long, spookiness. 2021-10-31 18:22:46 +01:00
deb4dc1089 Enable spookiness. 2021-10-23 19:26:01 +02:00
8c9ec82a56 I give up. 2021-09-17 20:53:24 +00:00
a363d8d574 Fixed cookie getting lost (attempt). 2021-09-17 20:51:18 +00:00
51bc99e454 Removed chat token creation. 2021-09-17 20:45:20 +00:00
6d3a24c723 Turned the air conditioner back off. 2021-09-10 13:57:07 +00:00
8bd006a576 Turned on the air conditioner. Don't catch a cold! 2021-09-08 20:59:37 +00:00
f4ca3edddf Fixed header disappearing at 800px width. 2021-09-01 16:08:59 +00:00
b7a14de9df Registration adjustments. 2021-08-28 20:36:24 +00:00
50dee8eeb4 Removed the existing, broken follow system. 2021-08-28 20:25:01 +00:00
813d3421bb Landing page redesign. 2021-08-28 17:06:14 +00:00
6084e5ba5c Update composer libraries. 2021-08-04 20:50:28 +00:00
2929adcc03 Removed tracking code. 2021-07-31 04:44:01 +00:00
70e340be34 Moved webhook handler for changelog into Misuzu. 2021-07-30 22:06:11 +00:00
284230a84c Fixed error on profile when non-existent user is specified. 2021-07-30 22:00:45 +00:00
6d72906851 Fixed msz file mode. 2021-07-30 20:29:03 +00:00
9de494e671 Added user resolve endpoint for Sock Chat. 2021-07-30 22:27:47 +02:00
1589be2245 Update LICENSE 2021-07-10 20:12:09 +02:00
71e905c9a8 Added ban management endpoints for the chat. 2021-03-02 19:40:17 +00:00
b7ff4f6a6e Optimise image assets. 2020-11-03 23:43:57 +01:00
318b3f121b spoopy no more 2020-11-02 20:46:32 +01:00
9385abed97 Added Moon flag. 2020-10-06 22:07:47 +02:00
daea16ee8c Fixed syntax error in forum/post.php. 2020-10-03 03:17:06 +02:00
910 changed files with 55300 additions and 28179 deletions

1
.browserslistrc Normal file
View file

@ -0,0 +1 @@
last 5 versions, not dead

View file

@ -6,3 +6,6 @@ insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 4
[Makefile]
indent_style = tab

41
.env.example Normal file
View file

@ -0,0 +1,41 @@
# Enable debug mode
# Useful for debugging
MSZ_DEBUG=1
# Database connection setting
# This uses the Index library's DSN syntax
# Currently Misuzu only supports MariaDB, or Null of course since that does nothing
#
# For normal TCP connection you can use the following syntax:
#DATABASE_DSN="mariadb://username:password@hostname/dbname?charset=utf8mb4"
#
# For a UNIX socket connection you can use the following syntax:
#DATABASE_DSN="mariadb://username:password@:unix:/dbname?socket=/path/to/mysqld.sock&charset=utf8mb4"
#
# And here's your unsensible default:
DATABASE_DSN="null:"
# Sentry error reporting setting
# I have not idea this works, just shove the value Sentry gives you in here.
# You can also leave it commented.
#SENTRY_DSN="https://6e41e3a2507d1542fd1e9aaf54f05d87@o4505858016870400.ingest.sentry.io/4505858023751680"
# Domain roles
# This assigns what domain has what role, domains can also have multiple roles!
# Pairs are split by ;, domain and role pairs are split by =, roles are split by , and if you want a prefix use :
# The example below maps everything to localhost for development.
# But to make things more understandable, the value for Flashii is also included
#DOMAIN_ROLES="flashii.net=main; fii.moe=redirect"
DOMAIN_ROLES="localhost=main,redirect:/go"
# Local storage path
# This determines where uploaded files are stored. If left unset, the storage folder in the project tree will be used.
#STORAGE_PATH_LOCAL="/path/to/storage"
# Remote storage path
# Path on which the storage folder is exposed to the web for NGINX.
#STORAGE_PATH_REMOTE="/_storage"
# Template cache directory
# Writeable directory path to which template files are cached.
#TEMPLATE_CACHE="/tmp/msz-tpl-cache"

35
.gitignore vendored
View file

@ -1,28 +1,63 @@
# Assets
/public/assets
/assets/current.json
# Libraries
/vendor
/node_modules
/npm-debug.log
/yarn-error.log
/lib/index-dev
/composer.local.json
# Configuration
/.env
/config/config.cfg
/config/github.cfg
/config/config.ini
/config/github.ini
/config/keys/*.pem
/.debug
/.migrating
# Storage
/storage/*
!/storage/.gitkeep
/store
# OS specific
[Tt]humbs.db
[Dd]esktop.ini
.DS_Store
# IDE specific
.vscode/
.vs/
.idea/
# Vagrant things
.vagrant/
/devel/nginx/dhparam.pem
/devel/nginx/misuzu.crt
/devel/nginx/misuzu.key
# Compiled/copied assets
/public/js
/public/css
/public/webfonts
/assets/typescript/*.d.ts
/public/errors.css
/public/error-*.html
# Google
/public/robots.txt
# Well known
/public/.well-known
# moguu?
/public/moguu.swf
/public/moguu.html
# admin
/public/admin

221
LICENSE
View file

@ -1,201 +1,30 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Copyright (c) 2017-2025, flashwave <me@flash.moe>
All rights reserved.
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
Redistribution and use in source and binary forms, with or without
modification, are permitted (subject to the limitations in the disclaimer
below) provided that the following conditions are met:
1. Definitions.
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright (c) 2017-2019, flashwave <me@flash.moe>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

58
Makefile Normal file
View file

@ -0,0 +1,58 @@
PHP_EXE := $(shell which php8.4)
COMPOSER_EXE := $(shell which composer)
NODE_EXE := $(shell which node)
NPM_EXE := $(shell which npm)
SUDO_EXE := $(shell which sudo)
WWW_USER := www-data
BUILD_EXE := build.js
ENV_FILE := .env
TOOLS_DIR := tools
VENDOR_DIR := vendor
all: install migrate clear-cache build cron
install: composer_install npm_install
composer_install:
${PHP_EXE} ${COMPOSER_EXE} install
npm_install:
${NPM_EXE} ci
update: composer_update npm_update
composer_update:
${PHP_EXE} ${COMPOSER_EXE} update
npm_update:
${NPM_EXE} update --save
migrate:
${SUDO_EXE} -u ${WWW_USER} ${PHP_EXE} ${TOOLS_DIR}/migrate
clear-cache:
${SUDO_EXE} -u ${WWW_USER} ${PHP_EXE} ${TOOLS_DIR}/nuke-tpl-cache
cron:
${SUDO_EXE} -u ${WWW_USER} ${PHP_EXE} ${TOOLS_DIR}/cron slow
build:
${NODE_EXE} --env-file-if-exists ${ENV_FILE} ${BUILD_EXE}
rebuild-css:
${NODE_EXE} --env-file-if-exists ${ENV_FILE} ${BUILD_EXE} css
rebuild-js:
${NODE_EXE} --env-file-if-exists ${ENV_FILE} ${BUILD_EXE} js
rebuild-twig:
${NODE_EXE} --env-file-if-exists ${ENV_FILE} ${BUILD_EXE} twig
analyse:
${PHP_EXE} ${VENDOR_DIR}/bin/phpstan
tag: analyse
${PHP_EXE} ${TOOLS_DIR}/create-tag
.PHONY: all update composer npm build rebuild-css rebuild-js rebuild-twig migrate clear-cache cron analyse tag

View file

@ -2,6 +2,6 @@
> Misuzu can and will steal your lunch money.
## Requirements
- PHP 7.4
- MariaDB 10.4
- PHP 8.4
- MariaDB 11.4
- [Composer](https://getcomposer.org/)

1
VERSION Normal file
View file

@ -0,0 +1 @@
20250616.1

View file

@ -1,6 +0,0 @@
# Misuzu Assets
Subdirectories of the `css` and `js` folder are accessible through the web as `example.com/assets/<subdirectory>.<directory>`.
Meaning `/assets/js/misuzu` is accessible as `/assets/misuzu.js`.
Files are concatenated recursively, files first then directories in alphabetical order.
Use `_` prefixes to raise things up.

View file

@ -0,0 +1,36 @@
.msz-loading {
display: flex;
justify-content: center;
flex-direction: column;
min-width: var(--msz-loading-container-width, calc(var(--msz-loading-size, 1) * 100px));
min-height: var(--msz-loading-container-height, calc(var(--msz-loading-size, 1) * 100px));
}
.msz-loading-inline {
display: inline-flex;
min-width: 0;
min-height: 0;
}
.msz-loading-frame {
display: flex;
justify-content: center;
flex: 0 0 auto;
}
.msz-loading-icon {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
gap: var(--msz-loading-gap, calc(var(--msz-loading-size, 1) * 1px));
margin: var(--msz-loading-margin, calc(var(--msz-loading-size, 1) * 10px));
}
.msz-loading-icon-block {
background: var(--msz-loading-colour, currentColor);
width: var(--msz-loading-width, calc(var(--msz-loading-size, 1) * 10px));
height: var(--msz-loading-height, calc(var(--msz-loading-size, 1) * 10px));
}
.msz-loading-icon-block-hidden {
opacity: 0;
}

View file

@ -0,0 +1,33 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
position: relative;
}
html, body {
width: 100%;
height: 100%;
}
[hidden],
.hidden {
display: none !important;
visibility: hidden !important;
}
:root {
--font-regular: Inter, 'Zen Kaku Gothic New', sans-serif;
--font-monospace: 'Victor Mono', monospace;
font-feature-settings: 'calt' 1, 'dlig' 1, 'ss01' 1;
font-optical-sizing: auto;
}
@supports (font-variation-settings: normal) {
:root {
--font-regular: InterVariable, 'Zen Kaku Gothic New', sans-serif;
}
}
@include loading.css;
@include perf.css;

101
assets/common.css/perf.css Normal file
View file

@ -0,0 +1,101 @@
.msz-perfs {
position: fixed;
bottom: 4px;
left: 4px;
display: flex;
gap: 2px;
flex-direction: column-reverse;
align-items: flex-start;
opacity: .5;
}
.msz-perfs-right {
left: initial;
right: 4px;
}
.msz-perfs:hover {
opacity: 1;
}
.msz-perf {
background-color: #111d;
color: #fff;
font-family: var(--font-monospace);
font-feature-settings: 'ss07' 1;
font-size: 12px;
line-height: 20px;
padding: 4px 8px;
border-radius: 6px;
}
.msz-perfs:hover .msz-perf {
backdrop-filter: blur(10px);
}
.msz-perf-number {
color: #fff;
}
.msz-perf-unit {
color: #888;
}
.msz-perf-header {
display: flex;
flex: 0 0 auto;
gap: 4px;
}
.msz-perf:hover .msz-perf-header {
border-bottom: 1px solid #888;
margin-bottom: 2px;
}
.msz-perf-type {
flex: 0 0 auto;
font-weight: 700;
min-width: 60px;
}
.msz-perf-type-navigation {
color: #f0f;
}
.msz-perf-type-other {
color: #0ff;
}
.msz-perf-target {
flex: 1 0 auto;
min-width: 200px;
}
.msz-perf-target-host,
.msz-perf-target-path,
.msz-perf-target-query {
display: inline-block;
}
.msz-perf-target-host,
.msz-perf-target-query {
color: #888;
}
.msz-perf-total {
flex: 0 0 auto;
min-width: 80px;
text-align: right;
}
.msz-perf-timings {
display: none;
border-collapse: collapse;
width: 100%;
}
.msz-perf:hover .msz-perf-timings {
display: table;
}
.msz-perf-timing-name {
font-weight: 700;
min-width: 60px;
}
.msz-perf-timing-comment {
color: #888;
}
.msz-perf-timing-duration {
min-width: 80px;
text-align: right;
}

27
assets/common.js/array.js Normal file
View file

@ -0,0 +1,27 @@
const $arrayRemoveAt = function(array, index) {
array.splice(index, 1);
};
const $arrayRemoveValue = function(array, item) {
let index;
while(array.length > 0 && (index = array.indexOf(item)) >= 0)
$arrayRemoveAt(array, index);
};
const $arrayRemoveAny = function(array, predicate) {
let index;
while(array.length > 0 && (index = array.findIndex(predicate)) >= 0)
$arrayRemoveAt(array, index);
};
const $arrayShuffle = function(array) {
if(array.length < 2)
return;
for(let i = array.length - 1; i > 0; --i) {
const j = Math.floor(Math.random() * (i + 1));
const tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
};

24
assets/common.js/csrf.js Normal file
View file

@ -0,0 +1,24 @@
#include html.js
const $csrf = (() => {
let elem;
const getElement = () => {
if(elem === undefined)
elem = $query('meta[name="csrf-token"]');
return elem;
};
return {
get token() {
return getElement()?.content ?? '';
},
set token(token) {
if(typeof token !== 'string')
throw 'token must be a string';
const elem = getElement();
if(elem instanceof HTMLMetaElement)
elem.content = token;
},
};
})();

157
assets/common.js/html.js Normal file
View file

@ -0,0 +1,157 @@
const $id = document.getElementById.bind(document);
const $query = document.querySelector.bind(document);
const $queryAll = document.querySelectorAll.bind(document);
const $text = document.createTextNode.bind(document);
const $insertBefore = function(target, element) {
target.parentNode.insertBefore(element, target);
};
const $appendChild = function(element, child) {
switch(typeof child) {
case 'undefined':
break;
case 'string':
element.appendChild($text(child));
break;
case 'function':
$appendChild(element, child());
break;
case 'object':
if(child === null)
break;
if(child instanceof Node)
element.appendChild(child);
else if(child?.element instanceof Node)
element.appendChild(child.element);
else if(typeof child?.toString === 'function')
element.appendChild($text(child.toString()));
break;
default:
element.appendChild($text(child.toString()));
break;
}
};
const $appendChildren = function(element, ...children) {
for(const child of children)
$appendChild(element, child);
};
const $removeChild = function(element, child) {
switch(typeof child) {
case 'function':
$removeChild(element, child());
break;
case 'object':
if(child === null)
break;
if(child instanceof Node)
element.removeChild(child);
else if(child?.element instanceof Node)
element.removeChild(child.element);
break;
}
};
const $removeChildren = function(element) {
while(element.lastChild)
element.removeChild(element.lastChild);
};
const $fragment = function(props, ...children) {
const fragment = document.createDocumentFragment();
$appendChildren(fragment, ...children);
return fragment;
};
const $element = function(type, props, ...children) {
if(typeof type === 'function')
return new type(props ?? {}, ...children);
const element = document.createElement(type ?? 'div');
if(props)
for(let key in props) {
const prop = props[key];
if(prop === undefined || prop === null)
continue;
switch(typeof prop) {
case 'function':
if(key.substring(0, 2) === 'on')
key = key.substring(2).toLowerCase();
element.addEventListener(key, prop);
break;
case 'object':
if(prop instanceof Array) {
if(key === 'class')
key = 'classList';
const attr = element[key];
let addFunc = null;
if(attr instanceof Array)
addFunc = attr.push.bind(attr);
else if(attr instanceof DOMTokenList)
addFunc = attr.add.bind(attr);
if(addFunc !== null) {
for(let j = 0; j < prop.length; ++j)
addFunc(prop[j]);
} else {
if(key === 'classList')
key = 'class';
element.setAttribute(key, prop.toString());
}
} else {
if(key === 'class' || key === 'className')
key = 'classList';
let setFunc = null;
if(element[key] instanceof DOMTokenList)
setFunc = (ak, av) => { if(av) element[key].add(ak); };
else if(element[key] instanceof CSSStyleDeclaration)
setFunc = (ak, av) => {
if(ak.includes('-'))
element[key].setProperty(ak, av);
else
element[key][ak] = av;
};
else
setFunc = (ak, av) => { element[key][ak] = av; };
for(const attrKey in prop) {
const attrValue = prop[attrKey];
if(attrValue)
setFunc(attrKey, attrValue);
}
}
break;
case 'boolean':
if(prop)
element.setAttribute(key, '');
break;
default:
if(key === 'className')
key = 'class';
element.setAttribute(key, prop.toString());
break;
}
}
$appendChildren(element, ...children);
return element;
};

View file

@ -0,0 +1,183 @@
const MszLoadingIcon = function() {
const element = <div class="msz-loading-icon"/>;
for(let i = 0; i < 9; ++i)
element.appendChild(<div class="msz-loading-icon-block"/>);
// this is moderately cursed but it'll do
const blocks = [
element.children[3],
element.children[0],
element.children[1],
element.children[2],
element.children[5],
element.children[8],
element.children[7],
element.children[6],
];
let tsLastUpdate;
let counter = 0;
let playing = false;
let delay = 50;
let playResolve;
let pauseResolve;
const update = tsCurrent => {
try {
if(tsLastUpdate !== undefined && (tsCurrent - tsLastUpdate) < delay)
return;
tsLastUpdate = tsCurrent;
for(let i = 0; i < blocks.length; ++i)
blocks[(counter + i) % blocks.length].classList.toggle('msz-loading-icon-block-hidden', i < 3);
++counter;
} finally {
if(playResolve)
try {
playResolve();
} finally {
playResolve = undefined;
playing = true;
}
if(pauseResolve)
try {
pauseResolve();
} finally {
pauseResolve = undefined;
playing = false;
}
if(playing)
requestAnimationFrame(update);
}
};
const play = () => {
return new Promise(resolve => {
if(playing || playResolve) {
resolve();
return;
}
playResolve = resolve;
requestAnimationFrame(update);
});
};
const pause = () => {
return new Promise(resolve => {
if(!playing || pauseResolve) {
resolve();
return;
}
pauseResolve = resolve;
});
};
const stop = async () => {
await pause();
counter = 0;
};
const restart = async () => {
await stop();
await play();
};
const reverse = () => {
blocks.reverse();
};
const setBlock = (num, state=null) => {
element.children[num].classList.toggle('msz-loading-icon-block-hidden', !state);
};
const batsu = () => {
setBlock(0, true);setBlock(1, false);setBlock(2, true);
setBlock(3, false);setBlock(4, true);setBlock(5, false);
setBlock(6, true);setBlock(7, false);setBlock(8, true);
};
const maru = () => {
setBlock(0, true);setBlock(1, true);setBlock(2, true);
setBlock(3, true);setBlock(4, false);setBlock(5, true);
setBlock(6, true);setBlock(7, true);setBlock(8, true);
};
return {
get element() { return element; },
get playing() { return playing; },
get delay() { return delay; },
set delay(value) {
if(typeof value !== 'number')
value = parseFloat(value);
if(isNaN(value) || !isFinite(value))
return;
if(value < 0)
value = Math.abs(value);
delay = value;
},
play,
pause,
stop,
restart,
reverse,
batsu,
maru,
};
};
const MszLoading = function(options=null) {
if(typeof options !== 'object')
throw 'options must be an object';
let {
element, size, colour,
width, height, inline,
containerWidth, containerHeight,
gap, margin, hidden,
} = options ?? {};
if(typeof element === 'string')
element = document.querySelector(element);
if(!(element instanceof HTMLElement))
element = <div class="msz-loading"/>;
if(!element.classList.contains('msz-loading'))
element.classList.add('msz-loading');
if(inline)
element.classList.add('msz-loading-inline');
if(hidden)
element.classList.add('hidden');
if(typeof size === 'number' && size > 0)
element.style.setProperty('--msz-loading-size', size);
if(typeof containerWidth === 'string')
element.style.setProperty('--msz-loading-container-width', containerWidth);
if(typeof containerHeight === 'string')
element.style.setProperty('--msz-loading-container-height', containerHeight);
if(typeof gap === 'string')
element.style.setProperty('--msz-loading-gap', gap);
if(typeof margin === 'string')
element.style.setProperty('--msz-loading-margin', margin);
if(typeof width === 'string')
element.style.setProperty('--msz-loading-width', width);
if(typeof height === 'string')
element.style.setProperty('--msz-loading-height', height);
if(typeof colour === 'string')
element.style.setProperty('--msz-loading-colour', colour);
let icon;
if(element.childElementCount < 1) {
icon = new MszLoadingIcon;
icon.play();
element.appendChild(<div class="msz-loading-frame">{icon}</div>);
}
return {
get element() { return element; },
get hasIcon() { return icon !== undefined; },
get icon() { return icon; },
get visible() { return !element.classList.contains('hidden'); },
set visible(state) { element.classList.toggle('hidden', !state); },
};
};

9
assets/common.js/main.js Normal file
View file

@ -0,0 +1,9 @@
#include array.js
#include csrf.js
#include html.js
#include meta.js
#include perf.jsx
#include uniqstr.js
#include xhr.js
#include loading.jsx

36
assets/common.js/meta.js Normal file
View file

@ -0,0 +1,36 @@
#include html.js
const $meta = (() => {
return {
get(name, prefixed=true) {
if(!name) return;
if(prefixed) name = `msz-${name}`;
const elem = $query(`meta[name="${name}"]`);
if(elem instanceof HTMLMetaElement && typeof elem.content === 'string')
return elem.content;
return null;
},
set(name, value, prefixed=true) {
if(!name) return;
if(prefixed) name = `msz-${name}`;
let elem = $query(`meta[name="${name}"]`);
if(elem instanceof HTMLMetaElement) {
if(typeof value === 'string')
elem.content = value;
else
elem.remove();
} else {
if(typeof value !== 'string')
return;
elem = document.createElement('meta');
elem.name = name;
elem.content = value;
document.head.appendChild(elem);
}
},
};
})();

72
assets/common.js/perf.jsx Normal file
View file

@ -0,0 +1,72 @@
#include html.js
(() => {
const perfs = <div class="msz-perfs"/>;
perfs.ondblclick = () => {
perfs.classList.toggle('msz-perfs-right');
};
const appendReal = elem => {
$appendChild(perfs, elem);
};
let append = elem => {
append = appendReal;
$appendChild(document.body, perfs);
appendReal(elem);
};
(new PerformanceObserver(list => {
for(const entry of list.getEntries()) {
if(entry.serverTiming.length < 1)
break;
const url = new URL(entry.name);
let total = 0;
let queries = -1;
const timings = <table class="msz-perf-timings"/>;
for(const timing of entry.serverTiming) {
if(timing.name === 'msz-queries') {
queries = Math.ceil(timing.duration);
continue;
}
total += timing.duration;
$appendChild(timings, <tr class="msz-perf-timing">
<td class="msz-perf-timing-name">{timing.name}</td>
<td class="msz-perf-timing-comment">{decodeURIComponent(timing.description)}</td>
<td class="msz-perf-timing-duration">
<span class="msz-perf-number">{timing.duration}</span>
<span class="msz-perf-unit">ms</span>
</td>
</tr>);
}
append(<div class="msz-perf">
<div class="msz-perf-header">
<div class={`msz-perf-type msz-perf-type-${entry instanceof PerformanceNavigationTiming ? 'navigation' : 'other'}`}>
{entry instanceof PerformanceNavigationTiming ? entry.type : (
entry.initiatorType === 'xmlhttprequest' ? 'xhr' : entry.initiatorType
)}
</div>
<div class="msz-perf-target">
{url.host !== location.host ? <div class="msz-perf-target-host">{url.host}</div> : null}
<div class="msz-perf-target-path">{url.pathname}</div>
{url.search !== '' ? <div class="msz-perf-target-query">{url.search}</div> : null}
</div>
{queries > 0 ? <div class="msz-perf-total">
<span class="msz-perf-number">{queries}</span>
{' '}
<span class="msz-perf-unit">{queries === 1 ? 'query' : 'queries'}</span>
</div> : null}
<div class="msz-perf-total">
<span class="msz-perf-number">{total.toFixed(5)}</span>
<span class="msz-perf-unit">ms</span>
</div>
</div>
{timings}
</div>);
}
})).observe({ entryTypes: ['navigation', 'resource'] });
})();

View file

@ -0,0 +1,38 @@
const $rngi = function(min, max) {
let ret = 0;
const range = max - min;
const bitsNeeded = Math.ceil(Math.log2(range));
if(bitsNeeded > 53)
return -1;
const bytesNeeded = Math.ceil(bitsNeeded / 8),
mask = Math.pow(2, bitsNeeded) - 1;
const bytes = new Uint8Array(bytesNeeded);
crypto.getRandomValues(bytes);
let p = (bytesNeeded - 1) * 8;
for(let i = 0; i < bytesNeeded; ++i) {
ret += bytes[i] * Math.pow(2, p);
p -= 8;
}
ret &= mask;
if(ret >= range)
return $rngi(min, max);
return min + ret;
};
const $rngs = (function() {
const chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789';
return function(length) {
let str = '';
for(let i = 0; i < length; ++i)
str += chars[$rngi(0, chars.length)];
return str;
};
})();

117
assets/common.js/xhr.js Normal file
View file

@ -0,0 +1,117 @@
#include csrf.js
const $xhr = (function() {
const send = function(method, url, options, body) {
if(options === undefined)
options = {};
else if(typeof options !== 'object')
throw 'options must be undefined or an object';
Object.freeze(options);
const xhr = new XMLHttpRequest;
const requestHeaders = new Map;
if('headers' in options && typeof options.headers === 'object')
for(const name in options.headers)
if(options.headers.hasOwnProperty(name))
requestHeaders.set(name.toLowerCase(), options.headers[name]);
if(options.csrf)
requestHeaders.set('x-csrf-token', $csrf.token);
if(typeof options.download === 'function') {
xhr.onloadstart = ev => options.download(ev);
xhr.onprogress = ev => options.download(ev);
xhr.onloadend = ev => options.download(ev);
}
if(typeof options.upload === 'function') {
xhr.upload.onloadstart = ev => options.upload(ev);
xhr.upload.onprogress = ev => options.upload(ev);
xhr.upload.onloadend = ev => options.upload(ev);
}
if(options.authed)
xhr.withCredentials = true;
if(typeof options.timeout === 'number')
xhr.timeout = options.timeout;
if(typeof options.type === 'string')
xhr.responseType = options.type;
if(typeof options.abort === 'function')
options.abort(() => xhr.abort());
if(typeof options.xhr === 'function')
options.xhr(() => xhr);
if(typeof body === 'object') {
if(body instanceof URLSearchParams) {
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
} else if(body instanceof FormData) {
// content-type is implicitly set
} else if(body instanceof Blob || body instanceof ArrayBuffer || body instanceof DataView) {
if(!requestHeaders.has('content-type'))
requestHeaders.set('content-type', 'application/octet-stream');
} else if(!requestHeaders.has('content-type')) {
const bodyParts = [];
for(const name in body)
if(body.hasOwnProperty(name))
bodyParts.push(encodeURIComponent(name) + '=' + encodeURIComponent(body[name]));
body = bodyParts.join('&');
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
}
}
return new Promise((resolve, reject) => {
xhr.onload = ev => {
const headers = (headersString => {
const headers = new Map;
const raw = headersString.trim().split(/[\r\n]+/);
for(const name in raw)
if(raw.hasOwnProperty(name)) {
const parts = raw[name].split(': ');
headers.set(parts.shift(), parts.join(': '));
}
return headers;
})(xhr.getAllResponseHeaders());
if(headers.has('x-csrf-token'))
$csrf.token = headers.get('x-csrf-token');
resolve({
get ev() { return ev; },
get xhr() { return xhr; },
get status() { return xhr.status; },
get headers() { return headers; },
get body() { return xhr.response; },
get text() { return xhr.responseText; },
});
};
xhr.onerror = ev => reject({
xhr: xhr,
ev: ev,
});
xhr.open(method, url);
for(const [name, value] of requestHeaders)
xhr.setRequestHeader(name, value);
xhr.send(body);
});
};
return {
send: send,
get: (url, options, body) => send('GET', url, options, body),
post: (url, options, body) => send('POST', url, options, body),
delete: (url, options, body) => send('DELETE', url, options, body),
patch: (url, options, body) => send('PATCH', url, options, body),
put: (url, options, body) => send('PUT', url, options, body),
};
})();

View file

@ -1,100 +0,0 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
position: relative;
outline-style: none;
}
html,
body {
width: 100%;
height: 100%;
}
[hidden],
.hidden {
display: none !important;
visibility: hidden !important;
}
:root {
--font-size: 12px;
--line-height: 20px;
--font-regular: Tahoma, Geneva, 'Dejavu Sans', Arial, Helvetica, sans-serif;
--font-monospace: Consolas, 'Liberation Mono', Menlo, Courier, monospace;
--site-max-width: 1200px;
--site-mobile-width: 800px;
--site-logo: url('/images/logos/imouto-default.png');
--header-height-desktop: 70px;
--header-height-mobile: 50px;
--background-image: initial;
--background-colour: #111;
--background-colour-translucent-1: rgba(17, 17, 17, 0.1);
--background-colour-translucent-2: rgba(17, 17, 17, 0.2);
--background-colour-translucent-3: rgba(17, 17, 17, 0.3);
--background-colour-translucent-4: rgba(17, 17, 17, 0.4);
--background-colour-translucent-5: rgba(17, 17, 17, 0.5);
--background-colour-translucent-6: rgba(17, 17, 17, 0.6);
--background-colour-translucent-7: rgba(17, 17, 17, 0.7);
--background-colour-translucent-8: rgba(17, 17, 17, 0.8);
--background-colour-translucent-9: rgba(17, 17, 17, 0.9);
--background-pattern: url('/images/clouds.png') fixed;
--container-colour: #161616;
--text-colour: #fff;
--text-colour-inverted: #000;
--user-colour: inherit;
--user-header: url('/images/pixel.png');
--accent-colour: #8559a5;
--header-accent-colour: var(--accent-colour);
/** octobre **/
--site-logo: url('/images/logos/imouto-halloween.png');
--accent-colour: #ee9400;
}
html {
scrollbar-color: var(--accent-colour) var(--background-colour);
}
.main {
display: flex;
flex-direction: column;
background-image: var(--background-image);
background-color: var(--background-colour);
font-size: var(--font-size);
line-height: var(--line-height);
font-family: var(--font-regular);
color: var(--text-colour);
background-attachment: fixed;
background-position: center center;
}
.main__wrapper {
max-width: var(--site-max-width);
width: 100%;
margin: 0 auto;
flex: 1 0 auto;
}
.main--bg-blend {
background-color: var(--accent-colour);
background-blend-mode: multiply;
}
.main--bg-slide { animation: background-slide infinite linear 2s; }
.main--bg-cover { background-size: cover; }
.main--bg-contain { background-size: contain; }
.main--bg-stretch { background-size: 100% 100%; }
.main--bg-tile { background-size: auto; }
.link {
color: var(--accent-colour);
text-decoration: none;
}
.link:hover, .link:focus { text-decoration: underline; }

View file

@ -1,159 +0,0 @@
.comment {
margin: 10px;
}
.comment__reply-toggle {
display: none;
}
.comment__reply-toggle:checked ~ .comment--reply {
display: block;
}
.comment--reply {
display: none;
}
.comment--deleted > .comment__container {
opacity: .5;
transition: opacity .2s;
}
.comment--deleted > .comment__container:hover {
opacity: .9;
}
.comment__container {
display: flex;
margin-bottom: 3px;
}
.comment__mention {
color: var(--user-colour);
text-decoration: none;
font-weight: 700;
}
.comment__mention:hover {
text-decoration: underline;
}
.comment__actions {
list-style: none;
display: flex;
font-size: .9em;
align-items: center;
}
.comment__action {
color: inherit;
text-decoration: none;
vertical-align: middle;
cursor: pointer;
}
.comment__action:not(:last-child) {
margin-right: 6px;
}
.comment__action--link:hover {
text-decoration: underline;
}
.comment__action--post {
margin-left: auto;
}
.comment__action--button {
cursor: pointer;
font: 12px/20px var(--font-regular);
padding: 0 10px;
}
.comment__action--hide {
opacity: 0;
transition: opacity .2s;
}
.comment__action--voted {
font-weight: 700;
}
.comment__action__checkbox {
vertical-align: text-top;
margin-right: 2px;
}
.comment__replies .comment--indent-1,
.comment__replies .comment--indent-2,
.comment__replies .comment--indent-3,
.comment__replies .comment--indent-4,
.comment__replies .comment--indent-5 {
margin-left: 20px;
}
.comment__avatar {
flex: 0 0 auto;
height: 50px;
width: 50px;
margin-right: 5px;
}
.comment__replies .comment__avatar {
width: 40px;
height: 40px;
}
.comment__content {
flex: 1 1 auto;
display: flex;
flex-direction: column;
overflow: hidden;
word-wrap: break-word;
padding-left: 5px;
}
.comment__content:hover .comment__action--hide {
opacity: 1;
}
.comment__info {
display: inline-flex;
}
.comment__text {
margin-right: 2px;
}
.comment__text--input {
min-width: 100%;
max-width: 100%;
min-height: 50px;
font: 12px/20px var(--font-regular);
margin-right: 1px;
}
.comment__user {
color: var(--user-colour);
text-decoration: none;
}
.comment__user--link:hover {
text-decoration: underline;
}
.comment__date,
.comment__pin {
color: #666;
font-size: .9em;
margin-left: 8px;
}
.comment__link {
color: #666;
display: inline-flex;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
.comment__pin {
margin-left: 4px;
}
.comment__pin:before {
content: "-";
padding-right: 4px;
}

View file

@ -1,36 +0,0 @@
.comments {
--comments-max-height: 600px;
margin: 1px;
overflow: hidden;
word-wrap: break-word;
}
.comments__listing {
overflow-y: auto;
}
.comments__listing--limit {
max-height: var(--comments-max-height);
}
/*.comments__input,*/
.comments__javascript,
.comments__notice--staff {
border-bottom: 1px solid var(--accent-colour);
padding-bottom: 1px;
margin-bottom: 1px;
}
.comments__none,
.comments__javascript,
.comments__notice {
padding: 10px;
font-size: 1.2em;
text-align: center;
}
.comments__notice__link {
color: var(--accent-colour);
text-decoration: none;
}
.comments__notice__link:hover {
text-decoration: underline;
}

View file

@ -1,11 +0,0 @@
.confirm {
max-width: 400px;
margin: 0 auto;
}
.confirm__buttons {
display: flex;
padding: 5px;
justify-content: center;
}
.confirm__message { padding: 2px 5px; }
.confirm__button { margin-right: 5px; }

View file

@ -1,15 +0,0 @@
.forum__confirm {
max-width: 400px;
margin: 0 auto;
}
.forum__confirm__message {
padding: 2px 5px;
}
.forum__confirm__buttons {
display: flex;
padding: 5px;
justify-content: center;
}
.forum__confirm__button {
margin-right: 5px;
}

View file

@ -1,104 +0,0 @@
.forum__poll__container {
margin: 2px 0;
padding: 5px;
display: flex;
flex-direction: column;
align-items: center;
}
.forum__poll__toggle,
.forum__poll__toggle:checked ~ .forum__poll__container--poll,
.forum__poll__toggle:not(:checked) ~ .forum__poll__container--results {
display: none;
}
.forum__poll__options {
display: flex;
flex-direction: column;
max-width: 500px;
min-width: 100%;
}
.forum__poll__results {
max-width: 800px;
width: 100%;
padding: 0 1px;
}
.forum__poll__option {
padding: 2px;
}
.forum__poll__remaining,
.forum__poll__expires {
line-height: 1.5em;
}
.forum__poll__remaining__num,
.forum__poll__expires__num,
.forum__poll__remaining__datetime,
.forum__poll__expires__datetime {
font-weight: 700;
}
.forum__poll__buttons {
display: flex;
margin-top: 2px;
}
.forum__poll__button {
margin: 0 2px;
}
.forum__poll__result {
overflow: hidden;
border-radius: 5px;
margin: 4px 0;
border: 1px solid var(--accent-colour);
width: 100%;
}
.forum__poll__result__background {
position: absolute;
top: 0;
left: 0;
height: 100%;
background: var(--accent-colour);
opacity: .2;
}
.forum__poll__result--voted .forum__poll__result__background {
opacity: .4;
}
.forum__poll__result__container {
display: flex;
justify-content: center;
}
.forum__poll__result__text {
flex: 1 1 auto;
padding: 5px;
}
.forum__poll__result--voted .forum__poll__result__text {
font-weight: 700;
}
.forum__poll__result__votes {
flex: 0 0 auto;
padding: 5px;
text-align: right;
}
.forum__poll__result__percent {
flex: 0 0 auto;
padding: 5px;
min-width: 60px;
text-align: right;
}
@media (min-width: 400px) {
.forum__poll__options {
min-width: 300px;
}
}

View file

@ -1,37 +0,0 @@
.forum__priority__votes {
text-align: center;
margin: 5px 16px 5px 5px;
-webkit-touch-callout: none !important;
-webkit-user-select: none !important;
-khtml-user-select: none !important;
-moz-user-select: none !important;
-ms-user-select: none !important;
user-select: none !important;
cursor: default;
}
.forum__priority__vote {
font-size: 14px;
display: inline;
}
.forum__priority__star {
margin-right: -.9em;
opacity: .6;
text-shadow: 0 1px 1px #000;
color: var(--user-colour);
transition: text-shadow .2s;
}
.forum__priority__star:last-child {
margin-right: 0;
opacity: 1;
}
.forum__priority__vote:hover .forum__priority__star {
text-shadow: 0 0 1px #fff;
}
.forum__priority__input {
margin: 5px;
text-align: center;
}

View file

@ -1,25 +0,0 @@
.manage {
display: flex;
}
.manage__sidebar {
flex: 0 0 auto;
width: 280px;
}
.manage__content {
flex: 1 1 auto;
}
.manage__description {
font-size: .9em;
margin: 1px 2px;
border-bottom: 1px solid var(--accent-colour);
padding: 2px 5px;
}
@media (max-width: 800px) {
.manage {
flex-direction: column;
}
.manage__sidebar {
width: 100%;
}
}

View file

@ -1,14 +0,0 @@
.manage__statistic {
border: 1px solid var(--accent-colour);
border-radius: 2px;
padding: 2px 5px;
}
.manage__statistic__name {
font-size: 1.1em;
line-height: 1.5em;
}
.manage__statistic__value {
text-align: right;
font-size: 1.5em;
line-height: 2em;
}

View file

@ -1,85 +0,0 @@
.navigation {
margin: 2px 0;
width: 100%;
display: flex;
border-width: 0;
border-color: var(--text-colour);
border-style: solid;
border-top-width: 1px;
align-items: flex-start;
justify-content: center;
}
.navigation--top {
border-top-width: 0;
border-bottom-width: 1px;
align-items: flex-end;
}
.navigation--top .navigation__option {
border-top-width: 1px;
border-bottom-width: 0;
}
.navigation__option {
list-style: none;
background-color: #c9bbcc;
border: 1px solid var(--text-colour);
border-top-width: 0;
flex-grow: 0;
}
.navigation__option:not(:first-child) { border-left-width: 0; }
.navigation__option--selected {
background-color: var(--accent-colour);
top: -1px;
}
.navigation__option--selected:not(:first-child) {
margin-left: -1px;
border-left-width: 1px;
}
.navigation__link {
display: block;
padding: 2px 1em;
color: var(--text-colour);
text-decoration: none;
}
.navigation__link:hover, .navigation__link:focus { color: #609; }
@media (max-width: 1000px) {
.navigation {
border: none;
align-items: center;
flex-direction: column;
}
.navigation--left {
justify-content: left;
padding-left: 25px;
}
.navigation--right {
justify-content: right;
padding-right: 25px;
}
.navigation--top .navigation__option--selected { top: 1px; }
.navigation__link {
padding: 10px 15px;
font-size: 1.5em;
}
.navigation__option {
background-color: var(--accent-colour);
width: 100%;
border: none;
flex-grow: 1;
margin-bottom: 1px;
}
.navigation__option--selected {
background-color: #a586c3;
top: 0;
}
.navigation__option--selected .navigation__link {
padding: 3px 1em;
}
}

View file

@ -1,129 +0,0 @@
.news__preview {
display: flex;
margin: 2px 0;
flex-direction: row-reverse;
--user-colour: var(--accent-colour);
}
.news__preview__info__content {
width: 200px;
text-align: center;
display: flex;
flex-direction: column;
padding: 15px;
flex: 0 0 auto;
margin-right: 4px;
}
.news__preview__info__background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
mask-image: linear-gradient(90deg, transparent 10%, var(--background-colour) 100%);
-webkit-mask-image: linear-gradient(90deg, transparent 10%, var(--background-colour) 100%);
background: var(--background-pattern);
background-color: var(--user-colour);
background-blend-mode: multiply;
}
.news__preview__listing {
flex-grow: 1;
flex-shrink: 1;
}
.news__preview__container {
display: flex;
margin: 1px;
flex-direction: column;
}
.news__preview__user {
display: flex;
text-align: left;
align-items: center;
margin-bottom: 10px;
}
.news__preview__user__details {
display: flex;
flex-direction: column;
}
.news__preview__avatar {
width: 60px;
height: 60px;
margin-right: 10px;
}
.news__preview__username {
color: inherit;
font-size: 1.4em;
line-height: 1.5em;
text-decoration: none;
}
.news__preview__username[href]:hover {
text-decoration: underline;
}
.news__preview__date {
font-size: 1.1em;
line-height: 1.5em;
}
.news__preview__category {
color: inherit;
text-decoration: none;
font-size: 1.1em;
line-height: 1.5em;
margin: 6px 0;
}
.news__preview__category:hover {
text-decoration: underline;
}
.news__preview__content {
display: flex;
flex-direction: column;
line-height: 1.2em;
flex: 1 1 auto;
word-wrap: break-word;
overflow: hidden;
margin: 2px;
padding: 0 10px 10px 10px;
}
.news__preview__text {
flex: 1 1 auto;
}
.news__preview__links {
display: flex;
justify-content: space-between;
}
.news__preview__link {
font-size: .9em;
}
@media (max-width: 800px) {
.news__preview { flex-direction: column-reverse; }
.news__preview__info { display: none; }
.news__preview__info__content {
width: 100%;
flex-wrap: wrap;
text-align: left;
}
.news__preview__info__background {
mask-image: linear-gradient(180deg, transparent 10%, var(--background-colour) 100%);
-webkit-mask-image: linear-gradient(180deg, transparent 10%, var(--background-colour) 100%);
}
.news__preview__user {
margin-bottom: 0;
margin-right: 10px;
}
.news__preview__avatar {
width: 50px;
height: 50px;
}
}

View file

@ -1,10 +0,0 @@
.profile__relations {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.profile__relations__user {
margin: 2px;
width: 300px;
display: flex;
}

View file

@ -1,139 +0,0 @@
.profile__warning {
margin: 2px;
border-radius: 2px;
border: 1px solid var(--accent-colour);
}
.profile__warning__container {
margin: 2px 0;
}
.profile__warning--warning {
--accent-colour: #666;
}
.profile__warning--silence {
--accent-colour: #f70;
}
.profile__warning--ban {
--accent-colour: #c33;
}
.profile__warning--extendo {
margin: 4px;
}
.profile__warning__background {
background-color: var(--accent-colour);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.profile__warning__content {
background-color: var(--background-colour-translucent-9);
display: flex;
padding: 1px;
}
.profile__warning__type,
.profile__warning__created,
.profile__warning__duration {
display: inline-flex;
align-items: center;
justify-content: center;
}
.profile__warning__type {
min-width: 80px;
background-color: var(--accent-colour);
border-radius: 1px;
padding: 0 4px;
}
.profile__warning__created,
.profile__warning__duration {
min-width: 100px;
padding: 0 4px;
}
.profile__warning__note {
padding: 1px 4px;
flex: 1 1 auto;
}
.profile__warning__private {
border-top: 1px solid var(--accent-colour);
margin-top: 1px;
width: 100%;
opacity: .5;
transition: opacity .2s;
}
.profile__warning__private:hover,
.profile__warning__private:active,
.profile__warning__private:focus {
opacity: 1;
}
.profile__warning__tools {
display: flex;
padding-bottom: 1px;
}
.profile__warning__options {
flex: 1 1 auto;
display: flex;
justify-content: flex-end;
align-items: center;
}
.profile__warning__option {
padding: 2px 5px;
color: inherit;
text-decoration: none;
}
.profile__warning__user {
display: flex;
padding: 2px;
min-width: 300px;
}
.profile__warning__user__avatar {
width: 20px;
height: 20px;
}
.profile__warning__user__username {
padding: 0 5px;
min-width: 60px;
color: inherit;
text-decoration: none;
}
.profile__warning__user__username:hover,
.profile__warning__user__username:focus,
.profile__warning__user__username:active {
text-decoration: underline;
}
.profile__warning__user__ip {
display: inline-flex;
padding: 0 5px;
}
.profile__warning__user__ip:before { content: "("; }
.profile__warning__user__ip:after { content: ")"; }
@media (max-width: 800px) {
.profile__warning__content {
flex-wrap: wrap;
}
.profile__warning__tools {
flex-direction: column;
}
.profile__warning__options {
justify-content: flex-start;
}
}

View file

@ -1,170 +0,0 @@
.usercard {
display: flex;
flex-direction: column;
transition: box-shadow .5s;
z-index: 1;
color: #fff;
background-color: var(--background-colour);
box-shadow: 0 1px 2px #000A;
text-shadow: 0 1px 4px #000;
overflow: hidden;
flex: 1 1 auto;
--usercard-header-overlay-start: transparent;
--usercard-header-overlay-stop: var(--background-colour-translucent-9);
}
.usercard:hover {
box-shadow: 0 1px 4px #000;
z-index: 2;
}
.usercard__background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--accent-colour) var(--background-pattern);
background-blend-mode: multiply;
}
.usercard__header {
flex: 0 0 auto;
}
.usercard__header__link {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.usercard__header__avatar {
width: 60px;
height: 60px;
z-index: 20;
}
.usercard__header__container {
display: flex;
align-items: center;
padding: 10px;
background-image: linear-gradient(0deg, var(--usercard-header-overlay-stop), var(--usercard-header-overlay-start));
pointer-events: none;
}
.usercard__header__details {
margin: 0 10px;
flex: 1 1 auto;
}
.usercard__header__relation {
font-variant: all-small-caps;
background: var(--usercard-header-overlay-stop);
border-radius: 2px;
line-height: 1.2em;
padding: 1px 5px 4px;
cursor: default;
}
.usercard__header__username {
font-size: 1.5em;
line-height: 1.3em;
}
.usercard__header__title {
font-size: .9em;
line-height: 1.2em;
}
.usercard__header__country {
display: inline-flex;
align-items: center;
}
.usercard__header__country__name {
font-size: .9em;
margin-left: 4px;
line-height: 1.2em;
}
.usercard__container {
flex: 1 1 auto;
background-color: var(--usercard-header-overlay-stop);
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.usercard__dates {
font-size: .9em;
line-height: 1em;
display: flex;
justify-content: space-evenly;
align-items: center;
flex: 0 0 auto;
margin-bottom: 4px;
}
.usercard__date {
padding: 4px;
}
.usercard__stats {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
flex: 0 0 auto;
}
.usercard__stat {
display: flex;
flex-direction: column-reverse;
color: inherit;
text-decoration: none;
padding: 5px 10px;
cursor: default;
flex: 0 0 auto;
text-align: right;
}
.usercard__stat[href] {
cursor: pointer;
}
.usercard__stat[href]:hover,
.usercard__stat[href]:focus {
border-bottom: 2px solid var(--accent-colour);
padding-bottom: 3px;
}
.usercard__stat__name {
font-size: .9em;
font-variant: small-caps;
cursor: inherit;
}
.usercard__stat__value {
font-size: 1.3em;
cursor: inherit;
display: block;
}
.usercard__actions {
flex: 0 0 auto;
display: flex;
height: 38px;
}
.usercard__action {
flex: 1 1 auto;
display: flex;
justify-content: center;
align-items: center;
color: inherit;
text-decoration: none;
font-size: 1.5em;
transition: background-color .2s;
text-align: center;
cursor: pointer;
}
.usercard__action:hover,
.usercard__action:focus { background-color: rgba(255, 255, 255, .2); }
.usercard__action:active { background-color: rgba(255, 255, 255, .1); }
@media (max-width: 800px) {
.usercard__header__details {
text-align: center;
}
}

157
assets/errors.css/main.css Normal file
View file

@ -0,0 +1,157 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
position: relative;
}
html,
body {
width: 100%;
height: 100%;
}
html {
scrollbar-color: #8559a5;
scrollbar-color: var(--error-colour, #8559a5) #111;
}
body {
color: #fff;
font-size: 16px;
line-height: 25px;
font-family: Inter, 'Zen Kaku Gothic New', sans-serif;
font-feature-settings: 'calt' 1, 'dlig' 1, 'ss01' 1;
font-optical-sizing: auto;
background-color: #8559a5;
background-color: var(--error-colour, #8559a5);
background-image: url('/images/clouds.png');
background-blend-mode: multiply;
position: static;
display: flex;
flex-direction: column;
}
@supports (font-variation-settings: normal) {
body {
--font-regular: InterVariable, 'Zen Kaku Gothic New', sans-serif;
}
}
.error {
display: flex;
flex-direction: column;
flex: 1 0 auto;
margin-bottom: 10px;
}
.error-wrapper {
display: flex;
flex: 1 0 auto;
padding: 10px;
width: 100%;
align-items: center;
justify-content: center;
}
.error-container {
max-width: 700px;
width: 100%;
margin: 0 auto;
padding: 4px;
background-color: #111;
box-shadow: 0 2px 4px #000;
overflow: hidden;
word-wrap: break-word;
}
.error-top {
display: flex;
align-items: center;
gap: 4px;
padding-bottom: 4px;
border-bottom: 1px solid #444;
}
.error-top a {
color: #fff;
text-decoration: none;
}
.error-top a:hover,
.error-top a:focus {
text-decoration: underline;
}
.error-logo {
width: 50px;
height: 50px;
}
.error-logo a {
color: inherit !important;
text-decoration: none !important;
}
.error-logo img {
width: 100%;
height: 100%;
vertical-align: middle;
border-width: 0;
object-fit: contain;
}
.error-home {
font-size: 1.5rem;
line-height: 1.375rem;
}
.error-nav {
margin-left: auto; /* lmao */
display: flex;
gap: 8px;
padding: 4px;
}
.error-body {
text-align: center;
height: 300px;
display: flex;
flex-direction: column;
justify-content: center;
}
.error-title {
line-height: 3rem;
}
.error-icon {
font-size: 4rem;
line-height: 1.5rem;
}
.error-blerb {
font-size: .875rem;
line-height: 1rem;
}
.error-footer {
text-align: center;
font-size: .75rem;
line-height: 1.375em;
color: #888;
border-top: 1px solid #444;
padding-top: 4px;
}
.error-footer a {
color: #88a;
text-decoration: underline;
text-decoration-style: dotted;
}
.error-footer a:hover,
.error-footer a:focus {
text-decoration-style: solid;
}
.error-footer a:active {
color: #a88;
}

View file

@ -1,176 +0,0 @@
Array.prototype.removeIndex = function(index) {
this.splice(index, 1);
return this;
};
Array.prototype.removeItem = function(item) {
var index;
while(this.length > 0 && (index = this.indexOf(item)) >= 0)
this.removeIndex(index);
return this;
};
Array.prototype.removeFind = function(predicate) {
var index;
while(this.length > 0 && (index = this.findIndex(predicate)) >= 0)
this.removeIndex(index);
return this;
};
HTMLCollection.prototype.toArray = function() {
return Array.prototype.slice.call(this);
};
HTMLTextAreaElement.prototype.insertTags = function(tagOpen, tagClose) {
tagOpen = tagOpen || '';
tagClose = tagClose || '';
if(document.selection) {
this.focus();
var selected = document.selection.createRange();
selected.text = tagOpen + selected.text + tagClose;
this.focus();
} else if(this.selectionStart || this.selectionStart === 0) {
var startPos = this.selectionStart,
endPos = this.selectionEnd,
scrollTop = this.scrollTop;
this.value = this.value.substring(0, startPos)
+ tagOpen
+ this.value.substring(startPos, endPos)
+ tagClose
+ this.value.substring(endPos, this.value.length);
this.focus();
this.selectionStart = startPos + tagOpen.length;
this.selectionEnd = endPos + tagOpen.length;
this.scrollTop + scrollTop;
} else {
this.value += tagOpen + tagClose;
this.focus();
}
};
var CreateElement = function(elemInfo) {
elemInfo = elemInfo || {};
var elem = document.createElement(elemInfo.tag || 'div');
if(elemInfo.props) {
var propKeys = Object.keys(elemInfo.props);
for(var i = 0; i < propKeys.length; i++) {
var propKey = propKeys[i];
if(elemInfo.props[propKey] === undefined
|| elemInfo.props[propKey] === null)
continue;
switch(typeof elemInfo.props[propKey]) {
case 'function':
elem.addEventListener(
propKey.substring(0, 2) === 'on'
? propKey.substring(2).toLowerCase()
: propKey,
elemInfo.props[propKey]
);
break;
default:
elem.setAttribute(propKey === 'className' ? 'class' : propKey, elemInfo.props[propKey]);
break;
}
}
}
if(elemInfo.children) {
var children = elemInfo.children;
if(!Array.isArray(children))
children = [children];
for(var i = 0; i < children.length; i++) {
var child = children[i];
switch(typeof child) {
case 'string':
elem.appendChild(document.createTextNode(child));
break;
case 'object':
if(child instanceof Element)
elem.appendChild(child);
else if(child.getElement)
elem.appendChild(child.getElement());
else
elem.appendChild(CreateElement(child));
break;
default:
elem.appendChild(document.createTextNode(child.toString()));
break;
}
}
}
if(elemInfo.created)
elemInfo.created(elem);
return elem;
};
var CreateBasicElement = function(className, children, tagName) {
return CreateElement({
tag: tagName || null,
props: {
'class': className || null,
},
'children': children || null,
});
};
var LoadScript = function(url, loaded, error) {
if(document.querySelector('script[src="' + encodeURI(url) + '"]')) {
if(loaded)
loaded();
return;
}
var script = document.createElement('script');
script.type = 'text/javascript';
if(loaded)
script.addEventListener('load', function() { loaded(); });
script.addEventListener('error', function() {
document.body.removeChild(script);
if(error)
error();
});
script.src = url;
document.body.appendChild(script);
};
var MakeEventTarget = function(object) {
object.eventListeners = {};
object.addEventListener = function(type, callback) {
if(!(type in this.eventListeners))
this.eventListeners[type] = [];
this.eventListeners[type].push(callback);
};
object.removeEventListener = function(type, callback) {
if(!(type in this.eventListeners))
return;
this.eventListeners[type].removeItem(callback);
};
object.dispatchEvent = function(event) {
if(!(event.type in this.eventListeners))
return true;
var stack = this.eventListeners[event.type].slice();
for(var i = 0; i < stack.length; ++i)
stack[i].call(this, event);
return !event.defaultPrevented;
};
};
var DefineEnum = function(values) {
var keys = Object.keys(values);
for(var i = 0; i < keys.length; ++i)
values[values[keys[i]]] = keys[i];
return values;
};

View file

@ -1,157 +0,0 @@
var Misuzu = function() {
if(Misuzu.initialised)
throw 'Misuzu script has already initialised.';
Misuzu.started = true;
console.log(
"%cMisuzu%c\nhttps://github.com/flashwave/misuzu",
'font-size: 48px; color: #8559a5; background: #111;'
+ 'border-radius: 5px; padding: 0 10px; text-shadow: 0 0 1em #fff;',
);
timeago.render(document.querySelectorAll('time'));
hljs.initHighlighting();
Misuzu.CSRF.init();
Misuzu.Urls.loadFromDocument();
Misuzu.User.refreshLocalUser();
Misuzu.UserRelations.init();
Misuzu.FormUtils.initDataRequestMethod();
Misuzu.initQuickSubmit();
Misuzu.Comments.init();
Misuzu.Forum.Editor.init();
Misuzu.Forum.Polls.init();
if(Misuzu.User.isLoggedIn())
console.log(
'You are %s with user id %d and colour %s.',
Misuzu.User.localUser.getUsername(),
Misuzu.User.localUser.getId(),
Misuzu.User.localUser.getColour().getCSS()
);
else
console.log('You aren\'t logged in.');
Misuzu.Events.dispatch();
Misuzu.initLoginPage();
};
Misuzu.Parser = DefineEnum({
plain: 0,
bbcode: 1,
markdown: 2,
});
Misuzu.supportsSidewaysText = function() { return CSS.supports('writing-mode', 'sideways-lr'); };
Misuzu.showMessageBox = function(text, title, buttons) {
if(document.querySelector('.messagebox'))
return false;
text = text || '';
title = title || '';
buttons = buttons || [];
var element = document.createElement('div');
element.className = 'messagebox';
var container = element.appendChild(document.createElement('div'));
container.className = 'container messagebox__container';
var titleElement = container.appendChild(document.createElement('div')),
titleBackground = titleElement.appendChild(document.createElement('div')),
titleText = titleElement.appendChild(document.createElement('div'));
titleElement.className = 'container__title';
titleBackground.className = 'container__title__background';
titleText.className = 'container__title__text';
titleText.textContent = title || 'Information';
var textElement = container.appendChild(document.createElement('div'));
textElement.className = 'container__content';
textElement.textContent = text;
var buttonsContainer = container.appendChild(document.createElement('div'));
buttonsContainer.className = 'messagebox__buttons';
var firstButton = null;
if(buttons.length < 1) {
firstButton = buttonsContainer.appendChild(document.createElement('button'));
firstButton.className = 'input__button';
firstButton.textContent = 'OK';
firstButton.addEventListener('click', function() { element.remove(); });
} else {
for(var i = 0; i < buttons.length; i++) {
var button = buttonsContainer.appendChild(document.createElement('button'));
button.className = 'input__button';
button.textContent = buttons[i].text;
button.addEventListener('click', function() {
element.remove();
buttons[i].callback();
});
if(firstButton === null)
firstButton = button;
}
}
document.body.appendChild(element);
firstButton.focus();
return true;
};
Misuzu.initLoginPage = function() {
var updateForm = function(avatarElem, usernameElem) {
var xhr = new XMLHttpRequest;
xhr.addEventListener('readystatechange', function() {
if(xhr.readyState !== 4)
return;
var json = JSON.parse(xhr.responseText);
if(!json)
return;
if(json.name)
usernameElem.value = json.name;
avatarElem.src = json.avatar;
});
xhr.open('GET', Misuzu.Urls.format('auth-resolve-user', [{name: 'username', value: encodeURIComponent(usernameElem.value)}]));
xhr.send();
};
var loginForms = document.getElementsByClassName('js-login-form');
for(var i = 0; i < loginForms.length; ++i)
(function(form) {
var loginTimeOut = 0,
loginAvatar = form.querySelector('.js-login-avatar'),
loginUsername = form.querySelector('.js-login-username');
updateForm(loginAvatar, loginUsername);
loginUsername.addEventListener('keyup', function() {
if(loginTimeOut)
return;
loginTimeOut = setTimeout(function() {
updateForm(loginAvatar, loginUsername);
clearTimeout(loginTimeOut);
loginTimeOut = 0;
}, 750);
});
})(loginForms[i]);
};
Misuzu.initQuickSubmit = function() {
var ctrlSubmit = document.getElementsByClassName('js-quick-submit').toArray().concat(document.getElementsByClassName('js-ctrl-enter-submit').toArray());
if(!ctrlSubmit)
return;
for(var i = 0; i < ctrlSubmit.length; ++i)
ctrlSubmit[i].addEventListener('keydown', function(ev) {
if((ev.code === 'Enter' || ev.code === 'NumpadEnter') // i hate this fucking language so much
&& ev.ctrlKey && !ev.altKey && !ev.shiftKey && !ev.metaKey) {
// hack: prevent forum editor from screaming when using this keycombo
// can probably be done in a less stupid manner
Misuzu.Forum.Editor.allowWindowClose = true;
this.form.submit();
ev.preventDefault();
}
});
};

View file

@ -1,93 +0,0 @@
Misuzu.Colour = function(raw) {
this.setRaw(raw || 0);
};
Misuzu.Colour.prototype.raw = 0;
Misuzu.Colour.FLAG_INHERIT = 0x40000000;
Misuzu.Colour.READABILITY_THRESHOLD = 186;
Misuzu.Colour.LUMINANCE_WEIGHT_RED = .299;
Misuzu.Colour.LUMINANCE_WEIGHT_GREEN = .587;
Misuzu.Colour.LUMINANCE_WEIGHT_BLUE = .114;
Misuzu.Colour.none = function() { return new Misuzu.Colour(Misuzu.Colour.FLAG_INHERIT); };
Misuzu.Colour.fromRGB = function(red, green, blue) {
var colour = new Misuzu.Colour;
colour.setRed(red);
colour.setGreen(green);
colour.setBlue(blue);
return colour;
};
Misuzu.Colour.fromHex = function(hex) {
var colour = new Misuzu.Colour;
colour.setHex(hex);
return colour;
};
Misuzu.Colour.prototype.getRaw = function() { return this.raw; };
Misuzu.Colour.prototype.setRaw = function(raw) {
this.raw = parseInt(raw) & 0x7FFFFFFF;
};
Misuzu.Colour.prototype.getInherit = function() { return (this.getRaw() & Misuzu.Colour.FLAG_INHERIT) > 0; };
Misuzu.Colour.prototype.setInherit = function(inherit) {
var raw = this.getRaw();
if(inherit)
raw |= Misuzu.Colour.FLAG_INHERIT;
else
raw &= ~Misuzu.Colour.FLAG_INHERIT;
this.setRaw(raw);
};
Misuzu.Colour.prototype.getRed = function() { return (this.getRaw() >> 16) & 0xFF };
Misuzu.Colour.prototype.setRed = function(red) {
var raw = this.getRaw();
raw &= ~0xFF0000;
raw |= (parseInt(red) & 0xFF) << 16;
this.setRaw(raw);
};
Misuzu.Colour.prototype.getGreen = function() { return (this.getRaw() >> 8) & 0xFF };
Misuzu.Colour.prototype.setGreen = function(green) {
var raw = this.getRaw();
raw &= ~0xFF0000;
raw |= (parseInt(green) & 0xFF) << 8;
this.setRaw(raw);
};
Misuzu.Colour.prototype.getBlue = function() { return this.getRaw() & 0xFF };
Misuzu.Colour.prototype.setBlue = function(blue) {
var raw = this.getRaw();
raw &= ~0xFF0000;
raw |= parseInt(blue) & 0xFF;
this.setRaw(raw);
};
Misuzu.Colour.prototype.getLuminance = function() {
return Misuzu.Colour.LUMINANCE_WEIGHT_RED * this.getRed()
+ Misuzu.Colour.LUMINANCE_WEIGHT_GREEN * this.getGreen()
+ Misuzu.Colour.LUMINANCE_WEIGHT_BLUE * this.getBlue();
};
Misuzu.Colour.prototype.getHex = function() {
var hex = (this.getRaw() & 0xFFFFFF).toString(16);
if(hex.length < 6)
hex = '000000'.substring(0, 6 - hex.length) + hex;
return hex;
};
Misuzu.Colour.prototype.setHex = function(hex) {
hex = (hex || '').toString();
if(hex[0] === '#')
hex = hex.substring(1);
if(/[^A-Fa-f0-9]/g.test(hex))
throw 'Argument contains invalid characters.';
if(hex.length === 3)
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
else if(hex.length !== 6)
throw 'Argument is not a hex string.';
return this.setRaw(parseInt(hex, 16));
};
Misuzu.Colour.prototype.getCSS = function() {
if(this.getInherit())
return 'inherit';
return '#' + this.getHex();
};
Misuzu.Colour.prototype.getCSSConstrast = function(dark, light, inheritIsDark) {
dark = dark || 'dark';
light = light || 'light';
if(this.getInherit())
return inheritIsDark ? dark : light;
return this.getLuminance() > Misuzu.Colour.READABILITY_THRESHOLD ? dark : light;
};

View file

@ -1,491 +0,0 @@
Misuzu.Comments = {};
Misuzu.Comments.Vote = DefineEnum({
none: 0,
like: 1,
dislike: -1,
});
Misuzu.Comments.init = function() {
var commentDeletes = document.getElementsByClassName('comment__action--delete');
for(var i = 0; i < commentDeletes.length; ++i) {
commentDeletes[i].addEventListener('click', Misuzu.Comments.deleteCommentHandler);
commentDeletes[i].dataset.href = commentDeletes[i].href;
commentDeletes[i].href = 'javascript:;';
}
var commentInputs = document.getElementsByClassName('comment__text--input');
for(var i = 0; i < commentInputs.length; ++i) {
commentInputs[i].form.action = 'javascript:void(0);';
commentInputs[i].form.addEventListener('submit', Misuzu.Comments.postCommentHandler);
commentInputs[i].addEventListener('keydown', Misuzu.Comments.inputCommentHandler);
}
var voteButtons = document.getElementsByClassName('comment__action--vote');
for(var i = 0; i < voteButtons.length; ++i) {
voteButtons[i].href = 'javascript:;';
voteButtons[i].addEventListener('click', Misuzu.Comments.voteCommentHandler);
}
var pinButtons = document.getElementsByClassName('comment__action--pin');
for(var i = 0; i < pinButtons.length; ++i) {
pinButtons[i].href = 'javascript:;';
pinButtons[i].addEventListener('click', Misuzu.Comments.pinCommentHandler);
}
};
Misuzu.Comments.postComment = function(formData, onSuccess, onFailure) {
if(!Misuzu.User.isLoggedIn()
|| !Misuzu.User.localUser.perms.canCreateComment()) {
if(onFailure)
onFailure("You aren't allowed to post comments.");
return;
}
var xhr = new XMLHttpRequest;
xhr.addEventListener('readystatechange', function() {
if(xhr.readyState !== 4)
return;
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
var json = JSON.parse(xhr.responseText),
message = json.error || json.message;
if(message && onFailure)
onFailure(message);
else if(!message && onSuccess)
onSuccess(json);
});
xhr.open('POST', Misuzu.Urls.format('comment-create'));
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
xhr.send(formData);
};
Misuzu.Comments.postCommentHandler = function() {
if(this.dataset.disabled)
return;
this.dataset.disabled = '1';
this.style.opacity = '0.5';
Misuzu.Comments.postComment(
Misuzu.FormUtils.extractFormData(this, true),
Misuzu.Comments.postCommentSuccess.bind(this),
Misuzu.Comments.postCommentFailed.bind(this)
);
};
Misuzu.Comments.inputCommentHandler = function(ev) {
if(ev.code === 'Enter' && ev.ctrlKey && !ev.altKey && !ev.shiftKey && !ev.metaKey) {
Misuzu.Comments.postComment(
Misuzu.FormUtils.extractFormData(this.form, true),
Misuzu.Comments.postCommentSuccess.bind(this.form),
Misuzu.Comments.postCommentFailed.bind(this.form)
);
}
};
Misuzu.Comments.postCommentSuccess = function(comment) {
if(this.classList.contains('comment--reply'))
this.parentNode.parentNode.querySelector('label.comment__action').click();
Misuzu.Comments.insertComment(comment, this);
this.style.opacity = '1';
this.dataset.disabled = '';
};
Misuzu.Comments.postCommentFailed = function(message) {
Misuzu.showMessageBox(message);
this.style.opacity = '1';
this.dataset.disabled = '';
};
Misuzu.Comments.deleteComment = function(commentId, onSuccess, onFailure) {
if(!Misuzu.User.isLoggedIn()
|| !Misuzu.User.localUser.perms.canDeleteOwnComment()) {
if(onFailure)
onFailure('You aren\'t allowed to delete comments.');
return;
}
var xhr = new XMLHttpRequest;
xhr.addEventListener('readystatechange', function() {
if(xhr.readyState !== 4)
return;
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
var json = JSON.parse(xhr.responseText),
message = json.error || json.message;
if(message && onFailure)
onFailure(message);
else if(!message && onSuccess)
onSuccess(json);
});
xhr.open('GET', Misuzu.Urls.format('comment-delete', [Misuzu.Urls.v('comment', commentId)]));
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
xhr.send();
};
Misuzu.Comments.deleteCommentHandler = function() {
var commentId = parseInt(this.dataset.commentId);
if(commentId < 1)
return;
Misuzu.Comments.deleteComment(
commentId,
function(info) {
var elem = document.getElementById('comment-' + info.id);
if(elem)
elem.parentNode.removeChild(elem);
},
function(message) { Misuzu.showMessageBox(message); }
);
};
Misuzu.Comments.pinComment = function(commentId, pin, onSuccess, onFailure) {
if(!Misuzu.User.isLoggedIn()
|| !Misuzu.User.localUser.perms.canPinComment()) {
if(onFailure)
onFailure("You aren't allowed to pin comments.");
return;
}
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function() {
if(xhr.readyState !== 4)
return;
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
var json = JSON.parse(xhr.responseText),
message = json.error || json.message;
if(message && onFailure)
onFailure(message);
else if(!message && onSuccess)
onSuccess(json);
};
xhr.open('GET', Misuzu.Urls.format('comment-' + (pin ? 'pin' : 'unpin'), [Misuzu.Urls.v('comment', commentId)]));
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
xhr.send();
};
Misuzu.Comments.pinCommentHandler = function() {
var target = this,
commentId = parseInt(target.dataset.commentId),
isPinned = target.dataset.commentPinned !== '0';
target.textContent = '...';
Misuzu.Comments.pinComment(
commentId,
!isPinned,
function(info) {
if(info.comment_pinned === null) {
target.textContent = 'Pin';
target.dataset.commentPinned = '0';
var pinElement = document.querySelector('#comment-' + info.comment_id + ' .comment__pin');
pinElement.parentElement.removeChild(pinElement);
} else {
target.textContent = 'Unpin';
target.dataset.commentPinned = '1';
var pinInfo = document.querySelector('#comment-' + info.comment_id + ' .comment__info'),
pinElement = document.createElement('div'),
pinTime = document.createElement('time'),
pinDateTime = new Date(info.comment_pinned + 'Z');
pinTime.title = pinDateTime.toLocaleString();
pinTime.dateTime = pinDateTime.toISOString();
pinTime.textContent = timeago.format(pinDateTime);
timeago.render(pinTime);
pinElement.className = 'comment__pin';
pinElement.appendChild(document.createTextNode('Pinned '));
pinElement.appendChild(pinTime);
pinInfo.appendChild(pinElement);
}
},
function(message) {
target.textContent = isPinned ? 'Unpin' : 'Pin';
Misuzu.showMessageBox(message);
}
);
};
Misuzu.Comments.voteComment = function(commentId, vote, onSuccess, onFailure) {
if(!Misuzu.User.isLoggedIn()
|| !Misuzu.User.localUser.perms.canVoteOnComment()) {
if(onFailure)
onFailure("You aren't allowed to vote on comments.");
return;
}
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function() {
if(xhr.readyState !== 4)
return;
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
var json = JSON.parse(xhr.responseText),
message = json.error || json.message;
if(message && onFailure)
onFailure(message);
else if(!message && onSuccess)
onSuccess(json);
};
xhr.open('GET', Misuzu.Urls.format('comment-vote', [Misuzu.Urls.v('comment', commentId), Misuzu.Urls.v('vote', vote)]));
xhr.setRequestHeader('X-Misuzu-XHR', 'comments');
xhr.send();
};
Misuzu.Comments.voteCommentHandler = function() {
var commentId = parseInt(this.dataset.commentId),
voteType = parseInt(this.dataset.commentVote),
buttons = document.querySelectorAll('.comment__action--vote[data-comment-id="' + commentId + '"]'),
likeButton = document.querySelector('.comment__action--like[data-comment-id="' + commentId + '"]'),
dislikeButton = document.querySelector('.comment__action--dislike[data-comment-id="' + commentId + '"]'),
classVoted = 'comment__action--voted';
for(var i = 0; i < buttons.length; ++i) {
buttons[i].textContent = buttons[i] === this ? '...' : '';
buttons[i].classList.remove(classVoted);
buttons[i].dataset.commentVote = buttons[i] === likeButton
? (voteType === Misuzu.Comments.Vote.like ? Misuzu.Comments.Vote.none : Misuzu.Comments.Vote.like ).toString()
: (voteType === Misuzu.Comments.Vote.dislike ? Misuzu.Comments.Vote.none : Misuzu.Comments.Vote.dislike).toString();
}
Misuzu.Comments.voteComment(
commentId,
voteType,
function(info) {
switch(voteType) {
case Misuzu.Comments.Vote.like:
likeButton.classList.add(classVoted);
break;
case Misuzu.Comments.Vote.dislike:
dislikeButton.classList.add(classVoted);
break;
}
likeButton.textContent = info.likes > 0 ? ('Like (' + info.likes.toLocaleString() + ')') : 'Like';
dislikeButton.textContent = info.dislikes > 0 ? ('Dislike (' + info.dislikes.toLocaleString() + ')') : 'Dislike';
},
function(message) {
likeButton.textContent = 'Like';
dislikeButton.textContent = 'Dislike';
Misuzu.showMessageBox(message);
}
);
};
Misuzu.Comments.insertComment = function(comment, form) {
var isReply = form.classList.contains('comment--reply'),
parent = isReply
? form.parentElement
: form.parentElement.parentElement.getElementsByClassName('comments__listing')[0],
repliesIndent = isReply
? (parseInt(parent.classList[1].substr(25)) + 1)
: 1,
commentElement = Misuzu.Comments.buildComment(comment, repliesIndent);
if(isReply)
parent.appendChild(commentElement);
else
parent.insertBefore(commentElement, parent.firstElementChild);
var placeholder = document.getElementById('_no_comments_notice_' + comment.category_id);
if(placeholder)
placeholder.parentNode.removeChild(placeholder);
};
Misuzu.Comments.buildComment = function(comment, layer) {
comment = comment || {};
layer = parseInt(layer || 0);
var date = new Date(comment.comment_created + 'Z'),
colour = new Misuzu.Colour(comment.user_colour),
actions = [],
commentTime = CreateElement({
tag: 'time',
props: {
className: 'comment__date',
title: date.toLocaleString(),
datetime: date.toISOString(),
},
children: timeago.format(date),
});
if(Misuzu.User.isLoggedIn() && Misuzu.User.localUser.perms.canVoteOnComment()) {
actions.push(CreateElement({
tag: 'a',
props: {
className: 'comment__action comment__action--link comment__action--vote comment__action--like',
'data-comment-id': comment.comment_id,
'data-comment-vote': Misuzu.Comments.Vote.like,
href: 'javascript:;',
onclick: Misuzu.Comments.voteCommentHandler,
},
children: 'Like',
}));
actions.push(CreateElement({
tag: 'a',
props: {
className: 'comment__action comment__action--link comment__action--vote comment__action--dislike',
'data-comment-id': comment.comment_id,
'data-comment-vote': Misuzu.Comments.Vote.dislike,
href: 'javascript:;',
onclick: Misuzu.Comments.voteCommentHandler,
},
children: 'Dislike',
}));
}
actions.push(CreateElement({
tag: 'label',
props: {
className: 'comment__action comment__action--link',
'for': 'comment-reply-toggle-' + comment.comment_id.toString()
},
children: 'Reply',
}));
var commentText = CreateBasicElement('comment__text');
if(comment.comment_html)
commentText.innerHTML = comment.comment_html;
else
commentText.textContent = comment.comment_text;
var commentElem = CreateElement({
props: {
className: 'comment',
id: 'comment-' + comment.comment_id.toString(),
},
children: [
{
props: { className: 'comment__container', },
children: [
{
tag: 'a',
props: {
className: 'comment__avatar',
href: Misuzu.Urls.format('user-profile', [{name:'user',value:comment.user_id}]),
},
children: {
tag: 'img',
props: {
className: 'avatar',
alt: comment.username,
width: (layer <= 1 ? 50 : 40),
height: (layer <= 1 ? 50 : 40),
src: Misuzu.Urls.format('user-avatar', [
{ name: 'user', value: comment.user_id },
{ name: 'res', value: layer <= 1 ? 100 : 80 }
]),
},
},
},
{
props: { className: 'comment__content', },
children: [
{
props: { className: 'comment__info', },
children: [
{
tag: 'a',
props: {
className: 'comment__user comment__user--link',
href: Misuzu.Urls.format('user-profile', [{name:'user',value:comment.user_id}]),
style: '--user-colour: ' + colour.getCSS(),
},
children: comment.username,
},
{
tag: 'a',
props: {
className: 'comment__link',
href: '#comment-' + comment.comment_id.toString(),
},
children: commentTime,
},
],
},
commentText,
{
props: { className: 'comment__actions', },
children: actions,
},
],
},
],
},
{
props: {
className: 'comment__replies comment__replies--indent-' + layer.toString(),
id: 'comment-' + comment.comment_id.toString() + '-replies',
},
children: [
{
tag: 'input',
props: {
className: 'comment__reply-toggle',
type: 'checkbox',
id: ('comment-reply-toggle-' + comment.comment_id.toString()),
},
},
{
tag: 'form',
props: {
className: 'comment comment--input comment--reply',
id: 'comment-reply-' + comment.comment_id.toString(),
method: 'post',
action: 'javascript:;',
onsubmit: Misuzu.Comments.postCommentHandler,
},
children: [
{ tag: 'input', props: { type: 'hidden', name: 'csrf', value: Misuzu.CSRF.getToken() } },
{ tag: 'input', props: { type: 'hidden', name: 'comment[category]', value: comment.category_id } },
{ tag: 'input', props: { type: 'hidden', name: 'comment[reply]', value: comment.comment_id } },
{
props: { className: 'comment__container' },
children: [
{
props: { className: 'avatar comment__avatar' },
children: {
tag: 'img',
props: {
className: 'avatar',
width: 40,
height: 40,
src: Misuzu.Urls.format('user-avatar', [{name: 'user', value: comment.user_id}, {name: 'res', value: 80}]),
},
},
},
{
props: { className: 'comment__content' },
children: [
{ props: { className: 'comment__info' } },
{
tag: 'textarea',
props: {
className: 'comment__text input__textarea comment__text--input',
name: 'comment[text]',
placeholder: 'Share your extensive insights...',
onkeydown: Misuzu.Comments.inputCommentHandler,
},
},
{
props: { className: 'comment__actions' },
children: {
tag: 'button',
props: {
className: 'input__button comment__action comment__action--button comment__action--post',
},
children: 'Reply',
},
},
],
},
],
},
],
},
],
},
],
});
timeago.render(commentTime);
return commentElem;
};

View file

@ -1,17 +0,0 @@
Misuzu.CSRF = {};
Misuzu.CSRF.tokenValue = undefined;
Misuzu.CSRF.tokenElement = undefined;
Misuzu.CSRF.init = function() {
Misuzu.CSRF.tokenElement = document.querySelector('[name="csrf-token"]');
Misuzu.CSRF.tokenValue = Misuzu.CSRF.tokenElement.getAttribute('value');
};
Misuzu.CSRF.getToken = function() { return Misuzu.CSRF.tokenValue || ''; };
Misuzu.CSRF.setToken = function(token) {
if(!token)
return;
Misuzu.CSRF.tokenElement.setAttribute('value', Misuzu.CSRF.tokenValue = token);
var elems = document.getElementsByName('csrf');
for(var i = 0; i < elems.length; ++i)
elems[i].value = token;
};

View file

@ -1,12 +0,0 @@
Misuzu.Events = {};
Misuzu.Events.getList = function() {
return [
new Misuzu.Events.Christmas2019,
];
};
Misuzu.Events.dispatch = function() {
var list = Misuzu.Events.getList();
for(var i = 0; i < list.length; ++i)
if(list[i].isActive())
list[i].dispatch();
};

View file

@ -1,33 +0,0 @@
Misuzu.Events.Christmas2019 = function() {
this.propName = propName = 'msz-christmas-' + (new Date).getFullYear().toString();
};
Misuzu.Events.Christmas2019.prototype.changeColour = function() {
var count = parseInt(localStorage.getItem(this.propName));
document.body.style.setProperty('--header-accent-colour', (count++ % 2) ? 'green' : 'red');
localStorage.setItem(this.propName, count.toString());
};
Misuzu.Events.Christmas2019.prototype.isActive = function() {
var d = new Date;
return d.getMonth() === 11 && d.getDate() > 5 && d.getDate() < 27;
};
Misuzu.Events.Christmas2019.prototype.dispatch = function() {
var headerBg = document.querySelector('.header__background'),
menuBgs = document.querySelectorAll('.header__desktop__submenu__background');
if(!localStorage.getItem(this.propName))
localStorage.setItem(this.propName, '0');
if(headerBg)
headerBg.style.transition = 'background-color .4s';
setTimeout(function() {
if(headerBg)
headerBg.style.transition = 'background-color 1s';
for(var i = 0; i < menuBgs.length; i++)
menuBgs[i].style.transition = 'background-color 1s';
}, 1000);
this.changeColour();
setInterval(this.changeColour, 10000);
};

View file

@ -1,81 +0,0 @@
Misuzu.FormUtils = {};
Misuzu.FormUtils.extractFormData = function(form, resetSource) {
var formData = new FormData;
for(var i = 0; i < form.length; ++i) {
if(form[i].type.toLowerCase() === 'checkbox' && !form[i].checked)
continue;
formData.append(form[i].name, form[i].value || '');
}
if(resetSource)
Misuzu.FormUtils.resetFormData(form);
return formData;
};
Misuzu.FormUtils.resetFormData = function(form, defaults) {
defaults = defaults || [];
for(var i = 0; i < form.length; ++i) {
var input = form[i];
switch(input.type.toLowerCase()) {
case 'checkbox':
input.checked = false;
break;
case 'hidden':
var hiddenDefault = defaults.find(function(fhd) { return fhd.Name.toLowerCase() === input.name.toLowerCase(); });
if(hiddenDefault)
input.value = hiddenDefault.Value;
break;
default:
input.value = '';
}
}
};
Misuzu.FormUtils.initDataRequestMethod = function() {
var links = document.links;
for(var i = 0; i < links.length; ++i) {
if(!links[i].href || !links[i].dataset || !links[i].dataset.mszMethod)
continue;
links[i].addEventListener('click', function(ev) {
Misuzu.FormUtils.handleDataRequestMethod(this, this.dataset.mszMethod, this.href);
ev.preventDefault();
});
}
};
Misuzu.FormUtils.handleDataRequestMethod = function(elem, method, url) {
var split = url.split('?', 2),
target = split[0],
query = split[1] || null;
if(elem.getAttribute('disabled'))
return;
elem.setAttribute('disabled', 'disabled');
var xhr = new XMLHttpRequest;
xhr.onreadystatechange = function(ev) {
if(xhr.readyState !== 4)
return;
elem.removeAttribute('disabled');
if(xhr.status === 301 || xhr.status === 302 || xhr.status === 307 || xhr.status === 308) {
location.assign(xhr.getResponseHeader('X-Misuzu-Location'));
return;
}
if(xhr.status >= 400 && xhr.status <= 599) {
alert(xhr.responseText);
return;
}
};
xhr.open(method, target);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.setRequestHeader('X-Misuzu-CSRF', Misuzu.CSRF.getToken());
xhr.setRequestHeader('X-Misuzu-XHR', '1');
xhr.send(query);
};

View file

@ -1 +0,0 @@
Misuzu.Forum = {};

View file

@ -1,178 +0,0 @@
Misuzu.Forum.Editor = {};
Misuzu.Forum.Editor.allowWindowClose = false;
Misuzu.Forum.Editor.init = function() {
var postingForm = document.querySelector('.js-forum-posting');
if(!postingForm)
return;
var postingButtons = postingForm.querySelector('.js-forum-posting-buttons'),
postingText = postingForm.querySelector('.js-forum-posting-text'),
postingParser = postingForm.querySelector('.js-forum-posting-parser'),
postingPreview = postingForm.querySelector('.js-forum-posting-preview'),
postingMode = postingForm.querySelector('.js-forum-posting-mode'),
previewButton = document.createElement('button'),
bbcodeButtons = document.querySelector('.forum__post__actions--bbcode'),
markdownButtons = document.querySelector('.forum__post__actions--markdown'),
markupButtons = document.querySelectorAll('.forum__post__action--tag');
// hack: don't prompt user when hitting submit, really need to make this not stupid.
postingButtons.firstElementChild.addEventListener('click', function() {
Misuzu.Forum.Editor.allowWindowClose = true;
});
window.addEventListener('beforeunload', function(ev) {
if(!Misuzu.Forum.Editor.allowWindowClose && postingText.value.length > 0) {
ev.preventDefault();
ev.returnValue = '';
}
});
for(var i = 0; i < markupButtons.length; ++i)
(function(currentBtn) {
currentBtn.addEventListener('click', function(ev) {
postingText.insertTags(currentBtn.dataset.tagOpen, currentBtn.dataset.tagClose);
});
})(markupButtons[i]);
Misuzu.Forum.Editor.switchButtons(parseInt(postingParser.value));
var lastPostText = '',
lastPostParser = null;
postingParser.addEventListener('change', function() {
var postParser = parseInt(postingParser.value);
Misuzu.Forum.Editor.switchButtons(postParser);
if(postingPreview.hasAttribute('hidden'))
return;
// dunno if this would even be possible, but ech
if(postParser === lastPostParser)
return;
postingParser.setAttribute('disabled', 'disabled');
previewButton.setAttribute('disabled', 'disabled');
previewButton.classList.add('input__button--busy');
Misuzu.Forum.Editor.renderPreview(postParser, lastPostText, function(success, text) {
if(!success) {
Misuzu.showMessageBox(text);
return;
}
if(postParser === Misuzu.Parser.markdown)
postingPreview.classList.add('markdown');
else
postingPreview.classList.remove('markdown');
lastPostParser = postParser;
postingPreview.innerHTML = text;
previewButton.removeAttribute('disabled');
postingParser.removeAttribute('disabled');
previewButton.classList.remove('input__button--busy');
});
});
previewButton.className = 'input__button';
previewButton.textContent = 'Preview';
previewButton.type = 'button';
previewButton.value = 'preview';
previewButton.addEventListener('click', function() {
if(previewButton.value === 'back') {
postingPreview.setAttribute('hidden', 'hidden');
postingText.removeAttribute('hidden');
previewButton.value = 'preview';
previewButton.textContent = 'Preview';
postingMode.textContent = postingMode.dataset.original;
postingMode.dataset.original = null;
} else {
var postText = postingText.value,
postParser = parseInt(postingParser.value);
if(lastPostText === postText && lastPostParser === postParser) {
postingPreview.removeAttribute('hidden');
postingText.setAttribute('hidden', 'hidden');
previewButton.value = 'back';
previewButton.textContent = 'Back';
postingMode.dataset.original = postingMode.textContent;
postingMode.textContent = 'Previewing';
return;
}
postingParser.setAttribute('disabled', 'disabled');
previewButton.setAttribute('disabled', 'disabled');
previewButton.classList.add('input__button--busy');
Misuzu.Forum.Editor.renderPreview(postParser, postText, function(success, text) {
if(!success) {
Misuzu.showMessageBox(text);
return;
}
if(postParser === Misuzu.Parser.markdown)
postingPreview.classList.add('markdown');
else
postingPreview.classList.remove('markdown');
lastPostText = postText;
lastPostParser = postParser;
postingPreview.innerHTML = text;
postingPreview.removeAttribute('hidden');
postingText.setAttribute('hidden', 'hidden');
previewButton.value = 'back';
previewButton.textContent = 'Back';
previewButton.removeAttribute('disabled');
postingParser.removeAttribute('disabled');
previewButton.classList.remove('input__button--busy');
postingMode.dataset.original = postingMode.textContent;
postingMode.textContent = 'Previewing';
});
}
});
postingButtons.insertBefore(previewButton, postingButtons.firstChild);
};
Misuzu.Forum.Editor.switchButtons = function(parser) {
var bbcodeButtons = document.querySelector('.forum__post__actions--bbcode'),
markdownButtons = document.querySelector('.forum__post__actions--markdown');
switch(parser) {
default:
case Misuzu.Parser.plain:
bbcodeButtons.hidden = markdownButtons.hidden = true;
break;
case Misuzu.Parser.bbcode:
bbcodeButtons.hidden = false;
markdownButtons.hidden = true;
break;
case Misuzu.Parser.markdown:
bbcodeButtons.hidden = true;
markdownButtons.hidden = false;
break;
}
};
Misuzu.Forum.Editor.renderPreview = function(parser, text, callback) {
if(!callback)
return;
parser = parseInt(parser);
text = text || '';
var xhr = new XMLHttpRequest,
formData = new FormData;
formData.append('post[mode]', 'preview');
formData.append('post[text]', text);
formData.append('post[parser]', parser.toString());
xhr.addEventListener('readystatechange', function() {
if(xhr.readyState !== XMLHttpRequest.DONE)
return;
if(xhr.status === 200)
callback(true, xhr.response);
else
callback(false, 'Failed to render preview.');
});
xhr.open('POST', Misuzu.Urls.format('forum-topic-new'));
xhr.withCredentials = true;
xhr.send(formData);
};

View file

@ -1,49 +0,0 @@
Misuzu.Forum.Polls = {};
Misuzu.Forum.Polls.init = function() {
var polls = document.getElementsByClassName('js-forum-poll');
if(!polls.length)
return;
for(var i = 0; i < polls.length; ++i)
Misuzu.Forum.Polls.initPoll(polls[i]);
};
Misuzu.Forum.Polls.initPoll = function() {
var options = poll.getElementsByClassName('input__checkbox__input'),
votesRemaining = poll.querySelector('.js-forum-poll-remaining'),
votesRemainingCount = poll.querySelector('.js-forum-poll-remaining-count'),
votesRemainingPlural = poll.querySelector('.js-forum-poll-remaining-plural'),
maxVotes = parseInt(poll.dataset.pollMaxVotes);
if(maxVotes < 2)
return;
var votes = maxVotes;
for(var i = 0; i < options.length; ++i) {
if(options[i].checked) {
if(votes < 1)
options[i].checked = false;
else
votes--;
}
options[i].addEventListener('change', function(ev) {
if(this.checked) {
if(votes < 1) {
this.checked = false;
ev.preventDefault();
return;
}
votes--;
} else
votes++;
votesRemainingCount.textContent = votes.toString();
votesRemainingPlural.hidden = votes == 1;
});
}
votesRemaining.hidden = false;
votesRemainingCount.textContent = votes.toString();
votesRemainingPlural.hidden = votes == 1;
};

View file

@ -1,15 +0,0 @@
Misuzu.Perms = function(perms) {
this.perms = perms || {};
};
Misuzu.Perms.prototype.perms = undefined;
Misuzu.Perms.check = function(section, value) {
return function() { return this.perms[section] && (this.perms[section] & value) > 0; };
};
// Comment permissions
Misuzu.Perms.prototype.canCreateComment = Misuzu.Perms.check('comments', 0x01);
Misuzu.Perms.prototype.canDeleteOwnComment = Misuzu.Perms.check('comments', 0x08 | 0x10);
Misuzu.Perms.prototype.canDeleteAnyComment = Misuzu.Perms.check('comments', 0x10);
Misuzu.Perms.prototype.canLockCommentSection = Misuzu.Perms.check('comments', 0x20);
Misuzu.Perms.prototype.canPinComment = Misuzu.Perms.check('comments', 0x40);
Misuzu.Perms.prototype.canVoteOnComment = Misuzu.Perms.check('comments', 0x80);

View file

@ -1,66 +0,0 @@
Misuzu.Urls = {};
Misuzu.Urls.registry = [];
Misuzu.Urls.loadFromDocument = function() {
var elem = document.getElementById('js-urls-list');
if(!elem)
return;
Misuzu.Urls.registry = JSON.parse(elem.textContent);
};
Misuzu.Urls.handleVariable = function(value, vars) {
if(value[0] === '<' && value.slice(-1) === '>')
return (vars.find(function(x) { return x.name == value.slice(1, -1); }) || {}).value || '';
if(value[0] === '[' && value.slice(-1) === ']')
return ''; // not sure if there's a proper substitute for this, should probably resolve these in url_list
if(value[0] === '{' && value.slice(-1) === '}')
return Misuzu.CSRF.getToken();
// Allow file extensions
var split = value.split('.'),
extension = split[split.length - 1],
fileName = split.slice(0, -1).join('.');
if(value !== fileName) {
var fallback = Misuzu.Urls.handleVariable(fileName, vars);
if(fallback !== fileName)
return fallback + '.' + extension;
}
return value;
};
Misuzu.Urls.v = function(name, value) {
if(typeof value === 'undefined' || value === null)
value = '';
return { name: name.toString(), value: value.toString() };
};
Misuzu.Urls.format = function(name, vars) {
vars = vars || [];
var entry = Misuzu.Urls.registry.find(function(x) { return x.name == name; });
if(!entry || !entry.path)
return '';
var split = entry.path.split('/');
for(var i = 0; i < split.length; ++i)
split[i] = Misuzu.Urls.handleVariable(split[i], vars);
var url = split.join('/');
if(entry.query) {
url += '?';
for(var i = 0; i < entry.query.length; ++i) {
var query = entry.query[i],
value = Misuzu.Urls.handleVariable(query.value, vars);
if(!value || (query.name === 'page' && parseInt(value) < 2))
continue;
url += query.name + '=' + value.toString() + '&';
}
url = url.replace(/^[\?\&]+|[\?\&]+$/g, '');
}
if(entry.fragment)
url += ('#' + Misuzu.Urls.handleVariable(entry.fragment, vars)).replace(/[\#]+$/g, '');
return url;
};

View file

@ -1,19 +0,0 @@
Misuzu.User = function(userInfo) {
this.id = parseInt(userInfo.user_id || 0);
this.name = (userInfo.username || '').toString();
this.colour = new Misuzu.Colour(userInfo.user_colour || Misuzu.Colour.FLAG_INHERIT);
this.perms = new Misuzu.Perms(userInfo.perms || {});
};
Misuzu.User.localUser = undefined;
Misuzu.User.refreshLocalUser = function() {
var userInfo = document.getElementById('js-user-info');
if(!userInfo)
Misuzu.User.localUser = undefined;
else
Misuzu.User.localUser = new Misuzu.User(JSON.parse(userInfo.textContent));
};
Misuzu.User.isLoggedIn = function() { return Misuzu.User.localUser !== undefined; };
Misuzu.User.prototype.getId = function() { return this.id || 0; };
Misuzu.User.prototype.getUsername = function() { return this.name || ''; };
Misuzu.User.prototype.getColour = function() { return this.colour || null; };

View file

@ -1,104 +0,0 @@
Misuzu.UserRelations = {};
Misuzu.UserRelations.Type = DefineEnum({ none: 0, follow: 1, });
Misuzu.UserRelations.init = function() {
var buttons = document.getElementsByClassName('js-user-relation-action');
for(var i = 0; i < buttons.length; ++i) {
switch(buttons[i].tagName.toLowerCase()) {
case 'a':
buttons[i].removeAttribute('href');
buttons[i].removeAttribute('target');
buttons[i].removeAttribute('rel');
break;
}
buttons[i].addEventListener('click', Misuzu.UserRelations.setRelationHandler);
}
};
Misuzu.UserRelations.setRelation = function(user, type, onSuccess, onFailure) {
var xhr = new XMLHttpRequest;
xhr.addEventListener('readystatechange', function() {
if(xhr.readyState !== 4)
return;
Misuzu.CSRF.setToken(xhr.getResponseHeader('X-Misuzu-CSRF'));
var json = JSON.parse(xhr.responseText),
message = json.error || json.message;
if(message && onFailure)
onFailure(message);
else if(!message && onSuccess)
onSuccess(json);
});
xhr.open('GET', Misuzu.Urls.format('user-relation-create', [Misuzu.Urls.v('user', user), Misuzu.Urls.v('type', type)]));
xhr.setRequestHeader('X-Misuzu-XHR', 'user_relation');
xhr.setRequestHeader('X-Misuzu-CSRF', Misuzu.CSRF.getToken());
xhr.send();
};
Misuzu.UserRelations.ICO_ADD = 'fas fa-user-plus';
Misuzu.UserRelations.ICO_REM = 'fas fa-user-minus';
Misuzu.UserRelations.ICO_BUS = 'fas fa-spinner fa-pulse';
Misuzu.UserRelations.BTN_BUS = 'input__button--busy';
Misuzu.UserRelations.setRelationHandler = function(ev) {
var target = this,
userId = parseInt(target.dataset.relationUser),
relationType = parseInt(target.dataset.relationType),
isButton = target.classList.contains('input__button'),
icon = target.querySelector('[class^="fa"]');
if(isButton) {
if(target.classList.contains(Misuzu.UserRelations.BTN_BUS))
return;
target.classList.add(Misuzu.UserRelations.BTN_BUS);
}
if(icon)
icon.className = Misuzu.UserRelations.ICO_BUS;
Misuzu.UserRelations.setRelation(
userId,
relationType,
function(info) {
target.classList.remove(Misuzu.UserRelations.BTN_BUS);
switch(info.relation_type) {
case Misuzu.UserRelations.Type.none:
if(isButton) {
if(target.classList.contains('input__button--destroy'))
target.classList.remove('input__button--destroy');
target.textContent = 'Follow';
}
if(icon) {
icon.className = Misuzu.UserRelations.ICO_ADD;
target.title = 'Follow';
}
target.dataset.relationType = Misuzu.UserRelations.Type.follow.toString();
break;
case Misuzu.UserRelations.Type.follow:
if(isButton) {
if(!target.classList.contains('input__button--destroy'))
target.classList.add('input__button--destroy');
target.textContent = 'Unfollow';
}
if(icon) {
icon.className = Misuzu.UserRelations.ICO_REM;
target.title = 'Unfollow';
}
target.dataset.relationType = Misuzu.UserRelations.Type.none.toString();
break;
}
},
function(msg) {
target.classList.remove(Misuzu.UserRelations.BTN_BUS);
Misuzu.showMessageBox(msg);
}
);
};

View file

@ -1,9 +1,7 @@
.input__button {
background-color: var(--background-colour);
font-family: var(--font-regular);
font-size: 1.2em;
line-height: 1.4em;
padding: 5px 10px;
padding: 4px 12px;
min-width: 80px;
text-align: center;
cursor: pointer;
@ -15,6 +13,8 @@
align-items: center;
justify-content: center;
text-decoration: none;
font-size: inherit;
line-height: inherit;
}
.input__button:hover, .input__button:active,
.input__button:focus, .input__button:checked,

View file

@ -4,10 +4,12 @@
background: #222;
color: #fff;
min-width: 150px;
font-size: 1.2em;
border-radius: 2px;
box-shadow: inset 0 0 4px #111;
transition: border-color .2s;
font-family: inherit;
font-size: 1em;
line-height: 1.25em;
}
.input__select:focus {
border-color: var(--accent-colour);

View file

@ -1,5 +1,4 @@
.input__text {
font-size: 1.2em;
border: 1px solid #222;
padding: 5px 10px;
background: #222;
@ -7,8 +6,11 @@
border-radius: 2px;
box-shadow: inset 0 0 4px #111;
transition: border-color .2s;
font-family: inherit;
font-size: 1em;
line-height: 1.25em;
}
.input__text:focus { border-color: var(--accent-colour); }
.input__text--readonly { color: #888; }
.input__text--monospace { font-family: var(--font-monospace); }
.input__text--monospace { font-family: var(--font-monospace); font-feature-settings: 'ss07' 1; }
.input__text--centre { text-align: center; }

View file

@ -1,11 +1,11 @@
.input__textarea {
font-size: 1.2em;
border: 1px solid #222;
padding: 5px 10px;
padding: 4px 12px;
vertical-align: bottom;
background: #222;
color: #fff;
font-family: var(--font-monospace);
font-feature-settings: 'ss07' 1;
border-radius: 2px;
box-shadow: inset 0 0 4px #111;
transition: border-color .2s;

View file

@ -10,9 +10,8 @@
}
.input__upload__selection {
text-align: center;
font-size: 1.2em;
border: 1px solid #222;
padding: 5px 10px;
padding: 4px 12px;
background: #222;
color: #fff;
border-radius: 2px;

31
assets/misuzu.css/bb.css Normal file
View file

@ -0,0 +1,31 @@
.bb-h1, .bb-h2,
.bb-h3, .bb-h4,
.bb-h5, .bb-h6 {
font-weight: 700;
line-height: 1.5em;
display: inline-block;
width: 100%;
margin-bottom: .25em;
}
.bb-h1 {
font-size: 2em;
border-bottom: 1px solid var(--accent-colour);
}
.bb-h2 {
font-size: 1.5em;
border-bottom: 1px solid var(--accent-colour);
}
.bb-h3 {
font-size: 1.25em;
}
.bb-h4 {
font-size: 1em;
}
.bb-h5 {
font-size: 0.875em;
}
.bb-h6 {
font-size: 0.85em;
color: var(--accent-colour);
}

View file

@ -43,7 +43,7 @@
.changelog__change__username {
color: inherit;
font-size: 1.4em;
font-size: 1.375em;
line-height: 1.5em;
text-decoration: none;
}
@ -52,7 +52,7 @@
}
.changelog__change__userrole {
font-size: .9em;
font-size: .875em;
line-height: 1.5em;
color: inherit;
text-decoration: none;
@ -64,15 +64,13 @@
.changelog__change__date {
color: inherit;
text-decoration: none;
font-size: 1.1em;
line-height: 1.5em;
}
.changelog__change__date:hover {
text-decoration: underline;
}
.changelog__change__text {
line-height: 1.2em;
line-height: 1.25em;
flex: 1 1 auto;
word-wrap: break-word;
overflow: hidden;

View file

@ -1,6 +1,8 @@
.changelog__entry {
display: flex;
margin: 5px;
font-size: .875em;
line-height: 1.5em;
}
.changelog__entry__info { display: flex; }
@ -68,7 +70,7 @@
.changelog__entry__tags {
display: flex;
flex-wrap: wrap;
font-size: .9em;
font-size: .75em;
line-height: 1.5em;
}

View file

@ -6,8 +6,6 @@
text-decoration: none;
padding: 1px 3px;
color: var(--accent-colour);
font-size: 1.2em;
line-height: 1.5em;
}
.changelog__listing__date:hover {
text-decoration: underline;

View file

@ -21,8 +21,8 @@
}
.changelog__log__text {
padding: 8px 12px;
font-size: 1.5em;
line-height: 1.3em;
font-size: 1.375em;
line-height: 1.25em;
align-self: center;
flex: 1 1 auto;
overflow: hidden;

View file

@ -0,0 +1,121 @@
.comments-entry-main {
display: grid;
grid-template-columns: 46px 1fr;
gap: 2px;
}
.comments-entry-root {
padding-bottom: 2px;
border-top: 1px solid var(--accent-colour);
}
.comments-entry-replies {
margin-left: 25px;
}
.comments-entry-avatar {
flex: 0 0 auto;
padding: 4px;
}
.comments-entry-wrap {
flex: 0 1 auto;
display: flex;
flex-direction: column;
gap: 2px;
}
.comments-entry-meta {
display: flex;
gap: 4px;
margin-top: 4px;
}
.comments-entry-user {
display: flex;
}
.comments-entry-user-link {
text-decoration: none;
}
.comments-entry-user-link:hover,
.comments-entry-user-link:focus {
text-decoration: underline solid var(--user-colour, var(--text-colour, #fff));
}
.comments-entry-user-dead {
text-decoration: line-through;
}
.comments-entry-time {
display: flex;
gap: 6px;
}
.comments-entry-time-edited,
.comments-entry-time-pinned,
.comments-entry-time-deleted {
margin-left: 6px;
}
.comments-entry-time-pinned .comments-entry-time-icon {
rotate: 45deg;
}
.comments-entry-time-link {
color: inherit;
text-decoration: none;
}
.comments-entry-time-link:hover,
.comments-entry-time-link:focus {
text-decoration: underline;
}
.comments-entry-actions {
display: flex;
gap: 2px;
margin-top: 2px;
}
.comments-entry-actions-group {
display: flex;
border-radius: 3px;
padding: 1px;
gap: 1px;
transition: opacity .1s;
}
.comments-entry-actions-group-votes,
.comments-entry-actions-group-replies {
border: 1px solid var(--accent-colour);
}
.comments-entry-actions-group-disabled {
opacity: .5;
}
.comments-entry-action {
background: transparent;
border-width: 0;
border-radius: 2px;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 3px 6px;
cursor: pointer;
transition: background-color .1s;
min-width: 24px;
min-height: 22px;
color: inherit;
}
.comments-entry-action:not([disabled]):hover,
.comments-entry-action:not([disabled]):focus {
background: var(--comments-entry-action-background-hover, #fff4);
}
.comments-entry-action-reply-active {
background: #fff2;
}
.comments-entry-action-vote-like.comments-entry-action-vote-cast {
background: #0808;
}
.comments-entry-action-vote-like {
--comments-entry-action-background-hover: #0804;
}
.comments-entry-action-vote-dislike.comments-entry-action-vote-cast {
background: #c008;
}
.comments-entry-action-vote-dislike {
--comments-entry-action-background-hover: #c004;
}

View file

@ -0,0 +1,73 @@
.comments-form {
border: 1px solid var(--accent-colour);
border-radius: 3px;
margin: 2px 0;
display: grid;
grid-template-columns: 46px 1fr;
transition: opacity .1s;
}
.comments-form-root {
margin: 2px;
}
.comments-form-disabled {
opacity: .5;
}
.comments-form-avatar {
flex: 0 0 auto;
padding: 3px;
}
.comments-form-wrap {
display: grid;
grid-template-rows: 1fr 35px;
gap: 2px;
margin: 3px;
margin-left: 0;
overflow: hidden;
}
.comments-form-input {
overflow: hidden;
}
.comments-form-input textarea {
min-width: 100%;
max-width: 100%;
width: 100%;
min-height: 40px;
height: 0;
}
.comments-form-root .comments-form-input textarea {
min-height: 60px;
}
.comments-form-actions {
display: flex;
align-items: center;
overflow: hidden;
gap: 6px;
}
.comments-form-status {
flex: 1 1 auto;
padding: 0 6px;
overflow: hidden;
transition: color .2s;
}
.comments-form-status-text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.comments-form-status-error {
color: #c00;
}
.comments-form-pin {
flex: 0 0 auto;
font-size: 1.25em;
line-height: 1.375em;
}
.comments-form-post {
flex: 0 0 auto;
}

View file

@ -0,0 +1,8 @@
.comments-listing {
display: flex;
flex-direction: column;
gap: 2px;
}
.comments-listing-root {
margin: 2px;
}

View file

@ -0,0 +1,5 @@
@include comments/form.css;
@include comments/entry.css;
@include comments/listing.css;
@include comments/notice.css;
@include comments/options.css;

View file

@ -0,0 +1,14 @@
.comments-notice {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
font-size: 1.25em;
line-height: 1.375em;
gap: 6px;
padding: 12px;
margin: 2px;
}
.comments-notice-inner {
flex: 0 1 auto;
}

View file

@ -0,0 +1,32 @@
.comments-options {
display: flex;
justify-content: flex-end;
margin: 2px;
padding: 6px;
gap: 6px;
}
.comments-options-actions {
display: flex;
gap: 6px;
}
.comments-options-action {
color: inherit;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 4px 8px;
background-color: transparent;
border-width: 0;
border-radius: 4px;
transition: background-color .1s, opacity .1s;
}
.comments-options-action[disabled] {
opacity: .5;
}
.comments-options-action:not([disabled]):hover,
.comments-options-action:not([disabled]):focus {
background-color: #fff4;
}

View file

@ -1,7 +1,6 @@
.container {
background-color: var(--container-colour);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
text-shadow: 0 1px 4px #000;
overflow: hidden;
word-wrap: break-word;
}
@ -14,10 +13,12 @@
overflow: hidden;
}
.container__title__text {
font-size: 1.5em;
font-size: 1.125rem;
line-height: 1.5em;
padding: 8px 10px;
word-wrap: break-word;
font-weight: 500;
min-height: 44px;
}
.container__title__link {
color: inherit;
@ -31,7 +32,6 @@
width: 100%;
height: 100%;
mask-image: linear-gradient(0deg, transparent 10%, var(--background-colour) 100%);
-webkit-mask-image: linear-gradient(0deg, transparent 10%, var(--background-colour) 100%);
background: var(--background-pattern);
background-color: var(--accent-colour);
background-blend-mode: multiply;

View file

@ -0,0 +1,104 @@
.eeprom-widget {
background-color: var(--container-colour);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
text-shadow: 0 1px 4px #000;
display: flex;
min-height: 50px;
}
.eeprom-widget-form {
display: flex;
text-align: center;
justify-content: center;
align-items: center;
flex: 0 0 auto;
min-width: 154px; /* same width as sidebar */
background-color: #aaa1;
transition: background-color .2s;
}
.eeprom-widget-form-input {
display: none;
visibility: hidden;
}
.eeprom-widget-form-text {
font-size: 1.325em;
line-height: 1.5em;
}
.eeprom-widget-form:focus,
.eeprom-widget-form:hover {
background-color: #fff1;
}
.eeprom-widget-form:active {
background-color: #ccc1;
}
.eeprom-widget-history {
overflow-y: auto;
scrollbar-width: thin;
}
.eeprom-widget-history-items {
display: flex;
padding: 0 3px;
}
.eeprom-widget-file {
margin: 4px 1px;
padding-top: 2px; /* adjust for the progress bar */
border: 1px solid var(--accent-colour);
border-radius: 2px;
overflow: hidden;
width: 200px;
flex: 0 0 auto;
}
.eeprom-widget-file-fail {
--accent-color: #c00;
}
.eeprom-widget-file-info {
padding: 0 2px;
}
.eeprom-widget-file-name {
color: #fff;
text-decoration: none;
}
.eeprom-widget-file-name-value {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.eeprom-widget-file-name:hover,
.eeprom-widget-file-name:focus {
text-decoration: underline;
}
.eeprom-widget-file-progress {
font-size: .875em;
line-height: 1.325em;
text-align: right;
padding: 0 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.eeprom-widget-file-progress a {
color: var(--accent-colour);
text-decoration: none;
}
.eeprom-widget-file-progress a:hover,
.eeprom-widget-file-progress a:focus {
text-decoration: underline;
}
.eeprom-widget-file-bar {
width: 100%;
height: 2px;
display: flex;
justify-content: flex-start;
align-items: flex-end;
}
.eeprom-widget-file-bar-fill {
width: 0%;
height: 2px;
background-color: var(--accent-colour);
transition: width .1s, height .1s;
}
.eeprom-widget-file-done .eeprom-widget-file-bar-fill {
height: 0;
}

369
assets/misuzu.css/embed.css Normal file
View file

@ -0,0 +1,369 @@
.embed {
display: inline-block;
overflow: hidden;
}
.embed iframe {
width: 100%;
height: 100%;
display: block;
}
.embedph {
display: inline-block;
overflow: hidden;
cursor: pointer;
color: var(--text-colour);
text-decoration: none;
}
.embedph:hover .embedph-bg img,
.embedph:active .embedph-bg img,
.embedph:focus .embedph-bg img,
.embedph:focus-within .embedph-bg img {
transform: scale(1.1);
filter: blur(10px) brightness(80%);
}
.embedph:hover .embedph-info,
.embedph:active .embedph-info,
.embedph:focus .embedph-info,
.embedph:focus-within .embedph-info {
opacity: 0;
}
.embedph:hover .embedph-play,
.embedph:active .embedph-play,
.embedph:focus .embedph-play,
.embedph:focus-within .embedph-play {
opacity: 1;
}
.embedph-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.embedph-bg img {
object-fit: cover;
width: 100%;
height: 100%;
display: inline-block;
transition: transform .2s, filter .2s;
box-sizing: border-box !important;
max-width: initial !important;
max-height: initial !important;
}
.embedph-fg {
width: 100%;
height: 100%;
}
.embedph-info {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: flex-end;
transition: opacity .2s;
}
.embedph-info-wrap {
margin: 5px;
background-color: var(--background-colour-translucent-8);
border-radius: 5px;
display: flex;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.embedph-info-bar {
width: 5px;
margin: 5px;
border-radius: 5px;
flex: 0 0 auto;
background-color: var(--embedph-colour, var(--accent-colour));
}
.embedph-info-body {
margin: 10px;
margin-left: 5px;
}
.embedph-info-title {
font-size: 1.5rem !important;
font-weight: 500 !important;
line-height: 1.5rem !important;
margin: 5px 0;
word-break: break-word;
margin: 0 !important;
padding: 0 !important;
border-width: 0 !important;
}
.embedph-info-desc {
font-size: .875rem;
line-height: 1.5rem;
margin: .25rem 0;
word-break: break-word;
}
.embedph-info-site {
font-size: .75rem;
}
@media (max-width: 640px) {
.embedph-info-desc {
display: none;
}
}
.embedph-play {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity .2s;
}
.embedph-play-internal {
margin-top: 40px;
margin-bottom: 20px;
}
.embedph-play-external {
padding: 4px 8px;
text-decoration: none !important;
color: var(--text-colour) !important;
background-color: var(--background-colour-translucent-6);
border-radius: 5px;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transition: background-color .2s, transform .2s;
}
.embedph-play-external:hover,
.embedph-play-external:focus {
background-color: var(--background-colour-translucent-8);
transform: scale(1.2);
}
.embed-youtube,
.embedph-youtube {
aspect-ratio: 16 / 9;
width: 100%;
height: 100%;
max-width: 560px;
max-height: 315px;
}
.embed-nicovideo,
.embedph-nicovideo {
aspect-ratio: 16 / 9;
width: 100%;
height: 100%;
max-width: 640px;
max-height: 360px;
}
.embedvf {
display: inline-block;
overflow: hidden;
}
.embedvf:hover .embedvf-controls,
.embedvf:focus .embedvf-controls,
.embedvf:active .embedvf-controls,
.embedvf:focus-within .embedvf-controls {
opacity: 1;
transform: scale(1);
}
.embedvf-player {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.embedvf-overlay {
width: 100%;
height: 100%;
pointer-events: none;
}
.embedvf-controls {
pointer-events: initial;
position: absolute;
bottom: 5px;
left: 5px;
right: 5px;
padding: 5px;
background-color: var(--background-colour-translucent-7);
border-radius: 5px;
opacity: 0;
transform: scale(.95);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transition: opacity .2s, transform .2s;
}
.aembed {
display: inline-block;
overflow: hidden;
}
.aembedph {
display: inline-block;
overflow: hidden;
cursor: pointer;
color: var(--text-colour);
text-decoration: none;
max-width: 500px;
min-width: 300px;
height: 70px;
border-radius: 5px;
margin: 5px;
font-size: .75rem;
}
.aembedph:hover .aembedph-play,
.aembedph:active .aembedph-play,
.aembedph:focus .aembedph-play,
.aembedph:focus-within .aembedph-play {
opacity: 1;
}
.aembedph-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
.aembedph-bg-none {
background: var(--background-pattern);
background-color: var(--aembedph-colour, var(--accent-colour));
background-blend-mode: multiply;
}
.aembedph-bg img {
object-fit: cover;
width: 100%;
height: 100%;
display: inline-block;
transform: scale(1.1);
filter: blur(10px) brightness(80%);
box-sizing: border-box !important;
max-width: initial !important;
max-height: initial !important;
}
.aembedph-fg {
width: 100%;
height: 100%;
}
.aembedph-info {
display: flex;
background-color: var(--background-colour-translucent-5);
align-items: center;
width: 100%;
height: 100%;
padding: 5px;
}
.aembedph-info-cover {
flex: 0 0 auto;
overflow: hidden;
border-radius: 5px;
}
.aembedph-info-cover-none {
background-color: var(--aembedph-colour, var(--accent-colour));
width: 5px;
height: 100%;
}
.aembedph-info-cover img {
max-width: 60px !important;
max-height: 60px !important;
display: inline-block;
vertical-align: middle;
box-sizing: border-box !important;
}
.aembedph-info-cover-none img {
display: none;
}
.aembedph-info-body {
padding: 0 5px;
}
.aembedph-info-title {
font-size: 1.25em !important;
font-weight: 500 !important;
line-height: 1.25em !important;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 430px;
margin: 0 !important;
padding: 0 !important;
border-width: 0 !important;
}
.aembedph-info-title-artist {
max-width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 600;
}
.aembedph-info-album {
line-height: 1.5em;
word-break: break-word;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 430px;
}
.aembedph-info-site {
font-size: .9em;
line-height: 1.25em;
}
.aembedph-play {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transition: opacity .2s;
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
}
.aembedph-play-internal {
width: 70px;
height: 70px;
text-align: center;
flex: 0 0 auto;
display: flex;
justify-content: center;
align-items: center;
}
.aembedph-play-external {
flex: 1 1 auto;
display: flex;
justify-content: flex-end;
align-items: center;
padding: 5px;
}
.aembedph-play-external-link {
padding: 2px 5px;
line-height: 1.5em;
text-decoration: none !important;
color: var(--text-colour) !important;
background-color: var(--background-colour-translucent-6);
border-radius: 5px;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
transition: background-color .2s;
}
.aembedph-play-external-link:hover,
.aembedph-play-external-link:focus {
background-color: var(--background-colour-translucent-8);
}
.aembedph-play-external-link:active {
background-color: var(--background-colour-translucent-5);
}

View file

@ -129,7 +129,7 @@
/* Ix */
.flag--id { background-position: top -96px left -48px; }
.flag--ie { background-position: top -96px left -64px; }
.flag--il { background-position: top -96px left -176px; }
.flag--il { background-position: top -180px left -288px; }
.flag--in { background-position: top -96px left -208px; }
.flag--io { background-position: top -96px left -224px; }
.flag--iq { background-position: top -96px left -256px; }
@ -295,6 +295,9 @@
.flag--wf { background-position: top -264px left -80px; }
.flag--ws { background-position: top -264px left -288px; }
/* Xx */
.flag--xm { background-position: top -276px left -192px; }
/* Yx */
.flag--ye { background-position: top -288px left -64px; }
.flag--yt { background-position: top -288px left -304px; }

View file

@ -5,6 +5,7 @@
color: inherit;
text-decoration: none;
}
.footer__link:focus,
.footer__link:hover {
text-decoration: underline;
}
@ -12,8 +13,8 @@
max-width: var(--site-max-width);
margin: 0 auto;
text-align: center;
font-size: .9em;
line-height: 1.5em;
font-size: .875rem;
line-height: 1.5rem;
padding: 1em 0;
}
.footer__background {

View file

@ -4,8 +4,6 @@
overflow: auto;
}
.forum__categories__empty {
font-size: 1.2em;
line-height: 1.5em;
text-align: center;
padding: 10px;
}
@ -63,8 +61,8 @@
background-size: 80px 80px;
background-image: radial-gradient(ellipse at center, rgba(255, 255, 255, .2) 0%, rgba(0, 0, 0, .4) 100%);
box-shadow: 0 1px 4px #111;
font-size: 2em;
line-height: 1.5em;
font-size: 1.5em;
line-height: 1.25em;
color: #fff;
display: flex;
justify-content: center;
@ -82,22 +80,25 @@
justify-content: center;
flex-direction: column;
line-height: 1.5em;
gap: 2px;
}
.forum__category__title {
font-size: 1.3em;
font-size: 1.125em;
line-height: 1.25em;
}
.forum__category__description,
.forum__category__subforums {
font-size: .9em;
font-size: .875em;
line-height: 1.25em;
}
.forum__category__subforums {
display: flex;
gap: 6px;
}
.forum__category__subforum {
padding: 2px;
pointer-events: initial;
color: var(--accent-colour);
text-decoration: none;
@ -125,21 +126,23 @@
}
.forum__category__stat {
font-size: .9em;
line-height: 1.3em;
font-size: .875em;
line-height: 1.25em;
opacity: .7;
pointer-events: auto;
font-feature-settings: 'ss01' 1, 'tnum' 1;
}
.forum__category__stat:first-child {
font-size: 1.5em;
font-size: 1.25em;
opacity: 1;
}
.forum__category__activity {
text-align: right;
min-width: 270px;
line-height: 1.5em;
min-width: 300px;
font-size: .875em;
line-height: 1.375em;
}
.forum__category__activity__none,
.forum__category__activity__details {
@ -160,7 +163,7 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 200px;
max-width: 230px;
}
.forum__category__activity__post:hover,
.forum__category__activity__post:focus {
@ -171,6 +174,7 @@
color: var(--user-colour);
text-decoration: none;
pointer-events: initial;
display: block;
}
.forum__category__username:hover,
.forum__category__username:focus {
@ -193,7 +197,7 @@
flex-wrap: wrap;
}
.forum__category__details {
flex-basis: calc(100% - 100px);
flex-basis: calc(100% - 8em); /* god knows what this does */
}
.forum__category__stats {
min-width: initial;
@ -229,4 +233,7 @@
.forum__category__avatar {
display: none;
}
}
.forum__category__username {
display: none;
}
}

View file

@ -7,8 +7,8 @@
}
.forum__header__title {
font-size: 2em;
line-height: 1.5em;
font-size: 1.5em;
line-height: 1.25em;
color: inherit;
text-decoration: none;
padding: 0 5px;
@ -28,19 +28,18 @@
margin: 0;
box-shadow: initial;
font-size: 1em;
font-family: inherit;
font-family: var(--font-regular);
}
.forum__header__breadcrumbs {
display: flex;
font-size: 1.1em;
line-height: 1.5em;
align-items: center;
}
.forum__header__breadcrumb {
color: var(--accent-colour);
text-decoration: none;
padding: 2px 5px;
padding: 2px 6px;
}
.forum__header__breadcrumb:hover {
text-decoration: underline;
@ -48,7 +47,7 @@
.forum__header__breadcrumb__separator {
color: var(--accent-colour);
margin: 0 4px;
font-size: .9em;
font-size: .875em;
}
.forum__header__actions {

View file

@ -36,14 +36,13 @@
.forum__leaderboard__user {
margin: 2px 0;
font-size: 1.2em;
}
.forum__leaderboard__user--rank-1 {
font-size: 1.6em;
font-size: 1.5em;
}
.forum__leaderboard__user--rank-2,
.forum__leaderboard__user--rank-3 {
font-size: 1.4em;
font-size: 1.25em;
}
.forum__leaderboard__user__background {
@ -69,6 +68,7 @@
justify-content: center;
font-weight: 700;
flex: 0 0 auto;
font-feature-settings: 'ss01' 1, 'tnum' 1;
}
.forum__leaderboard__user__rank:before {
content: "#";

View file

@ -22,8 +22,8 @@
}
.forum__post__details {
font-size: .9em;
line-height: 1.7em;
font-size: .875em;
line-height: 1.75em;
padding: 0 2px;
display: flex;
justify-content: space-between;
@ -36,6 +36,9 @@
color: inherit;
text-decoration: none;
}
.forum__post__id {
font-feature-settings: 'ss01' 1, 'tnum' 1;
}
.forum__post__datetime:hover,
.forum__post__datetime:focus,
.forum__post__id:hover,
@ -46,15 +49,11 @@
}
.forum__post__text {
margin: 2px;
line-height: 1.2em;
padding: 2px;
line-height: 1.5em;
flex: 1 1 auto;
overflow: auto;
}
.forum__post__text--edit {
/* figure out why this is needed */
max-width: calc(100% - 4px);
min-width: calc(100% - 4px);
.forum__post__text--edit {
margin: 2px 2px 0;
min-height: 400px;
height: 100%;
@ -66,6 +65,12 @@
font-family: inherit;
}
.forum__post__text img {
vertical-align: middle;
max-width: 100%;
max-height: 900px
}
.forum__post__info__content {
width: 150px;
text-align: center;
@ -95,14 +100,14 @@
}
.forum__post__posts-count {
font-size: .9em;
margin-left: 4px;
font-size: .75em;
margin-left: 8px;
}
.forum__post__joined {
flex: 1 1 auto;
max-width: 170px;
font-size: .9em;
font-size: .75em;
justify-self: flex-end;
}
@ -115,7 +120,7 @@
.forum__post__username {
color: inherit;
font-size: 1.4em;
font-size: 1.25em;
line-height: 2em;
text-decoration: none;
}
@ -125,8 +130,8 @@
}
.forum__post__usertitle {
font-size: .9em;
line-height: 1.5em;
font-size: .75em;
line-height: 1.25em;
margin-bottom: 4px;
}
@ -152,6 +157,9 @@
}
.forum__post__action {
background-color: transparent;
border: 0;
display: block;
padding: 5px 10px;
margin: 1px;
color: inherit;
@ -159,6 +167,9 @@
transition: background-color .2s;
border-radius: 3px;
cursor: pointer;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
.forum__post__action:hover,
.forum__post__action:focus {
@ -173,16 +184,19 @@
}
.forum__post__signature img {
vertical-align: middle;
max-width: 100%;
max-height: 150px;
}
.forum__post__badge {
background-color: var(--accent-colour);
border-radius: 12px;
border-radius: 24px;
width: 100%;
padding: 2px;
box-shadow: 0 2px 3px #000A;
margin: 4px;
overflow: hidden;
font-size: .875em;
}
.forum__post__badge__desktop {
display: block;
@ -197,13 +211,11 @@
}
.forum__post__text {
margin: 4px;
font-size: 1.2em;
line-height: 1.3em;
}
.forum__post__info {
flex-direction: row;
margin: 0;
padding: 5px;
padding: 4px;
}
.forum__post__info__content {
width: 100%;
@ -242,8 +254,8 @@
padding: 2px 10px;
margin: 0;
align-self: flex-start;
margin-left: 5px;
font-size: .9em;
margin-left: 10px;
font-size: .875em;
}
.forum__post__badge__desktop {
display: none;

View file

@ -12,7 +12,7 @@
display: flex;
justify-content: center;
align-items: center;
font-size: 2em;
font-size: 1.5em;
padding-bottom: 1px;
}
.forum__status__icon__background {

View file

@ -4,8 +4,6 @@
overflow: auto;
}
.forum__topics__empty {
font-size: 1.2em;
line-height: 1.5em;
text-align: center;
padding: 10px;
}
@ -76,7 +74,7 @@
background-size: 60px 60px;
background-image: radial-gradient(ellipse at center, rgba(255, 255, 255, .2) 0%, rgba(0, 0, 0, .4) 100%);
box-shadow: 0 1px 4px #111;
font-size: 1.5em;
font-size: 1.125em;
line-height: 1.5em;
color: #fff;
display: flex;
@ -91,9 +89,6 @@
.forum__topic__icon--unread {
background-color: var(--accent-colour);
}
.forum__topic__icon--faded {
opacity: .3;
}
.forum__topic__icon__participated {
position: absolute;
bottom: 2px;
@ -105,16 +100,6 @@
box-shadow: 0 1px 2px #111;
pointer-events: initial;
}
.forum__topic__icon__priority {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
line-height: 30px;
font-size: .9em;
text-align: center;
}
.forum__topic__details {
margin: 0 4px;
@ -127,14 +112,15 @@
}
.forum__topic__title {
font-size: 1.3em;
font-size: 1.125em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.forum__topic__info {
font-size: .9em;
font-size: .875em;
line-height: 1.25em;
}
.forum__topic__stats,
@ -150,14 +136,15 @@
}
.forum__topic__stat {
font-size: .9em;
line-height: 1.3em;
font-size: .875em;
line-height: 1.25em;
opacity: .7;
pointer-events: auto;
cursor: default;
font-feature-settings: 'ss01' 1, 'tnum' 1;
}
.forum__topic__stat:first-child {
font-size: 1.4em;
font-size: 1.25em;
opacity: 1;
}
@ -166,7 +153,7 @@
align-items: center;
text-align: right;
min-width: 200px;
line-height: 1.5em;
line-height: 1.25em;
}
.forum__topic__activity__details {
display: flex;
@ -211,8 +198,9 @@
.forum__topic__pagination {
display: flex;
align-items: center;
font-size: .9em;
line-height: 1.2em;
font-size: .875em;
line-height: 1.25em;
font-feature-settings: 'ss01' 1, 'tnum' 1;
}
.forum__topic__pagination__separator {
margin: 0 8px;
@ -222,7 +210,7 @@
text-decoration: none;
pointer-events: initial;
margin: 0 1px;
padding: 2px 4px;
padding: 3px;
border-radius: 2px;
min-width: 25px;
height: 25px;
@ -275,8 +263,8 @@
.forum__topic__pagination__item {
min-width: 30px;
height: 30px;
line-height: 26px;
font-size: 1.2em;
line-height: 1.375em;
font-size: 1.25em;
}
}
@ -285,4 +273,4 @@
position: absolute;
right: 0;
}
}
}

View file

@ -55,7 +55,6 @@
.header__desktop__link:focus {
background-color: rgba(255, 255, 255, .2);
}
.header__desktop__link:active {
background-color: rgba(255, 255, 255, .1);
}
@ -70,8 +69,7 @@
}
.header__desktop__menu__link {
margin: var(--header-link-margin) 0;
font-size: 1.2em;
padding: 6px 10px;
padding: 4px 10px;
text-align: center;
}
@ -87,6 +85,8 @@
}
.header__desktop__submenu__link {
margin: 5px;
font-size: .875em;
line-height: 1.5em;
}
.header__desktop__submenu__background {
background: var(--header-accent-colour);
@ -129,8 +129,8 @@
margin: 2px;
color: inherit;
text-decoration: none;
font-size: 1.5em;
line-height: 32px;
font-size: 1.125rem;
line-height: 2rem;
width: 32px;
height: 32px;
transition: background-color .2s;
@ -147,14 +147,20 @@
}
.header__desktop__user__button__count {
position: absolute;
bottom: 1px;
right: 1px;
font-size: 10px;
top: -5px;
right: -3px;
z-index: 1;
font-size: .625rem;
line-height: 1.375rem;
text-align: right;
padding: 2px 2px 0;
border-radius: 4px;
background-color: var(--header-accent-colour);
opacity: .9;
border-radius: 4px;
line-height: 12px;
padding: 2px 4px;
padding: 2px 3px;
font-feature-settings: 'ss01' 1, 'tnum' 1;
}
/** MOBILE HEADER **/
@ -182,18 +188,12 @@
.header__mobile__icon {
flex: 0 0 auto;
cursor: pointer;
font-size: 32px;
font-size: 1.5rem;
width: var(--header-icon-px);
height: var(--header-icon-px);
display: flex;
justify-content: center;
align-items: center;
-webkit-touch-callout: none !important;
-webkit-user-select: none !important;
-khtml-user-select: none !important;
-moz-user-select: none !important;
-ms-user-select: none !important;
user-select: none !important;
}
@ -223,9 +223,8 @@
background: var(--background-pattern);
background-color: var(--header-accent-colour);
background-blend-mode: multiply;
transition: max-height .2s;
transition: max-height .3s;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
text-shadow: 0 1px 4px #000;
max-height: 0;
overflow: hidden;
}
@ -234,7 +233,7 @@
}
.header__mobile__toggle:checked ~ .header__mobile__menu {
max-height: 600px;
max-height: 100vh;
}
.header__mobile__user {
@ -252,24 +251,23 @@
color: inherit;
text-decoration: none;
display: block;
padding: 8px;
padding-left: 20px;
padding: 6px;
padding-left: 24px;
cursor: pointer;
border-radius: 2px;
transition: background-color .2s, margin .1s, opacity .1s;
font-size: 1.2em;
}
.header__mobile__link:not(:last-child) {
margin-bottom: 2px;
}
.header__mobile__link--primary {
font-size: 1.5em;
padding: 10px;
font-size: 1.25rem;
padding: 8px;
}
.header__mobile__link--user {
margin: 2px;
font-size: 1.5em;
padding: 10px;
font-size: 1.25rem;
padding: 8px;
}
.header__mobile__link:hover,
.header__mobile__link:focus {
@ -282,6 +280,6 @@
@media (max-width: 800px) {
.header__desktop { display: none; }
}
@media (min-width: 800px) {
@media (min-width: 801px) {
.header__mobile { display: none; }
}

View file

@ -0,0 +1,92 @@
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em;
font-family: var(--font-monospace);
font-feature-settings: 'ss07' 1;
}
code.hljs {
padding: 2px 5px;
}
.hljs {
color: #eee;
background: #121212;
}
.hljs-strong,
.hljs-emphasis,
.hljs-section {
font-weight: 700;
}
.hljs-bullet,
.hljs-quote,
.hljs-number,
.hljs-regexp,
.hljs-literal {
color: #b2b376;
}
.hljs-code {
background-color: #242424;
}
.hljs-comment,
.hljs-meta,
.hljs-emphasis,
.hljs-stronge,
.hljs-type,
.hljs-attribute,
.hljs-params {
font-style: italic;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-section,
.hljs-symbol,
.hljs-name {
color: #9475b2;
}
.hljs-built_in,
.hljs-subst,
.hljs-tag,
.hljs-title,
.hljs-selector-attr {
color: #c8b9d7;
}
.hljs-variable,
.hljs-class .hljs-title,
.hljs-selector-class,
.hljs-selector-id,
.hljs-selector-pseudo {
color: #b37fae;
}
.hljs-string {
color: #76b38a;
}
.hljs-type,
.hljs-template-tag,
.hljs-template-variable,
.hljs-link {
color: #b39a76;
}
.hljs-comment,
.hljs-meta {
color: #70647b;
}
.hljs-addition {
background: #0e4d0e;
}
.hljs-deletion {
background: #4d0e0e;
}

View file

@ -0,0 +1,84 @@
.landingv2-footer {
flex: 0 0 auto;
--footer-background-mask-image: linear-gradient(180deg, transparent, var(--background-colour) 30px);
margin-top: 4px;
padding-top: 20px;
}
.landingv2-footer-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
mask-image: var(--footer-background-mask-image);
-webkit-mask-image: var(--footer-background-mask-image);
background: var(--background-pattern);
background-color: var(--header-accent-colour);
background-blend-mode: multiply;
}
.landingv2-footer-wrapper {
max-width: var(--site-max-width);
margin: 0 auto;
padding: 1em 4px;
display: grid;
grid-template-columns: repeat(2, 1fr);
}
.landingv2-footer-navigation {}
.landingv2-footer-navigation a {
display: inline-block;
color: inherit;
text-decoration: none;
min-width: 200px;
cursor: pointer;
border-radius: 2px;
padding: 4px 10px;
margin: 1px 0;
transition: background-color .2s;
}
.landingv2-footer-navigation a:hover,
.landingv2-footer-navigation a:focus {
background-color: rgba(255, 255, 255, .2);
}
.landingv2-footer-navigation a:active {
background-color: rgba(255, 255, 255, .1);
}
.landingv2-footer-copyright {
text-align: right;
line-height: 1.5em;
font-size: .875em;
align-self: flex-end;
}
.landingv2-footer-copyright a {
color: inherit;
text-decoration: none;
}
.landingv2-footer-copyright a:focus,
.landingv2-footer-copyright a:hover {
text-decoration: underline;
}
@media(max-width: 800px) {
.landingv2-footer-wrapper {
grid-template-columns: 1fr;
}
.landingv2-footer-navigation {
text-align: center;
margin: 0 8px;
}
.landingv2-footer-navigation div {
display: inline-block;
}
.landingv2-footer-navigation a {
text-align: center;
min-width: 100px;
margin: 2px;
}
.landingv2-footer-copyright {
text-align: center;
}
}

View file

@ -0,0 +1,91 @@
.landingv2-header {
flex: 0 0 auto;
--header-background-mask-image: linear-gradient(0deg, transparent, var(--background-colour) 100px);
padding-bottom: 100px;
}
.landingv2-header-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--background-pattern);
background-color: var(--header-accent-colour);
background-blend-mode: multiply;
mask-image: var(--header-background-mask-image);
-webkit-mask-image: var(--header-background-mask-image);
}
.landingv2-header-content {
margin: 0 auto;
max-width: 800px;
}
.landingv2-welcome {
text-align: center;
margin: 10px;
}
.landingv2-welcome a {
color: inherit;
text-decoration: none;
}
.landingv2-welcome img {
max-width: 100%;
max-height: 100%;
vertical-align: middle;
}
.landingv2-header-menu {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 4px;
padding: 0 4px;
}
.landingv2-header-menu-link {
color: #fff;
text-decoration: none;
cursor: pointer;
border-radius: 2px;
background-color: var(--background-colour);
border: 1px solid var(--header-accent-colour);
transition: background-color .2s;
display: flex;
align-items: center;
min-height: 70px;
font-size: 1.5em;
padding: 8px 16px;
grid-column: 1;
}
.landingv2-header-menu-link:hover,
.landingv2-header-menu-link:focus {
background-color: var(--accent-colour);
}
.landingv2-auth-link {
font-size: 2em;
justify-content: center;
text-align: center;
grid-column: 2;
}
.landingv2-auth-link-login {
grid-row: 1 / span 2;
}
@media(max-width: 700px) {
.landingv2-header-menu {
grid-template-columns: 1fr;
}
.landingv2-auth-link {
grid-column: 1;
}
.landingv2-auth-link-login {
grid-row: 1;
min-height: 100px;
}
.landingv2-auth-link-register {
grid-row: 2;
}
}

View file

@ -0,0 +1,209 @@
.landingv2-content {
padding: 0 4px;
}
.landingv2-stats {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 40px;
margin: 40px;
}
.landingv2-stat {
display: flex;
align-items: center;
margin: 10px;
}
.landingv2-stat-icon {
font-size: 4em;
}
.landingv2-stat-value {
font-size: 2em;
text-align: right;
flex: 1 1 auto;
}
.landingv2-stat-value-num {
font-weight: 700;
font-feature-settings: 'ss01' 1, 'tnum' 1;
}
.landingv2-forum {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-gap: 2px;
margin: 4px 0;
}
.landingv2-forum-topics {
background-color: var(--container-colour);
box-shadow: 0 1px 2px #0009;
overflow: hidden;
word-wrap: break-word;
}
.landingv2-forum-topics-list {
display: flex;
flex-direction: column;
margin: 5px;
overflow: hidden;
}
.landingv2-forum-topic {
border-radius: 2px;
background-color: rgba(17, 17, 17, .6);
transition: background-color .2s, box-shadow .2s, opacity .2s;
}
.landingv2-forum-topic:nth-child(even) {
background-color: rgba(25, 25, 25, .6);
}
.landingv2-forum-topic:hover,
.landingv2-forum-topic:focus {
background-color: rgba(34, 34, 34, .6);
box-shadow: 0 1px 4px #222;
}
.landingv2-forum-topic:not(:last-child) {
margin-bottom: 4px;
}
.landingv2-forum-topic-link {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
color: inherit;
text-decoration: none;
z-index: 200;
}
.landingv2-forum-topic-info {
z-index: 100;
display: flex;
padding: 5px;
align-items: center;
min-height: 40px;
pointer-events: none;
}
.landingv2-forum-topic-info-icon {
flex: 0 0 auto;
border-radius: 2px;
width: 30px;
height: 30px;
margin-right: 4px;
background-color: var(--accent-colour);
background-size: 60px 60px;
background-image: radial-gradient(ellipse at center, rgba(255, 255, 255, .2) 0%, rgba(0, 0, 0, .4) 100%);
box-shadow: 0 1px 4px #111;
font-size: 1.25em;
line-height: 1.5em;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
padding: 1px 1px 0 2px;
}
.landingv2-forum-topic-info-details {
margin: 0 4px;
flex: 1 1 auto;
display: flex;
justify-content: center;
flex-direction: column;
line-height: 1.625em;
overflow: hidden;
}
.landingv2-forum-topic-info-details-title {
font-size: 1.25em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.landingv2-forum-topic-info-stats {
font-size: .875em;
display: flex;
flex: 0 0 auto;
text-align: center;
min-width: 60px;
flex-direction: column;
font-feature-settings: 'ss01' 1, 'tnum' 1;
}
.landingv2-forum-topic-info-stats-posts,
.landingv2-forum-topic-info-stats-views {
font-size: .875em;
line-height: 1.25em;
opacity: .7;
pointer-events: auto;
cursor: default;
}
.landingv2-forum-topic-info-stats-posts {
font-size: 1.25em;
opacity: 1;
}
.landingv2-news {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 2px;
}
.landingv2-news-post {
background-color: var(--container-colour);
box-shadow: 0 1px 2px #0009;
overflow: hidden;
word-wrap: break-word;
padding: 0 10px 10px 10px;
display: flex;
flex-direction: column;
}
.landingv2-news-post p {
flex: 1 1 auto;
}
.landingv2-news-post-options {
text-align: right;
}
.landingv2-online {
background-color: var(--container-colour);
box-shadow: 0 1px 2px #0009;
margin: 4px 0;
}
.landingv2-online-users {
scrollbar-width: thin;
overflow: auto;
}
.landingv2-online-inner {
display: flex;
padding: 2px;
}
.landingv2-online-avatar {
margin: 2px;
display: block;
flex: 0 0 auto;
}
@media(max-width: 1100px) {
.landingv2-stat {
margin: 0;
}
}
@media(max-width: 1024px) {
.landingv2-stats {
grid-template-columns: repeat(2, 1fr);
margin: 20px;
}
}
@media(max-width: 900px) {
.landingv2-forum,
.landingv2-news {
grid-template-columns: 1fr;
}
}
@media(max-width: 700px) {
.landingv2-stats {
grid-template-columns: 1fr;
}
}

View file

@ -0,0 +1,52 @@
.impersonate {
--start-colour: var(--accent-colour);
--end-colour: var(--background-colour);
background-image: repeating-linear-gradient(-45deg, var(--start-colour), var(--start-colour) 10px, var(--end-colour) 10px, var(--end-colour) 20px);
height: 30px;
}
.impersonate-content {
max-width: var(--site-max-width);
margin: 0 auto;
display: flex;
justify-content: space-between;
height: 100%;
}
.impersonate-user {
padding: 4px 10px;
background-color: #222d;
}
.impersonate-user-link {
color: var(--user-colour);
text-decoration: none;
}
.impersonate-user-link:hover,
.impersonate-user-link:focus {
text-decoration: underline;
}
.impersonate-user-avatar {
display: inline-block;
}
.impersonate-options {
display: flex;
}
.impersonate-options-link {
width: 30px;
height: 30px;
line-height: 29px;
text-align: center;
background-color: #222d;
display: block;
color: var(--text-colour);
text-decoration: none;
transition: background-color .1s;
}
.impersonate-options-link:focus,
.impersonate-options-link:hover {
background-color: #555d;
}
.impersonate-options-link:active {
background-color: #333d;
}

Some files were not shown because too many files have changed in this diff Show more